@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+204 -74
+7
src/applications/maniphest/storage/ManiphestTask.php
··· 221 221 ); 222 222 } 223 223 224 + public function getWorkboardProperties() { 225 + return array( 226 + 'status' => $this->getStatus(), 227 + 'points' => (double)$this->getPoints(), 228 + ); 229 + } 230 + 224 231 225 232 /* -( PhabricatorSubscribableInterface )----------------------------------- */ 226 233
+15 -9
src/applications/project/controller/PhabricatorProjectBoardViewController.php
··· 318 318 $column_menu = $this->buildColumnMenu($project, $column); 319 319 $panel->addHeaderAction($column_menu); 320 320 321 - $tag_id = celerity_generate_unique_node_id(); 322 - $tag_content_id = celerity_generate_unique_node_id(); 323 - 324 321 $count_tag = id(new PHUITagView()) 325 322 ->setType(PHUITagView::TYPE_SHADE) 326 323 ->setShade(PHUITagView::COLOR_BLUE) 327 - ->setID($tag_id) 328 - ->setName(phutil_tag('span', array('id' => $tag_content_id), '-')) 324 + ->addSigil('column-points') 325 + ->setName( 326 + javelin_tag( 327 + 'span', 328 + array( 329 + 'sigil' => 'column-points-content', 330 + ), 331 + pht('-'))) 329 332 ->setStyle('display: none'); 330 333 331 334 $panel->setHeaderTag($count_tag); ··· 339 342 ->setMetadata( 340 343 array( 341 344 'columnPHID' => $column->getPHID(), 342 - 'countTagID' => $tag_id, 343 - 'countTagContentID' => $tag_content_id, 344 345 'pointLimit' => $column->getPointLimit(), 345 346 )); 346 347 ··· 359 360 } 360 361 361 362 $behavior_config = array( 362 - 'boardID' => $board_id, 363 - 'projectPHID' => $project->getPHID(), 364 363 'moveURI' => $this->getApplicationURI('move/'.$project->getID().'/'), 365 364 'createURI' => $this->getCreateURI(), 366 365 'uploadURI' => '/file/dropupload/', 367 366 'coverURI' => $this->getApplicationURI('cover/'), 368 367 'chunkThreshold' => PhabricatorFileStorageEngine::getChunkThreshold(), 368 + 'pointsEnabled' => ManiphestTaskPoints::getIsEnabled(), 369 + 370 + 'boardPHID' => $project->getPHID(), 369 371 'order' => $this->sortKey, 370 372 'templateMap' => $templates, 371 373 'columnMaps' => $column_maps, 372 374 'orderMaps' => mpull($all_tasks, 'getWorkboardOrderVectors'), 375 + 'propertyMaps' => mpull($all_tasks, 'getWorkboardProperties'), 376 + 377 + 'boardID' => $board_id, 378 + 'projectPHID' => $project->getPHID(), 373 379 ); 374 380 $this->initBehavior('project-boards', $behavior_config); 375 381
+14 -11
src/applications/project/engine/PhabricatorBoardResponseEngine.php
··· 80 80 $order_maps[$visible->getPHID()] = $visible->getWorkboardOrderVectors(); 81 81 } 82 82 83 - $template = $this->buildTemplate(); 83 + $object = id(new ManiphestTaskQuery()) 84 + ->setViewer($viewer) 85 + ->withPHIDs(array($object_phid)) 86 + ->needProjectPHIDs(true) 87 + ->executeOne(); 88 + if (!$object) { 89 + return new Aphront404Response(); 90 + } 91 + 92 + $template = $this->buildTemplate($object); 84 93 85 94 $payload = array( 86 95 'objectPHID' => $object_phid, 87 96 'cardHTML' => $template, 88 97 'columnMaps' => $natural, 89 98 'orderMaps' => $order_maps, 99 + 'propertyMaps' => array( 100 + $object_phid => $object->getWorkboardProperties(), 101 + ), 90 102 ); 91 103 92 104 return id(new AphrontAjaxResponse()) 93 105 ->setContent($payload); 94 106 } 95 107 96 - private function buildTemplate() { 108 + private function buildTemplate($object) { 97 109 $viewer = $this->getViewer(); 98 110 $object_phid = $this->getObjectPHID(); 99 111 100 112 $excluded_phids = $this->loadExcludedProjectPHIDs(); 101 - 102 - $object = id(new ManiphestTaskQuery()) 103 - ->setViewer($viewer) 104 - ->withPHIDs(array($object_phid)) 105 - ->needProjectPHIDs(true) 106 - ->executeOne(); 107 - if (!$object) { 108 - return new Aphront404Response(); 109 - } 110 113 111 114 $rendering_engine = id(new PhabricatorBoardRenderingEngine()) 112 115 ->setViewer($viewer)
+40 -3
webroot/rsrc/js/application/projects/WorkboardBoard.js
··· 19 19 20 20 this._templates = {}; 21 21 this._orderMaps = {}; 22 + this._propertiesMap = {}; 22 23 this._buildColumns(); 23 24 }, 24 25 25 26 properties: { 26 27 order: null, 28 + pointsEnabled: false 27 29 }, 28 30 29 31 members: { ··· 33 35 _columns: null, 34 36 _templates: null, 35 37 _orderMaps: null, 38 + _propertiesMap: null, 36 39 37 40 getRoot: function() { 38 41 return this._root; ··· 53 56 setCardTemplate: function(phid, template) { 54 57 this._templates[phid] = template; 55 58 return this; 59 + }, 60 + 61 + setObjectProperties: function(phid, properties) { 62 + this._propertiesMap[phid] = properties; 63 + return this; 64 + }, 65 + 66 + getObjectProperties: function(phid) { 67 + return this._propertiesMap[phid]; 56 68 }, 57 69 58 70 getCardTemplate: function(phid) { ··· 174 186 var card = src_column.removeCard(response.objectPHID); 175 187 dst_column.addCard(card, after_phid); 176 188 189 + src_column.markForRedraw(); 190 + dst_column.markForRedraw(); 191 + 177 192 this.updateCard(response); 178 193 179 194 list.unlock(); 180 195 }, 181 196 182 - updateCard: function(response) { 197 + updateCard: function(response, options) { 198 + options = options || {}; 199 + options.dirtyColumns = options.dirtyColumns || {}; 200 + 183 201 var columns = this.getColumns(); 184 202 185 203 var phid = response.objectPHID; ··· 202 220 this.getColumn(natural_phid).setNaturalOrder(column_maps[natural_phid]); 203 221 } 204 222 223 + var property_maps = response.propertyMaps; 224 + for (var property_phid in property_maps) { 225 + this.setObjectProperties(property_phid, property_maps[property_phid]); 226 + } 227 + 205 228 for (var column_phid in columns) { 206 - var cards = columns[column_phid].getCards(); 229 + var column = columns[column_phid]; 230 + 231 + var cards = column.getCards(); 207 232 for (var object_phid in cards) { 208 233 if (object_phid !== phid) { 209 234 continue; ··· 211 236 212 237 var card = cards[object_phid]; 213 238 card.redraw(); 239 + 240 + column.markForRedraw(); 214 241 } 215 - columns[column_phid].redraw(); 242 + } 243 + 244 + this._redrawColumns(); 245 + }, 246 + 247 + _redrawColumns: function() { 248 + var columns = this.getColumns(); 249 + for (var k in columns) { 250 + if (columns[k].isMarkedForRedraw()) { 251 + columns[k].redraw(); 252 + } 216 253 } 217 254 } 218 255
+12
webroot/rsrc/js/application/projects/WorkboardCard.js
··· 28 28 this._column = column; 29 29 }, 30 30 31 + getProperties: function() { 32 + return this.getColumn().getBoard().getObjectProperties(this.getPHID()); 33 + }, 34 + 35 + getPoints: function() { 36 + return this.getProperties().points; 37 + }, 38 + 39 + getStatus: function() { 40 + return this.getProperties().status; 41 + }, 42 + 31 43 getNode: function() { 32 44 if (!this._root) { 33 45 var phid = this.getPHID();
+109 -2
webroot/rsrc/js/application/projects/WorkboardColumn.js
··· 12 12 this._phid = phid; 13 13 this._root = root; 14 14 15 + this._panel = JX.DOM.findAbove(root, 'div', 'workpanel'); 16 + this._pointsNode = JX.DOM.find(this._panel, 'span', 'column-points'); 17 + 18 + this._pointsContentNode = JX.DOM.find( 19 + this._panel, 20 + 'span', 21 + 'column-points-content'); 22 + 15 23 this._cards = {}; 16 24 this._naturalOrder = []; 17 25 }, ··· 22 30 _board: null, 23 31 _cards: null, 24 32 _naturalOrder: null, 33 + _panel: null, 34 + _pointsNode: null, 35 + _pointsContentNode: null, 36 + _dirty: true, 25 37 26 38 getPHID: function() { 27 39 return this._phid; ··· 46 58 setNaturalOrder: function(order) { 47 59 this._naturalOrder = order; 48 60 return this; 61 + }, 62 + 63 + getPointsNode: function() { 64 + return this._pointsNode; 65 + }, 66 + 67 + getPointsContentNode: function() { 68 + return this._pointsContentNode; 69 + }, 70 + 71 + getWorkpanelNode: function() { 72 + return this._panel; 49 73 }, 50 74 51 75 newCard: function(phid) { ··· 112 136 return JX.keys(this.getCards()); 113 137 }, 114 138 139 + getPointLimit: function() { 140 + return JX.Stratcom.getData(this.getRoot()).pointLimit; 141 + }, 142 + 143 + markForRedraw: function() { 144 + this._dirty = true; 145 + }, 146 + 147 + isMarkedForRedraw: function() { 148 + return this._dirty; 149 + }, 150 + 115 151 redraw: function() { 116 - var order = this.getBoard().getOrder(); 152 + var board = this.getBoard(); 153 + var order = board.getOrder(); 117 154 118 155 var list; 119 156 if (order == 'natural') { ··· 124 161 125 162 var content = []; 126 163 for (var ii = 0; ii < list.length; ii++) { 127 - var node = list[ii].getNode(); 164 + var card = list[ii]; 165 + 166 + var node = card.getNode(); 128 167 content.push(node); 168 + 129 169 } 130 170 131 171 JX.DOM.setContent(this.getRoot(), content); 172 + 173 + this._redrawFrame(); 174 + 175 + this._dirty = false; 132 176 }, 133 177 134 178 _getCardsSortedNaturally: function() { ··· 170 214 } 171 215 172 216 return 0; 217 + }, 218 + 219 + _redrawFrame: function() { 220 + var cards = this.getCards(); 221 + var board = this.getBoard(); 222 + 223 + var points = {}; 224 + for (var phid in cards) { 225 + var card = cards[phid]; 226 + 227 + var card_points; 228 + if (board.getPointsEnabled()) { 229 + card_points = card.getPoints(); 230 + } else { 231 + card_points = 1; 232 + } 233 + 234 + if (card_points !== null) { 235 + var status = card.getStatus(); 236 + if (!points[status]) { 237 + points[status] = 0; 238 + } 239 + points[status] += card_points; 240 + } 241 + } 242 + 243 + var total_points = 0; 244 + for (var k in points) { 245 + total_points += points[k]; 246 + } 247 + 248 + var limit = this.getPointLimit(); 249 + 250 + var display_value; 251 + if (limit !== null && limit !== 0) { 252 + display_value = total_points + ' / ' + limit; 253 + } else { 254 + display_value = total_points; 255 + } 256 + 257 + var over_limit = ((limit !== null) && (total_points > limit)); 258 + 259 + var content_node = this.getPointsContentNode(); 260 + var points_node = this.getPointsNode(); 261 + 262 + JX.DOM.setContent(content_node, display_value); 263 + 264 + var is_empty = !this.getCardPHIDs().length; 265 + var panel = JX.DOM.findAbove(this.getRoot(), 'div', 'workpanel'); 266 + JX.DOM.alterClass(panel, 'project-panel-empty', is_empty); 267 + JX.DOM.alterClass(panel, 'project-panel-over-limit', over_limit); 268 + 269 + var color_map = { 270 + 'phui-tag-shade-disabled': (total_points === 0), 271 + 'phui-tag-shade-blue': (total_points > 0 && !over_limit), 272 + 'phui-tag-shade-red': (over_limit) 273 + }; 274 + 275 + for (var c in color_map) { 276 + JX.DOM.alterClass(points_node, c, !!color_map[c]); 277 + } 278 + 279 + JX.DOM.show(points_node); 173 280 } 174 281 175 282 }
+7 -49
webroot/rsrc/js/application/projects/behavior-project-boards.js
··· 11 11 12 12 JX.behavior('project-boards', function(config, statics) { 13 13 14 - 15 - function onupdate(col) { 16 - var data = JX.Stratcom.getData(col); 17 - var cards = finditems(col); 18 - 19 - // Update the count of tasks in the column header. 20 - if (!data.countTagNode) { 21 - data.countTagNode = JX.$(data.countTagID); 22 - JX.DOM.show(data.countTagNode); 23 - } 24 - 25 - var sum = 0; 26 - for (var ii = 0; ii < cards.length; ii++) { 27 - // TODO: Allow this to be computed in some more clever way. 28 - sum += 1; 29 - } 30 - 31 - // TODO: This is a little bit hacky, but we don't have a PHUIX version of 32 - // this element yet. 33 - 34 - var over_limit = (data.pointLimit && (sum > data.pointLimit)); 35 - 36 - var display_value = sum; 37 - if (data.pointLimit) { 38 - display_value = sum + ' / ' + data.pointLimit; 39 - } 40 - JX.DOM.setContent(JX.$(data.countTagContentID), display_value); 41 - 42 - 43 - var panel_map = { 44 - 'project-panel-empty': !cards.length, 45 - 'project-panel-over-limit': over_limit 46 - }; 47 - var panel = JX.DOM.findAbove(col, 'div', 'workpanel'); 48 - for (var p in panel_map) { 49 - JX.DOM.alterClass(panel, p, !!panel_map[p]); 50 - } 51 - 52 - var color_map = { 53 - 'phui-tag-shade-disabled': (sum === 0), 54 - 'phui-tag-shade-blue': (sum > 0 && !over_limit), 55 - 'phui-tag-shade-red': (over_limit) 56 - }; 57 - for (var c in color_map) { 58 - JX.DOM.alterClass(data.countTagNode, c, !!color_map[c]); 59 - } 60 - } 61 - 62 14 function update_statics(update_config) { 63 15 statics.boardID = update_config.boardID; 64 16 statics.projectPHID = update_config.projectPHID; ··· 135 87 var board_node = JX.$(config.boardID); 136 88 137 89 var board = statics.workboard.newBoard(board_phid, board_node) 138 - .setOrder(config.order); 90 + .setOrder(config.order) 91 + .setPointsEnabled(config.pointsEnabled); 139 92 140 93 var templates = config.templateMap; 141 94 for (var k in templates) { ··· 154 107 var order_maps = config.orderMaps; 155 108 for (var object_phid in order_maps) { 156 109 board.setOrderMap(object_phid, order_maps[object_phid]); 110 + } 111 + 112 + var property_maps = config.propertyMaps; 113 + for (var property_phid in property_maps) { 114 + board.setObjectProperties(property_phid, property_maps[property_phid]); 157 115 } 158 116 159 117 board.start();