summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrés Manelli <andresmanelli@gmail.com>2019-02-25 22:48:25 +0100
committerAndrés Manelli <andresmanelli@gmail.com>2019-02-25 22:48:32 +0100
commitdc7286a0ef8111c0855129911492588ba8a384df (patch)
treedcc4f9be071a1bf55d1f2638ed63c958e0a42634
parent13c2157e36f65be4138a85fae0379e0fe31f02bd (diff)
downloadwekan-dc7286a0ef8111c0855129911492588ba8a384df.tar.gz
wekan-dc7286a0ef8111c0855129911492588ba8a384df.tar.bz2
wekan-dc7286a0ef8111c0855129911492588ba8a384df.zip
Fix list view issues. Allow creation of boards from templates
-rw-r--r--client/components/boards/boardBody.jade2
-rw-r--r--client/components/boards/boardHeader.jade5
-rw-r--r--client/components/boards/boardHeader.js1
-rw-r--r--client/components/boards/miniboard.jade8
-rw-r--r--client/components/lists/listBody.jade17
-rw-r--r--client/components/lists/listBody.js55
-rwxr-xr-xclient/components/main/editor.js4
-rw-r--r--models/boards.js36
-rw-r--r--models/cardComments.js2
-rw-r--r--models/cards.js2
-rw-r--r--models/lists.js6
-rw-r--r--models/swimlanes.js19
12 files changed, 122 insertions, 35 deletions
diff --git a/client/components/boards/boardBody.jade b/client/components/boards/boardBody.jade
index e36058f6..32f8629f 100644
--- a/client/components/boards/boardBody.jade
+++ b/client/components/boards/boardBody.jade
@@ -27,7 +27,7 @@ template(name="boardBody")
each currentBoard.swimlanes
+swimlane(this)
else if isViewLists
- +listsGroup
+ +listsGroup(currentBoard)
else if isViewCalendar
+calendarView
diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade
index 4c9d6e43..1f6462bd 100644
--- a/client/components/boards/boardHeader.jade
+++ b/client/components/boards/boardHeader.jade
@@ -277,7 +277,10 @@ template(name="createBoard")
input.primary.wide(type="submit" value="{{_ 'create'}}")
span.quiet
| {{_ 'or'}}
- a.js-import-board {{_ 'import-board'}}
+ a.js-import-board {{_ 'import'}}
+ span.quiet
+ | /
+ a.js-board-template {{_ 'template'}}
template(name="chooseBoardSource")
ul.pop-over-list
diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js
index 89f686ab..492fda40 100644
--- a/client/components/boards/boardHeader.js
+++ b/client/components/boards/boardHeader.js
@@ -304,6 +304,7 @@ const CreateBoard = BlazeComponent.extendComponent({
'click .js-import': Popup.open('boardImportBoard'),
submit: this.onSubmit,
'click .js-import-board': Popup.open('chooseBoardSource'),
+ 'click .js-board-template': Popup.open('searchElement'),
}];
},
}).register('createBoardPopup');
diff --git a/client/components/boards/miniboard.jade b/client/components/boards/miniboard.jade
new file mode 100644
index 00000000..d1fb0b07
--- /dev/null
+++ b/client/components/boards/miniboard.jade
@@ -0,0 +1,8 @@
+template(name="miniboard")
+ .minicard(
+ class="minicard-{{colorClass}}")
+ .minicard-title
+ .handle
+ .fa.fa-arrows
+ +viewer
+ = title
diff --git a/client/components/lists/listBody.jade b/client/components/lists/listBody.jade
index fcc28777..b8e2adc7 100644
--- a/client/components/lists/listBody.jade
+++ b/client/components/lists/listBody.jade
@@ -103,16 +103,23 @@ template(name="searchElementPopup")
input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus)
.list-body.js-perfect-scrollbar.search-card-results
.minicards.clearfix.js-minicards
- each results
- if isListTemplateSearch
+ if isBoardTemplateSearch
+ each results
+ a.minicard-wrapper.js-minicard
+ +miniboard(this)
+ if isListTemplateSearch
+ each results
a.minicard-wrapper.js-minicard
+minilist(this)
- if isSwimlaneTemplateSearch
+ if isSwimlaneTemplateSearch
+ each results
a.minicard-wrapper.js-minicard
+miniswimlane(this)
- if isCardTemplateSearch
+ if isCardTemplateSearch
+ each results
a.minicard-wrapper.js-minicard
+minicard(this)
- unless isTemplateSearch
+ unless isTemplateSearch
+ each results
a.minicard-wrapper.js-minicard
+minicard(this)
diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js
index 7b3dc6a6..5a3862f3 100644
--- a/client/components/lists/listBody.js
+++ b/client/components/lists/listBody.js
@@ -527,7 +527,11 @@ BlazeComponent.extendComponent({
this.isCardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-card-template');
this.isListTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-list-template');
this.isSwimlaneTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-open-add-swimlane-menu');
- this.isTemplateSearch = this.isCardTemplateSearch || this.isListTemplateSearch || this.isSwimlaneTemplateSearch;
+ this.isBoardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-add-board');
+ this.isTemplateSearch = this.isCardTemplateSearch ||
+ this.isListTemplateSearch ||
+ this.isSwimlaneTemplateSearch ||
+ this.isBoardTemplateSearch;
let board = {};
if (this.isTemplateSearch) {
board = Boards.findOne(Meteor.user().profile.templatesBoardId);
@@ -548,23 +552,26 @@ BlazeComponent.extendComponent({
subManager.subscribe('board', boardId);
this.selectedBoardId = new ReactiveVar(boardId);
- this.boardId = Session.get('currentBoard');
- // In order to get current board info
- subManager.subscribe('board', this.boardId);
- // List where to insert card
- const list = $(Popup._getTopStack().openerElement).closest('.js-list');
- this.listId = Blaze.getData(list[0])._id;
- // Swimlane where to insert card
- const swimlane = $(Popup._getTopStack().openerElement).parents('.js-swimlane');
- this.swimlaneId = '';
- if (Meteor.user().profile.boardView === 'board-view-swimlanes')
- this.swimlaneId = Blaze.getData(swimlane[0])._id;
- else
- this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
+ if (!this.isBoardTemplateSearch) {
+ this.boardId = Session.get('currentBoard');
+ // In order to get current board info
+ subManager.subscribe('board', this.boardId);
+ this.swimlaneId = '';
+ // Swimlane where to insert card
+ const swimlane = $(Popup._getTopStack().openerElement).parents('.js-swimlane');
+ if (Meteor.user().profile.boardView === 'board-view-swimlanes')
+ this.swimlaneId = Blaze.getData(swimlane[0])._id;
+ else
+ this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
+ // List where to insert card
+ const list = $(Popup._getTopStack().openerElement).closest('.js-list');
+ this.listId = Blaze.getData(list[0])._id;
+ }
this.term = new ReactiveVar('');
},
boards() {
+ console.log('booom');
const boards = Boards.find({
archived: false,
'members.userId': Meteor.userId(),
@@ -587,6 +594,12 @@ BlazeComponent.extendComponent({
return board.searchLists(this.term.get());
} else if (this.isSwimlaneTemplateSearch) {
return board.searchSwimlanes(this.term.get());
+ } else if (this.isBoardTemplateSearch) {
+ const boards = board.searchBoards(this.term.get());
+ boards.forEach((board) => {
+ subManager.subscribe('board', board.linkedId);
+ });
+ return boards;
} else {
return [];
}
@@ -605,11 +618,11 @@ BlazeComponent.extendComponent({
'click .js-minicard'(evt) {
// 0. Common
const element = Blaze.getData(evt.currentTarget);
- element.boardId = this.boardId;
let _id = '';
if (!this.isTemplateSearch || this.isCardTemplateSearch) {
// Card insertion
// 1. Common
+ element.boardId = this.boardId;
element.listId = this.listId;
element.swimlaneId = this.swimlaneId;
element.sort = Lists.findOne(this.listId).cards().count();
@@ -620,7 +633,7 @@ BlazeComponent.extendComponent({
_id = element.copy();
// 1.B Linked card
} else {
- element._id = null;
+ delete element._id;
element.type = 'cardType-linkedCard';
element.linkedId = element.linkedId || element._id;
_id = Cards.insert(element);
@@ -628,14 +641,22 @@ BlazeComponent.extendComponent({
Filter.addException(_id);
// List insertion
} else if (this.isListTemplateSearch) {
+ element.boardId = this.boardId;
element.sort = Swimlanes.findOne(this.swimlaneId).lists().count();
element.type = 'list';
- element.swimlaneId = '';
_id = element.copy(this.swimlaneId);
} else if (this.isSwimlaneTemplateSearch) {
+ element.boardId = this.boardId;
element.sort = Boards.findOne(this.boardId).swimlanes().count();
element.type = 'swimlalne';
_id = element.copy();
+ } else if (this.isBoardTemplateSearch) {
+ board = Boards.findOne(element.linkedId);
+ board.sort = Boards.find({archived: false}).count();
+ board.type = 'board';
+ delete board.slug;
+ delete board.members;
+ _id = board.copy();
}
Popup.close();
},
diff --git a/client/components/main/editor.js b/client/components/main/editor.js
index 20ece562..88d8abf0 100755
--- a/client/components/main/editor.js
+++ b/client/components/main/editor.js
@@ -36,7 +36,10 @@ import sanitizeXss from 'xss';
const at = HTML.CharRef({html: '&commat;', str: '@'});
Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
const view = this;
+ let content = Blaze.toHTML(view.templateContentBlock);
const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ if (!currentBoard)
+ return HTML.Raw(sanitizeXss(content));
const knowedUsers = currentBoard.members.map((member) => {
const u = Users.findOne(member.userId);
if(u){
@@ -45,7 +48,6 @@ Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
return member;
});
const mentionRegex = /\B@([\w.]*)/gi;
- let content = Blaze.toHTML(view.templateContentBlock);
let currentMention;
while ((currentMention = mentionRegex.exec(content)) !== null) {
diff --git a/models/boards.js b/models/boards.js
index 0d3213bc..0db2e48e 100644
--- a/models/boards.js
+++ b/models/boards.js
@@ -315,6 +315,21 @@ Boards.attachSchema(new SimpleSchema({
Boards.helpers({
+ copy() {
+ const oldId = this._id;
+ delete this._id;
+ const _id = Boards.insert(this);
+
+ // Copy all swimlanes in board
+ Swimlanes.find({
+ boardId: oldId,
+ archived: false,
+ }).forEach((swimlane) => {
+ swimlane.type = 'swimlane';
+ swimlane.boardId = _id;
+ swimlane.copy(oldId);
+ });
+ },
/**
* Is supplied user authorized to view this board?
*/
@@ -463,6 +478,27 @@ Boards.helpers({
return _id;
},
+ searchBoards(term) {
+ check(term, Match.OneOf(String, null, undefined));
+
+ const query = { boardId: this._id };
+ query.type = 'cardType-linkedBoard';
+ query.archived = false;
+
+ const projection = { limit: 10, sort: { createdAt: -1 } };
+
+ if (term) {
+ const regex = new RegExp(term, 'i');
+
+ query.$or = [
+ { title: regex },
+ { description: regex },
+ ];
+ }
+
+ return Cards.find(query, projection);
+ },
+
searchSwimlanes(term) {
check(term, Match.OneOf(String, null, undefined));
diff --git a/models/cardComments.js b/models/cardComments.js
index f29366a5..fcb97104 100644
--- a/models/cardComments.js
+++ b/models/cardComments.js
@@ -69,7 +69,7 @@ CardComments.allow({
CardComments.helpers({
copy(newCardId) {
this.cardId = newCardId;
- this._id = null;
+ delete this._id;
CardComments.insert(this);
},
diff --git a/models/cards.js b/models/cards.js
index e91f0af5..c733c7f8 100644
--- a/models/cards.js
+++ b/models/cards.js
@@ -274,7 +274,7 @@ Cards.allow({
Cards.helpers({
copy() {
const oldId = this._id;
- this._id = null;
+ delete this._id;
const _id = Cards.insert(this);
// copy checklists
diff --git a/models/lists.js b/models/lists.js
index bf2430ee..d76c961c 100644
--- a/models/lists.js
+++ b/models/lists.js
@@ -139,20 +139,24 @@ Lists.allow({
Lists.helpers({
copy(swimlaneId) {
const oldId = this._id;
+ const oldSwimlaneId = this.swimlaneId || null;
let _id = null;
existingListWithSameName = Lists.findOne({
boardId: this.boardId,
title: this.title,
+ archived: false,
});
if (existingListWithSameName) {
_id = existingListWithSameName._id;
} else {
- this._id = null;
+ delete this._id;
+ delete this.swimlaneId;
_id = Lists.insert(this);
}
// Copy all cards in list
Cards.find({
+ swimlaneId: oldSwimlaneId,
listId: oldId,
archived: false,
}).forEach((card) => {
diff --git a/models/swimlanes.js b/models/swimlanes.js
index d3548329..a3427fc6 100644
--- a/models/swimlanes.js
+++ b/models/swimlanes.js
@@ -101,18 +101,23 @@ Swimlanes.allow({
});
Swimlanes.helpers({
- copy() {
+ copy(oldBoardId) {
const oldId = this._id;
- this._id = null;
+ delete this._id;
const _id = Swimlanes.insert(this);
- // Copy all lists in swimlane
- Lists.find({
- swimlaneId: oldId,
+ const query = {
+ swimlaneId: {$in: [oldId, '']},
archived: false,
- }).forEach((list) => {
+ };
+ if (oldBoardId) {
+ query.boardId = oldBoardId;
+ }
+
+ // Copy all lists in swimlane
+ Lists.find(query).forEach((list) => {
list.type = 'list';
- list.swimlaneId = '';
+ list.swimlaneId = oldId;
list.boardId = this.boardId;
list.copy(_id);
});