瀏覽代碼

Show parent in card (no links, yet)

Nicu Tofan 7 年之前
父節點
當前提交
c0ffd6c20f

+ 27 - 4
client/components/boards/boardHeader.jade

@@ -199,9 +199,30 @@ template(name="boardChangeColorPopup")
 
 template(name="boardSubtaskSettingsPopup")
   form.board-subtask-settings
-    a.flex.js-field-has-subtasks(class="{{#if allowsSubtasks}}is-checked{{/if}}")
-      .materialCheckBox(class="{{#if allowsSubtasks}}is-checked{{/if}}")
-      span {{_ 'show-subtasks-field'}}
+    h3 {{_ 'show-parent-in-minicard'}}
+      a#prefix-with-full-path.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'prefix-with-full-path'}}is-checked{{/if}}")
+        .materialCheckBox(class="{{#if $eq presentParentTask 'prefix-with-full-path'}}is-checked{{/if}}")
+        span {{_ 'prefix-with-full-path'}}
+      a#prefix-with-parent.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'prefix-with-parent'}}is-checked{{/if}}")
+        .materialCheckBox(class="{{#if $eq presentParentTask 'prefix-with-parent'}}is-checked{{/if}}")
+        span {{_ 'prefix-with-parent'}}
+      a#subtext-with-full-path.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'subtext-with-full-path'}}is-checked{{/if}}")
+        .materialCheckBox(class="{{#if $eq presentParentTask 'subtext-with-full-path'}}is-checked{{/if}}")
+        span {{_ 'subtext-with-full-path'}}
+      a#subtext-with-parent.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'subtext-with-parent'}}is-checked{{/if}}")
+        .materialCheckBox(class="{{#if $eq presentParentTask 'subtext-with-parent'}}is-checked{{/if}}")
+        span {{_ 'subtext-with-parent'}}
+      a#no-parent.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'no-parent'}}is-checked{{/if}}")
+        .materialCheckBox(class="{{#if $eq presentParentTask 'no-parent'}}is-checked{{/if}}")
+        span {{_ 'no-parent'}}
+    div
+      hr
+
+    div.check-div
+      a.flex.js-field-has-subtasks(class="{{#if allowsSubtasks}}is-checked{{/if}}")
+        .materialCheckBox(class="{{#if allowsSubtasks}}is-checked{{/if}}")
+        span {{_ 'show-subtasks-field'}}
+
     label
       | {{_ 'deposit-subtasks-board'}}
       select.js-field-deposit-board(disabled="{{#unless allowsSubtasks}}disabled{{/unless}}")
@@ -214,7 +235,9 @@ template(name="boardSubtaskSettingsPopup")
             option(value='null' selected="selected") {{_ 'custom-field-dropdown-none'}}
           else
             option(value='null') {{_ 'custom-field-dropdown-none'}}
-    hr
+    div
+      hr
+
     label
       | {{_ 'deposit-subtasks-list'}}
       select.js-field-deposit-list(disabled="{{#unless hasLists}}disabled{{/unless}}")

+ 27 - 0
client/components/boards/boardHeader.js

@@ -195,6 +195,14 @@ BlazeComponent.extendComponent({
     return this.currentBoard.subtasksDefaultBoardId === this.currentData()._id;
   },
 
+  presentParentTask() {
+    let result = this.currentBoard.presentParentTask;
+    if ((result === null) || (result === undefined)) {
+      result = 'no-parent';
+    }
+    return result;
+  },
+
   events() {
     return [{
       'click .js-field-has-subtasks'(evt) {
@@ -217,6 +225,25 @@ BlazeComponent.extendComponent({
         this.currentBoard.setSubtasksDefaultListId(evt.target.value);
         evt.preventDefault();
       },
+      'click .js-field-show-parent-in-minicard'(evt) {
+        const value = evt.target.id || $(evt.target).parent()[0].id ||  $(evt.target).parent()[0].parent()[0].id;
+        const options = [
+          'prefix-with-full-path',
+          'prefix-with-parent',
+          'subtext-with-full-path',
+          'subtext-with-parent',
+          'no-parent'];
+        options.forEach(function(element) {
+          if (element !== value) {
+            $(`#${element} .materialCheckBox`).toggleClass('is-checked', false);
+            $(`#${element}`).toggleClass('is-checked', false);
+          }
+        });
+        $(`#${value} .materialCheckBox`).toggleClass('is-checked', true);
+        $(`#${value}`).toggleClass('is-checked', true);
+        this.currentBoard.setPresentParentTask(value);
+        evt.preventDefault();
+      },
     }];
   },
 }).register('boardSubtaskSettingsPopup');

+ 19 - 0
client/components/boards/boardHeader.styl

@@ -1,3 +1,22 @@
 .integration-form
   padding: 5px
   border-bottom: 1px solid #ccc
+
+.flex
+  display: -webkit-box
+  display: -moz-box
+  display: -webkit-flex
+  display: -moz-flex
+  display: -ms-flexbox
+  display: flex
+
+.option
+  @extends .flex
+  -webkit-border-radius: 3px;
+  border-radius: 3px;
+  background: #fff;
+  text-decoration: none;
+  -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.2);
+  box-shadow: 0 1px 2px rgba(0,0,0,0.2);
+  margin-top: 5px;
+  padding: 5px;

+ 6 - 0
client/components/cards/cardDetails.jade

@@ -13,6 +13,12 @@ template(name="cardDetails")
               = title
               if isWatching
                 i.fa.fa-eye.card-details-watch
+        .card-details-path
+          each parentList
+            |   >  
+            a.js-parent-card {{title}}
+          // else
+            {{_ 'top-level-card'}}
 
     if archived
       p.warning {{_ 'card-archived'}}

+ 8 - 0
client/components/cards/cardDetails.js

@@ -70,6 +70,14 @@ BlazeComponent.extendComponent({
     }
   },
 
+  presentParentTask() {
+    let result = this.currentBoard.presentParentTask;
+    if ((result === null) || (result === undefined)) {
+      result = 'no-parent';
+    }
+    return result;
+  },
+
   onRendered() {
     if (!Utils.isMiniScreen()) this.scrollParentContainer();
     const $checklistsDom = this.$('.card-checklist-items');

+ 15 - 1
client/components/cards/minicard.jade

@@ -8,7 +8,21 @@ template(name="minicard")
           .minicard-label(class="card-label-{{color}}" title="{{name}}")
     .minicard-title
       +viewer
-        = title
+        if isTopLevel
+          = title
+        else
+          if $eq 'prefix-with-full-path' currentBoard.presentParentTask
+            [{{ parentString ' > ' }}] {{ title }}
+          else
+            if $eq 'prefix-with-parent' currentBoard.presentParentTask
+              [{{ parentCardName }}] {{ title }}
+            else
+              = title
+    if $eq 'subtext-with-full-path' currentBoard.presentParentTask
+      .small {{ parentString ' > ' }}
+    if $eq 'subtext-with-parent' currentBoard.presentParentTask
+      .small {{ parentCardName }}
+
     .dates
       if receivedAt
         unless startAt

+ 9 - 2
i18n/en.i18n.json

@@ -485,7 +485,14 @@
     "queue": "Queue",
     "subtask-settings": "Subtasks Settings",
     "boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
-    "show-subtasks-field": "Cards can have subtasks:",
+    "show-subtasks-field": "Cards can have subtasks",
     "deposit-subtasks-board": "Deposit subtasks to this board:",
-    "deposit-subtasks-list": "Landing list for subtasks deposited here:"
+    "deposit-subtasks-list": "Landing list for subtasks deposited here:",
+    "show-parent-in-minicard": "Show parent in minicard:",
+    "prefix-with-full-path": "Prefix with full path",
+    "prefix-with-parent": "Prefix with parent",
+    "subtext-with-full-path": "Subtext with full path",
+    "subtext-with-parent": "Subtext with full parent",
+    "no-parent": "Don't show parent"
+
 }

+ 16 - 0
models/boards.js

@@ -165,6 +165,18 @@ Boards.attachSchema(new SimpleSchema({
     type: Boolean,
     defaultValue: true,
   },
+  presentParentTask: {
+    type: String,
+    allowedValues: [
+      'prefix-with-full-path',
+      'prefix-with-parent',
+      'subtext-with-full-path',
+      'subtext-with-parent',
+      'no-parent',
+    ],
+    optional: true,
+    defaultValue: 'no-parent',
+  },
 }));
 
 
@@ -489,6 +501,10 @@ Boards.mutations({
   setSubtasksDefaultListId(subtasksDefaultListId) {
     return { $set: { subtasksDefaultListId } };
   },
+
+  setPresentParentTask(presentParentTask) {
+    return { $set: { presentParentTask } };
+  },
 });
 
 if (Meteor.isServer) {

+ 53 - 0
models/cards.js

@@ -326,6 +326,59 @@ Cards.helpers({
     return Cards.findOne(this.parentId);
   },
 
+  parentCardName() {
+    if (this.parentId === '') {
+      return '';
+    }
+    return Cards.findOne(this.parentId).title;
+  },
+
+  parentListId() {
+    const result = [];
+    let crtParentId = this.parentId;
+    while (crtParentId !== '') {
+      const crt = Cards.findOne(crtParentId);
+      if ((crt === null) || (crt === undefined)) {
+        // maybe it has been deleted
+        break;
+      }
+      if (crtParentId in result) {
+        // circular reference
+        break;
+      }
+      result.unshift(crtParentId);
+      crtParentId = crt.parentId;
+    }
+    return result;
+  },
+
+  parentList() {
+    const resultId = [];
+    const result = [];
+    let crtParentId = this.parentId;
+    while (crtParentId !== '') {
+      const crt = Cards.findOne(crtParentId);
+      if ((crt === null) || (crt === undefined)) {
+        // maybe it has been deleted
+        break;
+      }
+      if (crtParentId in resultId) {
+        // circular reference
+        break;
+      }
+      resultId.unshift(crtParentId);
+      result.unshift(crt);
+      crtParentId = crt.parentId;
+    }
+    return result;
+  },
+
+  parentString(sep) {
+    return this.parentList().map(function(elem){
+      return elem.title;
+    }).join(sep);
+  },
+
   isTopLevel() {
     return this.parentId === '';
   },

+ 13 - 1
server/migrations.js

@@ -294,7 +294,19 @@ Migrations.add('add-subtasks-allowed', () => {
     },
   }, {
     $set: {
-      allowsSubtasks: -1,
+      allowsSubtasks: true,
+    },
+  }, noValidateMulti);
+});
+
+Migrations.add('add-subtasks-allowed', () => {
+  Boards.update({
+    presentParentTask: {
+      $exists: false,
+    },
+  }, {
+    $set: {
+      presentParentTask: 'no-parent',
     },
   }, noValidateMulti);
 });