From dcc7b2970f3635b95bc71e3fc163a51cacad0931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Tue, 20 Mar 2018 00:13:42 -0300 Subject: [PATCH 01/24] Add UI for importing card-as-card and board-as-card --- client/components/forms/forms.styl | 3 + client/components/lists/list.styl | 11 +++ client/components/lists/listBody.jade | 53 ++++++++++++- client/components/lists/listBody.js | 106 ++++++++++++++++++++++++++ i18n/en.i18n.json | 5 ++ models/boards.js | 4 + models/cards.js | 7 ++ server/migrations.js | 11 +++ 8 files changed, 199 insertions(+), 1 deletion(-) diff --git a/client/components/forms/forms.styl b/client/components/forms/forms.styl index 0a9059435..5be70b7a4 100644 --- a/client/components/forms/forms.styl +++ b/client/components/forms/forms.styl @@ -225,9 +225,12 @@ textarea .edit-controls, .add-controls + display: flex + align-items: baseline margin-top: 0 button[type=submit] + input[type=button] float: left height: 32px margin-top: -2px diff --git a/client/components/lists/list.styl b/client/components/lists/list.styl index fa32ff6dc..0e170ebfc 100644 --- a/client/components/lists/list.styl +++ b/client/components/lists/list.styl @@ -187,3 +187,14 @@ padding: 7px top: -@padding right: 17px + +.import-board-wrapper + display: flex + align-items: baseline + + .js-import-board + margin-left: 15px + +.search-card-results + max-height: 250px + overflow: hidden diff --git a/client/components/lists/listBody.jade b/client/components/lists/listBody.jade index 32c6b2783..e0655fc2d 100644 --- a/client/components/lists/listBody.jade +++ b/client/components/lists/listBody.jade @@ -34,8 +34,59 @@ template(name="addCardForm") .add-controls.clearfix button.primary.confirm(type="submit") {{_ 'add'}} - a.fa.fa-times-thin.js-close-inlined-form + span.quiet + | {{_ 'or'}} + a.js-import {{_ 'import'}} template(name="autocompleteLabelLine") .minicard-label(class="card-label-{{colorName}}" title=labelName) span(class="{{#if hasNoName}}quiet{{/if}}")= labelName + +template(name="importCardPopup") + label {{_ 'boards'}}: + .import-board-wrapper + select.js-select-boards + each boards + if $eq _id currentBoard._id + option(value="{{_id}}" selected) {{_ 'current'}} + else + option(value="{{_id}}") {{title}} + input.primary.confirm.js-import-board(type="submit" value="{{_ 'add'}}") + + label {{_ 'swimlanes'}}: + select.js-select-swimlanes + each swimlanes + option(value="{{_id}}") {{title}} + + label {{_ 'lists'}}: + select.js-select-lists + each lists + option(value="{{_id}}") {{title}} + + label {{_ 'cards'}}: + select.js-select-lists + 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'}} + +template(name="searchCardPopup") + label {{_ 'boards'}}: + .import-board-wrapper + select.js-select-boards + each boards + if $eq _id currentBoard._id + option(value="{{_id}}" selected) {{_ 'current'}} + else + option(value="{{_id}}") {{title}} + form.js-search-term-form + input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus) + .list-body.js-perfect-scrollbar.search-card-results + .minicards.clearfix.js-minicards + each results + a.minicard-wrapper.js-minicard + +minicard(this) diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 0a10f7d57..4cae9f0b1 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -1,3 +1,5 @@ +const subManager = new SubsManager(); + BlazeComponent.extendComponent({ mixins() { return [Mixins.PerfectScrollbar]; @@ -55,6 +57,7 @@ BlazeComponent.extendComponent({ boardId: boardId._id, sort: sortIndex, swimlaneId, + type: 'cardType-card', }); // In case the filter is active we need to add the newly inserted card in // the list of exceptions -- cards that are not filtered. Otherwise the @@ -197,6 +200,7 @@ BlazeComponent.extendComponent({ events() { return [{ keydown: this.pressKey, + 'click .js-import': Popup.open('importCard'), }]; }, @@ -268,3 +272,105 @@ BlazeComponent.extendComponent({ }); }, }).register('addCardForm'); + +BlazeComponent.extendComponent({ + onCreated() { + subManager.subscribe('board', Session.get('currentBoard')); + this.selectedBoardId = new ReactiveVar(Session.get('currentBoard')); + }, + + boards() { + const boards = Boards.find({ + archived: false, + 'members.userId': Meteor.userId(), + }, { + sort: ['title'], + }); + return boards; + }, + + swimlanes() { + const board = Boards.findOne(this.selectedBoardId.get()); + return board.swimlanes(); + }, + + lists() { + const board = Boards.findOne(this.selectedBoardId.get()); + return board.lists(); + }, + + cards() { + const board = Boards.findOne(this.selectedBoardId.get()); + return board.cards(); + }, + + events() { + return [{ + 'change .js-select-boards'(evt) { + this.selectedBoardId.set($(evt.currentTarget).val()); + subManager.subscribe('board', this.selectedBoardId.get()); + }, + 'submit .js-done' (evt) { + // IMPORT CARD + 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; + Popup.close(); + }, + 'submit .js-import-board' (evt) { + //IMPORT BOARD + evt.preventDefault(); + Popup.close(); + }, + 'click .js-search': Popup.open('searchCard'), + }]; + }, +}).register('importCardPopup'); + +BlazeComponent.extendComponent({ + mixins() { + return [Mixins.PerfectScrollbar]; + }, + + onCreated() { + subManager.subscribe('board', Session.get('currentBoard')); + this.selectedBoardId = new ReactiveVar(Session.get('currentBoard')); + this.term = new ReactiveVar(''); + }, + + boards() { + const boards = Boards.find({ + archived: false, + 'members.userId': Meteor.userId(), + }, { + sort: ['title'], + }); + return boards; + }, + + results() { + const board = Boards.findOne(this.selectedBoardId.get()); + return board.searchCards(this.term.get()); + }, + + events() { + return [{ + 'change .js-select-boards'(evt) { + this.selectedBoardId.set($(evt.currentTarget).val()); + subManager.subscribe('board', this.selectedBoardId.get()); + }, + 'submit .js-search-term-form'(evt) { + evt.preventDefault(); + this.term.set(evt.target.searchTerm.value); + }, + 'click .js-minicard'() { + // IMPORT CARD + }, + }]; + }, +}).register('searchCardPopup'); diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 9244af9c7..08fc129f9 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -135,6 +135,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn" : "Sign In with CAS", + "cardType-card": "Card", + "cardType-importedCard": "Imported Card", + "cardType-importedBoard": "Imported Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +174,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "importCardPopup-title": "Import Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", diff --git a/models/boards.js b/models/boards.js index c51a98650..eda34bf4b 100644 --- a/models/boards.js +++ b/models/boards.js @@ -212,6 +212,10 @@ Boards.helpers({ return this.permission === 'public'; }, + cards() { + return Cards.find({ boardId: this._id, archived: false }, { sort: { title: 1 } }); + }, + lists() { return Lists.find({ boardId: this._id, archived: false }, { sort: { sort: 1 } }); }, diff --git a/models/cards.js b/models/cards.js index b6a7b4c61..af8bea482 100644 --- a/models/cards.js +++ b/models/cards.js @@ -133,6 +133,13 @@ Cards.attachSchema(new SimpleSchema({ defaultValue: -1, optional: true, }, + type: { + type: String, + }, + importedId: { + type: String, + optional: true, + }, })); Cards.allow({ diff --git a/server/migrations.js b/server/migrations.js index 6135f1bef..32f24e4c5 100644 --- a/server/migrations.js +++ b/server/migrations.js @@ -213,6 +213,17 @@ Migrations.add('add-profile-view', () => { }); }); +Migrations.add('add-card-types', () => { + Cards.find().forEach((card) => { + Cards.direct.update( + { _id: card._id }, + { $set: { + type: 'cardType-card', + importedId: null } }, + noValidate + ); + }); + Migrations.add('add-custom-fields-to-cards', () => { Cards.update({ customFields: { From 061a13e46e41f2bfed76860fadd96737caa8e0d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Tue, 20 Mar 2018 00:40:24 -0300 Subject: [PATCH 02/24] Avoid showing current board --- client/components/lists/listBody.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 4cae9f0b1..1aece1219 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -338,8 +338,13 @@ BlazeComponent.extendComponent({ }, onCreated() { - subManager.subscribe('board', Session.get('currentBoard')); - this.selectedBoardId = new ReactiveVar(Session.get('currentBoard')); + const boardId = Boards.findOne({ + archived: false, + 'members.userId': Meteor.userId(), + _id: {$ne: Session.get('currentBoard')}, + })._id; + subManager.subscribe('board', boardId); + this.selectedBoardId = new ReactiveVar(boardId); this.term = new ReactiveVar(''); }, @@ -347,6 +352,7 @@ BlazeComponent.extendComponent({ const boards = Boards.find({ archived: false, 'members.userId': Meteor.userId(), + _id: {$ne: Session.get('currentBoard')}, }, { sort: ['title'], }); @@ -368,7 +374,7 @@ BlazeComponent.extendComponent({ evt.preventDefault(); this.term.set(evt.target.searchTerm.value); }, - 'click .js-minicard'() { + 'click .js-minicard'(evt) { // IMPORT CARD }, }]; From 5644ef66af2fb6e2bfb629a499bb21130bfd5c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Tue, 20 Mar 2018 15:56:16 -0300 Subject: [PATCH 03/24] Import card-as-card, board-as-card. Add styling. Missing details and links --- client/components/cards/minicard.jade | 6 +- client/components/cards/minicard.js | 9 ++ client/components/cards/minicard.styl | 37 ++++++++ client/components/lists/listBody.jade | 13 +-- client/components/lists/listBody.js | 119 ++++++++++++++++++++++---- 5 files changed, 159 insertions(+), 25 deletions(-) diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 3f7e09400..95fa6e319 100644 --- a/client/components/cards/minicard.jade +++ b/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 diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index a98b5730e..5202232b9 100644 --- a/client/components/cards/minicard.js +++ b/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'); diff --git a/client/components/cards/minicard.styl b/client/components/cards/minicard.styl index 5624787ca..ea737c6b4 100644 --- a/client/components/cards/minicard.styl +++ b/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; diff --git a/client/components/lists/listBody.jade b/client/components/lists/listBody.jade index e0655fc2d..419e158a0 100644 --- a/client/components/lists/listBody.jade +++ b/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'}}: diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 1aece1219..39614108e 100644 --- a/client/components/lists/listBody.js +++ b/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(); }, }]; }, From 64367a01dd6b86982c22b4c124e8f37474e9cb08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Mon, 16 Apr 2018 16:38:20 -0300 Subject: [PATCH 04/24] Link description --- client/components/cards/cardDetails.jade | 4 +-- client/components/cards/cardDetails.js | 3 ++- client/components/cards/minicard.jade | 10 +++---- client/components/cards/minicard.js | 9 ------- client/components/lists/listBody.js | 6 ++++- models/cards.js | 33 ++++++++++++++++++++++++ server/publications/boards.js | 4 ++- 7 files changed, 50 insertions(+), 19 deletions(-) diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 34dbc117e..3d0bfb98c 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -109,10 +109,10 @@ template(name="cardDetails") a.js-open-inlined-form {{_ 'view-it'}} = ' - ' a.js-close-inlined-form {{_ 'discard'}} - else if description + else if getDescription h3.card-details-item-title {{_ 'description'}} +viewer - = description + = getDescription .card-details-items .card-details-item.card-details-item-name diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index b41bfc179..181fea1bf 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -43,7 +43,8 @@ BlazeComponent.extendComponent({ }, canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return Meteor.user() && Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() && !this.currentData().isImported(); }, scrollParentContainer() { diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 95fa6e319..7e2999d30 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -1,7 +1,7 @@ template(name="minicard") .minicard( - class="{{#if importedCard}}imported-card{{/if}}" - class="{{#if importedBoard}}imported-board{{/if}}") + class="{{#if isImportedCard}}imported-card{{/if}}" + class="{{#if isImportedBoard}}imported-board{{/if}}") if cover .minicard-cover(style="background-image: url('{{cover.url}}');") if labels @@ -15,7 +15,7 @@ template(name="minicard") if $eq 'prefix-with-parent' currentBoard.presentParentTask .parent-prefix | {{ parentCardName }} - if imported + if isImported span.imported-icon.fa.fa-share-alt +viewer | {{ title }} @@ -67,8 +67,8 @@ template(name="minicard") .badge(title="{{_ 'card-comments-title' comments.count }}") span.badge-icon.fa.fa-comment-o.badge-comment span.badge-text= comments.count - if description - .badge.badge-state-image-only(title=description) + if getDescription + .badge.badge-state-image-only(title=getDescription) span.badge-icon.fa.fa-align-left if attachments.count .badge diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index 5202232b9..a98b5730e 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -6,13 +6,4 @@ 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'); diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 39614108e..2c8b1af76 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -281,6 +281,8 @@ BlazeComponent.extendComponent({ archived: false, 'members.userId': Meteor.userId(), _id: {$ne: Session.get('currentBoard')}, + }, { + sort: ['title'], })._id; // Subscribe to this board subManager.subscribe('board', boardId); @@ -370,6 +372,7 @@ BlazeComponent.extendComponent({ //IMPORT BOARD evt.stopPropagation(); evt.preventDefault(); + const impBoardId = $('.js-select-boards option:selected').val(); const _id = Cards.insert({ title: $('.js-select-boards option:selected').text(), //dummy listId: this.listId, @@ -377,7 +380,8 @@ BlazeComponent.extendComponent({ boardId: this.boardId, sort: Lists.findOne(this.listId).cards().count(), type: 'cardType-importedBoard', - importedId: $('.js-select-boards option:selected').val(), + importedId: impBoardId, + description: Boards.findOne({_id: impBoardId}).description, }); Filter.addException(_id); Popup.close(); diff --git a/models/cards.js b/models/cards.js index af8bea482..4b18b8f34 100644 --- a/models/cards.js +++ b/models/cards.js @@ -393,6 +393,39 @@ Cards.helpers({ isTopLevel() { return this.parentId === ''; }, + + isImportedCard() { + return this.type === 'cardType-importedCard'; + }, + + isImportedBoard() { + return this.type === 'cardType-importedBoard'; + }, + + isImported() { + return this.isImportedCard() || this.isImportedBoard(); + }, + + getDescription() { + if (this.isImportedCard()) { + const card = Cards.findOne({_id: this.importedId}); + if (card && card.description) + return card.description; + else + return null; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({_id: this.importedId}); + if (board && board.description) + return board.description; + else + return null; + } else { + if (this.description) + return this.description; + else + return null; + } + }, }); Cards.mutations({ diff --git a/server/publications/boards.js b/server/publications/boards.js index 5d095c172..bf75196a2 100644 --- a/server/publications/boards.js +++ b/server/publications/boards.js @@ -98,7 +98,9 @@ Meteor.publishRelations('board', function(boardId) { // // And in the meantime our code below works pretty well -- it's not even a // hack! - this.cursor(Cards.find({ boardId }), function(cardId) { + this.cursor(Cards.find({ boardId }), function(cardId, card) { + this.cursor(Cards.find({_id: card.importedId})); + this.cursor(Boards.find({_id: card.importedId})); this.cursor(CardComments.find({ cardId })); this.cursor(Attachments.find({ cardId })); this.cursor(Checklists.find({ cardId })); From a93de07fb9b85f97da274bf549e5244ee8e30484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Mon, 16 Apr 2018 16:48:54 -0300 Subject: [PATCH 05/24] Avoid importing imported cards or boards --- client/components/lists/listBody.js | 3 ++- models/boards.js | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 2c8b1af76..c05330083 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -337,6 +337,7 @@ BlazeComponent.extendComponent({ swimlaneId: this.selectedSwimlaneId.get(), listId: this.selectedListId.get(), archived: false, + importedId: null, }); }, @@ -436,7 +437,7 @@ BlazeComponent.extendComponent({ results() { const board = Boards.findOne(this.selectedBoardId.get()); - return board.searchCards(this.term.get()); + return board.searchCards(this.term.get(), true); }, events() { diff --git a/models/boards.js b/models/boards.js index eda34bf4b..d5ccc9548 100644 --- a/models/boards.js +++ b/models/boards.js @@ -298,22 +298,22 @@ Boards.helpers({ return _id; }, - searchCards(term) { + searchCards(term, excludeImported) { check(term, Match.OneOf(String, null, undefined)); let query = { boardId: this._id }; + if (excludeImported) { + query.importedId = null; + } const projection = { limit: 10, sort: { createdAt: -1 } }; if (term) { const regex = new RegExp(term, 'i'); - query = { - boardId: this._id, - $or: [ + query.$or = [ { title: regex }, { description: regex }, - ], - }; + ]; } return Cards.find(query, projection); From 0a62089df02b2ab308d4749a837e08c4164cb770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Tue, 17 Apr 2018 01:55:57 -0300 Subject: [PATCH 06/24] Allow description and member two way binding --- client/components/cards/cardDetails.jade | 8 +-- client/components/cards/cardDetails.js | 5 +- client/components/cards/minicard.jade | 4 +- client/components/lists/listBody.js | 6 +-- client/components/users/userAvatar.js | 5 +- models/cards.js | 68 ++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 14 deletions(-) diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 3d0bfb98c..64ce7f66d 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -55,7 +55,7 @@ template(name="cardDetails") .card-details-items .card-details-item.card-details-item-members h3.card-details-item-title {{_ 'members'}} - each members + each getMembers +userAvatar(userId=this cardId=../_id) | {{! XXX Hack to hide syntaxic coloration /// }} if canModifyCard @@ -92,15 +92,15 @@ template(name="cardDetails") h3.card-details-item-title {{_ 'description'}} +inlinedCardDescription(classNames="card-description js-card-description") +editor(autofocus=true) - | {{getUnsavedValue 'cardDescription' _id description}} + | {{getUnsavedValue 'cardDescription' _id getDescription}} .edit-controls.clearfix button.primary(type="submit") {{_ 'save'}} a.fa.fa-times-thin.js-close-inlined-form else a.js-open-inlined-form - if description + if getDescription +viewer - = description + = getDescription else | {{_ 'edit'}} if (hasUnsavedValue 'cardDescription' _id) diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 181fea1bf..2cd399c19 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -43,8 +43,7 @@ BlazeComponent.extendComponent({ }, canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && - !Meteor.user().isCommentOnly() && !this.currentData().isImported(); + return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); }, scrollParentContainer() { @@ -275,7 +274,7 @@ BlazeComponent.extendComponent({ close(isReset = false) { if (this.isOpen.get() && !isReset) { const draft = this.getValue().trim(); - if (draft !== Cards.findOne(Session.get('currentCard')).description) { + if (draft !== Cards.findOne(Session.get('currentCard')).getDescription()) { UnsavedEdits.set(this._getUnsavedEditKey(), this.getValue()); } } diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 7e2999d30..001208824 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -57,9 +57,9 @@ template(name="minicard") +viewer = trueValue - if members + if getMembers .minicard-members.js-minicard-members - each members + each getMembers +userAvatar(userId=this) .badges diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index c05330083..778312d26 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -300,9 +300,10 @@ BlazeComponent.extendComponent({ // Swimlane where to insert card const swimlane = $(Popup._getTopStack().openerElement).closest('.js-swimlane'); this.swimlaneId = ''; - if (board.view === 'board-view-swimlanes') + const boardView = Meteor.user().profile.boardView; + if (boardView === 'board-view-swimlanes') this.swimlaneId = Blaze.getData(swimlane[0])._id; - else + else if (boardView === 'board-view-lists') this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id; }, @@ -382,7 +383,6 @@ BlazeComponent.extendComponent({ sort: Lists.findOne(this.listId).cards().count(), type: 'cardType-importedBoard', importedId: impBoardId, - description: Boards.findOne({_id: impBoardId}).description, }); Filter.addException(_id); Popup.close(); diff --git a/client/components/users/userAvatar.js b/client/components/users/userAvatar.js index be7a85d25..91cad2377 100644 --- a/client/components/users/userAvatar.js +++ b/client/components/users/userAvatar.js @@ -134,8 +134,9 @@ BlazeComponent.extendComponent({ Template.cardMembersPopup.helpers({ isCardMember() { - const cardId = Template.parentData()._id; - const cardMembers = Cards.findOne(cardId).members || []; + const card = Template.parentData(); + const cardMembers = card.getMembers(); + return _.contains(cardMembers, this.userId); }, diff --git a/models/cards.js b/models/cards.js index 4b18b8f34..de868dde3 100644 --- a/models/cards.js +++ b/models/cards.js @@ -406,6 +406,18 @@ Cards.helpers({ return this.isImportedCard() || this.isImportedBoard(); }, + setDescription(description) { + if (this.isImportedCard()) { + const card = Cards.findOne({_id: this.importedId}); + return Cards.update({_id: this.importedId}, {$set: {description}}); + } else if (this.isImportedBoard()) { + const board = Boards.findOne({_id: this.importedId}); + return Boards.update({_id: this.importedId}, {$set: {description}}); + } else { + return {$set: {description}}; + } + }, + getDescription() { if (this.isImportedCard()) { const card = Cards.findOne({_id: this.importedId}); @@ -426,6 +438,62 @@ Cards.helpers({ return null; } }, + + getMembers() { + if (this.isImportedCard()) { + const card = Cards.findOne({_id: this.importedId}); + return card.members; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({_id: this.importedId}); + return board.activeMembers().map((member) => { + return member.userId; + }); + } else { + return this.members; + } + }, + + assignMember(memberId) { + if (this.isImportedCard()) { + return Cards.update( + { _id: this.importedId }, + { $addToSet: { members: memberId }} + ); + } else if (this.isImportedBoard()) { + const board = Boards.findOne({_id: this.importedId}); + return board.addMember(memberId); + } else { + return Cards.update( + { _id: this._id }, + { $addToSet: { members: memberId}} + ); + } + }, + + unassignMember(memberId) { + if (this.isImportedCard()) { + return Cards.update( + { _id: this.importedId }, + { $pull: { members: memberId }} + ); + } else if (this.isImportedBoard()) { + const board = Boards.findOne({_id: this.importedId}); + return board.removeMember(memberId); + } else { + return Cards.update( + { _id: this._id }, + { $pull: { members: memberId}} + ); + } + }, + + toggleMember(memberId) { + if (this.getMembers() && this.getMembers().indexOf(memberId) > -1) { + return this.unassignMember(memberId); + } else { + return this.assignMember(memberId); + } + }, }); Cards.mutations({ From 724d26379c33afc2c3d44d3722b0c5c35c1b80ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Tue, 17 Apr 2018 23:17:44 -0300 Subject: [PATCH 07/24] Add two way binding of card/board times --- client/components/cards/cardDate.js | 56 +++++--- client/components/cards/cardDetails.jade | 17 ++- client/components/cards/cardTime.jade | 8 +- client/components/cards/cardTime.js | 18 +-- client/components/cards/minicard.jade | 20 ++- models/boards.js | 22 ++++ models/cards.js | 161 ++++++++++++++++++++++- 7 files changed, 250 insertions(+), 52 deletions(-) diff --git a/client/components/cards/cardDate.js b/client/components/cards/cardDate.js index 831a0f394..aa0dca4c1 100644 --- a/client/components/cards/cardDate.js +++ b/client/components/cards/cardDate.js @@ -96,7 +96,7 @@ Template.dateBadge.helpers({ (class extends DatePicker { onCreated() { super.onCreated(); - this.data().receivedAt && this.date.set(moment(this.data().receivedAt)); + this.data().getReceived() && this.date.set(moment(this.data().getReceived())); } _storeDate(date) { @@ -104,7 +104,7 @@ Template.dateBadge.helpers({ } _deleteDate() { - this.card.unsetReceived(); + this.card.setReceived(null); } }).register('editCardReceivedDatePopup'); @@ -113,13 +113,13 @@ Template.dateBadge.helpers({ (class extends DatePicker { onCreated() { super.onCreated(); - this.data().startAt && this.date.set(moment(this.data().startAt)); + this.data().getStart() && this.date.set(moment(this.data().getStart())); } onRendered() { super.onRendered(); - if (moment.isDate(this.card.receivedAt)) { - this.$('.js-datepicker').datepicker('setStartDate', this.card.receivedAt); + if (moment.isDate(this.card.getReceived())) { + this.$('.js-datepicker').datepicker('setStartDate', this.card.getReceived()); } } @@ -128,7 +128,7 @@ Template.dateBadge.helpers({ } _deleteDate() { - this.card.unsetStart(); + this.card.setStart(null); } }).register('editCardStartDatePopup'); @@ -136,13 +136,13 @@ Template.dateBadge.helpers({ (class extends DatePicker { onCreated() { super.onCreated(); - this.data().dueAt && this.date.set(moment(this.data().dueAt)); + this.data().getDue() && this.date.set(moment(this.data().getDue())); } onRendered() { super.onRendered(); - if (moment.isDate(this.card.startAt)) { - this.$('.js-datepicker').datepicker('setStartDate', this.card.startAt); + if (moment.isDate(this.card.getStart())) { + this.$('.js-datepicker').datepicker('setStartDate', this.card.getStart()); } } @@ -151,7 +151,7 @@ Template.dateBadge.helpers({ } _deleteDate() { - this.card.unsetDue(); + this.card.setDue(null); } }).register('editCardDueDatePopup'); @@ -159,13 +159,13 @@ Template.dateBadge.helpers({ (class extends DatePicker { onCreated() { super.onCreated(); - this.data().endAt && this.date.set(moment(this.data().endAt)); + this.data().getEnd() && this.date.set(moment(this.data().getEnd())); } onRendered() { super.onRendered(); - if (moment.isDate(this.card.startAt)) { - this.$('.js-datepicker').datepicker('setStartDate', this.card.startAt); + if (moment.isDate(this.card.getStart())) { + this.$('.js-datepicker').datepicker('setStartDate', this.card.getStart()); } } @@ -174,7 +174,7 @@ Template.dateBadge.helpers({ } _deleteDate() { - this.card.unsetEnd(); + this.card.setEnd(null); } }).register('editCardEndDatePopup'); @@ -213,15 +213,15 @@ class CardReceivedDate extends CardDate { super.onCreated(); const self = this; self.autorun(() => { - self.date.set(moment(self.data().receivedAt)); + self.date.set(moment(self.data().getReceived())); }); } classes() { let classes = 'received-date '; - const dueAt = this.data().dueAt; - const endAt = this.data().endAt; - const startAt = this.data().startAt; + const dueAt = this.data().getDue(); + const endAt = this.data().getEnd(); + const startAt = this.data().getStart(); const theDate = this.date.get(); // if dueAt, endAt and startAt exist & are > receivedAt, receivedAt doesn't need to be flagged if (((startAt) && (theDate.isAfter(dueAt))) || @@ -250,12 +250,13 @@ class CardStartDate extends CardDate { super.onCreated(); const self = this; self.autorun(() => { - self.date.set(moment(self.data().startAt)); + self.date.set(moment(self.data().getStart())); }); } classes() { let classes = 'start-date' + ' '; +<<<<<<< HEAD const dueAt = this.data().dueAt; const endAt = this.data().endAt; const theDate = this.date.get(); @@ -267,6 +268,10 @@ class CardStartDate extends CardDate { else if (theDate.isBefore(now, 'minute')) classes += 'almost-due'; else +======= + if (this.date.get().isBefore(this.now.get(), 'minute') && + this.now.get().isBefore(this.data().getDue())) { +>>>>>>> Add two way binding of card/board times classes += 'current'; return classes; } @@ -288,7 +293,7 @@ class CardDueDate extends CardDate { super.onCreated(); const self = this; self.autorun(() => { - self.date.set(moment(self.data().dueAt)); + self.date.set(moment(self.data().getDue())); }); } @@ -330,12 +335,13 @@ class CardEndDate extends CardDate { super.onCreated(); const self = this; self.autorun(() => { - self.date.set(moment(self.data().endAt)); + self.date.set(moment(self.data().getEnd())); }); } classes() { let classes = 'end-date' + ' '; +<<<<<<< HEAD const dueAt = this.data.dueAt; const theDate = this.date.get(); // if dueAt exists & is after endAt, endAt doesn't need to be flagged @@ -343,6 +349,14 @@ class CardEndDate extends CardDate { classes += 'long-overdue'; else classes += 'current'; +======= + if (this.date.get().diff(this.data().getDue(), 'days') >= 2) + classes += 'long-overdue'; + else if (this.date.get().diff(this.data().getDue(), 'days') >= 0) + classes += 'due'; + else if (this.date.get().diff(this.data().getDue(), 'days') >= -2) + classes += 'almost-due'; +>>>>>>> Add two way binding of card/board times return classes; } diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 64ce7f66d..b8c16f806 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -26,21 +26,28 @@ template(name="cardDetails") .card-details-items .card-details-item.card-details-item-received h3.card-details-item-title {{_ 'card-received'}} - if receivedAt + if getReceived +cardReceivedDate else a.js-received-date {{_ 'add'}} .card-details-item.card-details-item-start h3.card-details-item-title {{_ 'card-start'}} - if startAt + if getStart +cardStartDate else a.js-start-date {{_ 'add'}} + .card-details-item.card-details-item-due + h3.card-details-item-title {{_ 'card-due'}} + if getDue + +cardDueDate + else + a.js-due-date {{_ 'add'}} + .card-details-item.card-details-item-end h3.card-details-item-title {{_ 'card-end'}} - if endAt + if getEnd +cardEndDate else a.js-end-date {{_ 'add'}} @@ -79,9 +86,9 @@ template(name="cardDetails") +cardCustomField .card-details-items - if spentTime + if getSpentTime .card-details-item.card-details-item-spent - if isOvertime + if getIsOvertime h3.card-details-item-title {{_ 'overtime-hours'}} else h3.card-details-item-title {{_ 'spent-time-hours'}} diff --git a/client/components/cards/cardTime.jade b/client/components/cards/cardTime.jade index dcfc92f01..041af65a7 100644 --- a/client/components/cards/cardTime.jade +++ b/client/components/cards/cardTime.jade @@ -3,10 +3,10 @@ template(name="editCardSpentTime") form.edit-time .fields label(for="time") {{_ 'time'}} - input.js-time-field#time(type="number" step="0.01" name="time" value="{{card.spentTime}}" placeholder=timeFormat autofocus) + input.js-time-field#time(type="number" step="0.01" name="time" value="{{card.getSpentTime}}" placeholder=timeFormat autofocus) label(for="overtime") {{_ 'overtime'}} a.js-toggle-overtime - .materialCheckBox#overtime(class="{{#if card.isOvertime}}is-checked{{/if}}" name="overtime") + .materialCheckBox#overtime(class="{{#if card.getIsOvertime}}is-checked{{/if}}" name="overtime") if error.get .warning {{_ error.get}} @@ -15,8 +15,8 @@ template(name="editCardSpentTime") template(name="timeBadge") if canModifyCard - a.js-edit-time.card-time(title="{{showTitle}}" class="{{#if isOvertime}}card-label-red{{else}}card-label-green{{/if}}") + a.js-edit-time.card-time(title="{{showTitle}}" class="{{#if getIsOvertime}}card-label-red{{else}}card-label-green{{/if}}") | {{showTime}} else - a.card-time(title="{{showTitle}}" class="{{#if isOvertime}}card-label-red{{else}}card-label-green{{/if}}") + a.card-time(title="{{showTitle}}" class="{{#if getIsOvertime}}card-label-red{{else}}card-label-green{{/if}}") | {{showTime}} diff --git a/client/components/cards/cardTime.js b/client/components/cards/cardTime.js index eadcc88e1..9bab8e72b 100644 --- a/client/components/cards/cardTime.js +++ b/client/components/cards/cardTime.js @@ -7,17 +7,17 @@ BlazeComponent.extendComponent({ this.card = this.data(); }, toggleOvertime() { - this.card.isOvertime = !this.card.isOvertime; + this.card.setIsOvertime(!this.card.getIsOvertime()); $('#overtime .materialCheckBox').toggleClass('is-checked'); $('#overtime').toggleClass('is-checked'); }, storeTime(spentTime, isOvertime) { this.card.setSpentTime(spentTime); - this.card.setOvertime(isOvertime); + this.card.setIsOvertime(isOvertime); }, deleteTime() { - this.card.unsetSpentTime(); + this.card.setSpentTime(null); }, events() { return [{ @@ -26,7 +26,7 @@ BlazeComponent.extendComponent({ evt.preventDefault(); const spentTime = parseFloat(evt.target.time.value); - const isOvertime = this.card.isOvertime; + const isOvertime = this.card.getIsOvertime(); if (spentTime >= 0) { this.storeTime(spentTime, isOvertime); @@ -55,17 +55,17 @@ BlazeComponent.extendComponent({ self.time = ReactiveVar(); }, showTitle() { - if (this.data().isOvertime) { - return `${TAPi18n.__('overtime')} ${this.data().spentTime} ${TAPi18n.__('hours')}`; + if (this.data().getIsOvertime()) { + return `${TAPi18n.__('overtime')} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`; } else { - return `${TAPi18n.__('card-spent')} ${this.data().spentTime} ${TAPi18n.__('hours')}`; + return `${TAPi18n.__('card-spent')} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`; } }, showTime() { - return this.data().spentTime; + return this.data().getSpentTime(); }, isOvertime() { - return this.data().isOvertime; + return this.data().getIsOvertime(); }, events() { return [{ diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 001208824..88ad55645 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -27,23 +27,19 @@ template(name="minicard") | {{ parentCardName }} .dates - if receivedAt - unless startAt - unless dueAt - unless endAt + if getReceived + unless getStart + unless getDue + unless getEnd .date +minicardReceivedDate - if startAt + if getStart .date +minicardStartDate - if dueAt - unless endAt - .date - +minicardDueDate - if endAt + if getDue .date - +minicardEndDate - if spentTime + +minicardDueDate + if getSpentTime .date +cardSpentTime diff --git a/models/boards.js b/models/boards.js index d5ccc9548..a37981e0c 100644 --- a/models/boards.js +++ b/models/boards.js @@ -177,6 +177,28 @@ Boards.attachSchema(new SimpleSchema({ optional: true, defaultValue: 'no-parent', }, + startAt: { + type: Date, + optional: true, + }, + dueAt: { + type: Date, + optional: true, + }, + endAt: { + type: Date, + optional: true, + }, + spentTime: { + type: Number, + decimal: true, + optional: true, + }, + isOvertime: { + type: Boolean, + defaultValue: false, + optional: true, + }, })); diff --git a/models/cards.js b/models/cards.js index de868dde3..710b9d85b 100644 --- a/models/cards.js +++ b/models/cards.js @@ -494,6 +494,166 @@ Cards.helpers({ return this.assignMember(memberId); } }, + + getReceived() { + if (this.isImportedCard()) { + const card = Cards.findOne({_id: this.importedId}); + return card.receivedAt; + } else { + return this.receivedAt; + } + }, + + setReceived(receivedAt) { + if (this.isImportedCard()) { + return Cards.update( + {_id: this.importedId}, + {$set: {receivedAt}} + ); + } else { + return {$set: {receivedAt}}; + } + }, + + getStart() { + if (this.isImportedCard()) { + const card = Cards.findOne({_id: this.importedId}); + return card.startAt; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({_id: this.importedId}); + return board.startAt + } else { + return this.startAt; + } + }, + + setStart(startAt) { + if (this.isImportedCard()) { + return Cards.update( + { _id: this.importedId }, + {$set: {startAt}} + ); + } else if (this.isImportedBoard()) { + return Boards.update( + {_id: this.importedId}, + {$set: {startAt}} + ); + } else { + return {$set: {startAt}}; + } + }, + + getDue() { + if (this.isImportedCard()) { + const card = Cards.findOne({_id: this.importedId}); + return card.dueAt; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({_id: this.importedId}); + return board.dueAt + } else { + return this.dueAt; + } + }, + + setDue(dueAt) { + if (this.isImportedCard()) { + return Cards.update( + { _id: this.importedId }, + {$set: {dueAt}} + ); + } else if (this.isImportedBoard()) { + return Boards.update( + {_id: this.importedId}, + {$set: {dueAt}} + ); + } else { + return {$set: {dueAt}}; + } + }, + + getEnd() { + if (this.isImportedCard()) { + const card = Cards.findOne({_id: this.importedId}); + return card.endAt; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({_id: this.importedId}); + return board.endAt; + } else { + return this.endAt; + } + }, + + setEnd(endAt) { + if (this.isImportedCard()) { + return Cards.update( + { _id: this.importedId }, + {$set: {endAt}} + ); + } else if (this.isImportedBoard()) { + return Boards.update( + {_id: this.importedId}, + {$set: {endAt}} + ); + } else { + return {$set: {endAt}}; + } + }, + + getIsOvertime() { + if (this.isImportedCard()) { + const card = Cards.findOne({ _id: this.importedId }); + return card.isOvertime; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({ _id: this.importedId}); + return board.isOvertime; + } else { + return this.isOvertime; + } + }, + + setIsOvertime(isOvertime) { + if (this.isImportedCard()) { + return Cards.update( + { _id: this.importedId }, + {$set: {isOvertime}} + ); + } else if (this.isImportedBoard()) { + return Boards.update( + {_id: this.importedId}, + {$set: {isOvertime}} + ); + } else { + return {$set: {isOvertime}}; + } + }, + + getSpentTime() { + if (this.isImportedCard()) { + const card = Cards.findOne({ _id: this.importedId }); + return card.spentTime; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({ _id: this.importedId}); + return board.spentTime; + } else { + return this.spentTime; + } + }, + + setSpentTime(spentTime) { + if (this.isImportedCard()) { + return Cards.update( + { _id: this.importedId }, + {$set: {spentTime}} + ); + } else if (this.isImportedBoard()) { + return Boards.update( + {_id: this.importedId}, + {$set: {spentTime}} + ); + } else { + return {$set: {spentTime}}; + } + }, }); Cards.mutations({ @@ -657,7 +817,6 @@ Cards.mutations({ setParentId(parentId) { return {$set: {parentId}}; }, - }); From b2e175ba8ceb644e7ddd0a4c74283f1cd0c1c8aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Tue, 17 Apr 2018 23:39:09 -0300 Subject: [PATCH 08/24] Avoid exporting imported cards --- models/export.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/models/export.js b/models/export.js index 8c4c29d48..8d4f5448c 100644 --- a/models/export.js +++ b/models/export.js @@ -45,6 +45,7 @@ class Exporter { build() { const byBoard = { boardId: this._boardId }; + const byBoardNoImported = { boardId: this._boardId, importedId: null }; // we do not want to retrieve boardId in related elements const noBoardId = { fields: { boardId: 0 } }; const result = { @@ -52,7 +53,7 @@ class Exporter { }; _.extend(result, Boards.findOne(this._boardId, { fields: { stars: 0 } })); result.lists = Lists.find(byBoard, noBoardId).fetch(); - result.cards = Cards.find(byBoard, noBoardId).fetch(); + result.cards = Cards.find(byBoardNoImported, noBoardId).fetch(); result.swimlanes = Swimlanes.find(byBoard, noBoardId).fetch(); result.comments = CardComments.find(byBoard, noBoardId).fetch(); result.activities = Activities.find(byBoard, noBoardId).fetch(); From 49c415f0239d6645c41881690acfb2a18395fae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Wed, 18 Apr 2018 00:59:22 -0300 Subject: [PATCH 09/24] Add two way binding of checklists --- client/components/cards/cardTime.jade | 2 +- client/components/cards/cardTime.js | 3 -- client/components/cards/checklists.js | 4 ++- models/cards.js | 41 +++++++++++++++++++++------ 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/client/components/cards/cardTime.jade b/client/components/cards/cardTime.jade index 041af65a7..8af8c4143 100644 --- a/client/components/cards/cardTime.jade +++ b/client/components/cards/cardTime.jade @@ -6,7 +6,7 @@ template(name="editCardSpentTime") input.js-time-field#time(type="number" step="0.01" name="time" value="{{card.getSpentTime}}" placeholder=timeFormat autofocus) label(for="overtime") {{_ 'overtime'}} a.js-toggle-overtime - .materialCheckBox#overtime(class="{{#if card.getIsOvertime}}is-checked{{/if}}" name="overtime") + .materialCheckBox#overtime(class="{{#if getIsOvertime}}is-checked{{/if}}" name="overtime") if error.get .warning {{_ error.get}} diff --git a/client/components/cards/cardTime.js b/client/components/cards/cardTime.js index 9bab8e72b..80b7fc84b 100644 --- a/client/components/cards/cardTime.js +++ b/client/components/cards/cardTime.js @@ -64,9 +64,6 @@ BlazeComponent.extendComponent({ showTime() { return this.data().getSpentTime(); }, - isOvertime() { - return this.data().getIsOvertime(); - }, events() { return [{ 'click .js-edit-time': Popup.open('editCardSpentTime'), diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js index e014abba6..5a612a516 100644 --- a/client/components/cards/checklists.js +++ b/client/components/cards/checklists.js @@ -74,8 +74,10 @@ BlazeComponent.extendComponent({ event.preventDefault(); const textarea = this.find('textarea.js-add-checklist-item'); const title = textarea.value.trim(); - const cardId = this.currentData().cardId; + let cardId = this.currentData().cardId; const card = Cards.findOne(cardId); + if (card.isImported()) + cardId = card.importedId; if (title) { Checklists.insert({ diff --git a/models/cards.js b/models/cards.js index 710b9d85b..9a715ca3d 100644 --- a/models/cards.js +++ b/models/cards.js @@ -204,7 +204,11 @@ Cards.helpers({ }, checklists() { - return Checklists.find({cardId: this._id}, {sort: { sort: 1 } }); + if (this.isImportedCard()) { + return Checklists.find({cardId: this.importedId}, {sort: { sort: 1 } }); + } else { + return Checklists.find({cardId: this._id}, {sort: { sort: 1 } }); + } }, checklistItemCount() { @@ -414,7 +418,10 @@ Cards.helpers({ const board = Boards.findOne({_id: this.importedId}); return Boards.update({_id: this.importedId}, {$set: {description}}); } else { - return {$set: {description}}; + return Cards.update( + {_id: this._id}, + {$set: {description}} + ); } }, @@ -511,7 +518,10 @@ Cards.helpers({ {$set: {receivedAt}} ); } else { - return {$set: {receivedAt}}; + return Cards.update( + {_id: this._id}, + {$set: {receivedAt}} + ); } }, @@ -539,7 +549,10 @@ Cards.helpers({ {$set: {startAt}} ); } else { - return {$set: {startAt}}; + return Cards.update( + {_id: this._id}, + {$set: {startAt}} + ); } }, @@ -567,7 +580,10 @@ Cards.helpers({ {$set: {dueAt}} ); } else { - return {$set: {dueAt}}; + return Cards.update( + {_id: this._id}, + {$set: {dueAt}} + ); } }, @@ -595,7 +611,10 @@ Cards.helpers({ {$set: {endAt}} ); } else { - return {$set: {endAt}}; + return Cards.update( + {_id: this._id}, + {$set: {endAt}} + ); } }, @@ -623,7 +642,10 @@ Cards.helpers({ {$set: {isOvertime}} ); } else { - return {$set: {isOvertime}}; + return Cards.update( + {_id: this._id}, + {$set: {isOvertime}} + ); } }, @@ -651,7 +673,10 @@ Cards.helpers({ {$set: {spentTime}} ); } else { - return {$set: {spentTime}}; + return Cards.update( + {_id: this._id}, + {$set: {spentTime}} + ); } }, }); From 74a01691e3490675d78cc4f24b3b99959e702c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Wed, 18 Apr 2018 01:35:46 -0300 Subject: [PATCH 10/24] Add two way binding of activities, comments, and attachments --- client/components/activities/comments.js | 11 +++++++++-- client/components/cards/attachments.js | 9 +++++++-- models/cards.js | 22 ++++++++++++++++++---- server/publications/boards.js | 14 ++++++++++++-- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/client/components/activities/comments.js b/client/components/activities/comments.js index 9b6aedd69..137b6872f 100644 --- a/client/components/activities/comments.js +++ b/client/components/activities/comments.js @@ -21,11 +21,18 @@ BlazeComponent.extendComponent({ 'submit .js-new-comment-form'(evt) { const input = this.getInput(); const text = input.val().trim(); + const card = this.currentData(); + let boardId = card.boardId; + let cardId = card._id; + if (card.isImportedCard()) { + boardId = Cards.findOne(card.importedId).boardId; + cardId = card.importedId; + } if (text) { CardComments.insert({ text, - boardId: this.currentData().boardId, - cardId: this.currentData()._id, + boardId, + cardId, }); resetCommentInput(input); Tracker.flush(); diff --git a/client/components/cards/attachments.js b/client/components/cards/attachments.js index bc7d3979b..1a4d5bb64 100644 --- a/client/components/cards/attachments.js +++ b/client/components/cards/attachments.js @@ -57,8 +57,13 @@ Template.cardAttachmentsPopup.events({ const card = this; FS.Utility.eachFile(evt, (f) => { const file = new FS.File(f); - file.boardId = card.boardId; - file.cardId = card._id; + if (card.isImportedCard()) { + file.boardId = Cards.findOne(card.importedId).boardId; + file.cardId = card.importedId; + } else { + file.boardId = card.boardId; + file.cardId = card._id; + } file.userId = Meteor.userId(); const attachment = Attachments.insert(file); diff --git a/models/cards.js b/models/cards.js index 9a715ca3d..b295a4fe8 100644 --- a/models/cards.js +++ b/models/cards.js @@ -181,19 +181,33 @@ Cards.helpers({ }, isAssigned(memberId) { - return _.contains(this.members, memberId); + return _.contains(this.getMembers(), memberId); }, activities() { - return Activities.find({cardId: this._id}, {sort: {createdAt: -1}}); + if (this.isImportedCard()) { + return Activities.find({cardId: this.importedId}, {sort: {createdAt: -1}}); + } else if (this.isImportedBoard()) { + return Activities.find({boardId: this.importedId}, {sort: {createdAt: -1}}); + } else { + return Activities.find({cardId: this._id}, {sort: {createdAt: -1}}); + } }, comments() { - return CardComments.find({cardId: this._id}, {sort: {createdAt: -1}}); + if (this.isImportedCard()) { + return CardComments.find({cardId: this.importedId}, {sort: {createdAt: -1}}); + } else { + return CardComments.find({cardId: this._id}, {sort: {createdAt: -1}}); + } }, attachments() { - return Attachments.find({cardId: this._id}, {sort: {uploadedAt: -1}}); + if (this.isImportedCard()) { + return Attachments.find({cardId: this.importedId}, {sort: {uploadedAt: -1}}); + } else { + return Attachments.find({cardId: this._id}, {sort: {uploadedAt: -1}}); + } }, cover() { diff --git a/server/publications/boards.js b/server/publications/boards.js index bf75196a2..1d95c3d93 100644 --- a/server/publications/boards.js +++ b/server/publications/boards.js @@ -99,8 +99,18 @@ Meteor.publishRelations('board', function(boardId) { // And in the meantime our code below works pretty well -- it's not even a // hack! this.cursor(Cards.find({ boardId }), function(cardId, card) { - this.cursor(Cards.find({_id: card.importedId})); - this.cursor(Boards.find({_id: card.importedId})); + if (card.type === 'cardType-importedCard') { + const impCardId = card.importedId; + this.cursor(Cards.find({ _id: impCardId })); + this.cursor(CardComments.find({ cardId: impCardId })); + this.cursor(Activities.find({ cardId: impCardId })); + this.cursor(Attachments.find({ cardId: impCardId })); + this.cursor(Checklists.find({ cardId: impCardId })); + this.cursor(ChecklistItems.find({ cardId: impCardId })); + } else if (card.type === 'cardType-importedBoard') { + this.cursor(Boards.find({ _id: card.importedId})); + } + this.cursor(Activities.find({ cardId })); this.cursor(CardComments.find({ cardId })); this.cursor(Attachments.find({ cardId })); this.cursor(Checklists.find({ cardId })); From 4ffa8784a25913fda5ba2046b7e5d179569e5af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Wed, 18 Apr 2018 01:42:55 -0300 Subject: [PATCH 11/24] Avoid reimport imported card --- client/components/lists/listBody.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 778312d26..48532cac8 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -293,7 +293,7 @@ BlazeComponent.extendComponent({ this.boardId = Session.get('currentBoard'); // In order to get current board info subManager.subscribe('board', this.boardId); - const board = Boards.findOne(this.boardId); + this.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; @@ -339,6 +339,7 @@ BlazeComponent.extendComponent({ listId: this.selectedListId.get(), archived: false, importedId: null, + _id: {$nin: this.board.cards().map((card) => { return card.importedId || card._id})}, }); }, From 37306c8d2244c33aa924de375f2e17f438117d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Wed, 18 Apr 2018 02:30:24 -0300 Subject: [PATCH 12/24] Add title binding --- client/components/cards/cardDetails.jade | 6 +- client/components/cards/minicard.jade | 2 +- models/cards.js | 107 +++++++---------------- 3 files changed, 35 insertions(+), 80 deletions(-) diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index b8c16f806..71b3bce42 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -10,7 +10,7 @@ template(name="cardDetails") h2.card-details-title.js-card-title( class="{{#if canModifyCard}}js-open-inlined-form is-editable{{/if}}") +viewer - = title + = getTitle if isWatching i.fa.fa-eye.card-details-watch .card-details-path @@ -186,7 +186,7 @@ template(name="cardDetails") template(name="editCardTitleForm") textarea.js-edit-card-title(rows='1' autofocus) - = title + = getTitle .edit-controls.clearfix button.primary.confirm.js-submit-edit-card-title-form(type="submit") {{_ 'save'}} a.fa.fa-times-thin.js-close-inlined-form @@ -237,7 +237,7 @@ template(name="moveCardPopup") template(name="copyCardPopup") label(for='copy-card-title') {{_ 'title'}}: textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus) - = title + = getTitle +boardsAndLists template(name="copyChecklistToManyCardsPopup") diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 88ad55645..e7e38e7ae 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -18,7 +18,7 @@ template(name="minicard") if isImported span.imported-icon.fa.fa-share-alt +viewer - | {{ title }} + = getTitle if $eq 'subtext-with-full-path' currentBoard.presentParentTask .parent-subtext | {{ parentString ' > ' }} diff --git a/models/cards.js b/models/cards.js index b295a4fe8..c48c5fa18 100644 --- a/models/cards.js +++ b/models/cards.js @@ -693,6 +693,37 @@ Cards.helpers({ ); } }, + + getTitle() { + if (this.isImportedCard()) { + const card = Cards.findOne({ _id: this.importedId }); + return card.title; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({ _id: this.importedId}); + return board.title; + } else { + return this.title; + } + }, + + setTitle(title) { + if (this.isImportedCard()) { + return Cards.update( + { _id: this.importedId }, + {$set: {title}} + ); + } else if (this.isImportedBoard()) { + return Boards.update( + {_id: this.importedId}, + {$set: {title}} + ); + } else { + return Cards.update( + {_id: this._id}, + {$set: {title}} + ); + } + }, }); Cards.mutations({ @@ -712,22 +743,6 @@ Cards.mutations({ return {$set: {archived: false}}; }, - setTitle(title) { - return {$set: {title}}; - }, - - setDescription(description) { - return {$set: {description}}; - }, - - setRequestedBy(requestedBy) { - return {$set: {requestedBy}}; - }, - - setAssignedBy(assignedBy) { - return {$set: {assignedBy}}; - }, - move(swimlaneId, listId, sortIndex) { const list = Lists.findOne(listId); const mutatedFields = { @@ -756,22 +771,6 @@ Cards.mutations({ } }, - assignMember(memberId) { - return {$addToSet: {members: memberId}}; - }, - - unassignMember(memberId) { - return {$pull: {members: memberId}}; - }, - - toggleMember(memberId) { - if (this.members && this.members.indexOf(memberId) > -1) { - return this.unassignMember(memberId); - } else { - return this.assignMember(memberId); - } - }, - assignCustomField(customFieldId) { return {$addToSet: {customFields: {_id: customFieldId, value: null}}}; }, @@ -809,50 +808,6 @@ Cards.mutations({ return {$unset: {coverId: ''}}; }, - setReceived(receivedAt) { - return {$set: {receivedAt}}; - }, - - unsetReceived() { - return {$unset: {receivedAt: ''}}; - }, - - setStart(startAt) { - return {$set: {startAt}}; - }, - - unsetStart() { - return {$unset: {startAt: ''}}; - }, - - setDue(dueAt) { - return {$set: {dueAt}}; - }, - - unsetDue() { - return {$unset: {dueAt: ''}}; - }, - - setEnd(endAt) { - return {$set: {endAt}}; - }, - - unsetEnd() { - return {$unset: {endAt: ''}}; - }, - - setOvertime(isOvertime) { - return {$set: {isOvertime}}; - }, - - setSpentTime(spentTime) { - return {$set: {spentTime}}; - }, - - unsetSpentTime() { - return {$unset: {spentTime: '', isOvertime: false}}; - }, - setParentId(parentId) { return {$set: {parentId}}; }, From fb75a487fcde4f04a371a5ed097ba97cc7134c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Wed, 18 Apr 2018 02:37:20 -0300 Subject: [PATCH 13/24] Fix lint errors --- client/components/lists/listBody.js | 2 +- models/boards.js | 8 ++++---- models/cards.js | 13 +++++-------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 48532cac8..02e4ab7c6 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -339,7 +339,7 @@ BlazeComponent.extendComponent({ listId: this.selectedListId.get(), archived: false, importedId: null, - _id: {$nin: this.board.cards().map((card) => { return card.importedId || card._id})}, + _id: {$nin: this.board.cards().map((card) => { return card.importedId || card._id; })}, }); }, diff --git a/models/boards.js b/models/boards.js index a37981e0c..e3d82fc9e 100644 --- a/models/boards.js +++ b/models/boards.js @@ -323,7 +323,7 @@ Boards.helpers({ searchCards(term, excludeImported) { check(term, Match.OneOf(String, null, undefined)); - let query = { boardId: this._id }; + const query = { boardId: this._id }; if (excludeImported) { query.importedId = null; } @@ -333,9 +333,9 @@ Boards.helpers({ const regex = new RegExp(term, 'i'); query.$or = [ - { title: regex }, - { description: regex }, - ]; + { title: regex }, + { description: regex }, + ]; } return Cards.find(query, projection); diff --git a/models/cards.js b/models/cards.js index c48c5fa18..8e1ffcaa2 100644 --- a/models/cards.js +++ b/models/cards.js @@ -426,10 +426,8 @@ Cards.helpers({ setDescription(description) { if (this.isImportedCard()) { - const card = Cards.findOne({_id: this.importedId}); return Cards.update({_id: this.importedId}, {$set: {description}}); } else if (this.isImportedBoard()) { - const board = Boards.findOne({_id: this.importedId}); return Boards.update({_id: this.importedId}, {$set: {description}}); } else { return Cards.update( @@ -452,11 +450,10 @@ Cards.helpers({ return board.description; else return null; + } else if (this.description) { + return this.description; } else { - if (this.description) - return this.description; - else - return null; + return null; } }, @@ -545,7 +542,7 @@ Cards.helpers({ return card.startAt; } else if (this.isImportedBoard()) { const board = Boards.findOne({_id: this.importedId}); - return board.startAt + return board.startAt; } else { return this.startAt; } @@ -576,7 +573,7 @@ Cards.helpers({ return card.dueAt; } else if (this.isImportedBoard()) { const board = Boards.findOne({_id: this.importedId}); - return board.dueAt + return board.dueAt; } else { return this.dueAt; } From 10aab8a7336ff9a6c313eb34b22771b70b3df5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Fri, 20 Apr 2018 13:17:33 -0300 Subject: [PATCH 14/24] Remove imported cards and boards colors --- client/components/cards/minicard.styl | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/client/components/cards/minicard.styl b/client/components/cards/minicard.styl index ea737c6b4..f593c3426 100644 --- a/client/components/cards/minicard.styl +++ b/client/components/cards/minicard.styl @@ -44,33 +44,6 @@ 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 From f0597ef0c496352cb102d85227a46831a8b04c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Fri, 20 Apr 2018 23:52:13 -0300 Subject: [PATCH 15/24] Indicate board or card through icons. Indicate if archived --- client/components/cards/cardDetails.jade | 7 +++++-- client/components/cards/minicard.jade | 11 +++++++++-- client/components/cards/minicard.js | 11 +++++++++++ client/components/cards/minicard.styl | 2 ++ i18n/en.i18n.json | 1 + models/cards.js | 12 ++++++++++++ 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 71b3bce42..d8efc7a69 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -20,8 +20,11 @@ template(name="cardDetails") // else {{_ 'top-level-card'}} - if archived - p.warning {{_ 'card-archived'}} + if getArchived + if isImportedBoard + p.warning {{_ 'board-archived'}} + else + p.warning {{_ 'card-archived'}} .card-details-items .card-details-item.card-details-item-received diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index e7e38e7ae..450af3c61 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -15,8 +15,15 @@ template(name="minicard") if $eq 'prefix-with-parent' currentBoard.presentParentTask .parent-prefix | {{ parentCardName }} - if isImported - span.imported-icon.fa.fa-share-alt + if isImportedBoard + a.js-imported-link + span.imported-icon.fa.fa-folder + else if isImportedCard + a.js-imported-link + span.imported-icon.fa.fa-id-card + if getArchived + span.imported-icon.imported-archived.fa.fa-archive + +viewer = getTitle if $eq 'subtext-with-full-path' currentBoard.presentParentTask diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index a98b5730e..e81705a95 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -6,4 +6,15 @@ BlazeComponent.extendComponent({ template() { return 'minicard'; }, + + events() { + return [{ + 'click .js-imported-link' (evt) { + if (this.data().isImportedCard()) + Utils.goCardId(this.data().importedId); + else if (this.data().isImportedBoard()) + Utils.goBoardId(this.data().importedId); + }, + }]; + }, }).register('minicard'); diff --git a/client/components/cards/minicard.styl b/client/components/cards/minicard.styl index f593c3426..89beb1c25 100644 --- a/client/components/cards/minicard.styl +++ b/client/components/cards/minicard.styl @@ -51,6 +51,8 @@ margin-right: 11px vertical-align: baseline font-size: 0.9em + .imported-archived + color: #937760 .is-selected & transform: translateX(11px) diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 08fc129f9..bd9780a79 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", diff --git a/models/cards.js b/models/cards.js index 8e1ffcaa2..987ce330e 100644 --- a/models/cards.js +++ b/models/cards.js @@ -721,6 +721,18 @@ Cards.helpers({ ); } }, + + getArchived() { + if (this.isImportedCard()) { + const card = Cards.findOne({ _id: this.importedId }); + return card.archived; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({ _id: this.importedId}); + return board.archived; + } else { + return this.archived; + } + }, }); Cards.mutations({ From bce22425280248eda01132ccc58c9f5beefb712a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Sat, 21 Apr 2018 00:14:10 -0300 Subject: [PATCH 16/24] Add imported card location --- client/components/cards/cardDetails.jade | 4 ++++ client/components/cards/cardDetails.styl | 6 ++++++ models/cards.js | 14 ++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index d8efc7a69..7f2065698 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -19,6 +19,10 @@ template(name="cardDetails") a.js-parent-card(href=linkForCard) {{title}} // else {{_ 'top-level-card'}} + if isImportedCard + h3.imported-card-location + +viewer + | {{getBoardTitle}} > {{getTitle}} if getArchived if isImportedBoard diff --git a/client/components/cards/cardDetails.styl b/client/components/cards/cardDetails.styl index 42d27d119..ab65a5d6a 100644 --- a/client/components/cards/cardDetails.styl +++ b/client/components/cards/cardDetails.styl @@ -47,6 +47,12 @@ margin: 7px 0 0 padding: 0 + .imported-card-location + font-style: italic + font-size: 1em + margin-bottom: 0 + & p + margin-bottom: 0 form.inlined-form margin-top: 5px diff --git a/models/cards.js b/models/cards.js index 987ce330e..c6e80ea81 100644 --- a/models/cards.js +++ b/models/cards.js @@ -703,6 +703,20 @@ Cards.helpers({ } }, + getBoardTitle() { + if (this.isImportedCard()) { + const card = Cards.findOne({ _id: this.importedId }); + const board = Boards.findOne({ _id: card.boardId }); + return board.title; + } else if (this.isImportedBoard()) { + const board = Boards.findOne({ _id: this.importedId}); + return board.title; + } else { + const board = Boards.findOne({ _id: this.boardId }); + return board.title; + } + }, + setTitle(title) { if (this.isImportedCard()) { return Cards.update( From 6adfcb35138259c5969e63d20a68cd6f9e8c393c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Wed, 2 May 2018 14:20:55 -0300 Subject: [PATCH 17/24] Refactor imported -> linked in models --- models/boards.js | 6 +- models/cards.js | 194 +++++++++++++++++++++++------------------------ models/export.js | 4 +- 3 files changed, 102 insertions(+), 102 deletions(-) diff --git a/models/boards.js b/models/boards.js index e3d82fc9e..11df0bb53 100644 --- a/models/boards.js +++ b/models/boards.js @@ -320,12 +320,12 @@ Boards.helpers({ return _id; }, - searchCards(term, excludeImported) { + searchCards(term, excludeLinked) { check(term, Match.OneOf(String, null, undefined)); const query = { boardId: this._id }; - if (excludeImported) { - query.importedId = null; + if (excludeLinked) { + query.linkedId = null; } const projection = { limit: 10, sort: { createdAt: -1 } }; diff --git a/models/cards.js b/models/cards.js index c6e80ea81..2c0da0930 100644 --- a/models/cards.js +++ b/models/cards.js @@ -136,7 +136,7 @@ Cards.attachSchema(new SimpleSchema({ type: { type: String, }, - importedId: { + linkedId: { type: String, optional: true, }, @@ -185,26 +185,26 @@ Cards.helpers({ }, activities() { - if (this.isImportedCard()) { - return Activities.find({cardId: this.importedId}, {sort: {createdAt: -1}}); - } else if (this.isImportedBoard()) { - return Activities.find({boardId: this.importedId}, {sort: {createdAt: -1}}); + if (this.isLinkedCard()) { + return Activities.find({cardId: this.linkedId}, {sort: {createdAt: -1}}); + } else if (this.isLinkedBoard()) { + return Activities.find({boardId: this.linkedId}, {sort: {createdAt: -1}}); } else { return Activities.find({cardId: this._id}, {sort: {createdAt: -1}}); } }, comments() { - if (this.isImportedCard()) { - return CardComments.find({cardId: this.importedId}, {sort: {createdAt: -1}}); + if (this.isLinkedCard()) { + return CardComments.find({cardId: this.linkedId}, {sort: {createdAt: -1}}); } else { return CardComments.find({cardId: this._id}, {sort: {createdAt: -1}}); } }, attachments() { - if (this.isImportedCard()) { - return Attachments.find({cardId: this.importedId}, {sort: {uploadedAt: -1}}); + if (this.isLinkedCard()) { + return Attachments.find({cardId: this.linkedId}, {sort: {uploadedAt: -1}}); } else { return Attachments.find({cardId: this._id}, {sort: {uploadedAt: -1}}); } @@ -218,8 +218,8 @@ Cards.helpers({ }, checklists() { - if (this.isImportedCard()) { - return Checklists.find({cardId: this.importedId}, {sort: { sort: 1 } }); + if (this.isLinkedCard()) { + return Checklists.find({cardId: this.linkedId}, {sort: { sort: 1 } }); } else { return Checklists.find({cardId: this._id}, {sort: { sort: 1 } }); } @@ -412,23 +412,23 @@ Cards.helpers({ return this.parentId === ''; }, - isImportedCard() { - return this.type === 'cardType-importedCard'; + isLinkedCard() { + return this.type === 'cardType-linkedCard'; }, - isImportedBoard() { - return this.type === 'cardType-importedBoard'; + isLinkedBoard() { + return this.type === 'cardType-linkedBoard'; }, - isImported() { - return this.isImportedCard() || this.isImportedBoard(); + isLinked() { + return this.isLinkedCard() || this.isLinkedBoard(); }, setDescription(description) { - if (this.isImportedCard()) { - return Cards.update({_id: this.importedId}, {$set: {description}}); - } else if (this.isImportedBoard()) { - return Boards.update({_id: this.importedId}, {$set: {description}}); + if (this.isLinkedCard()) { + return Cards.update({_id: this.linkedId}, {$set: {description}}); + } else if (this.isLinkedBoard()) { + return Boards.update({_id: this.linkedId}, {$set: {description}}); } else { return Cards.update( {_id: this._id}, @@ -438,14 +438,14 @@ Cards.helpers({ }, getDescription() { - if (this.isImportedCard()) { - const card = Cards.findOne({_id: this.importedId}); + if (this.isLinkedCard()) { + const card = Cards.findOne({_id: this.linkedId}); if (card && card.description) return card.description; else return null; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({_id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({_id: this.linkedId}); if (board && board.description) return board.description; else @@ -458,11 +458,11 @@ Cards.helpers({ }, getMembers() { - if (this.isImportedCard()) { - const card = Cards.findOne({_id: this.importedId}); + if (this.isLinkedCard()) { + const card = Cards.findOne({_id: this.linkedId}); return card.members; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({_id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({_id: this.linkedId}); return board.activeMembers().map((member) => { return member.userId; }); @@ -472,13 +472,13 @@ Cards.helpers({ }, assignMember(memberId) { - if (this.isImportedCard()) { + if (this.isLinkedCard()) { return Cards.update( - { _id: this.importedId }, + { _id: this.linkedId }, { $addToSet: { members: memberId }} ); - } else if (this.isImportedBoard()) { - const board = Boards.findOne({_id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({_id: this.linkedId}); return board.addMember(memberId); } else { return Cards.update( @@ -489,13 +489,13 @@ Cards.helpers({ }, unassignMember(memberId) { - if (this.isImportedCard()) { + if (this.isLinkedCard()) { return Cards.update( - { _id: this.importedId }, + { _id: this.linkedId }, { $pull: { members: memberId }} ); - } else if (this.isImportedBoard()) { - const board = Boards.findOne({_id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({_id: this.linkedId}); return board.removeMember(memberId); } else { return Cards.update( @@ -514,8 +514,8 @@ Cards.helpers({ }, getReceived() { - if (this.isImportedCard()) { - const card = Cards.findOne({_id: this.importedId}); + if (this.isLinkedCard()) { + const card = Cards.findOne({_id: this.linkedId}); return card.receivedAt; } else { return this.receivedAt; @@ -523,9 +523,9 @@ Cards.helpers({ }, setReceived(receivedAt) { - if (this.isImportedCard()) { + if (this.isLinkedCard()) { return Cards.update( - {_id: this.importedId}, + {_id: this.linkedId}, {$set: {receivedAt}} ); } else { @@ -537,11 +537,11 @@ Cards.helpers({ }, getStart() { - if (this.isImportedCard()) { - const card = Cards.findOne({_id: this.importedId}); + if (this.isLinkedCard()) { + const card = Cards.findOne({_id: this.linkedId}); return card.startAt; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({_id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({_id: this.linkedId}); return board.startAt; } else { return this.startAt; @@ -549,14 +549,14 @@ Cards.helpers({ }, setStart(startAt) { - if (this.isImportedCard()) { + if (this.isLinkedCard()) { return Cards.update( - { _id: this.importedId }, + { _id: this.linkedId }, {$set: {startAt}} ); - } else if (this.isImportedBoard()) { + } else if (this.isLinkedBoard()) { return Boards.update( - {_id: this.importedId}, + {_id: this.linkedId}, {$set: {startAt}} ); } else { @@ -568,11 +568,11 @@ Cards.helpers({ }, getDue() { - if (this.isImportedCard()) { - const card = Cards.findOne({_id: this.importedId}); + if (this.isLinkedCard()) { + const card = Cards.findOne({_id: this.linkedId}); return card.dueAt; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({_id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({_id: this.linkedId}); return board.dueAt; } else { return this.dueAt; @@ -580,14 +580,14 @@ Cards.helpers({ }, setDue(dueAt) { - if (this.isImportedCard()) { + if (this.isLinkedCard()) { return Cards.update( - { _id: this.importedId }, + { _id: this.linkedId }, {$set: {dueAt}} ); - } else if (this.isImportedBoard()) { + } else if (this.isLinkedBoard()) { return Boards.update( - {_id: this.importedId}, + {_id: this.linkedId}, {$set: {dueAt}} ); } else { @@ -599,11 +599,11 @@ Cards.helpers({ }, getEnd() { - if (this.isImportedCard()) { - const card = Cards.findOne({_id: this.importedId}); + if (this.isLinkedCard()) { + const card = Cards.findOne({_id: this.linkedId}); return card.endAt; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({_id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({_id: this.linkedId}); return board.endAt; } else { return this.endAt; @@ -611,14 +611,14 @@ Cards.helpers({ }, setEnd(endAt) { - if (this.isImportedCard()) { + if (this.isLinkedCard()) { return Cards.update( - { _id: this.importedId }, + { _id: this.linkedId }, {$set: {endAt}} ); - } else if (this.isImportedBoard()) { + } else if (this.isLinkedBoard()) { return Boards.update( - {_id: this.importedId}, + {_id: this.linkedId}, {$set: {endAt}} ); } else { @@ -630,11 +630,11 @@ Cards.helpers({ }, getIsOvertime() { - if (this.isImportedCard()) { - const card = Cards.findOne({ _id: this.importedId }); + if (this.isLinkedCard()) { + const card = Cards.findOne({ _id: this.linkedId }); return card.isOvertime; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({ _id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({ _id: this.linkedId}); return board.isOvertime; } else { return this.isOvertime; @@ -642,14 +642,14 @@ Cards.helpers({ }, setIsOvertime(isOvertime) { - if (this.isImportedCard()) { + if (this.isLinkedCard()) { return Cards.update( - { _id: this.importedId }, + { _id: this.linkedId }, {$set: {isOvertime}} ); - } else if (this.isImportedBoard()) { + } else if (this.isLinkedBoard()) { return Boards.update( - {_id: this.importedId}, + {_id: this.linkedId}, {$set: {isOvertime}} ); } else { @@ -661,11 +661,11 @@ Cards.helpers({ }, getSpentTime() { - if (this.isImportedCard()) { - const card = Cards.findOne({ _id: this.importedId }); + if (this.isLinkedCard()) { + const card = Cards.findOne({ _id: this.linkedId }); return card.spentTime; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({ _id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({ _id: this.linkedId}); return board.spentTime; } else { return this.spentTime; @@ -673,14 +673,14 @@ Cards.helpers({ }, setSpentTime(spentTime) { - if (this.isImportedCard()) { + if (this.isLinkedCard()) { return Cards.update( - { _id: this.importedId }, + { _id: this.linkedId }, {$set: {spentTime}} ); - } else if (this.isImportedBoard()) { + } else if (this.isLinkedBoard()) { return Boards.update( - {_id: this.importedId}, + {_id: this.linkedId}, {$set: {spentTime}} ); } else { @@ -692,11 +692,11 @@ Cards.helpers({ }, getTitle() { - if (this.isImportedCard()) { - const card = Cards.findOne({ _id: this.importedId }); + if (this.isLinkedCard()) { + const card = Cards.findOne({ _id: this.linkedId }); return card.title; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({ _id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({ _id: this.linkedId}); return board.title; } else { return this.title; @@ -704,12 +704,12 @@ Cards.helpers({ }, getBoardTitle() { - if (this.isImportedCard()) { - const card = Cards.findOne({ _id: this.importedId }); + if (this.isLinkedCard()) { + const card = Cards.findOne({ _id: this.linkedId }); const board = Boards.findOne({ _id: card.boardId }); return board.title; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({ _id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({ _id: this.linkedId}); return board.title; } else { const board = Boards.findOne({ _id: this.boardId }); @@ -718,14 +718,14 @@ Cards.helpers({ }, setTitle(title) { - if (this.isImportedCard()) { + if (this.isLinkedCard()) { return Cards.update( - { _id: this.importedId }, + { _id: this.linkedId }, {$set: {title}} ); - } else if (this.isImportedBoard()) { + } else if (this.isLinkedBoard()) { return Boards.update( - {_id: this.importedId}, + {_id: this.linkedId}, {$set: {title}} ); } else { @@ -737,11 +737,11 @@ Cards.helpers({ }, getArchived() { - if (this.isImportedCard()) { - const card = Cards.findOne({ _id: this.importedId }); + if (this.isLinkedCard()) { + const card = Cards.findOne({ _id: this.linkedId }); return card.archived; - } else if (this.isImportedBoard()) { - const board = Boards.findOne({ _id: this.importedId}); + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({ _id: this.linkedId}); return board.archived; } else { return this.archived; diff --git a/models/export.js b/models/export.js index 8d4f5448c..ed4c52d90 100644 --- a/models/export.js +++ b/models/export.js @@ -45,7 +45,7 @@ class Exporter { build() { const byBoard = { boardId: this._boardId }; - const byBoardNoImported = { boardId: this._boardId, importedId: null }; + const byBoardNoLinked = { boardId: this._boardId, linkedId: null }; // we do not want to retrieve boardId in related elements const noBoardId = { fields: { boardId: 0 } }; const result = { @@ -53,7 +53,7 @@ class Exporter { }; _.extend(result, Boards.findOne(this._boardId, { fields: { stars: 0 } })); result.lists = Lists.find(byBoard, noBoardId).fetch(); - result.cards = Cards.find(byBoardNoImported, noBoardId).fetch(); + result.cards = Cards.find(byBoardNoLinked, noBoardId).fetch(); result.swimlanes = Swimlanes.find(byBoard, noBoardId).fetch(); result.comments = CardComments.find(byBoard, noBoardId).fetch(); result.activities = Activities.find(byBoard, noBoardId).fetch(); From f76d8e47a859c64a99cfd460e3fd496965bf021a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Wed, 2 May 2018 15:03:22 -0300 Subject: [PATCH 18/24] Refactor imported -> linked in components --- client/components/activities/comments.js | 6 ++--- client/components/cards/attachments.js | 6 ++--- client/components/cards/cardDetails.jade | 6 ++--- client/components/cards/cardDetails.styl | 2 +- client/components/cards/checklists.js | 4 ++-- client/components/cards/minicard.jade | 19 ++++++++-------- client/components/cards/minicard.js | 10 ++++----- client/components/cards/minicard.styl | 8 +++---- client/components/lists/list.styl | 4 ++-- client/components/lists/listBody.jade | 12 +++++----- client/components/lists/listBody.js | 28 ++++++++++++------------ 11 files changed, 52 insertions(+), 53 deletions(-) diff --git a/client/components/activities/comments.js b/client/components/activities/comments.js index 137b6872f..34b6402cd 100644 --- a/client/components/activities/comments.js +++ b/client/components/activities/comments.js @@ -24,9 +24,9 @@ BlazeComponent.extendComponent({ const card = this.currentData(); let boardId = card.boardId; let cardId = card._id; - if (card.isImportedCard()) { - boardId = Cards.findOne(card.importedId).boardId; - cardId = card.importedId; + if (card.isLinkedCard()) { + boardId = Cards.findOne(card.linkedId).boardId; + cardId = card.linkedId; } if (text) { CardComments.insert({ diff --git a/client/components/cards/attachments.js b/client/components/cards/attachments.js index 1a4d5bb64..5cac930d3 100644 --- a/client/components/cards/attachments.js +++ b/client/components/cards/attachments.js @@ -57,9 +57,9 @@ Template.cardAttachmentsPopup.events({ const card = this; FS.Utility.eachFile(evt, (f) => { const file = new FS.File(f); - if (card.isImportedCard()) { - file.boardId = Cards.findOne(card.importedId).boardId; - file.cardId = card.importedId; + if (card.isLinkedCard()) { + file.boardId = Cards.findOne(card.linkedId).boardId; + file.cardId = card.linkedId; } else { file.boardId = card.boardId; file.cardId = card._id; diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 7f2065698..98fba6926 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -19,13 +19,13 @@ template(name="cardDetails") a.js-parent-card(href=linkForCard) {{title}} // else {{_ 'top-level-card'}} - if isImportedCard - h3.imported-card-location + if isLinkedCard + h3.linked-card-location +viewer | {{getBoardTitle}} > {{getTitle}} if getArchived - if isImportedBoard + if isLinkedBoard p.warning {{_ 'board-archived'}} else p.warning {{_ 'card-archived'}} diff --git a/client/components/cards/cardDetails.styl b/client/components/cards/cardDetails.styl index ab65a5d6a..1e290305b 100644 --- a/client/components/cards/cardDetails.styl +++ b/client/components/cards/cardDetails.styl @@ -47,7 +47,7 @@ margin: 7px 0 0 padding: 0 - .imported-card-location + .linked-card-location font-style: italic font-size: 1em margin-bottom: 0 diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js index 5a612a516..5d789351c 100644 --- a/client/components/cards/checklists.js +++ b/client/components/cards/checklists.js @@ -76,8 +76,8 @@ BlazeComponent.extendComponent({ const title = textarea.value.trim(); let cardId = this.currentData().cardId; const card = Cards.findOne(cardId); - if (card.isImported()) - cardId = card.importedId; + if (card.isLinked()) + cardId = card.linkedId; if (title) { Checklists.insert({ diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 450af3c61..37f537db9 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -1,7 +1,7 @@ template(name="minicard") .minicard( - class="{{#if isImportedCard}}imported-card{{/if}}" - class="{{#if isImportedBoard}}imported-board{{/if}}") + class="{{#if isLinkedCard}}linked-card{{/if}}" + class="{{#if isLinkedBoard}}linked-board{{/if}}") if cover .minicard-cover(style="background-image: url('{{cover.url}}');") if labels @@ -15,15 +15,14 @@ template(name="minicard") if $eq 'prefix-with-parent' currentBoard.presentParentTask .parent-prefix | {{ parentCardName }} - if isImportedBoard - a.js-imported-link - span.imported-icon.fa.fa-folder - else if isImportedCard - a.js-imported-link - span.imported-icon.fa.fa-id-card + if isLinkedBoard + a.js-linked-link + span.linked-icon.fa.fa-folder + else if isLinkedCard + a.js-linked-link + span.linked-icon.fa.fa-id-card if getArchived - span.imported-icon.imported-archived.fa.fa-archive - + span.linked-icon.linked-archived.fa.fa-archive +viewer = getTitle if $eq 'subtext-with-full-path' currentBoard.presentParentTask diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index e81705a95..000836f93 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -9,11 +9,11 @@ BlazeComponent.extendComponent({ events() { return [{ - 'click .js-imported-link' (evt) { - if (this.data().isImportedCard()) - Utils.goCardId(this.data().importedId); - else if (this.data().isImportedBoard()) - Utils.goBoardId(this.data().importedId); + 'click .js-linked-link' (evt) { + if (this.data().isLinkedCard()) + Utils.goCardId(this.data().linkedId); + else if (this.data().isLinkedBoard()) + Utils.goBoardId(this.data().linkedId); }, }]; }, diff --git a/client/components/cards/minicard.styl b/client/components/cards/minicard.styl index 89beb1c25..8fec72388 100644 --- a/client/components/cards/minicard.styl +++ b/client/components/cards/minicard.styl @@ -44,14 +44,14 @@ transition: transform 0.2s, border-radius 0.2s - &.imported-board - &.imported-card - .imported-icon + &.linked-board + &.linked-card + .linked-icon display: inline-block margin-right: 11px vertical-align: baseline font-size: 0.9em - .imported-archived + .linked-archived color: #937760 .is-selected & diff --git a/client/components/lists/list.styl b/client/components/lists/list.styl index 0e170ebfc..72cb19f42 100644 --- a/client/components/lists/list.styl +++ b/client/components/lists/list.styl @@ -188,11 +188,11 @@ top: -@padding right: 17px -.import-board-wrapper +.link-board-wrapper display: flex align-items: baseline - .js-import-board + .js-link-board margin-left: 15px .search-card-results diff --git a/client/components/lists/listBody.jade b/client/components/lists/listBody.jade index 419e158a0..8069717e5 100644 --- a/client/components/lists/listBody.jade +++ b/client/components/lists/listBody.jade @@ -36,7 +36,7 @@ template(name="addCardForm") button.primary.confirm(type="submit") {{_ 'add'}} span.quiet | {{_ 'or'}} - a.js-import {{_ 'import'}} + a.js-link {{_ 'link'}} span.quiet |   | / @@ -46,16 +46,16 @@ template(name="autocompleteLabelLine") .minicard-label(class="card-label-{{colorName}}" title=labelName) span(class="{{#if hasNoName}}quiet{{/if}}")= labelName -template(name="importCardPopup") +template(name="linkCardPopup") label {{_ 'boards'}}: - .import-board-wrapper + .link-board-wrapper select.js-select-boards each boards if $eq _id currentBoard._id option(value="{{_id}}" selected) {{_ 'current'}} else option(value="{{_id}}") {{title}} - input.primary.confirm.js-import-board(type="button" value="{{_ 'import'}}") + input.primary.confirm.js-link-board(type="button" value="{{_ 'link'}}") label {{_ 'swimlanes'}}: select.js-select-swimlanes @@ -73,11 +73,11 @@ template(name="importCardPopup") option(value="{{_id}}") {{title}} .edit-controls.clearfix - input.primary.confirm.js-done(type="button" value="{{_ 'import'}}") + input.primary.confirm.js-done(type="button" value="{{_ 'link'}}") template(name="searchCardPopup") label {{_ 'boards'}}: - .import-board-wrapper + .link-board-wrapper select.js-select-boards each boards if $eq _id currentBoard._id diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 02e4ab7c6..83592a641 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -200,7 +200,7 @@ BlazeComponent.extendComponent({ events() { return [{ keydown: this.pressKey, - 'click .js-import': Popup.open('importCard'), + 'click .js-link': Popup.open('linkCard'), 'click .js-search': Popup.open('searchCard'), }]; }, @@ -338,8 +338,8 @@ BlazeComponent.extendComponent({ swimlaneId: this.selectedSwimlaneId.get(), listId: this.selectedListId.get(), archived: false, - importedId: null, - _id: {$nin: this.board.cards().map((card) => { return card.importedId || card._id; })}, + linkedId: null, + _id: {$nin: this.board.cards().map((card) => { return card.linkedId || card._id; })}, }); }, @@ -356,7 +356,7 @@ BlazeComponent.extendComponent({ this.selectedListId.set($(evt.currentTarget).val()); }, 'click .js-done' (evt) { - // IMPORT CARD + // LINK CARD evt.stopPropagation(); evt.preventDefault(); const _id = Cards.insert({ @@ -365,14 +365,14 @@ BlazeComponent.extendComponent({ swimlaneId: this.swimlaneId, boardId: this.boardId, sort: Lists.findOne(this.listId).cards().count(), - type: 'cardType-importedCard', - importedId: $('.js-select-cards option:selected').val(), + type: 'cardType-linkedCard', + linkedId: $('.js-select-cards option:selected').val(), }); Filter.addException(_id); Popup.close(); }, - 'click .js-import-board' (evt) { - //IMPORT BOARD + 'click .js-link-board' (evt) { + //LINK BOARD evt.stopPropagation(); evt.preventDefault(); const impBoardId = $('.js-select-boards option:selected').val(); @@ -382,15 +382,15 @@ BlazeComponent.extendComponent({ swimlaneId: this.swimlaneId, boardId: this.boardId, sort: Lists.findOne(this.listId).cards().count(), - type: 'cardType-importedBoard', - importedId: impBoardId, + type: 'cardType-linkedBoard', + linkedId: impBoardId, }); Filter.addException(_id); Popup.close(); }, }]; }, -}).register('importCardPopup'); +}).register('linkCardPopup'); BlazeComponent.extendComponent({ mixins() { @@ -452,7 +452,7 @@ BlazeComponent.extendComponent({ this.term.set(evt.target.searchTerm.value); }, 'click .js-minicard'(evt) { - // IMPORT CARD + // LINK CARD const card = Blaze.getData(evt.currentTarget); const _id = Cards.insert({ title: card.title, //dummy @@ -460,8 +460,8 @@ BlazeComponent.extendComponent({ swimlaneId: this.swimlaneId, boardId: this.boardId, sort: Lists.findOne(this.listId).cards().count(), - type: 'cardType-importedCard', - importedId: card._id, + type: 'cardType-linkedCard', + linkedId: card._id, }); Filter.addException(_id); Popup.close(); From 692a1bc369314bc3f8464e2b7ae611775a07be6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Wed, 2 May 2018 15:11:26 -0300 Subject: [PATCH 19/24] Refactor imported -> linked in server and i18n --- i18n/en.i18n.json | 7 ++++--- server/migrations.js | 2 +- server/publications/boards.js | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index bd9780a79..f4222c5bd 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -137,8 +137,8 @@ "cards-count": "Cards", "casSignIn" : "Sign In with CAS", "cardType-card": "Card", - "cardType-importedCard": "Imported Card", - "cardType-importedBoard": "Imported Board", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -175,7 +175,7 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", - "importCardPopup-title": "Import Card", + "linkCardPopup-title": "Link Card", "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", @@ -267,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/server/migrations.js b/server/migrations.js index 32f24e4c5..16fe225e1 100644 --- a/server/migrations.js +++ b/server/migrations.js @@ -219,7 +219,7 @@ Migrations.add('add-card-types', () => { { _id: card._id }, { $set: { type: 'cardType-card', - importedId: null } }, + linkedId: null } }, noValidate ); }); diff --git a/server/publications/boards.js b/server/publications/boards.js index 1d95c3d93..b68f7360c 100644 --- a/server/publications/boards.js +++ b/server/publications/boards.js @@ -99,16 +99,16 @@ Meteor.publishRelations('board', function(boardId) { // And in the meantime our code below works pretty well -- it's not even a // hack! this.cursor(Cards.find({ boardId }), function(cardId, card) { - if (card.type === 'cardType-importedCard') { - const impCardId = card.importedId; + if (card.type === 'cardType-linkedCard') { + const impCardId = card.linkedId; this.cursor(Cards.find({ _id: impCardId })); this.cursor(CardComments.find({ cardId: impCardId })); this.cursor(Activities.find({ cardId: impCardId })); this.cursor(Attachments.find({ cardId: impCardId })); this.cursor(Checklists.find({ cardId: impCardId })); this.cursor(ChecklistItems.find({ cardId: impCardId })); - } else if (card.type === 'cardType-importedBoard') { - this.cursor(Boards.find({ _id: card.importedId})); + } else if (card.type === 'cardType-linkedBoard') { + this.cursor(Boards.find({ _id: card.linkedId})); } this.cursor(Activities.find({ cardId })); this.cursor(CardComments.find({ cardId })); From 315db00e83d95c1a8a97d10c41de7a5e10d42cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Wed, 2 May 2018 15:29:52 -0300 Subject: [PATCH 20/24] Fix lint warning --- client/components/cards/minicard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index 000836f93..da7f9e01b 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -9,7 +9,7 @@ BlazeComponent.extendComponent({ events() { return [{ - 'click .js-linked-link' (evt) { + 'click .js-linked-link' () { if (this.data().isLinkedCard()) Utils.goCardId(this.data().linkedId); else if (this.data().isLinkedBoard()) From 67301e07e277f715de1b9d909e53f0875140e4af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Sat, 11 Aug 2018 00:50:20 +0200 Subject: [PATCH 21/24] Fix rebase errors --- client/components/cards/cardDate.js | 22 ++++------------------ client/components/cards/cardDetails.jade | 7 ------- client/components/cards/subtasks.js | 1 + server/migrations.js | 1 + 4 files changed, 6 insertions(+), 25 deletions(-) diff --git a/client/components/cards/cardDate.js b/client/components/cards/cardDate.js index aa0dca4c1..e38143d50 100644 --- a/client/components/cards/cardDate.js +++ b/client/components/cards/cardDate.js @@ -256,9 +256,8 @@ class CardStartDate extends CardDate { classes() { let classes = 'start-date' + ' '; -<<<<<<< HEAD - const dueAt = this.data().dueAt; - const endAt = this.data().endAt; + const dueAt = this.data().getDue(); + const endAt = this.data().getEnd(); const theDate = this.date.get(); const now = this.now.get(); // if dueAt or endAt exist & are > startAt, startAt doesn't need to be flagged @@ -268,10 +267,6 @@ class CardStartDate extends CardDate { else if (theDate.isBefore(now, 'minute')) classes += 'almost-due'; else -======= - if (this.date.get().isBefore(this.now.get(), 'minute') && - this.now.get().isBefore(this.data().getDue())) { ->>>>>>> Add two way binding of card/board times classes += 'current'; return classes; } @@ -299,8 +294,7 @@ class CardDueDate extends CardDate { classes() { let classes = 'due-date' + ' '; - - const endAt = this.data().endAt; + const endAt = this.data().getEnd(); const theDate = this.date.get(); const now = this.now.get(); // if the due date is after the end date, green - done early @@ -341,22 +335,14 @@ class CardEndDate extends CardDate { classes() { let classes = 'end-date' + ' '; -<<<<<<< HEAD - const dueAt = this.data.dueAt; + const dueAt = this.data().getDue(); const theDate = this.date.get(); - // if dueAt exists & is after endAt, endAt doesn't need to be flagged - if ((dueAt) && (theDate.isAfter(dueAt, 'minute'))) - classes += 'long-overdue'; - else - classes += 'current'; -======= if (this.date.get().diff(this.data().getDue(), 'days') >= 2) classes += 'long-overdue'; else if (this.date.get().diff(this.data().getDue(), 'days') >= 0) classes += 'due'; else if (this.date.get().diff(this.data().getDue(), 'days') >= -2) classes += 'almost-due'; ->>>>>>> Add two way binding of card/board times return classes; } diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 98fba6926..4401d24b1 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -59,13 +59,6 @@ template(name="cardDetails") else a.js-end-date {{_ 'add'}} - .card-details-item.card-details-item-due - h3.card-details-item-title {{_ 'card-due'}} - if dueAt - +cardDueDate - else - a.js-due-date {{_ 'add'}} - .card-details-items .card-details-item.card-details-item-members h3.card-details-item-title {{_ 'members'}} diff --git a/client/components/cards/subtasks.js b/client/components/cards/subtasks.js index 9c6f265e6..1651d4494 100644 --- a/client/components/cards/subtasks.js +++ b/client/components/cards/subtasks.js @@ -29,6 +29,7 @@ BlazeComponent.extendComponent({ boardId: targetBoard._id, sort: sortIndex, swimlaneId, + type: 'cardType-card', }); // In case the filter is active we need to add the newly inserted card in diff --git a/server/migrations.js b/server/migrations.js index 16fe225e1..91c34be2d 100644 --- a/server/migrations.js +++ b/server/migrations.js @@ -223,6 +223,7 @@ Migrations.add('add-card-types', () => { noValidate ); }); +}); Migrations.add('add-custom-fields-to-cards', () => { Cards.update({ From 17308dc5f306e9b357045e97e0a1abe963dcb5d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Manelli?= Date: Sat, 11 Aug 2018 01:00:21 +0200 Subject: [PATCH 22/24] Fix lint errors --- client/components/cards/cardDate.js | 6 +- client/lib/filter.js | 251 ++++++++++++++-------------- models/boards.js | 4 - 3 files changed, 127 insertions(+), 134 deletions(-) diff --git a/client/components/cards/cardDate.js b/client/components/cards/cardDate.js index e38143d50..182705d52 100644 --- a/client/components/cards/cardDate.js +++ b/client/components/cards/cardDate.js @@ -337,11 +337,11 @@ class CardEndDate extends CardDate { let classes = 'end-date' + ' '; const dueAt = this.data().getDue(); const theDate = this.date.get(); - if (this.date.get().diff(this.data().getDue(), 'days') >= 2) + if (theDate.diff(dueAt, 'days') >= 2) classes += 'long-overdue'; - else if (this.date.get().diff(this.data().getDue(), 'days') >= 0) + else if (theDate.diff(dueAt, 'days') >= 0) classes += 'due'; - else if (this.date.get().diff(this.data().getDue(), 'days') >= -2) + else if (theDate.diff(dueAt, 'days') >= -2) classes += 'almost-due'; return classes; } diff --git a/client/lib/filter.js b/client/lib/filter.js index a4e586923..26140ca6d 100644 --- a/client/lib/filter.js +++ b/client/lib/filter.js @@ -187,27 +187,27 @@ class AdvancedFilter { if (commands[i].cmd) { switch (commands[i].cmd) { case '(': - { - level++; - if (start === -1) start = i; - continue; - } + { + level++; + if (start === -1) start = i; + continue; + } case ')': - { - level--; - commands.splice(i, 1); - i--; - continue; - } - default: - { - if (level > 0) { - subcommands.push(commands[i]); + { + level--; commands.splice(i, 1); i--; continue; } - } + default: + { + if (level > 0) { + subcommands.push(commands[i]); + commands.splice(i, 1); + i--; + continue; + } + } } } } @@ -229,113 +229,112 @@ class AdvancedFilter { case '=': case '==': case '===': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - if (commands[i + 1].regex) { - const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); - let regex = null; - if (match.length > 2) - regex = new RegExp(match[1], match[2]); + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + if (commands[i + 1].regex) + { + const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); + let regex = null; + if (match.length > 2) + regex = new RegExp(match[1], match[2]); + else + regex = new RegExp(match[1]); + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': regex }; + } else - regex = new RegExp(match[1]); - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': regex }; + { + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} }; + } + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; } - else - { - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} }; - } - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } case '!=': case '!==': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - if (commands[i + 1].regex) { - const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); - let regex = null; - if (match.length > 2) - regex = new RegExp(match[1], match[2]); + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + if (commands[i + 1].regex) + { + const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); + let regex = null; + if (match.length > 2) + regex = new RegExp(match[1], match[2]); + else + regex = new RegExp(match[1]); + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: regex } }; + } else - regex = new RegExp(match[1]); - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: regex } }; + { + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} } }; + } + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; } - else - { - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} } }; - } - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } case '>': case 'gt': case 'Gt': case 'GT': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gt: parseInt(str, 10) } }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gt: parseInt(str, 10) } }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } case '>=': case '>==': case 'gte': case 'Gte': case 'GTE': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gte: parseInt(str, 10) } }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gte: parseInt(str, 10) } }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } case '<': case 'lt': case 'Lt': case 'LT': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lt: parseInt(str, 10) } }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lt: parseInt(str, 10) } }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } case '<=': case '<==': case 'lte': case 'Lte': case 'LTE': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lte: parseInt(str, 10) } }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lte: parseInt(str, 10) } }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } } } } @@ -350,45 +349,43 @@ class AdvancedFilter { case 'OR': case '|': case '||': - { - const op1 = commands[i - 1]; - const op2 = commands[i + 1]; - commands[i] = { $or: [op1, op2] }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } + { + const op1 = commands[i - 1]; + const op2 = commands[i + 1]; + commands[i] = { $or: [op1, op2] }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } case 'and': case 'And': case 'AND': case '&': case '&&': - { - const op1 = commands[i - 1]; - const op2 = commands[i + 1]; - commands[i] = { $and: [op1, op2] }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - + { + const op1 = commands[i - 1]; + const op2 = commands[i + 1]; + commands[i] = { $and: [op1, op2] }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } case 'not': case 'Not': case 'NOT': case '!': - { - const op1 = commands[i + 1]; - commands[i] = { $not: op1 }; - commands.splice(i + 1, 1); - //changed = true; - i--; - break; - } - + { + const op1 = commands[i + 1]; + commands[i] = { $not: op1 }; + commands.splice(i + 1, 1); + //changed = true; + i--; + break; + } } } } diff --git a/models/boards.js b/models/boards.js index 11df0bb53..a017eb3ff 100644 --- a/models/boards.js +++ b/models/boards.js @@ -246,10 +246,6 @@ Boards.helpers({ return Swimlanes.find({ boardId: this._id, archived: false }, { sort: { sort: 1 } }); }, - cards() { - return Cards.find({ boardId: this._id, archived: false }, { sort: { sort: 1 } }); - }, - hasOvertimeCards(){ const card = Cards.findOne({isOvertime: true, boardId: this._id, archived: false} ); return card !== undefined; From 8177a1ed0ac5f3061f4a9afb06ef779bcd798c23 Mon Sep 17 00:00:00 2001 From: Lauri Ojansivu Date: Sun, 12 Aug 2018 14:03:13 +0300 Subject: [PATCH 23/24] Update translations. --- i18n/ar.i18n.json | 7 +++++++ i18n/bg.i18n.json | 7 +++++++ i18n/br.i18n.json | 7 +++++++ i18n/ca.i18n.json | 7 +++++++ i18n/cs.i18n.json | 7 +++++++ i18n/de.i18n.json | 7 +++++++ i18n/el.i18n.json | 7 +++++++ i18n/en-GB.i18n.json | 7 +++++++ i18n/eo.i18n.json | 7 +++++++ i18n/es-AR.i18n.json | 7 +++++++ i18n/es.i18n.json | 7 +++++++ i18n/eu.i18n.json | 7 +++++++ i18n/fa.i18n.json | 7 +++++++ i18n/fi.i18n.json | 7 +++++++ i18n/fr.i18n.json | 7 +++++++ i18n/gl.i18n.json | 7 +++++++ i18n/he.i18n.json | 7 +++++++ i18n/hu.i18n.json | 7 +++++++ i18n/hy.i18n.json | 7 +++++++ i18n/id.i18n.json | 7 +++++++ i18n/ig.i18n.json | 7 +++++++ i18n/it.i18n.json | 7 +++++++ i18n/ja.i18n.json | 7 +++++++ i18n/ka.i18n.json | 7 +++++++ i18n/km.i18n.json | 7 +++++++ i18n/ko.i18n.json | 7 +++++++ i18n/lv.i18n.json | 7 +++++++ i18n/mn.i18n.json | 7 +++++++ i18n/nb.i18n.json | 7 +++++++ i18n/nl.i18n.json | 7 +++++++ i18n/pl.i18n.json | 7 +++++++ i18n/pt-BR.i18n.json | 7 +++++++ i18n/pt.i18n.json | 7 +++++++ i18n/ro.i18n.json | 7 +++++++ i18n/ru.i18n.json | 7 +++++++ i18n/sr.i18n.json | 7 +++++++ i18n/sv.i18n.json | 7 +++++++ i18n/ta.i18n.json | 7 +++++++ i18n/th.i18n.json | 7 +++++++ i18n/tr.i18n.json | 7 +++++++ i18n/uk.i18n.json | 7 +++++++ i18n/vi.i18n.json | 7 +++++++ i18n/zh-CN.i18n.json | 7 +++++++ i18n/zh-TW.i18n.json | 7 +++++++ 44 files changed, 308 insertions(+) diff --git a/i18n/ar.i18n.json b/i18n/ar.i18n.json index 53fa803b0..4b07b711a 100644 --- a/i18n/ar.i18n.json +++ b/i18n/ar.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "مثل « todo list » على سبيل المثال", "cancel": "إلغاء", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "%s تعليقات لهذه البطاقة", "card-delete-notice": "هذا حذف أبديّ . سوف تفقد كل الإجراءات المنوطة بهذه البطاقة", "card-delete-pop": "سيتم إزالة جميع الإجراءات من تبعات النشاط، وأنك لن تكون قادرا على إعادة فتح البطاقة. لا يوجد التراجع.", @@ -135,6 +136,9 @@ "cards": "بطاقات", "cards-count": "بطاقات", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "تعديل الصورة الشخصية", "change-password": "تغيير كلمة المرور", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "نسخ رابط البطاقة إلى الحافظة", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "نسخ البطاقة", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "إنشاء لوحة", "home": "الرئيسية", "import": "Import", + "link": "Link", "import-board": "استيراد لوحة", "import-board-c": "استيراد لوحة", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/bg.i18n.json b/i18n/bg.i18n.json index c8ca3b358..cb0618b4b 100644 --- a/i18n/bg.i18n.json +++ b/i18n/bg.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "Картата е преместена в Кошчето.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Тази карта има %s коментар.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Карти", "cards-count": "Карти", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Промени", "change-avatar": "Промени аватара", "change-password": "Промени паролата", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Копирай връзката на картата в клипборда", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Копирай картата", "copyChecklistToManyCardsPopup-title": "Копирай чеклисти в други карти", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Начало", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/br.i18n.json b/i18n/br.i18n.json index 7b511bf10..8832efc95 100644 --- a/i18n/br.i18n.json +++ b/i18n/br.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Kartennoù", "cards-count": "Kartennoù", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Kemmañ ger-tremen", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/ca.i18n.json b/i18n/ca.i18n.json index bf891c90b..3c0fcd26b 100644 --- a/i18n/ca.i18n.json +++ b/i18n/ca.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Igual que “Bucket List”, per exemple", "cancel": "Cancel·la", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Aquesta fitxa té %s comentaris.", "card-delete-notice": "L'esborrat és permanent. Perdreu totes les accions associades a aquesta fitxa.", "card-delete-pop": "Totes les accions s'eliminaran de l'activitat i no podreu tornar a obrir la fitxa. No es pot desfer.", @@ -135,6 +136,9 @@ "cards": "Fitxes", "cards-count": "Fitxes", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Canvia", "change-avatar": "Canvia Avatar", "change-password": "Canvia la clau", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copia l'enllaç de la ftixa al porta-retalls", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copia la fitxa", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Títols de fitxa i Descripcions de destí en aquest format JSON", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Crea tauler", "home": "Inici", "import": "importa", + "link": "Link", "import-board": "Importa tauler", "import-board-c": "Importa tauler", "import-board-title-trello": "Importa tauler des de Trello", diff --git a/i18n/cs.i18n.json b/i18n/cs.i18n.json index daf213261..09b1549e9 100644 --- a/i18n/cs.i18n.json +++ b/i18n/cs.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Například \"Než mě odvedou\"", "cancel": "Zrušit", "card-archived": "Karta byla přesunuta do koše.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Tato karta má %s komentářů.", "card-delete-notice": "Smazání je trvalé. Přijdete o všechny akce asociované s touto kartou.", "card-delete-pop": "Všechny akce budou odstraněny z kanálu aktivity a nebude možné kartu znovu otevřít. Toto nelze vrátit zpět.", @@ -135,6 +136,9 @@ "cards": "Karty", "cards-count": "Karty", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Změnit", "change-avatar": "Změnit avatar", "change-password": "Změnit heslo", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Kopírovat adresu karty do mezipaměti", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Kopírovat kartu", "copyChecklistToManyCardsPopup-title": "Kopírovat checklist do více karet", "copyChecklistToManyCardsPopup-instructions": "Názvy a popisy cílové karty v tomto formátu JSON", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Vytvořit tablo", "home": "Domů", "import": "Import", + "link": "Link", "import-board": "Importovat tablo", "import-board-c": "Importovat tablo", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/de.i18n.json b/i18n/de.i18n.json index bb4a317d7..3bc75e2d9 100644 --- a/i18n/de.i18n.json +++ b/i18n/de.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "z.B. \"Löffelliste\"", "cancel": "Abbrechen", "card-archived": "Diese Karte wurde in den Papierkorb verschoben", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Diese Karte hat %s Kommentar(e).", "card-delete-notice": "Löschen kann nicht rückgängig gemacht werden. Alle Aktionen, die dieser Karte zugeordnet sind, werden ebenfalls gelöscht.", "card-delete-pop": "Alle Aktionen werden aus dem Aktivitätsfeed entfernt und die Karte kann nicht wiedereröffnet werden. Die Aktion kann nicht rückgängig gemacht werden.", @@ -135,6 +136,9 @@ "cards": "Karten", "cards-count": "Karten", "casSignIn": "Mit CAS anmelden", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Ändern", "change-avatar": "Profilbild ändern", "change-password": "Passwort ändern", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Wollen Sie die Teilaufgabe wirklich löschen?", "confirm-checklist-delete-dialog": "Wollen Sie die Checkliste wirklich löschen?", "copy-card-link-to-clipboard": "Kopiere Link zur Karte in die Zwischenablage", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Karte kopieren", "copyChecklistToManyCardsPopup-title": "Checklistenvorlage in mehrere Karten kopieren", "copyChecklistToManyCardsPopup-instructions": "Titel und Beschreibungen der Zielkarten im folgenden JSON-Format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Board erstellen", "home": "Home", "import": "Importieren", + "link": "Link", "import-board": "Board importieren", "import-board-c": "Board importieren", "import-board-title-trello": "Board von Trello importieren", diff --git a/i18n/el.i18n.json b/i18n/el.i18n.json index 138440041..56afc6e4c 100644 --- a/i18n/el.i18n.json +++ b/i18n/el.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Ακύρωση", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Κάρτες", "cards-count": "Κάρτες", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Αλλαγή", "change-avatar": "Change Avatar", "change-password": "Αλλαγή Κωδικού", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Εισαγωγή", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/en-GB.i18n.json b/i18n/en-GB.i18n.json index 937fc657f..70d8f2d16 100644 --- a/i18n/en-GB.i18n.json +++ b/i18n/en-GB.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/eo.i18n.json b/i18n/eo.i18n.json index ef7c6476a..c8561488c 100644 --- a/i18n/eo.i18n.json +++ b/i18n/eo.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Kartoj", "cards-count": "Kartoj", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Ŝanĝi", "change-avatar": "Change Avatar", "change-password": "Ŝangi pasvorton", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Krei tavolon", "home": "Hejmo", "import": "Importi", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/es-AR.i18n.json b/i18n/es-AR.i18n.json index 649355858..b9a201ef6 100644 --- a/i18n/es-AR.i18n.json +++ b/i18n/es-AR.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Como \"Lista de Contenedores\" por ejemplo", "cancel": "Cancelar", "card-archived": "Esta tarjeta es movida a la Papelera de Reciclaje", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Esta tarjeta tiene %s comentario.", "card-delete-notice": "Borrar es permanente. Perderás todas las acciones asociadas con esta tarjeta.", "card-delete-pop": "Todas las acciones van a ser eliminadas del agregador de actividad y no podrás re-abrir la tarjeta. No hay deshacer.", @@ -135,6 +136,9 @@ "cards": "Tarjetas", "cards-count": "Tarjetas", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Cambiar", "change-avatar": "Cambiar Avatar", "change-password": "Cambiar Contraseña", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copiar enlace a tarjeta en el portapapeles", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copiar Tarjeta", "copyChecklistToManyCardsPopup-title": "Copiar Plantilla Checklist a Muchas Tarjetas", "copyChecklistToManyCardsPopup-instructions": "Títulos y Descripciones de la Tarjeta Destino en este formato JSON", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Crear Tablero", "home": "Inicio", "import": "Importar", + "link": "Link", "import-board": "importar tablero", "import-board-c": "Importar tablero", "import-board-title-trello": "Importar tablero de Trello", diff --git a/i18n/es.i18n.json b/i18n/es.i18n.json index c49f7e176..d2f42ed35 100644 --- a/i18n/es.i18n.json +++ b/i18n/es.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Como “Cosas por hacer” por ejemplo", "cancel": "Cancelar", "card-archived": "Esta tarjeta se ha enviado a la papelera de reciclaje.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Esta tarjeta tiene %s comentarios.", "card-delete-notice": "la eliminación es permanente. Perderás todas las acciones asociadas a esta tarjeta.", "card-delete-pop": "Se eliminarán todas las acciones del historial de actividades y no se podrá volver a abrir la tarjeta. Esta acción no puede deshacerse.", @@ -135,6 +136,9 @@ "cards": "Tarjetas", "cards-count": "Tarjetas", "casSignIn": "Iniciar sesión con CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Cambiar", "change-avatar": "Cambiar el avatar", "change-password": "Cambiar la contraseña", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "¿Seguro que quieres eliminar la subtarea?", "confirm-checklist-delete-dialog": "¿Seguro que quieres eliminar la lista de verificación?", "copy-card-link-to-clipboard": "Copiar el enlace de la tarjeta al portapapeles", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copiar la tarjeta", "copyChecklistToManyCardsPopup-title": "Copiar la plantilla de la lista de verificación en varias tarjetas", "copyChecklistToManyCardsPopup-instructions": "Títulos y descripciones de las tarjetas de destino en formato JSON", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Crear tablero", "home": "Inicio", "import": "Importar", + "link": "Link", "import-board": "importar un tablero", "import-board-c": "Importar un tablero", "import-board-title-trello": "Importar un tablero desde Trello", diff --git a/i18n/eu.i18n.json b/i18n/eu.i18n.json index 08729670e..9e5b9957c 100644 --- a/i18n/eu.i18n.json +++ b/i18n/eu.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Esaterako \"Pertz zerrenda\"", "cancel": "Utzi", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Txartel honek iruzkin %s dauka.", "card-delete-notice": "Ezabaketa behin betiko da. Txartel honi lotutako ekintza guztiak galduko dituzu.", "card-delete-pop": "Ekintza guztiak ekintza jariotik kenduko dira eta ezin izango duzu txartela berrireki. Ez dago desegiterik.", @@ -135,6 +136,9 @@ "cards": "Txartelak", "cards-count": "Txartelak", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Aldatu", "change-avatar": "Aldatu avatarra", "change-password": "Aldatu pasahitza", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Kopiatu txartela arbelera", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Kopiatu txartela", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Sortu arbela", "home": "Hasiera", "import": "Inportatu", + "link": "Link", "import-board": "inportatu arbela", "import-board-c": "Inportatu arbela", "import-board-title-trello": "Inportatu arbela Trellotik", diff --git a/i18n/fa.i18n.json b/i18n/fa.i18n.json index af711d21e..80139835d 100644 --- a/i18n/fa.i18n.json +++ b/i18n/fa.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "برای مثال چیزی شبیه \"لیست سبدها\"", "cancel": "انصراف", "card-archived": "این کارت به سطل زباله ریخته شده است", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "این کارت دارای %s نظر است.", "card-delete-notice": "حذف دائمی. تمامی موارد مرتبط با این کارت از بین خواهند رفت.", "card-delete-pop": "همه اقدامات از این پردازه (خوراک) حذف خواهد شد و امکان بازگرداندن کارت وجود نخواهد داشت.", @@ -135,6 +136,9 @@ "cards": "کارت‌ها", "cards-count": "کارت‌ها", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "تغییر", "change-avatar": "تغییر تصویر", "change-password": "تغییر کلمه عبور", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "مطمئنا چک لیست پاک شود؟", "copy-card-link-to-clipboard": "درج پیوند کارت در حافظه", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "کپی کارت", "copyChecklistToManyCardsPopup-title": "کپی قالب کارت به کارت‌های متعدد", "copyChecklistToManyCardsPopup-instructions": "عنوان و توضیحات کارت مقصد در این قالب JSON", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "ایجاد تخته", "home": "خانه", "import": "وارد کردن", + "link": "Link", "import-board": "وارد کردن تخته", "import-board-c": "وارد کردن تخته", "import-board-title-trello": "وارد کردن تخته از Trello", diff --git a/i18n/fi.i18n.json b/i18n/fi.i18n.json index 2b1e92863..d02dae06d 100644 --- a/i18n/fi.i18n.json +++ b/i18n/fi.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Kuten “Laatikko lista” esimerkiksi", "cancel": "Peruuta", "card-archived": "Tämä kortti on siirretty roskakoriin.", + "board-archived": "Tämä taulu on siirretty roskakoriin.", "card-comments-title": "Tässä kortissa on %s kommenttia.", "card-delete-notice": "Poistaminen on lopullista. Menetät kaikki toimet jotka on liitetty tähän korttiin.", "card-delete-pop": "Kaikki toimet poistetaan toimintasyötteestä ja et tule pystymään uudelleenavaamaan korttia. Tätä ei voi peruuttaa.", @@ -135,6 +136,9 @@ "cards": "Kortit", "cards-count": "korttia", "casSignIn": "CAS kirjautuminen", + "cardType-card": "Kortti", + "cardType-linkedCard": "Linkitetty kortti", + "cardType-linkedBoard": "Linkitetty taulu", "change": "Muokkaa", "change-avatar": "Muokkaa profiilikuvaa", "change-password": "Vaihda salasana", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Oletko varma että haluat poistaa alitehtävän?", "confirm-checklist-delete-dialog": "Oletko varma että haluat poistaa tarkistuslistan?", "copy-card-link-to-clipboard": "Kopioi kortin linkki leikepöydälle", + "linkCardPopup-title": "Linkitä kortti", + "searchCardPopup-title": "Etsi kortti", "copyCardPopup-title": "Kopioi kortti", "copyChecklistToManyCardsPopup-title": "Kopioi tarkistuslistan malli monille korteille", "copyChecklistToManyCardsPopup-instructions": "Kohde korttien otsikot ja kuvaukset JSON muodossa", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Luo taulu", "home": "Koti", "import": "Tuo", + "link": "Linkitä", "import-board": "tuo taulu", "import-board-c": "Tuo taulu", "import-board-title-trello": "Tuo taulu Trellosta", diff --git a/i18n/fr.i18n.json b/i18n/fr.i18n.json index eebd2b1cf..0468a7af2 100644 --- a/i18n/fr.i18n.json +++ b/i18n/fr.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Comme « todo list » par exemple", "cancel": "Annuler", "card-archived": "Cette carte est déplacée vers la corbeille.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Cette carte a %s commentaires.", "card-delete-notice": "La suppression est permanente. Vous perdrez toutes les actions associées à cette carte.", "card-delete-pop": "Toutes les actions vont être supprimées du suivi d'activités et vous ne pourrez plus utiliser cette carte. Cette action est irréversible.", @@ -135,6 +136,9 @@ "cards": "Cartes", "cards-count": "Cartes", "casSignIn": "Se connecter avec CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Modifier", "change-avatar": "Modifier l'avatar", "change-password": "Modifier le mot de passe", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Êtes-vous sûr de vouloir supprimer la sous-tâche ?", "confirm-checklist-delete-dialog": "Êtes-vous sûr de vouloir supprimer la checklist ?", "copy-card-link-to-clipboard": "Copier le lien vers la carte dans le presse-papier", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copier la carte", "copyChecklistToManyCardsPopup-title": "Copier le modèle de checklist vers plusieurs cartes", "copyChecklistToManyCardsPopup-instructions": "Titres et descriptions des cartes de destination dans ce format JSON", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Créer un tableau", "home": "Accueil", "import": "Importer", + "link": "Link", "import-board": "importer un tableau", "import-board-c": "Importer un tableau", "import-board-title-trello": "Importer le tableau depuis Trello", diff --git a/i18n/gl.i18n.json b/i18n/gl.i18n.json index aec06426c..ab4cce627 100644 --- a/i18n/gl.i18n.json +++ b/i18n/gl.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancelar", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Tarxetas", "cards-count": "Tarxetas", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Cambiar", "change-avatar": "Cambiar o avatar", "change-password": "Cambiar o contrasinal", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Crear taboleiro", "home": "Inicio", "import": "Importar", + "link": "Link", "import-board": "importar taboleiro", "import-board-c": "Importar taboleiro", "import-board-title-trello": "Importar taboleiro de Trello", diff --git a/i18n/he.i18n.json b/i18n/he.i18n.json index 68d51c340..021e80951 100644 --- a/i18n/he.i18n.json +++ b/i18n/he.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "כמו למשל „רשימת המשימות“", "cancel": "ביטול", "card-archived": "כרטיס זה הועבר לסל המחזור", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "לכרטיס זה %s תגובות.", "card-delete-notice": "מחיקה היא סופית. כל הפעולות המשויכות לכרטיס זה תלכנה לאיוד.", "card-delete-pop": "כל הפעולות יוסרו מלוח הפעילות ולא תהיה אפשרות לפתוח מחדש את הכרטיס. אין דרך חזרה.", @@ -135,6 +136,9 @@ "cards": "כרטיסים", "cards-count": "כרטיסים", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "שינוי", "change-avatar": "החלפת תמונת משתמש", "change-password": "החלפת ססמה", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "האם למחוק את תת המשימה?", "confirm-checklist-delete-dialog": "האם אתה בטוח שברצונך למחוק את רשימת המשימות?", "copy-card-link-to-clipboard": "העתקת קישור הכרטיס ללוח הגזירים", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "העתק כרטיס", "copyChecklistToManyCardsPopup-title": "העתקת תבנית רשימת מטלות למגוון כרטיסים", "copyChecklistToManyCardsPopup-instructions": "כותרות ותיאורים של כרטיסי יעד בתצורת JSON זו", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "יצירת לוח", "home": "בית", "import": "יבוא", + "link": "Link", "import-board": "ייבוא לוח", "import-board-c": "יבוא לוח", "import-board-title-trello": "ייבוא לוח מטרלו", diff --git a/i18n/hu.i18n.json b/i18n/hu.i18n.json index 3e3f39032..2e8861045 100644 --- a/i18n/hu.i18n.json +++ b/i18n/hu.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Mint például „Bakancslista”", "cancel": "Mégse", "card-archived": "Ez a kártya a lomtárba került.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Ez a kártya %s hozzászólást tartalmaz.", "card-delete-notice": "A törlés végleges. Az összes műveletet elveszíti, amely ehhez a kártyához tartozik.", "card-delete-pop": "Az összes művelet el lesz távolítva a tevékenységlistából, és nem lesz képes többé újra megnyitni a kártyát. Nincs visszaállítási lehetőség.", @@ -135,6 +136,9 @@ "cards": "Kártyák", "cards-count": "Kártyák", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Változtatás", "change-avatar": "Avatár megváltoztatása", "change-password": "Jelszó megváltoztatása", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Kártya hivatkozásának másolása a vágólapra", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Kártya másolása", "copyChecklistToManyCardsPopup-title": "Ellenőrzőlista sablon másolása több kártyára", "copyChecklistToManyCardsPopup-instructions": "A célkártyák címe és a leírások ebben a JSON formátumban", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Tábla létrehozása", "home": "Kezdőlap", "import": "Importálás", + "link": "Link", "import-board": "tábla importálása", "import-board-c": "Tábla importálása", "import-board-title-trello": "Tábla importálása a Trello oldalról", diff --git a/i18n/hy.i18n.json b/i18n/hy.i18n.json index a56db7589..2161be397 100644 --- a/i18n/hy.i18n.json +++ b/i18n/hy.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/id.i18n.json b/i18n/id.i18n.json index 06076aa55..f273ccf4e 100644 --- a/i18n/id.i18n.json +++ b/i18n/id.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Contohnya seperti “Bucket List” ", "cancel": "Batal", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Kartu ini punya %s komentar", "card-delete-notice": "Menghapus sama dengan permanen. Anda akan kehilangan semua aksi yang terhubung ke kartu ini", "card-delete-pop": "Semua aksi akan dihapus dari aktivitas dan anda tidak bisa lagi buka kartu ini", @@ -135,6 +136,9 @@ "cards": "Daftar Kartu", "cards-count": "Daftar Kartu", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Ubah", "change-avatar": "Ubah Avatar", "change-password": "Ubah Kata Sandi", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Buat Panel", "home": "Beranda", "import": "Impor", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Impor panel dari Trello", diff --git a/i18n/ig.i18n.json b/i18n/ig.i18n.json index 5b7597397..07f1a8240 100644 --- a/i18n/ig.i18n.json +++ b/i18n/ig.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Gbanwe", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/it.i18n.json b/i18n/it.i18n.json index 7968967df..b4d13dbe2 100644 --- a/i18n/it.i18n.json +++ b/i18n/it.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Per esempio come \"una lista di cose da fare\"", "cancel": "Cancella", "card-archived": "Questa scheda è stata spostata nel cestino.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Questa scheda ha %s commenti.", "card-delete-notice": "L'eliminazione è permanente. Tutte le azioni associate a questa scheda andranno perse.", "card-delete-pop": "Tutte le azioni saranno rimosse dal flusso attività e non sarai in grado di riaprire la scheda. Non potrai tornare indietro.", @@ -135,6 +136,9 @@ "cards": "Schede", "cards-count": "Schede", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Cambia", "change-avatar": "Cambia avatar", "change-password": "Cambia password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copia link della scheda sulla clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copia Scheda", "copyChecklistToManyCardsPopup-title": "Copia template checklist su più schede", "copyChecklistToManyCardsPopup-instructions": "Titolo e la descrizione della scheda di destinazione in questo formato JSON", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Crea bacheca", "home": "Home", "import": "Importa", + "link": "Link", "import-board": "Importa bacheca", "import-board-c": "Importa bacheca", "import-board-title-trello": "Importa una bacheca da Trello", diff --git a/i18n/ja.i18n.json b/i18n/ja.i18n.json index c70b0d35b..67207dbc6 100644 --- a/i18n/ja.i18n.json +++ b/i18n/ja.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "例:バケットリスト", "cancel": "キャンセル", "card-archived": "このカードはゴミ箱に移動されます", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "%s 件のコメントがあります。", "card-delete-notice": "削除は取り消しできません。このカードに関係するすべてのアクションがなくなります。", "card-delete-pop": "すべての内容がアクティビティから削除されます。この削除は元に戻すことができません。", @@ -135,6 +136,9 @@ "cards": "カード", "cards-count": "カード", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "変更", "change-avatar": "アバターの変更", "change-password": "パスワードの変更", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "カードへのリンクをクリップボードにコピー", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "カードをコピー", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "ボードの作成", "home": "ホーム", "import": "インポート", + "link": "Link", "import-board": "ボードをインポート", "import-board-c": "ボードをインポート", "import-board-title-trello": "Trelloからボードをインポート", diff --git a/i18n/ka.i18n.json b/i18n/ka.i18n.json index be7cce21e..2b3db17d7 100644 --- a/i18n/ka.i18n.json +++ b/i18n/ka.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "მაგალითად “Bucket List” ", "cancel": "გაუქმება", "card-archived": "ბარათი გადატანილია სანაგვე ურნაში ", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "ამ ბარათს ჰქონდა%s კომენტარი.", "card-delete-notice": "წაშლის შემთხვევაში ამ ბარათთან ასცირებული ყველა მოქმედება დაიკარგება.", "card-delete-pop": "ყველა მოქმედება წაიშლება აქტივობების ველიდან და თქვენ აღარ შეგეძლებათ ბარათის ხელახლა გახსნა. დაბრუნება შეუძლებელია.", @@ -135,6 +136,9 @@ "cards": "ბარათები", "cards-count": "ბარათები", "casSignIn": "შესვლა CAS-ით", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "ცვლილება", "change-avatar": "სურათის შეცვლა", "change-password": "პაროლის შეცვლა", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "დარწმუნებული ხართ, რომ გსურთ ქვესაქმიანობის წაშლა? ", "confirm-checklist-delete-dialog": "დარწმუნებული ხართ, რომ გსურთ კატალოგის წაშლა ? ", "copy-card-link-to-clipboard": "დააკოპირეთ ბარათის ბმული clipboard-ზე", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "ბარათის ასლი", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "დაფის შექმნა", "home": "სახლი", "import": "იმპორტირება", + "link": "Link", "import-board": " დაფის იმპორტი", "import-board-c": "დაფის იმპორტი", "import-board-title-trello": "დაფის იმპორტი Trello-დან", diff --git a/i18n/km.i18n.json b/i18n/km.i18n.json index e0838ffce..dc1e01bfa 100644 --- a/i18n/km.i18n.json +++ b/i18n/km.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/ko.i18n.json b/i18n/ko.i18n.json index ddcc3c0cd..e1f24f2ac 100644 --- a/i18n/ko.i18n.json +++ b/i18n/ko.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "예: “프로젝트 이름“ 입력", "cancel": "취소", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "이 카드에 %s 코멘트가 있습니다.", "card-delete-notice": "영구 삭제입니다. 이 카드와 관련된 모든 작업들을 잃게됩니다.", "card-delete-pop": "모든 작업이 활동 내역에서 제거되며 카드를 다시 열 수 없습니다. 복구가 안되니 주의하시기 바랍니다.", @@ -135,6 +136,9 @@ "cards": "카드", "cards-count": "카드", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "변경", "change-avatar": "아바타 변경", "change-password": "암호 변경", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "클립보드에 카드의 링크가 복사되었습니다.", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "카드 복사", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "보드 생성", "home": "홈", "import": "가져오기", + "link": "Link", "import-board": "보드 가져오기", "import-board-c": "보드 가져오기", "import-board-title-trello": "Trello에서 보드 가져오기", diff --git a/i18n/lv.i18n.json b/i18n/lv.i18n.json index abeec5ad8..0dd992379 100644 --- a/i18n/lv.i18n.json +++ b/i18n/lv.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/mn.i18n.json b/i18n/mn.i18n.json index f2f093b37..bb4048c8f 100644 --- a/i18n/mn.i18n.json +++ b/i18n/mn.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Аватар өөрчлөх", "change-password": "Нууц үг солих", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Самбар үүсгэх", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/nb.i18n.json b/i18n/nb.i18n.json index 72bd04309..edeb9e1f5 100644 --- a/i18n/nb.i18n.json +++ b/i18n/nb.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Som \"Bucket List\" for eksempel", "cancel": "Avbryt", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Dette kortet har %s kommentar.", "card-delete-notice": "Sletting er permanent. Du vil miste alle hendelser knyttet til dette kortet.", "card-delete-pop": "Alle handlinger vil fjernes fra feeden for aktiviteter og du vil ikke kunne åpne kortet på nytt. Det er ingen mulighet å angre.", @@ -135,6 +136,9 @@ "cards": "Kort", "cards-count": "Kort", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Endre", "change-avatar": "Endre avatar", "change-password": "Endre passord", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/nl.i18n.json b/i18n/nl.i18n.json index 6a54b9c53..966d09c07 100644 --- a/i18n/nl.i18n.json +++ b/i18n/nl.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Zoals \"Bucket List\" bijvoorbeeld", "cancel": "Annuleren", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Deze kaart heeft %s reactie.", "card-delete-notice": "Verwijdering is permanent. Als je dit doet, verlies je alle informatie die op deze kaart is opgeslagen.", "card-delete-pop": "Alle acties worden verwijderd van de activiteiten feed, en er zal geen mogelijkheid zijn om de kaart opnieuw te openen. Deze actie kan je niet ongedaan maken.", @@ -135,6 +136,9 @@ "cards": "Kaarten", "cards-count": "Kaarten", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Wijzig", "change-avatar": "Wijzig avatar", "change-password": "Wijzig wachtwoord", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Kopieer kaart link naar klembord", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Kopieer kaart", "copyChecklistToManyCardsPopup-title": "Checklist sjabloon kopiëren naar meerdere kaarten", "copyChecklistToManyCardsPopup-instructions": "Doel kaart titels en omschrijvingen in dit JSON formaat", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Bord aanmaken", "home": "Voorpagina", "import": "Importeer", + "link": "Link", "import-board": "Importeer bord", "import-board-c": "Importeer bord", "import-board-title-trello": "Importeer bord van Trello", diff --git a/i18n/pl.i18n.json b/i18n/pl.i18n.json index a12a53895..5208ffba6 100644 --- a/i18n/pl.i18n.json +++ b/i18n/pl.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Anuluj", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Ta karta ma %s komentarzy.", "card-delete-notice": "Usunięcie jest trwałe. Stracisz wszystkie akcje powiązane z tą kartą.", "card-delete-pop": "Wszystkie akcje będą usunięte z widoku aktywności, nie można będzie ponownie otworzyć karty. Usunięcie jest nieodwracalne.", @@ -135,6 +136,9 @@ "cards": "Karty", "cards-count": "Karty", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Zmień", "change-avatar": "Zmień Avatar", "change-password": "Zmień hasło", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Skopiuj kartę", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Utwórz tablicę", "home": "Strona główna", "import": "Importu", + "link": "Link", "import-board": "importuj tablice", "import-board-c": "Import tablicy", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/pt-BR.i18n.json b/i18n/pt-BR.i18n.json index 82bdf9521..288dc70bf 100644 --- a/i18n/pt-BR.i18n.json +++ b/i18n/pt-BR.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "\"Bucket List\", por exemplo", "cancel": "Cancelar", "card-archived": "Este cartão foi movido para a lixeira", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Este cartão possui %s comentários.", "card-delete-notice": "A exclusão será permanente. Você perderá todas as ações associadas a este cartão.", "card-delete-pop": "Todas as ações serão removidas da lista de Atividades e vocês não poderá re-abrir o cartão. Não há como desfazer.", @@ -135,6 +136,9 @@ "cards": "Cartões", "cards-count": "Cartões", "casSignIn": "Entrar com CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Alterar", "change-avatar": "Alterar Avatar", "change-password": "Alterar Senha", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Tem certeza que deseja deletar a subtarefa?", "confirm-checklist-delete-dialog": "Tem certeza que quer deletar o checklist?", "copy-card-link-to-clipboard": "Copiar link do cartão para a área de transferência", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copiar o cartão", "copyChecklistToManyCardsPopup-title": "Copiar modelo de checklist para vários cartões", "copyChecklistToManyCardsPopup-instructions": "Títulos e descrições do cartão de destino neste formato JSON", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Criar Quadro", "home": "Início", "import": "Importar", + "link": "Link", "import-board": "importar quadro", "import-board-c": "Importar quadro", "import-board-title-trello": "Importar board do Trello", diff --git a/i18n/pt.i18n.json b/i18n/pt.i18n.json index 0d6df67eb..46073e81d 100644 --- a/i18n/pt.i18n.json +++ b/i18n/pt.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cartões", "cards-count": "Cartões", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Alterar", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/ro.i18n.json b/i18n/ro.i18n.json index 8146ee3b8..79230bcbe 100644 --- a/i18n/ro.i18n.json +++ b/i18n/ro.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/ru.i18n.json b/i18n/ru.i18n.json index 1ae38aeae..967fb426c 100644 --- a/i18n/ru.i18n.json +++ b/i18n/ru.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Например “Список дел”", "cancel": "Отмена", "card-archived": "Эта карточка перемещена в Корзину", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Комментарии (%s)", "card-delete-notice": "Это действие невозможно будет отменить. Все изменения, которые вы вносили в карточку будут потеряны.", "card-delete-pop": "Все действия будут удалены из ленты активности участников и вы не сможете заново открыть карточку. Действие необратимо", @@ -135,6 +136,9 @@ "cards": "Карточки", "cards-count": "Карточки", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Изменить", "change-avatar": "Изменить аватар", "change-password": "Изменить пароль", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Вы уверены, что хотите удалить подзадачу?", "confirm-checklist-delete-dialog": "Вы уверены, что хотите удалить чеклист?", "copy-card-link-to-clipboard": "Копировать ссылку на карточку в буфер обмена", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Копировать карточку", "copyChecklistToManyCardsPopup-title": "Копировать шаблон контрольного списка в несколько карточек", "copyChecklistToManyCardsPopup-instructions": "Названия и описания целевых карт в формате JSON", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Создать доску", "home": "Главная", "import": "Импорт", + "link": "Link", "import-board": "импортировать доску", "import-board-c": "Импортировать доску", "import-board-title-trello": "Импортировать доску из Trello", diff --git a/i18n/sr.i18n.json b/i18n/sr.i18n.json index db8e9792c..f94b52401 100644 --- a/i18n/sr.i18n.json +++ b/i18n/sr.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Na primer \"Lista zadataka\"", "cancel": "Otkaži", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Ova kartica ima %s komentar.", "card-delete-notice": "Brisanje je trajno. Izgubićeš sve akcije povezane sa ovom karticom.", "card-delete-pop": "Sve akcije će biti uklonjene sa liste aktivnosti i kartica neće moći biti ponovo otvorena. Nema vraćanja unazad.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Uvezi tablu iz Trella", diff --git a/i18n/sv.i18n.json b/i18n/sv.i18n.json index b0d502373..9be9b46a5 100644 --- a/i18n/sv.i18n.json +++ b/i18n/sv.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Gilla \"att-göra-innan-jag-dör-lista\" till exempel", "cancel": "Avbryt", "card-archived": "Detta kort flyttas till papperskorgen.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Detta kort har %s kommentar.", "card-delete-notice": "Ta bort är permanent. Du kommer att förlora alla åtgärder i samband med detta kort.", "card-delete-pop": "Alla åtgärder kommer att tas bort från aktivitetsflöde och du kommer inte att kunna öppna kortet igen. Det går inte att ångra.", @@ -135,6 +136,9 @@ "cards": "Kort", "cards-count": "Kort", "casSignIn": "Logga in med CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Ändra", "change-avatar": "Ändra avatar", "change-password": "Ändra lösenord", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Är du säker på att du vill radera deluppgift?", "confirm-checklist-delete-dialog": "Är du säker på att du vill radera checklista?", "copy-card-link-to-clipboard": "Kopiera kortlänk till urklipp", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Kopiera kort", "copyChecklistToManyCardsPopup-title": "Kopiera checklist-mallen till flera kort", "copyChecklistToManyCardsPopup-instructions": "Destinationskorttitlar och beskrivningar i detta JSON-format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Skapa anslagstavla", "home": "Hem", "import": "Importera", + "link": "Link", "import-board": "importera anslagstavla", "import-board-c": "Importera anslagstavla", "import-board-title-trello": "Importera anslagstavla från Trello", diff --git a/i18n/ta.i18n.json b/i18n/ta.i18n.json index f2b32e0f1..dfc9eed17 100644 --- a/i18n/ta.i18n.json +++ b/i18n/ta.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Cancel", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/th.i18n.json b/i18n/th.i18n.json index 86e3a65d9..ff2b20e3b 100644 --- a/i18n/th.i18n.json +++ b/i18n/th.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "ตัวอย่างเช่น “ระบบที่ต้องทำ”", "cancel": "ยกเลิก", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "การ์ดนี้มี %s ความเห็น.", "card-delete-notice": "เป็นการลบถาวร คุณจะสูญเสียข้อมูลที่เกี่ยวข้องกับการ์ดนี้ทั้งหมด", "card-delete-pop": "การดำเนินการทั้งหมดจะถูกลบจาก feed กิจกรรมและคุณไม่สามารถเปิดได้อีกครั้งหรือยกเลิกการทำ", @@ -135,6 +136,9 @@ "cards": "การ์ด", "cards-count": "การ์ด", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "เปลี่ยน", "change-avatar": "เปลี่ยนภาพ", "change-password": "เปลี่ยนรหัสผ่าน", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "สร้างบอร์ด", "home": "หน้าหลัก", "import": "นำเข้า", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "นำเข้าบอร์ดจาก Trello", diff --git a/i18n/tr.i18n.json b/i18n/tr.i18n.json index c1e2d7f83..cfc46a29e 100644 --- a/i18n/tr.i18n.json +++ b/i18n/tr.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Örn: \"Marketten Alacaklarım\"", "cancel": "İptal", "card-archived": "Bu kart Geri Dönüşüm Kutusu'na taşındı", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Bu kartta %s yorum var.", "card-delete-notice": "Silme işlemi kalıcıdır. Bu kartla ilişkili tüm eylemleri kaybedersiniz.", "card-delete-pop": "Son hareketler alanındaki tüm veriler silinecek, ayrıca bu kartı yeniden açamayacaksın. Bu işlemin geri dönüşü yok.", @@ -135,6 +136,9 @@ "cards": "Kartlar", "cards-count": "Kartlar", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Değiştir", "change-avatar": "Avatar Değiştir", "change-password": "Parola Değiştir", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Kartın linkini kopyala", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Kartı Kopyala", "copyChecklistToManyCardsPopup-title": "Yapılacaklar Listesi şemasını birden çok karta kopyala", "copyChecklistToManyCardsPopup-instructions": "Hedef Kart Başlıkları ve Açıklamaları bu JSON formatında", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Pano Oluşturma", "home": "Ana Sayfa", "import": "İçeri aktar", + "link": "Link", "import-board": "panoyu içe aktar", "import-board-c": "Panoyu içe aktar", "import-board-title-trello": "Trello'dan panoyu içeri aktar", diff --git a/i18n/uk.i18n.json b/i18n/uk.i18n.json index d2b27f81e..4d1a60f62 100644 --- a/i18n/uk.i18n.json +++ b/i18n/uk.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Відміна", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "This card has %s comment.", "card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/vi.i18n.json b/i18n/vi.i18n.json index 438529350..120b2a920 100644 --- a/i18n/vi.i18n.json +++ b/i18n/vi.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "Like “Bucket List” for example", "cancel": "Hủy", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "Thẻ này có %s bình luận.", "card-delete-notice": "Hành động xóa là không thể khôi phục. Bạn sẽ mất hết các hoạt động liên quan đến thẻ này.", "card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.", @@ -135,6 +136,9 @@ "cards": "Cards", "cards-count": "Cards", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "Change", "change-avatar": "Change Avatar", "change-password": "Change Password", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "Copy card link to clipboard", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "Create Board", "home": "Home", "import": "Import", + "link": "Link", "import-board": "import board", "import-board-c": "Import board", "import-board-title-trello": "Import board from Trello", diff --git a/i18n/zh-CN.i18n.json b/i18n/zh-CN.i18n.json index f8e3821ff..b296e2b6d 100644 --- a/i18n/zh-CN.i18n.json +++ b/i18n/zh-CN.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "例如 “目标清单”", "cancel": "取消", "card-archived": "此卡片已经被移入回收站。", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "该卡片有 %s 条评论", "card-delete-notice": "彻底删除的操作不可恢复,你将会丢失该卡片相关的所有操作记录。", "card-delete-pop": "所有的活动将从活动摘要中被移除且您将无法重新打开该卡片。此操作无法撤销。", @@ -135,6 +136,9 @@ "cards": "卡片", "cards-count": "卡片", "casSignIn": "用CAS登录", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "变更", "change-avatar": "更改头像", "change-password": "更改密码", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "确定要删除子任务吗?", "confirm-checklist-delete-dialog": "确定要删除清单吗?", "copy-card-link-to-clipboard": "复制卡片链接到剪贴板", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "复制卡片", "copyChecklistToManyCardsPopup-title": "复制清单模板至多个卡片", "copyChecklistToManyCardsPopup-instructions": "以JSON格式表示目标卡片的标题和描述", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "创建看板", "home": "首页", "import": "导入", + "link": "Link", "import-board": "导入看板", "import-board-c": "导入看板", "import-board-title-trello": "从Trello导入看板", diff --git a/i18n/zh-TW.i18n.json b/i18n/zh-TW.i18n.json index e8bcbd2c0..8926b779c 100644 --- a/i18n/zh-TW.i18n.json +++ b/i18n/zh-TW.i18n.json @@ -109,6 +109,7 @@ "bucket-example": "例如 “目標清單”", "cancel": "取消", "card-archived": "This card is moved to Recycle Bin.", + "board-archived": "This board is moved to Recycle Bin.", "card-comments-title": "該卡片有 %s 則評論", "card-delete-notice": "徹底刪除的操作不可復原,你將會遺失該卡片相關的所有操作記錄。", "card-delete-pop": "所有的動作將從活動動態中被移除且您將無法重新打開該卡片。此操作無法復原。", @@ -135,6 +136,9 @@ "cards": "卡片", "cards-count": "卡片", "casSignIn": "Sign In with CAS", + "cardType-card": "Card", + "cardType-linkedCard": "Linked Card", + "cardType-linkedBoard": "Linked Board", "change": "變更", "change-avatar": "更改大頭貼", "change-password": "更改密碼", @@ -171,6 +175,8 @@ "confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?", "confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?", "copy-card-link-to-clipboard": "將卡片連結複製到剪貼板", + "linkCardPopup-title": "Link Card", + "searchCardPopup-title": "Search Card", "copyCardPopup-title": "Copy Card", "copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", @@ -261,6 +267,7 @@ "headerBarCreateBoardPopup-title": "建立看板", "home": "首頁", "import": "匯入", + "link": "Link", "import-board": "匯入看板", "import-board-c": "匯入看板", "import-board-title-trello": "匯入在 Trello 的看板", From eac0b3e7bb73e54a61de368fe87c0817a0225838 Mon Sep 17 00:00:00 2001 From: Lauri Ojansivu Date: Sun, 12 Aug 2018 14:05:58 +0300 Subject: [PATCH 24/24] - Linked Cards and Linked Boards. Thanks to andresmanelli ! --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8be1680b..4e6d06826 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# Upcoming Wekan release + +This release add the following new features: + +- [Linked Cards and Linked Boards](https://github.com/wekan/wekan/pull/1592). + +Thanks to GitHub user andresmanelli for contributions. + # v1.26 2018-08-09 Wekan release This release fixes the following bugs: