Tag filter
This commit is contained in:
parent
411b125b0f
commit
fdea16d601
@ -293,6 +293,9 @@
|
|||||||
&:not(:first-child) {
|
&:not(:first-child) {
|
||||||
margin-left: @alertify_padding-base !important;
|
margin-left: @alertify_padding-base !important;
|
||||||
}
|
}
|
||||||
|
&.left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -219,7 +219,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#cp-kanban-controls {
|
#cp-kanban-controls {
|
||||||
height: 40px;
|
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -228,9 +227,36 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
.cp-kanban-filterTags {
|
.cp-kanban-filterTags {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
width: 250px;
|
align-items: baseline;
|
||||||
height: 40px;
|
flex: 1;
|
||||||
align-items: center;
|
max-width: 80%;
|
||||||
|
min-width: 150px;
|
||||||
|
|
||||||
|
&> i {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.cp-kanban-filterTags-name {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.cp-kanban-filterTags-list {
|
||||||
|
margin-left: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&> .tokenfield {
|
&> .tokenfield {
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
|
|||||||
@ -51,6 +51,7 @@ 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 onRedraw = Util.mkEvent();
|
||||||
|
|
||||||
Messages.kanban_title = "Title"; // XXX
|
Messages.kanban_title = "Title"; // XXX
|
||||||
Messages.kanban_body = "Body"; // XXX
|
Messages.kanban_body = "Body"; // XXX
|
||||||
@ -60,9 +61,9 @@ define([
|
|||||||
Messages.kanban_tags = "Filter tags"; // XXX
|
Messages.kanban_tags = "Filter tags"; // XXX
|
||||||
|
|
||||||
// XXX
|
// XXX
|
||||||
// Tag filter:
|
// Conflicts
|
||||||
// remember tags in padAttribute
|
// use cursor channel to tell others what you are editing
|
||||||
// click on a tag ==> add it to the list
|
// add outline + warning inside the modal?
|
||||||
|
|
||||||
var setValueAndCursor = function (input, val, _cursor) {
|
var setValueAndCursor = function (input, val, _cursor) {
|
||||||
if (!input) { return; }
|
if (!input) { return; }
|
||||||
@ -259,7 +260,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var button = [{
|
var button = [{
|
||||||
className: 'danger', // XXX align left
|
className: 'danger left',
|
||||||
name: Messages.kanban_delete,
|
name: Messages.kanban_delete,
|
||||||
onClick: function () {
|
onClick: function () {
|
||||||
var boards = kanban.options.boards || {};
|
var boards = kanban.options.boards || {};
|
||||||
@ -432,6 +433,9 @@ define([
|
|||||||
widthBoard: '300px',
|
widthBoard: '300px',
|
||||||
buttonContent: '❌',
|
buttonContent: '❌',
|
||||||
readOnly: framework.isReadOnly(),
|
readOnly: framework.isReadOnly(),
|
||||||
|
refresh: function () {
|
||||||
|
onRedraw.fire();
|
||||||
|
},
|
||||||
onChange: function () {
|
onChange: function () {
|
||||||
verbose("Board object has changed");
|
verbose("Board object has changed");
|
||||||
framework.localChange();
|
framework.localChange();
|
||||||
@ -607,7 +611,7 @@ define([
|
|||||||
}
|
}
|
||||||
kanban.inEditMode = "new";
|
kanban.inEditMode = "new";
|
||||||
// create a form to enter element
|
// create a form to enter element
|
||||||
var boardId = $(el.parentNode.parentNode).attr("data-id");
|
var boardId = $(el).closest('.kanban-board').attr("data-id");
|
||||||
var $item = $('<div>', {'class': 'kanban-item new-item'});
|
var $item = $('<div>', {'class': 'kanban-item new-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]);
|
||||||
@ -620,10 +624,14 @@ define([
|
|||||||
kanban.inEditMode = false;
|
kanban.inEditMode = false;
|
||||||
if (!$input.val()) { return; }
|
if (!$input.val()) { return; }
|
||||||
var id = Util.createRandomInteger();
|
var id = Util.createRandomInteger();
|
||||||
kanban.addElement(boardId, {
|
var item = {
|
||||||
"id": id,
|
"id": id,
|
||||||
"title": $input.val(),
|
"title": $input.val(),
|
||||||
});
|
};
|
||||||
|
if (kanban.options.tags && kanban.options.tags.length) {
|
||||||
|
item.tags = kanban.options.tags;
|
||||||
|
}
|
||||||
|
kanban.addElement(boardId, item);
|
||||||
};
|
};
|
||||||
$input.blur(save);
|
$input.blur(save);
|
||||||
$input.keydown(function (e) {
|
$input.keydown(function (e) {
|
||||||
@ -673,6 +681,7 @@ define([
|
|||||||
|
|
||||||
var $container = $('#cp-app-kanban-content');
|
var $container = $('#cp-app-kanban-content');
|
||||||
var addControls = function () {
|
var addControls = function () {
|
||||||
|
// Quick or normal mode
|
||||||
var small = h('span.cp-kanban-view-small.fa.fa-minus');
|
var small = h('span.cp-kanban-view-small.fa.fa-minus');
|
||||||
var big = h('span.cp-kanban-view.fa.fa-bars');
|
var big = h('span.cp-kanban-view.fa.fa-bars');
|
||||||
$(small).click(function () {
|
$(small).click(function () {
|
||||||
@ -686,42 +695,108 @@ define([
|
|||||||
framework._.sfCommon.setPadAttribute('quickMode', false);
|
framework._.sfCommon.setPadAttribute('quickMode', false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Tags filter
|
||||||
var existing = getExistingTags(kanban.options.boards);
|
var existing = getExistingTags(kanban.options.boards);
|
||||||
var input = UI.dialog.textInput();
|
var list = h('div.cp-kanban-filterTags-list');
|
||||||
|
var reset = h('i.cp-kanban-filterTags-reset.fa.fa-times');
|
||||||
var tags = h('div.cp-kanban-filterTags', [
|
var tags = h('div.cp-kanban-filterTags', [
|
||||||
Messages.kanban_tags,
|
h('span.cp-kanban-filterTags-name', Messages.kanban_tags),
|
||||||
input
|
reset,
|
||||||
|
list
|
||||||
]);
|
]);
|
||||||
var field = UI.tokenField(input, existing).preventDuplicates(function (val) {
|
var $reset = $(reset);
|
||||||
UI.warn(Messages._getKey('tags_duplicate', [val]));
|
var $list = $(list);
|
||||||
});
|
|
||||||
field.setTokens([]);
|
var getTags = function () {
|
||||||
|
return $list.find('span.active').map(function () {
|
||||||
|
return $(this).data('tag');
|
||||||
|
}).get();
|
||||||
|
};
|
||||||
var commitTags = function () {
|
var commitTags = function () {
|
||||||
var t = field.getTokens();
|
var t = getTags();
|
||||||
|
if (t.length) {
|
||||||
|
$reset.show();
|
||||||
|
} else {
|
||||||
|
$reset.hide();
|
||||||
|
}
|
||||||
|
framework._.sfCommon.setPadAttribute('tagsFilter', t);
|
||||||
kanban.options.tags = t;
|
kanban.options.tags = t;
|
||||||
kanban.setBoards(kanban.options.boards);
|
kanban.setBoards(kanban.options.boards);
|
||||||
addEditItemButton(framework, kanban);
|
addEditItemButton(framework, kanban);
|
||||||
};
|
};
|
||||||
field.tokenfield.on('tokenfield:createdtoken', commitTags);
|
|
||||||
field.tokenfield.on('tokenfield:editedoken', commitTags);
|
var redrawList = function (allTags) {
|
||||||
field.tokenfield.on('tokenfield:removedtoken', commitTags);
|
if (!Array.isArray(allTags)) { return; }
|
||||||
|
$list.empty();
|
||||||
|
allTags.forEach(function (t) {
|
||||||
|
var tag;
|
||||||
|
$list.append(tag = h('span', {
|
||||||
|
'data-tag': t
|
||||||
|
}, t));
|
||||||
|
var $tag = $(tag).click(function () {
|
||||||
|
if ($tag.hasClass('active')) {
|
||||||
|
$tag.removeClass('active');
|
||||||
|
} else {
|
||||||
|
$tag.addClass('active');
|
||||||
|
}
|
||||||
|
commitTags();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
redrawList(existing);
|
||||||
|
|
||||||
|
var setTags = function (tags) {
|
||||||
|
$list.find('span').removeClass('active');
|
||||||
|
if (!Array.isArray(tags)) { return; }
|
||||||
|
tags.forEach(function (t, i) {
|
||||||
|
if (existing.indexOf(t) === -1) {
|
||||||
|
// This tag doesn't exist anymore
|
||||||
|
tags.splice(i, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$list.find('span').filter(function () {
|
||||||
|
return $(this).data('tag') === t;
|
||||||
|
}).addClass('active');
|
||||||
|
});
|
||||||
|
framework._.sfCommon.setPadAttribute('tagsFilter', tags);
|
||||||
|
};
|
||||||
|
$reset.hide().click(function () {
|
||||||
|
setTags([]);
|
||||||
|
commitTags();
|
||||||
|
});
|
||||||
|
|
||||||
var container = h('div#cp-kanban-controls', [
|
var container = h('div#cp-kanban-controls', [
|
||||||
tags, // XXX
|
tags,
|
||||||
h('div.cp-kanban-changeView', [
|
h('div.cp-kanban-changeView', [
|
||||||
small,
|
small,
|
||||||
big
|
big
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
$container.prepend(container);
|
$container.prepend(container);
|
||||||
return container;
|
|
||||||
};
|
onRedraw.reg(function () {
|
||||||
addControls();
|
// Redraw if new tags have been added to items
|
||||||
|
var old = Sortify(existing);
|
||||||
|
var t = getTags();
|
||||||
|
existing = getExistingTags(kanban.options.boards);
|
||||||
|
if (old === Sortify(existing)) { return; } // No change
|
||||||
|
// New tags:
|
||||||
|
redrawList(existing);
|
||||||
|
setTags(t);
|
||||||
|
});
|
||||||
|
framework._.sfCommon.getPadAttribute('tagsFilter', function (err, res) {
|
||||||
|
if (!err && Array.isArray(res)) {
|
||||||
|
setTags(res);
|
||||||
|
commitTags();
|
||||||
|
}
|
||||||
|
});
|
||||||
framework._.sfCommon.getPadAttribute('quickMode', function (err, res) {
|
framework._.sfCommon.getPadAttribute('quickMode', function (err, res) {
|
||||||
if (!err && res) {
|
if (!err && res) {
|
||||||
$container.addClass('cp-kanban-quick');
|
$container.addClass('cp-kanban-quick');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
addControls();
|
||||||
|
|
||||||
return kanban;
|
return kanban;
|
||||||
};
|
};
|
||||||
@ -795,7 +870,6 @@ define([
|
|||||||
var end = input.selectionEnd;
|
var end = input.selectionEnd;
|
||||||
|
|
||||||
var json = kanban.getBoardJSON(id) || kanban.getItemJSON(id);
|
var json = kanban.getBoardJSON(id) || kanban.getItemJSON(id);
|
||||||
// XXX only title for now...
|
|
||||||
var oldVal = json && json.title;
|
var oldVal = json && json.title;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -73,6 +73,7 @@
|
|||||||
colorClick: function (el, type) {},
|
colorClick: function (el, type) {},
|
||||||
addItemClick: function (el, boardId) {},
|
addItemClick: function (el, boardId) {},
|
||||||
renderMd: function (md) {},
|
renderMd: function (md) {},
|
||||||
|
refresh: function () {},
|
||||||
onChange: function () {}
|
onChange: function () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -526,6 +527,7 @@
|
|||||||
}
|
}
|
||||||
this.options.boards = boards;
|
this.options.boards = boards;
|
||||||
this.addBoards();
|
this.addBoards();
|
||||||
|
self.options.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.findBoard = function (id) {
|
this.findBoard = function (id) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user