Fix UI and realtime issues with kanban

This commit is contained in:
yflory 2018-05-22 18:22:25 +02:00
parent 365b32d378
commit f0512bbb1d
3 changed files with 74 additions and 37 deletions

View File

@ -84,16 +84,27 @@
.tools_unselectable(); .tools_unselectable();
} }
.kanban-removeboard { .kanban-additem, .kanban-remove-item {
float: right; float: right;
margin: 10px; background: #EEE;
padding: .25rem .5rem;
line-height: 1;
&:hover {
background: transparent;
}
/* margin: 10px;
padding: 3px; padding: 3px;
width: 30px; width: 30px;
text-align: center; text-align: center;
background: #eee; background: #eee;
font-weight: bold; font-weight: bold;
cursor: pointer; cursor: pointer;
.tools_unselectable(); .tools_unselectable(); */
}
.kanban-additem {
margin-bottom: 5px;
margin-right: 5px;
} }
.kanban-header-yellow { .kanban-header-yellow {

View File

@ -1,5 +1,6 @@
define([ define([
'jquery', 'jquery',
'json.sortify',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/common/sframe-common.js', '/common/sframe-common.js',
'/common/sframe-app-framework.js', '/common/sframe-app-framework.js',
@ -12,6 +13,7 @@ define([
'css!/kanban/jkanban.css', 'css!/kanban/jkanban.css',
], function ( ], function (
$, $,
Sortify,
nThen, nThen,
SFCommon, SFCommon,
Framework, Framework,
@ -25,6 +27,23 @@ define([
var verbose = function (x) { console.log(x); }; var verbose = function (x) { console.log(x); };
verbose = function () {}; // comment out to enable verbose logging verbose = function () {}; // comment out to enable verbose logging
var addRemoveItemButton = function (framework, kanban) {
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');
});
$('<button>', {'class': 'kanban-remove-item btn btn-default'}).click(function (e) {
e.stopPropagation();
board.item.splice(pos, 1);
$(el).remove();
kanban.onChange();
}).text('🗙').appendTo($(el));
});
};
// Kanban code // Kanban code
var initKanban = function (framework, boards) { var initKanban = function (framework, boards) {
var defaultBoards = [{ var defaultBoards = [{
@ -78,9 +97,13 @@ define([
element: '#cp-app-kanban-content', element: '#cp-app-kanban-content',
gutter: '15px', gutter: '15px',
widthBoard: '300px', widthBoard: '300px',
buttonContent: '🗙',
onChange: function () { onChange: function () {
verbose("Board object has changed"); verbose("Board object has changed");
framework.localChange(); framework.localChange();
if (kanban) {
addRemoveItemButton(framework, kanban);
}
}, },
click: function (el) { click: function (el) {
if (kanban.inEditMode) { if (kanban.inEditMode) {
@ -182,40 +205,42 @@ define([
kanban.onChange(); kanban.onChange();
}, },
removeClick: function (el) { buttonClick: function (el, boardId, e) {
e.stopPropagation();
UI.confirm(Messages.kanban_deleteBoard, function (yes) { UI.confirm(Messages.kanban_deleteBoard, function (yes) {
if (!yes) { return; } if (!yes) { return; }
verbose("Delete board"); verbose("Delete board");
var boardName = $(el.parentNode.parentNode).attr("data-id"); //var boardName = $(el.parentNode.parentNode).attr("data-id");
for (var index in kanban.options.boards) { for (var index in kanban.options.boards) {
if (kanban.options.boards[index].id === boardName) { if (kanban.options.boards[index].id === boardId) {
break; break;
} }
index++; index++;
} }
kanban.options.boards.splice(index, 1); kanban.options.boards.splice(index, 1);
kanban.removeBoard(boardName); kanban.removeBoard(boardId);
kanban.onChange(); kanban.onChange();
}); });
}, },
buttonClick: function (el, boardId, e) { addItemClick: function (el) {
e.stopPropagation();
if (kanban.inEditMode) { if (kanban.inEditMode) {
verbose("An edit is already active"); verbose("An edit is already active");
return; return;
} }
kanban.inEditMode = true; kanban.inEditMode = true;
// create a form to enter element // create a form to enter element
var boardId = $(el.parentNode.parentNode).attr("data-id");
var $item = $('<div>', {'class': 'kanban-item'}); var $item = $('<div>', {'class': 'kanban-item'});
var $input = getInput().val(name).appendTo($item); var $input = getInput().val(name).appendTo($item);
kanban.addForm(boardId, $item[0]); kanban.addForm(boardId, $item[0]);
$input.focus(); $input.focus();
var save = function () { var save = function () {
$item.remove(); $item.remove();
kanban.inEditMode = false;
if (!$input.val()) { return; }
kanban.addElement(boardId, { kanban.addElement(boardId, {
"title": $input.val(), "title": $input.val(),
}); });
kanban.inEditMode = false;
}; };
$input.blur(save); $input.blur(save);
$input.keydown(function (e) { $input.keydown(function (e) {
@ -236,7 +261,7 @@ define([
}, },
addItemButton: true, addItemButton: true,
boards: boards, boards: boards,
dragcancelEl: function (el, boardId) { /*dragcancelEl: function (el, boardId) {
var pos = kanban.findElementPosition(el); var pos = kanban.findElementPosition(el);
UI.confirm(Messages.kanban_deleteItem, function (yes) { UI.confirm(Messages.kanban_deleteItem, function (yes) {
if (!yes) { return; } if (!yes) { return; }
@ -251,7 +276,7 @@ define([
$(el).remove(); $(el).remove();
kanban.onChange(); kanban.onChange();
}); });
} }*/
}); });
var addBoardDefault = document.getElementById('kanban-addboard'); var addBoardDefault = document.getElementById('kanban-addboard');
@ -259,9 +284,8 @@ define([
var counter = 1; var counter = 1;
// Get the new board id // Get the new board id
while (kanban.options.boards.indexOf("board" + counter) !== -1) { var boardExists = function (b) { return b.id === "board" + counter; };
counter++; while (kanban.options.boards.some(boardExists)) { counter++; }
}
kanban.addBoards([{ kanban.addBoards([{
"id": "board" + counter, "id": "board" + counter,
@ -280,24 +304,32 @@ define([
// Start of the main loop // Start of the main loop
var andThen2 = function (framework) { var andThen2 = function (framework) {
var kanban = initKanban(framework); var kanban;
framework.onContentUpdate(function (newContent) { framework.onContentUpdate(function (newContent) {
// Init if needed
if (!kanban) {
kanban = initKanban(framework, (newContent || {}).content);
addRemoveItemButton(framework, kanban);
return;
}
// Need to update the content // Need to update the content
verbose("Content should be updated to " + newContent); verbose("Content should be updated to " + newContent);
var currentContent = kanban.getBoardsJSON(); var currentContent = kanban.getBoardsJSON();
var remoteContent = newContent.content; var remoteContent = newContent.content;
if (currentContent !== remoteContent) { if (Sortify(currentContent) !== Sortify(remoteContent)) {
// reinit kanban (TODO: optimize to diff only) // reinit kanban (TODO: optimize to diff only)
verbose("Content is different.. Applying content"); verbose("Content is different.. Applying content");
kanban.setBoards(remoteContent); kanban.setBoards(remoteContent);
kanban.inEditMode = false; kanban.inEditMode = false;
addRemoveItemButton(framework, kanban);
} }
}); });
framework.setContentGetter(function () { framework.setContentGetter(function () {
// var content = $("#cp-app-kanban-content").val(); if (!kanban) { return; }
var content = kanban.getBoardsJSON(); var content = kanban.getBoardsJSON();
verbose("Content current value is " + content); verbose("Content current value is " + content);
return { return {

View File

@ -67,7 +67,7 @@
boardTitleclick: function (el, boardId) {}, boardTitleclick: function (el, boardId) {},
buttonClick: function (el, boardId) {}, buttonClick: function (el, boardId) {},
colorClick: function (el, boardId) {}, colorClick: function (el, boardId) {},
removeClick: function (el, boardId) {}, addItemClick: function (el, boardId) {},
onChange: function () {} onChange: function () {}
}; };
@ -257,13 +257,6 @@
if (self.options.boards !== boards) if (self.options.boards !== boards)
self.options.boards.push(board); self.options.boards.push(board);
//add width to container
/*if (self.container.style.width === '') {
self.container.style.width = parseInt(boardWidth) + (parseInt(self.options.gutter) * 2) + 'px';
} else {
self.container.style.width = parseInt(self.container.style.width) + parseInt(boardWidth) + (parseInt(self.options.gutter) * 2) + 'px';
}*/
//create node //create node
var boardNode = document.createElement('div'); var boardNode = document.createElement('div');
boardNode.dataset.id = board.id; boardNode.dataset.id = board.id;
@ -325,12 +318,12 @@
} }
//footer board //footer board
var footerBoard = document.createElement('footer'); var footerBoard = document.createElement('footer');
//remove button //add button
var removeBoard = document.createElement('div'); var addBoardItem = document.createElement('button');
$(removeBoard).text("-") $(addBoardItem).text("")
$(removeBoard).addClass("kanban-removeboard"); $(addBoardItem).addClass("kanban-additem btn btn-default");
footerBoard.appendChild(removeBoard); footerBoard.appendChild(addBoardItem);
__onRemoveClickHandler(removeBoard); __onAddItemClickHandler(addBoardItem);
//board assembly //board assembly
boardNode.appendChild(headerBoard); boardNode.appendChild(headerBoard);
@ -347,9 +340,9 @@
} }
this.setBoards = function (boards) { this.setBoards = function (boards) {
for (var boardkey in boards) { self.element
// single board for (var boardkey in this.options.boards) {
var board = boards[boardkey]; var board = this.options.boards[boardkey];
this.removeBoard(board.id); this.removeBoard(board.id);
} }
this.options.boards = []; this.options.boards = [];
@ -478,10 +471,10 @@
}); });
} }
function __onRemoveClickHandler(nodeItem, clickfn) { function __onAddItemClickHandler(nodeItem, clickfn) {
nodeItem.addEventListener('click', function (e) { nodeItem.addEventListener('click', function (e) {
e.preventDefault; e.preventDefault;
self.options.removeClick(this); self.options.addItemClick(this);
if (typeof (this.clickfn) === 'function') if (typeof (this.clickfn) === 'function')
this.clickfn(this); this.clickfn(this);
}); });
@ -489,6 +482,7 @@
function __onButtonClickHandler(nodeItem, boardId) { function __onButtonClickHandler(nodeItem, boardId) {
nodeItem.addEventListener('click', function (e) { nodeItem.addEventListener('click', function (e) {
e.stopPropagation();
e.preventDefault; e.preventDefault;
self.options.buttonClick(this, boardId, e); self.options.buttonClick(this, boardId, e);
// if(typeof(this.clickfn) === 'function') // if(typeof(this.clickfn) === 'function')