From 07502775f5cb5b4cff947eea79bdf4badaddc72f Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 23 May 2018 11:48:30 +0200 Subject: [PATCH] Add support for readonly and locked modes in kanban --- www/kanban/app-kanban.less | 140 +++++++++++++++++++++---------------- www/kanban/inner.js | 31 ++++++-- www/kanban/jkanban.js | 13 +++- 3 files changed, 117 insertions(+), 67 deletions(-) diff --git a/www/kanban/app-kanban.less b/www/kanban/app-kanban.less index 60dd58135..bd19660f7 100644 --- a/www/kanban/app-kanban.less +++ b/www/kanban/app-kanban.less @@ -34,6 +34,8 @@ flex: 1; display: flex; align-items: center; + min-height: -webkit-min-content; + min-height: min-content; .kanban-container { flex: 1; display: flex; @@ -42,6 +44,12 @@ } } + .kanban-item { + display: flex; + align-items: center; + justify-content: space-between; + } + .kanban-board { header { display: flex; @@ -60,78 +68,86 @@ } } } - } - #kanban-edit { - width: 100%; - background: transparent; - border: 1px solid rgba(0,0,0,0.3); - } - - @button-size: 50px; - #kanban-addboard { - margin: 30px; - border: 1px solid; - width: @button-size; - height: @button-size; - line-height: @button-size; - text-align: center; - background: @colortheme_kanban-bg; - font-weight: bold; - align-self: flex-start; - font-size: 50px; - cursor: pointer; - .tools_unselectable(); - } - - .kanban-additem, .kanban-remove-item { - float: right; - background: #EEE; - padding: .25rem .5rem; - line-height: 1; - &:hover { + #kanban-edit { + width: 100%; background: transparent; + border: 1px solid rgba(0,0,0,0.3); } -/* margin: 10px; - padding: 3px; - width: 30px; - text-align: center; - background: #eee; - font-weight: bold; - cursor: pointer; - .tools_unselectable(); */ - } - .kanban-additem { - margin-bottom: 5px; - margin-right: 5px; - } + @button-size: 50px; + #kanban-addboard { + margin: 30px; + border: 1px solid; + width: @button-size; + height: @button-size; + line-height: @button-size; + text-align: center; + background: @colortheme_kanban-bg; + font-weight: bold; + align-self: flex-start; + font-size: 50px; + cursor: pointer; + .tools_unselectable(); + } - .kanban-header-yellow { - background: #FC3; - } + .kanban-remove-item { + padding: 0 0.5em; + } + .kanban-additem { + float: right; + background: #EEE; + padding: 5px .5rem 4px; + line-height: 1; + margin-bottom: 5px; + margin-right: 5px; + font-weight: bold; + font-size: 1.2em; + &:hover { + background: transparent; + } + } - .kanban-header-orange { - background: #F91; - } + .kanban-additem { + } - .kanban-header-blue { - background: #0AC; - } + .kanban-header-yellow { + background: #FC3; + } - .kanban-header-red { - background: #E43; - } + .kanban-header-orange { + background: #F91; + } - .kanban-header-green { - background: #8C4; - } + .kanban-header-blue { + background: #0AC; + } - @media (max-width: @browser_media-medium-screen) { - #cp-app-kanban-container { - flex: 1; - max-width: 100%; - resize: none; + .kanban-header-red { + background: #E43; + } + + .kanban-header-green { + background: #8C4; + } + + @media (max-width: @browser_media-medium-screen) { + #cp-app-kanban-container { + flex: 1; + max-width: 100%; + resize: none; + } + } + + &.cp-app-readonly { + .kanban-item, .kanban-title-board { + cursor: default !important; + .tools_unselectable(); + } + .kanban-title-button, #kanban-addboard, .kanban-remove-item, .kanban-additem { + display: none !important; + } } } + } diff --git a/www/kanban/inner.js b/www/kanban/inner.js index c6cbebb32..751a9a326 100644 --- a/www/kanban/inner.js +++ b/www/kanban/inner.js @@ -28,6 +28,7 @@ define([ verbose = function () {}; // comment out to enable verbose logging var addRemoveItemButton = function (framework, kanban) { + if (framework.isReadOnly() || framework.isLocked()) { return; } var $container = $(kanban.element); $container.find('.kanban-remove-item').remove(); $container.find('.kanban-board .kanban-item').each(function (i, el) { @@ -40,7 +41,7 @@ define([ board.item.splice(pos, 1); $(el).remove(); kanban.onChange(); - }).text('🗙').appendTo($(el)); + }).text('❌').appendTo($(el)); }); }; @@ -97,7 +98,8 @@ define([ element: '#cp-app-kanban-content', gutter: '15px', widthBoard: '300px', - buttonContent: '🗙', + buttonContent: '❌', + readOnly: framework.isReadOnly(), onChange: function () { verbose("Board object has changed"); framework.localChange(); @@ -106,11 +108,13 @@ define([ } }, click: function (el) { + if (framework.isReadOnly() || framework.isLocked()) { return; } if (kanban.inEditMode) { verbose("An edit is already active"); return; } kanban.inEditMode = true; + $(el).find('button').remove(); var name = $(el).text(); $(el).html(''); var $input = getInput().val(name).appendTo(el).focus(); @@ -141,6 +145,7 @@ define([ e.stopPropagation(); $(el).text(name); kanban.inEditMode = false; + addRemoveItemButton(framework, kanban); return; } }); @@ -148,6 +153,7 @@ define([ }, boardTitleClick: function (el, e) { e.stopPropagation(); + if (framework.isReadOnly() || framework.isLocked()) { return; } if (kanban.inEditMode) { verbose("An edit is already active"); return; @@ -187,6 +193,7 @@ define([ }); }, colorClick: function (el) { + if (framework.isReadOnly() || framework.isLocked()) { return; } verbose("in color click"); var board = $(el.parentNode).attr("data-id"); var boardJSON = kanban.getBoardJSON(board); @@ -203,10 +210,10 @@ define([ $(el).removeClass("kanban-header-" + currentColor); $(el).addClass("kanban-header-" + nextColor); kanban.onChange(); - }, buttonClick: function (el, boardId, e) { e.stopPropagation(); + if (framework.isReadOnly() || framework.isLocked()) { return; } UI.confirm(Messages.kanban_deleteBoard, function (yes) { if (!yes) { return; } verbose("Delete board"); @@ -223,6 +230,7 @@ define([ }); }, addItemClick: function (el) { + if (framework.isReadOnly() || framework.isLocked()) { return; } if (kanban.inEditMode) { verbose("An edit is already active"); return; @@ -253,7 +261,6 @@ define([ if (e.which === 27) { e.preventDefault(); e.stopPropagation(); - $(el).text(name); kanban.inEditMode = false; return; } @@ -281,6 +288,7 @@ define([ var addBoardDefault = document.getElementById('kanban-addboard'); addBoardDefault.addEventListener('click', function () { + if (framework.isReadOnly()) { return; } var counter = 1; // Get the new board id @@ -305,6 +313,21 @@ define([ var andThen2 = function (framework) { var kanban; + var $container = $('#cp-app-kanban-content'); + + 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'); + }); framework.onContentUpdate(function (newContent) { // Init if needed diff --git a/www/kanban/jkanban.js b/www/kanban/jkanban.js index 08ddc9776..029e86074 100644 --- a/www/kanban/jkanban.js +++ b/www/kanban/jkanban.js @@ -56,6 +56,7 @@ dragBoards: true, addItemButton: false, buttonContent: '+', + readOnly: false, dragEl: function (el, source) {}, dragendEl: function (el) {}, dropEl: function (el, target, source, sibling) {}, @@ -84,10 +85,12 @@ //Init Drag Board self.drakeBoard = self.dragula([self.container], { moves: function (el, source, handle, sibling) { + if (self.options.readOnly) { return false; } if (!self.options.dragBoards) return false; return (handle.classList.contains('kanban-board-header') || handle.classList.contains('kanban-title-board')); }, accepts: function (el, target, source, sibling) { + if (self.options.readOnly) { return false; } return target.classList.contains('kanban-container'); }, revertOnSpill: true, @@ -129,7 +132,15 @@ }); //Init Drag Item - self.drake = self.dragula(self.boardContainer, function () { + self.drake = self.dragula(self.boardContainer, { + moves: function (el, source, handle, sibling) { + if (self.options.readOnly) { return false; } + return handle.classList.contains('kanban-item'); + }, + accepts: function (el, target, source, sibling) { + if (self.options.readOnly) { return false; } + return true; + }, revertOnSpill: true }) .on('drag', function (el, source) {