From 1fb76655dfb4613cbeafde8179d9283aa322040b Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 10 Feb 2016 13:53:36 -0800 Subject: [PATCH] Restore column point counts to workboards Summary: Ref T4427. Test Plan: - Dragged a 17 XP task from "Hunting" to "Slain". - Saw 17 XP move. - Level up! Reviewers: chad Reviewed By: chad Maniphest Tasks: T4427 Differential Revision: https://secure.phabricator.com/D15237 --- .../maniphest/storage/ManiphestTask.php | 7 ++ .../PhabricatorProjectBoardViewController.php | 24 ++-- .../engine/PhabricatorBoardResponseEngine.php | 41 ++++--- .../js/application/projects/WorkboardBoard.js | 43 ++++++- .../js/application/projects/WorkboardCard.js | 12 ++ .../application/projects/WorkboardColumn.js | 111 +++++++++++++++++- .../projects/behavior-project-boards.js | 56 ++------- 7 files changed, 212 insertions(+), 82 deletions(-) diff --git a/src/applications/maniphest/storage/ManiphestTask.php b/src/applications/maniphest/storage/ManiphestTask.php index 5ac290078b..93a5f5562c 100644 --- a/src/applications/maniphest/storage/ManiphestTask.php +++ b/src/applications/maniphest/storage/ManiphestTask.php @@ -221,6 +221,13 @@ final class ManiphestTask extends ManiphestDAO ); } + 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 index 2138367ca9..c075072d9f 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -318,14 +318,17 @@ final class PhabricatorProjectBoardViewController $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 @@ final class PhabricatorProjectBoardViewController ->setMetadata( array( 'columnPHID' => $column->getPHID(), - 'countTagID' => $tag_id, - 'countTagContentID' => $tag_content_id, 'pointLimit' => $column->getPointLimit(), )); @@ -359,17 +360,22 @@ final class PhabricatorProjectBoardViewController } $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 index d1fd3f33a8..969dfa3bc8 100644 --- a/src/applications/project/engine/PhabricatorBoardResponseEngine.php +++ b/src/applications/project/engine/PhabricatorBoardResponseEngine.php @@ -80,25 +80,6 @@ final class PhabricatorBoardResponseEngine extends Phobject { $order_maps[$visible->getPHID()] = $visible->getWorkboardOrderVectors(); } - $template = $this->buildTemplate(); - - $payload = array( - 'objectPHID' => $object_phid, - 'cardHTML' => $template, - 'columnMaps' => $natural, - 'orderMaps' => $order_maps, - ); - - return id(new AphrontAjaxResponse()) - ->setContent($payload); - } - - private function buildTemplate() { - $viewer = $this->getViewer(); - $object_phid = $this->getObjectPHID(); - - $excluded_phids = $this->loadExcludedProjectPHIDs(); - $object = id(new ManiphestTaskQuery()) ->setViewer($viewer) ->withPHIDs(array($object_phid)) @@ -108,6 +89,28 @@ final class PhabricatorBoardResponseEngine extends Phobject { 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($object) { + $viewer = $this->getViewer(); + $object_phid = $this->getObjectPHID(); + + $excluded_phids = $this->loadExcludedProjectPHIDs(); + $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 index 343086d569..4506041cca 100644 --- a/webroot/rsrc/js/application/projects/WorkboardBoard.js +++ b/webroot/rsrc/js/application/projects/WorkboardBoard.js @@ -19,11 +19,13 @@ JX.install('WorkboardBoard', { this._templates = {}; this._orderMaps = {}; + this._propertiesMap = {}; this._buildColumns(); }, properties: { order: null, + pointsEnabled: false }, members: { @@ -33,6 +35,7 @@ JX.install('WorkboardBoard', { _columns: null, _templates: null, _orderMaps: null, + _propertiesMap: null, getRoot: function() { return this._root; @@ -55,6 +58,15 @@ JX.install('WorkboardBoard', { 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 @@ JX.install('WorkboardBoard', { 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 @@ JX.install('WorkboardBoard', { 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 @@ JX.install('WorkboardBoard', { 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 index 69294219c0..b506e655c1 100644 --- a/webroot/rsrc/js/application/projects/WorkboardCard.js +++ b/webroot/rsrc/js/application/projects/WorkboardCard.js @@ -28,6 +28,18 @@ JX.install('WorkboardCard', { 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 index 77f9ca3146..738cf151c2 100644 --- a/webroot/rsrc/js/application/projects/WorkboardColumn.js +++ b/webroot/rsrc/js/application/projects/WorkboardColumn.js @@ -12,6 +12,14 @@ JX.install('WorkboardColumn', { 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 @@ JX.install('WorkboardColumn', { _board: null, _cards: null, _naturalOrder: null, + _panel: null, + _pointsNode: null, + _pointsContentNode: null, + _dirty: true, getPHID: function() { return this._phid; @@ -48,6 +60,18 @@ JX.install('WorkboardColumn', { 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 @@ JX.install('WorkboardColumn', { 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 @@ JX.install('WorkboardColumn', { 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 @@ JX.install('WorkboardColumn', { } 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 index 5267a09fc2..8fccb1dc91 100644 --- 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 @@ JX.behavior('project-boards', function(config, statics) { 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 @@ JX.behavior('project-boards', function(config, statics) { 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(); });