diff options
author | Andrés Manelli <andresmanelli@gmail.com> | 2019-02-25 22:48:25 +0100 |
---|---|---|
committer | Andrés Manelli <andresmanelli@gmail.com> | 2019-02-25 22:48:32 +0100 |
commit | dc7286a0ef8111c0855129911492588ba8a384df (patch) | |
tree | dcc4f9be071a1bf55d1f2638ed63c958e0a42634 | |
parent | 13c2157e36f65be4138a85fae0379e0fe31f02bd (diff) | |
download | wekan-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.jade | 2 | ||||
-rw-r--r-- | client/components/boards/boardHeader.jade | 5 | ||||
-rw-r--r-- | client/components/boards/boardHeader.js | 1 | ||||
-rw-r--r-- | client/components/boards/miniboard.jade | 8 | ||||
-rw-r--r-- | client/components/lists/listBody.jade | 17 | ||||
-rw-r--r-- | client/components/lists/listBody.js | 55 | ||||
-rwxr-xr-x | client/components/main/editor.js | 4 | ||||
-rw-r--r-- | models/boards.js | 36 | ||||
-rw-r--r-- | models/cardComments.js | 2 | ||||
-rw-r--r-- | models/cards.js | 2 | ||||
-rw-r--r-- | models/lists.js | 6 | ||||
-rw-r--r-- | models/swimlanes.js | 19 |
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: '@', 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); }); |