mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 05:50:55 +01:00
Make the rest of the board drag-and-drop UI mostly work
Summary: Ref T1344. Makes the UI/UX a little nicer; still no actual backend stuff. This changes: - When you drop an item onto a different column, the item actually moves. - Empty columns render with a special CSS class now, but no nodes in the list. This cleans up some JS jankiness. I made the "empty" columns have a light blue background for now. We could put some sort of subtle background image in them instead, or some kind of call to action if it's not redundant with other UI. Test Plan: {F101208} Reviewers: chad, btrahan Reviewed By: chad CC: chad, aran Maniphest Tasks: T1344 Differential Revision: https://secure.phabricator.com/D7942
This commit is contained in:
parent
826914e990
commit
a101b4ba2e
7 changed files with 77 additions and 35 deletions
|
@ -7,7 +7,7 @@
|
||||||
return array(
|
return array(
|
||||||
'names' =>
|
'names' =>
|
||||||
array(
|
array(
|
||||||
'core.pkg.css' => 'ac7deb21',
|
'core.pkg.css' => 'dddca4dc',
|
||||||
'core.pkg.js' => 'c907bd96',
|
'core.pkg.js' => 'c907bd96',
|
||||||
'darkconsole.pkg.js' => 'ca8671ce',
|
'darkconsole.pkg.js' => 'ca8671ce',
|
||||||
'differential.pkg.css' => '827749c1',
|
'differential.pkg.css' => '827749c1',
|
||||||
|
@ -137,7 +137,7 @@ return array(
|
||||||
'rsrc/css/phui/phui-info-panel.css' => '27ea50a1',
|
'rsrc/css/phui/phui-info-panel.css' => '27ea50a1',
|
||||||
'rsrc/css/phui/phui-list.css' => '2edb76cf',
|
'rsrc/css/phui/phui-list.css' => '2edb76cf',
|
||||||
'rsrc/css/phui/phui-object-box.css' => '4f916b80',
|
'rsrc/css/phui/phui-object-box.css' => '4f916b80',
|
||||||
'rsrc/css/phui/phui-object-item-list-view.css' => 'fdd2c06f',
|
'rsrc/css/phui/phui-object-item-list-view.css' => 'e8192ada',
|
||||||
'rsrc/css/phui/phui-pinboard-view.css' => '53c5fca0',
|
'rsrc/css/phui/phui-pinboard-view.css' => '53c5fca0',
|
||||||
'rsrc/css/phui/phui-property-list-view.css' => '354465ae',
|
'rsrc/css/phui/phui-property-list-view.css' => '354465ae',
|
||||||
'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b',
|
'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b',
|
||||||
|
@ -145,7 +145,7 @@ return array(
|
||||||
'rsrc/css/phui/phui-status.css' => '2f562399',
|
'rsrc/css/phui/phui-status.css' => '2f562399',
|
||||||
'rsrc/css/phui/phui-text.css' => '23e9b4b7',
|
'rsrc/css/phui/phui-text.css' => '23e9b4b7',
|
||||||
'rsrc/css/phui/phui-workboard-view.css' => 'bf70dd2e',
|
'rsrc/css/phui/phui-workboard-view.css' => 'bf70dd2e',
|
||||||
'rsrc/css/phui/phui-workpanel-view.css' => '26f738ce',
|
'rsrc/css/phui/phui-workpanel-view.css' => 'ffb31e99',
|
||||||
'rsrc/css/sprite-actions.css' => '4557baf8',
|
'rsrc/css/sprite-actions.css' => '4557baf8',
|
||||||
'rsrc/css/sprite-apps-large.css' => 'e37c2ff1',
|
'rsrc/css/sprite-apps-large.css' => 'e37c2ff1',
|
||||||
'rsrc/css/sprite-apps-xlarge.css' => 'db66c878',
|
'rsrc/css/sprite-apps-xlarge.css' => 'db66c878',
|
||||||
|
@ -392,7 +392,7 @@ return array(
|
||||||
'rsrc/js/application/policy/behavior-policy-control.js' => 'c01153ea',
|
'rsrc/js/application/policy/behavior-policy-control.js' => 'c01153ea',
|
||||||
'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '263aeb8c',
|
'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '263aeb8c',
|
||||||
'rsrc/js/application/ponder/behavior-votebox.js' => '327dbe61',
|
'rsrc/js/application/ponder/behavior-votebox.js' => '327dbe61',
|
||||||
'rsrc/js/application/projects/behavior-project-boards.js' => 'd4cbe3d5',
|
'rsrc/js/application/projects/behavior-project-boards.js' => '9c9f91ec',
|
||||||
'rsrc/js/application/projects/behavior-project-create.js' => '065227cc',
|
'rsrc/js/application/projects/behavior-project-create.js' => '065227cc',
|
||||||
'rsrc/js/application/releeph/releeph-preview-branch.js' => '9eb2cedb',
|
'rsrc/js/application/releeph/releeph-preview-branch.js' => '9eb2cedb',
|
||||||
'rsrc/js/application/releeph/releeph-request-state-change.js' => 'fe7fc914',
|
'rsrc/js/application/releeph/releeph-request-state-change.js' => 'fe7fc914',
|
||||||
|
@ -417,7 +417,7 @@ return array(
|
||||||
'rsrc/js/application/uiexample/notification-example.js' => 'c51a6616',
|
'rsrc/js/application/uiexample/notification-example.js' => 'c51a6616',
|
||||||
'rsrc/js/core/Busy.js' => '6453c869',
|
'rsrc/js/core/Busy.js' => '6453c869',
|
||||||
'rsrc/js/core/DragAndDropFileUpload.js' => 'ae6abfba',
|
'rsrc/js/core/DragAndDropFileUpload.js' => 'ae6abfba',
|
||||||
'rsrc/js/core/DraggableList.js' => '5fb99faa',
|
'rsrc/js/core/DraggableList.js' => '14824eb5',
|
||||||
'rsrc/js/core/DropdownMenu.js' => '2f6f80f4',
|
'rsrc/js/core/DropdownMenu.js' => '2f6f80f4',
|
||||||
'rsrc/js/core/DropdownMenuItem.js' => '0f386ef4',
|
'rsrc/js/core/DropdownMenuItem.js' => '0f386ef4',
|
||||||
'rsrc/js/core/FileUpload.js' => '96713558',
|
'rsrc/js/core/FileUpload.js' => '96713558',
|
||||||
|
@ -603,7 +603,7 @@ return array(
|
||||||
'javelin-behavior-policy-control' => 'c01153ea',
|
'javelin-behavior-policy-control' => 'c01153ea',
|
||||||
'javelin-behavior-policy-rule-editor' => '263aeb8c',
|
'javelin-behavior-policy-rule-editor' => '263aeb8c',
|
||||||
'javelin-behavior-ponder-votebox' => '327dbe61',
|
'javelin-behavior-ponder-votebox' => '327dbe61',
|
||||||
'javelin-behavior-project-boards' => 'd4cbe3d5',
|
'javelin-behavior-project-boards' => '9c9f91ec',
|
||||||
'javelin-behavior-project-create' => '065227cc',
|
'javelin-behavior-project-create' => '065227cc',
|
||||||
'javelin-behavior-refresh-csrf' => 'c4b31646',
|
'javelin-behavior-refresh-csrf' => 'c4b31646',
|
||||||
'javelin-behavior-releeph-preview-branch' => '9eb2cedb',
|
'javelin-behavior-releeph-preview-branch' => '9eb2cedb',
|
||||||
|
@ -675,7 +675,7 @@ return array(
|
||||||
'phabricator-countdown-css' => '86b7b0a0',
|
'phabricator-countdown-css' => '86b7b0a0',
|
||||||
'phabricator-crumbs-view-css' => '2d9db584',
|
'phabricator-crumbs-view-css' => '2d9db584',
|
||||||
'phabricator-drag-and-drop-file-upload' => 'ae6abfba',
|
'phabricator-drag-and-drop-file-upload' => 'ae6abfba',
|
||||||
'phabricator-draggable-list' => '5fb99faa',
|
'phabricator-draggable-list' => '14824eb5',
|
||||||
'phabricator-dropdown-menu' => '2f6f80f4',
|
'phabricator-dropdown-menu' => '2f6f80f4',
|
||||||
'phabricator-fatal-config-template-css' => '25d446d6',
|
'phabricator-fatal-config-template-css' => '25d446d6',
|
||||||
'phabricator-feed-css' => '4716c86f',
|
'phabricator-feed-css' => '4716c86f',
|
||||||
|
@ -743,7 +743,7 @@ return array(
|
||||||
'phui-info-panel-css' => '27ea50a1',
|
'phui-info-panel-css' => '27ea50a1',
|
||||||
'phui-list-view-css' => '2edb76cf',
|
'phui-list-view-css' => '2edb76cf',
|
||||||
'phui-object-box-css' => '4f916b80',
|
'phui-object-box-css' => '4f916b80',
|
||||||
'phui-object-item-list-view-css' => 'fdd2c06f',
|
'phui-object-item-list-view-css' => 'e8192ada',
|
||||||
'phui-pinboard-view-css' => '53c5fca0',
|
'phui-pinboard-view-css' => '53c5fca0',
|
||||||
'phui-property-list-view-css' => '354465ae',
|
'phui-property-list-view-css' => '354465ae',
|
||||||
'phui-remarkup-preview-css' => '19ad512b',
|
'phui-remarkup-preview-css' => '19ad512b',
|
||||||
|
@ -751,7 +751,7 @@ return array(
|
||||||
'phui-status-list-view-css' => '2f562399',
|
'phui-status-list-view-css' => '2f562399',
|
||||||
'phui-text-css' => '23e9b4b7',
|
'phui-text-css' => '23e9b4b7',
|
||||||
'phui-workboard-view-css' => 'bf70dd2e',
|
'phui-workboard-view-css' => 'bf70dd2e',
|
||||||
'phui-workpanel-view-css' => '26f738ce',
|
'phui-workpanel-view-css' => 'ffb31e99',
|
||||||
'policy-css' => '957ea14c',
|
'policy-css' => '957ea14c',
|
||||||
'policy-edit-css' => '05cca26a',
|
'policy-edit-css' => '05cca26a',
|
||||||
'ponder-comment-table-css' => '6cdccea7',
|
'ponder-comment-table-css' => '6cdccea7',
|
||||||
|
@ -871,6 +871,15 @@ return array(
|
||||||
4 => 'javelin-util',
|
4 => 'javelin-util',
|
||||||
5 => 'phabricator-shaped-request',
|
5 => 'phabricator-shaped-request',
|
||||||
),
|
),
|
||||||
|
'14824eb5' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-install',
|
||||||
|
1 => 'javelin-dom',
|
||||||
|
2 => 'javelin-stratcom',
|
||||||
|
3 => 'javelin-util',
|
||||||
|
4 => 'javelin-vector',
|
||||||
|
5 => 'javelin-magical-init',
|
||||||
|
),
|
||||||
'1693a296' =>
|
'1693a296' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-behavior',
|
0 => 'javelin-behavior',
|
||||||
|
@ -1155,15 +1164,6 @@ return array(
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-install',
|
0 => 'javelin-install',
|
||||||
),
|
),
|
||||||
'5fb99faa' =>
|
|
||||||
array(
|
|
||||||
0 => 'javelin-install',
|
|
||||||
1 => 'javelin-dom',
|
|
||||||
2 => 'javelin-stratcom',
|
|
||||||
3 => 'javelin-util',
|
|
||||||
4 => 'javelin-vector',
|
|
||||||
5 => 'javelin-magical-init',
|
|
||||||
),
|
|
||||||
'61d927ec' =>
|
'61d927ec' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-behavior',
|
0 => 'javelin-behavior',
|
||||||
|
@ -1400,6 +1400,13 @@ return array(
|
||||||
3 => 'javelin-vector',
|
3 => 'javelin-vector',
|
||||||
4 => 'phabricator-hovercard',
|
4 => 'phabricator-hovercard',
|
||||||
),
|
),
|
||||||
|
'9c9f91ec' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-behavior',
|
||||||
|
1 => 'javelin-dom',
|
||||||
|
2 => 'javelin-util',
|
||||||
|
3 => 'phabricator-draggable-list',
|
||||||
|
),
|
||||||
'9db3d160' =>
|
'9db3d160' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-behavior',
|
0 => 'javelin-behavior',
|
||||||
|
@ -1713,13 +1720,6 @@ return array(
|
||||||
1 => 'javelin-dom',
|
1 => 'javelin-dom',
|
||||||
2 => 'javelin-view',
|
2 => 'javelin-view',
|
||||||
),
|
),
|
||||||
'd4cbe3d5' =>
|
|
||||||
array(
|
|
||||||
0 => 'javelin-behavior',
|
|
||||||
1 => 'javelin-dom',
|
|
||||||
2 => 'javelin-util',
|
|
||||||
3 => 'phabricator-draggable-list',
|
|
||||||
),
|
|
||||||
'd6ca6b1c' =>
|
'd6ca6b1c' =>
|
||||||
array(
|
array(
|
||||||
0 => 'javelin-install',
|
0 => 'javelin-install',
|
||||||
|
|
|
@ -84,6 +84,7 @@ final class PhabricatorProjectBoardController
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
->setCards(true)
|
->setCards(true)
|
||||||
->setFlush(true)
|
->setFlush(true)
|
||||||
|
->setAllowEmptyList(true)
|
||||||
->addSigil('project-column');
|
->addSigil('project-column');
|
||||||
$task_phids = idx($task_map, $column->getPHID(), array());
|
$task_phids = idx($task_map, $column->getPHID(), array());
|
||||||
foreach (array_select_keys($tasks, $task_phids) as $task) {
|
foreach (array_select_keys($tasks, $task_phids) as $task) {
|
||||||
|
@ -91,6 +92,10 @@ final class PhabricatorProjectBoardController
|
||||||
}
|
}
|
||||||
$panel->setCards($cards);
|
$panel->setCards($cards);
|
||||||
|
|
||||||
|
if (!$task_phids) {
|
||||||
|
$cards->addClass('project-column-empty');
|
||||||
|
}
|
||||||
|
|
||||||
$board->addPanel($panel);
|
$board->addPanel($panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,17 @@ final class PHUIObjectItemListView extends AphrontTagView {
|
||||||
private $noDataString;
|
private $noDataString;
|
||||||
private $flush;
|
private $flush;
|
||||||
private $plain;
|
private $plain;
|
||||||
|
private $allowEmptyList;
|
||||||
|
|
||||||
|
|
||||||
|
public function setAllowEmptyList($allow_empty_list) {
|
||||||
|
$this->allowEmptyList = $allow_empty_list;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllowEmptyList() {
|
||||||
|
return $this->allowEmptyList;
|
||||||
|
}
|
||||||
|
|
||||||
public function setFlush($flush) {
|
public function setFlush($flush) {
|
||||||
$this->flush = $flush;
|
$this->flush = $flush;
|
||||||
|
@ -92,6 +103,8 @@ final class PHUIObjectItemListView extends AphrontTagView {
|
||||||
|
|
||||||
if ($this->items) {
|
if ($this->items) {
|
||||||
$items = $this->items;
|
$items = $this->items;
|
||||||
|
} else if ($this->allowEmptyList) {
|
||||||
|
$items = null;
|
||||||
} else {
|
} else {
|
||||||
$string = nonempty($this->noDataString, pht('No data.'));
|
$string = nonempty($this->noDataString, pht('No data.'));
|
||||||
$items = id(new AphrontErrorView())
|
$items = id(new AphrontErrorView())
|
||||||
|
|
|
@ -571,8 +571,3 @@
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drag-target-list {
|
|
||||||
/* TODO: This is a work in progress. */
|
|
||||||
background: red;
|
|
||||||
}
|
|
||||||
|
|
|
@ -56,7 +56,16 @@
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.phui-workpanel-body .phui-object-item-list-view {
|
||||||
|
min-height: 54px;
|
||||||
|
}
|
||||||
|
|
||||||
.device .aphront-multi-column-outer
|
.device .aphront-multi-column-outer
|
||||||
div.aphront-multi-column-column-outer .phui-workpanel-body {
|
div.aphront-multi-column-column-outer .phui-workpanel-body {
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.project-column-empty {
|
||||||
|
/* TODO: Use this to put some kind of reasonable null state in the columns? */
|
||||||
|
background: {$red};
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,10 @@ JX.behavior('project-boards', function(config) {
|
||||||
return JX.DOM.scry(col, 'li', 'project-card');
|
return JX.DOM.scry(col, 'li', 'project-card');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onupdate(node) {
|
||||||
|
JX.DOM.alterClass(node, 'project-column-empty', !this.findItems().length);
|
||||||
|
}
|
||||||
|
|
||||||
var lists = [];
|
var lists = [];
|
||||||
var ii;
|
var ii;
|
||||||
var cols = JX.DOM.scry(JX.$(config.boardID), 'ul', 'project-column');
|
var cols = JX.DOM.scry(JX.$(config.boardID), 'ul', 'project-column');
|
||||||
|
@ -19,6 +23,10 @@ JX.behavior('project-boards', function(config) {
|
||||||
for (ii = 0; ii < cols.length; ii++) {
|
for (ii = 0; ii < cols.length; ii++) {
|
||||||
var list = new JX.DraggableList('project-card', cols[ii])
|
var list = new JX.DraggableList('project-card', cols[ii])
|
||||||
.setFindItemsHandler(JX.bind(null, finditems, cols[ii]));
|
.setFindItemsHandler(JX.bind(null, finditems, cols[ii]));
|
||||||
|
|
||||||
|
list.listen('didSend', JX.bind(list, onupdate, cols[ii]));
|
||||||
|
list.listen('didReceive', JX.bind(list, onupdate, cols[ii]));
|
||||||
|
|
||||||
lists.push(list);
|
lists.push(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,9 @@ JX.install('DraggableList', {
|
||||||
'didBeginDrag',
|
'didBeginDrag',
|
||||||
'didCancelDrag',
|
'didCancelDrag',
|
||||||
'didEndDrag',
|
'didEndDrag',
|
||||||
'didDrop'],
|
'didDrop',
|
||||||
|
'didSend',
|
||||||
|
'didReceive'],
|
||||||
|
|
||||||
properties : {
|
properties : {
|
||||||
findItemsHandler : null
|
findItemsHandler : null
|
||||||
|
@ -378,18 +380,28 @@ JX.install('DraggableList', {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var target = this._target;
|
var p = JX.$V(e);
|
||||||
var dragging = this._dragging;
|
|
||||||
var ghost = this.getGhostNode();
|
|
||||||
|
|
||||||
|
var dragging = this._dragging;
|
||||||
this._dragging = null;
|
this._dragging = null;
|
||||||
|
|
||||||
|
var target = false;
|
||||||
|
var ghost = false;
|
||||||
|
|
||||||
|
var target_list = this._getTargetList(p);
|
||||||
|
if (target_list) {
|
||||||
|
target = target_list._target;
|
||||||
|
ghost = target_list.getGhostNode();
|
||||||
|
}
|
||||||
|
|
||||||
JX.$V(0, 0).setPos(dragging);
|
JX.$V(0, 0).setPos(dragging);
|
||||||
|
|
||||||
if (target !== false) {
|
if (target !== false) {
|
||||||
JX.DOM.remove(dragging);
|
JX.DOM.remove(dragging);
|
||||||
JX.DOM.replace(ghost, dragging);
|
JX.DOM.replace(ghost, dragging);
|
||||||
this.invoke('didDrop', dragging, target);
|
this.invoke('didSend', dragging, target_list);
|
||||||
|
target_list.invoke('didReceive', dragging, this);
|
||||||
|
target_list.invoke('didDrop', dragging, target, this);
|
||||||
} else {
|
} else {
|
||||||
this.invoke('didCancelDrag', dragging);
|
this.invoke('didCancelDrag', dragging);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue