2016-02-10 14:59:46 +01:00
|
|
|
/**
|
|
|
|
* @provides javelin-workboard-controller
|
|
|
|
* @requires javelin-install
|
|
|
|
* javelin-dom
|
|
|
|
* javelin-util
|
|
|
|
* javelin-vector
|
|
|
|
* javelin-stratcom
|
|
|
|
* javelin-workflow
|
|
|
|
* phabricator-drag-and-drop-file-upload
|
|
|
|
* javelin-workboard-board
|
|
|
|
* @javelin
|
|
|
|
*/
|
|
|
|
|
|
|
|
JX.install('WorkboardController', {
|
|
|
|
|
|
|
|
construct: function() {
|
|
|
|
this._boards = {};
|
|
|
|
},
|
|
|
|
|
|
|
|
properties: {
|
|
|
|
uploadURI: null,
|
|
|
|
coverURI: null,
|
|
|
|
moveURI: null,
|
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
|
|
|
reloadURI: null,
|
2016-02-10 14:59:46 +01:00
|
|
|
chunkThreshold: null
|
|
|
|
},
|
|
|
|
|
|
|
|
members: {
|
|
|
|
_boards: null,
|
|
|
|
|
|
|
|
_panOrigin: null,
|
|
|
|
_panNode: null,
|
|
|
|
_panX: null,
|
|
|
|
|
|
|
|
start: function() {
|
|
|
|
this._setupCoverImageHandlers();
|
|
|
|
this._setupPanHandlers();
|
|
|
|
this._setupEditHandlers();
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
newBoard: function(phid, node) {
|
|
|
|
var board = new JX.WorkboardBoard(this, phid, node);
|
|
|
|
this._boards[phid] = board;
|
|
|
|
return board;
|
|
|
|
},
|
|
|
|
|
|
|
|
_getBoard: function(board_phid) {
|
|
|
|
return this._boards[board_phid];
|
|
|
|
},
|
|
|
|
|
|
|
|
_setupCoverImageHandlers: function() {
|
|
|
|
if (!JX.PhabricatorDragAndDropFileUpload.isSupported()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var drop = new JX.PhabricatorDragAndDropFileUpload('project-card')
|
|
|
|
.setURI(this.getUploadURI())
|
|
|
|
.setChunkThreshold(this.getChunkThreshold());
|
|
|
|
|
|
|
|
drop.listen('didBeginDrag', function(node) {
|
|
|
|
JX.DOM.alterClass(node, 'phui-workcard-upload-target', true);
|
|
|
|
});
|
|
|
|
|
|
|
|
drop.listen('didEndDrag', function(node) {
|
|
|
|
JX.DOM.alterClass(node, 'phui-workcard-upload-target', false);
|
|
|
|
});
|
|
|
|
|
|
|
|
drop.listen('didUpload', JX.bind(this, this._oncoverupload));
|
|
|
|
|
|
|
|
drop.start();
|
|
|
|
},
|
|
|
|
|
|
|
|
_oncoverupload: function(file) {
|
|
|
|
var node = file.getTargetNode();
|
|
|
|
|
|
|
|
var board = this._getBoardFromNode(node);
|
|
|
|
|
|
|
|
var column_node = JX.DOM.findAbove(node, 'ul', 'project-column');
|
|
|
|
var column_phid = JX.Stratcom.getData(column_node).columnPHID;
|
|
|
|
var column = board.getColumn(column_phid);
|
|
|
|
|
|
|
|
var data = {
|
|
|
|
boardPHID: board.getPHID(),
|
|
|
|
objectPHID: JX.Stratcom.getData(node).objectPHID,
|
|
|
|
filePHID: file.getPHID(),
|
|
|
|
visiblePHIDs: column.getCardPHIDs()
|
|
|
|
};
|
|
|
|
|
|
|
|
new JX.Workflow(this.getCoverURI(), data)
|
|
|
|
.setHandler(JX.bind(board, board.updateCard))
|
|
|
|
.start();
|
|
|
|
},
|
|
|
|
|
|
|
|
_getBoardFromNode: function(node) {
|
|
|
|
var board_node = JX.DOM.findAbove(node, 'div', 'jx-workboard');
|
|
|
|
var board_phid = JX.Stratcom.getData(board_node).boardPHID;
|
|
|
|
return this._getBoard(board_phid);
|
|
|
|
},
|
|
|
|
|
|
|
|
_setupPanHandlers: function() {
|
|
|
|
var mousedown = JX.bind(this, this._onpanmousedown);
|
|
|
|
var mousemove = JX.bind(this, this._onpanmousemove);
|
|
|
|
var mouseup = JX.bind(this, this._onpanmouseup);
|
|
|
|
|
|
|
|
JX.Stratcom.listen('mousedown', 'workboard-shadow', mousedown);
|
|
|
|
JX.Stratcom.listen('mousemove', null, mousemove);
|
|
|
|
JX.Stratcom.listen('mouseup', null, mouseup);
|
|
|
|
},
|
|
|
|
|
|
|
|
_onpanmousedown: function(e) {
|
|
|
|
if (!JX.Device.isDesktop()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e.getNode('workpanel')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (JX.Stratcom.pass()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
e.kill();
|
|
|
|
|
|
|
|
this._panOrigin = JX.$V(e);
|
|
|
|
this._panNode = e.getNode('workboard-shadow');
|
|
|
|
this._panX = this._panNode.scrollLeft;
|
|
|
|
},
|
|
|
|
|
|
|
|
_onpanmousemove: function(e) {
|
|
|
|
if (!this._panOrigin) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var cursor = JX.$V(e);
|
|
|
|
this._panNode.scrollLeft = this._panX + (this._panOrigin.x - cursor.x);
|
|
|
|
},
|
|
|
|
|
|
|
|
_onpanmouseup: function() {
|
|
|
|
this._panOrigin = null;
|
|
|
|
},
|
|
|
|
|
|
|
|
_setupEditHandlers: function() {
|
|
|
|
var onadd = JX.bind(this, this._onaddcard);
|
|
|
|
var onedit = JX.bind(this, this._oneditcard);
|
|
|
|
|
|
|
|
JX.Stratcom.listen('click', 'column-add-task', onadd);
|
|
|
|
JX.Stratcom.listen('click', 'edit-project-card', onedit);
|
|
|
|
},
|
|
|
|
|
|
|
|
_onaddcard: function(e) {
|
2023-03-18 14:57:15 +01:00
|
|
|
|
|
|
|
// Allow CTRL+click and maybe other actions
|
|
|
|
if(!e.isNormalMouseEvent()) {
|
|
|
|
e.stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
// We want the 'boards-dropdown-menu' behavior to see this event and
|
|
|
|
// close the dropdown, but don't want to follow the link.
|
|
|
|
e.prevent();
|
|
|
|
|
|
|
|
var column_data = e.getNodeData('column-add-task');
|
|
|
|
var column_phid = column_data.columnPHID;
|
|
|
|
|
2016-02-11 18:51:32 +01:00
|
|
|
var board_phid = column_data.boardPHID;
|
2016-02-10 14:59:46 +01:00
|
|
|
var board = this._getBoard(board_phid);
|
|
|
|
var column = board.getColumn(column_phid);
|
|
|
|
|
|
|
|
var request_data = {
|
|
|
|
responseType: 'card',
|
|
|
|
columnPHID: column.getPHID(),
|
2016-02-11 18:51:32 +01:00
|
|
|
projects: column_data.projectPHID,
|
2016-02-10 14:59:46 +01:00
|
|
|
visiblePHIDs: column.getCardPHIDs(),
|
|
|
|
order: board.getOrder()
|
|
|
|
};
|
|
|
|
|
2017-03-02 02:13:36 +01:00
|
|
|
new JX.Workflow(column_data.createURI, request_data)
|
2016-02-10 14:59:46 +01:00
|
|
|
.setHandler(JX.bind(board, board.updateCard))
|
|
|
|
.start();
|
|
|
|
},
|
|
|
|
|
|
|
|
_oneditcard: function(e) {
|
2023-03-18 14:57:15 +01:00
|
|
|
|
|
|
|
// Allow CTRL+click and maybe other actions
|
|
|
|
if(!e.isNormalMouseEvent()) {
|
|
|
|
e.stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-02-10 14:59:46 +01:00
|
|
|
e.kill();
|
|
|
|
|
|
|
|
var column_node = e.getNode('project-column');
|
|
|
|
var column_phid = JX.Stratcom.getData(column_node).columnPHID;
|
|
|
|
|
|
|
|
var board = this._getBoardFromNode(column_node);
|
|
|
|
var column = board.getColumn(column_phid);
|
|
|
|
|
|
|
|
var request_data = {
|
|
|
|
responseType: 'card',
|
|
|
|
columnPHID: column.getPHID(),
|
|
|
|
visiblePHIDs: column.getCardPHIDs(),
|
|
|
|
order: board.getOrder()
|
|
|
|
};
|
|
|
|
|
|
|
|
new JX.Workflow(e.getNode('tag:a').href, request_data)
|
|
|
|
.setHandler(JX.bind(board, board.updateCard))
|
|
|
|
.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|