mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-23 07:12:41 +01:00
Use ObjectItemListView for Maniphest
Summary: This isn't quite complete, but everything else is technical cleanup. Broadly: - Removed checkboxes. Selected state is now indicated with CSS, and toggled with shift-click. When nothing is selected, the text reads "Shift-Click Tasks to Select" to let users discover this feature. - Updated drag-to-reorder code to work with ObjectItemListView. - Closed/resolved is now shown with a grey footer icon. - Assigned is now shown with a user profile image handle icon, with a hover state. This could probably use some more tweaks, but overall I think it looks pretty reasonable? Test Plan: {F35897} Reviewers: chad Reviewed By: chad CC: aran Differential Revision: https://secure.phabricator.com/D5340
This commit is contained in:
parent
5e53fc750a
commit
018de5dec7
12 changed files with 359 additions and 531 deletions
|
@ -1638,13 +1638,14 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-behavior-maniphest-batch-selector' =>
|
'javelin-behavior-maniphest-batch-selector' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/398cf8d7/rsrc/js/application/maniphest/behavior-batch-selector.js',
|
'uri' => '/res/f8cf3b84/rsrc/js/application/maniphest/behavior-batch-selector.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-behavior',
|
0 => 'javelin-behavior',
|
||||||
1 => 'javelin-dom',
|
1 => 'javelin-dom',
|
||||||
2 => 'javelin-stratcom',
|
2 => 'javelin-stratcom',
|
||||||
|
3 => 'javelin-util',
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/maniphest/behavior-batch-selector.js',
|
'disk' => '/rsrc/js/application/maniphest/behavior-batch-selector.js',
|
||||||
),
|
),
|
||||||
|
@ -1663,7 +1664,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-behavior-maniphest-subpriority-editor' =>
|
'javelin-behavior-maniphest-subpriority-editor' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/5e02f19a/rsrc/js/application/maniphest/behavior-subpriorityeditor.js',
|
'uri' => '/res/21b73c2a/rsrc/js/application/maniphest/behavior-subpriorityeditor.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -2632,7 +2633,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'maniphest-task-summary-css' =>
|
'maniphest-task-summary-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/b3930263/rsrc/css/application/maniphest/task-summary.css',
|
'uri' => '/res/7aa9e2eb/rsrc/css/application/maniphest/task-summary.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -2995,7 +2996,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'phabricator-object-item-list-view-css' =>
|
'phabricator-object-item-list-view-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/aa09c531/rsrc/css/layout/phabricator-object-item-list-view.css',
|
'uri' => '/res/7d35d590/rsrc/css/layout/phabricator-object-item-list-view.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -3693,7 +3694,7 @@ celerity_register_resource_map(array(
|
||||||
), array(
|
), array(
|
||||||
'packages' =>
|
'packages' =>
|
||||||
array(
|
array(
|
||||||
'6c294512' =>
|
'a56848af' =>
|
||||||
array(
|
array(
|
||||||
'name' => 'core.pkg.css',
|
'name' => 'core.pkg.css',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
|
@ -3735,7 +3736,7 @@ celerity_register_resource_map(array(
|
||||||
34 => 'phabricator-object-item-list-view-css',
|
34 => 'phabricator-object-item-list-view-css',
|
||||||
35 => 'global-drag-and-drop-css',
|
35 => 'global-drag-and-drop-css',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/6c294512/core.pkg.css',
|
'uri' => '/res/pkg/a56848af/core.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'95ceba95' =>
|
'95ceba95' =>
|
||||||
|
@ -3895,7 +3896,7 @@ celerity_register_resource_map(array(
|
||||||
'uri' => '/res/pkg/fe22443b/javelin.pkg.js',
|
'uri' => '/res/pkg/fe22443b/javelin.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
'c41b4907' =>
|
'6b1fccc6' =>
|
||||||
array(
|
array(
|
||||||
'name' => 'maniphest.pkg.css',
|
'name' => 'maniphest.pkg.css',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
|
@ -3905,10 +3906,10 @@ celerity_register_resource_map(array(
|
||||||
2 => 'aphront-attached-file-view-css',
|
2 => 'aphront-attached-file-view-css',
|
||||||
3 => 'phabricator-project-tag-css',
|
3 => 'phabricator-project-tag-css',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/c41b4907/maniphest.pkg.css',
|
'uri' => '/res/pkg/6b1fccc6/maniphest.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'7707de41' =>
|
'f85eb6d8' =>
|
||||||
array(
|
array(
|
||||||
'name' => 'maniphest.pkg.js',
|
'name' => 'maniphest.pkg.js',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
|
@ -3919,23 +3920,23 @@ celerity_register_resource_map(array(
|
||||||
3 => 'javelin-behavior-maniphest-transaction-expand',
|
3 => 'javelin-behavior-maniphest-transaction-expand',
|
||||||
4 => 'javelin-behavior-maniphest-subpriority-editor',
|
4 => 'javelin-behavior-maniphest-subpriority-editor',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/7707de41/maniphest.pkg.js',
|
'uri' => '/res/pkg/f85eb6d8/maniphest.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'reverse' =>
|
'reverse' =>
|
||||||
array(
|
array(
|
||||||
'aphront-attached-file-view-css' => 'c41b4907',
|
'aphront-attached-file-view-css' => '6b1fccc6',
|
||||||
'aphront-dialog-view-css' => '6c294512',
|
'aphront-dialog-view-css' => 'a56848af',
|
||||||
'aphront-error-view-css' => '6c294512',
|
'aphront-error-view-css' => 'a56848af',
|
||||||
'aphront-form-view-css' => '6c294512',
|
'aphront-form-view-css' => 'a56848af',
|
||||||
'aphront-list-filter-view-css' => '6c294512',
|
'aphront-list-filter-view-css' => 'a56848af',
|
||||||
'aphront-pager-view-css' => '6c294512',
|
'aphront-pager-view-css' => 'a56848af',
|
||||||
'aphront-panel-view-css' => '6c294512',
|
'aphront-panel-view-css' => 'a56848af',
|
||||||
'aphront-table-view-css' => '6c294512',
|
'aphront-table-view-css' => 'a56848af',
|
||||||
'aphront-tokenizer-control-css' => '6c294512',
|
'aphront-tokenizer-control-css' => 'a56848af',
|
||||||
'aphront-tooltip-css' => '6c294512',
|
'aphront-tooltip-css' => 'a56848af',
|
||||||
'aphront-typeahead-control-css' => '6c294512',
|
'aphront-typeahead-control-css' => 'a56848af',
|
||||||
'differential-changeset-view-css' => '8aaacd1b',
|
'differential-changeset-view-css' => '8aaacd1b',
|
||||||
'differential-core-view-css' => '8aaacd1b',
|
'differential-core-view-css' => '8aaacd1b',
|
||||||
'differential-inline-comment-editor' => '322728f3',
|
'differential-inline-comment-editor' => '322728f3',
|
||||||
|
@ -3949,7 +3950,7 @@ celerity_register_resource_map(array(
|
||||||
'differential-table-of-contents-css' => '8aaacd1b',
|
'differential-table-of-contents-css' => '8aaacd1b',
|
||||||
'diffusion-commit-view-css' => 'c8ce2d88',
|
'diffusion-commit-view-css' => 'c8ce2d88',
|
||||||
'diffusion-icons-css' => 'c8ce2d88',
|
'diffusion-icons-css' => 'c8ce2d88',
|
||||||
'global-drag-and-drop-css' => '6c294512',
|
'global-drag-and-drop-css' => 'a56848af',
|
||||||
'inline-comment-summary-css' => '8aaacd1b',
|
'inline-comment-summary-css' => '8aaacd1b',
|
||||||
'javelin-aphlict' => '95ceba95',
|
'javelin-aphlict' => '95ceba95',
|
||||||
'javelin-behavior' => 'fe22443b',
|
'javelin-behavior' => 'fe22443b',
|
||||||
|
@ -3982,11 +3983,11 @@ celerity_register_resource_map(array(
|
||||||
'javelin-behavior-konami' => '95ceba95',
|
'javelin-behavior-konami' => '95ceba95',
|
||||||
'javelin-behavior-lightbox-attachments' => '95ceba95',
|
'javelin-behavior-lightbox-attachments' => '95ceba95',
|
||||||
'javelin-behavior-load-blame' => '322728f3',
|
'javelin-behavior-load-blame' => '322728f3',
|
||||||
'javelin-behavior-maniphest-batch-selector' => '7707de41',
|
'javelin-behavior-maniphest-batch-selector' => 'f85eb6d8',
|
||||||
'javelin-behavior-maniphest-subpriority-editor' => '7707de41',
|
'javelin-behavior-maniphest-subpriority-editor' => 'f85eb6d8',
|
||||||
'javelin-behavior-maniphest-transaction-controls' => '7707de41',
|
'javelin-behavior-maniphest-transaction-controls' => 'f85eb6d8',
|
||||||
'javelin-behavior-maniphest-transaction-expand' => '7707de41',
|
'javelin-behavior-maniphest-transaction-expand' => 'f85eb6d8',
|
||||||
'javelin-behavior-maniphest-transaction-preview' => '7707de41',
|
'javelin-behavior-maniphest-transaction-preview' => 'f85eb6d8',
|
||||||
'javelin-behavior-phabricator-active-nav' => '95ceba95',
|
'javelin-behavior-phabricator-active-nav' => '95ceba95',
|
||||||
'javelin-behavior-phabricator-autofocus' => '95ceba95',
|
'javelin-behavior-phabricator-autofocus' => '95ceba95',
|
||||||
'javelin-behavior-phabricator-gesture' => '95ceba95',
|
'javelin-behavior-phabricator-gesture' => '95ceba95',
|
||||||
|
@ -4021,48 +4022,48 @@ celerity_register_resource_map(array(
|
||||||
'javelin-util' => 'fe22443b',
|
'javelin-util' => 'fe22443b',
|
||||||
'javelin-vector' => 'fe22443b',
|
'javelin-vector' => 'fe22443b',
|
||||||
'javelin-workflow' => 'fe22443b',
|
'javelin-workflow' => 'fe22443b',
|
||||||
'lightbox-attachment-css' => '6c294512',
|
'lightbox-attachment-css' => 'a56848af',
|
||||||
'maniphest-task-summary-css' => 'c41b4907',
|
'maniphest-task-summary-css' => '6b1fccc6',
|
||||||
'maniphest-transaction-detail-css' => 'c41b4907',
|
'maniphest-transaction-detail-css' => '6b1fccc6',
|
||||||
'phabricator-busy' => '95ceba95',
|
'phabricator-busy' => '95ceba95',
|
||||||
'phabricator-content-source-view-css' => '8aaacd1b',
|
'phabricator-content-source-view-css' => '8aaacd1b',
|
||||||
'phabricator-core-buttons-css' => '6c294512',
|
'phabricator-core-buttons-css' => 'a56848af',
|
||||||
'phabricator-core-css' => '6c294512',
|
'phabricator-core-css' => 'a56848af',
|
||||||
'phabricator-crumbs-view-css' => '6c294512',
|
'phabricator-crumbs-view-css' => 'a56848af',
|
||||||
'phabricator-directory-css' => '6c294512',
|
'phabricator-directory-css' => 'a56848af',
|
||||||
'phabricator-drag-and-drop-file-upload' => '322728f3',
|
'phabricator-drag-and-drop-file-upload' => '322728f3',
|
||||||
'phabricator-dropdown-menu' => '95ceba95',
|
'phabricator-dropdown-menu' => '95ceba95',
|
||||||
'phabricator-file-upload' => '95ceba95',
|
'phabricator-file-upload' => '95ceba95',
|
||||||
'phabricator-filetree-view-css' => '6c294512',
|
'phabricator-filetree-view-css' => 'a56848af',
|
||||||
'phabricator-flag-css' => '6c294512',
|
'phabricator-flag-css' => 'a56848af',
|
||||||
'phabricator-form-view-css' => '6c294512',
|
'phabricator-form-view-css' => 'a56848af',
|
||||||
'phabricator-header-view-css' => '6c294512',
|
'phabricator-header-view-css' => 'a56848af',
|
||||||
'phabricator-jump-nav' => '6c294512',
|
'phabricator-jump-nav' => 'a56848af',
|
||||||
'phabricator-keyboard-shortcut' => '95ceba95',
|
'phabricator-keyboard-shortcut' => '95ceba95',
|
||||||
'phabricator-keyboard-shortcut-manager' => '95ceba95',
|
'phabricator-keyboard-shortcut-manager' => '95ceba95',
|
||||||
'phabricator-main-menu-view' => '6c294512',
|
'phabricator-main-menu-view' => 'a56848af',
|
||||||
'phabricator-menu-item' => '95ceba95',
|
'phabricator-menu-item' => '95ceba95',
|
||||||
'phabricator-nav-view-css' => '6c294512',
|
'phabricator-nav-view-css' => 'a56848af',
|
||||||
'phabricator-notification' => '95ceba95',
|
'phabricator-notification' => '95ceba95',
|
||||||
'phabricator-notification-css' => '6c294512',
|
'phabricator-notification-css' => 'a56848af',
|
||||||
'phabricator-notification-menu-css' => '6c294512',
|
'phabricator-notification-menu-css' => 'a56848af',
|
||||||
'phabricator-object-item-list-view-css' => '6c294512',
|
'phabricator-object-item-list-view-css' => 'a56848af',
|
||||||
'phabricator-object-selector-css' => '8aaacd1b',
|
'phabricator-object-selector-css' => '8aaacd1b',
|
||||||
'phabricator-paste-file-upload' => '95ceba95',
|
'phabricator-paste-file-upload' => '95ceba95',
|
||||||
'phabricator-prefab' => '95ceba95',
|
'phabricator-prefab' => '95ceba95',
|
||||||
'phabricator-project-tag-css' => 'c41b4907',
|
'phabricator-project-tag-css' => '6b1fccc6',
|
||||||
'phabricator-remarkup-css' => '6c294512',
|
'phabricator-remarkup-css' => 'a56848af',
|
||||||
'phabricator-shaped-request' => '322728f3',
|
'phabricator-shaped-request' => '322728f3',
|
||||||
'phabricator-side-menu-view-css' => '6c294512',
|
'phabricator-side-menu-view-css' => 'a56848af',
|
||||||
'phabricator-standard-page-view' => '6c294512',
|
'phabricator-standard-page-view' => 'a56848af',
|
||||||
'phabricator-textareautils' => '95ceba95',
|
'phabricator-textareautils' => '95ceba95',
|
||||||
'phabricator-tooltip' => '95ceba95',
|
'phabricator-tooltip' => '95ceba95',
|
||||||
'phabricator-transaction-view-css' => '6c294512',
|
'phabricator-transaction-view-css' => 'a56848af',
|
||||||
'phabricator-zindex-css' => '6c294512',
|
'phabricator-zindex-css' => 'a56848af',
|
||||||
'sprite-apps-large-css' => '6c294512',
|
'sprite-apps-large-css' => 'a56848af',
|
||||||
'sprite-gradient-css' => '6c294512',
|
'sprite-gradient-css' => 'a56848af',
|
||||||
'sprite-icon-css' => '6c294512',
|
'sprite-icon-css' => 'a56848af',
|
||||||
'sprite-menu-css' => '6c294512',
|
'sprite-menu-css' => 'a56848af',
|
||||||
'syntax-highlighting-css' => '6c294512',
|
'syntax-highlighting-css' => 'a56848af',
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
|
@ -7,6 +7,7 @@ final class ManiphestSubpriorityController extends ManiphestController {
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
if (!$request->validateCSRF()) {
|
if (!$request->validateCSRF()) {
|
||||||
return new Aphront403Response();
|
return new Aphront403Response();
|
||||||
|
@ -50,15 +51,26 @@ final class ManiphestSubpriorityController extends ManiphestController {
|
||||||
$task->setSubpriority($new_sub);
|
$task->setSubpriority($new_sub);
|
||||||
$task->save();
|
$task->save();
|
||||||
|
|
||||||
$pri_class = ManiphestTaskSummaryView::getPriorityClass(
|
$phids = $task->getProjectPHIDs();
|
||||||
$task->getPriority());
|
if ($task->getOwnerPHID()) {
|
||||||
$class = 'maniphest-task-handle maniphest-active-handle '.$pri_class;
|
$phids[] = $task->getOwnerPHID();
|
||||||
|
}
|
||||||
|
|
||||||
$response = array(
|
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||||
'className' => $class,
|
->setViewer($user)
|
||||||
);
|
->loadHandles();
|
||||||
|
|
||||||
return id(new AphrontAjaxResponse())->setContent($response);
|
$view = id(new ManiphestTaskListView())
|
||||||
|
->setUser($user)
|
||||||
|
->setShowSubpriorityControls(true)
|
||||||
|
->setShowBatchControls(true)
|
||||||
|
->setHandles($handles)
|
||||||
|
->setTasks(array($task));
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())->setContent(
|
||||||
|
array(
|
||||||
|
'tasks' => $view,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,23 +378,12 @@ final class ManiphestTaskListController extends ManiphestController {
|
||||||
$selector->appendChild($lists);
|
$selector->appendChild($lists);
|
||||||
$selector->appendChild($this->renderBatchEditor($query));
|
$selector->appendChild($this->renderBatchEditor($query));
|
||||||
|
|
||||||
$form_id = celerity_generate_unique_node_id();
|
|
||||||
$selector = phabricator_form(
|
|
||||||
$user,
|
|
||||||
array(
|
|
||||||
'method' => 'POST',
|
|
||||||
'action' => '/maniphest/batch/',
|
|
||||||
'id' => $form_id,
|
|
||||||
),
|
|
||||||
$selector->render());
|
|
||||||
|
|
||||||
$list_container->appendChild($selector);
|
$list_container->appendChild($selector);
|
||||||
$list_container->appendChild($pager);
|
$list_container->appendChild($pager);
|
||||||
|
|
||||||
Javelin::initBehavior(
|
Javelin::initBehavior(
|
||||||
'maniphest-subpriority-editor',
|
'maniphest-subpriority-editor',
|
||||||
array(
|
array(
|
||||||
'root' => $form_id,
|
|
||||||
'uri' => '/maniphest/subpriority/',
|
'uri' => '/maniphest/subpriority/',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -644,6 +633,8 @@ final class ManiphestTaskListController extends ManiphestController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderBatchEditor(PhabricatorSearchQuery $search_query) {
|
private function renderBatchEditor(PhabricatorSearchQuery $search_query) {
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
|
||||||
Javelin::initBehavior(
|
Javelin::initBehavior(
|
||||||
'maniphest-batch-selector',
|
'maniphest-batch-selector',
|
||||||
array(
|
array(
|
||||||
|
@ -651,6 +642,8 @@ final class ManiphestTaskListController extends ManiphestController {
|
||||||
'selectNone' => 'batch-select-none',
|
'selectNone' => 'batch-select-none',
|
||||||
'submit' => 'batch-select-submit',
|
'submit' => 'batch-select-submit',
|
||||||
'status' => 'batch-select-status-cell',
|
'status' => 'batch-select-status-cell',
|
||||||
|
'idContainer' => 'batch-select-id-container',
|
||||||
|
'formID' => 'batch-select-form',
|
||||||
));
|
));
|
||||||
|
|
||||||
$select_all = javelin_tag(
|
$select_all = javelin_tag(
|
||||||
|
@ -690,7 +683,14 @@ final class ManiphestTaskListController extends ManiphestController {
|
||||||
),
|
),
|
||||||
pht('Export to Excel'));
|
pht('Export to Excel'));
|
||||||
|
|
||||||
return hsprintf(
|
$hidden = phutil_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'id' => 'batch-select-id-container',
|
||||||
|
),
|
||||||
|
'');
|
||||||
|
|
||||||
|
$editor = hsprintf(
|
||||||
'<div class="maniphest-batch-editor">'.
|
'<div class="maniphest-batch-editor">'.
|
||||||
'<div class="batch-editor-header">%s</div>'.
|
'<div class="batch-editor-header">%s</div>'.
|
||||||
'<table class="maniphest-batch-editor-layout">'.
|
'<table class="maniphest-batch-editor-layout">'.
|
||||||
|
@ -698,16 +698,28 @@ final class ManiphestTaskListController extends ManiphestController {
|
||||||
'<td>%s%s</td>'.
|
'<td>%s%s</td>'.
|
||||||
'<td>%s</td>'.
|
'<td>%s</td>'.
|
||||||
'<td id="batch-select-status-cell">%s</td>'.
|
'<td id="batch-select-status-cell">%s</td>'.
|
||||||
'<td class="batch-select-submit-cell">%s</td>'.
|
'<td class="batch-select-submit-cell">%s%s</td>'.
|
||||||
'</tr>'.
|
'</tr>'.
|
||||||
'</table>'.
|
'</table>'.
|
||||||
'</table>',
|
'</div>',
|
||||||
pht('Batch Task Editor'),
|
pht('Batch Task Editor'),
|
||||||
$select_all,
|
$select_all,
|
||||||
$select_none,
|
$select_none,
|
||||||
$export,
|
$export,
|
||||||
pht('0 Selected'),
|
'',
|
||||||
$submit);
|
$submit,
|
||||||
|
$hidden);
|
||||||
|
|
||||||
|
$editor = phabricator_form(
|
||||||
|
$user,
|
||||||
|
array(
|
||||||
|
'method' => 'POST',
|
||||||
|
'action' => '/maniphest/batch/',
|
||||||
|
'id' => 'batch-select-form',
|
||||||
|
),
|
||||||
|
$editor);
|
||||||
|
|
||||||
|
return $editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildQueryFromRequest() {
|
private function buildQueryFromRequest() {
|
||||||
|
|
|
@ -33,19 +33,74 @@ final class ManiphestTaskListView extends ManiphestView {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
|
$handles = $this->handles;
|
||||||
|
|
||||||
|
$list = new PhabricatorObjectItemListView();
|
||||||
|
$list->setCards(true);
|
||||||
|
$list->setFlush(true);
|
||||||
|
|
||||||
|
$status_map = ManiphestTaskStatus::getTaskStatusMap();
|
||||||
|
$color_map = array(
|
||||||
|
ManiphestTaskPriority::PRIORITY_UNBREAK_NOW => 'magenta',
|
||||||
|
ManiphestTaskPriority::PRIORITY_TRIAGE => 'violet',
|
||||||
|
ManiphestTaskPriority::PRIORITY_HIGH => 'red',
|
||||||
|
ManiphestTaskPriority::PRIORITY_NORMAL => 'orange',
|
||||||
|
ManiphestTaskPriority::PRIORITY_LOW => 'yellow',
|
||||||
|
ManiphestTaskPriority::PRIORITY_WISH => 'sky',
|
||||||
|
);
|
||||||
|
|
||||||
$views = array();
|
|
||||||
foreach ($this->tasks as $task) {
|
foreach ($this->tasks as $task) {
|
||||||
$view = new ManiphestTaskSummaryView();
|
$item = new PhabricatorObjectItemView();
|
||||||
$view->setTask($task);
|
$item->setObjectName('T'.$task->getID());
|
||||||
$view->setShowBatchControls($this->showBatchControls);
|
$item->setHeader($task->getTitle());
|
||||||
$view->setShowSubpriorityControls($this->showSubpriorityControls);
|
$item->setHref('/T'.$task->getID());
|
||||||
$view->setUser($this->user);
|
|
||||||
$view->setHandles($this->handles);
|
if ($task->getOwnerPHID()) {
|
||||||
$views[] = $view->render();
|
$owner = $handles[$task->getOwnerPHID()];
|
||||||
|
$item->addHandleIcon(
|
||||||
|
$owner,
|
||||||
|
pht('Assigned: %s', $owner->getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = $task->getStatus();
|
||||||
|
if ($status != ManiphestTaskStatus::STATUS_OPEN) {
|
||||||
|
$item->addFootIcon(
|
||||||
|
($status == ManiphestTaskStatus::STATUS_CLOSED_RESOLVED)
|
||||||
|
? 'enable-white'
|
||||||
|
: 'delete-white',
|
||||||
|
idx($status_map, $status, 'Unknown'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->setBarColor(idx($color_map, $task->getPriority(), 'grey'));
|
||||||
|
|
||||||
|
$item->addIcon(
|
||||||
|
'none',
|
||||||
|
phabricator_datetime($task->getDateModified(), $this->getUser()));
|
||||||
|
|
||||||
|
if ($this->showSubpriorityControls) {
|
||||||
|
$item->setGrippable(true);
|
||||||
|
$item->addSigil('maniphest-task');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($task->getProjectPHIDs()) {
|
||||||
|
$projects_view = new ManiphestTaskProjectsView();
|
||||||
|
$projects_view->setHandles(
|
||||||
|
array_select_keys(
|
||||||
|
$handles,
|
||||||
|
$task->getProjectPHIDs()));
|
||||||
|
|
||||||
|
$item->addAttribute($projects_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->setMetadata(
|
||||||
|
array(
|
||||||
|
'taskID' => $task->getID(),
|
||||||
|
));
|
||||||
|
|
||||||
|
$list->addItem($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $views;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,196 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @group maniphest
|
|
||||||
*/
|
|
||||||
final class ManiphestTaskSummaryView extends ManiphestView {
|
|
||||||
|
|
||||||
private $task;
|
|
||||||
private $handles;
|
|
||||||
private $showBatchControls;
|
|
||||||
private $showSubpriorityControls;
|
|
||||||
|
|
||||||
public function setTask(ManiphestTask $task) {
|
|
||||||
$this->task = $task;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setHandles(array $handles) {
|
|
||||||
assert_instances_of($handles, 'PhabricatorObjectHandle');
|
|
||||||
$this->handles = $handles;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setShowBatchControls($show_batch_controls) {
|
|
||||||
$this->showBatchControls = $show_batch_controls;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setShowSubpriorityControls($show_subpriority_controls) {
|
|
||||||
$this->showSubpriorityControls = $show_subpriority_controls;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getPriorityClass($priority) {
|
|
||||||
$classes = array(
|
|
||||||
ManiphestTaskPriority::PRIORITY_UNBREAK_NOW => 'pri-unbreak',
|
|
||||||
ManiphestTaskPriority::PRIORITY_TRIAGE => 'pri-triage',
|
|
||||||
ManiphestTaskPriority::PRIORITY_HIGH => 'pri-high',
|
|
||||||
ManiphestTaskPriority::PRIORITY_NORMAL => 'pri-normal',
|
|
||||||
ManiphestTaskPriority::PRIORITY_LOW => 'pri-low',
|
|
||||||
ManiphestTaskPriority::PRIORITY_WISH => 'pri-wish',
|
|
||||||
);
|
|
||||||
|
|
||||||
return idx($classes, $priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render() {
|
|
||||||
|
|
||||||
if (!$this->user) {
|
|
||||||
throw new Exception("Call setUser() before rendering!");
|
|
||||||
}
|
|
||||||
|
|
||||||
$task = $this->task;
|
|
||||||
$handles = $this->handles;
|
|
||||||
|
|
||||||
require_celerity_resource('maniphest-task-summary-css');
|
|
||||||
|
|
||||||
$pri_class = self::getPriorityClass($task->getPriority());
|
|
||||||
$status_map = ManiphestTaskStatus::getTaskStatusMap();
|
|
||||||
|
|
||||||
$batch = null;
|
|
||||||
if ($this->showBatchControls) {
|
|
||||||
$batch = phutil_tag(
|
|
||||||
'td',
|
|
||||||
array(
|
|
||||||
'rowspan' => 2,
|
|
||||||
'class' => 'maniphest-task-batch',
|
|
||||||
),
|
|
||||||
javelin_tag(
|
|
||||||
'input',
|
|
||||||
array(
|
|
||||||
'type' => 'checkbox',
|
|
||||||
'name' => 'batch[]',
|
|
||||||
'value' => $task->getID(),
|
|
||||||
'sigil' => 'maniphest-batch',
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$projects_view = new ManiphestTaskProjectsView();
|
|
||||||
$projects_view->setHandles(
|
|
||||||
array_select_keys(
|
|
||||||
$this->handles,
|
|
||||||
$task->getProjectPHIDs()));
|
|
||||||
|
|
||||||
$control_class = null;
|
|
||||||
$control_sigil = null;
|
|
||||||
if ($this->showSubpriorityControls) {
|
|
||||||
$control_class = 'maniphest-active-handle';
|
|
||||||
$control_sigil = 'maniphest-task-handle';
|
|
||||||
}
|
|
||||||
|
|
||||||
$handle = javelin_tag(
|
|
||||||
'td',
|
|
||||||
array(
|
|
||||||
'rowspan' => 2,
|
|
||||||
'class' => 'maniphest-task-handle '.$pri_class.' '.$control_class,
|
|
||||||
'sigil' => $control_sigil,
|
|
||||||
),
|
|
||||||
'');
|
|
||||||
|
|
||||||
$task_name = phutil_tag(
|
|
||||||
'span',
|
|
||||||
array(
|
|
||||||
'class' => 'maniphest-task-name',
|
|
||||||
),
|
|
||||||
phutil_tag(
|
|
||||||
'a',
|
|
||||||
array(
|
|
||||||
'href' => '/T'.$task->getID(),
|
|
||||||
),
|
|
||||||
$task->getTitle()));
|
|
||||||
|
|
||||||
$task_updated = phutil_tag(
|
|
||||||
'span',
|
|
||||||
array(
|
|
||||||
'class' => 'maniphest-task-updated',
|
|
||||||
),
|
|
||||||
phabricator_date($task->getDateModified(), $this->user));
|
|
||||||
|
|
||||||
$task_info = phutil_tag(
|
|
||||||
'td',
|
|
||||||
array(
|
|
||||||
'colspan' => 2,
|
|
||||||
'class' => 'maniphest-task-number',
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'T'.$task->getID(),
|
|
||||||
$task_name,
|
|
||||||
$task_updated,
|
|
||||||
));
|
|
||||||
|
|
||||||
$owner = '';
|
|
||||||
if ($task->getOwnerPHID()) {
|
|
||||||
$owner = pht('Assigned to %s',
|
|
||||||
$handles[$task->getOwnerPHID()]->renderLink());
|
|
||||||
}
|
|
||||||
|
|
||||||
$task_owner = phutil_tag(
|
|
||||||
'span',
|
|
||||||
array(
|
|
||||||
'class' => 'maniphest-task-owner',
|
|
||||||
),
|
|
||||||
$task->getOwnerPHID()
|
|
||||||
? $owner
|
|
||||||
: phutil_tag('em', array(), pht('None')));
|
|
||||||
|
|
||||||
$task_status = phutil_tag(
|
|
||||||
'td',
|
|
||||||
array(
|
|
||||||
'class' => 'maniphest-task-status',
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
idx($status_map, $task->getStatus(), pht('Unknown')),
|
|
||||||
$task_owner,
|
|
||||||
));
|
|
||||||
|
|
||||||
$task_projects = phutil_tag(
|
|
||||||
'td',
|
|
||||||
array(
|
|
||||||
'class' => 'maniphest-task-projects',
|
|
||||||
),
|
|
||||||
$projects_view->render());
|
|
||||||
|
|
||||||
$row1 = phutil_tag(
|
|
||||||
'tr',
|
|
||||||
array(),
|
|
||||||
array(
|
|
||||||
$handle,
|
|
||||||
$batch,
|
|
||||||
$task_info,
|
|
||||||
));
|
|
||||||
|
|
||||||
$row2 = phutil_tag(
|
|
||||||
'tr',
|
|
||||||
array(),
|
|
||||||
array(
|
|
||||||
$task_status,
|
|
||||||
$task_projects,
|
|
||||||
));
|
|
||||||
|
|
||||||
return javelin_tag(
|
|
||||||
'table',
|
|
||||||
array(
|
|
||||||
'class' => 'maniphest-task-summary',
|
|
||||||
'sigil' => 'maniphest-task',
|
|
||||||
'meta' => array(
|
|
||||||
'taskID' => $task->getID(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
$row1,
|
|
||||||
$row2,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -240,6 +240,8 @@ final class PhabricatorProjectProfileController
|
||||||
PhabricatorProject $project,
|
PhabricatorProject $project,
|
||||||
PhabricatorProjectProfile $profile) {
|
PhabricatorProjectProfile $profile) {
|
||||||
|
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
|
||||||
$query = id(new ManiphestTaskQuery())
|
$query = id(new ManiphestTaskQuery())
|
||||||
->withAnyProjects(array($project->getPHID()))
|
->withAnyProjects(array($project->getPHID()))
|
||||||
->withStatus(ManiphestTaskQuery::STATUS_OPEN)
|
->withStatus(ManiphestTaskQuery::STATUS_OPEN)
|
||||||
|
@ -250,23 +252,16 @@ final class PhabricatorProjectProfileController
|
||||||
$count = $query->getRowCount();
|
$count = $query->getRowCount();
|
||||||
|
|
||||||
$phids = mpull($tasks, 'getOwnerPHID');
|
$phids = mpull($tasks, 'getOwnerPHID');
|
||||||
|
$phids = array_merge(
|
||||||
|
$phids,
|
||||||
|
array_mergev(mpull($tasks, 'getProjectPHIDs')));
|
||||||
$phids = array_filter($phids);
|
$phids = array_filter($phids);
|
||||||
$handles = $this->loadViewerHandles($phids);
|
$handles = $this->loadViewerHandles($phids);
|
||||||
|
|
||||||
$task_views = array();
|
$task_list = new ManiphestTaskListView();
|
||||||
foreach ($tasks as $task) {
|
$task_list->setUser($user);
|
||||||
$view = id(new ManiphestTaskSummaryView())
|
$task_list->setTasks($tasks);
|
||||||
->setTask($task)
|
$task_list->setHandles($handles);
|
||||||
->setHandles($handles)
|
|
||||||
->setUser($this->getRequest()->getUser());
|
|
||||||
$task_views[] = $view->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($tasks)) {
|
|
||||||
$task_views = phutil_tag('em', array(), pht('No open tasks.'));
|
|
||||||
} else {
|
|
||||||
$task_views = phutil_implode_html('', $task_views);
|
|
||||||
}
|
|
||||||
|
|
||||||
$open = number_format($count);
|
$open = number_format($count);
|
||||||
|
|
||||||
|
@ -286,7 +281,7 @@ final class PhabricatorProjectProfileController
|
||||||
'</div>
|
'</div>
|
||||||
</div>',
|
</div>',
|
||||||
pht('Open Tasks (%s)', $open),
|
pht('Open Tasks (%s)', $open),
|
||||||
$task_views,
|
$task_list,
|
||||||
$more_link);
|
$more_link);
|
||||||
|
|
||||||
return $content;
|
return $content;
|
||||||
|
|
|
@ -8,6 +8,12 @@ final class PhabricatorObjectItemListView extends AphrontView {
|
||||||
private $stackable;
|
private $stackable;
|
||||||
private $cards;
|
private $cards;
|
||||||
private $noDataString;
|
private $noDataString;
|
||||||
|
private $flush;
|
||||||
|
|
||||||
|
public function setFlush($flush) {
|
||||||
|
$this->flush = $flush;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setHeader($header) {
|
public function setHeader($header) {
|
||||||
$this->header = $header;
|
$this->header = $header;
|
||||||
|
@ -74,6 +80,9 @@ final class PhabricatorObjectItemListView extends AphrontView {
|
||||||
if ($this->cards) {
|
if ($this->cards) {
|
||||||
$classes[] = 'phabricator-object-list-cards';
|
$classes[] = 'phabricator-object-list-cards';
|
||||||
}
|
}
|
||||||
|
if ($this->flush) {
|
||||||
|
$classes[] = 'phabricator-object-list-flush';
|
||||||
|
}
|
||||||
|
|
||||||
return phutil_tag(
|
return phutil_tag(
|
||||||
'ul',
|
'ul',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class PhabricatorObjectItemView extends AphrontView {
|
final class PhabricatorObjectItemView extends AphrontTagView {
|
||||||
|
|
||||||
private $objectName;
|
private $objectName;
|
||||||
private $header;
|
private $header;
|
||||||
|
@ -105,9 +105,58 @@ final class PhabricatorObjectItemView extends AphrontView {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render() {
|
protected function getTagName() {
|
||||||
$content_classes = array();
|
return 'li';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTagAttributes() {
|
||||||
$item_classes = array();
|
$item_classes = array();
|
||||||
|
$item_classes[] = 'phabricator-object-item';
|
||||||
|
|
||||||
|
if ($this->icons) {
|
||||||
|
$item_classes[] = 'phabricator-object-item-with-icons';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->attributes) {
|
||||||
|
$item_classes[] = 'phabricator-object-item-with-attrs';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->handleIcons) {
|
||||||
|
$item_classes[] = 'phabricator-object-item-with-handle-icons';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->barColor) {
|
||||||
|
$item_classes[] = 'phabricator-object-item-bar-color-'.$this->barColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->footIcons) {
|
||||||
|
$item_classes[] = 'phabricator-object-item-with-foot-icons';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->effect) {
|
||||||
|
case 'highlighted':
|
||||||
|
$item_classes[] = 'phabricator-object-item-highlighted';
|
||||||
|
break;
|
||||||
|
case 'selected':
|
||||||
|
$item_classes[] = 'phabricator-object-item-selected';
|
||||||
|
break;
|
||||||
|
case null:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception(pht("Invalid effect!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getGrippable()) {
|
||||||
|
$item_classes[] = 'phabricator-object-item-grippable';
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'class' => $item_classes,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTagContent() {
|
||||||
|
$content_classes = array();
|
||||||
$content_classes[] = 'phabricator-object-item-content';
|
$content_classes[] = 'phabricator-object-item-content';
|
||||||
|
|
||||||
$header_name = null;
|
$header_name = null;
|
||||||
|
@ -131,10 +180,11 @@ final class PhabricatorObjectItemView extends AphrontView {
|
||||||
),
|
),
|
||||||
$this->header);
|
$this->header);
|
||||||
|
|
||||||
$header = phutil_tag(
|
$header = javelin_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'class' => 'phabricator-object-item-name',
|
'class' => 'phabricator-object-item-name',
|
||||||
|
'sigil' => 'slippery',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
$header_name,
|
$header_name,
|
||||||
|
@ -162,7 +212,6 @@ final class PhabricatorObjectItemView extends AphrontView {
|
||||||
),
|
),
|
||||||
$spec['label']);
|
$spec['label']);
|
||||||
|
|
||||||
|
|
||||||
if ($spec['href']) {
|
if ($spec['href']) {
|
||||||
$icon_href = phutil_tag(
|
$icon_href = phutil_tag(
|
||||||
'a',
|
'a',
|
||||||
|
@ -172,10 +221,16 @@ final class PhabricatorObjectItemView extends AphrontView {
|
||||||
$icon_href = array($label, $icon);
|
$icon_href = array($label, $icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$classes = array();
|
||||||
|
$classes[] = 'phabricator-object-item-icon';
|
||||||
|
if ($spec['icon'] == 'none') {
|
||||||
|
$classes[] = 'phabricator-object-item-icon-none';
|
||||||
|
}
|
||||||
|
|
||||||
$icon_list[] = phutil_tag(
|
$icon_list[] = phutil_tag(
|
||||||
'li',
|
'li',
|
||||||
array(
|
array(
|
||||||
'class' => 'phabricator-object-item-icon',
|
'class' => implode(' ', $classes),
|
||||||
),
|
),
|
||||||
$icon_href);
|
$icon_href);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +241,6 @@ final class PhabricatorObjectItemView extends AphrontView {
|
||||||
'class' => 'phabricator-object-item-icons',
|
'class' => 'phabricator-object-item-icons',
|
||||||
),
|
),
|
||||||
$icon_list);
|
$icon_list);
|
||||||
$item_classes[] = 'phabricator-object-item-with-icons';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->handleIcons) {
|
if ($this->handleIcons) {
|
||||||
|
@ -200,7 +254,6 @@ final class PhabricatorObjectItemView extends AphrontView {
|
||||||
'class' => 'phabricator-object-item-handle-icons',
|
'class' => 'phabricator-object-item-handle-icons',
|
||||||
),
|
),
|
||||||
$handle_bar);
|
$handle_bar);
|
||||||
$item_classes[] = 'phabricator-object-item-with-handle-icons';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($icons) {
|
if ($icons) {
|
||||||
|
@ -240,7 +293,6 @@ final class PhabricatorObjectItemView extends AphrontView {
|
||||||
'class' => 'phabricator-object-item-attributes',
|
'class' => 'phabricator-object-item-attributes',
|
||||||
),
|
),
|
||||||
$attrs);
|
$attrs);
|
||||||
$item_classes[] = 'phabricator-object-item-with-attrs';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$foot = null;
|
$foot = null;
|
||||||
|
@ -255,30 +307,10 @@ final class PhabricatorObjectItemView extends AphrontView {
|
||||||
'class' => 'phabricator-object-item-foot-icons',
|
'class' => 'phabricator-object-item-foot-icons',
|
||||||
),
|
),
|
||||||
$foot_bar);
|
$foot_bar);
|
||||||
$item_classes[] = 'phabricator-object-item-with-foot-icons';
|
|
||||||
}
|
|
||||||
|
|
||||||
$item_classes[] = 'phabricator-object-item';
|
|
||||||
if ($this->barColor) {
|
|
||||||
$item_classes[] = 'phabricator-object-item-bar-color-'.$this->barColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($this->effect) {
|
|
||||||
case 'highlighted':
|
|
||||||
$item_classes[] = 'phabricator-object-item-highlighted';
|
|
||||||
break;
|
|
||||||
case 'selected':
|
|
||||||
$item_classes[] = 'phabricator-object-item-selected';
|
|
||||||
break;
|
|
||||||
case null:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Exception(pht("Invalid effect!"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$grippable = null;
|
$grippable = null;
|
||||||
if ($this->getGrippable()) {
|
if ($this->getGrippable()) {
|
||||||
$item_classes[] = 'phabricator-object-item-grippable';
|
|
||||||
$grippable = phutil_tag(
|
$grippable = phutil_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
|
@ -300,20 +332,15 @@ final class PhabricatorObjectItemView extends AphrontView {
|
||||||
));
|
));
|
||||||
|
|
||||||
return phutil_tag(
|
return phutil_tag(
|
||||||
'li',
|
'div',
|
||||||
array(
|
array(
|
||||||
'class' => implode(' ', $item_classes),
|
'class' => 'phabricator-object-item-frame',
|
||||||
),
|
),
|
||||||
phutil_tag(
|
array(
|
||||||
'div',
|
$grippable,
|
||||||
array(
|
$icons,
|
||||||
'class' => 'phabricator-object-item-frame',
|
$content,
|
||||||
),
|
));
|
||||||
array(
|
|
||||||
$grippable,
|
|
||||||
$icons,
|
|
||||||
$content,
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderFootIcon($icon, $label) {
|
private function renderFootIcon($icon, $label) {
|
||||||
|
|
|
@ -2,123 +2,19 @@
|
||||||
* @provides maniphest-task-summary-css
|
* @provides maniphest-task-summary-css
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.maniphest-task-summary {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 0 -1px 0;
|
|
||||||
border-collapse: separate;
|
|
||||||
color: #333;
|
|
||||||
border: 1px solid #c0c5d1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-group {
|
.maniphest-task-group {
|
||||||
padding-bottom: 30px;
|
padding-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.maniphest-task-summary td {
|
|
||||||
padding: 0 10px;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary td em {
|
|
||||||
color: #888888;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-batch-selected td {
|
.maniphest-batch-selected td {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.maniphest-task-summary .maniphest-task-handle {
|
|
||||||
padding: 0 4px 0 0;
|
|
||||||
width: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary td.maniphest-task-batch {
|
|
||||||
padding: 15px 4px 0 10px;
|
|
||||||
width: 8px;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-phone .maniphest-task-batch,
|
.device-phone .maniphest-task-batch,
|
||||||
.device-phone .maniphest-task-updated {
|
.device-phone .maniphest-task-updated {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.maniphest-task-summary td.maniphest-task-batch,
|
|
||||||
.maniphest-task-summary td.maniphest-task-batch input {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary td.maniphest-task-batch input {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary td.maniphest-task-number {
|
|
||||||
padding: 6px 0 2px 10px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary td.maniphest-task-status {
|
|
||||||
padding: 2px 10px 6px 10px;
|
|
||||||
text-align: left;
|
|
||||||
color: #777;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary .maniphest-task-owner {
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary .maniphest-task-name {
|
|
||||||
font-weight: bold;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary td.maniphest-task-projects {
|
|
||||||
text-align: right;
|
|
||||||
padding: 0px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary .maniphest-task-updated {
|
|
||||||
float: right;
|
|
||||||
padding: 0 8px;
|
|
||||||
color: #777;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary .pri-unbreak {
|
|
||||||
border-color: #ff0000;
|
|
||||||
background-color: #ff0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary .pri-triage {
|
|
||||||
border-color: #ee00ee;
|
|
||||||
background-color: #ee00ee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary .pri-high {
|
|
||||||
border-color: #ff6622;
|
|
||||||
background-color: #ff6622;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary .pri-normal {
|
|
||||||
border-color: #ffaa66;
|
|
||||||
background-color: #ffaa66;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary .pri-low {
|
|
||||||
border-color: #eecc66;
|
|
||||||
background-color: #eecc66;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-summary .pri-wish {
|
|
||||||
border-color: #0099ff;
|
|
||||||
background-color: #0099ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-task-group-header {
|
.maniphest-task-group-header {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -179,26 +75,20 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
td.maniphest-active-handle {
|
|
||||||
cursor: move;
|
|
||||||
background-image: url('/rsrc/image/grippy_texture.png');
|
|
||||||
background-position: 3px 0px;
|
|
||||||
background-repeat: repeat-y;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maniphest-subpriority-target {
|
.maniphest-subpriority-target {
|
||||||
position: relative;
|
position: relative;
|
||||||
border: 1px dashed #aaaaaa;
|
border: 1px dashed #aaaaaa;
|
||||||
background: #f9f9f9;
|
background: #f9f9f9;
|
||||||
|
margin: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.maniphest-task-loading {
|
.maniphest-task-loading {
|
||||||
opacity: 0.5;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
.maniphest-task-dragging {
|
.maniphest-task-dragging {
|
||||||
position: relative;
|
position: relative;
|
||||||
opacity: 0.5;
|
opacity: 0.90;
|
||||||
}
|
}
|
||||||
|
|
||||||
.maniphest-list-container {
|
.maniphest-list-container {
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.phabricator-object-item-name {
|
.phabricator-object-item-name {
|
||||||
display: block;
|
display: inline-block;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
|
@ -49,9 +49,9 @@
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.phabricator-object-item-objname {
|
.phabricator-object-item-objname {
|
||||||
color: #222222;
|
color: #222222;
|
||||||
|
cursor: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.phabricator-object-item-with-attrs .phabricator-object-item-name {
|
.phabricator-object-item-with-attrs .phabricator-object-item-name {
|
||||||
|
|
|
@ -3,39 +3,42 @@
|
||||||
* @requires javelin-behavior
|
* @requires javelin-behavior
|
||||||
* javelin-dom
|
* javelin-dom
|
||||||
* javelin-stratcom
|
* javelin-stratcom
|
||||||
|
* javelin-util
|
||||||
*/
|
*/
|
||||||
|
|
||||||
JX.behavior('maniphest-batch-selector', function(config) {
|
JX.behavior('maniphest-batch-selector', function(config) {
|
||||||
|
|
||||||
// When a task row's selection state is changed, this issues updates to other
|
var selected = {};
|
||||||
// parts of the application.
|
|
||||||
|
|
||||||
var onchange = function(task) {
|
// Test if a task node is selected.
|
||||||
var input = JX.DOM.find(task, 'input', 'maniphest-batch');
|
|
||||||
var state = input.checked;
|
|
||||||
|
|
||||||
JX.DOM.alterClass(task, 'maniphest-batch-selected', state);
|
var get_id = function(task) {
|
||||||
|
return JX.Stratcom.getData(task).taskID;
|
||||||
JX.Stratcom.invoke(
|
}
|
||||||
(state ? 'maniphest-batch-task-add' : 'maniphest-batch-task-rem'),
|
|
||||||
null,
|
|
||||||
{id: input.value})
|
|
||||||
};
|
|
||||||
|
|
||||||
|
var is_selected = function(task) {
|
||||||
|
return (get_id(task) in selected);
|
||||||
|
}
|
||||||
|
|
||||||
// Change the selected state of a task.
|
// Change the selected state of a task.
|
||||||
// If 'to' is undefined, toggle. Otherwise, set to true or false.
|
|
||||||
|
|
||||||
var change = function(task, to) {
|
var change = function(task, to) {
|
||||||
|
|
||||||
var input = JX.DOM.find(task, 'input', 'maniphest-batch');
|
|
||||||
var state = input.checked;
|
|
||||||
if (to === undefined) {
|
if (to === undefined) {
|
||||||
input.checked = !input.checked;
|
to = !is_selected(task);
|
||||||
} else {
|
|
||||||
input.checked = to;
|
|
||||||
}
|
}
|
||||||
onchange(task);
|
|
||||||
|
if (to) {
|
||||||
|
selected[get_id(task)] = true;
|
||||||
|
} else {
|
||||||
|
delete selected[get_id(task)];
|
||||||
|
}
|
||||||
|
|
||||||
|
JX.DOM.alterClass(
|
||||||
|
task,
|
||||||
|
'phabricator-object-item-selected',
|
||||||
|
is_selected(task));
|
||||||
|
|
||||||
|
update();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,62 +46,72 @@ JX.behavior('maniphest-batch-selector', function(config) {
|
||||||
// buttons).
|
// buttons).
|
||||||
|
|
||||||
var changeall = function(to) {
|
var changeall = function(to) {
|
||||||
var inputs = JX.DOM.scry(document.body, 'table', 'maniphest-task');
|
var inputs = JX.DOM.scry(document.body, 'li', 'maniphest-task');
|
||||||
for (var ii = 0; ii < inputs.length; ii++) {
|
for (var ii = 0; ii < inputs.length; ii++) {
|
||||||
change(inputs[ii], to);
|
change(inputs[ii], to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear any document text selection after toggling a task via shift click,
|
||||||
|
// since errant clicks tend to start selecting various ranges otherwise.
|
||||||
|
|
||||||
|
var clear_selection = function() {
|
||||||
|
if (window.getSelection) {
|
||||||
|
if (window.getSelection().empty) {
|
||||||
|
window.getSelection().empty();
|
||||||
|
} else if (window.getSelection().removeAllRanges) {
|
||||||
|
window.getSelection().removeAllRanges();
|
||||||
|
}
|
||||||
|
} else if (document.selection) {
|
||||||
|
document.selection.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update the status text showing how many tasks are selected, and the button
|
// Update the status text showing how many tasks are selected, and the button
|
||||||
// state.
|
// state.
|
||||||
|
|
||||||
var selected = {};
|
|
||||||
var selected_count = 0;
|
|
||||||
|
|
||||||
var update = function() {
|
var update = function() {
|
||||||
var status = (selected_count == 1)
|
var count = JX.keys(selected).length;
|
||||||
? '1 Selected Task'
|
var status;
|
||||||
: selected_count + ' Selected Tasks';
|
if (count == 0) {
|
||||||
|
status = 'Shift-Click to Select Tasks';
|
||||||
|
} else if (status == 1) {
|
||||||
|
status = '1 Selected Task';
|
||||||
|
} else {
|
||||||
|
status = count + ' Selected Tasks';
|
||||||
|
}
|
||||||
JX.DOM.setContent(JX.$(config.status), status);
|
JX.DOM.setContent(JX.$(config.status), status);
|
||||||
|
|
||||||
var submit = JX.$(config.submit);
|
var submit = JX.$(config.submit);
|
||||||
var disable = (selected_count == 0);
|
var disable = (count == 0);
|
||||||
submit.disabled = disable;
|
submit.disabled = disable;
|
||||||
JX.DOM.alterClass(submit, 'disabled', disable);
|
JX.DOM.alterClass(submit, 'disabled', disable);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// When he user shift-clicks the task, update the rest of the application
|
||||||
// When the user clicks the entire <td /> surrounding the checkbox, count it
|
// state.
|
||||||
// as a checkbox click.
|
|
||||||
|
|
||||||
JX.Stratcom.listen(
|
JX.Stratcom.listen(
|
||||||
'click',
|
'click',
|
||||||
'maniphest-task',
|
'maniphest-task',
|
||||||
function(e) {
|
function(e) {
|
||||||
if (!JX.DOM.isNode(e.getTarget(), 'td')) {
|
var raw = e.getRawEvent();
|
||||||
// Only count clicks in the <td />, not (e.g.) the table border.
|
if (!raw.shiftKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the clicked <td /> contains a checkbox.
|
if (raw.ctrlKey || raw.altKey || raw.metaKey || e.isRightButton()) {
|
||||||
var inputs = JX.DOM.scry(e.getTarget(), 'input', 'maniphest-batch');
|
|
||||||
if (!inputs.length) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (JX.Stratcom.pass(e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.kill();
|
||||||
change(e.getNode('maniphest-task'));
|
change(e.getNode('maniphest-task'));
|
||||||
});
|
|
||||||
|
|
||||||
|
clear_selection();
|
||||||
// When he user clicks the <input />, update the rest of the application
|
|
||||||
// state.
|
|
||||||
|
|
||||||
JX.Stratcom.listen(
|
|
||||||
['click', 'onchange'],
|
|
||||||
'maniphest-batch',
|
|
||||||
function(e) {
|
|
||||||
onchange(e.getNode('maniphest-task'));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -125,30 +138,21 @@ JX.behavior('maniphest-batch-selector', function(config) {
|
||||||
e.kill();
|
e.kill();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// When the user submits the form, dump selected state into it.
|
||||||
|
|
||||||
JX.Stratcom.listen(
|
JX.DOM.listen(
|
||||||
'maniphest-batch-task-add',
|
JX.$(config.formID),
|
||||||
|
'submit',
|
||||||
null,
|
null,
|
||||||
function(e) {
|
function(e) {
|
||||||
var id = e.getData().id;
|
var inputs = [];
|
||||||
if (!(id in selected)) {
|
for (var k in selected) {
|
||||||
selected[id] = true;
|
inputs.push(
|
||||||
selected_count++;
|
JX.$N('input', {type: 'hidden', name: 'batch[]', value: k}));
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
JX.DOM.setContent(JX.$(config.idContainer), inputs);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
update();
|
||||||
JX.Stratcom.listen(
|
|
||||||
'maniphest-batch-task-rem',
|
|
||||||
null,
|
|
||||||
function(e) {
|
|
||||||
var id = e.getData().id;
|
|
||||||
if (id in selected) {
|
|
||||||
delete selected[id];
|
|
||||||
selected_count--;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,18 +15,27 @@ JX.behavior('maniphest-subpriority-editor', function(config) {
|
||||||
var origin = null;
|
var origin = null;
|
||||||
var targets = null;
|
var targets = null;
|
||||||
var target = null;
|
var target = null;
|
||||||
var droptarget = JX.$N('div', {className: 'maniphest-subpriority-target'});
|
var droptarget = JX.$N('li', {className: 'maniphest-subpriority-target'});
|
||||||
|
|
||||||
var ondrag = function(e) {
|
var ondrag = function(e) {
|
||||||
if (dragging || sending) {
|
if (dragging || sending) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!e.isNormalMouseEvent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't grab onto slippery nodes.
|
||||||
|
if (e.getNode('slippery')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dragging = e.getNode('maniphest-task');
|
dragging = e.getNode('maniphest-task');
|
||||||
origin = JX.$V(e);
|
origin = JX.$V(e);
|
||||||
|
|
||||||
var tasks = JX.DOM.scry(JX.$(config.root), 'table', 'maniphest-task');
|
var tasks = JX.DOM.scry(document.body, 'li', 'maniphest-task');
|
||||||
var heads = JX.DOM.scry(JX.$(config.root), 'h1', 'task-group');
|
var heads = JX.DOM.scry(document.body, 'h1', 'task-group');
|
||||||
|
|
||||||
var nodes = tasks.concat(heads);
|
var nodes = tasks.concat(heads);
|
||||||
|
|
||||||
|
@ -107,10 +116,19 @@ JX.behavior('maniphest-subpriority-editor', function(config) {
|
||||||
|
|
||||||
if (cur_target) {
|
if (cur_target) {
|
||||||
if (cur_target.nextSibling) {
|
if (cur_target.nextSibling) {
|
||||||
cur_target.parentNode.insertBefore(
|
if (JX.DOM.isType(cur_target, 'h1')) {
|
||||||
droptarget,
|
// Dropping at the beginning of a priority list.
|
||||||
cur_target.nextSibling);
|
cur_target.nextSibling.insertBefore(
|
||||||
|
droptarget,
|
||||||
|
cur_target.nextSibling.firstChild);
|
||||||
|
} else {
|
||||||
|
// Dropping in the middle of a priority list.
|
||||||
|
cur_target.parentNode.insertBefore(
|
||||||
|
droptarget,
|
||||||
|
cur_target.nextSibling);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Dropping at the end of a priority list.
|
||||||
cur_target.parentNode.appendChild(droptarget);
|
cur_target.parentNode.appendChild(droptarget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,9 +198,10 @@ JX.behavior('maniphest-subpriority-editor', function(config) {
|
||||||
JX.DOM.alterClass(sending, 'maniphest-task-loading', true);
|
JX.DOM.alterClass(sending, 'maniphest-task-loading', true);
|
||||||
|
|
||||||
var onresponse = function(r) {
|
var onresponse = function(r) {
|
||||||
JX.DOM.alterClass(sending, 'maniphest-task-loading', false);
|
var nodes = JX.$H(r.tasks).getFragment().firstChild;
|
||||||
var handle = JX.DOM.find(sending, 'td', 'maniphest-task-handle');
|
var task = JX.DOM.find(nodes, 'li', 'maniphest-task');
|
||||||
handle.className = r.className;
|
JX.DOM.replace(sending, task);
|
||||||
|
|
||||||
sending = null;
|
sending = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -196,8 +215,8 @@ JX.behavior('maniphest-subpriority-editor', function(config) {
|
||||||
// NOTE: Javelin does not dispatch mousemove by default.
|
// NOTE: Javelin does not dispatch mousemove by default.
|
||||||
JX.enableDispatch(document.body, 'mousemove');
|
JX.enableDispatch(document.body, 'mousemove');
|
||||||
|
|
||||||
JX.Stratcom.listen('mousedown', 'maniphest-task-handle', ondrag);
|
JX.Stratcom.listen('mousedown', 'maniphest-task', ondrag);
|
||||||
JX.Stratcom.listen('mousemove', null, onmove);
|
JX.Stratcom.listen('mousemove', null, onmove);
|
||||||
JX.Stratcom.listen('mouseup', null, ondrop);
|
JX.Stratcom.listen('mouseup', null, ondrop);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue