Page MenuHomePhabricator

D15237.id36779.diff
No OneTemporary

D15237.id36779.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -415,11 +415,11 @@
'rsrc/js/application/phortune/phortune-credit-card-form.js' => '2290aeef',
'rsrc/js/application/policy/behavior-policy-control.js' => 'd0c516d5',
'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '5e9f347c',
- 'rsrc/js/application/projects/WorkboardBoard.js' => '069d6dd3',
- 'rsrc/js/application/projects/WorkboardCard.js' => '2fcefa17',
- 'rsrc/js/application/projects/WorkboardColumn.js' => 'e8f303bb',
+ 'rsrc/js/application/projects/WorkboardBoard.js' => '52291776',
+ 'rsrc/js/application/projects/WorkboardCard.js' => 'c587b80f',
+ 'rsrc/js/application/projects/WorkboardColumn.js' => 'f05d6e5d',
'rsrc/js/application/projects/WorkboardController.js' => 'fa1378c3',
- 'rsrc/js/application/projects/behavior-project-boards.js' => 'e1b56d72',
+ 'rsrc/js/application/projects/behavior-project-boards.js' => '14a1faae',
'rsrc/js/application/projects/behavior-project-create.js' => '065227cc',
'rsrc/js/application/projects/behavior-reorder-columns.js' => 'e1d25dfb',
'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf',
@@ -659,7 +659,7 @@
'javelin-behavior-phui-profile-menu' => '12884df9',
'javelin-behavior-policy-control' => 'd0c516d5',
'javelin-behavior-policy-rule-editor' => '5e9f347c',
- 'javelin-behavior-project-boards' => 'e1b56d72',
+ 'javelin-behavior-project-boards' => '14a1faae',
'javelin-behavior-project-create' => '065227cc',
'javelin-behavior-quicksand-blacklist' => '7927a7d3',
'javelin-behavior-recurring-edit' => '5f1c4d5f',
@@ -726,9 +726,9 @@
'javelin-view-renderer' => '6c2b09a2',
'javelin-view-visitor' => 'efe49472',
'javelin-websocket' => 'e292eaf4',
- 'javelin-workboard-board' => '069d6dd3',
- 'javelin-workboard-card' => '2fcefa17',
- 'javelin-workboard-column' => 'e8f303bb',
+ 'javelin-workboard-board' => '52291776',
+ 'javelin-workboard-card' => 'c587b80f',
+ 'javelin-workboard-column' => 'f05d6e5d',
'javelin-workboard-controller' => 'fa1378c3',
'javelin-workflow' => '5b2e3e2b',
'lightbox-attachment-css' => '7acac05d',
@@ -919,15 +919,6 @@
'javelin-stratcom',
'javelin-workflow',
),
- '069d6dd3' => array(
- 'javelin-install',
- 'javelin-dom',
- 'javelin-util',
- 'javelin-stratcom',
- 'javelin-workflow',
- 'phabricator-draggable-list',
- 'javelin-workboard-column',
- ),
'06c32383' => array(
'javelin-behavior',
'javelin-typeahead-ondemand-source',
@@ -975,6 +966,15 @@
'javelin-dom',
'javelin-history',
),
+ '14a1faae' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-util',
+ 'javelin-vector',
+ 'javelin-stratcom',
+ 'javelin-workflow',
+ 'javelin-workboard-controller',
+ ),
'1ad0a787' => array(
'javelin-install',
'javelin-reactor',
@@ -1082,9 +1082,6 @@
'2ee659ce' => array(
'javelin-install',
),
- '2fcefa17' => array(
- 'javelin-install',
- ),
'327a00d1' => array(
'javelin-behavior',
'javelin-stratcom',
@@ -1217,6 +1214,15 @@
'javelin-dom',
'javelin-reactor-dom',
),
+ 52291776 => array(
+ 'javelin-install',
+ 'javelin-dom',
+ 'javelin-util',
+ 'javelin-stratcom',
+ 'javelin-workflow',
+ 'phabricator-draggable-list',
+ 'javelin-workboard-column',
+ ),
'5359e785' => array(
'javelin-install',
'javelin-util',
@@ -1802,6 +1808,9 @@
'javelin-dom',
'javelin-vector',
),
+ 'c587b80f' => array(
+ 'javelin-install',
+ ),
'c72aa091' => array(
'javelin-behavior',
'javelin-dom',
@@ -1934,15 +1943,6 @@
'javelin-dom',
'phabricator-prefab',
),
- 'e1b56d72' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-util',
- 'javelin-vector',
- 'javelin-stratcom',
- 'javelin-workflow',
- 'javelin-workboard-controller',
- ),
'e1d25dfb' => array(
'javelin-behavior',
'javelin-stratcom',
@@ -2010,10 +2010,6 @@
'e6e25838' => array(
'javelin-install',
),
- 'e8f303bb' => array(
- 'javelin-install',
- 'javelin-workboard-card',
- ),
'e9581f08' => array(
'javelin-behavior',
'javelin-stratcom',
@@ -2049,6 +2045,10 @@
'javelin-workflow',
'javelin-json',
),
+ 'f05d6e5d' => array(
+ 'javelin-install',
+ 'javelin-workboard-card',
+ ),
'f411b6ae' => array(
'javelin-behavior',
'javelin-stratcom',
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
@@ -221,6 +221,13 @@
);
}
+ public function getWorkboardProperties() {
+ return array(
+ 'status' => $this->getStatus(),
+ 'points' => (double)$this->getPoints(),
+ );
+ }
+
/* -( PhabricatorSubscribableInterface )----------------------------------- */
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
@@ -318,14 +318,17 @@
$column_menu = $this->buildColumnMenu($project, $column);
$panel->addHeaderAction($column_menu);
- $tag_id = celerity_generate_unique_node_id();
- $tag_content_id = celerity_generate_unique_node_id();
-
$count_tag = id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE)
->setShade(PHUITagView::COLOR_BLUE)
- ->setID($tag_id)
- ->setName(phutil_tag('span', array('id' => $tag_content_id), '-'))
+ ->addSigil('column-points')
+ ->setName(
+ javelin_tag(
+ 'span',
+ array(
+ 'sigil' => 'column-points-content',
+ ),
+ pht('-')))
->setStyle('display: none');
$panel->setHeaderTag($count_tag);
@@ -339,8 +342,6 @@
->setMetadata(
array(
'columnPHID' => $column->getPHID(),
- 'countTagID' => $tag_id,
- 'countTagContentID' => $tag_content_id,
'pointLimit' => $column->getPointLimit(),
));
@@ -359,17 +360,22 @@
}
$behavior_config = array(
- 'boardID' => $board_id,
- 'projectPHID' => $project->getPHID(),
'moveURI' => $this->getApplicationURI('move/'.$project->getID().'/'),
'createURI' => $this->getCreateURI(),
'uploadURI' => '/file/dropupload/',
'coverURI' => $this->getApplicationURI('cover/'),
'chunkThreshold' => PhabricatorFileStorageEngine::getChunkThreshold(),
+ 'pointsEnabled' => ManiphestTaskPoints::getIsEnabled(),
+
+ 'boardPHID' => $project->getPHID(),
'order' => $this->sortKey,
'templateMap' => $templates,
'columnMaps' => $column_maps,
'orderMaps' => mpull($all_tasks, 'getWorkboardOrderVectors'),
+ 'propertyMaps' => mpull($all_tasks, 'getWorkboardProperties'),
+
+ 'boardID' => $board_id,
+ 'projectPHID' => $project->getPHID(),
);
$this->initBehavior('project-boards', $behavior_config);
diff --git a/src/applications/project/engine/PhabricatorBoardResponseEngine.php b/src/applications/project/engine/PhabricatorBoardResponseEngine.php
--- a/src/applications/project/engine/PhabricatorBoardResponseEngine.php
+++ b/src/applications/project/engine/PhabricatorBoardResponseEngine.php
@@ -80,34 +80,37 @@
$order_maps[$visible->getPHID()] = $visible->getWorkboardOrderVectors();
}
- $template = $this->buildTemplate();
+ $object = id(new ManiphestTaskQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($object_phid))
+ ->needProjectPHIDs(true)
+ ->executeOne();
+ if (!$object) {
+ return new Aphront404Response();
+ }
+
+ $template = $this->buildTemplate($object);
$payload = array(
'objectPHID' => $object_phid,
'cardHTML' => $template,
'columnMaps' => $natural,
'orderMaps' => $order_maps,
+ 'propertyMaps' => array(
+ $object_phid => $object->getWorkboardProperties(),
+ ),
);
return id(new AphrontAjaxResponse())
->setContent($payload);
}
- private function buildTemplate() {
+ private function buildTemplate($object) {
$viewer = $this->getViewer();
$object_phid = $this->getObjectPHID();
$excluded_phids = $this->loadExcludedProjectPHIDs();
- $object = id(new ManiphestTaskQuery())
- ->setViewer($viewer)
- ->withPHIDs(array($object_phid))
- ->needProjectPHIDs(true)
- ->executeOne();
- if (!$object) {
- return new Aphront404Response();
- }
-
$rendering_engine = id(new PhabricatorBoardRenderingEngine())
->setViewer($viewer)
->setObjects(array($object))
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
@@ -19,11 +19,13 @@
this._templates = {};
this._orderMaps = {};
+ this._propertiesMap = {};
this._buildColumns();
},
properties: {
order: null,
+ pointsEnabled: false
},
members: {
@@ -33,6 +35,7 @@
_columns: null,
_templates: null,
_orderMaps: null,
+ _propertiesMap: null,
getRoot: function() {
return this._root;
@@ -55,6 +58,15 @@
return this;
},
+ setObjectProperties: function(phid, properties) {
+ this._propertiesMap[phid] = properties;
+ return this;
+ },
+
+ getObjectProperties: function(phid) {
+ return this._propertiesMap[phid];
+ },
+
getCardTemplate: function(phid) {
return this._templates[phid];
},
@@ -174,12 +186,18 @@
var card = src_column.removeCard(response.objectPHID);
dst_column.addCard(card, after_phid);
+ src_column.markForRedraw();
+ dst_column.markForRedraw();
+
this.updateCard(response);
list.unlock();
},
- updateCard: function(response) {
+ updateCard: function(response, options) {
+ options = options || {};
+ options.dirtyColumns = options.dirtyColumns || {};
+
var columns = this.getColumns();
var phid = response.objectPHID;
@@ -202,8 +220,15 @@
this.getColumn(natural_phid).setNaturalOrder(column_maps[natural_phid]);
}
+ var property_maps = response.propertyMaps;
+ for (var property_phid in property_maps) {
+ this.setObjectProperties(property_phid, property_maps[property_phid]);
+ }
+
for (var column_phid in columns) {
- var cards = columns[column_phid].getCards();
+ var column = columns[column_phid];
+
+ var cards = column.getCards();
for (var object_phid in cards) {
if (object_phid !== phid) {
continue;
@@ -211,8 +236,20 @@
var card = cards[object_phid];
card.redraw();
+
+ column.markForRedraw();
+ }
+ }
+
+ this._redrawColumns();
+ },
+
+ _redrawColumns: function() {
+ var columns = this.getColumns();
+ for (var k in columns) {
+ if (columns[k].isMarkedForRedraw()) {
+ columns[k].redraw();
}
- columns[column_phid].redraw();
}
}
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
@@ -28,6 +28,18 @@
this._column = column;
},
+ getProperties: function() {
+ return this.getColumn().getBoard().getObjectProperties(this.getPHID());
+ },
+
+ getPoints: function() {
+ return this.getProperties().points;
+ },
+
+ getStatus: function() {
+ return this.getProperties().status;
+ },
+
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
@@ -12,6 +12,14 @@
this._phid = phid;
this._root = root;
+ this._panel = JX.DOM.findAbove(root, 'div', 'workpanel');
+ this._pointsNode = JX.DOM.find(this._panel, 'span', 'column-points');
+
+ this._pointsContentNode = JX.DOM.find(
+ this._panel,
+ 'span',
+ 'column-points-content');
+
this._cards = {};
this._naturalOrder = [];
},
@@ -22,6 +30,10 @@
_board: null,
_cards: null,
_naturalOrder: null,
+ _panel: null,
+ _pointsNode: null,
+ _pointsContentNode: null,
+ _dirty: true,
getPHID: function() {
return this._phid;
@@ -48,6 +60,18 @@
return this;
},
+ getPointsNode: function() {
+ return this._pointsNode;
+ },
+
+ getPointsContentNode: function() {
+ return this._pointsContentNode;
+ },
+
+ getWorkpanelNode: function() {
+ return this._panel;
+ },
+
newCard: function(phid) {
var card = new JX.WorkboardCard(this, phid);
@@ -112,8 +136,21 @@
return JX.keys(this.getCards());
},
+ getPointLimit: function() {
+ return JX.Stratcom.getData(this.getRoot()).pointLimit;
+ },
+
+ markForRedraw: function() {
+ this._dirty = true;
+ },
+
+ isMarkedForRedraw: function() {
+ return this._dirty;
+ },
+
redraw: function() {
- var order = this.getBoard().getOrder();
+ var board = this.getBoard();
+ var order = board.getOrder();
var list;
if (order == 'natural') {
@@ -124,11 +161,18 @@
var content = [];
for (var ii = 0; ii < list.length; ii++) {
- var node = list[ii].getNode();
+ var card = list[ii];
+
+ var node = card.getNode();
content.push(node);
+
}
JX.DOM.setContent(this.getRoot(), content);
+
+ this._redrawFrame();
+
+ this._dirty = false;
},
_getCardsSortedNaturally: function() {
@@ -170,6 +214,69 @@
}
return 0;
+ },
+
+ _redrawFrame: function() {
+ var cards = this.getCards();
+ var board = this.getBoard();
+
+ var points = {};
+ for (var phid in cards) {
+ var card = cards[phid];
+
+ var card_points;
+ if (board.getPointsEnabled()) {
+ card_points = card.getPoints();
+ } else {
+ card_points = 1;
+ }
+
+ if (card_points !== null) {
+ var status = card.getStatus();
+ if (!points[status]) {
+ points[status] = 0;
+ }
+ points[status] += card_points;
+ }
+ }
+
+ var total_points = 0;
+ for (var k in points) {
+ total_points += points[k];
+ }
+
+ var limit = this.getPointLimit();
+
+ var display_value;
+ if (limit !== null && limit !== 0) {
+ display_value = total_points + ' / ' + limit;
+ } else {
+ display_value = total_points;
+ }
+
+ var over_limit = ((limit !== null) && (total_points > limit));
+
+ var content_node = this.getPointsContentNode();
+ var points_node = this.getPointsNode();
+
+ JX.DOM.setContent(content_node, display_value);
+
+ var is_empty = !this.getCardPHIDs().length;
+ var panel = JX.DOM.findAbove(this.getRoot(), 'div', 'workpanel');
+ JX.DOM.alterClass(panel, 'project-panel-empty', is_empty);
+ JX.DOM.alterClass(panel, 'project-panel-over-limit', over_limit);
+
+ var color_map = {
+ 'phui-tag-shade-disabled': (total_points === 0),
+ 'phui-tag-shade-blue': (total_points > 0 && !over_limit),
+ 'phui-tag-shade-red': (over_limit)
+ };
+
+ for (var c in color_map) {
+ JX.DOM.alterClass(points_node, c, !!color_map[c]);
+ }
+
+ JX.DOM.show(points_node);
}
}
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
@@ -11,54 +11,6 @@
JX.behavior('project-boards', function(config, statics) {
-
- function onupdate(col) {
- var data = JX.Stratcom.getData(col);
- var cards = finditems(col);
-
- // Update the count of tasks in the column header.
- if (!data.countTagNode) {
- data.countTagNode = JX.$(data.countTagID);
- JX.DOM.show(data.countTagNode);
- }
-
- var sum = 0;
- for (var ii = 0; ii < cards.length; ii++) {
- // TODO: Allow this to be computed in some more clever way.
- sum += 1;
- }
-
- // TODO: This is a little bit hacky, but we don't have a PHUIX version of
- // this element yet.
-
- var over_limit = (data.pointLimit && (sum > data.pointLimit));
-
- var display_value = sum;
- if (data.pointLimit) {
- display_value = sum + ' / ' + data.pointLimit;
- }
- JX.DOM.setContent(JX.$(data.countTagContentID), display_value);
-
-
- var panel_map = {
- 'project-panel-empty': !cards.length,
- 'project-panel-over-limit': over_limit
- };
- var panel = JX.DOM.findAbove(col, 'div', 'workpanel');
- for (var p in panel_map) {
- JX.DOM.alterClass(panel, p, !!panel_map[p]);
- }
-
- var color_map = {
- 'phui-tag-shade-disabled': (sum === 0),
- 'phui-tag-shade-blue': (sum > 0 && !over_limit),
- 'phui-tag-shade-red': (over_limit)
- };
- for (var c in color_map) {
- JX.DOM.alterClass(data.countTagNode, c, !!color_map[c]);
- }
- }
-
function update_statics(update_config) {
statics.boardID = update_config.boardID;
statics.projectPHID = update_config.projectPHID;
@@ -135,7 +87,8 @@
var board_node = JX.$(config.boardID);
var board = statics.workboard.newBoard(board_phid, board_node)
- .setOrder(config.order);
+ .setOrder(config.order)
+ .setPointsEnabled(config.pointsEnabled);
var templates = config.templateMap;
for (var k in templates) {
@@ -156,6 +109,11 @@
board.setOrderMap(object_phid, order_maps[object_phid]);
}
+ var property_maps = config.propertyMaps;
+ for (var property_phid in property_maps) {
+ board.setObjectProperties(property_phid, property_maps[property_phid]);
+ }
+
board.start();
});

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 16, 2:32 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7705231
Default Alt Text
D15237.id36779.diff (18 KB)

Event Timeline