cryptpad/www/kanban/inner.js

383 lines
14 KiB
JavaScript
Raw Normal View History

2018-04-01 16:52:21 +00:00
define([
'jquery',
2018-05-22 16:22:25 +00:00
'json.sortify',
2018-04-01 16:52:21 +00:00
'/bower_components/nthen/index.js',
'/common/sframe-common.js',
'/common/sframe-app-framework.js',
'/common/common-util.js',
'/common/common-hash.js',
2018-05-16 10:22:43 +00:00
'/common/common-interface.js',
'/common/modes.js',
2018-04-01 16:52:21 +00:00
'/customize/messages.js',
'/kanban/jkanban.js',
'css!/kanban/jkanban.css',
2018-04-01 16:52:21 +00:00
], function (
$,
2018-05-22 16:22:25 +00:00
Sortify,
2018-04-01 16:52:21 +00:00
nThen,
SFCommon,
Framework,
Util,
Hash,
2018-05-16 10:22:43 +00:00
UI,
Modes,
2018-05-16 10:22:43 +00:00
Messages)
{
2018-05-17 08:27:16 +00:00
var verbose = function (x) { console.log(x); };
verbose = function () {}; // comment out to enable verbose logging
2018-05-22 16:22:25 +00:00
var addRemoveItemButton = function (framework, kanban) {
if (framework.isReadOnly() || framework.isLocked()) { return; }
2018-05-22 16:22:25 +00:00
var $container = $(kanban.element);
$container.find('.kanban-remove-item').remove();
$container.find('.kanban-board .kanban-item').each(function (i, el) {
var pos = kanban.findElementPosition(el);
var board = kanban.options.boards.find(function (b) {
return b.id === $(el.parentNode.parentNode).attr('data-id');
});
2018-05-23 12:24:18 +00:00
$('<button>', {
'class': 'kanban-remove-item btn btn-default',
title: Messages.kanban_removeItem
}).click(function (e) {
2018-05-22 16:22:25 +00:00
e.stopPropagation();
board.item.splice(pos, 1);
$(el).remove();
kanban.onChange();
}).text('❌').appendTo($(el));
2018-05-22 16:22:25 +00:00
});
};
// Kanban code
var initKanban = function (framework, boards) {
2018-05-16 14:45:16 +00:00
var defaultBoards = [{
2018-05-16 10:22:43 +00:00
"id": "todo",
2018-05-16 14:45:16 +00:00
"title": Messages.kanban_todo,
2018-05-16 10:22:43 +00:00
"color": "blue",
2018-05-16 14:45:16 +00:00
"item": [{
"title": Messages._getKey('kanban_item', [1])
}, {
"title": Messages._getKey('kanban_item', [2])
}]
2018-05-16 10:22:43 +00:00
}, {
"id": "working",
2018-05-16 14:45:16 +00:00
"title": Messages.kanban_working,
2018-05-16 10:22:43 +00:00
"color": "orange",
"item": [{
2018-05-16 14:45:16 +00:00
"title": Messages._getKey('kanban_item', [3])
2018-05-16 10:22:43 +00:00
}, {
2018-05-16 14:45:16 +00:00
"title": Messages._getKey('kanban_item', [4])
2018-05-16 10:22:43 +00:00
}]
}, {
"id": "done",
2018-05-16 14:45:16 +00:00
"title": Messages.kanban_done,
2018-05-16 10:22:43 +00:00
"color": "green",
"item": [{
2018-05-16 14:45:16 +00:00
"title": Messages._getKey('kanban_item', [5])
2018-05-16 10:22:43 +00:00
}, {
2018-05-16 14:45:16 +00:00
"title": Messages._getKey('kanban_item', [6])
2018-05-16 10:22:43 +00:00
}]
}];
2018-04-01 16:52:21 +00:00
2018-05-16 10:22:43 +00:00
if (!boards) {
2018-05-17 08:27:16 +00:00
verbose("Initializing with default boards content");
boards = defaultBoards;
} else {
2018-05-17 08:27:16 +00:00
verbose("Initializing with boards content " + boards);
}
2018-04-01 16:52:21 +00:00
// Remove any existing elements
$(".kanban-container-outer").remove();
2018-05-16 17:28:30 +00:00
var getInput = function () {
return $('<input>', {
'type': 'text',
'id': 'kanban-edit',
'size': '30'
});
};
2018-05-16 10:22:43 +00:00
var kanban = new window.jKanban({
element: '#cp-app-kanban-content',
gutter: '15px',
widthBoard: '300px',
buttonContent: '❌',
readOnly: framework.isReadOnly(),
onChange: function () {
2018-05-17 08:27:16 +00:00
verbose("Board object has changed");
framework.localChange();
2018-05-22 16:22:25 +00:00
if (kanban) {
addRemoveItemButton(framework, kanban);
}
},
click: function (el) {
if (framework.isReadOnly() || framework.isLocked()) { return; }
if (kanban.inEditMode) {
2018-05-17 08:27:16 +00:00
verbose("An edit is already active");
return;
}
kanban.inEditMode = true;
$(el).find('button').remove();
var name = $(el).text();
$(el).html('');
2018-05-16 17:28:30 +00:00
var $input = getInput().val(name).appendTo(el).focus();
$input[0].select();
var save = function () {
// Store the value
var name = $input.val();
// Remove the input
$(el).text(name);
2018-05-16 17:28:30 +00:00
// Save the value for the correct board
var board = $(el.parentNode.parentNode).attr("data-id");
var pos = kanban.findElementPosition(el);
kanban.getBoardJSON(board).item[pos].title = name;
kanban.onChange();
2018-05-16 17:28:30 +00:00
// Unlock edit mode
kanban.inEditMode = false;
2018-05-16 17:28:30 +00:00
};
$input.blur(save);
$input.keydown(function (e) {
if (e.which === 13) {
e.preventDefault();
e.stopPropagation();
save();
return;
}
if (e.which === 27) {
e.preventDefault();
e.stopPropagation();
$(el).text(name);
kanban.inEditMode = false;
addRemoveItemButton(framework, kanban);
2018-05-16 17:28:30 +00:00
return;
}
});
2018-04-01 16:52:21 +00:00
},
2018-05-16 17:28:30 +00:00
boardTitleClick: function (el, e) {
e.stopPropagation();
if (framework.isReadOnly() || framework.isLocked()) { return; }
if (kanban.inEditMode) {
2018-05-17 08:27:16 +00:00
verbose("An edit is already active");
return;
}
kanban.inEditMode = true;
var name = $(el).text();
$(el).html('');
2018-05-16 17:28:30 +00:00
var $input = getInput().val(name).appendTo(el).focus();
$input[0].select();
var save = function () {
// Store the value
var name = $input.val();
// Remove the input
$(el).text(name);
2018-05-16 17:28:30 +00:00
// Save the value for the correct board
var board = $(el.parentNode.parentNode).attr("data-id");
kanban.getBoardJSON(board).title = name;
kanban.onChange();
2018-05-16 17:28:30 +00:00
// Unlock edit mode
kanban.inEditMode = false;
2018-05-16 17:28:30 +00:00
};
$input.blur(save);
$input.keydown(function (e) {
if (e.which === 13) {
e.preventDefault();
e.stopPropagation();
save();
return;
}
if (e.which === 27) {
e.preventDefault();
e.stopPropagation();
$(el).text(name);
kanban.inEditMode = false;
return;
}
});
},
2018-05-16 10:22:43 +00:00
colorClick: function (el) {
if (framework.isReadOnly() || framework.isLocked()) { return; }
2018-05-17 08:27:16 +00:00
verbose("in color click");
var board = $(el.parentNode).attr("data-id");
var boardJSON = kanban.getBoardJSON(board);
var currentColor = boardJSON.color;
2018-05-17 08:27:16 +00:00
verbose("Current color " + currentColor);
var index = kanban.options.colors.findIndex(function (element) {
2018-05-16 10:22:43 +00:00
return (element === currentColor);
}) + 1;
2018-05-17 08:27:16 +00:00
verbose("Next index " + index);
2018-05-16 10:22:43 +00:00
if (index >= kanban.options.colors.length) { index = 0; }
var nextColor = kanban.options.colors[index];
2018-05-17 08:27:16 +00:00
verbose("Next color " + nextColor);
boardJSON.color = nextColor;
$(el).removeClass("kanban-header-" + currentColor);
$(el).addClass("kanban-header-" + nextColor);
kanban.onChange();
},
2018-05-22 16:22:25 +00:00
buttonClick: function (el, boardId, e) {
e.stopPropagation();
if (framework.isReadOnly() || framework.isLocked()) { return; }
2018-05-16 14:45:16 +00:00
UI.confirm(Messages.kanban_deleteBoard, function (yes) {
2018-05-16 10:22:43 +00:00
if (!yes) { return; }
2018-05-17 08:27:16 +00:00
verbose("Delete board");
2018-05-22 16:22:25 +00:00
//var boardName = $(el.parentNode.parentNode).attr("data-id");
2018-05-16 10:22:43 +00:00
for (var index in kanban.options.boards) {
2018-05-22 16:22:25 +00:00
if (kanban.options.boards[index].id === boardId) {
break;
}
index++;
}
kanban.options.boards.splice(index, 1);
2018-05-22 16:22:25 +00:00
kanban.removeBoard(boardId);
kanban.onChange();
2018-05-16 10:22:43 +00:00
});
},
2018-05-22 16:22:25 +00:00
addItemClick: function (el) {
if (framework.isReadOnly() || framework.isLocked()) { return; }
2018-05-16 17:28:30 +00:00
if (kanban.inEditMode) {
2018-05-17 08:27:16 +00:00
verbose("An edit is already active");
2018-05-16 17:28:30 +00:00
return;
}
kanban.inEditMode = true;
// create a form to enter element
2018-05-22 16:22:25 +00:00
var boardId = $(el.parentNode.parentNode).attr("data-id");
2018-05-16 17:28:30 +00:00
var $item = $('<div>', {'class': 'kanban-item'});
var $input = getInput().val(name).appendTo($item);
kanban.addForm(boardId, $item[0]);
$input.focus();
var save = function () {
$item.remove();
2018-05-22 16:22:25 +00:00
kanban.inEditMode = false;
if (!$input.val()) { return; }
kanban.addElement(boardId, {
2018-05-16 17:28:30 +00:00
"title": $input.val(),
2018-05-16 10:22:43 +00:00
});
};
2018-05-16 17:28:30 +00:00
$input.blur(save);
$input.keydown(function (e) {
if (e.which === 13) {
e.preventDefault();
e.stopPropagation();
save();
return;
}
if (e.which === 27) {
e.preventDefault();
e.stopPropagation();
kanban.inEditMode = false;
return;
}
});
},
addItemButton: true,
2018-05-23 12:24:18 +00:00
boards: boards
});
2018-04-01 16:52:21 +00:00
var addBoardDefault = document.getElementById('kanban-addboard');
2018-05-23 12:24:18 +00:00
$(addBoardDefault).attr('title', Messages.kanban_addBoard);
addBoardDefault.addEventListener('click', function () {
if (framework.isReadOnly()) { return; }
var counter = 1;
2018-05-16 10:22:43 +00:00
// Get the new board id
2018-05-22 16:22:25 +00:00
var boardExists = function (b) { return b.id === "board" + counter; };
while (kanban.options.boards.some(boardExists)) { counter++; }
2018-04-01 16:52:21 +00:00
2018-05-16 10:22:43 +00:00
kanban.addBoards([{
"id": "board" + counter,
2018-05-16 14:45:16 +00:00
"title": Messages.kanban_newBoard,
2018-05-16 10:22:43 +00:00
"color": "yellow",
"item": [{
2018-05-16 14:45:16 +00:00
"title": Messages._getKey('kanban_item', [1]),
2018-05-16 10:22:43 +00:00
}]
}]);
kanban.onChange();
});
2018-04-01 16:52:21 +00:00
return kanban;
};
2018-04-01 16:52:21 +00:00
2018-05-23 12:24:18 +00:00
var mkHelpMenu = function (framework) {
var $toolbarContainer = $('#cp-app-kanban-container');
var helpMenu = framework._.sfCommon.createHelpMenu(['kanban']);
$toolbarContainer.prepend(helpMenu.menu);
framework._.toolbar.$drawer.append(helpMenu.button);
};
// Start of the main loop
var andThen2 = function (framework) {
2018-04-01 16:52:21 +00:00
2018-05-22 16:22:25 +00:00
var kanban;
var $container = $('#cp-app-kanban-content');
2018-05-23 12:24:18 +00:00
mkHelpMenu(framework);
if (framework.isReadOnly()) {
$container.addClass('cp-app-readonly');
}
framework.onEditableChange(function (unlocked) {
if (framework.isReadOnly()) { return; }
if (unlocked) {
addRemoveItemButton(framework, kanban);
kanban.options.readOnly = false;
return void $container.removeClass('cp-app-readonly');
}
kanban.options.readOnly = true;
$container.addClass('cp-app-readonly');
});
2018-04-01 16:52:21 +00:00
framework.onContentUpdate(function (newContent) {
2018-05-22 16:22:25 +00:00
// Init if needed
if (!kanban) {
kanban = initKanban(framework, (newContent || {}).content);
addRemoveItemButton(framework, kanban);
return;
}
// Need to update the content
2018-05-17 08:27:16 +00:00
verbose("Content should be updated to " + newContent);
var currentContent = kanban.getBoardsJSON();
var remoteContent = newContent.content;
2018-05-16 10:22:43 +00:00
2018-05-22 16:22:25 +00:00
if (Sortify(currentContent) !== Sortify(remoteContent)) {
// reinit kanban (TODO: optimize to diff only)
verbose("Content is different.. Applying content");
kanban.setBoards(remoteContent);
kanban.inEditMode = false;
2018-05-22 16:22:25 +00:00
addRemoveItemButton(framework, kanban);
}
2018-04-01 16:52:21 +00:00
});
framework.setContentGetter(function () {
2018-05-22 16:22:25 +00:00
if (!kanban) { return; }
var content = kanban.getBoardsJSON();
2018-05-17 08:27:16 +00:00
verbose("Content current value is " + content);
return {
content: content
};
2018-04-01 16:52:21 +00:00
});
2018-05-16 10:22:43 +00:00
framework.onReady(function () {
$("#cp-app-kanban-content").focus();
});
2018-04-01 16:52:21 +00:00
framework.start();
2018-04-01 16:52:21 +00:00
};
var main = function () {
// var framework;
2018-04-01 16:52:21 +00:00
nThen(function (waitFor) {
// Framework initialization
Framework.create({
toolbarContainer: '#cme_toolbox',
contentContainer: '#cp-app-kanban-editor',
2018-05-16 10:22:43 +00:00
}, waitFor(function (framework) {
andThen2(framework);
2018-04-01 16:52:21 +00:00
}));
});
};
main();
});