瀏覽代碼

Added "Move Checklist" to checklist menu action

Martin Filser 3 年之前
父節點
當前提交
a66257ec21
共有 5 個文件被更改,包括 274 次插入1 次删除
  1. 31 0
      client/components/cards/checklists.jade
  2. 153 0
      client/components/cards/checklists.js
  3. 3 1
      i18n/en.i18n.json
  4. 31 0
      models/checklists.js
  5. 56 0
      models/users.js

+ 31 - 0
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'}}

+ 153 - 0
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');

+ 3 - 1
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"
 }

+ 31 - 0
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) {

+ 56 - 0
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
+   * <li> 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 {