diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index b8a082f2f..862630e9b 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -724,30 +724,7 @@ template(name="copyChecklistToManyCardsPopup") label(for='copy-checklist-cards-title') {{_ 'copyChecklistToManyCardsPopup-instructions'}}: textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus) | {{_ 'copyChecklistToManyCardsPopup-format'}} - +boardsAndLists - -template(name="boardsAndLists") - unless currentUser.isWorker - label {{_ 'boards'}}: - select.js-select-boards(autofocus) - each boards - if $eq _id currentBoard._id - option(value="{{_id}}" selected) {{_ 'current'}} - else - option(value="{{_id}}" selected="{{#if isMoveAndCopyDialogOptionBoardId _id}}selected{{/if}}") {{title}} - - label {{_ 'swimlanes'}}: - select.js-select-swimlanes - each swimlanes - option(value="{{_id}}" selected="{{#if isMoveAndCopyDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}} - - label {{_ 'lists'}}: - select.js-select-lists - each aBoardLists - option(value="{{_id}}" selected="{{#if isMoveAndCopyDialogOptionListId _id}}selected{{/if}}") {{title}} - - .edit-controls.clearfix - button.primary.confirm.js-done {{_ 'done'}} + +copyAndMoveCard template(name="copyAndMoveCard") unless currentUser.isWorker diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 6fc2fbf1e..a5af18272 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -1057,113 +1057,6 @@ class DialogWithBoardSwimlaneList extends BlazeComponent { } }).register('copyCardPopup'); -BlazeComponent.extendComponent({ - onCreated() { - this.currentBoardId = Utils.getCurrentBoardId(); - this.selectedBoardId = new ReactiveVar(this.currentBoardId); - this.setMoveAndCopyDialogOption(this.currentBoardId); - }, - - /** set the last confirmed dialog field values - * @param boardId the current board id - */ - setMoveAndCopyDialogOption(boardId) { - this.moveAndCopyDialogOption = { - 'boardId': "", - 'swimlaneId': "", - 'listId': "", - } - - let currentOptions = Meteor.user().getMoveAndCopyDialogOptions(); - if (currentOptions && boardId && currentOptions[boardId]) { - this.moveAndCopyDialogOption = currentOptions[boardId]; - if (this.moveAndCopyDialogOption.boardId) { - this.selectedBoardId.set(this.moveAndCopyDialogOption.boardId) - } - } - subManager.subscribe('board', this.selectedBoardId.get(), false); - }, - - /** returns if the board id was the last confirmed one - * @param boardId check this board id - * @return if the board id was the last confirmed one - */ - isMoveAndCopyDialogOptionBoardId(boardId) { - let ret = this.moveAndCopyDialogOption.boardId == boardId; - return ret; - }, - - /** returns if the swimlane id was the last confirmed one - * @param swimlaneId check this swimlane id - * @return if the swimlane id was the last confirmed one - */ - isMoveAndCopyDialogOptionSwimlaneId(swimlaneId) { - let ret = this.moveAndCopyDialogOption.swimlaneId == swimlaneId; - return ret; - }, - - /** returns if the list id was the last confirmed one - * @param listId check this list id - * @return if the list id was the last confirmed one - */ - isMoveAndCopyDialogOptionListId(listId) { - let ret = this.moveAndCopyDialogOption.listId == listId; - return ret; - }, - - boards() { - return Boards.find( - { - archived: false, - 'members.userId': Meteor.userId(), - _id: { $ne: Meteor.user().getTemplatesBoardId() }, - }, - { - sort: { sort: 1 /* boards default sorting */ }, - }, - ); - }, - - swimlanes() { - const board = Boards.findOne(this.selectedBoardId.get()); - return board.swimlanes(); - }, - - aBoardLists() { - const board = Boards.findOne(this.selectedBoardId.get()); - return board.lists(); - }, - - events() { - return [ - { - 'click .js-done'() { - const boardSelect = this.$('.js-select-boards')[0]; - const boardId = boardSelect.options[boardSelect.selectedIndex].value; - - const listSelect = this.$('.js-select-lists')[0]; - const listId = listSelect.options[listSelect.selectedIndex].value; - - const swimlaneSelect = this.$('.js-select-swimlanes')[0]; - const swimlaneId = swimlaneSelect.options[swimlaneSelect.selectedIndex].value; - - const options = { - 'boardId': boardId, - 'swimlaneId': swimlaneId, - 'listId': listId, - } - Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options); - }, - 'change .js-select-boards'(event) { - const boardId = $(event.currentTarget).val(); - this.selectedBoardId.set(boardId); - subManager.subscribe('board', boardId, false); - }, - }, - ]; - }, -}).register('boardsAndLists'); - Template.convertChecklistItemToCardPopup.events({ 'click .js-done'() { const card = Utils.getCurrentCard(); @@ -1192,60 +1085,47 @@ Template.convertChecklistItemToCardPopup.events({ }, }); -Template.copyChecklistToManyCardsPopup.events({ - 'click .js-done'() { - const card = Utils.getCurrentCard(); - const oldId = card._id; - card._id = null; - const lSelect = $('.js-select-lists')[0]; - card.listId = lSelect.options[lSelect.selectedIndex].value; - const slSelect = $('.js-select-swimlanes')[0]; - card.swimlaneId = slSelect.options[slSelect.selectedIndex].value; - const bSelect = $('.js-select-boards')[0]; - card.boardId = bSelect.options[bSelect.selectedIndex].value; - const textarea = $('#copy-card-title'); - const titleEntry = textarea.val().trim(); - // insert new card to the bottom of new list - card.sort = Lists.findOne(card.listId).cards().count(); +/** Copy many cards dialog */ +(class extends DialogWithBoardSwimlaneList { + getCardDialogOptions() { + const ret = Meteor.user().getMoveAndCopyDialogOptions(); + return ret; + } + setDone(boardId, swimlaneId, listId, options) { + Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options); + const card = this.data(); - if (titleEntry) { - const titleList = JSON.parse(titleEntry); + const textarea = this.$('#copy-card-title'); + const title = textarea.val().trim(); + + if (title) { + const oldTitle = card.title; + + const titleList = JSON.parse(title); for (let i = 0; i < titleList.length; i++) { const obj = titleList[i]; card.title = obj.title; card.description = obj.description; card.coverId = ''; - const _id = Cards.insert(card); + + // insert new card to the top of new list + const maxOrder = card.getMaxSort(listId, swimlaneId); + card.sort = maxOrder + 1; + + const newCardId = card.copy(boardId, swimlaneId, listId); + // In case the filter is active we need to add the newly inserted card in // the list of exceptions -- cards that are not filtered. Otherwise the // card will disappear instantly. // See https://github.com/wekan/wekan/issues/80 - Filter.addException(_id); - - // copy checklists - Checklists.find({ cardId: oldId }).forEach((ch) => { - ch.copy(_id); - }); - - // copy subtasks - const cursor = Cards.find({ parentId: oldId }); - cursor.forEach(function () { - 'use strict'; - const subtask = arguments[0]; - subtask.parentId = _id; - subtask._id = null; - /* const newSubtaskId = */ Cards.insert(subtask); - }); - - // copy card comments - CardComments.find({ cardId: oldId }).forEach((cmt) => { - cmt.copy(_id); - }); + Filter.addException(newCardId); } - Popup.back(); + + // restore the old card title, otherwise the card title would change in the current view (only temporary) + card.title = oldTitle; } - }, -}); + } +}).register('copyChecklistToManyCardsPopup'); BlazeComponent.extendComponent({ onCreated() { diff --git a/models/cards.js b/models/cards.js index ef4b2003e..4a3497c6a 100644 --- a/models/cards.js +++ b/models/cards.js @@ -609,6 +609,8 @@ Cards.helpers({ CardComments.find({ cardId: oldId }).forEach(cmt => { cmt.copy(_id); }); + // restore the id, otherwise new copies will fail + this._id = oldId; return _id; },