瀏覽代碼

Copy Checklist added to checklist action popup

Relates to: #4306
Martin Filser 3 年之前
父節點
當前提交
3a2b50720e
共有 4 個文件被更改,包括 133 次插入28 次删除
  1. 13 4
      client/components/cards/checklists.jade
  2. 59 21
      client/components/cards/checklists.js
  3. 3 1
      i18n/en.i18n.json
  4. 58 2
      models/users.js

+ 13 - 4
client/components/cards/checklists.jade

@@ -153,8 +153,17 @@ template(name="checklistActionsPopup")
       a.js-move-checklist.move-checklist
         i.fa.fa-arrow-right
         | {{_ "moveChecklist"}} ...
+      a.js-copy-checklist.copy-checklist
+        i.fa.fa-copy
+        | {{_ "copyChecklist"}} ...
+
+template(name="copyChecklistPopup")
+  +copyAndMoveChecklist
 
 template(name="moveChecklistPopup")
+  +copyAndMoveChecklist
+
+template(name="copyAndMoveChecklist")
   unless currentUser.isWorker
     label {{_ 'boards'}}:
     select.js-select-boards(autofocus)
@@ -162,22 +171,22 @@ template(name="moveChecklistPopup")
         if $eq _id currentBoard._id
           option(value="{{_id}}" selected) {{_ 'current'}}
         else
-          option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionBoardId _id}}selected{{/if}}") {{title}}
+          option(value="{{_id}}" selected="{{#if isChecklistDialogOptionBoardId _id}}selected{{/if}}") {{title}}
 
   label {{_ 'swimlanes'}}:
   select.js-select-swimlanes
     each swimlanes
-      option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}}
+      option(value="{{_id}}" selected="{{#if isChecklistDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}}
 
   label {{_ 'lists'}}:
   select.js-select-lists
     each lists
-      option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionListId _id}}selected{{/if}}") {{title}}
+      option(value="{{_id}}" selected="{{#if isChecklistDialogOptionListId _id}}selected{{/if}}") {{title}}
 
   label {{_ 'cards'}}:
   select.js-select-cards
     each cards
-      option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionCardId _id}}selected{{/if}}") {{title}}
+      option(value="{{_id}}" selected="{{#if isChecklistDialogOptionCardId _id}}selected{{/if}}") {{title}}
 
   .edit-controls.clearfix
     button.primary.confirm.js-done {{_ 'done'}}

+ 59 - 21
client/components/cards/checklists.js

@@ -313,6 +313,7 @@ BlazeComponent.extendComponent({
           }
         }),
         'click .js-move-checklist' : Popup.open('moveChecklist'),
+        'click .js-copy-checklist' : Popup.open('copyChecklist'),
       }
     ]
   }
@@ -379,36 +380,49 @@ BlazeComponent.extendComponent({
 }).register('checklistItemDetail');
 
 class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
+  /** returns the checklist dialog options
+   * @return Object with properties { boardId, swimlaneId, listId, cardId }
+   */
+  getChecklistDialogOptions() {
+  }
+
+  /** checklist is done
+   * @param cardId the selected card id
+   * @param options the selected options (Object with properties { boardId, swimlaneId, listId, cardId })
+   */
+  setDone(cardId, options) {
+  }
+
   onCreated() {
     this.currentBoardId = Utils.getCurrentBoardId();
     this.selectedBoardId = new ReactiveVar(this.currentBoardId);
     this.selectedSwimlaneId = new ReactiveVar('');
     this.selectedListId = new ReactiveVar('');
-    this.setMoveChecklistDialogOption(this.currentBoardId);
+    this.setChecklistDialogOption(this.currentBoardId);
   }
 
   /** set the last confirmed dialog field values
    * @param boardId the current board id
    */
-  setMoveChecklistDialogOption(boardId) {
-    this.moveChecklistDialogOption = {
+  setChecklistDialogOption(boardId) {
+    this.checklistDialogOption = {
       'boardId' : "",
       'swimlaneId' : "",
       'listId' : "",
       'cardId': "",
     }
 
-    let currentOptions = Meteor.user().getMoveChecklistDialogOptions();
+    let currentOptions = this.getChecklistDialogOptions();
     if (currentOptions && boardId && currentOptions[boardId]) {
-      this.moveChecklistDialogOption = currentOptions[boardId];
-      if (this.moveChecklistDialogOption.boardId &&
-          this.moveChecklistDialogOption.swimlaneId &&
-          this.moveChecklistDialogOption.listId
+      this.checklistDialogOption = currentOptions[boardId];
+      if (this.checklistDialogOption.boardId &&
+          this.checklistDialogOption.swimlaneId &&
+          this.checklistDialogOption.listId
       )
       {
-        this.selectedBoardId.set(this.moveChecklistDialogOption.boardId)
-        this.selectedSwimlaneId.set(this.moveChecklistDialogOption.swimlaneId);
-        this.selectedListId.set(this.moveChecklistDialogOption.listId);
+        this.selectedBoardId.set(this.checklistDialogOption.boardId)
+        this.selectedSwimlaneId.set(this.checklistDialogOption.swimlaneId);
+        this.selectedListId.set(this.checklistDialogOption.listId);
       }
     }
     this.getBoardData(this.selectedBoardId.get());
@@ -440,8 +454,8 @@ class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
    * @param boardId check this board id
    * @return if the board id was the last confirmed one
    */
-  isMoveChecklistDialogOptionBoardId(boardId) {
-    let ret = this.moveChecklistDialogOption.boardId == boardId;
+  isChecklistDialogOptionBoardId(boardId) {
+    let ret = this.checklistDialogOption.boardId == boardId;
     return ret;
   }
 
@@ -449,8 +463,8 @@ class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
    * @param swimlaneId check this swimlane id
    * @return if the swimlane id was the last confirmed one
    */
-  isMoveChecklistDialogOptionSwimlaneId(swimlaneId) {
-    let ret = this.moveChecklistDialogOption.swimlaneId == swimlaneId;
+  isChecklistDialogOptionSwimlaneId(swimlaneId) {
+    let ret = this.checklistDialogOption.swimlaneId == swimlaneId;
     return ret;
   }
 
@@ -458,8 +472,8 @@ class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
    * @param listId check this list id
    * @return if the list id was the last confirmed one
    */
-  isMoveChecklistDialogOptionListId(listId) {
-    let ret = this.moveChecklistDialogOption.listId == listId;
+  isChecklistDialogOptionListId(listId) {
+    let ret = this.checklistDialogOption.listId == listId;
     return ret;
   }
 
@@ -467,11 +481,12 @@ class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
    * @param cardId check this card id
    * @return if the card id was the last confirmed one
    */
-  isMoveChecklistDialogOptionCardId(cardId) {
-    let ret = this.moveChecklistDialogOption.cardId == cardId;
+  isChecklistDialogOptionCardId(cardId) {
+    let ret = this.checklistDialogOption.cardId == cardId;
     return ret;
   }
 
+  /** returns all available board */
   boards() {
     const ret = Boards.find(
       {
@@ -486,18 +501,21 @@ class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
     return ret;
   }
 
+  /** returns all available swimlanes of the current board */
   swimlanes() {
     const board = Boards.findOne(this.selectedBoardId.get());
     const ret = board.swimlanes();
     return ret;
   }
 
+  /** returns all available lists of the current board */
   lists() {
     const board = Boards.findOne(this.selectedBoardId.get());
     const ret = board.lists();
     return ret;
   }
 
+  /** returns all available cards of the current list */
   cards() {
     const list = Lists.findOne(this.selectedListId.get());
     const ret = list.cards(this.selectedSwimlaneId.get());
@@ -547,8 +565,7 @@ class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
             'listId' : listId,
             'cardId': cardId,
           }
-          Meteor.user().setMoveChecklistDialogOption(this.currentBoardId, options);
-          this.data().checklist.move(cardId);
+          this.setDone(cardId, options);
           Popup.back(2);
         },
         'change .js-select-boards'(event) {
@@ -566,5 +583,26 @@ class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
   }
 }
 
+/** Move Checklist Dialog */
 (class extends DialogWithBoardSwimlaneListAndCard {
+  getChecklistDialogOptions() {
+    const ret = Meteor.user().getMoveChecklistDialogOptions();
+    return ret;
+  }
+  setDone(cardId, options) {
+    Meteor.user().setMoveChecklistDialogOption(this.currentBoardId, options);
+    this.data().checklist.move(cardId);
+  }
 }).register('moveChecklistPopup');
+
+/** Copy Checklist Dialog */
+(class extends DialogWithBoardSwimlaneListAndCard {
+  getChecklistDialogOptions() {
+    const ret = Meteor.user().getCopyChecklistDialogOptions();
+    return ret;
+  }
+  setDone(cardId, options) {
+    Meteor.user().setCopyChecklistDialogOption(this.currentBoardId, options);
+    this.data().checklist.copy(cardId);
+  }
+}).register('copyChecklistPopup');

+ 3 - 1
i18n/en.i18n.json

@@ -1142,5 +1142,7 @@
   "checklistActionsPopup-title": "Checklist Actions",
   "moveChecklist": "Move Checklist",
   "moveChecklistPopup-title": "Move Checklist",
-  "newlineBecomesNewChecklistItem": "Newline becomes new checklist item"
+  "newlineBecomesNewChecklistItem": "Newline becomes new checklist item",
+  "copyChecklist": "Copy Checklist",
+  "copyChecklistPopup-title": "Copy Checklist"
 }

+ 58 - 2
models/users.js

@@ -254,7 +254,7 @@ Users.attachSchema(
     },
     'profile.moveChecklistDialog' : {
       /**
-       * move and copy card dialog
+       * move checklist dialog
        */
       type: Object,
       optional: true,
@@ -284,6 +284,38 @@ Users.attachSchema(
        */
       type: String,
     },
+    'profile.copyChecklistDialog' : {
+      /**
+       * copy checklist dialog
+       */
+      type: Object,
+      optional: true,
+      blackbox: true,
+    },
+    'profile.copyChecklistDialog.$.boardId': {
+      /**
+       * last selected board id
+       */
+      type: String,
+    },
+    'profile.copyChecklistDialog.$.swimlaneId': {
+      /**
+       * last selected swimlane id
+       */
+      type: String,
+    },
+    'profile.copyChecklistDialog.$.listId': {
+      /**
+       * last selected list id
+       */
+      type: String,
+    },
+    'profile.copyChecklistDialog.$.cardId': {
+      /**
+       * last selected card id
+       */
+      type: String,
+    },
     'profile.notifications': {
       /**
        * enabled notifications for the user
@@ -696,6 +728,17 @@ Users.helpers({
     return _ret;
   },
 
+  /** returns all confirmed copy checklist dialog field values
+   * <li> the board, swimlane, list and card id is stored for each board
+   */
+  getCopyChecklistDialogOptions() {
+    let _ret = {}
+    if (this.profile && this.profile.copyChecklistDialog) {
+      _ret = this.profile.copyChecklistDialog;
+    }
+    return _ret;
+  },
+
   hasTag(tag) {
     const { tags = [] } = this.profile || {};
     return _.contains(tags, tag);
@@ -824,7 +867,7 @@ Users.mutations({
       },
     };
   },
-  /** set the confirmed board id/swimlane id/list id/card id of a board
+  /** set the confirmed board id/swimlane id/list id/card id of a board (move checklist)
    * @param boardId the current board id
    * @param options an object with the confirmed field values
    */
@@ -837,6 +880,19 @@ Users.mutations({
       },
     };
   },
+  /** set the confirmed board id/swimlane id/list id/card id of a board (copy checklist)
+   * @param boardId the current board id
+   * @param options an object with the confirmed field values
+   */
+  setCopyChecklistDialogOption(boardId, options) {
+    let currentOptions = this.getCopyChecklistDialogOptions();
+    currentOptions[boardId] = options;
+    return {
+      $set: {
+        'profile.copyChecklistDialog': currentOptions,
+      },
+    };
+  },
   toggleBoardStar(boardId) {
     const queryKind = this.hasStarred(boardId) ? '$pull' : '$addToSet';
     return {