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:
@@ -7,7 +7,7 @@
|
||||
return array(
|
||||
'names' =>
|
||||
array(
|
||||
'core.pkg.css' => 'ac7deb21',
|
||||
'core.pkg.css' => 'dddca4dc',
|
||||
'core.pkg.js' => 'c907bd96',
|
||||
'darkconsole.pkg.js' => 'ca8671ce',
|
||||
'differential.pkg.css' => '827749c1',
|
||||
@@ -137,7 +137,7 @@ return array(
|
||||
'rsrc/css/phui/phui-info-panel.css' => '27ea50a1',
|
||||
'rsrc/css/phui/phui-list.css' => '2edb76cf',
|
||||
'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-property-list-view.css' => '354465ae',
|
||||
'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-text.css' => '23e9b4b7',
|
||||
'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-apps-large.css' => 'e37c2ff1',
|
||||
'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-rule-editor.js' => '263aeb8c',
|
||||
'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/releeph/releeph-preview-branch.js' => '9eb2cedb',
|
||||
'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/core/Busy.js' => '6453c869',
|
||||
'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/DropdownMenuItem.js' => '0f386ef4',
|
||||
'rsrc/js/core/FileUpload.js' => '96713558',
|
||||
@@ -603,7 +603,7 @@ return array(
|
||||
'javelin-behavior-policy-control' => 'c01153ea',
|
||||
'javelin-behavior-policy-rule-editor' => '263aeb8c',
|
||||
'javelin-behavior-ponder-votebox' => '327dbe61',
|
||||
'javelin-behavior-project-boards' => 'd4cbe3d5',
|
||||
'javelin-behavior-project-boards' => '9c9f91ec',
|
||||
'javelin-behavior-project-create' => '065227cc',
|
||||
'javelin-behavior-refresh-csrf' => 'c4b31646',
|
||||
'javelin-behavior-releeph-preview-branch' => '9eb2cedb',
|
||||
@@ -675,7 +675,7 @@ return array(
|
||||
'phabricator-countdown-css' => '86b7b0a0',
|
||||
'phabricator-crumbs-view-css' => '2d9db584',
|
||||
'phabricator-drag-and-drop-file-upload' => 'ae6abfba',
|
||||
'phabricator-draggable-list' => '5fb99faa',
|
||||
'phabricator-draggable-list' => '14824eb5',
|
||||
'phabricator-dropdown-menu' => '2f6f80f4',
|
||||
'phabricator-fatal-config-template-css' => '25d446d6',
|
||||
'phabricator-feed-css' => '4716c86f',
|
||||
@@ -743,7 +743,7 @@ return array(
|
||||
'phui-info-panel-css' => '27ea50a1',
|
||||
'phui-list-view-css' => '2edb76cf',
|
||||
'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-property-list-view-css' => '354465ae',
|
||||
'phui-remarkup-preview-css' => '19ad512b',
|
||||
@@ -751,7 +751,7 @@ return array(
|
||||
'phui-status-list-view-css' => '2f562399',
|
||||
'phui-text-css' => '23e9b4b7',
|
||||
'phui-workboard-view-css' => 'bf70dd2e',
|
||||
'phui-workpanel-view-css' => '26f738ce',
|
||||
'phui-workpanel-view-css' => 'ffb31e99',
|
||||
'policy-css' => '957ea14c',
|
||||
'policy-edit-css' => '05cca26a',
|
||||
'ponder-comment-table-css' => '6cdccea7',
|
||||
@@ -871,6 +871,15 @@ return array(
|
||||
4 => 'javelin-util',
|
||||
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' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
@@ -1155,15 +1164,6 @@ return array(
|
||||
array(
|
||||
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' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
@@ -1400,6 +1400,13 @@ return array(
|
||||
3 => 'javelin-vector',
|
||||
4 => 'phabricator-hovercard',
|
||||
),
|
||||
'9c9f91ec' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-dom',
|
||||
2 => 'javelin-util',
|
||||
3 => 'phabricator-draggable-list',
|
||||
),
|
||||
'9db3d160' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
@@ -1713,13 +1720,6 @@ return array(
|
||||
1 => 'javelin-dom',
|
||||
2 => 'javelin-view',
|
||||
),
|
||||
'd4cbe3d5' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-dom',
|
||||
2 => 'javelin-util',
|
||||
3 => 'phabricator-draggable-list',
|
||||
),
|
||||
'd6ca6b1c' =>
|
||||
array(
|
||||
0 => 'javelin-install',
|
||||
|
||||
@@ -84,6 +84,7 @@ final class PhabricatorProjectBoardController
|
||||
->setUser($viewer)
|
||||
->setCards(true)
|
||||
->setFlush(true)
|
||||
->setAllowEmptyList(true)
|
||||
->addSigil('project-column');
|
||||
$task_phids = idx($task_map, $column->getPHID(), array());
|
||||
foreach (array_select_keys($tasks, $task_phids) as $task) {
|
||||
@@ -91,6 +92,10 @@ final class PhabricatorProjectBoardController
|
||||
}
|
||||
$panel->setCards($cards);
|
||||
|
||||
if (!$task_phids) {
|
||||
$cards->addClass('project-column-empty');
|
||||
}
|
||||
|
||||
$board->addPanel($panel);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,17 @@ final class PHUIObjectItemListView extends AphrontTagView {
|
||||
private $noDataString;
|
||||
private $flush;
|
||||
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) {
|
||||
$this->flush = $flush;
|
||||
@@ -92,6 +103,8 @@ final class PHUIObjectItemListView extends AphrontTagView {
|
||||
|
||||
if ($this->items) {
|
||||
$items = $this->items;
|
||||
} else if ($this->allowEmptyList) {
|
||||
$items = null;
|
||||
} else {
|
||||
$string = nonempty($this->noDataString, pht('No data.'));
|
||||
$items = id(new AphrontErrorView())
|
||||
|
||||
@@ -571,8 +571,3 @@
|
||||
padding-left: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.drag-target-list {
|
||||
/* TODO: This is a work in progress. */
|
||||
background: red;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,16 @@
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.phui-workpanel-body .phui-object-item-list-view {
|
||||
min-height: 54px;
|
||||
}
|
||||
|
||||
.device .aphront-multi-column-outer
|
||||
div.aphront-multi-column-column-outer .phui-workpanel-body {
|
||||
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');
|
||||
}
|
||||
|
||||
function onupdate(node) {
|
||||
JX.DOM.alterClass(node, 'project-column-empty', !this.findItems().length);
|
||||
}
|
||||
|
||||
var lists = [];
|
||||
var ii;
|
||||
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++) {
|
||||
var list = new JX.DraggableList('project-card', 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ JX.install('DraggableList', {
|
||||
'didBeginDrag',
|
||||
'didCancelDrag',
|
||||
'didEndDrag',
|
||||
'didDrop'],
|
||||
'didDrop',
|
||||
'didSend',
|
||||
'didReceive'],
|
||||
|
||||
properties : {
|
||||
findItemsHandler : null
|
||||
@@ -378,18 +380,28 @@ JX.install('DraggableList', {
|
||||
return;
|
||||
}
|
||||
|
||||
var target = this._target;
|
||||
var dragging = this._dragging;
|
||||
var ghost = this.getGhostNode();
|
||||
var p = JX.$V(e);
|
||||
|
||||
var dragging = this._dragging;
|
||||
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);
|
||||
|
||||
if (target !== false) {
|
||||
JX.DOM.remove(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 {
|
||||
this.invoke('didCancelDrag', dragging);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user