Page MenuHomePhabricator

D20247.id.diff
No OneTemporary

D20247.id.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -178,7 +178,7 @@
'rsrc/css/phui/workboards/phui-workboard-color.css' => 'e86de308',
'rsrc/css/phui/workboards/phui-workboard.css' => '74fc9d98',
'rsrc/css/phui/workboards/phui-workcard.css' => '8c536f90',
- 'rsrc/css/phui/workboards/phui-workpanel.css' => '7e12d43c',
+ 'rsrc/css/phui/workboards/phui-workpanel.css' => 'bc16cf33',
'rsrc/css/sprite-login.css' => '18b368a6',
'rsrc/css/sprite-tokens.css' => 'f1896dc5',
'rsrc/css/syntax/syntax-default.css' => '055fc231',
@@ -409,11 +409,13 @@
'rsrc/js/application/phortune/phortune-credit-card-form.js' => 'd12d214f',
'rsrc/js/application/policy/behavior-policy-control.js' => '0eaa33a9',
'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '9347f172',
- 'rsrc/js/application/projects/WorkboardBoard.js' => 'fd96a6e8',
- 'rsrc/js/application/projects/WorkboardCard.js' => '9a513421',
- 'rsrc/js/application/projects/WorkboardColumn.js' => '1f71e559',
+ 'rsrc/js/application/projects/WorkboardBoard.js' => 'e4e2d107',
+ 'rsrc/js/application/projects/WorkboardCard.js' => 'c23ddfde',
+ 'rsrc/js/application/projects/WorkboardColumn.js' => 'fd9cb972',
'rsrc/js/application/projects/WorkboardController.js' => '42c7a5a7',
- 'rsrc/js/application/projects/behavior-project-boards.js' => '05c74d65',
+ 'rsrc/js/application/projects/WorkboardHeader.js' => '354c5c0e',
+ 'rsrc/js/application/projects/WorkboardHeaderTemplate.js' => '9b86cd0d',
+ 'rsrc/js/application/projects/behavior-project-boards.js' => 'a3f6b67f',
'rsrc/js/application/projects/behavior-project-create.js' => '34c53422',
'rsrc/js/application/projects/behavior-reorder-columns.js' => '8ac32fd9',
'rsrc/js/application/releeph/releeph-preview-branch.js' => '75184d68',
@@ -655,7 +657,7 @@
'javelin-behavior-phuix-example' => 'c2c500a7',
'javelin-behavior-policy-control' => '0eaa33a9',
'javelin-behavior-policy-rule-editor' => '9347f172',
- 'javelin-behavior-project-boards' => '05c74d65',
+ 'javelin-behavior-project-boards' => 'a3f6b67f',
'javelin-behavior-project-create' => '34c53422',
'javelin-behavior-quicksand-blacklist' => '5a6f6a06',
'javelin-behavior-read-only-warning' => 'b9109f8f',
@@ -727,10 +729,12 @@
'javelin-view-renderer' => '9aae2b66',
'javelin-view-visitor' => '308f9fe4',
'javelin-websocket' => 'fdc13e4e',
- 'javelin-workboard-board' => 'fd96a6e8',
- 'javelin-workboard-card' => '9a513421',
- 'javelin-workboard-column' => '1f71e559',
+ 'javelin-workboard-board' => 'e4e2d107',
+ 'javelin-workboard-card' => 'c23ddfde',
+ 'javelin-workboard-column' => 'fd9cb972',
'javelin-workboard-controller' => '42c7a5a7',
+ 'javelin-workboard-header' => '354c5c0e',
+ 'javelin-workboard-header-template' => '9b86cd0d',
'javelin-workflow' => '958e9045',
'maniphest-report-css' => '3d53188b',
'maniphest-task-edit-css' => '272daa84',
@@ -854,7 +858,7 @@
'phui-workboard-color-css' => 'e86de308',
'phui-workboard-view-css' => '74fc9d98',
'phui-workcard-view-css' => '8c536f90',
- 'phui-workpanel-view-css' => '7e12d43c',
+ 'phui-workpanel-view-css' => 'bc16cf33',
'phuix-action-list-view' => 'c68f183f',
'phuix-action-view' => 'aaa08f3b',
'phuix-autocomplete' => '8f139ef0',
@@ -915,15 +919,6 @@
'javelin-dom',
'javelin-workflow',
),
- '05c74d65' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-util',
- 'javelin-vector',
- 'javelin-stratcom',
- 'javelin-workflow',
- 'javelin-workboard-controller',
- ),
'05d290ef' => array(
'javelin-install',
'javelin-util',
@@ -1034,10 +1029,6 @@
'javelin-behavior',
'javelin-dom',
),
- '1f71e559' => array(
- 'javelin-install',
- 'javelin-workboard-card',
- ),
'1ff278aa' => array(
'phui-button-css',
),
@@ -1172,6 +1163,9 @@
'javelin-stratcom',
'javelin-workflow',
),
+ '354c5c0e' => array(
+ 'javelin-install',
+ ),
'37b8a04a' => array(
'javelin-install',
'javelin-util',
@@ -1535,9 +1529,6 @@
'javelin-install',
'javelin-dom',
),
- '7e12d43c' => array(
- 'phui-workcard-view-css',
- ),
'80bff3af' => array(
'javelin-install',
'javelin-typeahead-source',
@@ -1701,9 +1692,6 @@
'javelin-dom',
'javelin-router',
),
- '9a513421' => array(
- 'javelin-install',
- ),
'9aae2b66' => array(
'javelin-install',
'javelin-util',
@@ -1713,6 +1701,9 @@
'javelin-dom',
'javelin-stratcom',
),
+ '9b86cd0d' => array(
+ 'javelin-install',
+ ),
'9cec214e' => array(
'javelin-behavior',
'javelin-stratcom',
@@ -1737,6 +1728,15 @@
'a241536a' => array(
'javelin-install',
),
+ 'a3f6b67f' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-util',
+ 'javelin-vector',
+ 'javelin-stratcom',
+ 'javelin-workflow',
+ 'javelin-workboard-controller',
+ ),
'a4356cde' => array(
'javelin-install',
'javelin-dom',
@@ -1887,6 +1887,9 @@
'javelin-uri',
'phabricator-notification',
),
+ 'bc16cf33' => array(
+ 'phui-workcard-view-css',
+ ),
'bdce4d78' => array(
'javelin-install',
'javelin-util',
@@ -1903,6 +1906,9 @@
'javelin-stratcom',
'javelin-uri',
),
+ 'c23ddfde' => array(
+ 'javelin-install',
+ ),
'c2c500a7' => array(
'javelin-install',
'javelin-dom',
@@ -2019,6 +2025,16 @@
'javelin-dom',
'javelin-history',
),
+ 'e4e2d107' => array(
+ 'javelin-install',
+ 'javelin-dom',
+ 'javelin-util',
+ 'javelin-stratcom',
+ 'javelin-workflow',
+ 'phabricator-draggable-list',
+ 'javelin-workboard-column',
+ 'javelin-workboard-header-template',
+ ),
'e562708c' => array(
'javelin-install',
),
@@ -2120,14 +2136,10 @@
'javelin-magical-init',
'javelin-util',
),
- 'fd96a6e8' => array(
+ 'fd9cb972' => array(
'javelin-install',
- 'javelin-dom',
- 'javelin-util',
- 'javelin-stratcom',
- 'javelin-workflow',
- 'phabricator-draggable-list',
- 'javelin-workboard-column',
+ 'javelin-workboard-card',
+ 'javelin-workboard-header',
),
'fdc13e4e' => array(
'javelin-install',
diff --git a/src/applications/maniphest/storage/ManiphestTask.php b/src/applications/maniphest/storage/ManiphestTask.php
--- a/src/applications/maniphest/storage/ManiphestTask.php
+++ b/src/applications/maniphest/storage/ManiphestTask.php
@@ -306,6 +306,7 @@
return array(
'status' => $this->getStatus(),
'points' => (double)$this->getPoints(),
+ 'priority' => $this->getPriority(),
);
}
diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php
--- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php
+++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php
@@ -621,6 +621,45 @@
$board->addPanel($panel);
}
+ // It's possible for tasks to have an invalid/unknown priority in the
+ // database. We still want to generate a header for these tasks so we
+ // don't break the workboard.
+ $priorities =
+ ManiphestTaskPriority::getTaskPriorityMap() +
+ mpull($all_tasks, null, 'getPriority');
+ $priorities = array_keys($priorities);
+
+ $headers = array();
+ foreach ($priorities as $priority) {
+ $header_key = sprintf('priority(%s)', $priority);
+
+ $priority_name = ManiphestTaskPriority::getTaskPriorityName($priority);
+ $priority_color = ManiphestTaskPriority::getTaskPriorityColor($priority);
+ $priority_icon = ManiphestTaskPriority::getTaskPriorityIcon($priority);
+
+ $icon_view = id(new PHUIIconView())
+ ->setIcon("{$priority_icon} {$priority_color}");
+
+ $template = phutil_tag(
+ 'li',
+ array(
+ 'class' => 'workboard-group-header',
+ ),
+ array(
+ $icon_view,
+ $priority_name,
+ ));
+
+ $headers[] = array(
+ 'order' => 'priority',
+ 'key' => $header_key,
+ 'template' => hsprintf('%s', $template),
+ 'vector' => array(
+ (int)-$priority,
+ ),
+ );
+ }
+
$behavior_config = array(
'moveURI' => $this->getApplicationURI('move/'.$project->getID().'/'),
'uploadURI' => '/file/dropupload/',
@@ -630,6 +669,7 @@
'boardPHID' => $project->getPHID(),
'order' => $this->sortKey,
+ 'headers' => $headers,
'templateMap' => $templates,
'columnMaps' => $column_maps,
'orderMaps' => mpull($all_tasks, 'getWorkboardOrderVectors'),
diff --git a/webroot/rsrc/css/phui/workboards/phui-workpanel.css b/webroot/rsrc/css/phui/workboards/phui-workpanel.css
--- a/webroot/rsrc/css/phui/workboards/phui-workpanel.css
+++ b/webroot/rsrc/css/phui/workboards/phui-workpanel.css
@@ -145,3 +145,16 @@
.phui-workpanel-view.workboard-column-drop-target .phui-box-grey {
border-color: {$lightblueborder};
}
+
+.workboard-group-header {
+ background: rgba({$alphablue}, 0.10);
+ padding: 4px 8px;
+ margin: 0 0 8px -8px;
+ border-bottom: 1px solid {$lightgreyborder};
+ font-weight: bold;
+ color: {$darkgreytext};
+}
+
+.workboard-group-header .phui-icon-view {
+ margin-right: 8px;
+}
diff --git a/webroot/rsrc/js/application/projects/WorkboardBoard.js b/webroot/rsrc/js/application/projects/WorkboardBoard.js
--- a/webroot/rsrc/js/application/projects/WorkboardBoard.js
+++ b/webroot/rsrc/js/application/projects/WorkboardBoard.js
@@ -7,6 +7,7 @@
* javelin-workflow
* phabricator-draggable-list
* javelin-workboard-column
+ * javelin-workboard-header-template
* @javelin
*/
@@ -20,6 +21,7 @@
this._templates = {};
this._orderMaps = {};
this._propertiesMap = {};
+ this._headers = {};
this._buildColumns();
},
@@ -36,6 +38,7 @@
_templates: null,
_orderMaps: null,
_propertiesMap: null,
+ _headers: null,
getRoot: function() {
return this._root;
@@ -58,6 +61,36 @@
return this;
},
+ getHeaderTemplate: function(header_key) {
+ if (!this._headers[header_key]) {
+ this._headers[header_key] = new JX.WorkboardHeaderTemplate(header_key);
+ }
+
+ return this._headers[header_key];
+ },
+
+ getHeaderTemplatesForOrder: function(order) {
+ var templates = [];
+
+ for (var k in this._headers) {
+ var header = this._headers[k];
+
+ if (header.getOrder() !== order) {
+ continue;
+ }
+
+ templates.push(header);
+ }
+
+ templates.sort(JX.bind(this, this._sortHeaderTemplates));
+
+ return templates;
+ },
+
+ _sortHeaderTemplates: function(u, v) {
+ return this.compareVectors(u.getVector(), v.getVector());
+ },
+
setObjectProperties: function(phid, properties) {
this._propertiesMap[phid] = properties;
return this;
@@ -84,6 +117,20 @@
return this._orderMaps[phid][key];
},
+ compareVectors: function(u_vec, v_vec) {
+ for (var ii = 0; ii < u_vec.length; ii++) {
+ if (u_vec[ii] > v_vec[ii]) {
+ return 1;
+ }
+
+ if (u_vec[ii] < v_vec[ii]) {
+ return -1;
+ }
+ }
+
+ return 0;
+ },
+
start: function() {
this._setupDragHandlers();
diff --git a/webroot/rsrc/js/application/projects/WorkboardCard.js b/webroot/rsrc/js/application/projects/WorkboardCard.js
--- a/webroot/rsrc/js/application/projects/WorkboardCard.js
+++ b/webroot/rsrc/js/application/projects/WorkboardCard.js
@@ -40,6 +40,10 @@
return this.getProperties().status;
},
+ getPriority: function(order) {
+ return this.getProperties().priority;
+ },
+
getNode: function() {
if (!this._root) {
var phid = this.getPHID();
diff --git a/webroot/rsrc/js/application/projects/WorkboardColumn.js b/webroot/rsrc/js/application/projects/WorkboardColumn.js
--- a/webroot/rsrc/js/application/projects/WorkboardColumn.js
+++ b/webroot/rsrc/js/application/projects/WorkboardColumn.js
@@ -2,6 +2,7 @@
* @provides javelin-workboard-column
* @requires javelin-install
* javelin-workboard-card
+ * javelin-workboard-header
* @javelin
*/
@@ -21,6 +22,8 @@
'column-points-content');
this._cards = {};
+ this._headers = {};
+ this._objects = [];
this._naturalOrder = [];
},
@@ -29,11 +32,13 @@
_root: null,
_board: null,
_cards: null,
+ _headers: null,
_naturalOrder: null,
_panel: null,
_pointsNode: null,
_pointsContentNode: null,
_dirty: true,
+ _objects: null,
getPHID: function() {
return this._phid;
@@ -148,24 +153,85 @@
return this._dirty;
},
+ getHeader: function(key) {
+ if (!this._headers[key]) {
+ this._headers[key] = new JX.WorkboardHeader(this, key);
+ }
+ return this._headers[key];
+ },
+
+ _getCardHeaderKey: function(card, order) {
+ switch (order) {
+ case 'priority':
+ return 'priority(' + card.getPriority() + ')';
+ default:
+ return null;
+ }
+ },
+
redraw: function() {
var board = this.getBoard();
var order = board.getOrder();
var list;
+ var has_headers;
if (order == 'natural') {
list = this._getCardsSortedNaturally();
+ has_headers = false;
} else {
list = this._getCardsSortedByKey(order);
+ has_headers = true;
}
- var content = [];
- for (var ii = 0; ii < list.length; ii++) {
+ var ii;
+ var objects = [];
+
+ var header_keys = [];
+ var seen_headers = {};
+ if (has_headers) {
+ var header_templates = board.getHeaderTemplatesForOrder(order);
+ for (var k in header_templates) {
+ header_keys.push(header_templates[k].getHeaderKey());
+ }
+ header_keys.reverse();
+ }
+
+ for (ii = 0; ii < list.length; ii++) {
var card = list[ii];
- var node = card.getNode();
- content.push(node);
+ // If a column has a "High" priority card and a "Low" priority card,
+ // we need to add the "Normal" header in between them. This allows
+ // you to change priority to "Normal" even if there are no "Normal"
+ // cards in a column.
+
+ if (has_headers) {
+ var header_key = this._getCardHeaderKey(card, order);
+ if (!seen_headers[header_key]) {
+ while (header_keys.length) {
+ var next = header_keys.pop();
+
+ var header = this.getHeader(next);
+ objects.push(header);
+ seen_headers[header_key] = true;
+
+ if (next === header_key) {
+ break;
+ }
+ }
+ }
+ }
+ objects.push(card);
+ }
+
+ this._objects = objects;
+
+ var content = [];
+ for (ii = 0; ii < this._objects.length; ii++) {
+ var object = this._objects[ii];
+
+ var node = object.getNode();
+ content.push(node);
}
JX.DOM.setContent(this.getRoot(), content);
@@ -182,10 +248,10 @@
var src_phid = JX.Stratcom.getData(src_node).objectPHID;
var dst_phid = JX.Stratcom.getData(dst_node).objectPHID;
- var u_vec = this.getBoard().getOrderVector(src_phid, order);
- var v_vec = this.getBoard().getOrderVector(dst_phid, order);
+ var u_vec = board.getOrderVector(src_phid, order);
+ var v_vec = board.getOrderVector(dst_phid, order);
- return this._compareVectors(u_vec, v_vec);
+ return board.compareVectors(u_vec, v_vec);
},
setIsDropTarget: function(is_target) {
@@ -218,24 +284,11 @@
},
_sortCards: function(order, u, v) {
- var u_vec = this.getBoard().getOrderVector(u.getPHID(), order);
- var v_vec = this.getBoard().getOrderVector(v.getPHID(), order);
-
- return this._compareVectors(u_vec, v_vec);
- },
-
- _compareVectors: function(u_vec, v_vec) {
- for (var ii = 0; ii < u_vec.length; ii++) {
- if (u_vec[ii] > v_vec[ii]) {
- return 1;
- }
-
- if (u_vec[ii] < v_vec[ii]) {
- return -1;
- }
- }
+ var board = this.getBoard();
+ var u_vec = board.getOrderVector(u.getPHID(), order);
+ var v_vec = board.getOrderVector(v.getPHID(), order);
- return 0;
+ return board.compareVectors(u_vec, v_vec);
},
_redrawFrame: function() {
diff --git a/webroot/rsrc/js/application/projects/WorkboardHeader.js b/webroot/rsrc/js/application/projects/WorkboardHeader.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/application/projects/WorkboardHeader.js
@@ -0,0 +1,38 @@
+/**
+ * @provides javelin-workboard-header
+ * @requires javelin-install
+ * @javelin
+ */
+
+JX.install('WorkboardHeader', {
+
+ construct: function(column, header_key) {
+ this._column = column;
+ this._headerKey = header_key;
+ },
+
+ members: {
+ _root: null,
+ _column: null,
+ _headerKey: null,
+
+ getColumn: function() {
+ return this._column;
+ },
+
+ getHeaderKey: function() {
+ return this._headerKey;
+ },
+
+ getNode: function() {
+ if (!this._root) {
+ var header_key = this.getHeaderKey();
+ var board = this.getColumn().getBoard();
+ var template = board.getHeaderTemplate(header_key).getTemplate();
+ this._root = JX.$H(template).getFragment().firstChild;
+ }
+ return this._root;
+ }
+ }
+
+});
diff --git a/webroot/rsrc/js/application/projects/WorkboardHeaderTemplate.js b/webroot/rsrc/js/application/projects/WorkboardHeaderTemplate.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/application/projects/WorkboardHeaderTemplate.js
@@ -0,0 +1,28 @@
+/**
+ * @provides javelin-workboard-header-template
+ * @requires javelin-install
+ * @javelin
+ */
+
+JX.install('WorkboardHeaderTemplate', {
+
+ construct: function(header_key) {
+ this._headerKey = header_key;
+ },
+
+ properties: {
+ template: null,
+ order: null,
+ vector: null
+ },
+
+ members: {
+ _headerKey: null,
+
+ getHeaderKey: function() {
+ return this._headerKey;
+ }
+
+ }
+
+});
diff --git a/webroot/rsrc/js/application/projects/behavior-project-boards.js b/webroot/rsrc/js/application/projects/behavior-project-boards.js
--- a/webroot/rsrc/js/application/projects/behavior-project-boards.js
+++ b/webroot/rsrc/js/application/projects/behavior-project-boards.js
@@ -105,6 +105,16 @@
board.setObjectProperties(property_phid, property_maps[property_phid]);
}
+ var headers = config.headers;
+ for (var jj = 0; jj < headers.length; jj++) {
+ var header = headers[jj];
+
+ board.getHeaderTemplate(header.key)
+ .setOrder(header.order)
+ .setTemplate(header.template)
+ .setVector(header.vector);
+ }
+
board.start();
});

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 31, 5:26 PM (4 h, 41 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7079251
Default Alt Text
D20247.id.diff (19 KB)

Event Timeline