2016-02-10 14:59:46 +01:00
|
|
|
/**
|
|
|
|
* @provides javelin-workboard-board
|
|
|
|
* @requires javelin-install
|
|
|
|
* javelin-dom
|
|
|
|
* javelin-util
|
|
|
|
* javelin-stratcom
|
|
|
|
* javelin-workflow
|
|
|
|
* phabricator-draggable-list
|
|
|
|
* javelin-workboard-column
|
Add priority group headers to workboard columns (display only)
Summary:
Ref T10333. When workboards are ordered (for example, by priority), add headers to the various groups. Major goals are:
- Allow users to drag-and-drop to set values that no cards currently have: for example, you can change a card priority to "normal" by dragging it under the "normal" header, even if no other cards in the column are currently "Normal".
- Make future orderings more useful, particularly "order by assignee". We don't really have room to put the username on every card and it would create a fair amount of clutter, but we can put usernames in these headers and then reference them with just the profile picture. This also allows you to assign to users who are not currently assigned anything in a given column.
- Make the drag-and-drop behavior more obvious by showing what it will do more clearly (see T8135).
- Make things a little easier to scan in general: because space on cards is limited, some information isn't conveyed very clearly (for example, priority information is currently conveyed //only// through color, which can be hard to pick out visually and is probably not functional for users who need vision accommodations).
- Maybe do "swimlanes": this is pretty much a "swimlanes" UI if we add whitespace at the bottom of each group so that the headers line up across all the columns (e.g., "Normal" is at the same y-axis position in every column as you scroll down the page). Not sold on this being useful, but it's just a UI adjustment if we do want to try it.
NOTE: This only makes these headers work for display.
They aren't yet recognized as targets by the drag list UI, so you can't drag cards into an empty group. I'll tackle that in a followup.
Test Plan: {F6257686}
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20247
2019-03-05 15:00:12 +01:00
|
|
|
* javelin-workboard-header-template
|
2019-03-11 03:53:25 +01:00
|
|
|
* javelin-workboard-card-template
|
2019-03-11 16:58:46 +01:00
|
|
|
* javelin-workboard-order-template
|
2016-02-10 14:59:46 +01:00
|
|
|
* @javelin
|
|
|
|
*/
|
|
|
|
|
|
|
|
JX.install('WorkboardBoard', {
|
|
|
|
|
|
|
|
construct: function(controller, phid, root) {
|
|
|
|
this._controller = controller;
|
|
|
|
this._phid = phid;
|
|
|
|
this._root = root;
|
|
|
|
|
Add priority group headers to workboard columns (display only)
Summary:
Ref T10333. When workboards are ordered (for example, by priority), add headers to the various groups. Major goals are:
- Allow users to drag-and-drop to set values that no cards currently have: for example, you can change a card priority to "normal" by dragging it under the "normal" header, even if no other cards in the column are currently "Normal".
- Make future orderings more useful, particularly "order by assignee". We don't really have room to put the username on every card and it would create a fair amount of clutter, but we can put usernames in these headers and then reference them with just the profile picture. This also allows you to assign to users who are not currently assigned anything in a given column.
- Make the drag-and-drop behavior more obvious by showing what it will do more clearly (see T8135).
- Make things a little easier to scan in general: because space on cards is limited, some information isn't conveyed very clearly (for example, priority information is currently conveyed //only// through color, which can be hard to pick out visually and is probably not functional for users who need vision accommodations).
- Maybe do "swimlanes": this is pretty much a "swimlanes" UI if we add whitespace at the bottom of each group so that the headers line up across all the columns (e.g., "Normal" is at the same y-axis position in every column as you scroll down the page). Not sold on this being useful, but it's just a UI adjustment if we do want to try it.
NOTE: This only makes these headers work for display.
They aren't yet recognized as targets by the drag list UI, so you can't drag cards into an empty group. I'll tackle that in a followup.
Test Plan: {F6257686}
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20247
2019-03-05 15:00:12 +01:00
|
|
|
this._headers = {};
|
2019-03-11 03:53:25 +01:00
|
|
|
this._cards = {};
|
2019-03-11 16:58:46 +01:00
|
|
|
this._orders = {};
|
2019-03-11 03:53:25 +01:00
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
this._buildColumns();
|
|
|
|
},
|
|
|
|
|
|
|
|
properties: {
|
|
|
|
order: null,
|
2016-02-10 22:53:36 +01:00
|
|
|
pointsEnabled: false
|
2016-02-10 14:59:46 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
members: {
|
|
|
|
_controller: null,
|
|
|
|
_phid: null,
|
|
|
|
_root: null,
|
|
|
|
_columns: null,
|
Add priority group headers to workboard columns (display only)
Summary:
Ref T10333. When workboards are ordered (for example, by priority), add headers to the various groups. Major goals are:
- Allow users to drag-and-drop to set values that no cards currently have: for example, you can change a card priority to "normal" by dragging it under the "normal" header, even if no other cards in the column are currently "Normal".
- Make future orderings more useful, particularly "order by assignee". We don't really have room to put the username on every card and it would create a fair amount of clutter, but we can put usernames in these headers and then reference them with just the profile picture. This also allows you to assign to users who are not currently assigned anything in a given column.
- Make the drag-and-drop behavior more obvious by showing what it will do more clearly (see T8135).
- Make things a little easier to scan in general: because space on cards is limited, some information isn't conveyed very clearly (for example, priority information is currently conveyed //only// through color, which can be hard to pick out visually and is probably not functional for users who need vision accommodations).
- Maybe do "swimlanes": this is pretty much a "swimlanes" UI if we add whitespace at the bottom of each group so that the headers line up across all the columns (e.g., "Normal" is at the same y-axis position in every column as you scroll down the page). Not sold on this being useful, but it's just a UI adjustment if we do want to try it.
NOTE: This only makes these headers work for display.
They aren't yet recognized as targets by the drag list UI, so you can't drag cards into an empty group. I'll tackle that in a followup.
Test Plan: {F6257686}
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20247
2019-03-05 15:00:12 +01:00
|
|
|
_headers: null,
|
2019-03-11 03:53:25 +01:00
|
|
|
_cards: null,
|
2019-03-19 23:27:21 +01:00
|
|
|
_dropPreviewNode: null,
|
|
|
|
_dropPreviewListNode: null,
|
2019-03-21 21:19:12 +01:00
|
|
|
_previewPHID: null,
|
|
|
|
_hidePreivew: false,
|
2019-03-25 16:04:33 +01:00
|
|
|
_previewPositionVector: null,
|
|
|
|
_previewDimState: false,
|
2016-02-10 14:59:46 +01:00
|
|
|
|
|
|
|
getRoot: function() {
|
|
|
|
return this._root;
|
|
|
|
},
|
|
|
|
|
|
|
|
getColumns: function() {
|
|
|
|
return this._columns;
|
|
|
|
},
|
|
|
|
|
|
|
|
getColumn: function(k) {
|
|
|
|
return this._columns[k];
|
|
|
|
},
|
|
|
|
|
|
|
|
getPHID: function() {
|
|
|
|
return this._phid;
|
|
|
|
},
|
|
|
|
|
2019-03-11 03:53:25 +01:00
|
|
|
getCardTemplate: function(phid) {
|
|
|
|
if (!this._cards[phid]) {
|
|
|
|
this._cards[phid] = new JX.WorkboardCardTemplate(phid);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._cards[phid];
|
2016-02-10 14:59:46 +01:00
|
|
|
},
|
|
|
|
|
Add priority group headers to workboard columns (display only)
Summary:
Ref T10333. When workboards are ordered (for example, by priority), add headers to the various groups. Major goals are:
- Allow users to drag-and-drop to set values that no cards currently have: for example, you can change a card priority to "normal" by dragging it under the "normal" header, even if no other cards in the column are currently "Normal".
- Make future orderings more useful, particularly "order by assignee". We don't really have room to put the username on every card and it would create a fair amount of clutter, but we can put usernames in these headers and then reference them with just the profile picture. This also allows you to assign to users who are not currently assigned anything in a given column.
- Make the drag-and-drop behavior more obvious by showing what it will do more clearly (see T8135).
- Make things a little easier to scan in general: because space on cards is limited, some information isn't conveyed very clearly (for example, priority information is currently conveyed //only// through color, which can be hard to pick out visually and is probably not functional for users who need vision accommodations).
- Maybe do "swimlanes": this is pretty much a "swimlanes" UI if we add whitespace at the bottom of each group so that the headers line up across all the columns (e.g., "Normal" is at the same y-axis position in every column as you scroll down the page). Not sold on this being useful, but it's just a UI adjustment if we do want to try it.
NOTE: This only makes these headers work for display.
They aren't yet recognized as targets by the drag list UI, so you can't drag cards into an empty group. I'll tackle that in a followup.
Test Plan: {F6257686}
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20247
2019-03-05 15:00:12 +01:00
|
|
|
getHeaderTemplate: function(header_key) {
|
|
|
|
if (!this._headers[header_key]) {
|
|
|
|
this._headers[header_key] = new JX.WorkboardHeaderTemplate(header_key);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._headers[header_key];
|
|
|
|
},
|
|
|
|
|
2019-03-11 16:58:46 +01:00
|
|
|
getOrderTemplate: function(order_key) {
|
|
|
|
if (!this._orders[order_key]) {
|
|
|
|
this._orders[order_key] = new JX.WorkboardOrderTemplate(order_key);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._orders[order_key];
|
|
|
|
},
|
|
|
|
|
Add priority group headers to workboard columns (display only)
Summary:
Ref T10333. When workboards are ordered (for example, by priority), add headers to the various groups. Major goals are:
- Allow users to drag-and-drop to set values that no cards currently have: for example, you can change a card priority to "normal" by dragging it under the "normal" header, even if no other cards in the column are currently "Normal".
- Make future orderings more useful, particularly "order by assignee". We don't really have room to put the username on every card and it would create a fair amount of clutter, but we can put usernames in these headers and then reference them with just the profile picture. This also allows you to assign to users who are not currently assigned anything in a given column.
- Make the drag-and-drop behavior more obvious by showing what it will do more clearly (see T8135).
- Make things a little easier to scan in general: because space on cards is limited, some information isn't conveyed very clearly (for example, priority information is currently conveyed //only// through color, which can be hard to pick out visually and is probably not functional for users who need vision accommodations).
- Maybe do "swimlanes": this is pretty much a "swimlanes" UI if we add whitespace at the bottom of each group so that the headers line up across all the columns (e.g., "Normal" is at the same y-axis position in every column as you scroll down the page). Not sold on this being useful, but it's just a UI adjustment if we do want to try it.
NOTE: This only makes these headers work for display.
They aren't yet recognized as targets by the drag list UI, so you can't drag cards into an empty group. I'll tackle that in a followup.
Test Plan: {F6257686}
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20247
2019-03-05 15:00:12 +01:00
|
|
|
getHeaderTemplatesForOrder: function(order) {
|
|
|
|
var templates = [];
|
|
|
|
|
|
|
|
for (var k in this._headers) {
|
|
|
|
var header = this._headers[k];
|
|
|
|
|
|
|
|
if (header.getOrder() !== order) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
templates.push(header);
|
|
|
|
}
|
|
|
|
|
|
|
|
templates.sort(JX.bind(this, this._sortHeaderTemplates));
|
|
|
|
|
|
|
|
return templates;
|
|
|
|
},
|
|
|
|
|
|
|
|
_sortHeaderTemplates: function(u, v) {
|
|
|
|
return this.compareVectors(u.getVector(), v.getVector());
|
|
|
|
},
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
getController: function() {
|
|
|
|
return this._controller;
|
|
|
|
},
|
|
|
|
|
Add priority group headers to workboard columns (display only)
Summary:
Ref T10333. When workboards are ordered (for example, by priority), add headers to the various groups. Major goals are:
- Allow users to drag-and-drop to set values that no cards currently have: for example, you can change a card priority to "normal" by dragging it under the "normal" header, even if no other cards in the column are currently "Normal".
- Make future orderings more useful, particularly "order by assignee". We don't really have room to put the username on every card and it would create a fair amount of clutter, but we can put usernames in these headers and then reference them with just the profile picture. This also allows you to assign to users who are not currently assigned anything in a given column.
- Make the drag-and-drop behavior more obvious by showing what it will do more clearly (see T8135).
- Make things a little easier to scan in general: because space on cards is limited, some information isn't conveyed very clearly (for example, priority information is currently conveyed //only// through color, which can be hard to pick out visually and is probably not functional for users who need vision accommodations).
- Maybe do "swimlanes": this is pretty much a "swimlanes" UI if we add whitespace at the bottom of each group so that the headers line up across all the columns (e.g., "Normal" is at the same y-axis position in every column as you scroll down the page). Not sold on this being useful, but it's just a UI adjustment if we do want to try it.
NOTE: This only makes these headers work for display.
They aren't yet recognized as targets by the drag list UI, so you can't drag cards into an empty group. I'll tackle that in a followup.
Test Plan: {F6257686}
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20247
2019-03-05 15:00:12 +01:00
|
|
|
compareVectors: function(u_vec, v_vec) {
|
|
|
|
for (var ii = 0; ii < u_vec.length; ii++) {
|
|
|
|
if (u_vec[ii] > v_vec[ii]) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (u_vec[ii] < v_vec[ii]) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
},
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
start: function() {
|
|
|
|
this._setupDragHandlers();
|
|
|
|
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
// TODO: This is temporary code to make it easier to debug this workflow
|
|
|
|
// by pressing the "R" key.
|
|
|
|
var on_reload = JX.bind(this, this._reloadCards);
|
|
|
|
new JX.KeyboardShortcut('R', 'Reload Card State (Prototype)')
|
|
|
|
.setHandler(on_reload)
|
|
|
|
.register();
|
|
|
|
|
2019-07-17 21:23:32 +02:00
|
|
|
var board_phid = this.getPHID();
|
|
|
|
|
|
|
|
JX.Stratcom.listen('aphlict-server-message', null, function(e) {
|
|
|
|
var message = e.getData();
|
|
|
|
|
|
|
|
if (message.type != 'workboards') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if this update notification is about the currently visible
|
|
|
|
// board. If it is, update the board state.
|
|
|
|
|
|
|
|
var found_board = false;
|
|
|
|
for (var ii = 0; ii < message.subscribers.length; ii++) {
|
|
|
|
var subscriber_phid = message.subscribers[ii];
|
|
|
|
if (subscriber_phid === board_phid) {
|
|
|
|
found_board = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found_board) {
|
|
|
|
on_reload();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
JX.Stratcom.listen('aphlict-reconnect', null, function(e) {
|
|
|
|
on_reload();
|
|
|
|
});
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
for (var k in this._columns) {
|
|
|
|
this._columns[k].redraw();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_buildColumns: function() {
|
|
|
|
var nodes = JX.DOM.scry(this.getRoot(), 'ul', 'project-column');
|
|
|
|
|
|
|
|
this._columns = {};
|
|
|
|
for (var ii = 0; ii < nodes.length; ii++) {
|
|
|
|
var node = nodes[ii];
|
|
|
|
var data = JX.Stratcom.getData(node);
|
|
|
|
var phid = data.columnPHID;
|
|
|
|
|
|
|
|
this._columns[phid] = new JX.WorkboardColumn(this, phid, node);
|
|
|
|
}
|
2019-03-21 21:19:12 +01:00
|
|
|
|
|
|
|
var on_over = JX.bind(this, this._showTriggerPreview);
|
|
|
|
var on_out = JX.bind(this, this._hideTriggerPreview);
|
|
|
|
JX.Stratcom.listen('mouseover', 'trigger-preview', on_over);
|
|
|
|
JX.Stratcom.listen('mouseout', 'trigger-preview', on_out);
|
2019-03-25 16:04:33 +01:00
|
|
|
|
|
|
|
var on_move = JX.bind(this, this._dimPreview);
|
|
|
|
JX.Stratcom.listen('mousemove', null, on_move);
|
|
|
|
},
|
|
|
|
|
|
|
|
_dimPreview: function(e) {
|
|
|
|
var p = this._previewPositionVector;
|
|
|
|
if (!p) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// When the mouse cursor gets near the drop preview element, fade it
|
|
|
|
// out so you can see through it. We can't do this with ":hover" because
|
|
|
|
// we disable cursor events.
|
|
|
|
|
|
|
|
var cursor = JX.$V(e);
|
|
|
|
var margin = 64;
|
|
|
|
|
|
|
|
var near_x = (cursor.x > (p.x - margin));
|
|
|
|
var near_y = (cursor.y > (p.y - margin));
|
|
|
|
var should_dim = (near_x && near_y);
|
|
|
|
|
|
|
|
this._setPreviewDimState(should_dim);
|
|
|
|
},
|
|
|
|
|
|
|
|
_setPreviewDimState: function(is_dim) {
|
|
|
|
if (is_dim === this._previewDimState) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._previewDimState = is_dim;
|
|
|
|
var node = this._getDropPreviewNode();
|
|
|
|
JX.DOM.alterClass(node, 'workboard-drop-preview-fade', is_dim);
|
2019-03-21 21:19:12 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
_showTriggerPreview: function(e) {
|
|
|
|
if (this._disablePreview) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var target = e.getTarget();
|
|
|
|
var node = e.getNode('trigger-preview');
|
|
|
|
|
|
|
|
if (target !== node) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var phid = JX.Stratcom.getData(node).columnPHID;
|
|
|
|
var column = this._columns[phid];
|
|
|
|
|
|
|
|
// Bail out if we don't know anything about this column.
|
|
|
|
if (!column) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (phid === this._previewPHID) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._previewPHID = phid;
|
|
|
|
|
|
|
|
var effects = column.getDropEffects();
|
|
|
|
|
|
|
|
var triggers = [];
|
|
|
|
for (var ii = 0; ii < effects.length; ii++) {
|
|
|
|
if (effects[ii].getIsTriggerEffect()) {
|
|
|
|
triggers.push(effects[ii]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (triggers.length) {
|
|
|
|
var header = column.getTriggerPreviewEffect();
|
|
|
|
triggers = [header].concat(triggers);
|
|
|
|
}
|
|
|
|
|
|
|
|
this._showEffects(triggers);
|
|
|
|
},
|
|
|
|
|
|
|
|
_hideTriggerPreview: function(e) {
|
|
|
|
if (this._disablePreview) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var target = e.getTarget();
|
|
|
|
|
|
|
|
if (target !== e.getNode('trigger-preview')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._removeTriggerPreview();
|
|
|
|
},
|
|
|
|
|
|
|
|
_removeTriggerPreview: function() {
|
|
|
|
this._showEffects([]);
|
|
|
|
this._previewPHID = null;
|
|
|
|
},
|
|
|
|
|
|
|
|
_beginDrag: function() {
|
|
|
|
this._disablePreview = true;
|
|
|
|
this._showEffects([]);
|
|
|
|
},
|
|
|
|
|
|
|
|
_endDrag: function() {
|
|
|
|
this._disablePreview = false;
|
2016-02-10 14:59:46 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
_setupDragHandlers: function() {
|
|
|
|
var columns = this.getColumns();
|
|
|
|
|
2019-03-11 16:58:46 +01:00
|
|
|
var order_template = this.getOrderTemplate(this.getOrder());
|
|
|
|
var has_headers = order_template.getHasHeaders();
|
|
|
|
var can_reorder = order_template.getCanReorder();
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
var lists = [];
|
|
|
|
for (var k in columns) {
|
|
|
|
var column = columns[k];
|
|
|
|
|
2019-03-11 06:56:54 +01:00
|
|
|
var list = new JX.DraggableList('draggable-card', column.getRoot())
|
2016-02-10 14:59:46 +01:00
|
|
|
.setOuterContainer(this.getRoot())
|
Make drag-and-drop on workboards interact with priority column headers
Summary:
Ref T10333. Ref T8135. Depends on D20247. Allow users to drag-and-drop cards on a priority-sorted workboard under headers, even if the header has no other cards.
As of D20247, headers show up but they aren't really interactive. Now, you can drag cards directly underneath a header (instead of only between other cards). For example, if a column has only one "Wishlist" task, you may drag it under the "High", "Normal", or "Low" priority headers to select a specific priority.
(Some of this code still feels a little rough, but I think it will generalize once other types of sorting are available.)
Test Plan: Dragged cards within and between priority groups, saw appropriate priority edits applied in every case I could come up with.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333, T8135
Differential Revision: https://secure.phabricator.com/D20248
2019-03-05 16:38:35 +01:00
|
|
|
.setFindItemsHandler(JX.bind(column, column.getDropTargetNodes))
|
2016-02-10 14:59:46 +01:00
|
|
|
.setCanDragX(true)
|
2019-03-02 16:45:51 +01:00
|
|
|
.setHasInfiniteHeight(true)
|
|
|
|
.setIsDropTargetHandler(JX.bind(column, column.setIsDropTarget));
|
2016-02-10 14:59:46 +01:00
|
|
|
|
Make drag-and-drop on workboards interact with priority column headers
Summary:
Ref T10333. Ref T8135. Depends on D20247. Allow users to drag-and-drop cards on a priority-sorted workboard under headers, even if the header has no other cards.
As of D20247, headers show up but they aren't really interactive. Now, you can drag cards directly underneath a header (instead of only between other cards). For example, if a column has only one "Wishlist" task, you may drag it under the "High", "Normal", or "Low" priority headers to select a specific priority.
(Some of this code still feels a little rough, but I think it will generalize once other types of sorting are available.)
Test Plan: Dragged cards within and between priority groups, saw appropriate priority edits applied in every case I could come up with.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333, T8135
Differential Revision: https://secure.phabricator.com/D20248
2019-03-05 16:38:35 +01:00
|
|
|
var default_handler = list.getGhostHandler();
|
|
|
|
list.setGhostHandler(
|
|
|
|
JX.bind(column, column.handleDragGhost, default_handler));
|
|
|
|
|
2019-03-11 16:58:46 +01:00
|
|
|
// The "compare handler" locks cards into a specific position in the
|
|
|
|
// column.
|
|
|
|
list.setCompareHandler(JX.bind(column, column.compareHandler));
|
|
|
|
|
|
|
|
// If the view has group headers, we lock cards into the right position
|
|
|
|
// when moving them between columns, but not within a column.
|
|
|
|
if (has_headers) {
|
|
|
|
list.setCompareOnMove(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we can't reorder cards, we always lock them into their current
|
|
|
|
// position.
|
|
|
|
if (!can_reorder) {
|
|
|
|
list.setCompareOnMove(true);
|
|
|
|
list.setCompareOnReorder(true);
|
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
2019-03-02 00:13:25 +01:00
|
|
|
}
|
|
|
|
|
2019-03-19 23:27:21 +01:00
|
|
|
list.setTargetChangeHandler(JX.bind(this, this._didChangeDropTarget));
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
list.listen('didDrop', JX.bind(this, this._onmovecard, list));
|
|
|
|
|
2019-03-21 21:19:12 +01:00
|
|
|
list.listen('didBeginDrag', JX.bind(this, this._beginDrag));
|
|
|
|
list.listen('didEndDrag', JX.bind(this, this._endDrag));
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
lists.push(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var ii = 0; ii < lists.length; ii++) {
|
|
|
|
lists[ii].setGroup(lists);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-03-19 23:27:21 +01:00
|
|
|
_didChangeDropTarget: function(src_list, src_node, dst_list, dst_node) {
|
|
|
|
if (!dst_list) {
|
|
|
|
// The card is being dragged into a dead area, like the left menu.
|
2019-03-21 21:19:12 +01:00
|
|
|
this._showEffects([]);
|
2019-03-19 23:27:21 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dst_node === false) {
|
|
|
|
// The card is being dragged over itself, so dropping it won't
|
|
|
|
// affect anything.
|
2019-03-21 21:19:12 +01:00
|
|
|
this._showEffects([]);
|
2019-03-19 23:27:21 +01:00
|
|
|
return;
|
|
|
|
}
|
2016-02-10 14:59:46 +01:00
|
|
|
|
|
|
|
var src_phid = JX.Stratcom.getData(src_list.getRootNode()).columnPHID;
|
2019-03-19 23:27:21 +01:00
|
|
|
var dst_phid = JX.Stratcom.getData(dst_list.getRootNode()).columnPHID;
|
2016-02-10 14:59:46 +01:00
|
|
|
|
2019-03-19 23:27:21 +01:00
|
|
|
var src_column = this.getColumn(src_phid);
|
|
|
|
var dst_column = this.getColumn(dst_phid);
|
|
|
|
|
|
|
|
var effects = [];
|
|
|
|
if (src_column !== dst_column) {
|
|
|
|
effects = effects.concat(dst_column.getDropEffects());
|
|
|
|
}
|
|
|
|
|
|
|
|
var context = this._getDropContext(dst_node);
|
|
|
|
if (context.headerKey) {
|
|
|
|
var header = this.getHeaderTemplate(context.headerKey);
|
|
|
|
effects = effects.concat(header.getDropEffects());
|
|
|
|
}
|
|
|
|
|
2019-03-20 03:29:33 +01:00
|
|
|
var card_phid = JX.Stratcom.getData(src_node).objectPHID;
|
|
|
|
var card = src_column.getCard(card_phid);
|
|
|
|
|
|
|
|
var visible = [];
|
|
|
|
for (var ii = 0; ii < effects.length; ii++) {
|
|
|
|
if (effects[ii].isEffectVisibleForCard(card)) {
|
|
|
|
visible.push(effects[ii]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
effects = visible;
|
|
|
|
|
2019-03-21 21:19:12 +01:00
|
|
|
this._showEffects(effects);
|
|
|
|
},
|
|
|
|
|
|
|
|
_showEffects: function(effects) {
|
|
|
|
var node = this._getDropPreviewNode();
|
|
|
|
|
2019-03-19 23:27:21 +01:00
|
|
|
if (!effects.length) {
|
|
|
|
JX.DOM.remove(node);
|
2019-03-25 16:04:33 +01:00
|
|
|
this._previewPositionVector = null;
|
2019-03-19 23:27:21 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var items = [];
|
|
|
|
for (var ii = 0; ii < effects.length; ii++) {
|
|
|
|
var effect = effects[ii];
|
|
|
|
items.push(effect.newNode());
|
|
|
|
}
|
|
|
|
|
|
|
|
JX.DOM.setContent(this._getDropPreviewListNode(), items);
|
|
|
|
document.body.appendChild(node);
|
2019-03-25 16:04:33 +01:00
|
|
|
|
|
|
|
// Undim the drop preview element if it was previously dimmed.
|
|
|
|
this._setPreviewDimState(false);
|
|
|
|
this._previewPositionVector = JX.$V(node);
|
2019-03-19 23:27:21 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
_getDropPreviewNode: function() {
|
|
|
|
if (!this._dropPreviewNode) {
|
|
|
|
var attributes = {
|
|
|
|
className: 'workboard-drop-preview'
|
|
|
|
};
|
|
|
|
|
|
|
|
var content = [
|
|
|
|
this._getDropPreviewListNode()
|
|
|
|
];
|
|
|
|
|
|
|
|
this._dropPreviewNode = JX.$N('div', attributes, content);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._dropPreviewNode;
|
|
|
|
},
|
|
|
|
|
|
|
|
_getDropPreviewListNode: function() {
|
|
|
|
if (!this._dropPreviewListNode) {
|
|
|
|
var attributes = {};
|
|
|
|
this._dropPreviewListNode = JX.$N('ul', attributes);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._dropPreviewListNode;
|
|
|
|
},
|
|
|
|
|
|
|
|
_findCardsInColumn: function(column_node) {
|
|
|
|
return JX.DOM.scry(column_node, 'li', 'project-card');
|
|
|
|
},
|
|
|
|
|
|
|
|
_getDropContext: function(after_node, item) {
|
|
|
|
var header_key;
|
2019-03-25 17:37:02 +01:00
|
|
|
var after_phids = [];
|
|
|
|
var before_phids = [];
|
2016-02-10 14:59:46 +01:00
|
|
|
|
On Workboards, sort groups by "natural order", not subpriority
Summary:
Depends on D20263. Ref T10333. I want to add groups like "Assignee" to workboards. This means you may have several tasks grouped under, say, "Alice".
When you drag the bottom-most task under "Alice" to the top, what does that mean?
Today, the only grouping is "Priority", and it means "change the task's secret/hidden global subpriority". However, this seems to generally be a somewhat-bad answer, and is quite complex. It also doesn't make much sense for an author grouping, since one task can't really be "more assigned" to Alice than another task.
Users likely intend this operation to mean "move it, visually, with no other effects" -- that is, user intent is to shuffle sticky notes around on a board, not edit anything substantive. The meaning is probably something like "this is similar to other nearby tasks" or "maybe this is a good place to start", which we can't really capture with any top-level attribute.
We could extend "subpriority" and give tasks a secret/hidden "sub-assignment strength" and so on, but this seems like a bad road to walk down. We'll also run into trouble later when subproject columns may appear on the board, and a user could want to put a task in different positions on different subprojects, conceivably.
In the "Natural" order view, we already have what is probably a generally better approach for this: a task display order particular to the column, that just remembers where you put the sticky notes.
Move away from "subpriority", and toward a world where we mostly keep sticky notes where you stuck them and move them around only when we have to. With no grouping, we still sort by "natural" order, as before. With priority grouping, we now sort by `<priority, natural>`. When you drag stuff around inside a priority group, we update the natural order.
This means that moving cards around on a "priority" board will also move them around on a "natural" board, at least somewhat. I think this is okay. If it's not intuitive, we could give every ordering its own separate "natural" view, so we remember where you stuck stuff on the "priority" board but that doesn't affect the "Natural" board. But I suspect we won't need to.
Test Plan:
- Viewed and dragged a natural board.
- Viewed and dragged a priority board.
- Dragged within and between groups of 0, 1, and multiple items.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20265
2019-03-10 16:43:55 +01:00
|
|
|
// We're going to send an "afterPHID" and a "beforePHID" if the card
|
|
|
|
// was dropped immediately adjacent to another card. If a card was
|
|
|
|
// dropped before or after a header, we don't send a PHID for the card
|
|
|
|
// on the other side of the header.
|
|
|
|
|
|
|
|
// If the view has headers, we always send the header the card was
|
|
|
|
// dropped under.
|
|
|
|
|
Make drag-and-drop on workboards interact with priority column headers
Summary:
Ref T10333. Ref T8135. Depends on D20247. Allow users to drag-and-drop cards on a priority-sorted workboard under headers, even if the header has no other cards.
As of D20247, headers show up but they aren't really interactive. Now, you can drag cards directly underneath a header (instead of only between other cards). For example, if a column has only one "Wishlist" task, you may drag it under the "High", "Normal", or "Low" priority headers to select a specific priority.
(Some of this code still feels a little rough, but I think it will generalize once other types of sorting are available.)
Test Plan: Dragged cards within and between priority groups, saw appropriate priority edits applied in every case I could come up with.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333, T8135
Differential Revision: https://secure.phabricator.com/D20248
2019-03-05 16:38:35 +01:00
|
|
|
var after_data;
|
|
|
|
var after_card = after_node;
|
|
|
|
while (after_card) {
|
|
|
|
after_data = JX.Stratcom.getData(after_card);
|
2019-03-25 17:37:02 +01:00
|
|
|
|
On Workboards, sort groups by "natural order", not subpriority
Summary:
Depends on D20263. Ref T10333. I want to add groups like "Assignee" to workboards. This means you may have several tasks grouped under, say, "Alice".
When you drag the bottom-most task under "Alice" to the top, what does that mean?
Today, the only grouping is "Priority", and it means "change the task's secret/hidden global subpriority". However, this seems to generally be a somewhat-bad answer, and is quite complex. It also doesn't make much sense for an author grouping, since one task can't really be "more assigned" to Alice than another task.
Users likely intend this operation to mean "move it, visually, with no other effects" -- that is, user intent is to shuffle sticky notes around on a board, not edit anything substantive. The meaning is probably something like "this is similar to other nearby tasks" or "maybe this is a good place to start", which we can't really capture with any top-level attribute.
We could extend "subpriority" and give tasks a secret/hidden "sub-assignment strength" and so on, but this seems like a bad road to walk down. We'll also run into trouble later when subproject columns may appear on the board, and a user could want to put a task in different positions on different subprojects, conceivably.
In the "Natural" order view, we already have what is probably a generally better approach for this: a task display order particular to the column, that just remembers where you put the sticky notes.
Move away from "subpriority", and toward a world where we mostly keep sticky notes where you stuck them and move them around only when we have to. With no grouping, we still sort by "natural" order, as before. With priority grouping, we now sort by `<priority, natural>`. When you drag stuff around inside a priority group, we update the natural order.
This means that moving cards around on a "priority" board will also move them around on a "natural" board, at least somewhat. I think this is okay. If it's not intuitive, we could give every ordering its own separate "natural" view, so we remember where you stuck stuff on the "priority" board but that doesn't affect the "Natural" board. But I suspect we won't need to.
Test Plan:
- Viewed and dragged a natural board.
- Viewed and dragged a priority board.
- Dragged within and between groups of 0, 1, and multiple items.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20265
2019-03-10 16:43:55 +01:00
|
|
|
if (after_data.headerKey) {
|
|
|
|
break;
|
|
|
|
}
|
Make drag-and-drop on workboards interact with priority column headers
Summary:
Ref T10333. Ref T8135. Depends on D20247. Allow users to drag-and-drop cards on a priority-sorted workboard under headers, even if the header has no other cards.
As of D20247, headers show up but they aren't really interactive. Now, you can drag cards directly underneath a header (instead of only between other cards). For example, if a column has only one "Wishlist" task, you may drag it under the "High", "Normal", or "Low" priority headers to select a specific priority.
(Some of this code still feels a little rough, but I think it will generalize once other types of sorting are available.)
Test Plan: Dragged cards within and between priority groups, saw appropriate priority edits applied in every case I could come up with.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333, T8135
Differential Revision: https://secure.phabricator.com/D20248
2019-03-05 16:38:35 +01:00
|
|
|
|
On Workboards, sort groups by "natural order", not subpriority
Summary:
Depends on D20263. Ref T10333. I want to add groups like "Assignee" to workboards. This means you may have several tasks grouped under, say, "Alice".
When you drag the bottom-most task under "Alice" to the top, what does that mean?
Today, the only grouping is "Priority", and it means "change the task's secret/hidden global subpriority". However, this seems to generally be a somewhat-bad answer, and is quite complex. It also doesn't make much sense for an author grouping, since one task can't really be "more assigned" to Alice than another task.
Users likely intend this operation to mean "move it, visually, with no other effects" -- that is, user intent is to shuffle sticky notes around on a board, not edit anything substantive. The meaning is probably something like "this is similar to other nearby tasks" or "maybe this is a good place to start", which we can't really capture with any top-level attribute.
We could extend "subpriority" and give tasks a secret/hidden "sub-assignment strength" and so on, but this seems like a bad road to walk down. We'll also run into trouble later when subproject columns may appear on the board, and a user could want to put a task in different positions on different subprojects, conceivably.
In the "Natural" order view, we already have what is probably a generally better approach for this: a task display order particular to the column, that just remembers where you put the sticky notes.
Move away from "subpriority", and toward a world where we mostly keep sticky notes where you stuck them and move them around only when we have to. With no grouping, we still sort by "natural" order, as before. With priority grouping, we now sort by `<priority, natural>`. When you drag stuff around inside a priority group, we update the natural order.
This means that moving cards around on a "priority" board will also move them around on a "natural" board, at least somewhat. I think this is okay. If it's not intuitive, we could give every ordering its own separate "natural" view, so we remember where you stuck stuff on the "priority" board but that doesn't affect the "Natural" board. But I suspect we won't need to.
Test Plan:
- Viewed and dragged a natural board.
- Viewed and dragged a priority board.
- Dragged within and between groups of 0, 1, and multiple items.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20265
2019-03-10 16:43:55 +01:00
|
|
|
if (after_data.objectPHID) {
|
2019-03-25 17:37:02 +01:00
|
|
|
after_phids.push(after_data.objectPHID);
|
On Workboards, sort groups by "natural order", not subpriority
Summary:
Depends on D20263. Ref T10333. I want to add groups like "Assignee" to workboards. This means you may have several tasks grouped under, say, "Alice".
When you drag the bottom-most task under "Alice" to the top, what does that mean?
Today, the only grouping is "Priority", and it means "change the task's secret/hidden global subpriority". However, this seems to generally be a somewhat-bad answer, and is quite complex. It also doesn't make much sense for an author grouping, since one task can't really be "more assigned" to Alice than another task.
Users likely intend this operation to mean "move it, visually, with no other effects" -- that is, user intent is to shuffle sticky notes around on a board, not edit anything substantive. The meaning is probably something like "this is similar to other nearby tasks" or "maybe this is a good place to start", which we can't really capture with any top-level attribute.
We could extend "subpriority" and give tasks a secret/hidden "sub-assignment strength" and so on, but this seems like a bad road to walk down. We'll also run into trouble later when subproject columns may appear on the board, and a user could want to put a task in different positions on different subprojects, conceivably.
In the "Natural" order view, we already have what is probably a generally better approach for this: a task display order particular to the column, that just remembers where you put the sticky notes.
Move away from "subpriority", and toward a world where we mostly keep sticky notes where you stuck them and move them around only when we have to. With no grouping, we still sort by "natural" order, as before. With priority grouping, we now sort by `<priority, natural>`. When you drag stuff around inside a priority group, we update the natural order.
This means that moving cards around on a "priority" board will also move them around on a "natural" board, at least somewhat. I think this is okay. If it's not intuitive, we could give every ordering its own separate "natural" view, so we remember where you stuck stuff on the "priority" board but that doesn't affect the "Natural" board. But I suspect we won't need to.
Test Plan:
- Viewed and dragged a natural board.
- Viewed and dragged a priority board.
- Dragged within and between groups of 0, 1, and multiple items.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20265
2019-03-10 16:43:55 +01:00
|
|
|
}
|
2019-03-25 17:37:02 +01:00
|
|
|
|
|
|
|
after_card = after_card.previousSibling;
|
2016-02-10 14:59:46 +01:00
|
|
|
}
|
|
|
|
|
2019-03-19 23:27:21 +01:00
|
|
|
if (item) {
|
|
|
|
var before_data;
|
|
|
|
var before_card = item.nextSibling;
|
|
|
|
while (before_card) {
|
|
|
|
before_data = JX.Stratcom.getData(before_card);
|
2019-03-25 17:37:02 +01:00
|
|
|
|
2019-03-19 23:27:21 +01:00
|
|
|
if (before_data.headerKey) {
|
|
|
|
break;
|
|
|
|
}
|
Make drag-and-drop on workboards interact with priority column headers
Summary:
Ref T10333. Ref T8135. Depends on D20247. Allow users to drag-and-drop cards on a priority-sorted workboard under headers, even if the header has no other cards.
As of D20247, headers show up but they aren't really interactive. Now, you can drag cards directly underneath a header (instead of only between other cards). For example, if a column has only one "Wishlist" task, you may drag it under the "High", "Normal", or "Low" priority headers to select a specific priority.
(Some of this code still feels a little rough, but I think it will generalize once other types of sorting are available.)
Test Plan: Dragged cards within and between priority groups, saw appropriate priority edits applied in every case I could come up with.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333, T8135
Differential Revision: https://secure.phabricator.com/D20248
2019-03-05 16:38:35 +01:00
|
|
|
|
2019-03-19 23:27:21 +01:00
|
|
|
if (before_data.objectPHID) {
|
2019-03-25 17:37:02 +01:00
|
|
|
before_phids.push(before_data.objectPHID);
|
2019-03-19 23:27:21 +01:00
|
|
|
}
|
2019-03-25 17:37:02 +01:00
|
|
|
|
|
|
|
before_card = before_card.nextSibling;
|
On Workboards, sort groups by "natural order", not subpriority
Summary:
Depends on D20263. Ref T10333. I want to add groups like "Assignee" to workboards. This means you may have several tasks grouped under, say, "Alice".
When you drag the bottom-most task under "Alice" to the top, what does that mean?
Today, the only grouping is "Priority", and it means "change the task's secret/hidden global subpriority". However, this seems to generally be a somewhat-bad answer, and is quite complex. It also doesn't make much sense for an author grouping, since one task can't really be "more assigned" to Alice than another task.
Users likely intend this operation to mean "move it, visually, with no other effects" -- that is, user intent is to shuffle sticky notes around on a board, not edit anything substantive. The meaning is probably something like "this is similar to other nearby tasks" or "maybe this is a good place to start", which we can't really capture with any top-level attribute.
We could extend "subpriority" and give tasks a secret/hidden "sub-assignment strength" and so on, but this seems like a bad road to walk down. We'll also run into trouble later when subproject columns may appear on the board, and a user could want to put a task in different positions on different subprojects, conceivably.
In the "Natural" order view, we already have what is probably a generally better approach for this: a task display order particular to the column, that just remembers where you put the sticky notes.
Move away from "subpriority", and toward a world where we mostly keep sticky notes where you stuck them and move them around only when we have to. With no grouping, we still sort by "natural" order, as before. With priority grouping, we now sort by `<priority, natural>`. When you drag stuff around inside a priority group, we update the natural order.
This means that moving cards around on a "priority" board will also move them around on a "natural" board, at least somewhat. I think this is okay. If it's not intuitive, we could give every ordering its own separate "natural" view, so we remember where you stuck stuff on the "priority" board but that doesn't affect the "Natural" board. But I suspect we won't need to.
Test Plan:
- Viewed and dragged a natural board.
- Viewed and dragged a priority board.
- Dragged within and between groups of 0, 1, and multiple items.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20265
2019-03-10 16:43:55 +01:00
|
|
|
}
|
Make drag-and-drop on workboards interact with priority column headers
Summary:
Ref T10333. Ref T8135. Depends on D20247. Allow users to drag-and-drop cards on a priority-sorted workboard under headers, even if the header has no other cards.
As of D20247, headers show up but they aren't really interactive. Now, you can drag cards directly underneath a header (instead of only between other cards). For example, if a column has only one "Wishlist" task, you may drag it under the "High", "Normal", or "Low" priority headers to select a specific priority.
(Some of this code still feels a little rough, but I think it will generalize once other types of sorting are available.)
Test Plan: Dragged cards within and between priority groups, saw appropriate priority edits applied in every case I could come up with.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333, T8135
Differential Revision: https://secure.phabricator.com/D20248
2019-03-05 16:38:35 +01:00
|
|
|
}
|
|
|
|
|
On Workboards, sort groups by "natural order", not subpriority
Summary:
Depends on D20263. Ref T10333. I want to add groups like "Assignee" to workboards. This means you may have several tasks grouped under, say, "Alice".
When you drag the bottom-most task under "Alice" to the top, what does that mean?
Today, the only grouping is "Priority", and it means "change the task's secret/hidden global subpriority". However, this seems to generally be a somewhat-bad answer, and is quite complex. It also doesn't make much sense for an author grouping, since one task can't really be "more assigned" to Alice than another task.
Users likely intend this operation to mean "move it, visually, with no other effects" -- that is, user intent is to shuffle sticky notes around on a board, not edit anything substantive. The meaning is probably something like "this is similar to other nearby tasks" or "maybe this is a good place to start", which we can't really capture with any top-level attribute.
We could extend "subpriority" and give tasks a secret/hidden "sub-assignment strength" and so on, but this seems like a bad road to walk down. We'll also run into trouble later when subproject columns may appear on the board, and a user could want to put a task in different positions on different subprojects, conceivably.
In the "Natural" order view, we already have what is probably a generally better approach for this: a task display order particular to the column, that just remembers where you put the sticky notes.
Move away from "subpriority", and toward a world where we mostly keep sticky notes where you stuck them and move them around only when we have to. With no grouping, we still sort by "natural" order, as before. With priority grouping, we now sort by `<priority, natural>`. When you drag stuff around inside a priority group, we update the natural order.
This means that moving cards around on a "priority" board will also move them around on a "natural" board, at least somewhat. I think this is okay. If it's not intuitive, we could give every ordering its own separate "natural" view, so we remember where you stuck stuff on the "priority" board but that doesn't affect the "Natural" board. But I suspect we won't need to.
Test Plan:
- Viewed and dragged a natural board.
- Viewed and dragged a priority board.
- Dragged within and between groups of 0, 1, and multiple items.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20265
2019-03-10 16:43:55 +01:00
|
|
|
var header_data;
|
|
|
|
var header_node = after_node;
|
|
|
|
while (header_node) {
|
|
|
|
header_data = JX.Stratcom.getData(header_node);
|
|
|
|
if (header_data.headerKey) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
header_node = header_node.previousSibling;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (header_data) {
|
2019-03-19 23:27:21 +01:00
|
|
|
header_key = header_data.headerKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
headerKey: header_key,
|
2019-03-25 17:37:02 +01:00
|
|
|
afterPHIDs: after_phids,
|
|
|
|
beforePHIDs: before_phids
|
2019-03-19 23:27:21 +01:00
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
_onmovecard: function(list, item, after_node, src_list) {
|
|
|
|
list.lock();
|
|
|
|
JX.DOM.alterClass(item, 'drag-sending', true);
|
|
|
|
|
|
|
|
var src_phid = JX.Stratcom.getData(src_list.getRootNode()).columnPHID;
|
|
|
|
var dst_phid = JX.Stratcom.getData(list.getRootNode()).columnPHID;
|
|
|
|
|
|
|
|
var item_phid = JX.Stratcom.getData(item).objectPHID;
|
|
|
|
var data = {
|
|
|
|
objectPHID: item_phid,
|
|
|
|
columnPHID: dst_phid,
|
|
|
|
order: this.getOrder()
|
|
|
|
};
|
|
|
|
|
When moving cards on workboards, treat before/after cards as optional hints, not strict requirements
Summary:
Depends on D20320. Ref T12175. Ref T13074. Currently, when you move a card between columns, the internal transaction takes exactly one `afterPHID` or `beforePHID` and moves the card before or after the specified card.
This is a fairly strict interpretation and causes a number of practical issues, mostly because the user/client view of the board may be out of date and the card they're dragging before or after may no longer exist: another user might have moved or hidden it between the last client update and the current time.
In T13074, we also run into a more subtle issue where a card that incorrectly appears in multiple columns fatals when dropped before or after itself.
In all cases, a better behavior is just to complete the move and accept that the position may not end up exactly like the user specified. We could prompt the user instead:
> You tried to drop this card after card X, but that card has moved since you last loaded the board. Reload the board and try again.
...but this is pretty hostile and probably rarely/never what the user wants.
Instead, accept a list of before/after PHIDs and just try them until we find one that works, or accept a default position if none work. In essentially all cases, this means that the move "just works" like users expect it to instead of fataling in a confusing/disruptive/undesirable (but "technically correct") way.
(A followup will make the client JS send more beforePHIDs/afterPHIDs so this works more often.)
We could eventually add a "strict" mode in the API or something if there's some bot/API use case for precise behavior here, but I suspect none exist today or are (ever?) likely to exist in the future.
Test Plan:
- (T13074) Inserted two conflicting rows to put a card on two columns on the same board. Dropped one version of it underneath the other version. Before: confusing fatal. After: cards merge sensibly into one consistent card.
- (T12175) Opened two views of a board. Moved card A to a different column on the first view. On the second view, dropped card B under card A (still showing in the old column). Before: confusing fatal. After: card ended up in the right column in approximately the right place, very reasonably.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T13074, T12175
Differential Revision: https://secure.phabricator.com/D20321
2019-03-25 18:12:10 +01:00
|
|
|
var context = this._getDropContext(after_node, item);
|
2019-03-25 17:37:02 +01:00
|
|
|
data.afterPHIDs = context.afterPHIDs.join(',');
|
|
|
|
data.beforePHIDs = context.beforePHIDs.join(',');
|
2019-03-19 23:27:21 +01:00
|
|
|
|
|
|
|
if (context.headerKey) {
|
|
|
|
var properties = this.getHeaderTemplate(context.headerKey)
|
|
|
|
.getEditProperties();
|
|
|
|
data.header = JX.JSON.stringify(properties);
|
2016-02-10 14:59:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var visible_phids = [];
|
|
|
|
var column = this.getColumn(dst_phid);
|
|
|
|
for (var object_phid in column.getCards()) {
|
|
|
|
visible_phids.push(object_phid);
|
|
|
|
}
|
|
|
|
|
|
|
|
data.visiblePHIDs = visible_phids.join(',');
|
|
|
|
|
2019-03-21 21:37:43 +01:00
|
|
|
// If the user cancels the workflow (for example, by hitting an MFA
|
|
|
|
// prompt that they click "Cancel" on), put the card back where it was
|
|
|
|
// and reset the UI state.
|
|
|
|
var on_revert = JX.bind(
|
|
|
|
this,
|
|
|
|
this._revertCard,
|
|
|
|
list,
|
|
|
|
item,
|
|
|
|
src_phid,
|
|
|
|
dst_phid);
|
|
|
|
|
2019-03-25 17:37:02 +01:00
|
|
|
var after_phid = null;
|
|
|
|
if (data.afterPHIDs.length) {
|
|
|
|
after_phid = data.afterPHIDs[0];
|
|
|
|
}
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
var onupdate = JX.bind(
|
|
|
|
this,
|
|
|
|
this._oncardupdate,
|
|
|
|
list,
|
|
|
|
src_phid,
|
|
|
|
dst_phid,
|
2019-03-25 17:37:02 +01:00
|
|
|
after_phid);
|
2016-02-10 14:59:46 +01:00
|
|
|
|
|
|
|
new JX.Workflow(this.getController().getMoveURI(), data)
|
|
|
|
.setHandler(onupdate)
|
2019-03-21 21:37:43 +01:00
|
|
|
.setCloseHandler(on_revert)
|
2016-02-10 14:59:46 +01:00
|
|
|
.start();
|
|
|
|
},
|
|
|
|
|
2019-03-21 21:37:43 +01:00
|
|
|
_revertCard: function(list, item, src_phid, dst_phid) {
|
|
|
|
JX.DOM.alterClass(item, 'drag-sending', false);
|
|
|
|
|
|
|
|
var src_column = this.getColumn(src_phid);
|
|
|
|
var dst_column = this.getColumn(dst_phid);
|
|
|
|
|
|
|
|
src_column.markForRedraw();
|
|
|
|
dst_column.markForRedraw();
|
|
|
|
this._redrawColumns();
|
|
|
|
|
|
|
|
list.unlock();
|
|
|
|
},
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
_oncardupdate: function(list, src_phid, dst_phid, after_phid, response) {
|
|
|
|
this.updateCard(response);
|
|
|
|
|
2019-03-21 23:22:09 +01:00
|
|
|
var sounds = response.sounds || [];
|
|
|
|
for (var ii = 0; ii < sounds.length; ii++) {
|
|
|
|
JX.Sound.queue(sounds[ii]);
|
|
|
|
}
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
list.unlock();
|
|
|
|
},
|
|
|
|
|
2019-07-02 19:19:03 +02:00
|
|
|
updateCard: function(response) {
|
2016-02-10 14:59:46 +01:00
|
|
|
var columns = this.getColumns();
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
var column_phid;
|
|
|
|
var card_phid;
|
|
|
|
var card_data;
|
|
|
|
|
|
|
|
// The server may send us a full or partial update for a card. If we've
|
|
|
|
// received a full update, we're going to redraw the entire card and may
|
|
|
|
// need to change which columns it appears in.
|
2016-02-10 14:59:46 +01:00
|
|
|
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
// For a partial update, we've just received supplemental sorting or
|
|
|
|
// property information and do not need to perform a full redraw.
|
2016-02-10 14:59:46 +01:00
|
|
|
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
// When we reload card state, edit a card, or move a card, we get a full
|
|
|
|
// update for the card.
|
|
|
|
|
|
|
|
// Ween we move a card in a column, we may get a partial update for other
|
|
|
|
// visible cards in the column.
|
|
|
|
|
|
|
|
|
|
|
|
// Figure out which columns each card now appears in. For cards that
|
|
|
|
// have received a full update, we'll use this map to move them into
|
|
|
|
// the correct columns.
|
|
|
|
var update_map = {};
|
|
|
|
for (column_phid in response.columnMaps) {
|
|
|
|
var target_column = this.getColumn(column_phid);
|
2017-01-24 16:25:57 +01:00
|
|
|
|
2019-03-11 03:53:25 +01:00
|
|
|
if (!target_column) {
|
|
|
|
// If the column isn't visible, don't try to add a card to it.
|
|
|
|
continue;
|
2016-02-10 14:59:46 +01:00
|
|
|
}
|
2019-03-11 03:53:25 +01:00
|
|
|
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
var column_map = response.columnMaps[column_phid];
|
2016-02-10 14:59:46 +01:00
|
|
|
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
for (var ii = 0; ii < column_map.length; ii++) {
|
|
|
|
card_phid = column_map[ii];
|
|
|
|
if (!update_map[card_phid]) {
|
|
|
|
update_map[card_phid] = {};
|
|
|
|
}
|
|
|
|
update_map[card_phid][column_phid] = true;
|
2016-08-14 17:58:17 +02:00
|
|
|
}
|
2016-02-10 14:59:46 +01:00
|
|
|
}
|
|
|
|
|
Move "BoardResponseEngine" toward a more comprehensive update model
Summary:
Depends on D20639. Ref T4900. Currently, "BoardResponseEngine" has a `setObjectPHID()` method. This is called after edit operations to mean "we just edited object X, so we know it needs to be updated".
Move toward `setUpdatePHIDs(...)` in all cases, with `setUpdatePHIDs(array(the-object-we-just-edited))` as a special case of that. After this change, callers pass:
- An optional list of PHIDs they know need to be updated on the client. Today, this is always be a card we just edited (on edit/move flows), or a sort of made-up list of PHIDs for the moment (when you press "R"). In the future, the "R" endpoint will do a better job of figuring out a more realistic update set.
- An optional list of PHIDs currently visible on the client. This is used to update ordering details and mark cards for removal. This is currently passed by edit/move, but not by pressing "R" (it will be in the future).
- An optional list of objects. The "R" workflow has to load these anyway, so we can save a couple queries by letting callers pass them. For now, the edit/move flows still rely on the engine to figure out what it needs to load.
This does very little to actually change client behavior, it mostly just paves the way for the next update to the "R" workflow to make it handle add/remove cases properly.
Test Plan:
- Edited and moved cards on a workboard.
- Pressed "R" to reload a workboard.
Neither of these operations seem any worse off than they were before. They still don't fully work:
- When you edit a card and delete the current workboard project from it, it remains visible. This is also the behavior on `master`. This is sort of intentional since we don't necessarily want to make these cards suddenly disappear? Ideally, we would probably have some kind of "tombstone" state where the card can still be edited but can't be dragged, and the next explicit user interaction would clean up old tombstones. This interaction is very rare and I don't think it's particularly important to specialize.
- When a card is removed from the board, "R" can't currently figure out that it should be removed from the client. This is because the client does not yet pass a "visiblePHIDs" state. It will in an upcoming change.
- The "R" flow always sends a full set of card updates, and can not yet detect that some cards have not changed.
- There's a TODO, but some ordering stuff isn't handled yet.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20652
2019-07-17 19:12:39 +02:00
|
|
|
// Process card removals. These are cases where the client still sees
|
|
|
|
// a particular card on a board but it has been removed on the server.
|
|
|
|
for (card_phid in response.cards) {
|
|
|
|
card_data = response.cards[card_phid];
|
|
|
|
|
|
|
|
if (!card_data.remove) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (column_phid in columns) {
|
|
|
|
var column = columns[column_phid];
|
|
|
|
|
|
|
|
var card = column.getCard(card_phid);
|
|
|
|
if (card) {
|
|
|
|
column.removeCard(card_phid);
|
|
|
|
column.markForRedraw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
// Process partial updates for cards. This is supplemental data which
|
|
|
|
// we can just merge in without any special handling.
|
|
|
|
for (card_phid in response.cards) {
|
|
|
|
card_data = response.cards[card_phid];
|
Move "BoardResponseEngine" toward a more comprehensive update model
Summary:
Depends on D20639. Ref T4900. Currently, "BoardResponseEngine" has a `setObjectPHID()` method. This is called after edit operations to mean "we just edited object X, so we know it needs to be updated".
Move toward `setUpdatePHIDs(...)` in all cases, with `setUpdatePHIDs(array(the-object-we-just-edited))` as a special case of that. After this change, callers pass:
- An optional list of PHIDs they know need to be updated on the client. Today, this is always be a card we just edited (on edit/move flows), or a sort of made-up list of PHIDs for the moment (when you press "R"). In the future, the "R" endpoint will do a better job of figuring out a more realistic update set.
- An optional list of PHIDs currently visible on the client. This is used to update ordering details and mark cards for removal. This is currently passed by edit/move, but not by pressing "R" (it will be in the future).
- An optional list of objects. The "R" workflow has to load these anyway, so we can save a couple queries by letting callers pass them. For now, the edit/move flows still rely on the engine to figure out what it needs to load.
This does very little to actually change client behavior, it mostly just paves the way for the next update to the "R" workflow to make it handle add/remove cases properly.
Test Plan:
- Edited and moved cards on a workboard.
- Pressed "R" to reload a workboard.
Neither of these operations seem any worse off than they were before. They still don't fully work:
- When you edit a card and delete the current workboard project from it, it remains visible. This is also the behavior on `master`. This is sort of intentional since we don't necessarily want to make these cards suddenly disappear? Ideally, we would probably have some kind of "tombstone" state where the card can still be edited but can't be dragged, and the next explicit user interaction would clean up old tombstones. This interaction is very rare and I don't think it's particularly important to specialize.
- When a card is removed from the board, "R" can't currently figure out that it should be removed from the client. This is because the client does not yet pass a "visiblePHIDs" state. It will in an upcoming change.
- The "R" flow always sends a full set of card updates, and can not yet detect that some cards have not changed.
- There's a TODO, but some ordering stuff isn't handled yet.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20652
2019-07-17 19:12:39 +02:00
|
|
|
|
|
|
|
if (card_data.remove) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
Modularize workboard column orders
Summary:
Depends on D20267. Depends on D20268. Ref T10333. Currently, we support "Natural" and "Priority" orders, but a lot of the particulars are pretty hard-coded, including some logic in `ManiphestTask`.
Although it's not clear that we'll ever put other types of objects on workboards, it seems generally bad that you need to modify `ManiphestTask` to get a new ordering.
Pull the ordering logic out into a `ProjectColumnOrder` hierarchy instead, and let each ordering define the things it needs to work (name, icon, what headers look like, how different objects are sorted, and how to apply an edit when you drop an object under a header).
Then move the existing "Natural" and "Priority" orders into this new hierarchy.
This has a minor bug where using the "Edit" workflow to change a card's priority on a priority-ordered board doesn't fully refresh card/header order since the response isn't ordering-aware. I'll fix that in an upcoming change.
Test Plan: Grouped workboards by "Natural" and "Priority", dragged stuff around within and between columns, grepped for all touched symbols.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20269
2019-03-11 05:49:12 +01:00
|
|
|
var card_template = this.getCardTemplate(card_phid);
|
|
|
|
|
|
|
|
if (card_data.nodeHTMLTemplate) {
|
|
|
|
card_template.setNodeHTMLTemplate(card_data.nodeHTMLTemplate);
|
|
|
|
}
|
|
|
|
|
|
|
|
var order;
|
|
|
|
for (order in card_data.vectors) {
|
|
|
|
card_template.setSortVector(order, card_data.vectors[order]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (order in card_data.headers) {
|
|
|
|
card_template.setHeaderKey(order, card_data.headers[order]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var key in card_data.properties) {
|
|
|
|
card_template.setObjectProperty(key, card_data.properties[key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
// Process full updates for cards which we have a full update for. This
|
|
|
|
// may involve moving them between columns.
|
|
|
|
for (card_phid in response.cards) {
|
|
|
|
card_data = response.cards[card_phid];
|
|
|
|
|
|
|
|
if (!card_data.update) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (column_phid in columns) {
|
|
|
|
var column = columns[column_phid];
|
|
|
|
var card = column.getCard(card_phid);
|
|
|
|
|
|
|
|
if (card) {
|
|
|
|
card.redraw();
|
|
|
|
column.markForRedraw();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compare the server state to the client state, and add or remove
|
|
|
|
// cards on the client as necessary to synchronize them.
|
|
|
|
|
2019-07-24 19:14:22 +02:00
|
|
|
if (update_map[card_phid] && update_map[card_phid][column_phid]) {
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
if (!card) {
|
|
|
|
column.newCard(card_phid);
|
|
|
|
column.markForRedraw();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (card) {
|
|
|
|
column.removeCard(card_phid);
|
|
|
|
column.markForRedraw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var column_maps = response.columnMaps;
|
|
|
|
var natural_column;
|
|
|
|
for (var natural_phid in column_maps) {
|
|
|
|
natural_column = this.getColumn(natural_phid);
|
|
|
|
if (!natural_column) {
|
|
|
|
// Our view of the board may be out of date, so we might get back
|
|
|
|
// information about columns that aren't visible. Just ignore the
|
|
|
|
// position information for any columns we aren't displaying on the
|
|
|
|
// client.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
natural_column.setNaturalOrder(column_maps[natural_phid]);
|
|
|
|
}
|
|
|
|
|
Modularize workboard column orders
Summary:
Depends on D20267. Depends on D20268. Ref T10333. Currently, we support "Natural" and "Priority" orders, but a lot of the particulars are pretty hard-coded, including some logic in `ManiphestTask`.
Although it's not clear that we'll ever put other types of objects on workboards, it seems generally bad that you need to modify `ManiphestTask` to get a new ordering.
Pull the ordering logic out into a `ProjectColumnOrder` hierarchy instead, and let each ordering define the things it needs to work (name, icon, what headers look like, how different objects are sorted, and how to apply an edit when you drop an object under a header).
Then move the existing "Natural" and "Priority" orders into this new hierarchy.
This has a minor bug where using the "Edit" workflow to change a card's priority on a priority-ordered board doesn't fully refresh card/header order since the response isn't ordering-aware. I'll fix that in an upcoming change.
Test Plan: Grouped workboards by "Natural" and "Priority", dragged stuff around within and between columns, grepped for all touched symbols.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T10333
Differential Revision: https://secure.phabricator.com/D20269
2019-03-11 05:49:12 +01:00
|
|
|
var headers = response.headers;
|
|
|
|
for (var jj = 0; jj < headers.length; jj++) {
|
|
|
|
var header = headers[jj];
|
|
|
|
|
|
|
|
this.getHeaderTemplate(header.key)
|
|
|
|
.setOrder(header.order)
|
|
|
|
.setNodeHTMLTemplate(header.template)
|
|
|
|
.setVector(header.vector)
|
|
|
|
.setEditProperties(header.editProperties);
|
2016-02-10 22:53:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
this._redrawColumns();
|
|
|
|
},
|
|
|
|
|
|
|
|
_redrawColumns: function() {
|
|
|
|
var columns = this.getColumns();
|
|
|
|
for (var k in columns) {
|
|
|
|
if (columns[k].isMarkedForRedraw()) {
|
|
|
|
columns[k].redraw();
|
2016-02-10 14:59:46 +01:00
|
|
|
}
|
|
|
|
}
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
_reloadCards: function() {
|
When updating a workboard with "R", send the client visible set with version numbers
Summary:
Depends on D20652. Ref T4900. When the user presses "R", send a list of cards currently visible on the client and their version numbers.
On the server:
- Compare the client verisons to the server versions so we can skip updates for objects which have not changed. (For now, the client version is always "1" and the server version is always "2", so this doesn't do anything meaningful, and every card is always updated.)
- Compare the client visible set to the server visible set and "remove" any cards which have been removed from the board.
I believe this means that "R" always puts the board into the right state (except for some issues with client orderings not being fully handled yet). It's not tremendously efficient, but we can make versioning better (using the largest object transaction ID) to improve that and loading the page in the first place doesn't take all that long so even sending down the full visible set shouldn't be a huge problem.
Test Plan:
- In window A, removed a card from a board.
- In window B, pressed "R" and saw the removal reflected on the client.
- (Also added cards, edited cards, etc., and didn't catch anything exploding.)
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20653
2019-07-03 21:36:17 +02:00
|
|
|
var state = {};
|
|
|
|
|
|
|
|
var columns = this.getColumns();
|
|
|
|
for (var column_phid in columns) {
|
|
|
|
var cards = columns[column_phid].getCards();
|
|
|
|
for (var card_phid in cards) {
|
|
|
|
state[card_phid] = this.getCardTemplate(card_phid).getVersion();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var data = {
|
|
|
|
state: JX.JSON.stringify(state),
|
Make reloading workboards with "R" respect workboard ordering
Summary:
Depends on D20653. Ref T4900. Pass ordering details to the reload endpoint so it can give the client accurate ordering/header information in the response.
The removed comment mentions this, but here's why this is a difficult mess:
- In window A, view a board with "Group by: Owner" and no tasks owned by "Alice". Since "Alice" owns no tasks, this means the columns do not have an "Assigned to: Alice" header!
- In window B, edit task T and assign it to Alice.
- In window A, press "R".
Window A now not only needs to update to properly reflect the state of task T, it actually needs to draw a new "Assigned to: Alice" header in every column.
Fortunately, the "group by" code anticipates this being a big mess, is fairly careful about handling it, and the client can handle this state change and the actual code change here isn't too involved. This is just causing a lot of not-very-obvious indirect effects in the pipeline to handle these situations that need complex redraws.
Test Plan:
- After making various normal edits/creates/moves in window A, pressed "R" in window B. Saw ordering reflected correctly after sync.
- Went through the whole "Group by: Owner" + assign to unrepresented owner flow above. After pressing "R", saw "Assigned to: Alice" appear on the board.
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20654
2019-07-17 19:55:17 +02:00
|
|
|
order: this.getOrder()
|
When updating a workboard with "R", send the client visible set with version numbers
Summary:
Depends on D20652. Ref T4900. When the user presses "R", send a list of cards currently visible on the client and their version numbers.
On the server:
- Compare the client verisons to the server versions so we can skip updates for objects which have not changed. (For now, the client version is always "1" and the server version is always "2", so this doesn't do anything meaningful, and every card is always updated.)
- Compare the client visible set to the server visible set and "remove" any cards which have been removed from the board.
I believe this means that "R" always puts the board into the right state (except for some issues with client orderings not being fully handled yet). It's not tremendously efficient, but we can make versioning better (using the largest object transaction ID) to improve that and loading the page in the first place doesn't take all that long so even sending down the full visible set shouldn't be a huge problem.
Test Plan:
- In window A, removed a card from a board.
- In window B, pressed "R" and saw the removal reflected on the client.
- (Also added cards, edited cards, etc., and didn't catch anything exploding.)
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20653
2019-07-03 21:36:17 +02:00
|
|
|
};
|
|
|
|
|
Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.
Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.
However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.
In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.
Test Plan:
- Opened the same workboard in two windows.
- Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
- Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").
Reviewers: amckinley
Reviewed By: amckinley
Maniphest Tasks: T4900
Differential Revision: https://secure.phabricator.com/D20639
2019-07-02 19:33:13 +02:00
|
|
|
var on_reload = JX.bind(this, this._onReloadResponse);
|
|
|
|
|
|
|
|
new JX.Request(this.getController().getReloadURI(), on_reload)
|
|
|
|
.setData(data)
|
|
|
|
.send();
|
|
|
|
},
|
|
|
|
|
|
|
|
_onReloadResponse: function(response) {
|
|
|
|
this.updateCard(response);
|
2016-02-10 14:59:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|