summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/components/boards/boardHeader.jade31
-rw-r--r--client/components/boards/boardHeader.js70
-rw-r--r--client/components/cards/cardDetails.jade5
-rw-r--r--client/components/cards/subtasks.js1
-rw-r--r--i18n/en.i18n.json7
-rw-r--r--models/boards.js16
-rw-r--r--models/cards.js2
-rw-r--r--server/migrations.js12
8 files changed, 140 insertions, 4 deletions
diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade
index b4ccd3b3..59691a61 100644
--- a/client/components/boards/boardHeader.jade
+++ b/client/components/boards/boardHeader.jade
@@ -130,6 +130,10 @@ template(name="boardMenuPopup")
li: a(href="{{exportUrl}}", download="{{exportFilename}}") {{_ 'export-board'}}
li: a.js-archive-board {{_ 'archive-board'}}
li: a.js-outgoing-webhooks {{_ 'outgoing-webhooks'}}
+ hr
+ ul.pop-over-list
+ li: a.js-subtask-settings {{_ 'subtask-settings'}}
+
if isSandstorm
hr
ul.pop-over-list
@@ -193,6 +197,33 @@ template(name="boardChangeColorPopup")
if isSelected
i.fa.fa-check
+template(name="boardSubtaskSettingsPopup")
+ form.board-subtask-settings
+ a.flex.js-field-has-subtasks(class="{{#if allowsSubtasks}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsSubtasks}}is-checked{{/if}}")
+ span {{_ 'show-subtasks-field'}}
+ label
+ | {{_ 'deposit-subtasks-board'}}
+ select.js-field-deposit-board(disabled="{{#unless allowsSubtasks}}disabled{{/unless}}")
+ each boards
+ if isBoardSelected
+ option(value=_id selected="selected") {{title}}
+ else
+ option(value=_id) {{title}}
+ if isNullBoardSelected
+ option(value='null' selected="selected") {{_ 'custom-field-dropdown-none'}}
+ else
+ option(value='null') {{_ 'custom-field-dropdown-none'}}
+ hr
+ label
+ | {{_ 'deposit-subtasks-list'}}
+ select.js-field-deposit-list(disabled="{{#unless hasLists}}disabled{{/unless}}")
+ each lists
+ if isListSelected
+ option(value=_id selected="selected") {{title}}
+ else
+ option(value=_id) {{title}}
+
template(name="createBoard")
form
label
diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js
index b2640474..bafee9b9 100644
--- a/client/components/boards/boardHeader.js
+++ b/client/components/boards/boardHeader.js
@@ -25,6 +25,7 @@ Template.boardMenuPopup.events({
}),
'click .js-outgoing-webhooks': Popup.open('outgoingWebhooks'),
'click .js-import-board': Popup.open('chooseBoardSource'),
+ 'click .js-subtask-settings': Popup.open('boardSubtaskSettings'),
});
Template.boardMenuPopup.helpers({
@@ -151,6 +152,75 @@ BlazeComponent.extendComponent({
},
}).register('boardChangeColorPopup');
+BlazeComponent.extendComponent({
+ onCreated() {
+ this.currentBoard = Boards.findOne(Session.get('currentBoard'));
+ },
+
+ allowsSubtasks() {
+ return this.currentBoard.allowsSubtasks;
+ },
+
+ isBoardSelected() {
+ return this.currentBoard.subtasksDefaultBoardId === this.currentData()._id;
+ },
+
+ isNullBoardSelected() {
+ return (this.currentBoard.subtasksDefaultBoardId === null) || (this.currentBoard.subtasksDefaultBoardId === undefined);
+ },
+
+ boards() {
+ return Boards.find({
+ archived: false,
+ 'members.userId': Meteor.userId(),
+ }, {
+ sort: ['title'],
+ });
+ },
+
+ lists() {
+ return Lists.find({
+ boardId: this.currentBoard._id,
+ archived: false,
+ }, {
+ sort: ['title'],
+ });
+ },
+
+ hasLists() {
+ return this.lists().count() > 0;
+ },
+
+ isListSelected() {
+ return this.currentBoard.subtasksDefaultBoardId === this.currentData()._id;
+ },
+
+ events() {
+ return [{
+ 'click .js-field-has-subtasks'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsSubtasks = !this.currentBoard.allowsSubtasks;
+ this.currentBoard.setAllowsSubtasks(this.currentBoard.allowsSubtasks);
+ $('.js-field-has-subtasks .materialCheckBox').toggleClass('is-checked', this.currentBoard.allowsSubtasks);
+ $('.js-field-has-subtasks').toggleClass('is-checked', this.currentBoard.allowsSubtasks);
+ $('.js-field-deposit-board').prop('disabled', !this.currentBoard.allowsSubtasks);
+ },
+ 'change .js-field-deposit-board'(evt) {
+ let value = evt.target.value;
+ if (value === 'null') {
+ value = null;
+ }
+ this.currentBoard.setSubtasksDefaultBoardId(value);
+ evt.preventDefault();
+ },
+ 'change .js-field-deposit-list'(evt) {
+ this.currentBoard.setSubtasksDefaultListId(evt.target.value);
+ evt.preventDefault();
+ },
+ }];
+ },
+}).register('boardSubtaskSettingsPopup');
+
const CreateBoard = BlazeComponent.extendComponent({
template() {
return 'createBoard';
diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade
index bc0ce45c..789cc4b1 100644
--- a/client/components/cards/cardDetails.jade
+++ b/client/components/cards/cardDetails.jade
@@ -144,8 +144,9 @@ template(name="cardDetails")
hr
+checklists(cardId = _id)
- hr
- +subtasks(cardId = _id)
+ if currentBoard.allowsSubtasks
+ hr
+ +subtasks(cardId = _id)
hr
h3
diff --git a/client/components/cards/subtasks.js b/client/components/cards/subtasks.js
index 335eba36..9c6f265e 100644
--- a/client/components/cards/subtasks.js
+++ b/client/components/cards/subtasks.js
@@ -30,6 +30,7 @@ BlazeComponent.extendComponent({
sort: sortIndex,
swimlaneId,
});
+
// 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
// card will disappear instantly.
diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json
index 5e1a99e8..e410572f 100644
--- a/i18n/en.i18n.json
+++ b/i18n/en.i18n.json
@@ -482,5 +482,10 @@
"delete-board": "Delete Board",
"default-subtasks-board": "Subtasks for __board__ board",
"default": "Default",
- "queue": "Queue"
+ "queue": "Queue",
+ "subtask-settings": "Subtasks Settings",
+ "boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
+ "show-subtasks-field": "Cards can have subtasks:",
+ "deposit-subtasks-board": "Deposit subtasks to this board:",
+ "deposit-subtasks-list": "Landing list for subtasks deposited here:"
}
diff --git a/models/boards.js b/models/boards.js
index fce674ae..b5b0b0fc 100644
--- a/models/boards.js
+++ b/models/boards.js
@@ -161,6 +161,10 @@ Boards.attachSchema(new SimpleSchema({
optional: true,
defaultValue: null,
},
+ allowsSubtasks: {
+ type: Boolean,
+ defaultValue: true,
+ },
}));
@@ -473,6 +477,18 @@ Boards.mutations({
},
};
},
+
+ setAllowsSubtasks(allowsSubtasks) {
+ return { $set: { allowsSubtasks } };
+ },
+
+ setSubtasksDefaultBoardId(subtasksDefaultBoardId) {
+ return { $set: { subtasksDefaultBoardId } };
+ },
+
+ setSubtasksDefaultListId(subtasksDefaultListId) {
+ return { $set: { subtasksDefaultListId } };
+ },
});
if (Meteor.isServer) {
diff --git a/models/cards.js b/models/cards.js
index 2563fdf8..8d7a93d0 100644
--- a/models/cards.js
+++ b/models/cards.js
@@ -258,7 +258,7 @@ Cards.helpers({
return finishCount > 0 && this.subtasksCount() === finishCount;
},
- hasSubtasks() {
+ allowsSubtasks() {
return this.subtasksCount() !== 0;
},
diff --git a/server/migrations.js b/server/migrations.js
index af866d13..c3da3221 100644
--- a/server/migrations.js
+++ b/server/migrations.js
@@ -287,3 +287,15 @@ Migrations.add('add-subtasks-sort', () => {
}, noValidateMulti);
});
+Migrations.add('add-subtasks-allowed', () => {
+ Boards.update({
+ allowsSubtasks: {
+ $exists: false,
+ },
+ }, {
+ $set: {
+ allowsSubtasks: -1,
+ },
+ }, noValidateMulti);
+});
+