Merge branch 'communities-kanban' into staging

This commit is contained in:
yflory 2020-03-10 15:18:16 +01:00
commit 195ee1f1e0
10 changed files with 1644 additions and 564 deletions

View file

@ -277,7 +277,7 @@
margin-bottom: 15px;
}
button {
button:not('.pure-button') {
display: inline-block;
position: relative;
margin: 6px 8px;
@ -293,6 +293,9 @@
&:not(:first-child) {
margin-left: @alertify_padding-base !important;
}
&.left {
float: left;
}
}
}
}

View file

@ -53,6 +53,49 @@
}
}
.markdown_cryptpad() {
word-wrap: break-word;
h1, h2, h3, h4, h5, h6 {
font-weight: bold;
padding-bottom: 0.3em;
border-bottom: 1px solid #eee;
}
li {
min-height: 22px;
}
.todo-list-item {
list-style: none;
position: relative;
.fa {
position: absolute;
margin-left: -17px;
margin-top: 4px;
&.fa-check-square {
font-size: 15px;
margin-top: 5px;
}
}
}
media-tag {
* {
max-width: 100%;
}
iframe[src$=".pdf"] {
width: 100%;
height: 80vh;
max-height: 90vh;
}
}
media-tag:empty {
width: 100px;
height: 100px;
display: inline-block;
border: 1px solid #BBB;
}
}
.markdown_preformatted-code (@color: #333) {
pre > code {
display: block;

View file

@ -11,7 +11,6 @@
.tools_unselectable();
display: flex;
flex-wrap: wrap;
justify-content: space-around;
height: auto;
min-height: 34px;
padding-bottom: 0px;
@ -29,6 +28,7 @@
background-color: #ededed;
white-space: nowrap;
margin: 2px 0;
margin-right: 5px;
height: 24px;
vertical-align: middle;
cursor: default;

View file

@ -168,6 +168,7 @@
position: relative;
order: -2;
resize: horizontal;
z-index: 1;
#cp-app-contacts-container {
height: 100%;
}
@ -196,6 +197,7 @@
padding: 10px;
box-sizing: border-box;
order: -3;
z-index: 1;
.cp-toolbar-userlist-drawer-close {
position: absolute;
margin-top: -10px;

View file

@ -65,47 +65,12 @@
box-sizing: border-box;
//font-family: Calibri,Ubuntu,sans-serif;
font: @colortheme_app-font;
word-wrap: break-word;
position: relative;
flex: 1;
h1, h2, h3, h4, h5, h6 {
font-weight: bold;
padding-bottom: 0.3em;
border-bottom: 1px solid #eee;
}
li {
min-height: 22px;
}
.todo-list-item {
list-style: none;
.fa {
position: absolute;
margin-left: -17px;
margin-top: 4px;
&.fa-check-square {
font-size: 15px;
margin-top: 5px;
}
}
}
media-tag {
* {
max-width:100%;
}
iframe[src$=".pdf"] {
width: 100%;
height: 80vh;
max-height: 90vh;
}
}
media-tag:empty {
width: 100px;
height: 100px;
display: inline-block;
border: 1px solid #BBB;
}
.markdown_main();
.markdown_cryptpad();
.cp-app-code-preview-empty {
display: none;
}

View file

@ -64,7 +64,7 @@ define([
editor._noCursorUpdate = false;
editor.scrollTo(scroll.left, scroll.top);
if (!editor.state.focused) { return; }
if (!editor.hasFocus()) { return; }
if(selects[0] === selects[1]) {
editor.setCursor(posToCursor(selects[0], remoteDoc));

View file

@ -1,6 +1,8 @@
@import (reference) "../../customize/src/less2/include/browser.less";
@import (reference) "../../customize/src/less2/include/framework.less";
@import (reference) "../../customize/src/less2/include/tools.less";
@import (reference) "../../customize/src/less2/include/markdown.less";
@import (reference) "../../customize/src/less2/include/avatar.less";
// body
&.cp-app-kanban {
@ -14,11 +16,142 @@
flex-flow: column;
max-height: 100%;
min-height: auto;
color: @cryptpad_text_col;
@board-bg: #eaeaea;
@palette0: #888; // Default bg color for header
@palette1: #FFD4D4;
@palette2: #FFDECA;
@palette3: #FFE69C;
@palette4: #DBFFB7;
@palette5: #AFFDC2;
@palette6: #C9FFFE;
@palette7: #C8D6FF;
@palette8: #E4CAFF;
.kanban-board-header {
background-color: #c9c9c9;
}
.kanban-board {
.kanban-board-inner {
background-color: @board-bg;
max-height: 100%;
display: flex;
flex-flow: column;
}
color: @cryptpad_text_col;
}
.cp-kanban-palette-nocolor {
background-color: @palette0;
}
.cp-kanban-palette-color1 {
background-color: @palette1;
&.kanban-board-inner {
background-color: lighten(@palette1, 5%);
}
}
.cp-kanban-palette-color2 {
background-color: @palette2;
&.kanban-board-inner {
background-color: lighten(@palette2, 5%);
}
}
.cp-kanban-palette-color3 {
background-color: @palette3;
&.kanban-board-inner {
background-color: lighten(@palette3, 10%);
}
}
.cp-kanban-palette-color4 {
background-color: @palette4;
&.kanban-board-inner {
background-color: lighten(@palette4, 10%);
}
}
.cp-kanban-palette-color5 {
background-color: @palette5;
&.kanban-board-inner {
background-color: lighten(@palette5, 10%);
}
}
.cp-kanban-palette-color6 {
background-color: @palette6;
&.kanban-board-inner {
background-color: lighten(@palette6, 5%);
}
}
.cp-kanban-palette-color7 {
background-color: @palette7;
&.kanban-board-inner {
background-color: lighten(@palette7, 5%);
}
}
.cp-kanban-palette-color8 {
background-color: @palette8;
&.kanban-board-inner {
background-color: lighten(@palette8, 5%);
}
}
.cp-kanban-edit-modal {
display: flex;
flex-flow: column;
overflow: hidden;
}
#cp-kanban-edit-conflicts {
padding: 5px;
background: #eee;
color: @cryptpad_text_col;
font-size: 14px;
.cp-kanban-cursors {
margin-top: 5px;
}
margin-bottom: 5px;
}
#cp-kanban-edit-body {
border: 1px solid @colortheme_modal-input;
.CodeMirror {
height: 105px;
}
.CodeMirror-scroll {
box-sizing: content-box;
}
.cp-markdown-toolbar {
background-color: #eee;
color: @cryptpad_text_col;
}
margin-bottom: 15px;
}
#cp-kanban-edit-colors {
display: flex;
justify-content: space-between;
.cp-kanban-palette {
display: inline-block;
border-radius: 50%;
height: 30px;
width: 30px;
text-align: center;
line-height: 30px;
color: @cryptpad_text_col;
}
.cp-kanban-palette-nocolor {
border: 1px solid @cryptpad_text_col;
}
}
#cp-kanban-edit-tags {
.tokenfield {
margin: 0;
}
margin-bottom: 15px;
}
#cp-app-kanban-container {
flex: 1;
display: flex;
flex-flow: column;
overflow-x: hidden;
}
#cp-app-kanban-editor {
flex: 1;
@ -27,57 +160,271 @@
height: 100%;
overflow: hidden;
}
.kanban-edit-item {
padding: 5px;
}
.cp-kanban-cursors {
&:empty { display: none; }
order: 2;
width: 100%;
&> span {
display: inline-block;
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
margin-right: 5px;
.tools_unselectable();
cursor: default;
}
}
.kanban-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px;
flex-wrap: wrap;
.cp-kanban-cursors {
margin-top: 10px;
}
.kanban-item-body, .kanban-item-tags {
.tools_unselectable();
width: 100%;
}
.kanban-item-body {
margin: 10px 0;
font-size: 0.8em;
:last-child {
margin-bottom: 0px;
}
.markdown_main();
.markdown_cryptpad();
.markdown_preformatted-code;
.markdown_gfm-table(black);
ul {
padding-left: 30px;
}
}
.kanban-item-tags {
display: flex;
align-items: center;
flex-wrap: wrap;
span {
padding: 0 5px;
margin-right: 5px;
margin-top: 5px;
background-color: rgba(0,0,0,0.1);
display: inline-block;
font-size: 12px;
}
}
&.new-item {
padding: 10px;
}
.kanban-item-text {
.tools_unselectable();
cursor: text;
overflow-wrap: anywhere;
flex: 1;
}
&.kanban-item-hidden {
display: none;
}
}
.kanban-board {
main {
padding: 0 10px;
margin: 10px 0;
flex: 1;
overflow-y: auto;
justify-content: space-around;
min-height: 50px;
}
header {
display: flex;
flex-wrap: wrap;
align-items: center;
padding: 5px 10px;
.kanban-title-board {
flex: 1;
margin-right: 10px;
min-width: 0;
overflow: hidden;
//white-space: nowrap;
text-overflow: ellipsis;
}
#kanban-edit {
font-weight: bold;
}
&:hover {
cursor: move;
}
}
footer {
margin: 10px;
margin-top: 0px;
span {
.tools_unselectable();
outline: none;
width: 100%;
border: 1px solid @cryptpad_text_col;
border-radius: 0px;
font-size: 40px;
display: inline-flex;
justify-content: center;
align-items: center;
line-height: 1;
cursor: pointer;
&:hover {
background-color: rgba(0,0,0,0.1);
}
}
}
}
#cp-kanban-controls {
padding: 10px;
display: flex;
position: relative;
width: 100%;
justify-content: space-between;
position: relative;
min-height: 50px;
.cp-kanban-filterTags {
display: inline-flex;
align-items: baseline;
flex: 1;
max-width: 80%;
min-width: 150px;
&> i {
cursor: pointer;
margin-left: 10px;
}
.cp-kanban-filterTags-name {
flex-shrink: 0;
}
.cp-kanban-filterTags-list {
margin-left: 10px;
display: flex;
flex-wrap: wrap;
em {
font-size: 14px;
color: lighten(@cryptpad_text_col, 10%);
}
span {
.tools_unselectable();
padding: 0 5px;
margin-right: 5px;
margin-top: 5px;
background-color: rgba(0,0,0,0.1);
display: inline-block;
font-size: 14px;
cursor: pointer;
&.active {
background-color: @cryptpad_text_col;
color: #fff;
}
}
}
}
.cp-kanban-changeView {
right: 10px;
height: 30px;
width: 60px;
span {
height: 30px;
width: 30px;
line-height: 30px;
text-align: center;
display: inline-block;
background-color: @board-bg;
cursor: pointer;
&:hover {
background-color: darken(@board-bg, 10%);
}
}
}
}
#cp-app-kanban-container {
&:not(.cp-kanban-quick) {
#cp-kanban-controls {
.cp-kanban-changeView {
span.cp-kanban-view {
background-color: @cryptpad_text_col !important;
color: white;
}
span.cp-kanban-view-small {
}
}
}
}
&.cp-kanban-quick {
#cp-kanban-controls {
.cp-kanban-changeView {
span.cp-kanban-view {
}
span.cp-kanban-view-small {
background-color: @cryptpad_text_col !important;
color: white;
}
}
}
.kanban-item {
.kanban-item-body, .kanban-item-tags {
display: none;
}
}
}
}
#cp-app-kanban-content {
flex: 1;
overflow-y: auto;
display: flex;
flex-flow: column;
max-height: 100%;
overflow-x: auto;
.kanban-container-outer {
flex: 1;
display: flex;
align-items: center;
min-height: -webkit-min-content;
min-height: min-content;
min-height: 0;
.kanban-container {
flex: 1;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
max-height: 100%;
}
}
.kanban-item {
#kanban-trash {
height: 60px;
font-size: 40px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 5px 10px 10px;
.kanban-item-text {
cursor: text;
overflow-wrap: anywhere;
flex: 1;
justify-content: center;
position: relative;
width: 100%;
//pointer-events: none;
i {
position: fixed;
}
}
.kanban-board {
header {
display: flex;
align-items: center;
padding: 13px 10px;
.kanban-title-board {
flex: 1;
margin-right: 10px;
min-width: 0;
overflow: hidden;
//white-space: nowrap;
text-overflow: ellipsis;
}
#kanban-edit {
font-weight: bold;
}
&:hover {
cursor: move;
div {
width: 100%;
height: 60px;
position: fixed;
right: 0;
}
&.kanban-trash-active {
color: red;
div {
background: rgba(255,0,0,0.5);
}
}
.kanban-item, .kanban-board {
display: none;
}
}
#kanban-edit {
@ -87,40 +434,21 @@
color: inherit;
}
@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;
order: 2;
width: 300px;
margin: 10px 5px;
border: 1px solid @cryptpad_text_col;
height: 40px;
display: inline-flex;
justify-content: center;
align-items: center;
align-self: flex-start;
font-size: 30px;
font-size: 40px;
cursor: pointer;
.tools_unselectable();
}
.kanban-remove-item {
padding: 0 0.5em;
visibility: hidden;
}
.kanban-item:hover {
.kanban-remove-item {
visibility: visible;
}
}
.kanban-additem {
float: right;
background: #EEE;
padding: 5px .5rem 4px;
line-height: 1;
margin-bottom: 5px;
margin-right: 5px;
&:hover {
background: transparent;
background-color: rgba(0,0,0,0.1);
}
}
@ -176,6 +504,9 @@
.kanban-title-button, #kanban-addboard, .kanban-remove-item, .kanban-additem {
display: none !important;
}
#kanban-trash {
display: none;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -4,13 +4,13 @@
.kanban-board {
position: relative;
float: left;
background: #E2E4E6;
transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
margin: 10px;
vertical-align: top;
display: flex;
flex-flow: column;
width: 300px;
margin: 10px 5px;
}
.kanban-board.disabled-board {
@ -19,6 +19,7 @@
.kanban-board.is-moving.gu-mirror {
transform: rotate(3deg);
opacity: 0.8;
}
.kanban-board.is-moving.gu-mirror .kanban-drag {
@ -45,17 +46,11 @@
padding: .25rem .5rem;
}
.kanban-board .kanban-drag {
min-height: 200px;
padding: 20px;
flex: 1;
}
.kanban-item {
background: #fff;
padding: 15px;
margin-bottom: 20px;
transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
margin-bottom: 10px;
}
.kanban-item:hover {
@ -69,6 +64,7 @@
.kanban-item.is-moving.gu-mirror {
transform: rotate(3deg);
height: auto !important;
opacity: 0.8;
}
/* Dragula CSS */

View file

@ -45,18 +45,23 @@
this.drake = '';
this.drakeBoard = '';
this.addItemButton = false;
this.buttonContent = '+';
defaults = {
element: '',
gutter: '15px',
widthBoard: '250px',
responsive: '700',
colors: ["yellow", "green", "blue", "red", "orange"],
responsivePercentage: false,
boards: [],
boards: {
data: {},
items: {},
list: []
},
getAvatar: function () {},
getTextColor: function () { return '#000'; },
cursors: {},
tags: [],
dragBoards: true,
addItemButton: false,
buttonContent: '+',
readOnly: false,
dragEl: function (el, source) {},
dragendEl: function (el) {},
@ -67,9 +72,9 @@
dropBoard: function (el, target, source, sibling) {},
click: function (el) {},
boardTitleclick: function (el, boardId) {},
buttonClick: function (el, boardId) {},
colorClick: function (el, type) {},
addItemClick: function (el, boardId) {},
renderMd: function (md) {},
refresh: function () {},
onChange: function () {}
};
@ -80,19 +85,62 @@
this.init = function () {
// set initial boards
__setBoard();
// Scroll on drag
var $el = $(self.element)
var $inner = $el.find('.kanban-container');
var leftRegion = $el.position().left + 10;
var rightRegion = $(window).width() - 10;
var activeBoard;
var $aB;
var setActiveDrag = function (board) {
activeBoard = undefined;
if (!board) { return; }
if (!board.classList.contains('kanban-drag')) { return; }
activeBoard = board;
$aB = $(activeBoard);
};
var onMouseMove = function (isItem) {
return function (e) {
if (e.which !== 1) { return; } // left click
var distance = 20;
// If this is an item drag, check scroll
if (isItem && activeBoard) {
var rect = activeBoard.getBoundingClientRect();
if (e.pageX > rect.left && e.pageX < rect.right) {
if (e.pageY < (rect.top + 10)) {
distance *= -1;
$aB.scrollTop(distance + $aB.scrollTop()) ;
} else if (e.pageY > (rect.bottom - 10)) {
$aB.scrollTop(distance + $aB.scrollTop()) ;
}
}
}
// Itme or board: horizontal scroll if needed
if (e.pageX < leftRegion) {
distance *= -1;
$el.scrollLeft(distance + $el.scrollLeft()) ;
} else if (e.pageX >= rightRegion) {
$el.scrollLeft(distance + $el.scrollLeft()) ;
}
};
};
//set drag with dragula
if (window.innerWidth > self.options.responsive) {
//Init Drag Board
self.drakeBoard = self.dragula([self.container], {
self.drakeBoard = self.dragula([self.container, self.trashContainer], {
moves: function (el, source, handle, sibling) {
if (self.options.readOnly) { return false; }
if (!self.options.dragBoards) 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');
if (sibling && sibling.getAttribute('id') === "kanban-addboard") { return false; }
return target.classList.contains('kanban-container') ||
target.classList.contains('kanban-trash');
},
revertOnSpill: true,
direction: 'horizontal',
@ -100,47 +148,66 @@
.on('drag', function (el, source) {
el.classList.add('is-moving');
self.options.dragBoard(el, source);
if (typeof (el.dragfn) === 'function')
if (typeof (el.dragfn) === 'function') {
el.dragfn(el, source);
}
$(document).on('mousemove', onMouseMove());
})
.on('dragend', function (el) {
el.classList.remove('is-moving');
self.options.dragendBoard(el);
$(document).off('mousemove');
if (typeof (el.dragendfn) === 'function')
el.dragendfn(el);
})
.on('over', function (el, target, source) {
if (!target.classList.contains('kanban-trash')) { return false; }
$('.kanban-trash').addClass('kanban-trash-active');
})
.on('out', function (el, target) {
if (!target.classList.contains('kanban-trash')) { return false; }
$('.kanban-trash').removeClass('kanban-trash-active');
})
.on('drop', function (el, target, source, sibling) {
el.classList.remove('is-moving');
self.options.dropBoard(el, target, source, sibling);
if (typeof (el.dropfn) === 'function')
if (typeof (el.dropfn) === 'function') {
el.dropfn(el, target, source, sibling);
// TODO: update board object board order
console.log("Drop " + $(el).attr("data-id") + " just before " + (sibling ? $(sibling).attr("data-id") : " end "));
var index1, index2;
self.options.boards.some(function (element, index) {
if (element.id === $(el).attr("data-id")) {
index1 = index;
return true;
}
});
if (sibling) {
self.options.boards.some(function (element, index) {
if (element.id === $(sibling).attr("data-id")) {
index2 = index;
return true;
}
})
} else {
index2 = self.options.boards.length;
}
var id = Number($(el).attr('data-id'));
var list = self.options.boards.list || [];
var index1 = list.indexOf(id);
if (index1 === -1) { return; }
// Move to trash?
if (target.classList.contains('kanban-trash')) {
list.splice(index1, 1);
delete self.options.boards.data[id];
self.onChange();
return;
}
var index2;
var id2 = Number($(sibling).attr("data-id"));
if (sibling && id2) {
index2 = list.indexOf(id2);
}
// If we can't find the drop position, drop at the end
if (typeof(index2) === "undefined" || index2 === -1) {
index2 = list.length;
}
console.log("Switch " + index1 + " and " + index2);
if (index1 < index2)
if (index1 < index2) {
index2 = index2 - 1;
self.options.boards.splice(index2, 0, self.options.boards.splice(index1, 1)[0]);
}
list.splice(index1, 1);
list.splice(index2, 0, id);
// send event that board has changed
self.onChange();
self.setBoards(self.options.boards);
});
//Init Drag Item
@ -148,7 +215,7 @@
moves: function (el, source, handle, sibling) {
if (self.options.readOnly) { return false; }
if (el.classList.contains('new-item')) { return false; }
return handle.classList.contains('kanban-item');
return el.classList.contains('kanban-item');
},
accepts: function (el, target, source, sibling) {
if (self.options.readOnly) { return false; }
@ -163,93 +230,121 @@
// we need to calculate the position before starting to drag
self.dragItemPos = self.findElementPosition(el);
setActiveDrag();
el.classList.add('is-moving');
var boardJSON = __findBoardJSON(source.parentNode.dataset.id);
if (boardJSON.dragTo !== undefined) {
self.options.boards.map(function (board) {
if (boardJSON.dragTo.indexOf(board.id) === -1 && board.id !== source.parentNode.dataset.id) {
self.findBoard(board.id).classList.add('disabled-board');
}
})
}
$(document).on('mousemove', onMouseMove(el));
self.options.dragEl(el, source);
if (el !== null && typeof (el.dragfn) === 'function')
if (el !== null && typeof (el.dragfn) === 'function') {
el.dragfn(el, source);
}
})
.on('dragend', function (el) {
console.log("In dragend");
el.classList.remove('is-moving');
self.options.dragendEl(el);
if (el !== null && typeof (el.dragendfn) === 'function')
$(document).off('mousemove');
if (el !== null && typeof (el.dragendfn) === 'function') {
el.dragendfn(el);
}
})
.on('cancel', function (el, container, source) {
console.log("In cancel");
el.classList.remove('is-moving');
// FIXME custom code
var boardId = source.parentNode.dataset.id;
var boardId = $(source).closest('kanban-board').data('id');
self.options.dragcancelEl(el, boardId);
})
.on('over', function (el, target, source) {
setActiveDrag(target);
if (!target.classList.contains('kanban-trash')) { return false; }
target.classList.add('kanban-trash-active');
})
.on('out', function (el, target) {
setActiveDrag();
if (!target.classList.contains('kanban-trash')) { return false; }
target.classList.remove('kanban-trash-active');
})
.on('drop', function(el, target, source, sibling) {
self.enableAllBoards();
el.classList.remove('is-moving');
console.log("In drop");
// TODO: update board object board order
var board1;
self.options.boards.some(function (element) {
if (element.id === $(source.parentNode).attr("data-id")) {
return board1 = element;
}
});
var board2;
self.options.boards.some(function (element) {
if (element.id === $(target.parentNode).attr("data-id")) {
return board2 = element;
}
});
var pos1 = self.dragItemPos;
var pos2 = (sibling) ? self.findElementPosition(sibling) : (board2.item.length + 1);
console.log("Drop element " + pos1 + " before " + pos2);
var id1 = Number($(el).attr('data-eid'));
// TODO: update board object item order
// Move to trash?
if (target.classList.contains('kanban-trash')) {
self.moveItem(id1);
self.onChange();
return;
}
var allB = document.querySelectorAll('.kanban-board');
if (allB.length > 0 && allB !== undefined) {
for (var i = 0; i < allB.length; i++) {
allB[i].classList.remove('disabled-board');
}
}
var boardJSON = __findBoardJSON(source.parentNode.dataset.id);
if (boardJSON.dragTo !== undefined) {
if (boardJSON.dragTo.indexOf(target.parentNode.dataset.id) === -1 && target.parentNode.dataset.id !== source.parentNode.dataset.id) {
self.drake.cancel(true)
}
}
// Find the new board
var targetId = Number($(target).closest('.kanban-board').data('id'));
if (!targetId) { return; }
var board2 = __findBoardJSON(targetId);
var id2 = $(sibling).attr('data-eid');
if (id2) { id2 = Number(id2); }
var pos2 = id2 ? board2.item.indexOf(id2) : board2.item.length;
if (pos2 === -1) { pos2 = board2.item.length; }
// Remove the "move" effect
if (el !== null) {
self.options.dropEl(el, target, source, sibling);
el.classList.remove('is-moving');
if (typeof (el.dropfn) === 'function')
el.dropfn(el, target, source, sibling);
}
var item = board1.item[pos1];
// if (board1==board2 && pos2<pos1)
// pos2 = pos2;
// moving element to target array
board1.item.splice(pos1, 1);
board2.item.splice(pos2 - 1, 0, item);
// Move the item
self.moveItem(id1, board2, pos2);
// send event that board has changed
self.onChange();
self.setBoards(self.options.boards);
})
}
};
var findItem = function (eid) {
var boards = self.options.boards;
var list = boards.list || [];
var res = [];
list.forEach(function (id) {
var b = boards.data[id];
if (!b) { return; }
var items = b.item || [];
var idx = items.indexOf(eid);
if (idx === -1) { return; }
// This board contains our item...
res.push({
board: b,
pos: idx
});
});
return res;
};
this.moveItem = function (eid, board, pos) {
var boards = self.options.boards;
var list = boards.list || [];
var from = [];
var same = -1;
var from = findItem(eid);
// Remove the item from its board
from.forEach(function (obj) {
obj.board.item.splice(obj.pos, 1);
if (obj.board === board) { same = obj.pos; }
});
// If it's a deletion, remove the item data
if (!board) {
delete boards.items[eid];
return;
}
// If it's moved to the same board at a bigger index, decrement the index by one
// (we just removed one element)
if (same !== -1 && same < pos) {
pos = pos - 1;
}
board.item.splice(pos, 0, eid);
};
this.enableAllBoards = function() {
var allB = document.querySelectorAll('.kanban-board');
if (allB.length > 0 && allB !== undefined) {
@ -259,31 +354,84 @@
}
};
this.addElement = function (boardID, element) {
// add Element to JSON
var boardJSON = __findBoardJSON(boardID);
boardJSON.item.push({
title: element.title
});
var board = self.element.querySelector('[data-id="' + boardID + '"] .kanban-drag');
var getElementNode = function (element) {
var nodeItem = document.createElement('div');
nodeItem.classList.add('kanban-item');
if (element.id) {
nodeItem.setAttribute('data-eid', element.id)
nodeItem.dataset.eid = element.id;
if (element.color) {
if (/color/.test(element.color)) {
// Palette color
nodeItem.classList.add('cp-kanban-palette-'+element.color);
} else {
// Hex color code
var textColor = self.options.getTextColor(element.color);
nodeItem.setAttribute('style', 'background-color:#'+element.color+';color:'+textColor+';');
}
}
var nodeCursors = document.createElement('div');
nodeCursors.classList.add('cp-kanban-cursors');
Object.keys(self.options.cursors).forEach(function (id) {
var c = self.options.cursors[id];
if (Number(c.item) !== Number(element.id)) { return; }
var el = self.options.getAvatar(c);
nodeCursors.appendChild(el);
});
var nodeItemText = document.createElement('div');
nodeItemText.classList.add('kanban-item-text');
nodeItemText.innerHTML = element.title;
nodeItemText.dataset.eid = element.id;
nodeItemText.innerText = element.title;
nodeItem.appendChild(nodeItemText);
// Check if this card is filtered out
if (Array.isArray(self.options.tags) && self.options.tags.length) {
var hide = !Array.isArray(element.tags) ||
!element.tags.some(function (tag) {
return self.options.tags.indexOf(tag) !== -1;
});
if (hide) {
nodeItem.classList.add('kanban-item-hidden');
}
}
if (element.body) {
var html = self.renderMd(element.body);
var nodeBody = document.createElement('div');
nodeBody.classList.add('kanban-item-body');
nodeBody.onclick = function (e) {
e.preventDefault();
};
nodeBody.innerHTML = html;
nodeItem.appendChild(nodeBody);
}
if (Array.isArray(element.tags)) {
var nodeTags = document.createElement('div');
nodeTags.classList.add('kanban-item-tags');
element.tags.forEach(function (_tag) {
var tag = document.createElement('span');
tag.innerText = _tag;
nodeTags.appendChild(tag);
});
nodeItem.appendChild(nodeTags);
}
nodeItem.appendChild(nodeCursors);
//add function
nodeItem.clickfn = element.click;
nodeItem.dragfn = element.drag;
nodeItem.dragendfn = element.dragend;
nodeItem.dropfn = element.drop;
__onclickHandler(nodeItemText);
__onColorClickHandler(nodeItem, "item");
board.appendChild(nodeItem);
return nodeItem;
};
this.addElement = function (boardID, element) {
// add Element to JSON
var boardJSON = __findBoardJSON(boardID);
boardJSON.item.push(element.id);
self.options.boards.items = self.options.boards.items || {};
self.options.boards.items[element.id] = element;
var board = self.element.querySelector('[data-id="' + boardID + '"] .kanban-drag');
board.appendChild(getElementNode(element));
// send event that board has changed
self.onChange();
return self;
@ -295,116 +443,125 @@
return self;
};
this.addBoards = function(boards) {
var getBoardNode = function (board) {
var boards = self.options.boards;
var boardWidth = self.options.widthBoard;
//create node
var boardNode = document.createElement('div');
boardNode.dataset.id = board.id;
boardNode.classList.add('kanban-board');
var boardNodeInner = document.createElement('div');
boardNodeInner.classList.add('kanban-board-inner');
//set style
if (self.options.responsivePercentage) {
self.container.style.width = '100%';
self.options.gutter = '1%';
if (window.innerWidth > self.options.responsive) {
var boardWidth = (100 - boards.length * 2) / boards.length;
} else {
var boardWidth = 100 - (boards.length * 2);
}
boardNode.style.width = boardWidth + '%';
} else {
var boardWidth = self.options.widthBoard;
boardNode.style.width = boardWidth;
}
var addButton = self.options.addItemButton;
var buttonContent = self.options.buttonContent;
//for on all the boards
for (var boardkey in boards) {
// single board
var board = boards[boardkey];
if (self.options.boards !== boards)
self.options.boards.push(board);
//create node
var boardNode = document.createElement('div');
boardNode.dataset.id = board.id;
boardNode.classList.add('kanban-board');
//set style
if (self.options.responsivePercentage) {
boardNode.style.width = boardWidth + '%';
} else {
boardNode.style.width = boardWidth;
}
boardNode.style.marginLeft = self.options.gutter;
boardNode.style.marginRight = self.options.gutter;
// header board
var headerBoard = document.createElement('header');
if (board.class !== '' && board.class !== undefined)
var allClasses = board.class.split(",");
else allClasses = [];
headerBoard.classList.add('kanban-board-header');
allClasses.map(function (value) {
headerBoard.classList.add(value);
});
if (board.color !== '' && board.color !== undefined) {
headerBoard._jscLinkedInstance = undefined;
jscolorL = new jscolor(headerBoard,{showOnClick: false, valueElement:undefined});
jscolorL.fromString(board.color);
headerBoard._jscLinkedInstance = undefined;
boardNode.style.marginLeft = self.options.gutter;
boardNode.style.marginRight = self.options.gutter;
// header board
var headerBoard = document.createElement('header');
if (board.class !== '' && board.class !== undefined) {
var allClasses = board.class.split(",");
} else {
allClasses = [];
}
headerBoard.classList.add('kanban-board-header');
allClasses.map(function (value) {
headerBoard.classList.add(value);
});
if (board.color !== '' && board.color !== undefined) {
if (/color/.test(board.color)) {
// Palette color
headerBoard.classList.add('cp-kanban-palette-'+board.color);
boardNodeInner.classList.add('cp-kanban-palette-'+board.color);
} else if (!/^[0-9a-f]{6}$/.test(board.color)) {
// "string" color (red, blue, etc.)
headerBoard.classList.add("kanban-header-" + board.color);
} else {
// Hex color code
var textColor = self.options.getTextColor(board.color);
headerBoard.setAttribute('style', 'background-color:#'+board.color+';color:'+textColor+';');
}
titleBoard = document.createElement('div');
titleBoard.classList.add('kanban-title-board');
titleBoard.innerHTML = board.title;
//titleBoard.setAttribute('title', board.title);
titleBoard.clickfn = board.boardTitleClick;
__onboardTitleClickHandler(titleBoard);
headerBoard.appendChild(titleBoard);
__onColorClickHandler(headerBoard, "board");
}
// if add button is true, add button to the board
if (addButton) {
var btn = document.createElement("BUTTON");
btn.setAttribute("class", "kanban-title-button btn btn-default btn-xs fa fa-times");
//var buttonHtml = '<button class="kanban-title-button btn btn-default btn-xs">'+buttonContent+'</button>'
headerBoard.appendChild(btn);
__onButtonClickHandler(btn, board.id);
}
//content board
var contentBoard = document.createElement('main');
contentBoard.classList.add('kanban-drag');
//add drag to array for dragula
self.boardContainer.push(contentBoard);
for (var itemkey in board.item) {
//create item
var itemKanban = board.item[itemkey];
var nodeItem = document.createElement('div');
nodeItem.classList.add('kanban-item');
nodeItem.dataset.eid = itemKanban.id;
var nodeItemText = document.createElement('div');
nodeItemText.classList.add('kanban-item-text');
nodeItemText.dataset.eid = itemKanban.id;
nodeItemText.innerHTML = itemKanban.title;
nodeItem.appendChild(nodeItemText);
//add function
nodeItemText.clickfn = itemKanban.click;
nodeItemText.dragfn = itemKanban.drag;
nodeItemText.dragendfn = itemKanban.dragend;
nodeItemText.dropfn = itemKanban.drop;
//add click handler of item
__onclickHandler(nodeItemText);
if (itemKanban.color !== '' && itemKanban.color !== undefined) {
jscolorL = new jscolor(nodeItem,{showOnClick: false, valueElement:undefined});
jscolorL.fromString(itemKanban.color);
}
__onColorClickHandler(nodeItem, "item");
titleBoard = document.createElement('div');
titleBoard.classList.add('kanban-title-board');
titleBoard.innerText = board.title;
contentBoard.appendChild(nodeItem);
}
//footer board
//add button
var addBoardItem = document.createElement('button');
$(addBoardItem).addClass("kanban-title-button btn btn-default fa fa-plus");
headerBoard.appendChild(addBoardItem);
__onAddItemClickHandler(addBoardItem);
titleBoard.clickfn = board.boardTitleClick;
__onboardTitleClickHandler(titleBoard);
headerBoard.appendChild(titleBoard);
var nodeCursors = document.createElement('div');
nodeCursors.classList.add('cp-kanban-cursors');
Object.keys(self.options.cursors).forEach(function (id) {
var c = self.options.cursors[id];
if (Number(c.board) !== Number(board.id)) { return; }
var el = self.options.getAvatar(c);
nodeCursors.appendChild(el);
});
headerBoard.appendChild(nodeCursors);
//content board
var contentBoard = document.createElement('main');
contentBoard.classList.add('kanban-drag');
//add drag to array for dragula
self.boardContainer.push(contentBoard);
(board.item || []).forEach(function (itemkey) {
//create item
var itemKanban = boards.items[itemkey];
if (!itemKanban) { return; } // XXX clean invalid data
var nodeItem = getElementNode(itemKanban);
contentBoard.appendChild(nodeItem);
});
//footer board
var footerBoard = document.createElement('footer');
footerBoard.classList.add('kanban-board-footer');
//add button
var addBoardItem = document.createElement('span');
addBoardItem.classList.add('kanban-title-button');
addBoardItem.innerText = '+';
footerBoard.appendChild(addBoardItem);
__onAddItemClickHandler(addBoardItem);
//board assembly
boardNode.appendChild(boardNodeInner);
boardNodeInner.appendChild(headerBoard);
boardNodeInner.appendChild(contentBoard);
boardNodeInner.appendChild(footerBoard);
return boardNode;
};
this.addBoard = function (board) {
if (!board || !board.id) { return; }
var boards = self.options.boards;
boards.data = boards.data || {};
boards.list = boards.list || [];
// If it already there, abort
boards.data[board.id] = board;
if (boards.list.indexOf(board.id) !== -1) { return; }
boards.list.push(board.id);
var boardNode = getBoardNode(board);
self.container.appendChild(boardNode);
};
this.addBoards = function() {
//for on all the boards
var boards = self.options.boards;
boards.list = boards.list || [];
boards.data = boards.data || {};
for (var index in boards.list) {
// single board
var boardkey = boards.list[index];
var board = boards.data[boardkey];
if (!board) { continue; } // XXX clean invalid data
var boardNode = getBoardNode(board);
//board assembly
boardNode.appendChild(headerBoard);
boardNode.appendChild(contentBoard);
//board add
self.container.appendChild(boardNode);
}
@ -416,13 +573,14 @@
}
this.setBoards = function (boards) {
self.element
for (var boardkey in this.options.boards) {
var board = this.options.boards[boardkey];
this.removeBoard(board.id);
//self.element
for (var i in this.options.boards.list) {
var boardkey = this.options.boards.list[i];
this.removeBoard(boardkey);
}
this.options.boards = [];
this.addBoards(boards);
this.options.boards = boards;
this.addBoards();
self.options.refresh();
}
this.findBoard = function (id) {
@ -457,8 +615,13 @@
};
this.removeBoard = function (board) {
if (typeof (board) === 'string')
var id;
if (typeof (board) === 'string' || typeof (board) === "number") {
id = board;
board = self.element.querySelector('[data-id="' + board + '"]');
} else if (board) {
id = board.id;
}
if (board) {
board.remove();
@ -466,14 +629,15 @@
self.onChange();
}
// Remove duplicates
if (id) { $(self.element).find('.kanban-board[data-id="' + board + '"]').remove(); }
return self;
}
// board button on click function
this.onButtonClick = function (el) {
this.renderMd = function (md) {
return self.options.renderMd(md);
}
this.onChange = function () {
self.options.onChange();
}
@ -485,6 +649,9 @@
this.getBoardJSON = function (id) {
return __findBoardJSON(id);
}
this.getItemJSON = function (id) {
return (self.options.boards.items || {})[id];
};
//PRIVATE FUNCTION
function __extendDefaults(source, properties) {
@ -507,14 +674,24 @@
boardContainerOuter.appendChild(boardContainer);
var addBoard = document.createElement('div');
addBoard.id = 'kanban-addboard';
addBoard.setAttribute('class', 'fa fa-plus');
addBoard.innerText = '+';
boardContainer.appendChild(addBoard);
var trash = self.trashContainer = document.createElement('div');
trash.setAttribute('id', 'kanban-trash');
trash.setAttribute('class', 'kanban-trash');
var trashBg = document.createElement('div');
var trashIcon = document.createElement('i');
trashIcon.setAttribute('class', 'fa fa-trash');
trash.appendChild(trashIcon);
trash.appendChild(trashBg);
self.boardContainer.push(trash);
self.container = boardContainer;
//add boards
self.addBoards(self.options.boards);
self.addBoards();
//appends to container
self.element.appendChild(boardContainerOuter);
self.element.appendChild(addBoard);
self.element.appendChild(trash);
// send event that board has changed
self.onChange();
@ -539,17 +716,6 @@
});
}
function __onColorClickHandler(nodeItem, type) {
nodeItem.addEventListener('click', function (e) {
if (Array.prototype.slice.call(nodeItem.classList).indexOf('is-moving') !== -1) {
return;
}
e.preventDefault;
e.stopPropagation();
self.options.colorClick(this, type);
});
}
function __onAddItemClickHandler(nodeItem, clickfn) {
nodeItem.addEventListener('click', function (e) {
e.preventDefault;
@ -560,24 +726,8 @@
});
}
function __onButtonClickHandler(nodeItem, boardId) {
nodeItem.addEventListener('click', function (e) {
e.stopPropagation();
e.preventDefault;
self.options.buttonClick(this, boardId, e);
// if(typeof(this.clickfn) === 'function')
// this.clickfn(this);
});
}
function __findBoardJSON(id) {
var el = []
self.options.boards.map(function (board) {
if (board.id === id) {
return el.push(board)
}
})
return el[0]
return (self.options.boards.data || {})[id];
}