1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-29 18:22:41 +01:00

Allow named queries to be reordered by dragging

Summary:
Also you have to drop them. So drag, and then drop.

This needs some cleanup and reconciliation/generalization with the Maniphest implementation. In particular, you can't drag things to the very top right now, and they should share more CSS and more behaviors.

Test Plan:
Look I alphabetized them:

{F45286}

Reviewers: chad

Reviewed By: chad

CC: aran

Differential Revision: https://secure.phabricator.com/D6136
This commit is contained in:
epriestley 2013-06-05 16:22:27 -07:00
parent f26be0e2d4
commit 0f82990798
11 changed files with 221 additions and 68 deletions

View file

@ -1782,7 +1782,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-maniphest-list-editor' =>
array(
'uri' => '/res/170f8457/rsrc/js/application/maniphest/behavior-list-edit.js',
'uri' => '/res/a251e72f/rsrc/js/application/maniphest/behavior-list-edit.js',
'type' => 'js',
'requires' =>
array(
@ -1797,7 +1797,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-maniphest-subpriority-editor' =>
array(
'uri' => '/res/994f0a9d/rsrc/js/application/maniphest/behavior-subpriorityeditor.js',
'uri' => '/res/57540d92/rsrc/js/application/maniphest/behavior-subpriorityeditor.js',
'type' => 'js',
'requires' =>
array(
@ -2271,6 +2271,21 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/js/application/repository/repository-crossreference.js',
),
'javelin-behavior-search-reorder-queries' =>
array(
'uri' => '/res/47148be5/rsrc/js/application/search/behavior-reorder-queries.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-vector',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
4 => 'javelin-dom',
5 => 'phabricator-draggable-list',
),
'disk' => '/rsrc/js/application/search/behavior-reorder-queries.js',
),
'javelin-behavior-slowvote-embed' =>
array(
'uri' => '/res/8e85e20d/rsrc/js/application/slowvote/behavior-slowvote-embed.js',
@ -3206,7 +3221,7 @@ celerity_register_resource_map(array(
),
'phabricator-object-item-list-view-css' =>
array(
'uri' => '/res/b114bc9a/rsrc/css/layout/phabricator-object-item-list-view.css',
'uri' => '/res/90b606a1/rsrc/css/layout/phabricator-object-item-list-view.css',
'type' => 'css',
'requires' =>
array(
@ -3583,7 +3598,7 @@ celerity_register_resource_map(array(
),
'phabricator-zindex-css' =>
array(
'uri' => '/res/d4048e34/rsrc/css/core/z-index.css',
'uri' => '/res/f064ab0f/rsrc/css/core/z-index.css',
'type' => 'css',
'requires' =>
array(
@ -4012,7 +4027,7 @@ celerity_register_resource_map(array(
), array(
'packages' =>
array(
'21f9f13d' =>
'd5a2d8cd' =>
array(
'name' => 'core.pkg.css',
'symbols' =>
@ -4060,7 +4075,7 @@ celerity_register_resource_map(array(
40 => 'phabricator-property-list-view-css',
41 => 'phabricator-tag-view-css',
),
'uri' => '/res/pkg/21f9f13d/core.pkg.css',
'uri' => '/res/pkg/d5a2d8cd/core.pkg.css',
'type' => 'css',
),
'f2ad0683' =>
@ -4236,7 +4251,7 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/03ab92cf/maniphest.pkg.css',
'type' => 'css',
),
'c0c9bc0b' =>
'265bc3fa' =>
array(
'name' => 'maniphest.pkg.js',
'symbols' =>
@ -4247,23 +4262,23 @@ celerity_register_resource_map(array(
3 => 'javelin-behavior-maniphest-transaction-expand',
4 => 'javelin-behavior-maniphest-subpriority-editor',
),
'uri' => '/res/pkg/c0c9bc0b/maniphest.pkg.js',
'uri' => '/res/pkg/265bc3fa/maniphest.pkg.js',
'type' => 'js',
),
),
'reverse' =>
array(
'aphront-attached-file-view-css' => '03ab92cf',
'aphront-dialog-view-css' => '21f9f13d',
'aphront-error-view-css' => '21f9f13d',
'aphront-form-view-css' => '21f9f13d',
'aphront-list-filter-view-css' => '21f9f13d',
'aphront-pager-view-css' => '21f9f13d',
'aphront-panel-view-css' => '21f9f13d',
'aphront-table-view-css' => '21f9f13d',
'aphront-tokenizer-control-css' => '21f9f13d',
'aphront-tooltip-css' => '21f9f13d',
'aphront-typeahead-control-css' => '21f9f13d',
'aphront-dialog-view-css' => 'd5a2d8cd',
'aphront-error-view-css' => 'd5a2d8cd',
'aphront-form-view-css' => 'd5a2d8cd',
'aphront-list-filter-view-css' => 'd5a2d8cd',
'aphront-pager-view-css' => 'd5a2d8cd',
'aphront-panel-view-css' => 'd5a2d8cd',
'aphront-table-view-css' => 'd5a2d8cd',
'aphront-tokenizer-control-css' => 'd5a2d8cd',
'aphront-tooltip-css' => 'd5a2d8cd',
'aphront-typeahead-control-css' => 'd5a2d8cd',
'differential-changeset-view-css' => 'dd27a69b',
'differential-core-view-css' => 'dd27a69b',
'differential-inline-comment-editor' => '9488bb69',
@ -4277,7 +4292,7 @@ celerity_register_resource_map(array(
'differential-table-of-contents-css' => 'dd27a69b',
'diffusion-commit-view-css' => 'c8ce2d88',
'diffusion-icons-css' => 'c8ce2d88',
'global-drag-and-drop-css' => '21f9f13d',
'global-drag-and-drop-css' => 'd5a2d8cd',
'inline-comment-summary-css' => 'dd27a69b',
'javelin-aphlict' => 'f2ad0683',
'javelin-behavior' => 'a9f14d76',
@ -4310,11 +4325,11 @@ celerity_register_resource_map(array(
'javelin-behavior-konami' => 'f2ad0683',
'javelin-behavior-lightbox-attachments' => 'f2ad0683',
'javelin-behavior-load-blame' => '9488bb69',
'javelin-behavior-maniphest-batch-selector' => 'c0c9bc0b',
'javelin-behavior-maniphest-subpriority-editor' => 'c0c9bc0b',
'javelin-behavior-maniphest-transaction-controls' => 'c0c9bc0b',
'javelin-behavior-maniphest-transaction-expand' => 'c0c9bc0b',
'javelin-behavior-maniphest-transaction-preview' => 'c0c9bc0b',
'javelin-behavior-maniphest-batch-selector' => '265bc3fa',
'javelin-behavior-maniphest-subpriority-editor' => '265bc3fa',
'javelin-behavior-maniphest-transaction-controls' => '265bc3fa',
'javelin-behavior-maniphest-transaction-expand' => '265bc3fa',
'javelin-behavior-maniphest-transaction-preview' => '265bc3fa',
'javelin-behavior-phabricator-active-nav' => 'f2ad0683',
'javelin-behavior-phabricator-autofocus' => 'f2ad0683',
'javelin-behavior-phabricator-gesture' => 'f2ad0683',
@ -4351,55 +4366,55 @@ celerity_register_resource_map(array(
'javelin-util' => 'a9f14d76',
'javelin-vector' => 'a9f14d76',
'javelin-workflow' => 'a9f14d76',
'lightbox-attachment-css' => '21f9f13d',
'lightbox-attachment-css' => 'd5a2d8cd',
'maniphest-task-summary-css' => '03ab92cf',
'maniphest-transaction-detail-css' => '03ab92cf',
'phabricator-action-list-view-css' => '21f9f13d',
'phabricator-application-launch-view-css' => '21f9f13d',
'phabricator-action-list-view-css' => 'd5a2d8cd',
'phabricator-application-launch-view-css' => 'd5a2d8cd',
'phabricator-busy' => 'f2ad0683',
'phabricator-content-source-view-css' => 'dd27a69b',
'phabricator-core-buttons-css' => '21f9f13d',
'phabricator-core-css' => '21f9f13d',
'phabricator-crumbs-view-css' => '21f9f13d',
'phabricator-core-buttons-css' => 'd5a2d8cd',
'phabricator-core-css' => 'd5a2d8cd',
'phabricator-crumbs-view-css' => 'd5a2d8cd',
'phabricator-drag-and-drop-file-upload' => '9488bb69',
'phabricator-dropdown-menu' => 'f2ad0683',
'phabricator-file-upload' => 'f2ad0683',
'phabricator-filetree-view-css' => '21f9f13d',
'phabricator-flag-css' => '21f9f13d',
'phabricator-form-view-css' => '21f9f13d',
'phabricator-header-view-css' => '21f9f13d',
'phabricator-filetree-view-css' => 'd5a2d8cd',
'phabricator-flag-css' => 'd5a2d8cd',
'phabricator-form-view-css' => 'd5a2d8cd',
'phabricator-header-view-css' => 'd5a2d8cd',
'phabricator-hovercard' => 'f2ad0683',
'phabricator-jump-nav' => '21f9f13d',
'phabricator-jump-nav' => 'd5a2d8cd',
'phabricator-keyboard-shortcut' => 'f2ad0683',
'phabricator-keyboard-shortcut-manager' => 'f2ad0683',
'phabricator-main-menu-view' => '21f9f13d',
'phabricator-main-menu-view' => 'd5a2d8cd',
'phabricator-menu-item' => 'f2ad0683',
'phabricator-nav-view-css' => '21f9f13d',
'phabricator-nav-view-css' => 'd5a2d8cd',
'phabricator-notification' => 'f2ad0683',
'phabricator-notification-css' => '21f9f13d',
'phabricator-notification-menu-css' => '21f9f13d',
'phabricator-object-item-list-view-css' => '21f9f13d',
'phabricator-notification-css' => 'd5a2d8cd',
'phabricator-notification-menu-css' => 'd5a2d8cd',
'phabricator-object-item-list-view-css' => 'd5a2d8cd',
'phabricator-object-selector-css' => 'dd27a69b',
'phabricator-phtize' => 'f2ad0683',
'phabricator-prefab' => 'f2ad0683',
'phabricator-project-tag-css' => '03ab92cf',
'phabricator-property-list-view-css' => '21f9f13d',
'phabricator-remarkup-css' => '21f9f13d',
'phabricator-property-list-view-css' => 'd5a2d8cd',
'phabricator-remarkup-css' => 'd5a2d8cd',
'phabricator-shaped-request' => '9488bb69',
'phabricator-side-menu-view-css' => '21f9f13d',
'phabricator-standard-page-view' => '21f9f13d',
'phabricator-tag-view-css' => '21f9f13d',
'phabricator-side-menu-view-css' => 'd5a2d8cd',
'phabricator-standard-page-view' => 'd5a2d8cd',
'phabricator-tag-view-css' => 'd5a2d8cd',
'phabricator-textareautils' => 'f2ad0683',
'phabricator-tooltip' => 'f2ad0683',
'phabricator-transaction-view-css' => '21f9f13d',
'phabricator-zindex-css' => '21f9f13d',
'phui-form-css' => '21f9f13d',
'phui-icon-view-css' => '21f9f13d',
'spacing-css' => '21f9f13d',
'sprite-apps-large-css' => '21f9f13d',
'sprite-gradient-css' => '21f9f13d',
'sprite-icons-css' => '21f9f13d',
'sprite-menu-css' => '21f9f13d',
'syntax-highlighting-css' => '21f9f13d',
'phabricator-transaction-view-css' => 'd5a2d8cd',
'phabricator-zindex-css' => 'd5a2d8cd',
'phui-form-css' => 'd5a2d8cd',
'phui-icon-view-css' => 'd5a2d8cd',
'spacing-css' => 'd5a2d8cd',
'sprite-apps-large-css' => 'd5a2d8cd',
'sprite-gradient-css' => 'd5a2d8cd',
'sprite-icons-css' => 'd5a2d8cd',
'sprite-menu-css' => 'd5a2d8cd',
'syntax-highlighting-css' => 'd5a2d8cd',
),
));

View file

@ -1400,6 +1400,7 @@ phutil_register_library_map(array(
'PhabricatorSearchIndexer' => 'applications/search/index/PhabricatorSearchIndexer.php',
'PhabricatorSearchManagementIndexWorkflow' => 'applications/search/management/PhabricatorSearchManagementIndexWorkflow.php',
'PhabricatorSearchManagementWorkflow' => 'applications/search/management/PhabricatorSearchManagementWorkflow.php',
'PhabricatorSearchOrderController' => 'applications/search/controller/PhabricatorSearchOrderController.php',
'PhabricatorSearchQuery' => 'applications/search/storage/PhabricatorSearchQuery.php',
'PhabricatorSearchRelationship' => 'applications/search/constants/PhabricatorSearchRelationship.php',
'PhabricatorSearchResultView' => 'applications/search/view/PhabricatorSearchResultView.php',
@ -3229,6 +3230,7 @@ phutil_register_library_map(array(
'PhabricatorSearchHovercardController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchManagementIndexWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorSearchManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorSearchOrderController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
'PhabricatorSearchResultView' => 'AphrontView',
'PhabricatorSearchSelectController' => 'PhabricatorSearchBaseController',

View file

@ -37,6 +37,7 @@ final class PhabricatorApplicationSearch extends PhabricatorApplication {
'edit/(?P<queryKey>[^/]+)/' => 'PhabricatorSearchEditController',
'delete/(?P<queryKey>[^/]+)/(?P<engine>[^/]+)/'
=> 'PhabricatorSearchDeleteController',
'order/(?P<engine>[^/]+)/' => 'PhabricatorSearchOrderController',
),
);
}

View file

@ -228,17 +228,23 @@ final class PhabricatorApplicationSearchController
$named_queries = $engine->loadAllNamedQueries();
$list_id = celerity_generate_unique_node_id();
$list = new PhabricatorObjectItemListView();
$list->setUser($user);
$list->setID($list_id);
Javelin::initBehavior(
'search-reorder-queries',
array(
'listID' => $list_id,
'orderURI' => '/search/order/'.get_class($engine).'/',
));
foreach ($named_queries as $named_query) {
$class = get_class($engine);
$key = $named_query->getQueryKey();
$date_created = phabricator_datetime(
$named_query->getDateCreated(),
$user);
$item = id(new PhabricatorObjectItemView())
->setHeader($named_query->getQueryName())
->setHref($engine->getQueryResultsPageURI($key));
@ -263,13 +269,19 @@ final class PhabricatorApplicationSearchController
}
$item->setBarColor('grey');
} else {
$item->addIcon('none', $date_created);
$item->addAction(
id(new PHUIListItemView())
->setIcon('edit')
->setHref('/search/edit/'.$key.'/'));
}
$item->setGrippable(true);
$item->addSigil('named-query');
$item->setMetadata(
array(
'queryKey' => $named_query->getQueryKey(),
));
$list->addItem($item);
}

View file

@ -36,12 +36,7 @@ final class PhabricatorSearchDeleteController
->executeOne();
if (!$named_query && $engine->isBuiltinQuery($key)) {
$named_query = id(new PhabricatorNamedQuery())
->setUserPHID($user->getPHID())
->setQueryName('(BUILTIN)')
->setQueryKey($key)
->setEngineClassName($this->engineClass)
->setIsBuiltin(true);
$named_query = $engine->getBuiltinQuery($key);
}
if (!$named_query) {

View file

@ -0,0 +1,44 @@
<?php
/**
* @group search
*/
final class PhabricatorSearchOrderController
extends PhabricatorSearchBaseController {
private $engineClass;
public function willProcessRequest(array $data) {
$this->engineClass = idx($data, 'engine');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$request->validateCSRF();
$base_class = 'PhabricatorApplicationSearchEngine';
if (!is_subclass_of($this->engineClass, $base_class)) {
return new Aphront400Response();
}
$engine = newv($this->engineClass, array());
$engine->setViewer($user);
$queries = $engine->loadAllNamedQueries();
$queries = mpull($queries, null, 'getQueryKey');
$order = $request->getStrList('order');
$queries = array_select_keys($queries, $order) + $queries;
$sequence = 1;
foreach ($queries as $query) {
$query->setSequence($sequence++);
$query->save();
}
return id(new AphrontAjaxResponse());
}
}

View file

@ -157,6 +157,8 @@ abstract class PhabricatorApplicationSearchEngine {
unset($builtin[$key]);
}
$named_queries = msort($named_queries, 'getSortKey');
return $named_queries + $builtin;
}
@ -181,12 +183,15 @@ abstract class PhabricatorApplicationSearchEngine {
$names = $this->getBuiltinQueryNames();
$queries = array();
$sequence = 0;
foreach ($names as $key => $name) {
$queries[$key] = id(new PhabricatorNamedQuery())
->setUserPHID($this->requireViewer()->getPHID())
->setEngineClassName(get_class($this))
->setQueryName($name)
->setQueryKey($key)
->setIsBuiltin(true)
->makeEphemeral();
->setSequence((1 << 24) + $sequence++)
->setIsBuiltin(true);
}
return $queries;

View file

@ -15,6 +15,10 @@ final class PhabricatorNamedQuery extends PhabricatorSearchDAO
protected $isDisabled = 0;
protected $sequence = 0;
public function getSortKey() {
return sprintf('~%010d%010d', $this->sequence, $this->getID());
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -50,6 +50,10 @@
z-index: 5;
}
.drag-dragging {
z-index: 5;
}
.phabricator-crumbs-view {
z-index: 3;
}

View file

@ -464,3 +464,20 @@
.phabricator-object-item-frame {
border-color: #99ccff;
}
.drag-ghost {
position: relative;
border: 1px dashed #aaaaaa;
background: #f9f9f9;
margin: 4px;
}
.drag-dragging {
position: relative;
opacity: 0.8;
}
.drag-sending {
opacity: 0.5;
}

View file

@ -0,0 +1,54 @@
/**
* @provides javelin-behavior-search-reorder-queries
* @requires javelin-behavior
* javelin-vector
* javelin-stratcom
* javelin-workflow
* javelin-dom
* phabricator-draggable-list
*/
JX.behavior('search-reorder-queries', function(config) {
var ghost = JX.$N('div', {className: 'drag-ghost'});
var root = JX.$(config.listID);
var list = new JX.DraggableList('named-query', root)
.setGhostNode(ghost)
.setFindItemsHandler(function() {
return JX.DOM.scry(root, 'li', 'named-query');
});
list.listen('didBeginDrag', function(node) {
list.getGhostNode().style.height = JX.Vector.getDim(node).y + 'px';
JX.DOM.alterClass(node, 'drag-dragging', true);
});
list.listen('didEndDrag', function(node) {
JX.DOM.alterClass(node, 'drag-dragging', false);
});
list.listen('didDrop', function(node, after) {
var nodes = list.findItems();
var order = [];
var key;
for (var ii = 0; ii < nodes.length; ii++) {
key = JX.Stratcom.getData(nodes[ii]).queryKey;
if (key) {
order.push(key);
}
}
list.lock();
JX.DOM.alterClass(node, 'drag-sending', true);
new JX.Workflow(config.orderURI, {order: order.join()})
.setHandler(function(e) {
JX.DOM.alterClass(node, 'drag-sending', false);
list.unlock();
})
.start();
});
});