Browse Source

Import card-as-card, board-as-card. Add styling. Missing details and links

Andrés Manelli 7 years ago
parent
commit
5644ef66af

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

@@ -1,5 +1,7 @@
 template(name="minicard")
-  .minicard
+  .minicard(
+    class="{{#if importedCard}}imported-card{{/if}}"
+    class="{{#if importedBoard}}imported-board{{/if}}")
     if cover
       .minicard-cover(style="background-image: url('{{cover.url}}');")
     if labels
@@ -13,6 +15,8 @@ template(name="minicard")
       if $eq 'prefix-with-parent' currentBoard.presentParentTask
         .parent-prefix
           | {{ parentCardName }}
+      if imported
+        span.imported-icon.fa.fa-share-alt
       +viewer
         | {{ title }}
       if $eq 'subtext-with-full-path' currentBoard.presentParentTask

+ 9 - 0
client/components/cards/minicard.js

@@ -6,4 +6,13 @@ BlazeComponent.extendComponent({
   template() {
     return 'minicard';
   },
+  importedCard() {
+    return this.currentData().type === 'cardType-importedCard';
+  },
+  importedBoard() {
+    return this.currentData().type === 'cardType-importedBoard';
+  },
+  imported() {
+    return this.importedCard() || this.importedBoard();
+  },
 }).register('minicard');

+ 37 - 0
client/components/cards/minicard.styl

@@ -44,6 +44,41 @@
   transition: transform 0.2s,
               border-radius 0.2s
 
+  &.imported-board
+    background-color: #efd8e6
+    &:hover:not(.minicard-composer),
+    .is-selected &,
+    .draggable-hover-card &
+      background: darken(#efd8e6, 3%)
+
+    .is-selected &
+      border-left: 3px solid darken(#efd8e6, 50%)
+
+    .minicard-title
+      font-style: italic
+      font-weight: bold
+
+  &.imported-card
+    background-color: #d5e4bd
+    &:hover:not(.minicard-composer),
+    .is-selected &,
+    .draggable-hover-card &
+      background: darken(#d5e4bd, 3%)
+
+    .is-selected &
+      border-left: 3px solid darken(#d5e4bd, 50%)
+
+    .minicard-title
+      font-style: italic
+
+  &.imported-board
+  &.imported-card
+    .imported-icon
+      display: inline-block
+      margin-right: 11px
+      vertical-align: baseline
+      font-size: 0.9em
+
   .is-selected &
     transform: translateX(11px)
     border-bottom-right-radius: 0
@@ -87,6 +122,8 @@
   .minicard-title
     p:last-child
       margin-bottom: 0
+    .viewer
+      display: inline-block
   .dates
     display: flex;
     flex-direction: row;

+ 7 - 6
client/components/lists/listBody.jade

@@ -37,6 +37,10 @@ template(name="addCardForm")
     span.quiet
       | {{_ 'or'}}
       a.js-import {{_ 'import'}}
+    span.quiet
+      |  
+      | /
+      a.js-search {{_ 'search'}}
 
 template(name="autocompleteLabelLine")
   .minicard-label(class="card-label-{{colorName}}" title=labelName)
@@ -51,7 +55,7 @@ template(name="importCardPopup")
           option(value="{{_id}}" selected) {{_ 'current'}}
         else
           option(value="{{_id}}") {{title}}
-    input.primary.confirm.js-import-board(type="submit" value="{{_ 'add'}}")
+    input.primary.confirm.js-import-board(type="button" value="{{_ 'import'}}")
 
   label {{_ 'swimlanes'}}:
   select.js-select-swimlanes
@@ -64,15 +68,12 @@ template(name="importCardPopup")
       option(value="{{_id}}") {{title}}
 
   label {{_ 'cards'}}:
-  select.js-select-lists
+  select.js-select-cards
     each cards
       option(value="{{_id}}") {{title}}
 
   .edit-controls.clearfix
-    input.primary.confirm.js-done(type="submit" value="{{_ 'done'}}")
-    span.quiet
-      | {{_ 'or'}}
-      a.js-search {{_ 'search'}}
+    input.primary.confirm.js-done(type="button" value="{{_ 'import'}}")
 
 template(name="searchCardPopup")
   label {{_ 'boards'}}:

+ 101 - 18
client/components/lists/listBody.js

@@ -201,6 +201,7 @@ BlazeComponent.extendComponent({
     return [{
       keydown: this.pressKey,
       'click .js-import': Popup.open('importCard'),
+      'click .js-search': Popup.open('searchCard'),
     }];
   },
 
@@ -275,14 +276,39 @@ BlazeComponent.extendComponent({
 
 BlazeComponent.extendComponent({
   onCreated() {
-    subManager.subscribe('board', Session.get('currentBoard'));
-    this.selectedBoardId = new ReactiveVar(Session.get('currentBoard'));
+    // Prefetch first non-current board id
+    const boardId = Boards.findOne({
+      archived: false,
+      'members.userId': Meteor.userId(),
+      _id: {$ne: Session.get('currentBoard')},
+    })._id;
+    // Subscribe to this board
+    subManager.subscribe('board', boardId);
+    this.selectedBoardId = new ReactiveVar(boardId);
+    this.selectedSwimlaneId = new ReactiveVar('');
+    this.selectedListId = new ReactiveVar('');
+
+    this.boardId = Session.get('currentBoard');
+    // In order to get current board info
+    subManager.subscribe('board', this.boardId);
+    const board = Boards.findOne(this.boardId);
+    // List where to insert card
+    const list = $(Popup._getTopStack().openerElement).closest('.js-list');
+    this.listId = Blaze.getData(list[0])._id;
+    // Swimlane where to insert card
+    const swimlane = $(Popup._getTopStack().openerElement).closest('.js-swimlane');
+    this.swimlaneId = '';
+    if (board.view === 'board-view-swimlanes')
+      this.swimlaneId = Blaze.getData(swimlane[0])._id;
+    else
+      this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
   },
 
   boards() {
     const boards = Boards.find({
       archived: false,
       'members.userId': Meteor.userId(),
+      _id: {$ne: Session.get('currentBoard')},
     }, {
       sort: ['title'],
     });
@@ -290,18 +316,26 @@ BlazeComponent.extendComponent({
   },
 
   swimlanes() {
-    const board = Boards.findOne(this.selectedBoardId.get());
-    return board.swimlanes();
+    const swimlanes = Swimlanes.find({boardId: this.selectedBoardId.get()});
+    if (swimlanes.count())
+      this.selectedSwimlaneId.set(swimlanes.fetch()[0]._id);
+    return swimlanes;
   },
 
   lists() {
-    const board = Boards.findOne(this.selectedBoardId.get());
-    return board.lists();
+    const lists = Lists.find({boardId: this.selectedBoardId.get()});
+    if (lists.count())
+      this.selectedListId.set(lists.fetch()[0]._id);
+    return lists;
   },
 
   cards() {
-    const board = Boards.findOne(this.selectedBoardId.get());
-    return board.cards();
+    return Cards.find({
+      boardId: this.selectedBoardId.get(),
+      swimlaneId: this.selectedSwimlaneId.get(),
+      listId: this.selectedListId.get(),
+      archived: false,
+    });
   },
 
   events() {
@@ -310,24 +344,44 @@ BlazeComponent.extendComponent({
         this.selectedBoardId.set($(evt.currentTarget).val());
         subManager.subscribe('board', this.selectedBoardId.get());
       },
-      'submit .js-done' (evt) {
+      'change .js-select-swimlanes'(evt) {
+        this.selectedSwimlaneId.set($(evt.currentTarget).val());
+      },
+      'change .js-select-lists'(evt) {
+        this.selectedListId.set($(evt.currentTarget).val());
+      },
+      'click .js-done' (evt) {
         // IMPORT CARD
+        evt.stopPropagation();
         evt.preventDefault();
-        // XXX We should *not* get the currentCard from the global state, but
-        // instead from a “component” state.
-        const card = Cards.findOne(Session.get('currentCard'));
-        const lSelect = $('.js-select-lists')[0];
-        const newListId = lSelect.options[lSelect.selectedIndex].value;
-        const slSelect = $('.js-select-swimlanes')[0];
-        card.swimlaneId = slSelect.options[slSelect.selectedIndex].value;
+        const _id = Cards.insert({
+          title: $('.js-select-cards option:selected').text(), //dummy
+          listId: this.listId,
+          swimlaneId: this.swimlaneId,
+          boardId: this.boardId,
+          sort: Lists.findOne(this.listId).cards().count(),
+          type: 'cardType-importedCard',
+          importedId: $('.js-select-cards option:selected').val(),
+        });
+        Filter.addException(_id);
         Popup.close();
       },
-      'submit .js-import-board' (evt) {
+      'click .js-import-board' (evt) {
         //IMPORT BOARD
+        evt.stopPropagation();
         evt.preventDefault();
+        const _id = Cards.insert({
+          title: $('.js-select-boards option:selected').text(), //dummy
+          listId: this.listId,
+          swimlaneId: this.swimlaneId,
+          boardId: this.boardId,
+          sort: Lists.findOne(this.listId).cards().count(),
+          type: 'cardType-importedBoard',
+          importedId: $('.js-select-boards option:selected').val(),
+        });
+        Filter.addException(_id);
         Popup.close();
       },
-      'click .js-search': Popup.open('searchCard'),
     }];
   },
 }).register('importCardPopup');
@@ -338,13 +392,30 @@ BlazeComponent.extendComponent({
   },
 
   onCreated() {
+    // Prefetch first non-current board id
     const boardId = Boards.findOne({
       archived: false,
       'members.userId': Meteor.userId(),
       _id: {$ne: Session.get('currentBoard')},
     })._id;
+    // Subscribe to this board
     subManager.subscribe('board', boardId);
     this.selectedBoardId = new ReactiveVar(boardId);
+
+    this.boardId = Session.get('currentBoard');
+    // In order to get current board info
+    subManager.subscribe('board', this.boardId);
+    const board = Boards.findOne(this.boardId);
+    // List where to insert card
+    const list = $(Popup._getTopStack().openerElement).closest('.js-list');
+    this.listId = Blaze.getData(list[0])._id;
+    // Swimlane where to insert card
+    const swimlane = $(Popup._getTopStack().openerElement).closest('.js-swimlane');
+    this.swimlaneId = '';
+    if (board.view === 'board-view-swimlanes')
+      this.swimlaneId = Blaze.getData(swimlane[0])._id;
+    else
+      this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
     this.term = new ReactiveVar('');
   },
 
@@ -376,6 +447,18 @@ BlazeComponent.extendComponent({
       },
       'click .js-minicard'(evt) {
         // IMPORT CARD
+        const card = Blaze.getData(evt.currentTarget);
+        const _id = Cards.insert({
+          title: card.title, //dummy
+          listId: this.listId,
+          swimlaneId: this.swimlaneId,
+          boardId: this.boardId,
+          sort: Lists.findOne(this.listId).cards().count(),
+          type: 'cardType-importedCard',
+          importedId: card._id,
+        });
+        Filter.addException(_id);
+        Popup.close();
       },
     }];
   },