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

Allow draggable elements to be dragged to the first list position

Summary:
Currently, draggable lists (in Config and ApplicationSearch, for example) don't let you drag an item into the first position.

This is because the behavior is correct in Maniphest: the first position is above an initial header, like "High Prioirty", and shouldn't be targetable.

Permit the behavior in general; forbid it in Maniphest.

Test Plan:
- Dragged elements into the first position in ApplicationSearch.
- Failed to drag elements into the first position in Maniphest.

Reviewers: garoevans, btrahan

Reviewed By: garoevans

CC: aran

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

+32 -17
+9 -9
src/__celerity_resource_map__.php
··· 1859 1859 ), 1860 1860 'javelin-behavior-maniphest-subpriority-editor' => 1861 1861 array( 1862 - 'uri' => '/res/99d84c61/rsrc/js/application/maniphest/behavior-subpriorityeditor.js', 1862 + 'uri' => '/res/1fa4961f/rsrc/js/application/maniphest/behavior-subpriorityeditor.js', 1863 1863 'type' => 'js', 1864 1864 'requires' => 1865 1865 array( ··· 3095 3095 ), 3096 3096 'phabricator-draggable-list' => 3097 3097 array( 3098 - 'uri' => '/res/7292a1c4/rsrc/js/core/DraggableList.js', 3098 + 'uri' => '/res/75c556db/rsrc/js/core/DraggableList.js', 3099 3099 'type' => 'js', 3100 3100 'requires' => 3101 3101 array( ··· 4382 4382 'uri' => '/res/pkg/49898640/maniphest.pkg.css', 4383 4383 'type' => 'css', 4384 4384 ), 4385 - '83a3853e' => 4385 + '0a694954' => 4386 4386 array( 4387 4387 'name' => 'maniphest.pkg.js', 4388 4388 'symbols' => ··· 4393 4393 3 => 'javelin-behavior-maniphest-transaction-expand', 4394 4394 4 => 'javelin-behavior-maniphest-subpriority-editor', 4395 4395 ), 4396 - 'uri' => '/res/pkg/83a3853e/maniphest.pkg.js', 4396 + 'uri' => '/res/pkg/0a694954/maniphest.pkg.js', 4397 4397 'type' => 'js', 4398 4398 ), 4399 4399 ), ··· 4453 4453 'javelin-behavior-konami' => '8977e356', 4454 4454 'javelin-behavior-lightbox-attachments' => '8977e356', 4455 4455 'javelin-behavior-load-blame' => '5e9e5c4e', 4456 - 'javelin-behavior-maniphest-batch-selector' => '83a3853e', 4457 - 'javelin-behavior-maniphest-subpriority-editor' => '83a3853e', 4458 - 'javelin-behavior-maniphest-transaction-controls' => '83a3853e', 4459 - 'javelin-behavior-maniphest-transaction-expand' => '83a3853e', 4460 - 'javelin-behavior-maniphest-transaction-preview' => '83a3853e', 4456 + 'javelin-behavior-maniphest-batch-selector' => '0a694954', 4457 + 'javelin-behavior-maniphest-subpriority-editor' => '0a694954', 4458 + 'javelin-behavior-maniphest-transaction-controls' => '0a694954', 4459 + 'javelin-behavior-maniphest-transaction-expand' => '0a694954', 4460 + 'javelin-behavior-maniphest-transaction-preview' => '0a694954', 4461 4461 'javelin-behavior-phabricator-active-nav' => '8977e356', 4462 4462 'javelin-behavior-phabricator-autofocus' => '8977e356', 4463 4463 'javelin-behavior-phabricator-gesture' => '8977e356',
+6
webroot/rsrc/js/application/maniphest/behavior-subpriorityeditor.js
··· 16 16 return tasks.concat(heads); 17 17 }) 18 18 .setGhostHandler(function(ghost, target) { 19 + if (!target) { 20 + // The user is trying to drag a task above the first group header; 21 + // don't permit that since it doesn't make sense. 22 + return false; 23 + } 24 + 19 25 if (target.nextSibling) { 20 26 if (JX.DOM.isType(target, 'h1')) { 21 27 target.nextSibling.insertBefore(ghost, target.nextSibling.firstChild);
+17 -8
webroot/rsrc/js/core/DraggableList.js
··· 126 126 } 127 127 targets.sort(function(u, v) { return v.y - u.y; }); 128 128 this._targets = targets; 129 - this._target = null; 129 + this._target = false; 130 130 131 131 if (!this.invoke('didBeginDrag', this._dragging).getPrevented()) { 132 132 var ghost = this.getGhostNode(); ··· 158 158 // node in the list that's above the cursor. If that node is the node 159 159 // we're dragging or its predecessor, don't select a target, because the 160 160 // operation would be a no-op. 161 + 162 + // NOTE: When we're dragging into the first position in the list, we 163 + // use the target `null`. When we don't have a valid target, we use 164 + // the target `false`. Spooky! Magic! Anyway, `null` and `false` mean 165 + // completely different things. 161 166 162 167 var cur_target = null; 163 168 var trigger; ··· 183 188 184 189 cur_target = targets[ii].item; 185 190 if (cur_target == dragging) { 186 - cur_target = null; 191 + cur_target = false; 187 192 } 188 193 if (targets[ii - 1] && targets[ii - 1].item == dragging) { 189 - cur_target = null; 194 + cur_target = false; 190 195 } 191 196 192 197 break; ··· 201 206 JX.DOM.remove(ghost); 202 207 } 203 208 204 - if (cur_target) { 205 - this.getGhostHandler()(ghost, cur_target); 209 + if (cur_target !== false) { 210 + var ok = this.getGhostHandler()(ghost, cur_target); 211 + // If the handler returns explicit `false`, prevent the drag. 212 + if (ok === false) { 213 + cur_target = false; 214 + } 206 215 } 207 216 208 217 target = cur_target; 209 218 210 - if (target) { 219 + if (target !== false) { 211 220 212 221 // If we've changed where the ghost node is, update the adjustments 213 222 // so we accurately reflect document state when we tweak things below. ··· 223 232 // adjust the cursor position for the change in node document position. 224 233 // Do this before choosing a new target to avoid a flash of nonsense. 225 234 226 - if (target) { 235 + if (target !== false) { 227 236 if (adjust_y <= origin.y) { 228 237 p.y -= adjust_h; 229 238 } ··· 250 259 251 260 JX.$V(0, 0).setPos(dragging); 252 261 253 - if (target) { 262 + if (target !== false) { 254 263 JX.DOM.remove(dragging); 255 264 JX.DOM.replace(ghost, dragging); 256 265 this.invoke('didDrop', dragging, target);