mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-26 23:40:57 +01:00
Add a dropdown menu for Differential view options
Summary: There are several open Differential tasks that are basically blocked on not having reasonable places in the UI to put things. Replace the "View Standalone / Raw" button with a "View Options" dropdown menu so we can shove things like "Expand All", "Fold / Unfold File", and "View in Diffusion" in there. This doesn't change any behavior, just puts the existing options in a menu. Test Plan: - Toggled menu open by clicking button. - Clicked menu items. - Toggled menu closed by clicking button. - Toggled menu closed by clicking document. - Toggled menu closed by opening another menu. - Toggled menu closed by selecting an item. Reviewers: btrahan, jungejason Reviewed By: btrahan CC: aran, btrahan Maniphest Tasks: T497, T309 Differential Revision: https://secure.phabricator.com/D1316
This commit is contained in:
parent
1c1fe96bec
commit
7abdf3afe0
8 changed files with 347 additions and 64 deletions
|
@ -470,6 +470,20 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/differential/behavior-diff-radios.js',
|
||||
),
|
||||
'javelin-behavior-differential-dropdown-menus' =>
|
||||
array(
|
||||
'uri' => '/res/08e751ee/rsrc/js/application/differential/behavior-dropdown-menus.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-dom',
|
||||
2 => 'javelin-stratcom',
|
||||
3 => 'phabricator-dropdown-menu',
|
||||
4 => 'phabricator-menu-item',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/differential/behavior-dropdown-menus.js',
|
||||
),
|
||||
'javelin-behavior-differential-edit-inline-comments' =>
|
||||
array(
|
||||
'uri' => '/res/c24338ce/rsrc/js/application/differential/behavior-edit-inline-comments.js',
|
||||
|
@ -1303,7 +1317,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'phabricator-core-buttons-css' =>
|
||||
array(
|
||||
'uri' => '/res/3059cf79/rsrc/css/core/buttons.css',
|
||||
'uri' => '/res/89b939ae/rsrc/css/core/buttons.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -1351,6 +1365,21 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/core/DragAndDropFileUpload.js',
|
||||
),
|
||||
'phabricator-dropdown-menu' =>
|
||||
array(
|
||||
'uri' => '/res/d55c3771/rsrc/js/application/core/DropdownMenu.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-install',
|
||||
1 => 'javelin-util',
|
||||
2 => 'javelin-dom',
|
||||
3 => 'javelin-vector',
|
||||
4 => 'javelin-stratcom',
|
||||
5 => 'phabricator-menu-item',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/core/DropdownMenu.js',
|
||||
),
|
||||
'phabricator-feed-css' =>
|
||||
array(
|
||||
'uri' => '/res/7d1d0015/rsrc/css/application/feed/feed.css',
|
||||
|
@ -1386,6 +1415,17 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/core/KeyboardShortcutManager.js',
|
||||
),
|
||||
'phabricator-menu-item' =>
|
||||
array(
|
||||
'uri' => '/res/8a9be282/rsrc/js/application/core/DropdownMenuItem.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-install',
|
||||
1 => 'javelin-dom',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/core/DropdownMenuItem.js',
|
||||
),
|
||||
'phabricator-object-selector-css' =>
|
||||
array(
|
||||
'uri' => '/res/608461d2/rsrc/css/application/objectselector/object-selector.css',
|
||||
|
@ -1707,30 +1747,6 @@ celerity_register_resource_map(array(
|
|||
'uri' => '/res/pkg/4e7acf1a/core.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
'4f6e449d' =>
|
||||
array(
|
||||
'name' => 'core.pkg.css',
|
||||
'symbols' =>
|
||||
array(
|
||||
0 => 'phabricator-core-css',
|
||||
1 => 'phabricator-core-buttons-css',
|
||||
2 => 'phabricator-standard-page-view',
|
||||
3 => 'aphront-dialog-view-css',
|
||||
4 => 'aphront-form-view-css',
|
||||
5 => 'aphront-panel-view-css',
|
||||
6 => 'aphront-side-nav-view-css',
|
||||
7 => 'aphront-table-view-css',
|
||||
8 => 'aphront-crumbs-view-css',
|
||||
9 => 'aphront-tokenizer-control-css',
|
||||
10 => 'aphront-typeahead-control-css',
|
||||
11 => 'aphront-list-filter-view-css',
|
||||
12 => 'phabricator-directory-css',
|
||||
13 => 'phabricator-remarkup-css',
|
||||
14 => 'syntax-highlighting-css',
|
||||
),
|
||||
'uri' => '/res/pkg/4f6e449d/core.pkg.css',
|
||||
'type' => 'css',
|
||||
),
|
||||
'540effd7' =>
|
||||
array(
|
||||
'name' => 'typeahead.pkg.js',
|
||||
|
@ -1787,19 +1803,43 @@ celerity_register_resource_map(array(
|
|||
'uri' => '/res/pkg/b164acea/javelin.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
'faf854fc' =>
|
||||
array(
|
||||
'name' => 'core.pkg.css',
|
||||
'symbols' =>
|
||||
array(
|
||||
0 => 'phabricator-core-css',
|
||||
1 => 'phabricator-core-buttons-css',
|
||||
2 => 'phabricator-standard-page-view',
|
||||
3 => 'aphront-dialog-view-css',
|
||||
4 => 'aphront-form-view-css',
|
||||
5 => 'aphront-panel-view-css',
|
||||
6 => 'aphront-side-nav-view-css',
|
||||
7 => 'aphront-table-view-css',
|
||||
8 => 'aphront-crumbs-view-css',
|
||||
9 => 'aphront-tokenizer-control-css',
|
||||
10 => 'aphront-typeahead-control-css',
|
||||
11 => 'aphront-list-filter-view-css',
|
||||
12 => 'phabricator-directory-css',
|
||||
13 => 'phabricator-remarkup-css',
|
||||
14 => 'syntax-highlighting-css',
|
||||
),
|
||||
'uri' => '/res/pkg/faf854fc/core.pkg.css',
|
||||
'type' => 'css',
|
||||
),
|
||||
),
|
||||
'reverse' =>
|
||||
array(
|
||||
'aphront-crumbs-view-css' => '4f6e449d',
|
||||
'aphront-dialog-view-css' => '4f6e449d',
|
||||
'aphront-form-view-css' => '4f6e449d',
|
||||
'aphront-crumbs-view-css' => 'faf854fc',
|
||||
'aphront-dialog-view-css' => 'faf854fc',
|
||||
'aphront-form-view-css' => 'faf854fc',
|
||||
'aphront-headsup-action-list-view-css' => '8b139246',
|
||||
'aphront-list-filter-view-css' => '4f6e449d',
|
||||
'aphront-panel-view-css' => '4f6e449d',
|
||||
'aphront-side-nav-view-css' => '4f6e449d',
|
||||
'aphront-table-view-css' => '4f6e449d',
|
||||
'aphront-tokenizer-control-css' => '4f6e449d',
|
||||
'aphront-typeahead-control-css' => '4f6e449d',
|
||||
'aphront-list-filter-view-css' => 'faf854fc',
|
||||
'aphront-panel-view-css' => 'faf854fc',
|
||||
'aphront-side-nav-view-css' => 'faf854fc',
|
||||
'aphront-table-view-css' => 'faf854fc',
|
||||
'aphront-tokenizer-control-css' => 'faf854fc',
|
||||
'aphront-typeahead-control-css' => 'faf854fc',
|
||||
'differential-changeset-view-css' => '8b139246',
|
||||
'differential-core-view-css' => '8b139246',
|
||||
'differential-inline-comment-editor' => '11a5c52c',
|
||||
|
@ -1848,16 +1888,16 @@ celerity_register_resource_map(array(
|
|||
'javelin-vector' => 'b164acea',
|
||||
'javelin-workflow' => '4e7acf1a',
|
||||
'phabricator-content-source-view-css' => '8b139246',
|
||||
'phabricator-core-buttons-css' => '4f6e449d',
|
||||
'phabricator-core-css' => '4f6e449d',
|
||||
'phabricator-directory-css' => '4f6e449d',
|
||||
'phabricator-core-buttons-css' => 'faf854fc',
|
||||
'phabricator-core-css' => 'faf854fc',
|
||||
'phabricator-directory-css' => 'faf854fc',
|
||||
'phabricator-drag-and-drop-file-upload' => '11a5c52c',
|
||||
'phabricator-keyboard-shortcut' => '4e7acf1a',
|
||||
'phabricator-keyboard-shortcut-manager' => '4e7acf1a',
|
||||
'phabricator-object-selector-css' => '8b139246',
|
||||
'phabricator-remarkup-css' => '4f6e449d',
|
||||
'phabricator-remarkup-css' => 'faf854fc',
|
||||
'phabricator-shaped-request' => '11a5c52c',
|
||||
'phabricator-standard-page-view' => '4f6e449d',
|
||||
'syntax-highlighting-css' => '4f6e449d',
|
||||
'phabricator-standard-page-view' => 'faf854fc',
|
||||
'syntax-highlighting-css' => 'faf854fc',
|
||||
),
|
||||
));
|
||||
|
|
|
@ -194,25 +194,6 @@ class DifferentialChangesetViewController extends DifferentialController {
|
|||
$detail->setChangeset($changeset);
|
||||
$detail->appendChild($output);
|
||||
|
||||
if (!$vs) {
|
||||
$detail->addButton(
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $request->getRequestURI()->alter('view', 'old'),
|
||||
'class' => 'grey button small',
|
||||
),
|
||||
'View Raw File (Old Version)'));
|
||||
$detail->addButton(
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $request->getRequestURI()->alter('view', 'new'),
|
||||
'class' => 'grey button small',
|
||||
),
|
||||
'View Raw File (New Version)'));
|
||||
}
|
||||
|
||||
$detail->setRevisionID($request->getInt('revision_id'));
|
||||
|
||||
$output =
|
||||
|
|
|
@ -22,7 +22,6 @@ phutil_require_module('phabricator', 'applications/phid/handle/data');
|
|||
phutil_require_module('phabricator', 'infrastructure/diff/engine');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -71,6 +71,12 @@ class DifferentialChangesetListView extends AphrontView {
|
|||
|
||||
$changesets = $this->changesets;
|
||||
|
||||
if ($this->standaloneViews) {
|
||||
Javelin::initBehavior(
|
||||
'differential-dropdown-menus',
|
||||
array());
|
||||
}
|
||||
|
||||
$output = array();
|
||||
$mapping = array();
|
||||
foreach ($changesets as $key => $changeset) {
|
||||
|
@ -91,14 +97,20 @@ class DifferentialChangesetListView extends AphrontView {
|
|||
'whitespace' => $this->whitespace,
|
||||
));
|
||||
|
||||
$detail_button = phutil_render_tag(
|
||||
$detail_button = javelin_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'class' => 'button small grey',
|
||||
'meta' => array(
|
||||
'detailURI' => (string)$detail_uri,
|
||||
'leftURI' => (string)$detail_uri->alter('view', 'old'),
|
||||
'rightURI' => (string)$detail_uri->alter('view', 'new'),
|
||||
),
|
||||
'href' => $detail_uri,
|
||||
'target' => '_blank',
|
||||
'sigil' => 'differential-view-options',
|
||||
),
|
||||
'View Standalone / Raw');
|
||||
"View Options \xE2\x96\xBC");
|
||||
}
|
||||
|
||||
$uniq_id = celerity_generate_unique_node_id();
|
||||
|
|
|
@ -101,7 +101,8 @@ button.disabled {
|
|||
|
||||
button.grey:active,
|
||||
a.grey:active,
|
||||
button.grey_active {
|
||||
button.grey_active,
|
||||
a.dropdown-open {
|
||||
background-color: #dddddd;
|
||||
background-position: 0 -200px;
|
||||
border-bottom-color: #999;
|
||||
|
@ -185,3 +186,37 @@ a.toggle-fixed {
|
|||
a.toggle-fixed:hover {
|
||||
background: #909090;
|
||||
}
|
||||
|
||||
|
||||
a.dropdown-open {
|
||||
}
|
||||
|
||||
.dropdown-menu-frame {
|
||||
z-index: 32;
|
||||
position: absolute;
|
||||
width: 240px;
|
||||
background: #f6f6f6;
|
||||
border: 1px solid #999;
|
||||
margin-top: -1px;
|
||||
|
||||
box-shadow: 1px 3px 1px rgba(0, 0, 0, 0.25);
|
||||
-moz-box-shadow: 1px 3px 1px rgba(0, 0, 0, 0.25);
|
||||
-webkit-box-shadow: 1px 3px 1px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.dropdown-menu-frame a,
|
||||
.dropdown-menu-frame span {
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.dropdown-menu-frame span {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.dropdown-menu-frame a:hover {
|
||||
background: #005588;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
140
webroot/rsrc/js/application/core/DropdownMenu.js
Normal file
140
webroot/rsrc/js/application/core/DropdownMenu.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* @requires javelin-install
|
||||
* javelin-util
|
||||
* javelin-dom
|
||||
* javelin-vector
|
||||
* javelin-stratcom
|
||||
* phabricator-menu-item
|
||||
* @provides phabricator-dropdown-menu
|
||||
* @javelin
|
||||
*/
|
||||
|
||||
JX.install('PhabricatorDropdownMenu', {
|
||||
|
||||
construct : function(node) {
|
||||
this._node = node;
|
||||
this._items = [];
|
||||
this._menu = JX.$N('div', { className : 'dropdown-menu-frame' });
|
||||
|
||||
JX.DOM.listen(
|
||||
this._node,
|
||||
'click',
|
||||
null,
|
||||
JX.bind(this, this._onclick));
|
||||
|
||||
JX.DOM.listen(
|
||||
this._menu,
|
||||
'click',
|
||||
null,
|
||||
JX.bind(this, this._onclickitem));
|
||||
|
||||
JX.Stratcom.listen(
|
||||
'mousedown',
|
||||
null,
|
||||
JX.bind(this, this._onclickglobal));
|
||||
|
||||
JX.PhabricatorDropdownMenu.listen(
|
||||
'open',
|
||||
JX.bind(this, this.close));
|
||||
},
|
||||
|
||||
events : ['open'],
|
||||
|
||||
members : {
|
||||
_node : null,
|
||||
_menu : null,
|
||||
_open : false,
|
||||
_items : null,
|
||||
|
||||
open : function() {
|
||||
if (this._open) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.invoke('open');
|
||||
|
||||
var menu_items = [];
|
||||
for (var ii = 0; ii < this._items.length; ii++) {
|
||||
menu_items.push(this._items[ii].render());
|
||||
}
|
||||
JX.DOM.setContent(this._menu, menu_items);
|
||||
|
||||
this._open = true;
|
||||
this._show();
|
||||
},
|
||||
|
||||
close : function() {
|
||||
if (!this._open) {
|
||||
return;
|
||||
}
|
||||
this._open = false;
|
||||
this._hide();
|
||||
},
|
||||
|
||||
addItem : function(item) {
|
||||
if (__DEV__) {
|
||||
if (!(item instanceof JX.PhabricatorMenuItem)) {
|
||||
JX.$E(
|
||||
'JX.DropdownMenu.addItem(<junk>): ' +
|
||||
'item must be a JX.PhabricatorMenuItem.');
|
||||
}
|
||||
}
|
||||
this._items.push(item);
|
||||
return this;
|
||||
},
|
||||
|
||||
_onclick : function(e) {
|
||||
if (this._open) {
|
||||
this.close();
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
e.prevent();
|
||||
},
|
||||
|
||||
_onclickitem : function(e) {
|
||||
var item = JX.Stratcom.getData(e.getTarget()).item;
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
item.select();
|
||||
e.prevent();
|
||||
this.close();
|
||||
},
|
||||
|
||||
_onclickglobal : function(e) {
|
||||
if (JX.Stratcom.pass(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var t = e.getTarget();
|
||||
while (t) {
|
||||
if (t == this._menu || t == this._node) {
|
||||
return;
|
||||
}
|
||||
t = t.parentNode;
|
||||
}
|
||||
|
||||
this.close();
|
||||
},
|
||||
|
||||
_show : function() {
|
||||
document.body.appendChild(this._menu);
|
||||
|
||||
var m = JX.Vector.getDim(this._menu);
|
||||
|
||||
JX.$V(this._node)
|
||||
.add(JX.Vector.getDim(this._node))
|
||||
.add(JX.$V(-m.x, 0))
|
||||
.setPos(this._menu);
|
||||
|
||||
JX.DOM.alterClass(this._node, 'dropdown-open', true);
|
||||
},
|
||||
|
||||
_hide : function() {
|
||||
JX.DOM.remove(this._menu);
|
||||
JX.DOM.alterClass(this._node, 'dropdown-open', false);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
28
webroot/rsrc/js/application/core/DropdownMenuItem.js
Normal file
28
webroot/rsrc/js/application/core/DropdownMenuItem.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* @requires javelin-install
|
||||
* javelin-dom
|
||||
* @provides phabricator-menu-item
|
||||
* @javelin
|
||||
*/
|
||||
|
||||
JX.install('PhabricatorMenuItem', {
|
||||
|
||||
construct : function(name, action) {
|
||||
this._name = name;
|
||||
this._action = action;
|
||||
},
|
||||
|
||||
members : {
|
||||
_name : null,
|
||||
_action : null,
|
||||
|
||||
render : function() {
|
||||
return JX.$N('a', { href : '#', meta : { item : this } }, this._name);
|
||||
},
|
||||
|
||||
select : function() {
|
||||
this._action();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* @provides javelin-behavior-differential-dropdown-menus
|
||||
* @requires javelin-behavior
|
||||
* javelin-dom
|
||||
* javelin-stratcom
|
||||
* phabricator-dropdown-menu
|
||||
* phabricator-menu-item
|
||||
*/
|
||||
|
||||
JX.behavior('differential-dropdown-menus', function(config) {
|
||||
|
||||
function standalone(button) {
|
||||
return function() {
|
||||
window.open(JX.Stratcom.getData(button).detailURI);
|
||||
}
|
||||
}
|
||||
|
||||
function left_file(button) {
|
||||
return function() {
|
||||
window.open(JX.Stratcom.getData(button).leftURI);
|
||||
}
|
||||
}
|
||||
|
||||
function right_file(button) {
|
||||
return function() {
|
||||
window.open(JX.Stratcom.getData(button).rightURI);
|
||||
}
|
||||
}
|
||||
|
||||
var buttons = JX.DOM.scry(window.document, 'a', 'differential-view-options');
|
||||
for (var ii = 0; ii < buttons.length; ii++) {
|
||||
var button = buttons[ii];
|
||||
new JX.PhabricatorDropdownMenu(buttons[ii])
|
||||
.addItem(
|
||||
new JX.PhabricatorMenuItem(
|
||||
'View Standalone',
|
||||
standalone(button)))
|
||||
.addItem(
|
||||
new JX.PhabricatorMenuItem(
|
||||
'Show Raw File (Left)',
|
||||
left_file(button)))
|
||||
.addItem(
|
||||
new JX.PhabricatorMenuItem(
|
||||
'Show Raw File (Right)',
|
||||
right_file(button)));
|
||||
}
|
||||
|
||||
});
|
Loading…
Reference in a new issue