@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.

When dragging nodes between different columns on an ordered board, don't reorder them by making secondary edits

Summary:
Ref T10334. When a workboard is ordered by priority, dragging from column "A" to a particular place in column "B" currently means "move this task to column B, and adjust its priority so that it naturally sorts into the location under my mouse cursor".

Users frequently find this confusing / undesirable.

To begin improving this, make "drag from column A to column B" and "drag from somewhere in column A to somewhere else in column A" into different operations. The first operation, a movement between columns, no longer implies an ordering change. The second action still does.

So if you actually want to change the priority of a task, you drag it within its current column. If you just want to move it to a different column, you drag it between columns.

This creates some possible problems:

- Some users may love the current behavior and just not be very vocal about it. I doubt it, but presumably we'll hear from them if we break it.
- If you actualy want to move + reorder, it's a bit more cumbersome now. We could possibly add something like "shift + drag" for this if there's feedback.
- The new behavior is probably less surprising, but may not be much more obvious. Future changes (for example, in T10335) should help make it more clear.
- When you mouse cursor goes over column B, the card dashed-rectangle preview target thing jumps to the correct position in the column -- but that may not be under your mouse cursor. This feels pretty much fine if the whole column fits on screen. It may not be so great if the column does not fit on screen and the dashed-rectangle-thing has vanished. This is just a UI feedback issue and we could refine this later (scroll/highlight the column).

Test Plan:
- Created several tasks at different priority levels, sorted a board by priority, dragged tasks between columns. Dragging from "A" to "B" no longer causes a priority edit.
- Also, dragged within a column. This still performs priority edits.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T10334

Differential Revision: https://secure.phabricator.com/D20242

+84 -35
+28 -28
resources/celerity/map.php
··· 10 10 'conpherence.pkg.css' => '3c8a0668', 11 11 'conpherence.pkg.js' => '020aebcf', 12 12 'core.pkg.css' => '34ce1741', 13 - 'core.pkg.js' => '2cda17a4', 13 + 'core.pkg.js' => '9eb1254b', 14 14 'differential.pkg.css' => '1755a478', 15 15 'differential.pkg.js' => '67e02996', 16 16 'diffusion.pkg.css' => '42c75c37', ··· 409 409 'rsrc/js/application/phortune/phortune-credit-card-form.js' => 'd12d214f', 410 410 'rsrc/js/application/policy/behavior-policy-control.js' => '0eaa33a9', 411 411 'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '9347f172', 412 - 'rsrc/js/application/projects/WorkboardBoard.js' => '45d0b2b1', 412 + 'rsrc/js/application/projects/WorkboardBoard.js' => '3a8c42a3', 413 413 'rsrc/js/application/projects/WorkboardCard.js' => '9a513421', 414 - 'rsrc/js/application/projects/WorkboardColumn.js' => '8573dc1b', 414 + 'rsrc/js/application/projects/WorkboardColumn.js' => 'b451fd4c', 415 415 'rsrc/js/application/projects/WorkboardController.js' => '42c7a5a7', 416 416 'rsrc/js/application/projects/behavior-project-boards.js' => '05c74d65', 417 417 'rsrc/js/application/projects/behavior-project-create.js' => '34c53422', ··· 434 434 'rsrc/js/application/uiexample/notification-example.js' => '29819b75', 435 435 'rsrc/js/core/Busy.js' => '5202e831', 436 436 'rsrc/js/core/DragAndDropFileUpload.js' => '4370900d', 437 - 'rsrc/js/core/DraggableList.js' => '3c6bd549', 437 + 'rsrc/js/core/DraggableList.js' => 'd594c805', 438 438 'rsrc/js/core/Favicon.js' => '7930776a', 439 439 'rsrc/js/core/FileUpload.js' => 'ab85e184', 440 440 'rsrc/js/core/Hovercard.js' => '074f0783', ··· 727 727 'javelin-view-renderer' => '9aae2b66', 728 728 'javelin-view-visitor' => '308f9fe4', 729 729 'javelin-websocket' => 'fdc13e4e', 730 - 'javelin-workboard-board' => '45d0b2b1', 730 + 'javelin-workboard-board' => '3a8c42a3', 731 731 'javelin-workboard-card' => '9a513421', 732 - 'javelin-workboard-column' => '8573dc1b', 732 + 'javelin-workboard-column' => 'b451fd4c', 733 733 'javelin-workboard-controller' => '42c7a5a7', 734 734 'javelin-workflow' => '958e9045', 735 735 'maniphest-report-css' => '3d53188b', ··· 755 755 'phabricator-diff-changeset-list' => '04023d82', 756 756 'phabricator-diff-inline' => 'a4a14a94', 757 757 'phabricator-drag-and-drop-file-upload' => '4370900d', 758 - 'phabricator-draggable-list' => '3c6bd549', 758 + 'phabricator-draggable-list' => 'd594c805', 759 759 'phabricator-fatal-config-template-css' => '20babf50', 760 760 'phabricator-favicon' => '7930776a', 761 761 'phabricator-feed-css' => 'd8b6e3f8', ··· 1188 1188 'javelin-install', 1189 1189 'javelin-dom', 1190 1190 ), 1191 - '3b4899b0' => array( 1192 - 'javelin-behavior', 1193 - 'phabricator-prefab', 1194 - ), 1195 - '3c6bd549' => array( 1191 + '3a8c42a3' => array( 1196 1192 'javelin-install', 1197 1193 'javelin-dom', 1198 - 'javelin-stratcom', 1199 1194 'javelin-util', 1200 - 'javelin-vector', 1201 - 'javelin-magical-init', 1195 + 'javelin-stratcom', 1196 + 'javelin-workflow', 1197 + 'phabricator-draggable-list', 1198 + 'javelin-workboard-column', 1199 + ), 1200 + '3b4899b0' => array( 1201 + 'javelin-behavior', 1202 + 'phabricator-prefab', 1202 1203 ), 1203 1204 '3dc5ad43' => array( 1204 1205 'javelin-behavior', ··· 1255 1256 ), 1256 1257 '43bc9360' => array( 1257 1258 'javelin-install', 1258 - ), 1259 - '45d0b2b1' => array( 1260 - 'javelin-install', 1261 - 'javelin-dom', 1262 - 'javelin-util', 1263 - 'javelin-stratcom', 1264 - 'javelin-workflow', 1265 - 'phabricator-draggable-list', 1266 - 'javelin-workboard-column', 1267 1259 ), 1268 1260 '46116c01' => array( 1269 1261 'javelin-request', ··· 1565 1557 'javelin-workflow', 1566 1558 'phabricator-draggable-list', 1567 1559 ), 1568 - '8573dc1b' => array( 1569 - 'javelin-install', 1570 - 'javelin-workboard-card', 1571 - ), 1572 1560 '87428eb2' => array( 1573 1561 'javelin-behavior', 1574 1562 'javelin-diffusion-locate-file-source', ··· 1855 1843 'b347a301' => array( 1856 1844 'javelin-behavior', 1857 1845 ), 1846 + 'b451fd4c' => array( 1847 + 'javelin-install', 1848 + 'javelin-workboard-card', 1849 + ), 1858 1850 'b517bfa0' => array( 1859 1851 'phui-oi-list-view-css', 1860 1852 ), ··· 1993 1985 ), 1994 1986 'd3799cb4' => array( 1995 1987 'javelin-install', 1988 + ), 1989 + 'd594c805' => array( 1990 + 'javelin-install', 1991 + 'javelin-dom', 1992 + 'javelin-stratcom', 1993 + 'javelin-util', 1994 + 'javelin-vector', 1995 + 'javelin-magical-init', 1996 1996 ), 1997 1997 'd8a86cfb' => array( 1998 1998 'javelin-behavior',
+4
webroot/rsrc/js/application/projects/WorkboardBoard.js
··· 118 118 .setCanDragX(true) 119 119 .setHasInfiniteHeight(true); 120 120 121 + if (this.getOrder() !== 'natural') { 122 + list.setCompareHandler(JX.bind(column, column.compareHandler)); 123 + } 124 + 121 125 list.listen('didDrop', JX.bind(this, this._onmovecard, list)); 122 126 123 127 lists.push(list);
+22 -5
webroot/rsrc/js/application/projects/WorkboardColumn.js
··· 175 175 this._dirty = false; 176 176 }, 177 177 178 + compareHandler: function(src_list, src_node, dst_list, dst_node) { 179 + var board = this.getBoard(); 180 + var order = board.getOrder(); 181 + 182 + var src_phid = JX.Stratcom.getData(src_node).objectPHID; 183 + var dst_phid = JX.Stratcom.getData(dst_node).objectPHID; 184 + 185 + var u_vec = this.getBoard().getOrderVector(src_phid, order); 186 + var v_vec = this.getBoard().getOrderVector(dst_phid, order); 187 + 188 + return this._compareVectors(u_vec, v_vec); 189 + }, 190 + 178 191 _getCardsSortedNaturally: function() { 179 192 var list = []; 180 193 ··· 200 213 }, 201 214 202 215 _sortCards: function(order, u, v) { 203 - var ud = this.getBoard().getOrderVector(u.getPHID(), order); 204 - var vd = this.getBoard().getOrderVector(v.getPHID(), order); 216 + var u_vec = this.getBoard().getOrderVector(u.getPHID(), order); 217 + var v_vec = this.getBoard().getOrderVector(v.getPHID(), order); 218 + 219 + return this._compareVectors(u_vec, v_vec); 220 + }, 205 221 206 - for (var ii = 0; ii < ud.length; ii++) { 207 - if (ud[ii] > vd[ii]) { 222 + _compareVectors: function(u_vec, v_vec) { 223 + for (var ii = 0; ii < u_vec.length; ii++) { 224 + if (u_vec[ii] > v_vec[ii]) { 208 225 return 1; 209 226 } 210 227 211 - if (ud[ii] < vd[ii]) { 228 + if (u_vec[ii] < v_vec[ii]) { 212 229 return -1; 213 230 } 214 231 }
+30 -2
webroot/rsrc/js/core/DraggableList.js
··· 39 39 40 40 properties : { 41 41 findItemsHandler: null, 42 + compareHandler: null, 42 43 canDragX: false, 43 44 outerContainer: null, 44 45 hasInfiniteHeight: false ··· 367 368 return this; 368 369 }, 369 370 371 + _getOrderedTarget: function(src_list, src_node) { 372 + var targets = this._getTargets(); 373 + 374 + // NOTE: The targets are ordered from the bottom of the column to the 375 + // top, so we're looking for the first node that we sort below. If we 376 + // don't find one, we'll sort to the head of the column. 377 + 378 + for (var ii = 0; ii < targets.length; ii++) { 379 + var target = targets[ii]; 380 + if (this._compareTargets(src_list, src_node, target.item) > 0) { 381 + return target.item; 382 + } 383 + } 384 + 385 + return null; 386 + }, 387 + 388 + _compareTargets: function(src_list, src_node, dst_node) { 389 + var dst_list = this; 390 + return this.getCompareHandler()(src_list, src_node, dst_list, dst_node); 391 + }, 392 + 370 393 _getCurrentTarget : function(p) { 371 - var ghost = this.getGhostNode(); 372 394 var targets = this._getTargets(); 373 395 var dragging = this._dragging; 374 396 ··· 461 483 // Compute the size and position of the drop target indicator, because we 462 484 // need to update our static position computations to account for it. 463 485 486 + var compare_handler = this.getCompareHandler(); 487 + 464 488 var cur_target = false; 465 489 if (target_list) { 466 - cur_target = target_list._getCurrentTarget(p); 490 + if (compare_handler && (target_list !== this)) { 491 + cur_target = target_list._getOrderedTarget(this, this._dragging); 492 + } else { 493 + cur_target = target_list._getCurrentTarget(p); 494 + } 467 495 } 468 496 469 497 // If we've selected a new target, update the UI to show where we're