From 7651c00d572d7d77fad5a86c4c6f75d48944dbe8 Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Mon, 10 Jan 2022 23:43:29 +0100 Subject: [PATCH 1/5] Add actions menu to checklist --- client/components/cards/checklists.jade | 5 +++++ client/components/cards/checklists.js | 1 + client/components/cards/checklists.styl | 5 +++++ i18n/en.i18n.json | 3 ++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/client/components/cards/checklists.jade b/client/components/cards/checklists.jade index 531ada257..350da35b1 100644 --- a/client/components/cards/checklists.jade +++ b/client/components/cards/checklists.jade @@ -31,6 +31,7 @@ template(name="checklistDetail") .checklist-title span if canModifyCard + a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}") a.js-delete-checklist.toggle-delete-checklist-dialog {{_ "delete"}}... if canModifyCard @@ -133,3 +134,7 @@ template(name="boardsSwimlanesAndLists") .edit-controls.clearfix button.primary.confirm.js-done {{_ 'done'}} + +template(name="checklistActionsPopup") + ul.pop-over-list + li diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js index a1e76cd34..609e4b251 100644 --- a/client/components/cards/checklists.js +++ b/client/components/cards/checklists.js @@ -190,6 +190,7 @@ BlazeComponent.extendComponent({ return [ { ...events, + 'click .js-open-checklist-details-menu': Popup.open('checklistActions'), 'click .toggle-delete-checklist-dialog' : Popup.afterConfirm('checklistDelete', function () { Popup.close(); const checklist = this.checklist; diff --git a/client/components/cards/checklists.styl b/client/components/cards/checklists.styl index b78da0600..22e17df1d 100644 --- a/client/components/cards/checklists.styl +++ b/client/components/cards/checklists.styl @@ -142,3 +142,8 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item background: #dbdbdb color: #222 box-shadow: 0 1px 2px rgba(0,0,0,.2) + +.checklist-details-menu + float: right + padding-top: 6px + margin-right: 10px diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 06cee4af3..94460e7e5 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -1138,5 +1138,6 @@ "custom-legal-notice-link-url": "Custom legal notice page URL", "acceptance_of_our_legalNotice": "By continuing, you accept our", "legalNotice": "legal notice", - "copied": "Copied!" + "copied": "Copied!", + "checklistActionsPopup-title": "Checklist Actions" } From e40e42103e15d24da1304d8e52637f565b401646 Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Tue, 11 Jan 2022 19:26:44 +0100 Subject: [PATCH 2/5] Delete checklist moved to checklist menu action --- client/components/cards/checklists.jade | 4 +++- client/components/cards/checklists.js | 23 ++++++++++++++++------- client/components/cards/checklists.styl | 3 --- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/client/components/cards/checklists.jade b/client/components/cards/checklists.jade index 350da35b1..ce3ff17a9 100644 --- a/client/components/cards/checklists.jade +++ b/client/components/cards/checklists.jade @@ -32,7 +32,6 @@ template(name="checklistDetail") span if canModifyCard a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}") - a.js-delete-checklist.toggle-delete-checklist-dialog {{_ "delete"}}... if canModifyCard h2.title.js-open-inlined-form.is-editable @@ -138,3 +137,6 @@ template(name="boardsSwimlanesAndLists") template(name="checklistActionsPopup") ul.pop-over-list li + a.js-delete-checklist.delete-checklist + i.fa.fa-trash + | {{_ "delete"}}... diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js index 609e4b251..745740895 100644 --- a/client/components/cards/checklists.js +++ b/client/components/cards/checklists.js @@ -191,13 +191,6 @@ BlazeComponent.extendComponent({ { ...events, 'click .js-open-checklist-details-menu': Popup.open('checklistActions'), - 'click .toggle-delete-checklist-dialog' : Popup.afterConfirm('checklistDelete', function () { - Popup.close(); - const checklist = this.checklist; - if (checklist && checklist._id) { - Checklists.remove(checklist._id); - } - }), 'submit .js-add-checklist': this.addChecklist, 'submit .js-edit-checklist-title': this.editChecklist, 'submit .js-add-checklist-item': this.addChecklistItem, @@ -294,6 +287,22 @@ BlazeComponent.extendComponent({ } }).register('addChecklistItemForm'); +BlazeComponent.extendComponent({ + events() { + return [ + { + 'click .js-delete-checklist' : Popup.afterConfirm('checklistDelete', function () { + Popup.back(2); + const checklist = this.checklist; + if (checklist && checklist._id) { + Checklists.remove(checklist._id); + } + }), + } + ] + } +}).register('checklistActionsPopup'); + BlazeComponent.extendComponent({ onRendered() { autosize(this.$('textarea.js-edit-checklist-item')); diff --git a/client/components/cards/checklists.styl b/client/components/cards/checklists.styl index 22e17df1d..c711eb3b9 100644 --- a/client/components/cards/checklists.styl +++ b/client/components/cards/checklists.styl @@ -39,9 +39,6 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item &.is-finished color: #3cb500 - .js-delete-checklist - @extends .delete-text - span.fa.checklist-handle padding-right: 20px padding-top: 3px From 395452b54f6512e1422cd1db6d01632899ac61e8 Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Tue, 11 Jan 2022 19:36:52 +0100 Subject: [PATCH 3/5] Added spaces to delete checklist menu action --- client/components/cards/checklists.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/components/cards/checklists.jade b/client/components/cards/checklists.jade index ce3ff17a9..2a3055e41 100644 --- a/client/components/cards/checklists.jade +++ b/client/components/cards/checklists.jade @@ -139,4 +139,4 @@ template(name="checklistActionsPopup") li a.js-delete-checklist.delete-checklist i.fa.fa-trash - | {{_ "delete"}}... + | {{_ "delete"}} ... From a66257ec2145d08a6d63f5a86a82dccbc0b4af2d Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Tue, 11 Jan 2022 19:42:57 +0100 Subject: [PATCH 4/5] Added "Move Checklist" to checklist menu action --- client/components/cards/checklists.jade | 31 +++++ client/components/cards/checklists.js | 153 ++++++++++++++++++++++++ i18n/en.i18n.json | 4 +- models/checklists.js | 31 +++++ models/users.js | 56 +++++++++ 5 files changed, 274 insertions(+), 1 deletion(-) diff --git a/client/components/cards/checklists.jade b/client/components/cards/checklists.jade index 2a3055e41..d387de307 100644 --- a/client/components/cards/checklists.jade +++ b/client/components/cards/checklists.jade @@ -140,3 +140,34 @@ template(name="checklistActionsPopup") a.js-delete-checklist.delete-checklist i.fa.fa-trash | {{_ "delete"}} ... + a.js-move-checklist.move-checklist + i.fa.fa-arrow-right + | {{_ "moveChecklist"}} ... + +template(name="moveChecklistPopup") + 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 isMoveChecklistDialogOptionBoardId _id}}selected{{/if}}") {{title}} + + label {{_ 'swimlanes'}}: + select.js-select-swimlanes + each swimlanes + option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}} + + label {{_ 'lists'}}: + select.js-select-lists + each lists + option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionListId _id}}selected{{/if}}") {{title}} + + label {{_ 'cards'}}: + select.js-select-cards + each cards + option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionCardId _id}}selected{{/if}}") {{title}} + + .edit-controls.clearfix + button.primary.confirm.js-done {{_ 'done'}} diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js index 745740895..fcb404b95 100644 --- a/client/components/cards/checklists.js +++ b/client/components/cards/checklists.js @@ -298,6 +298,7 @@ BlazeComponent.extendComponent({ Checklists.remove(checklist._id); } }), + 'click .js-move-checklist' : Popup.open('moveChecklist'), } ] } @@ -362,3 +363,155 @@ BlazeComponent.extendComponent({ ]; }, }).register('checklistItemDetail'); + +BlazeComponent.extendComponent({ + onCreated() { + const boardId = Utils.getCurrentBoardId(); + subManager.subscribe('board', boardId, false); + // subManager.subscribe('swimlane', swimlaneId, false); + // subManager.subscribe('list', listId, false); + // subManager.subscribe('card', cardId, false); + this.selectedBoardId = new ReactiveVar(boardId); + this.selectedSwimlaneId = new ReactiveVar(''); + this.selectedListId = new ReactiveVar(''); + this.selectedCardId = new ReactiveVar(''); + this.setMoveChecklistDialogOption(boardId); + }, + + /** set the last confirmed dialog field values + * @param boardId the current board id + */ + setMoveChecklistDialogOption(boardId) { + this.moveChecklistDialogOption = { + 'boardId' : "", + 'swimlaneId' : "", + 'listId' : "", + 'cardId': "", + } + + let currentOptions = Meteor.user().getMoveChecklistDialogOptions(); + if (currentOptions && boardId && currentOptions[boardId]) { + this.moveChecklistDialogOption = currentOptions[boardId]; + } + const board = Boards.findOne(boardId); + try { + const swimlaneId = board.swimlanes().fetch()[0]._id; + this.selectedSwimlaneId.set(swimlaneId); + } catch (e) {} + + try { + const listId = board.lists().fetch()[0]; + this.selectedListId.set(listId); + } catch (e) {} + + const cardId = Utils.getCurrentCardId(); + this.selectedCardId.set(cardId); + }, + + /** 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 + */ + isMoveChecklistDialogOptionBoardId(boardId) { + let ret = this.moveChecklistDialogOption.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 + */ + isMoveChecklistDialogOptionSwimlaneId(swimlaneId) { + let ret = this.moveChecklistDialogOption.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 + */ + isMoveChecklistDialogOptionListId(listId) { + let ret = this.moveChecklistDialogOption.listId == listId; + return ret; + }, + + /** returns if the card id was the last confirmed one + * @param cardId check this card id + * @return if the card id was the last confirmed one + */ + isMoveChecklistDialogOptionCardId(cardId) { + let ret = this.moveChecklistDialogOption.cardId == cardId; + return ret; + }, + + boards() { + return Boards.find( + { + archived: false, + 'members.userId': Meteor.userId(), + _id: { $ne: Meteor.user().getTemplatesBoardId() }, + }, + { + sort: { sort: 1 }, + }, + ); + }, + + swimlanes() { + const board = Boards.findOne(this.selectedBoardId.get()); + return board.swimlanes(); + }, + + lists() { + const board = Boards.findOne(this.selectedBoardId.get()); + return board.lists(); + }, + + cards() { + const list = Lists.findOne(this.selectedListId.get()); + const ret = list.cards(this.selectedSwimlaneId.get()); + return ret; + }, + + 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 cardSelect = this.$('.js-select-cards')[0]; + const cardId = cardSelect.options[cardSelect.selectedIndex].value; + + const options = { + 'boardId' : boardId, + 'swimlaneId' : swimlaneId, + 'listId' : listId, + 'cardId': cardId, + } + Meteor.user().setMoveChecklistDialogOption(boardId, options); + this.data().checklist.move(cardId); + Popup.back(2); + }, + 'change .js-select-boards'(event) { + const boardId = $(event.currentTarget).val(); + subManager.subscribe('board', boardId, false); + this.setMoveChecklistDialogOption(boardId); + this.selectedBoardId.set(boardId); + }, + 'change .js-select-swimlanes'(event) { + this.selectedSwimlaneId.set($(event.currentTarget).val()); + }, + 'change .js-select-lists'(event) { + this.selectedListId.set($(event.currentTarget).val()); + }, + }, + ]; + }, +}).register('moveChecklistPopup'); diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 94460e7e5..39dad5c4b 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -1139,5 +1139,7 @@ "acceptance_of_our_legalNotice": "By continuing, you accept our", "legalNotice": "legal notice", "copied": "Copied!", - "checklistActionsPopup-title": "Checklist Actions" + "checklistActionsPopup-title": "Checklist Actions", + "moveChecklist": "Move Checklist", + "moveChecklistPopup-title": "Move Checklist" } diff --git a/models/checklists.js b/models/checklists.js index 30a6f2c2d..0e76d4001 100644 --- a/models/checklists.js +++ b/models/checklists.js @@ -147,6 +147,37 @@ Checklists.mutations({ setTitle(title) { return { $set: { title } }; }, + /** move the checklist to another card + * @param newCardId move the checklist to this cardId + */ + move(newCardId) { + // update every activity + Activities.find( + {checklistId: this._id} + ).forEach(activity => { + Activities.update(activity._id, { + $set: { + cardId: newCardId, + }, + }); + }); + // update every checklist-item + ChecklistItems.find( + {checklistId: this._id} + ).forEach(checklistItem => { + ChecklistItems.update(checklistItem._id, { + $set: { + cardId: newCardId, + }, + }); + }); + // update the checklist itself + return { + $set: { + cardId: newCardId, + }, + }; + }, }); if (Meteor.isServer) { diff --git a/models/users.js b/models/users.js index 98f658412..60047a17a 100644 --- a/models/users.js +++ b/models/users.js @@ -252,6 +252,38 @@ Users.attachSchema( */ type: String, }, + 'profile.moveChecklistDialog' : { + /** + * move and copy card dialog + */ + type: Object, + optional: true, + blackbox: true, + }, + 'profile.moveChecklistDialog.$.boardId': { + /** + * last selected board id + */ + type: String, + }, + 'profile.moveChecklistDialog.$.swimlaneId': { + /** + * last selected swimlane id + */ + type: String, + }, + 'profile.moveChecklistDialog.$.listId': { + /** + * last selected list id + */ + type: String, + }, + 'profile.moveChecklistDialog.$.cardId': { + /** + * last selected card id + */ + type: String, + }, 'profile.notifications': { /** * enabled notifications for the user @@ -653,6 +685,17 @@ Users.helpers({ return _ret; }, + /** returns all confirmed move checklist dialog field values + *
  • the board, swimlane, list and card id is stored for each board + */ + getMoveChecklistDialogOptions() { + let _ret = {} + if (this.profile && this.profile.moveChecklistDialog) { + _ret = this.profile.moveChecklistDialog; + } + return _ret; + }, + hasTag(tag) { const { tags = [] } = this.profile || {}; return _.contains(tags, tag); @@ -781,6 +824,19 @@ Users.mutations({ }, }; }, + /** set the confirmed board id/swimlane id/list id/card id of a board + * @param boardId the current board id + * @param options an object with the confirmed field values + */ + setMoveChecklistDialogOption(boardId, options) { + let currentOptions = this.getMoveChecklistDialogOptions(); + currentOptions[boardId] = options; + return { + $set: { + 'profile.moveChecklistDialog': currentOptions, + }, + }; + }, toggleBoardStar(boardId) { const queryKind = this.hasStarred(boardId) ? '$pull' : '$addToSet'; return { From a72d51d9019e5ead7e27dfeda1167bc96a4d105a Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Mon, 17 Jan 2022 23:17:58 +0100 Subject: [PATCH 5/5] Checklist Action-Menu easier clickable - especially useful at mobile devices --- client/components/cards/checklists.styl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/components/cards/checklists.styl b/client/components/cards/checklists.styl index c711eb3b9..b9983e32d 100644 --- a/client/components/cards/checklists.styl +++ b/client/components/cards/checklists.styl @@ -142,5 +142,4 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item .checklist-details-menu float: right - padding-top: 6px - margin-right: 10px + padding: 6px 10px 6px 10px