diff options
-rw-r--r-- | client/components/cards/minicard.jade | 6 | ||||
-rw-r--r-- | client/components/cards/minicard.js | 9 | ||||
-rw-r--r-- | client/components/cards/minicard.styl | 37 | ||||
-rw-r--r-- | client/components/lists/listBody.jade | 13 | ||||
-rw-r--r-- | client/components/lists/listBody.js | 119 |
5 files changed, 159 insertions, 25 deletions
diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 3f7e0940..95fa6e31 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -1,5 +1,7 @@ template(name="minicard") - .minicard + .minicard( + class="{{#if importedCard}}imported-card{{/if}}" + class="{{#if importedBoard}}imported-board{{/if}}") if cover .minicard-cover(style="background-image: url('{{cover.url}}');") if labels @@ -13,6 +15,8 @@ template(name="minicard") if $eq 'prefix-with-parent' currentBoard.presentParentTask .parent-prefix | {{ parentCardName }} + if imported + span.imported-icon.fa.fa-share-alt +viewer | {{ title }} if $eq 'subtext-with-full-path' currentBoard.presentParentTask diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index a98b5730..5202232b 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -6,4 +6,13 @@ BlazeComponent.extendComponent({ template() { return 'minicard'; }, + importedCard() { + return this.currentData().type === 'cardType-importedCard'; + }, + importedBoard() { + return this.currentData().type === 'cardType-importedBoard'; + }, + imported() { + return this.importedCard() || this.importedBoard(); + }, }).register('minicard'); diff --git a/client/components/cards/minicard.styl b/client/components/cards/minicard.styl index 5624787c..ea737c6b 100644 --- a/client/components/cards/minicard.styl +++ b/client/components/cards/minicard.styl @@ -44,6 +44,41 @@ transition: transform 0.2s, border-radius 0.2s + &.imported-board + background-color: #efd8e6 + &:hover:not(.minicard-composer), + .is-selected &, + .draggable-hover-card & + background: darken(#efd8e6, 3%) + + .is-selected & + border-left: 3px solid darken(#efd8e6, 50%) + + .minicard-title + font-style: italic + font-weight: bold + + &.imported-card + background-color: #d5e4bd + &:hover:not(.minicard-composer), + .is-selected &, + .draggable-hover-card & + background: darken(#d5e4bd, 3%) + + .is-selected & + border-left: 3px solid darken(#d5e4bd, 50%) + + .minicard-title + font-style: italic + + &.imported-board + &.imported-card + .imported-icon + display: inline-block + margin-right: 11px + vertical-align: baseline + font-size: 0.9em + .is-selected & transform: translateX(11px) border-bottom-right-radius: 0 @@ -87,6 +122,8 @@ .minicard-title p:last-child margin-bottom: 0 + .viewer + display: inline-block .dates display: flex; flex-direction: row; diff --git a/client/components/lists/listBody.jade b/client/components/lists/listBody.jade index e0655fc2..419e158a 100644 --- a/client/components/lists/listBody.jade +++ b/client/components/lists/listBody.jade @@ -37,6 +37,10 @@ template(name="addCardForm") span.quiet | {{_ 'or'}} a.js-import {{_ 'import'}} + span.quiet + | + | / + a.js-search {{_ 'search'}} template(name="autocompleteLabelLine") .minicard-label(class="card-label-{{colorName}}" title=labelName) @@ -51,7 +55,7 @@ template(name="importCardPopup") option(value="{{_id}}" selected) {{_ 'current'}} else option(value="{{_id}}") {{title}} - input.primary.confirm.js-import-board(type="submit" value="{{_ 'add'}}") + input.primary.confirm.js-import-board(type="button" value="{{_ 'import'}}") label {{_ 'swimlanes'}}: select.js-select-swimlanes @@ -64,15 +68,12 @@ template(name="importCardPopup") option(value="{{_id}}") {{title}} label {{_ 'cards'}}: - select.js-select-lists + select.js-select-cards each cards option(value="{{_id}}") {{title}} .edit-controls.clearfix - input.primary.confirm.js-done(type="submit" value="{{_ 'done'}}") - span.quiet - | {{_ 'or'}} - a.js-search {{_ 'search'}} + input.primary.confirm.js-done(type="button" value="{{_ 'import'}}") template(name="searchCardPopup") label {{_ 'boards'}}: diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 1aece121..39614108 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -201,6 +201,7 @@ BlazeComponent.extendComponent({ return [{ keydown: this.pressKey, 'click .js-import': Popup.open('importCard'), + 'click .js-search': Popup.open('searchCard'), }]; }, @@ -275,14 +276,39 @@ BlazeComponent.extendComponent({ BlazeComponent.extendComponent({ onCreated() { - subManager.subscribe('board', Session.get('currentBoard')); - this.selectedBoardId = new ReactiveVar(Session.get('currentBoard')); + // Prefetch first non-current board id + const boardId = Boards.findOne({ + archived: false, + 'members.userId': Meteor.userId(), + _id: {$ne: Session.get('currentBoard')}, + })._id; + // Subscribe to this board + subManager.subscribe('board', boardId); + this.selectedBoardId = new ReactiveVar(boardId); + this.selectedSwimlaneId = new ReactiveVar(''); + this.selectedListId = new ReactiveVar(''); + + this.boardId = Session.get('currentBoard'); + // In order to get current board info + subManager.subscribe('board', this.boardId); + const board = Boards.findOne(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).closest('.js-swimlane'); + this.swimlaneId = ''; + if (board.view === 'board-view-swimlanes') + this.swimlaneId = Blaze.getData(swimlane[0])._id; + else + this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id; }, boards() { const boards = Boards.find({ archived: false, 'members.userId': Meteor.userId(), + _id: {$ne: Session.get('currentBoard')}, }, { sort: ['title'], }); @@ -290,18 +316,26 @@ BlazeComponent.extendComponent({ }, swimlanes() { - const board = Boards.findOne(this.selectedBoardId.get()); - return board.swimlanes(); + const swimlanes = Swimlanes.find({boardId: this.selectedBoardId.get()}); + if (swimlanes.count()) + this.selectedSwimlaneId.set(swimlanes.fetch()[0]._id); + return swimlanes; }, lists() { - const board = Boards.findOne(this.selectedBoardId.get()); - return board.lists(); + const lists = Lists.find({boardId: this.selectedBoardId.get()}); + if (lists.count()) + this.selectedListId.set(lists.fetch()[0]._id); + return lists; }, cards() { - const board = Boards.findOne(this.selectedBoardId.get()); - return board.cards(); + return Cards.find({ + boardId: this.selectedBoardId.get(), + swimlaneId: this.selectedSwimlaneId.get(), + listId: this.selectedListId.get(), + archived: false, + }); }, events() { @@ -310,24 +344,44 @@ BlazeComponent.extendComponent({ this.selectedBoardId.set($(evt.currentTarget).val()); subManager.subscribe('board', this.selectedBoardId.get()); }, - 'submit .js-done' (evt) { + 'change .js-select-swimlanes'(evt) { + this.selectedSwimlaneId.set($(evt.currentTarget).val()); + }, + 'change .js-select-lists'(evt) { + this.selectedListId.set($(evt.currentTarget).val()); + }, + 'click .js-done' (evt) { // IMPORT CARD + evt.stopPropagation(); evt.preventDefault(); - // XXX We should *not* get the currentCard from the global state, but - // instead from a “component” state. - const card = Cards.findOne(Session.get('currentCard')); - const lSelect = $('.js-select-lists')[0]; - const newListId = lSelect.options[lSelect.selectedIndex].value; - const slSelect = $('.js-select-swimlanes')[0]; - card.swimlaneId = slSelect.options[slSelect.selectedIndex].value; + const _id = Cards.insert({ + title: $('.js-select-cards option:selected').text(), //dummy + listId: this.listId, + swimlaneId: this.swimlaneId, + boardId: this.boardId, + sort: Lists.findOne(this.listId).cards().count(), + type: 'cardType-importedCard', + importedId: $('.js-select-cards option:selected').val(), + }); + Filter.addException(_id); Popup.close(); }, - 'submit .js-import-board' (evt) { + 'click .js-import-board' (evt) { //IMPORT BOARD + evt.stopPropagation(); evt.preventDefault(); + const _id = Cards.insert({ + title: $('.js-select-boards option:selected').text(), //dummy + listId: this.listId, + swimlaneId: this.swimlaneId, + boardId: this.boardId, + sort: Lists.findOne(this.listId).cards().count(), + type: 'cardType-importedBoard', + importedId: $('.js-select-boards option:selected').val(), + }); + Filter.addException(_id); Popup.close(); }, - 'click .js-search': Popup.open('searchCard'), }]; }, }).register('importCardPopup'); @@ -338,13 +392,30 @@ BlazeComponent.extendComponent({ }, onCreated() { + // Prefetch first non-current board id const boardId = Boards.findOne({ archived: false, 'members.userId': Meteor.userId(), _id: {$ne: Session.get('currentBoard')}, })._id; + // Subscribe to this board 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); + const board = Boards.findOne(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).closest('.js-swimlane'); + this.swimlaneId = ''; + if (board.view === 'board-view-swimlanes') + this.swimlaneId = Blaze.getData(swimlane[0])._id; + else + this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id; this.term = new ReactiveVar(''); }, @@ -376,6 +447,18 @@ BlazeComponent.extendComponent({ }, 'click .js-minicard'(evt) { // IMPORT CARD + const card = Blaze.getData(evt.currentTarget); + const _id = Cards.insert({ + title: card.title, //dummy + listId: this.listId, + swimlaneId: this.swimlaneId, + boardId: this.boardId, + sort: Lists.findOne(this.listId).cards().count(), + type: 'cardType-importedCard', + importedId: card._id, + }); + Filter.addException(_id); + Popup.close(); }, }]; }, |