Summary: First stab at a batch editor for Maniphest. Basically, you can select a group of tasks and then import them into the "batch" interface, where you can edit all of them at once. High level goal is to make it easier for users in PM/filer/support/QA roles to deal with large numbers of tasks quickly. This implementation has a few major limitations: - The only available actions are "add projects" and "remove projects". - There is no review / undo / log stuff. - All the changes are applied in-process, which may not scale terribly well. However, the immediate need is just around projects and this seemed like a reasonable place to draw the line for a minimal useful version of the tool. Test Plan: Used batch editor to add and remove projects from groups of tasks. Reviewers: btrahan, yairlivne Reviewed By: btrahan CC: aran, epriestley, sandra Maniphest Tasks: T441 Differential Revision: https://secure.phabricator.com/D1680
115 lines
2.5 KiB
JavaScript
115 lines
2.5 KiB
JavaScript
/**
|
|
* @provides javelin-behavior-maniphest-batch-editor
|
|
* @requires javelin-behavior
|
|
* javelin-dom
|
|
* javelin-util
|
|
* phabricator-prefab
|
|
* multirow-row-manager
|
|
* javelin-tokenizer
|
|
* javelin-typeahead-preloaded-source
|
|
* javelin-typeahead
|
|
* javelin-json
|
|
*/
|
|
|
|
JX.behavior('maniphest-batch-editor', function(config) {
|
|
|
|
var root = JX.$(config.root);
|
|
var editor_table = JX.DOM.find(root, 'table', 'maniphest-batch-actions');
|
|
var manager = new JX.MultirowRowManager(editor_table);
|
|
var action_rows = [];
|
|
|
|
addRow({});
|
|
|
|
function renderRow(data) {
|
|
|
|
var action_select = JX.Prefab.renderSelect(
|
|
{
|
|
'add_project': 'Add Projects',
|
|
'remove_project' : 'Remove Projects'/*,
|
|
'priority': 'Change Priority',
|
|
'add_comment': 'Comment',
|
|
'status': 'Open / Close',
|
|
'assign': 'Assign'*/
|
|
});
|
|
|
|
var tokenizer = build_tokenizer(config.sources.project)
|
|
|
|
var r = [];
|
|
r.push([null, action_select]);
|
|
r.push(['batch-editor-input', tokenizer.template]);
|
|
|
|
for (var ii = 0; ii < r.length; ii++) {
|
|
r[ii] = JX.$N('td', {className : r[ii][0]}, r[ii][1]);
|
|
}
|
|
|
|
return {
|
|
nodes : r,
|
|
dataCallback : function() {
|
|
return {
|
|
action: action_select.value,
|
|
value: JX.keys(tokenizer.object.getTokens())
|
|
};
|
|
}
|
|
};
|
|
}
|
|
|
|
function onaddaction(e) {
|
|
e.kill();
|
|
addRow({});
|
|
}
|
|
|
|
function addRow(info) {
|
|
var data = renderRow(info);
|
|
var row = manager.addRow(data.nodes);
|
|
var id = manager.getRowID(row);
|
|
|
|
action_rows[id] = data.dataCallback;
|
|
}
|
|
|
|
function onsubmit(e) {
|
|
var input = JX.$(config.input);
|
|
|
|
var actions = [];
|
|
for (var k in action_rows) {
|
|
actions.push(action_rows[k]());
|
|
}
|
|
|
|
input.value = JX.JSON.stringify(actions);
|
|
}
|
|
|
|
JX.DOM.listen(
|
|
root,
|
|
'click',
|
|
'add-action',
|
|
onaddaction);
|
|
|
|
JX.DOM.listen(
|
|
root,
|
|
'submit',
|
|
null,
|
|
onsubmit);
|
|
|
|
manager.listen(
|
|
'row-removed',
|
|
function(row_id) {
|
|
delete action_rows[row_id];
|
|
});
|
|
|
|
function build_tokenizer(source) {
|
|
var template = JX.$N('div', JX.$H(config.tokenizerTemplate)).firstChild;
|
|
template.id = '';
|
|
var datasource = new JX.TypeaheadPreloadedSource(source);
|
|
var typeahead = new JX.Typeahead(template);
|
|
typeahead.setDatasource(datasource);
|
|
var tokenizer = new JX.Tokenizer(template);
|
|
tokenizer.setTypeahead(typeahead);
|
|
tokenizer.start();
|
|
|
|
return {
|
|
object: tokenizer,
|
|
template: template
|
|
};
|
|
}
|
|
|
|
});
|