mirror of
https://github.com/wekan/wekan.git
synced 2026-01-24 18:26:10 +01:00
Merge branch 'harryadel-collection-mutations-migrations'
This commit is contained in:
commit
904211dba5
38 changed files with 752 additions and 1355 deletions
|
|
@ -20,7 +20,6 @@ reywood:publish-composite
|
|||
dburles:collection-helpers
|
||||
idmontie:migrations
|
||||
mongo@1.16.8
|
||||
mquandalle:collection-mutations
|
||||
|
||||
# Account system
|
||||
accounts-password@2.4.0
|
||||
|
|
|
|||
|
|
@ -79,7 +79,6 @@ mongo-dev-server@1.1.0
|
|||
mongo-id@1.0.8
|
||||
mongo-livedata@1.0.12
|
||||
mquandalle:autofocus@1.0.0
|
||||
mquandalle:collection-mutations@0.1.0
|
||||
mquandalle:jade@0.4.9
|
||||
mquandalle:jade-compiler@0.4.5
|
||||
msavin:usercache@1.8.0
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ ENV BUILD_DEPS="apt-utils gnupg gosu wget bzip2 g++ curl libarchive-tools build-
|
|||
ENV \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v14.21.4 \
|
||||
METEOR_RELEASE=METEOR@2.14 \
|
||||
METEOR_RELEASE=METEOR@2.16 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
NPM_VERSION=6.14.17 \
|
||||
|
|
@ -222,8 +222,8 @@ cd /home/wekan
|
|||
chown --recursive wekan:wekan /home/wekan
|
||||
echo "Starting meteor ${METEOR_RELEASE} installation... \n"
|
||||
#gosu wekan:wekan curl https://install.meteor.com/ | /bin/sh
|
||||
# Specify Meteor version 2.14 to be compatible: https://github.com/wekan/wekan/pull/5816/files
|
||||
#gosu wekan:wekan npm -g install meteor@2.14 --unsafe-perm
|
||||
# Specify Meteor version 2.16 to be compatible: https://github.com/wekan/wekan/pull/5816/files
|
||||
#gosu wekan:wekan npm -g install meteor@2.16 --unsafe-perm
|
||||
#mv /root/.meteor /home/wekan/
|
||||
#chown --recursive wekan:wekan /home/wekan/.meteor
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ BlazeComponent.extendComponent({
|
|||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-restore-board'() {
|
||||
async 'click .js-restore-board'() {
|
||||
// TODO : Make isSandstorm variable global
|
||||
const isSandstorm =
|
||||
Meteor.settings &&
|
||||
|
|
@ -31,13 +31,13 @@ BlazeComponent.extendComponent({
|
|||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && Utils.getCurrentBoardId()) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.archive();
|
||||
await currentBoard.archive();
|
||||
}
|
||||
const board = this.currentData();
|
||||
board.restore();
|
||||
await board.restore();
|
||||
Utils.goBoardId(board._id);
|
||||
},
|
||||
'click .js-delete-board': Popup.afterConfirm('boardDelete', function() {
|
||||
'click .js-delete-board': Popup.afterConfirm('boardDelete', async function() {
|
||||
Popup.back();
|
||||
const isSandstorm =
|
||||
Meteor.settings &&
|
||||
|
|
@ -45,9 +45,9 @@ BlazeComponent.extendComponent({
|
|||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && Utils.getCurrentBoardId()) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
Boards.remove(currentBoard._id);
|
||||
await Boards.removeAsync(currentBoard._id);
|
||||
}
|
||||
Boards.remove(this._id);
|
||||
await Boards.removeAsync(this._id);
|
||||
FlowRouter.go('home');
|
||||
}),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const UPCLS = 'fa-sort-up';
|
|||
const sortCardsBy = new ReactiveVar('');
|
||||
|
||||
Template.boardChangeTitlePopup.events({
|
||||
submit(event, templateInstance) {
|
||||
async submit(event, templateInstance) {
|
||||
const newTitle = templateInstance
|
||||
.$('.js-board-name')
|
||||
.val()
|
||||
|
|
@ -20,8 +20,8 @@ Template.boardChangeTitlePopup.events({
|
|||
.val()
|
||||
.trim();
|
||||
if (newTitle) {
|
||||
this.rename(newTitle);
|
||||
this.setDescription(newDesc);
|
||||
await this.rename(newTitle);
|
||||
await this.setDescription(newDesc);
|
||||
Popup.back();
|
||||
}
|
||||
event.preventDefault();
|
||||
|
|
@ -364,10 +364,10 @@ const CreateBoard = BlazeComponent.extendComponent({
|
|||
}).register('createTemplateContainerPopup');
|
||||
|
||||
(class HeaderBarCreateBoard extends CreateBoard {
|
||||
onSubmit(event) {
|
||||
async onSubmit(event) {
|
||||
super.onSubmit(event);
|
||||
// Immediately star boards crated with the headerbar popup.
|
||||
ReactiveCache.getCurrentUser().toggleBoardStar(this.boardId.get());
|
||||
await ReactiveCache.getCurrentUser().toggleBoardStar(this.boardId.get());
|
||||
}
|
||||
}.register('headerBarCreateBoardPopup'));
|
||||
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ BlazeComponent.extendComponent({
|
|||
ui.placeholder.height(ui.helper.height());
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
},
|
||||
stop(evt, ui) {
|
||||
async stop(evt, ui) {
|
||||
const prevBoardDom = ui.item.prev('.js-board').get(0);
|
||||
const nextBoardDom = ui.item.next('.js-board').get(0);
|
||||
const sortIndex = Utils.calculateIndex(prevBoardDom, nextBoardDom, 1);
|
||||
|
|
@ -153,7 +153,7 @@ BlazeComponent.extendComponent({
|
|||
$boards.sortable('cancel');
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser && typeof currentUser.setBoardSortIndex === 'function') {
|
||||
currentUser.setBoardSortIndex(board._id, sortIndex.base);
|
||||
await currentUser.setBoardSortIndex(board._id, sortIndex.base);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ BlazeComponent.extendComponent({
|
|||
events() {
|
||||
return [
|
||||
{
|
||||
'submit .js-card-description'(event) {
|
||||
async 'submit .js-card-description'(event) {
|
||||
event.preventDefault();
|
||||
const description = this.currentComponent().getValue();
|
||||
this.data().setDescription(description);
|
||||
await this.data().setDescription(description);
|
||||
},
|
||||
// Pressing Ctrl+Enter should submit the form
|
||||
'keydown form textarea'(evt) {
|
||||
|
|
|
|||
|
|
@ -462,18 +462,18 @@ BlazeComponent.extendComponent({
|
|||
const currentMode = Utils.getMobileMode();
|
||||
Utils.setMobileMode(!currentMode);
|
||||
},
|
||||
'submit .js-card-description'(event) {
|
||||
async 'submit .js-card-description'(event) {
|
||||
event.preventDefault();
|
||||
const description = this.currentComponent().getValue();
|
||||
this.data().setDescription(description);
|
||||
await this.data().setDescription(description);
|
||||
},
|
||||
'submit .js-card-details-title'(event) {
|
||||
async 'submit .js-card-details-title'(event) {
|
||||
event.preventDefault();
|
||||
const title = this.currentComponent().getValue().trim();
|
||||
if (title) {
|
||||
this.data().setTitle(title);
|
||||
await this.data().setTitle(title);
|
||||
} else {
|
||||
this.data().setTitle('');
|
||||
await this.data().setTitle('');
|
||||
}
|
||||
},
|
||||
'submit .js-card-details-assigner'(event) {
|
||||
|
|
@ -500,23 +500,23 @@ BlazeComponent.extendComponent({
|
|||
this.find('button[type=submit]').click();
|
||||
}
|
||||
},
|
||||
'submit .js-card-details-sort'(event) {
|
||||
async 'submit .js-card-details-sort'(event) {
|
||||
event.preventDefault();
|
||||
const sort = parseFloat(this.currentComponent()
|
||||
.getValue()
|
||||
.trim());
|
||||
if (!Number.isNaN(sort)) {
|
||||
let card = this.data();
|
||||
card.move(card.boardId, card.swimlaneId, card.listId, sort);
|
||||
await card.move(card.boardId, card.swimlaneId, card.listId, sort);
|
||||
}
|
||||
},
|
||||
'change .js-select-card-details-lists'(event) {
|
||||
async 'change .js-select-card-details-lists'(event) {
|
||||
let card = this.data();
|
||||
const listSelect = this.$('.js-select-card-details-lists')[0];
|
||||
const listId = listSelect.options[listSelect.selectedIndex].value;
|
||||
|
||||
const minOrder = card.getMinSort(listId, card.swimlaneId);
|
||||
card.move(card.boardId, card.swimlaneId, listId, minOrder - 1);
|
||||
await card.move(card.boardId, card.swimlaneId, listId, minOrder - 1);
|
||||
},
|
||||
'click .js-go-to-linked-card'() {
|
||||
Utils.goCardId(this.data().linkedId);
|
||||
|
|
@ -554,8 +554,8 @@ BlazeComponent.extendComponent({
|
|||
Session.set('cardDetailsIsDragging', false);
|
||||
Session.set('cardDetailsIsMouseDown', false);
|
||||
},
|
||||
'click #toggleHideCheckedChecklistItems'() {
|
||||
this.data().toggleHideCheckedChecklistItems();
|
||||
async 'click #toggleHideCheckedChecklistItems'() {
|
||||
await this.data().toggleHideCheckedChecklistItems();
|
||||
},
|
||||
'click #toggleCustomFieldsGridButton'() {
|
||||
Meteor.call('toggleCustomFieldsGrid');
|
||||
|
|
@ -862,21 +862,21 @@ Template.cardDetailsActionsPopup.events({
|
|||
'click .js-convert-checklist-item-to-card': Popup.open('convertChecklistItemToCard'),
|
||||
'click .js-copy-checklist-cards': Popup.open('copyManyCards'),
|
||||
'click .js-set-card-color': Popup.open('setCardColor'),
|
||||
'click .js-move-card-to-top'(event) {
|
||||
async 'click .js-move-card-to-top'(event) {
|
||||
event.preventDefault();
|
||||
const minOrder = this.getMinSort();
|
||||
this.move(this.boardId, this.swimlaneId, this.listId, minOrder - 1);
|
||||
await this.move(this.boardId, this.swimlaneId, this.listId, minOrder - 1);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-move-card-to-bottom'(event) {
|
||||
async 'click .js-move-card-to-bottom'(event) {
|
||||
event.preventDefault();
|
||||
const maxOrder = this.getMaxSort();
|
||||
this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1);
|
||||
await this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-archive': Popup.afterConfirm('cardArchive', function () {
|
||||
'click .js-archive': Popup.afterConfirm('cardArchive', async function () {
|
||||
Popup.close();
|
||||
this.archive();
|
||||
await this.archive();
|
||||
Utils.goBoardId(this.boardId);
|
||||
}),
|
||||
'click .js-more': Popup.open('cardMore'),
|
||||
|
|
@ -1011,11 +1011,11 @@ Template.editCardAssignerForm.events({
|
|||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
async setDone(cardId, options) {
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
let sortIndex = 0;
|
||||
|
||||
|
||||
if (cardId) {
|
||||
const targetCard = ReactiveCache.getCard(cardId);
|
||||
if (targetCard) {
|
||||
|
|
@ -1030,8 +1030,8 @@ Template.editCardAssignerForm.events({
|
|||
// If no card selected, move to end
|
||||
sortIndex = card.getMaxSort(options.listId, options.swimlaneId) + 1;
|
||||
}
|
||||
|
||||
card.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
|
||||
await card.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
}
|
||||
}).register('moveCardPopup');
|
||||
|
||||
|
|
@ -1041,7 +1041,7 @@ Template.editCardAssignerForm.events({
|
|||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
async setDone(cardId, options) {
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
|
|
@ -1056,7 +1056,7 @@ Template.editCardAssignerForm.events({
|
|||
if (newCardId) {
|
||||
const newCard = ReactiveCache.getCard(newCardId);
|
||||
let sortIndex = 0;
|
||||
|
||||
|
||||
if (cardId) {
|
||||
const targetCard = ReactiveCache.getCard(cardId);
|
||||
if (targetCard) {
|
||||
|
|
@ -1071,8 +1071,8 @@ Template.editCardAssignerForm.events({
|
|||
// If no card selected, copy to end
|
||||
sortIndex = newCard.getMaxSort(options.listId, options.swimlaneId) + 1;
|
||||
}
|
||||
|
||||
newCard.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
|
||||
await newCard.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
}
|
||||
|
||||
// In case the filter is active we need to add the newly inserted card in
|
||||
|
|
@ -1090,7 +1090,7 @@ Template.editCardAssignerForm.events({
|
|||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
async setDone(cardId, options) {
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
|
|
@ -1106,7 +1106,7 @@ Template.editCardAssignerForm.events({
|
|||
sort: 0,
|
||||
});
|
||||
const newCard = ReactiveCache.getCard(_id);
|
||||
|
||||
|
||||
let sortIndex = 0;
|
||||
if (cardId) {
|
||||
const targetCard = ReactiveCache.getCard(cardId);
|
||||
|
|
@ -1121,8 +1121,8 @@ Template.editCardAssignerForm.events({
|
|||
} else {
|
||||
sortIndex = newCard.getMaxSort(options.listId, options.swimlaneId) + 1;
|
||||
}
|
||||
|
||||
newCard.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
|
||||
await newCard.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
|
||||
Filter.addException(_id);
|
||||
}
|
||||
|
|
@ -1135,7 +1135,7 @@ Template.editCardAssignerForm.events({
|
|||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
async setDone(cardId, options) {
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
|
|
@ -1151,7 +1151,7 @@ Template.editCardAssignerForm.events({
|
|||
if (newCardId) {
|
||||
const newCard = ReactiveCache.getCard(newCardId);
|
||||
let sortIndex = 0;
|
||||
|
||||
|
||||
if (cardId) {
|
||||
const targetCard = ReactiveCache.getCard(cardId);
|
||||
if (targetCard) {
|
||||
|
|
@ -1165,8 +1165,8 @@ Template.editCardAssignerForm.events({
|
|||
} else {
|
||||
sortIndex = newCard.getMaxSort(options.listId, options.swimlaneId) + 1;
|
||||
}
|
||||
|
||||
newCard.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
|
||||
await newCard.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
}
|
||||
|
||||
// In case the filter is active we need to add the newly inserted card in
|
||||
|
|
@ -1202,14 +1202,14 @@ BlazeComponent.extendComponent({
|
|||
'click .js-palette-color'() {
|
||||
this.currentColor.set(this.currentData().color);
|
||||
},
|
||||
'click .js-submit'(event) {
|
||||
async 'click .js-submit'(event) {
|
||||
event.preventDefault();
|
||||
this.currentCard.setColor(this.currentColor.get());
|
||||
await this.currentCard.setColor(this.currentColor.get());
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-remove-color'(event) {
|
||||
async 'click .js-remove-color'(event) {
|
||||
event.preventDefault();
|
||||
this.currentCard.setColor(null);
|
||||
await this.currentCard.setColor(null);
|
||||
Popup.back();
|
||||
},
|
||||
},
|
||||
|
|
@ -1240,21 +1240,21 @@ BlazeComponent.extendComponent({
|
|||
const color = colorClass ? colorClass.replace('card-details-', '') : null;
|
||||
this.currentColor.set(color);
|
||||
},
|
||||
'click .js-submit'(event) {
|
||||
async 'click .js-submit'(event) {
|
||||
event.preventDefault();
|
||||
const color = this.currentColor.get();
|
||||
// Use MultiSelection to get selected cards and set color on each
|
||||
ReactiveCache.getCards(MultiSelection.getMongoSelector()).forEach(card => {
|
||||
card.setColor(color);
|
||||
});
|
||||
for (const card of ReactiveCache.getCards(MultiSelection.getMongoSelector())) {
|
||||
await card.setColor(color);
|
||||
}
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-remove-color'(event) {
|
||||
async 'click .js-remove-color'(event) {
|
||||
event.preventDefault();
|
||||
// Use MultiSelection to get selected cards and remove color from each
|
||||
ReactiveCache.getCards(MultiSelection.getMongoSelector()).forEach(card => {
|
||||
card.setColor(null);
|
||||
});
|
||||
for (const card of ReactiveCache.getCards(MultiSelection.getMongoSelector())) {
|
||||
await card.setColor(null);
|
||||
}
|
||||
Popup.back();
|
||||
},
|
||||
},
|
||||
|
|
@ -1866,7 +1866,7 @@ BlazeComponent.extendComponent({
|
|||
// Close the card details pane by pressing escape
|
||||
EscapeActions.register(
|
||||
'detailsPane',
|
||||
() => {
|
||||
async () => {
|
||||
// if card description diverges from database due to editing
|
||||
// ask user whether changes should be applied
|
||||
if (ReactiveCache.getCurrentUser()) {
|
||||
|
|
@ -1874,7 +1874,7 @@ EscapeActions.register(
|
|||
currentDescription = document.getElementsByClassName("editor js-new-description-input").item(0)
|
||||
if (currentDescription?.value && !(currentDescription.value === Utils.getCurrentCard().getDescription())) {
|
||||
if (confirm(TAPi18n.__('rescue-card-description-dialogue'))) {
|
||||
Utils.getCurrentCard().setDescription(document.getElementsByClassName("editor js-new-description-input").item(0).value);
|
||||
await Utils.getCurrentCard().setDescription(document.getElementsByClassName("editor js-new-description-input").item(0).value);
|
||||
// Save it!
|
||||
console.log(document.getElementsByClassName("editor js-new-description-input").item(0).value);
|
||||
console.log("current description", Utils.getCurrentCard().getDescription());
|
||||
|
|
|
|||
|
|
@ -157,21 +157,21 @@ BlazeComponent.extendComponent({
|
|||
textarea.focus();
|
||||
},
|
||||
|
||||
editChecklist(event) {
|
||||
async editChecklist(event) {
|
||||
event.preventDefault();
|
||||
const textarea = this.find('textarea.js-edit-checklist-item');
|
||||
const title = textarea.value.trim();
|
||||
const checklist = this.currentData().checklist;
|
||||
checklist.setTitle(title);
|
||||
await checklist.setTitle(title);
|
||||
},
|
||||
|
||||
editChecklistItem(event) {
|
||||
async editChecklistItem(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const textarea = this.find('textarea.js-edit-checklist-item');
|
||||
const title = textarea.value.trim();
|
||||
const item = this.currentData().item;
|
||||
item.setTitle(title);
|
||||
await item.setTitle(title);
|
||||
},
|
||||
|
||||
pressKey(event) {
|
||||
|
|
@ -321,20 +321,20 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
'click .js-move-checklist': Popup.open('moveChecklist'),
|
||||
'click .js-copy-checklist': Popup.open('copyChecklist'),
|
||||
'click .js-hide-checked-checklist-items'(event) {
|
||||
async 'click .js-hide-checked-checklist-items'(event) {
|
||||
event.preventDefault();
|
||||
this.data().checklist.toggleHideCheckedChecklistItems();
|
||||
await this.data().checklist.toggleHideCheckedChecklistItems();
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-hide-all-checklist-items'(event) {
|
||||
async 'click .js-hide-all-checklist-items'(event) {
|
||||
event.preventDefault();
|
||||
this.data().checklist.toggleHideAllChecklistItems();
|
||||
await this.data().checklist.toggleHideAllChecklistItems();
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-toggle-show-checklist-at-minicard'(event) {
|
||||
async 'click .js-toggle-show-checklist-at-minicard'(event) {
|
||||
event.preventDefault();
|
||||
const checklist = this.data().checklist;
|
||||
checklist.toggleShowChecklistAtMinicard();
|
||||
await checklist.toggleShowChecklistAtMinicard();
|
||||
Popup.back();
|
||||
},
|
||||
}
|
||||
|
|
@ -365,11 +365,11 @@ Template.checklistItemDetail.helpers({
|
|||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
toggleItem() {
|
||||
async toggleItem() {
|
||||
const checklist = this.currentData().checklist;
|
||||
const item = this.currentData().item;
|
||||
if (checklist && item && item._id) {
|
||||
item.toggleItem();
|
||||
await item.toggleItem();
|
||||
}
|
||||
},
|
||||
events() {
|
||||
|
|
|
|||
|
|
@ -91,10 +91,10 @@ BlazeComponent.extendComponent({
|
|||
}
|
||||
},
|
||||
|
||||
toggleChecklistItem() {
|
||||
async toggleChecklistItem() {
|
||||
const item = this.currentData();
|
||||
if (item && item._id) {
|
||||
item.toggleItem();
|
||||
await item.toggleItem();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -319,15 +319,15 @@ Template.cardDetailsActionsPopup.events({
|
|||
this.move(this.boardId, this.swimlaneId, this.listId, minOrder - 1);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-move-card-to-bottom'(event) {
|
||||
async 'click .js-move-card-to-bottom'(event) {
|
||||
event.preventDefault();
|
||||
const maxOrder = this.getMaxSort();
|
||||
this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1);
|
||||
await this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-archive': Popup.afterConfirm('cardArchive', function () {
|
||||
'click .js-archive': Popup.afterConfirm('cardArchive', async function () {
|
||||
Popup.close();
|
||||
this.archive();
|
||||
await this.archive();
|
||||
Utils.goBoardId(this.boardId);
|
||||
}),
|
||||
'click .js-toggle-watch-card'() {
|
||||
|
|
|
|||
|
|
@ -62,10 +62,10 @@ BlazeComponent.extendComponent({
|
|||
textarea.focus();
|
||||
},
|
||||
|
||||
deleteSubtask() {
|
||||
async deleteSubtask() {
|
||||
const subtask = this.currentData().subtask;
|
||||
if (subtask && subtask._id) {
|
||||
subtask.archive();
|
||||
await subtask.archive();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -73,12 +73,12 @@ BlazeComponent.extendComponent({
|
|||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
|
||||
editSubtask(event) {
|
||||
async editSubtask(event) {
|
||||
event.preventDefault();
|
||||
const textarea = this.find('textarea.js-edit-subtask-item');
|
||||
const title = textarea.value.trim();
|
||||
const subtask = this.currentData().subtask;
|
||||
subtask.setTitle(title);
|
||||
await subtask.setTitle(title);
|
||||
},
|
||||
|
||||
pressKey(event) {
|
||||
|
|
@ -105,10 +105,10 @@ BlazeComponent.extendComponent({
|
|||
}).register('subtasks');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
toggleItem() {
|
||||
async toggleItem() {
|
||||
const item = this.currentData().item;
|
||||
if (item && item._id) {
|
||||
item.toggleItem();
|
||||
await item.toggleItem();
|
||||
}
|
||||
},
|
||||
events() {
|
||||
|
|
@ -138,11 +138,11 @@ BlazeComponent.extendComponent({
|
|||
});
|
||||
}
|
||||
},
|
||||
'click .js-delete-subtask' : Popup.afterConfirm('subtaskDelete', function () {
|
||||
'click .js-delete-subtask' : Popup.afterConfirm('subtaskDelete', async function () {
|
||||
Popup.back(2);
|
||||
const subtask = this.subtask;
|
||||
if (subtask && subtask._id) {
|
||||
subtask.archive();
|
||||
await subtask.archive();
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ BlazeComponent.extendComponent({
|
|||
isBoardAdmin() {
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
starred(check = undefined) {
|
||||
async starred(check = undefined) {
|
||||
const list = Template.currentData();
|
||||
const status = list.isStarred();
|
||||
if (check === undefined) {
|
||||
// just check
|
||||
return status;
|
||||
} else {
|
||||
list.star(!status);
|
||||
await list.star(!status);
|
||||
return !status;
|
||||
}
|
||||
},
|
||||
|
|
@ -45,14 +45,14 @@ BlazeComponent.extendComponent({
|
|||
return next;
|
||||
}
|
||||
},
|
||||
editTitle(event) {
|
||||
async editTitle(event) {
|
||||
event.preventDefault();
|
||||
const newTitle = this.childComponents('inlinedForm')[0]
|
||||
.getValue()
|
||||
.trim();
|
||||
const list = this.currentData();
|
||||
if (newTitle) {
|
||||
list.rename(newTitle.trim());
|
||||
await list.rename(newTitle.trim());
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -226,9 +226,9 @@ Template.listActionPopup.events({
|
|||
if (!err && ret) Popup.back();
|
||||
});
|
||||
},
|
||||
'click .js-close-list'(event) {
|
||||
async 'click .js-close-list'(event) {
|
||||
event.preventDefault();
|
||||
this.archive();
|
||||
await this.archive();
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-set-wip-limit': Popup.open('setWipLimit'),
|
||||
|
|
@ -255,26 +255,26 @@ BlazeComponent.extendComponent({
|
|||
}
|
||||
},
|
||||
|
||||
enableSoftLimit() {
|
||||
async enableSoftLimit() {
|
||||
const list = Template.currentData();
|
||||
|
||||
if (
|
||||
list.getWipLimit('soft') &&
|
||||
list.getWipLimit('value') < list.cards().length
|
||||
) {
|
||||
list.setWipLimit(list.cards().length);
|
||||
await list.setWipLimit(list.cards().length);
|
||||
}
|
||||
Meteor.call('enableSoftLimit', Template.currentData()._id);
|
||||
},
|
||||
|
||||
enableWipLimit() {
|
||||
async enableWipLimit() {
|
||||
const list = Template.currentData();
|
||||
// Prevent user from using previously stored wipLimit.value if it is less than the current number of cards in the list
|
||||
if (
|
||||
!list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') < list.cards().length
|
||||
) {
|
||||
list.setWipLimit(list.cards().length);
|
||||
await list.setWipLimit(list.cards().length);
|
||||
}
|
||||
Meteor.call('enableWipLimit', list._id);
|
||||
},
|
||||
|
|
@ -368,12 +368,12 @@ BlazeComponent.extendComponent({
|
|||
'click .js-palette-color'() {
|
||||
this.currentColor.set(this.currentData().color);
|
||||
},
|
||||
'click .js-submit'() {
|
||||
this.currentList.setColor(this.currentColor.get());
|
||||
async 'click .js-submit'() {
|
||||
await this.currentList.setColor(this.currentColor.get());
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-remove-color'() {
|
||||
this.currentList.setColor(null);
|
||||
async 'click .js-remove-color'() {
|
||||
await this.currentList.setColor(null);
|
||||
Popup.close();
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -15,12 +15,12 @@ Template.bookmarks.helpers({
|
|||
});
|
||||
|
||||
Template.bookmarks.events({
|
||||
'click .js-toggle-star'(e) {
|
||||
async 'click .js-toggle-star'(e) {
|
||||
e.preventDefault();
|
||||
const boardId = this._id;
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (user && boardId) {
|
||||
user.toggleBoardStar(boardId);
|
||||
await user.toggleBoardStar(boardId);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
@ -42,12 +42,12 @@ Template.bookmarksPopup.helpers({
|
|||
});
|
||||
|
||||
Template.bookmarksPopup.events({
|
||||
'click .js-toggle-star'(e) {
|
||||
async 'click .js-toggle-star'(e) {
|
||||
e.preventDefault();
|
||||
const boardId = this._id;
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (user && boardId) {
|
||||
user.toggleBoardStar(boardId);
|
||||
await user.toggleBoardStar(boardId);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -327,9 +327,9 @@ Template.boardMenuPopup.events({
|
|||
// You could add a toast notification here if available
|
||||
}
|
||||
}),
|
||||
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
|
||||
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', async function() {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.archive();
|
||||
await currentBoard.archive();
|
||||
// XXX We should have some kind of notification on top of the page to
|
||||
// confirm that the board was successfully archived.
|
||||
FlowRouter.go('home');
|
||||
|
|
@ -382,7 +382,7 @@ Template.memberPopup.events({
|
|||
Popup.back();
|
||||
},
|
||||
'click .js-change-role': Popup.open('changePermissions'),
|
||||
'click .js-remove-member': Popup.afterConfirm('removeMember', function() {
|
||||
'click .js-remove-member': Popup.afterConfirm('removeMember', async function() {
|
||||
// This works from removing member from board, card members and assignees.
|
||||
const boardId = Session.get('currentBoard');
|
||||
const memberId = this.userId;
|
||||
|
|
@ -392,7 +392,7 @@ Template.memberPopup.events({
|
|||
ReactiveCache.getCards({ boardId, assignees: memberId }).forEach(card => {
|
||||
card.unassignAssignee(memberId);
|
||||
});
|
||||
ReactiveCache.getBoard(boardId).removeMember(memberId);
|
||||
await ReactiveCache.getBoard(boardId).removeMember(memberId);
|
||||
Popup.back();
|
||||
}),
|
||||
'click .js-leave-member': Popup.afterConfirm('leaveBoard', () => {
|
||||
|
|
@ -774,10 +774,10 @@ BlazeComponent.extendComponent({
|
|||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-select-background'(evt) {
|
||||
async 'click .js-select-background'(evt) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const newColor = this.currentData().toString();
|
||||
currentBoard.setColor(newColor);
|
||||
await currentBoard.setColor(newColor);
|
||||
evt.preventDefault();
|
||||
},
|
||||
},
|
||||
|
|
@ -789,10 +789,10 @@ BlazeComponent.extendComponent({
|
|||
events() {
|
||||
return [
|
||||
{
|
||||
submit(event) {
|
||||
async submit(event) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const backgroundImageURL = this.find('.js-board-background-image-url').value.trim();
|
||||
currentBoard.setBackgroundImageURL(backgroundImageURL);
|
||||
await currentBoard.setBackgroundImageURL(backgroundImageURL);
|
||||
Utils.setBackgroundImage();
|
||||
Popup.back();
|
||||
event.preventDefault();
|
||||
|
|
@ -1945,7 +1945,7 @@ Template.removeBoardTeamPopup.helpers({
|
|||
});
|
||||
|
||||
Template.changePermissionsPopup.events({
|
||||
'click .js-set-admin, click .js-set-normal, click .js-set-normal-assigned-only, click .js-set-no-comments, click .js-set-comment-only, click .js-set-comment-assigned-only, click .js-set-read-only, click .js-set-read-assigned-only, click .js-set-worker'(
|
||||
async 'click .js-set-admin, click .js-set-normal, click .js-set-normal-assigned-only, click .js-set-no-comments, click .js-set-comment-only, click .js-set-comment-assigned-only, click .js-set-read-only, click .js-set-read-assigned-only, click .js-set-worker'(
|
||||
event,
|
||||
) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
|
|
@ -1964,7 +1964,7 @@ Template.changePermissionsPopup.events({
|
|||
const isReadAssignedOnly = $(event.currentTarget).hasClass('js-set-read-assigned-only');
|
||||
const isNoComments = $(event.currentTarget).hasClass('js-set-no-comments');
|
||||
const isWorker = $(event.currentTarget).hasClass('js-set-worker');
|
||||
currentBoard.setMemberPermission(
|
||||
await currentBoard.setMemberPermission(
|
||||
memberId,
|
||||
isAdmin,
|
||||
isNoComments,
|
||||
|
|
|
|||
|
|
@ -81,76 +81,76 @@ BlazeComponent.extendComponent({
|
|||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-restore-card'() {
|
||||
async 'click .js-restore-card'() {
|
||||
const card = this.currentData();
|
||||
if (card.canBeRestored()) {
|
||||
card.restore();
|
||||
await card.restore();
|
||||
}
|
||||
},
|
||||
'click .js-restore-all-cards'() {
|
||||
this.archivedCards().forEach(card => {
|
||||
async 'click .js-restore-all-cards'() {
|
||||
for (const card of this.archivedCards()) {
|
||||
if (card.canBeRestored()) {
|
||||
card.restore();
|
||||
await card.restore();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
'click .js-delete-card': Popup.afterConfirm('cardDelete', function() {
|
||||
'click .js-delete-card': Popup.afterConfirm('cardDelete', async function() {
|
||||
const cardId = this._id;
|
||||
Cards.remove(cardId);
|
||||
await Cards.removeAsync(cardId);
|
||||
Popup.back();
|
||||
}),
|
||||
'click .js-delete-all-cards': Popup.afterConfirm('cardDelete', () => {
|
||||
this.archivedCards().forEach(card => {
|
||||
Cards.remove(card._id);
|
||||
});
|
||||
'click .js-delete-all-cards': Popup.afterConfirm('cardDelete', async () => {
|
||||
for (const card of this.archivedCards()) {
|
||||
await Cards.removeAsync(card._id);
|
||||
}
|
||||
Popup.back();
|
||||
}),
|
||||
|
||||
'click .js-restore-list'() {
|
||||
async 'click .js-restore-list'() {
|
||||
const list = this.currentData();
|
||||
list.restore();
|
||||
await list.restore();
|
||||
},
|
||||
'click .js-restore-all-lists'() {
|
||||
this.archivedLists().forEach(list => {
|
||||
list.restore();
|
||||
});
|
||||
async 'click .js-restore-all-lists'() {
|
||||
for (const list of this.archivedLists()) {
|
||||
await list.restore();
|
||||
}
|
||||
},
|
||||
|
||||
'click .js-delete-list': Popup.afterConfirm('listDelete', function() {
|
||||
this.remove();
|
||||
'click .js-delete-list': Popup.afterConfirm('listDelete', async function() {
|
||||
await this.remove();
|
||||
Popup.back();
|
||||
}),
|
||||
'click .js-delete-all-lists': Popup.afterConfirm('listDelete', () => {
|
||||
this.archivedLists().forEach(list => {
|
||||
list.remove();
|
||||
});
|
||||
'click .js-delete-all-lists': Popup.afterConfirm('listDelete', async () => {
|
||||
for (const list of this.archivedLists()) {
|
||||
await list.remove();
|
||||
}
|
||||
Popup.back();
|
||||
}),
|
||||
|
||||
'click .js-restore-swimlane'() {
|
||||
async 'click .js-restore-swimlane'() {
|
||||
const swimlane = this.currentData();
|
||||
swimlane.restore();
|
||||
await swimlane.restore();
|
||||
},
|
||||
'click .js-restore-all-swimlanes'() {
|
||||
this.archivedSwimlanes().forEach(swimlane => {
|
||||
swimlane.restore();
|
||||
});
|
||||
async 'click .js-restore-all-swimlanes'() {
|
||||
for (const swimlane of this.archivedSwimlanes()) {
|
||||
await swimlane.restore();
|
||||
}
|
||||
},
|
||||
|
||||
'click .js-delete-swimlane': Popup.afterConfirm(
|
||||
'swimlaneDelete',
|
||||
function() {
|
||||
this.remove();
|
||||
async function() {
|
||||
await this.remove();
|
||||
Popup.back();
|
||||
},
|
||||
),
|
||||
'click .js-delete-all-swimlanes': Popup.afterConfirm(
|
||||
'swimlaneDelete',
|
||||
() => {
|
||||
this.archivedSwimlanes().forEach(swimlane => {
|
||||
swimlane.remove();
|
||||
});
|
||||
async () => {
|
||||
for (const swimlane of this.archivedSwimlanes()) {
|
||||
await swimlane.remove();
|
||||
}
|
||||
Popup.back();
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ Meteor.startup(() => {
|
|||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
editTitle(event) {
|
||||
async editTitle(event) {
|
||||
event.preventDefault();
|
||||
const newTitle = this.childComponents('inlinedForm')[0]
|
||||
.getValue()
|
||||
.trim();
|
||||
const swimlane = this.currentData();
|
||||
if (newTitle) {
|
||||
swimlane.rename(newTitle.trim());
|
||||
await swimlane.rename(newTitle.trim());
|
||||
}
|
||||
},
|
||||
collapsed(check = undefined) {
|
||||
|
|
@ -106,9 +106,9 @@ Template.editSwimlaneTitleForm.helpers({
|
|||
Template.swimlaneActionPopup.events({
|
||||
'click .js-set-swimlane-color': Popup.open('setSwimlaneColor'),
|
||||
'click .js-set-swimlane-height': Popup.open('setSwimlaneHeight'),
|
||||
'click .js-close-swimlane'(event) {
|
||||
async 'click .js-close-swimlane'(event) {
|
||||
event.preventDefault();
|
||||
this.archive();
|
||||
await this.archive();
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-move-swimlane': Popup.open('moveSwimlane'),
|
||||
|
|
@ -183,20 +183,20 @@ BlazeComponent.extendComponent({
|
|||
events() {
|
||||
return [
|
||||
{
|
||||
'submit form'(event) {
|
||||
async 'submit form'(event) {
|
||||
event.preventDefault();
|
||||
this.currentSwimlane.setColor(this.currentColor.get());
|
||||
await this.currentSwimlane.setColor(this.currentColor.get());
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-palette-color'() {
|
||||
this.currentColor.set(this.currentData().color);
|
||||
},
|
||||
'click .js-submit'() {
|
||||
this.currentSwimlane.setColor(this.currentColor.get());
|
||||
async 'click .js-submit'() {
|
||||
await this.currentSwimlane.setColor(this.currentColor.get());
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-remove-color'() {
|
||||
this.currentSwimlane.setColor(null);
|
||||
async 'click .js-remove-color'() {
|
||||
await this.currentSwimlane.setColor(null);
|
||||
Popup.back();
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ hotkeys('space', (event) => {
|
|||
}
|
||||
});
|
||||
|
||||
const archiveCard = (event) => {
|
||||
const archiveCard = async (event) => {
|
||||
event.preventDefault();
|
||||
const cardId = getSelectedCardId();
|
||||
if (!cardId) {
|
||||
|
|
@ -282,7 +282,7 @@ const archiveCard = (event) => {
|
|||
|
||||
if (Utils.canModifyBoard()) {
|
||||
const card = Cards.findOne(cardId);
|
||||
card.archive();
|
||||
await card.archive();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@ import { ReactiveCache } from '/imports/reactiveCache';
|
|||
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
|
||||
|
||||
Utils = {
|
||||
setBackgroundImage(url) {
|
||||
async setBackgroundImage(url) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (currentBoard.backgroundImageURL !== undefined) {
|
||||
$(".board-wrapper").css({"background":"url(" + currentBoard.backgroundImageURL + ")","background-size":"cover"});
|
||||
$(".swimlane,.swimlane .list,.swimlane .list .list-body,.swimlane .list:first-child .list-body").css({"background-color":"transparent"});
|
||||
$(".minicard").css({"opacity": "0.9"});
|
||||
} else if (currentBoard["background-color"]) {
|
||||
currentBoard.setColor(currentBoard["background-color"]);
|
||||
await currentBoard.setColor(currentBoard["background-color"]);
|
||||
}
|
||||
},
|
||||
/** returns the current board id
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ sudo npm install -g n
|
|||
export N_NODE_MIRROR=https://github.com/wekan/node-v14-esm/releases/download
|
||||
sudo -E n 14.21.4
|
||||
sudo npm -g install @mapbox/node-pre-gyp
|
||||
sudo npm -g install meteor@2.14 --unsafe-perm
|
||||
sudo npm -g install meteor@2.16 --unsafe-perm
|
||||
export PATH=$PATH:$HOME/.meteor
|
||||
meteor npm install production
|
||||
meteor build .build --directory --platforms=web.browser
|
||||
|
|
|
|||
259
models/boards.js
259
models/boards.js
|
|
@ -1431,93 +1431,80 @@ Boards.helpers({
|
|||
isTemplatesBoard() {
|
||||
return this.type === 'template-container';
|
||||
},
|
||||
});
|
||||
|
||||
Boards.mutations({
|
||||
archive() {
|
||||
return { $set: { archived: true, archivedAt: new Date() } };
|
||||
async archive() {
|
||||
return await Boards.updateAsync(this._id, { $set: { archived: true, archivedAt: new Date() } });
|
||||
},
|
||||
|
||||
restore() {
|
||||
return { $set: { archived: false } };
|
||||
async restore() {
|
||||
return await Boards.updateAsync(this._id, { $set: { archived: false } });
|
||||
},
|
||||
|
||||
rename(title) {
|
||||
return { $set: { title } };
|
||||
async rename(title) {
|
||||
return await Boards.updateAsync(this._id, { $set: { title } });
|
||||
},
|
||||
|
||||
setDescription(description) {
|
||||
return { $set: { description } };
|
||||
async setDescription(description) {
|
||||
return await Boards.updateAsync(this._id, { $set: { description } });
|
||||
},
|
||||
|
||||
setColor(color) {
|
||||
return { $set: { color } };
|
||||
async setColor(color) {
|
||||
return await Boards.updateAsync(this._id, { $set: { color } });
|
||||
},
|
||||
|
||||
setBackgroundImageURL(backgroundImageURL) {
|
||||
async setBackgroundImageURL(backgroundImageURL) {
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if(currentUser.isBoardAdmin()) {
|
||||
return { $set: { backgroundImageURL } };
|
||||
} else if (currentUser.isAdmin()) {
|
||||
return { $set: { backgroundImageURL } };
|
||||
} else {
|
||||
return false;
|
||||
if (currentUser.isBoardAdmin() || currentUser.isAdmin()) {
|
||||
return await Boards.updateAsync(this._id, { $set: { backgroundImageURL } });
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
setVisibility(visibility) {
|
||||
return { $set: { permission: visibility } };
|
||||
async setVisibility(visibility) {
|
||||
return await Boards.updateAsync(this._id, { $set: { permission: visibility } });
|
||||
},
|
||||
|
||||
addLabel(name, color) {
|
||||
// If label with the same name and color already exists we don't want to
|
||||
// create another one because they would be indistinguishable in the UI
|
||||
// (they would still have different `_id` but that is not exposed to the
|
||||
// user).
|
||||
async addLabel(name, color) {
|
||||
if (!this.getLabel(name, color)) {
|
||||
const _id = Random.id(6);
|
||||
return { $push: { labels: { _id, name, color } } };
|
||||
return await Boards.updateAsync(this._id, { $push: { labels: { _id, name, color } } });
|
||||
}
|
||||
return {};
|
||||
return null;
|
||||
},
|
||||
|
||||
editLabel(labelId, name, color) {
|
||||
async editLabel(labelId, name, color) {
|
||||
if (!this.getLabel(name, color)) {
|
||||
const labelIndex = this.labelIndex(labelId);
|
||||
return {
|
||||
return await Boards.updateAsync(this._id, {
|
||||
$set: {
|
||||
[`labels.${labelIndex}.name`]: name,
|
||||
[`labels.${labelIndex}.color`]: color,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
return {};
|
||||
return null;
|
||||
},
|
||||
|
||||
removeLabel(labelId) {
|
||||
return { $pull: { labels: { _id: labelId } } };
|
||||
async removeLabel(labelId) {
|
||||
return await Boards.updateAsync(this._id, { $pull: { labels: { _id: labelId } } });
|
||||
},
|
||||
|
||||
changeOwnership(fromId, toId) {
|
||||
async changeOwnership(fromId, toId) {
|
||||
const memberIndex = this.memberIndex(fromId);
|
||||
return {
|
||||
$set: {
|
||||
[`members.${memberIndex}.userId`]: toId,
|
||||
},
|
||||
};
|
||||
return await Boards.updateAsync(this._id, {
|
||||
$set: { [`members.${memberIndex}.userId`]: toId },
|
||||
});
|
||||
},
|
||||
|
||||
addMember(memberId) {
|
||||
async addMember(memberId) {
|
||||
const memberIndex = this.memberIndex(memberId);
|
||||
if (memberIndex >= 0) {
|
||||
return {
|
||||
$set: {
|
||||
[`members.${memberIndex}.isActive`]: true,
|
||||
},
|
||||
};
|
||||
return await Boards.updateAsync(this._id, {
|
||||
$set: { [`members.${memberIndex}.isActive`]: true },
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
return await Boards.updateAsync(this._id, {
|
||||
$push: {
|
||||
members: {
|
||||
userId: memberId,
|
||||
|
|
@ -1532,32 +1519,28 @@ Boards.mutations({
|
|||
isReadAssignedOnly: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
removeMember(memberId) {
|
||||
async removeMember(memberId) {
|
||||
const memberIndex = this.memberIndex(memberId);
|
||||
|
||||
// we do not allow the only one admin to be removed
|
||||
const allowRemove =
|
||||
!this.members[memberIndex].isAdmin || this.activeAdmins().length > 1;
|
||||
if (!allowRemove) {
|
||||
return {
|
||||
$set: {
|
||||
[`members.${memberIndex}.isActive`]: true,
|
||||
},
|
||||
};
|
||||
return await Boards.updateAsync(this._id, {
|
||||
$set: { [`members.${memberIndex}.isActive`]: true },
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
return await Boards.updateAsync(this._id, {
|
||||
$set: {
|
||||
[`members.${memberIndex}.isActive`]: false,
|
||||
[`members.${memberIndex}.isAdmin`]: false,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
setMemberPermission(
|
||||
async setMemberPermission(
|
||||
memberId,
|
||||
isAdmin,
|
||||
isNoComments,
|
||||
|
|
@ -1570,12 +1553,11 @@ Boards.mutations({
|
|||
currentUserId = Meteor.userId(),
|
||||
) {
|
||||
const memberIndex = this.memberIndex(memberId);
|
||||
// do not allow change permission of self
|
||||
if (memberId === currentUserId) {
|
||||
isAdmin = this.members[memberIndex].isAdmin;
|
||||
}
|
||||
|
||||
return {
|
||||
return await Boards.updateAsync(this._id, {
|
||||
$set: {
|
||||
[`members.${memberIndex}.isAdmin`]: isAdmin,
|
||||
[`members.${memberIndex}.isNoComments`]: isNoComments,
|
||||
|
|
@ -1586,144 +1568,143 @@ Boards.mutations({
|
|||
[`members.${memberIndex}.isReadOnly`]: isReadOnly,
|
||||
[`members.${memberIndex}.isReadAssignedOnly`]: isReadAssignedOnly,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
setAllowsSubtasks(allowsSubtasks) {
|
||||
return { $set: { allowsSubtasks } };
|
||||
async setAllowsSubtasks(allowsSubtasks) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsSubtasks } });
|
||||
},
|
||||
|
||||
setAllowsCreator(allowsCreator) {
|
||||
return { $set: { allowsCreator } };
|
||||
async setAllowsCreator(allowsCreator) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsCreator } });
|
||||
},
|
||||
|
||||
setAllowsCreatorOnMinicard(allowsCreatorOnMinicard) {
|
||||
return { $set: { allowsCreatorOnMinicard } };
|
||||
async setAllowsCreatorOnMinicard(allowsCreatorOnMinicard) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsCreatorOnMinicard } });
|
||||
},
|
||||
|
||||
setAllowsMembers(allowsMembers) {
|
||||
return { $set: { allowsMembers } };
|
||||
async setAllowsMembers(allowsMembers) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsMembers } });
|
||||
},
|
||||
|
||||
setAllowsChecklists(allowsChecklists) {
|
||||
return { $set: { allowsChecklists } };
|
||||
async setAllowsChecklists(allowsChecklists) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsChecklists } });
|
||||
},
|
||||
|
||||
setAllowsAssignee(allowsAssignee) {
|
||||
return { $set: { allowsAssignee } };
|
||||
async setAllowsAssignee(allowsAssignee) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsAssignee } });
|
||||
},
|
||||
|
||||
setAllowsAssignedBy(allowsAssignedBy) {
|
||||
return { $set: { allowsAssignedBy } };
|
||||
async setAllowsAssignedBy(allowsAssignedBy) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsAssignedBy } });
|
||||
},
|
||||
|
||||
setAllowsShowListsOnMinicard(allowsShowListsOnMinicard) {
|
||||
return { $set: { allowsShowListsOnMinicard } };
|
||||
async setAllowsShowListsOnMinicard(allowsShowListsOnMinicard) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsShowListsOnMinicard } });
|
||||
},
|
||||
|
||||
setAllowsChecklistAtMinicard(allowsChecklistAtMinicard) {
|
||||
return { $set: { allowsChecklistAtMinicard } };
|
||||
async setAllowsChecklistAtMinicard(allowsChecklistAtMinicard) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsChecklistAtMinicard } });
|
||||
},
|
||||
|
||||
setAllowsRequestedBy(allowsRequestedBy) {
|
||||
return { $set: { allowsRequestedBy } };
|
||||
async setAllowsRequestedBy(allowsRequestedBy) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsRequestedBy } });
|
||||
},
|
||||
|
||||
setAllowsCardSortingByNumber(allowsCardSortingByNumber) {
|
||||
return { $set: { allowsCardSortingByNumber } };
|
||||
async setAllowsCardSortingByNumber(allowsCardSortingByNumber) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsCardSortingByNumber } });
|
||||
},
|
||||
|
||||
setAllowsShowLists(allowsShowLists) {
|
||||
return { $set: { allowsShowLists } };
|
||||
async setAllowsShowLists(allowsShowLists) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsShowLists } });
|
||||
},
|
||||
|
||||
|
||||
setAllowsAttachments(allowsAttachments) {
|
||||
return { $set: { allowsAttachments } };
|
||||
async setAllowsAttachments(allowsAttachments) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsAttachments } });
|
||||
},
|
||||
|
||||
setAllowsLabels(allowsLabels) {
|
||||
return { $set: { allowsLabels } };
|
||||
async setAllowsLabels(allowsLabels) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsLabels } });
|
||||
},
|
||||
|
||||
setAllowsComments(allowsComments) {
|
||||
return { $set: { allowsComments } };
|
||||
async setAllowsComments(allowsComments) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsComments } });
|
||||
},
|
||||
|
||||
setAllowsDescriptionTitle(allowsDescriptionTitle) {
|
||||
return { $set: { allowsDescriptionTitle } };
|
||||
async setAllowsDescriptionTitle(allowsDescriptionTitle) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsDescriptionTitle } });
|
||||
},
|
||||
|
||||
setAllowsCardNumber(allowsCardNumber) {
|
||||
return { $set: { allowsCardNumber } };
|
||||
async setAllowsCardNumber(allowsCardNumber) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsCardNumber } });
|
||||
},
|
||||
|
||||
setAllowsDescriptionText(allowsDescriptionText) {
|
||||
return { $set: { allowsDescriptionText } };
|
||||
async setAllowsDescriptionText(allowsDescriptionText) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsDescriptionText } });
|
||||
},
|
||||
|
||||
setallowsDescriptionTextOnMinicard(allowsDescriptionTextOnMinicard) {
|
||||
return { $set: { allowsDescriptionTextOnMinicard } };
|
||||
async setallowsDescriptionTextOnMinicard(allowsDescriptionTextOnMinicard) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsDescriptionTextOnMinicard } });
|
||||
},
|
||||
|
||||
setallowsCoverAttachmentOnMinicard(allowsCoverAttachmentOnMinicard) {
|
||||
return { $set: { allowsCoverAttachmentOnMinicard } };
|
||||
async setallowsCoverAttachmentOnMinicard(allowsCoverAttachmentOnMinicard) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsCoverAttachmentOnMinicard } });
|
||||
},
|
||||
|
||||
setallowsBadgeAttachmentOnMinicard(allowsBadgeAttachmentOnMinicard) {
|
||||
return { $set: { allowsBadgeAttachmentOnMinicard } };
|
||||
async setallowsBadgeAttachmentOnMinicard(allowsBadgeAttachmentOnMinicard) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsBadgeAttachmentOnMinicard } });
|
||||
},
|
||||
|
||||
setallowsCardSortingByNumberOnMinicard(allowsCardSortingByNumberOnMinicard) {
|
||||
return { $set: { allowsCardSortingByNumberOnMinicard } };
|
||||
async setallowsCardSortingByNumberOnMinicard(allowsCardSortingByNumberOnMinicard) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsCardSortingByNumberOnMinicard } });
|
||||
},
|
||||
|
||||
setAllowsActivities(allowsActivities) {
|
||||
return { $set: { allowsActivities } };
|
||||
async setAllowsActivities(allowsActivities) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsActivities } });
|
||||
},
|
||||
|
||||
setAllowsReceivedDate(allowsReceivedDate) {
|
||||
return { $set: { allowsReceivedDate } };
|
||||
async setAllowsReceivedDate(allowsReceivedDate) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsReceivedDate } });
|
||||
},
|
||||
|
||||
setAllowsCardCounterList(allowsCardCounterList) {
|
||||
return { $set: { allowsCardCounterList } };
|
||||
async setAllowsCardCounterList(allowsCardCounterList) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsCardCounterList } });
|
||||
},
|
||||
|
||||
setAllowsBoardMemberList(allowsBoardMemberList) {
|
||||
return { $set: { allowsBoardMemberList } };
|
||||
async setAllowsBoardMemberList(allowsBoardMemberList) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsBoardMemberList } });
|
||||
},
|
||||
|
||||
setAllowsStartDate(allowsStartDate) {
|
||||
return { $set: { allowsStartDate } };
|
||||
async setAllowsStartDate(allowsStartDate) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsStartDate } });
|
||||
},
|
||||
|
||||
setAllowsEndDate(allowsEndDate) {
|
||||
return { $set: { allowsEndDate } };
|
||||
async setAllowsEndDate(allowsEndDate) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsEndDate } });
|
||||
},
|
||||
|
||||
setAllowsDueDate(allowsDueDate) {
|
||||
return { $set: { allowsDueDate } };
|
||||
async setAllowsDueDate(allowsDueDate) {
|
||||
return await Boards.updateAsync(this._id, { $set: { allowsDueDate } });
|
||||
},
|
||||
|
||||
setSubtasksDefaultBoardId(subtasksDefaultBoardId) {
|
||||
return { $set: { subtasksDefaultBoardId } };
|
||||
async setSubtasksDefaultBoardId(subtasksDefaultBoardId) {
|
||||
return await Boards.updateAsync(this._id, { $set: { subtasksDefaultBoardId } });
|
||||
},
|
||||
|
||||
setSubtasksDefaultListId(subtasksDefaultListId) {
|
||||
return { $set: { subtasksDefaultListId } };
|
||||
async setSubtasksDefaultListId(subtasksDefaultListId) {
|
||||
return await Boards.updateAsync(this._id, { $set: { subtasksDefaultListId } });
|
||||
},
|
||||
|
||||
setPresentParentTask(presentParentTask) {
|
||||
return { $set: { presentParentTask } };
|
||||
async setPresentParentTask(presentParentTask) {
|
||||
return await Boards.updateAsync(this._id, { $set: { presentParentTask } });
|
||||
},
|
||||
|
||||
move(sortIndex) {
|
||||
return { $set: { sort: sortIndex } };
|
||||
async move(sortIndex) {
|
||||
return await Boards.updateAsync(this._id, { $set: { sort: sortIndex } });
|
||||
},
|
||||
|
||||
toggleShowActivities() {
|
||||
return { $set: { showActivities: !this.showActivities } };
|
||||
async toggleShowActivities() {
|
||||
return await Boards.updateAsync(this._id, { $set: { showActivities: !this.showActivities } });
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -1909,14 +1890,14 @@ if (Meteor.isServer) {
|
|||
check(boardId, String);
|
||||
return ReactiveCache.getBoard(boardId, {}, { backgroundImageUrl: 1 });
|
||||
},
|
||||
quitBoard(boardId) {
|
||||
async quitBoard(boardId) {
|
||||
check(boardId, String);
|
||||
const board = ReactiveCache.getBoard(boardId);
|
||||
if (board) {
|
||||
const userId = Meteor.userId();
|
||||
const index = board.memberIndex(userId);
|
||||
if (index >= 0) {
|
||||
board.removeMember(userId);
|
||||
await board.removeMember(userId);
|
||||
return true;
|
||||
} else throw new Meteor.Error('error-board-notAMember');
|
||||
} else throw new Meteor.Error('error-board-doesNotExist');
|
||||
|
|
@ -1993,14 +1974,14 @@ if (Meteor.isServer) {
|
|||
});
|
||||
|
||||
Meteor.methods({
|
||||
archiveBoard(boardId) {
|
||||
async archiveBoard(boardId) {
|
||||
check(boardId, String);
|
||||
const board = ReactiveCache.getBoard(boardId);
|
||||
if (board) {
|
||||
const userId = Meteor.userId();
|
||||
const index = board.memberIndex(userId);
|
||||
if (index >= 0) {
|
||||
board.archive();
|
||||
await board.archive();
|
||||
return true;
|
||||
} else throw new Meteor.Error('error-board-notAMember');
|
||||
} else throw new Meteor.Error('error-board-doesNotExist');
|
||||
|
|
@ -2159,7 +2140,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
if (modifier.$set) {
|
||||
const boardId = doc._id;
|
||||
foreachRemovedMember(doc, modifier.$set, memberId => {
|
||||
foreachRemovedMember(doc, modifier.$set, async memberId => {
|
||||
Cards.update(
|
||||
{ boardId },
|
||||
{
|
||||
|
|
@ -2182,7 +2163,7 @@ if (Meteor.isServer) {
|
|||
);
|
||||
|
||||
const board = Boards._transform(doc);
|
||||
board.setWatcher(memberId, false);
|
||||
await board.setWatcher(memberId, false);
|
||||
|
||||
// Remove board from users starred list
|
||||
if (!board.isPublic()) {
|
||||
|
|
@ -2589,7 +2570,7 @@ JsonRoutes.add('POST', '/api/boards/:boardId/copy', function(req, res) {
|
|||
* @param {boolean} isReadOnly ReadOnly capability
|
||||
* @param {boolean} isReadAssignedOnly ReadAssignedOnly capability
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/members/:memberId', function(
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/members/:memberId', async function(
|
||||
req,
|
||||
res,
|
||||
) {
|
||||
|
|
@ -2606,7 +2587,7 @@ JsonRoutes.add('POST', '/api/boards/:boardId/copy', function(req, res) {
|
|||
return data;
|
||||
}
|
||||
}
|
||||
const query = board.setMemberPermission(
|
||||
const query = await board.setMemberPermission(
|
||||
memberId,
|
||||
isTrue(isAdmin),
|
||||
isTrue(isNoComments),
|
||||
|
|
|
|||
713
models/cards.js
713
models/cards.js
|
|
@ -572,15 +572,17 @@ Cards.helpers({
|
|||
});
|
||||
},
|
||||
|
||||
mapCustomFieldsToBoard(boardId) {
|
||||
async mapCustomFieldsToBoard(boardId) {
|
||||
// Map custom fields to new board
|
||||
return this.customFields.map(cf => {
|
||||
const result = [];
|
||||
for (const cf of this.customFields) {
|
||||
const oldCf = ReactiveCache.getCustomField(cf._id);
|
||||
|
||||
// Check if oldCf is undefined or null
|
||||
if (!oldCf) {
|
||||
//console.error(`Custom field with ID ${cf._id} not found.`);
|
||||
return cf; // Skip this field if oldCf is not found
|
||||
result.push(cf); // Skip this field if oldCf is not found
|
||||
continue;
|
||||
}
|
||||
|
||||
const newCf = ReactiveCache.getCustomField({
|
||||
|
|
@ -592,11 +594,12 @@ Cards.helpers({
|
|||
if (newCf) {
|
||||
cf._id = newCf._id;
|
||||
} else if (!_.contains(oldCf.boardIds, boardId)) {
|
||||
oldCf.addBoard(boardId);
|
||||
await oldCf.addBoard(boardId);
|
||||
}
|
||||
|
||||
return cf;
|
||||
});
|
||||
result.push(cf);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
|
|
@ -1203,11 +1206,11 @@ Cards.helpers({
|
|||
}
|
||||
},
|
||||
|
||||
assignMember(memberId) {
|
||||
async assignMember(memberId) {
|
||||
let ret;
|
||||
if (this.isLinkedBoard()) {
|
||||
const board = ReactiveCache.getBoard(this.linkedId);
|
||||
ret = board.addMember(memberId);
|
||||
ret = await board.addMember(memberId);
|
||||
} else {
|
||||
ret = Cards.update(
|
||||
{ _id: this.getRealId() },
|
||||
|
|
@ -1234,7 +1237,7 @@ Cards.helpers({
|
|||
}
|
||||
},
|
||||
|
||||
unassignMember(memberId) {
|
||||
async unassignMember(memberId) {
|
||||
if (this.isLinkedCard()) {
|
||||
return Cards.update(
|
||||
{ _id: this.linkedId },
|
||||
|
|
@ -1242,7 +1245,7 @@ Cards.helpers({
|
|||
);
|
||||
} else if (this.isLinkedBoard()) {
|
||||
const board = ReactiveCache.getBoard(this.linkedId);
|
||||
return board.removeMember(memberId);
|
||||
return await board.removeMember(memberId);
|
||||
} else {
|
||||
return Cards.update({ _id: this._id }, { $pull: { members: memberId } });
|
||||
}
|
||||
|
|
@ -1991,52 +1994,41 @@ Cards.helpers({
|
|||
}
|
||||
return pokerWinnersListMap[0].pokerCard;
|
||||
},
|
||||
});
|
||||
|
||||
Cards.mutations({
|
||||
applyToChildren(funct) {
|
||||
ReactiveCache.getCards({
|
||||
parentId: this._id,
|
||||
}).forEach(card => {
|
||||
funct(card);
|
||||
async applyToChildren(funct) {
|
||||
const cards = ReactiveCache.getCards({ parentId: this._id });
|
||||
for (const card of cards) {
|
||||
await funct(card);
|
||||
}
|
||||
},
|
||||
|
||||
async archive() {
|
||||
await this.applyToChildren(async card => {
|
||||
await card.archive();
|
||||
});
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$set: { archived: true, archivedAt: new Date() },
|
||||
});
|
||||
},
|
||||
|
||||
archive() {
|
||||
this.applyToChildren(card => {
|
||||
return card.archive();
|
||||
async restore() {
|
||||
await this.applyToChildren(async card => {
|
||||
await card.restore();
|
||||
});
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$set: { archived: false },
|
||||
});
|
||||
return {
|
||||
$set: {
|
||||
archived: true,
|
||||
archivedAt: new Date(),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
restore() {
|
||||
this.applyToChildren(card => {
|
||||
return card.restore();
|
||||
});
|
||||
return {
|
||||
$set: {
|
||||
archived: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
moveToEndOfList({ listId, swimlaneId } = {}) {
|
||||
async moveToEndOfList({ listId, swimlaneId } = {}) {
|
||||
swimlaneId = swimlaneId || this.swimlaneId;
|
||||
const boardId = this.boardId;
|
||||
let sortIndex = 0;
|
||||
|
||||
// This should never happen, but there was a bug that was fixed in commit
|
||||
// ea0239538a68e225c867411a4f3e0d27c158383.
|
||||
if (!swimlaneId) {
|
||||
const board = ReactiveCache.getBoard(boardId);
|
||||
swimlaneId = board.getDefaultSwimline()._id;
|
||||
}
|
||||
// Move the minicard to the end of the target list
|
||||
let parentElementDom = $(`#swimlane-${swimlaneId}`).get(0);
|
||||
if (!parentElementDom) parentElementDom = $(':root');
|
||||
|
||||
|
|
@ -2045,7 +2037,7 @@ Cards.mutations({
|
|||
.get(0);
|
||||
if (lastCardDom) sortIndex = Utils.calculateIndex(lastCardDom, null).base;
|
||||
|
||||
return this.moveOptionalArgs({
|
||||
return await this.moveOptionalArgs({
|
||||
boardId,
|
||||
swimlaneId,
|
||||
listId,
|
||||
|
|
@ -2053,22 +2045,19 @@ Cards.mutations({
|
|||
});
|
||||
},
|
||||
|
||||
moveOptionalArgs({ boardId, swimlaneId, listId, sort } = {}) {
|
||||
async moveOptionalArgs({ boardId, swimlaneId, listId, sort } = {}) {
|
||||
boardId = boardId || this.boardId;
|
||||
swimlaneId = swimlaneId || this.swimlaneId;
|
||||
// This should never happen, but there was a bug that was fixed in commit
|
||||
// ea0239538a68e225c867411a4f3e0d27c158383.
|
||||
if (!swimlaneId) {
|
||||
const board = ReactiveCache.getBoard(boardId);
|
||||
swimlaneId = board.getDefaultSwimline()._id;
|
||||
}
|
||||
listId = listId || this.listId;
|
||||
if (sort === undefined || sort === null) sort = this.sort;
|
||||
return this.move(boardId, swimlaneId, listId, sort);
|
||||
return await this.move(boardId, swimlaneId, listId, sort);
|
||||
},
|
||||
|
||||
move(boardId, swimlaneId, listId, sort = null) {
|
||||
// Capture previous state for history tracking
|
||||
async move(boardId, swimlaneId, listId, sort = null) {
|
||||
const previousState = {
|
||||
boardId: this.boardId,
|
||||
swimlaneId: this.swimlaneId,
|
||||
|
|
@ -2076,20 +2065,13 @@ Cards.mutations({
|
|||
sort: this.sort,
|
||||
};
|
||||
|
||||
const mutatedFields = {
|
||||
boardId,
|
||||
swimlaneId,
|
||||
listId,
|
||||
};
|
||||
const mutatedFields = { boardId, swimlaneId, listId };
|
||||
|
||||
if (sort !== null) {
|
||||
mutatedFields.sort = sort;
|
||||
}
|
||||
|
||||
// we must only copy the labels and custom fields if the target board
|
||||
// differs from the source board
|
||||
if (this.boardId !== boardId) {
|
||||
// Get label names
|
||||
const oldBoard = ReactiveCache.getBoard(this.boardId);
|
||||
const oldBoardLabels = oldBoard.labels;
|
||||
const oldCardLabels = _.pluck(
|
||||
|
|
@ -2108,7 +2090,6 @@ Cards.mutations({
|
|||
'_id',
|
||||
);
|
||||
|
||||
// assign the new card number from the target board
|
||||
const newCardNumber = newBoard.getNextCardNumber();
|
||||
|
||||
Object.assign(mutatedFields, {
|
||||
|
|
@ -2119,11 +2100,8 @@ Cards.mutations({
|
|||
mutatedFields.customFields = this.mapCustomFieldsToBoard(newBoard._id);
|
||||
}
|
||||
|
||||
Cards.update(this._id, {
|
||||
$set: mutatedFields,
|
||||
});
|
||||
await Cards.updateAsync(this._id, { $set: mutatedFields });
|
||||
|
||||
// Track position change in user history (server-side only)
|
||||
if (Meteor.isServer && Meteor.userId() && typeof UserPositionHistory !== 'undefined') {
|
||||
try {
|
||||
UserPositionHistory.trackChange({
|
||||
|
|
@ -2145,7 +2123,6 @@ Cards.mutations({
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure attachments follow the card to its new board/list/swimlane
|
||||
if (Meteor.isServer) {
|
||||
const updateMeta = {};
|
||||
if (mutatedFields.boardId !== undefined) updateMeta['meta.boardId'] = mutatedFields.boardId;
|
||||
|
|
@ -2154,293 +2131,159 @@ Cards.mutations({
|
|||
|
||||
if (Object.keys(updateMeta).length > 0) {
|
||||
try {
|
||||
Attachments.collection.update(
|
||||
await Attachments.collection.updateAsync(
|
||||
{ 'meta.cardId': this._id },
|
||||
{ $set: updateMeta },
|
||||
{ multi: true },
|
||||
);
|
||||
} catch (err) {
|
||||
// Do not block the move if attachment update fails
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Failed to update attachments metadata after moving card', this._id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addLabel(labelId) {
|
||||
async addLabel(labelId) {
|
||||
this.labelIds.push(labelId);
|
||||
return {
|
||||
$addToSet: {
|
||||
labelIds: labelId,
|
||||
},
|
||||
};
|
||||
return await Cards.updateAsync(this._id, { $addToSet: { labelIds: labelId } });
|
||||
},
|
||||
|
||||
removeLabel(labelId) {
|
||||
async removeLabel(labelId) {
|
||||
this.labelIds = _.without(this.labelIds, labelId);
|
||||
return {
|
||||
$pull: {
|
||||
labelIds: labelId,
|
||||
},
|
||||
};
|
||||
return await Cards.updateAsync(this._id, { $pull: { labelIds: labelId } });
|
||||
},
|
||||
|
||||
toggleLabel(labelId) {
|
||||
async toggleLabel(labelId) {
|
||||
if (this.labelIds && this.labelIds.indexOf(labelId) > -1) {
|
||||
return this.removeLabel(labelId);
|
||||
return await this.removeLabel(labelId);
|
||||
} else {
|
||||
return this.addLabel(labelId);
|
||||
return await this.addLabel(labelId);
|
||||
}
|
||||
},
|
||||
|
||||
setColor(newColor) {
|
||||
async setColor(newColor) {
|
||||
if (newColor === 'white') {
|
||||
newColor = null;
|
||||
}
|
||||
return {
|
||||
$set: {
|
||||
color: newColor,
|
||||
},
|
||||
};
|
||||
return await Cards.updateAsync(this._id, { $set: { color: newColor } });
|
||||
},
|
||||
|
||||
assignMember(memberId) {
|
||||
return {
|
||||
$addToSet: {
|
||||
members: memberId,
|
||||
},
|
||||
};
|
||||
async assignMember(memberId) {
|
||||
return await Cards.updateAsync(this._id, { $addToSet: { members: memberId } });
|
||||
},
|
||||
|
||||
assignAssignee(assigneeId) {
|
||||
// If there is not any assignee, allow one assignee, not more.
|
||||
/*
|
||||
if (this.getAssignees().length === 0) {
|
||||
return {
|
||||
$addToSet: {
|
||||
assignees: assigneeId,
|
||||
},
|
||||
};
|
||||
*/
|
||||
// Allow more that one assignee:
|
||||
// https://github.com/wekan/wekan/issues/3302
|
||||
return {
|
||||
$addToSet: {
|
||||
assignees: assigneeId,
|
||||
},
|
||||
};
|
||||
//} else {
|
||||
// return false,
|
||||
//}
|
||||
async assignAssignee(assigneeId) {
|
||||
return await Cards.updateAsync(this._id, { $addToSet: { assignees: assigneeId } });
|
||||
},
|
||||
|
||||
unassignMember(memberId) {
|
||||
return {
|
||||
$pull: {
|
||||
members: memberId,
|
||||
},
|
||||
};
|
||||
async unassignMember(memberId) {
|
||||
return await Cards.updateAsync(this._id, { $pull: { members: memberId } });
|
||||
},
|
||||
|
||||
unassignAssignee(assigneeId) {
|
||||
return {
|
||||
$pull: {
|
||||
assignees: assigneeId,
|
||||
},
|
||||
};
|
||||
async unassignAssignee(assigneeId) {
|
||||
return await Cards.updateAsync(this._id, { $pull: { assignees: assigneeId } });
|
||||
},
|
||||
|
||||
toggleMember(memberId) {
|
||||
async toggleMember(memberId) {
|
||||
if (this.members && this.members.indexOf(memberId) > -1) {
|
||||
return this.unassignMember(memberId);
|
||||
return await this.unassignMember(memberId);
|
||||
} else {
|
||||
return this.assignMember(memberId);
|
||||
return await this.assignMember(memberId);
|
||||
}
|
||||
},
|
||||
|
||||
toggleAssignee(assigneeId) {
|
||||
async toggleAssignee(assigneeId) {
|
||||
if (this.assignees && this.assignees.indexOf(assigneeId) > -1) {
|
||||
return this.unassignAssignee(assigneeId);
|
||||
return await this.unassignAssignee(assigneeId);
|
||||
} else {
|
||||
return this.assignAssignee(assigneeId);
|
||||
return await this.assignAssignee(assigneeId);
|
||||
}
|
||||
},
|
||||
|
||||
assignCustomField(customFieldId) {
|
||||
return {
|
||||
$addToSet: {
|
||||
customFields: {
|
||||
_id: customFieldId,
|
||||
value: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
async assignCustomField(customFieldId) {
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$addToSet: { customFields: { _id: customFieldId, value: null } },
|
||||
});
|
||||
},
|
||||
|
||||
unassignCustomField(customFieldId) {
|
||||
return {
|
||||
$pull: {
|
||||
customFields: {
|
||||
_id: customFieldId,
|
||||
},
|
||||
},
|
||||
};
|
||||
async unassignCustomField(customFieldId) {
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$pull: { customFields: { _id: customFieldId } },
|
||||
});
|
||||
},
|
||||
|
||||
toggleCustomField(customFieldId) {
|
||||
async toggleCustomField(customFieldId) {
|
||||
if (this.customFields && this.customFieldIndex(customFieldId) > -1) {
|
||||
return this.unassignCustomField(customFieldId);
|
||||
return await this.unassignCustomField(customFieldId);
|
||||
} else {
|
||||
return this.assignCustomField(customFieldId);
|
||||
return await this.assignCustomField(customFieldId);
|
||||
}
|
||||
},
|
||||
|
||||
toggleShowActivities() {
|
||||
return {
|
||||
$set: {
|
||||
showActivities: !this.showActivities,
|
||||
}
|
||||
};
|
||||
async toggleShowActivities() {
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$set: { showActivities: !this.showActivities },
|
||||
});
|
||||
},
|
||||
|
||||
toggleShowChecklistAtMinicard() {
|
||||
return {
|
||||
$set: {
|
||||
showChecklistAtMinicard: !this.showChecklistAtMinicard,
|
||||
}
|
||||
};
|
||||
async toggleShowChecklistAtMinicard() {
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$set: { showChecklistAtMinicard: !this.showChecklistAtMinicard },
|
||||
});
|
||||
},
|
||||
|
||||
setCustomField(customFieldId, value) {
|
||||
// todo
|
||||
async setCustomField(customFieldId, value) {
|
||||
const index = this.customFieldIndex(customFieldId);
|
||||
if (index > -1) {
|
||||
const update = {
|
||||
$set: {},
|
||||
};
|
||||
const update = { $set: {} };
|
||||
update.$set[`customFields.${index}.value`] = value;
|
||||
return update;
|
||||
return await Cards.updateAsync(this._id, update);
|
||||
}
|
||||
// TODO
|
||||
// Ignatz 18.05.2018: Return null to silence ESLint. No Idea if that is correct
|
||||
return null;
|
||||
},
|
||||
|
||||
setCover(coverId) {
|
||||
return {
|
||||
$set: {
|
||||
coverId,
|
||||
},
|
||||
};
|
||||
async setCover(coverId) {
|
||||
return await Cards.updateAsync(this._id, { $set: { coverId } });
|
||||
},
|
||||
|
||||
unsetCover() {
|
||||
return {
|
||||
$unset: {
|
||||
coverId: '',
|
||||
},
|
||||
};
|
||||
async unsetCover() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { coverId: '' } });
|
||||
},
|
||||
|
||||
//setReceived(receivedAt) {
|
||||
// return {
|
||||
// $set: {
|
||||
// receivedAt,
|
||||
// },
|
||||
// };
|
||||
//},
|
||||
|
||||
unsetReceived() {
|
||||
return {
|
||||
$unset: {
|
||||
receivedAt: '',
|
||||
},
|
||||
};
|
||||
async unsetReceived() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { receivedAt: '' } });
|
||||
},
|
||||
|
||||
//setStart(startAt) {
|
||||
// return {
|
||||
// $set: {
|
||||
// startAt,
|
||||
// },
|
||||
// };
|
||||
//},
|
||||
|
||||
unsetStart() {
|
||||
return {
|
||||
$unset: {
|
||||
startAt: '',
|
||||
},
|
||||
};
|
||||
async unsetStart() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { startAt: '' } });
|
||||
},
|
||||
|
||||
//setDue(dueAt) {
|
||||
// return {
|
||||
// $set: {
|
||||
// dueAt,
|
||||
// },
|
||||
// };
|
||||
//},
|
||||
|
||||
unsetDue() {
|
||||
return {
|
||||
$unset: {
|
||||
dueAt: '',
|
||||
},
|
||||
};
|
||||
async unsetDue() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { dueAt: '' } });
|
||||
},
|
||||
|
||||
//setEnd(endAt) {
|
||||
// return {
|
||||
// $set: {
|
||||
// endAt,
|
||||
// },
|
||||
// };
|
||||
//},
|
||||
|
||||
unsetEnd() {
|
||||
return {
|
||||
$unset: {
|
||||
endAt: '',
|
||||
},
|
||||
};
|
||||
async unsetEnd() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { endAt: '' } });
|
||||
},
|
||||
|
||||
setOvertime(isOvertime) {
|
||||
return {
|
||||
$set: {
|
||||
isOvertime,
|
||||
},
|
||||
};
|
||||
async setOvertime(isOvertime) {
|
||||
return await Cards.updateAsync(this._id, { $set: { isOvertime } });
|
||||
},
|
||||
|
||||
setSpentTime(spentTime) {
|
||||
return {
|
||||
$set: {
|
||||
spentTime,
|
||||
},
|
||||
};
|
||||
async setSpentTime(spentTime) {
|
||||
return await Cards.updateAsync(this._id, { $set: { spentTime } });
|
||||
},
|
||||
|
||||
unsetSpentTime() {
|
||||
return {
|
||||
$unset: {
|
||||
spentTime: '',
|
||||
isOvertime: false,
|
||||
},
|
||||
};
|
||||
async unsetSpentTime() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { spentTime: '', isOvertime: false } });
|
||||
},
|
||||
|
||||
setParentId(parentId) {
|
||||
return {
|
||||
$set: {
|
||||
parentId,
|
||||
},
|
||||
};
|
||||
async setParentId(parentId) {
|
||||
return await Cards.updateAsync(this._id, { $set: { parentId } });
|
||||
},
|
||||
setVoteQuestion(question, publicVote, allowNonBoardMembers) {
|
||||
return {
|
||||
|
||||
async setVoteQuestion(question, publicVote, allowNonBoardMembers) {
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$set: {
|
||||
vote: {
|
||||
question,
|
||||
|
|
@ -2450,61 +2293,42 @@ Cards.mutations({
|
|||
negative: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
unsetVote() {
|
||||
return {
|
||||
$unset: {
|
||||
vote: '',
|
||||
},
|
||||
};
|
||||
|
||||
async unsetVote() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { vote: '' } });
|
||||
},
|
||||
setVoteEnd(end) {
|
||||
return {
|
||||
$set: { 'vote.end': end },
|
||||
};
|
||||
|
||||
async setVoteEnd(end) {
|
||||
return await Cards.updateAsync(this._id, { $set: { 'vote.end': end } });
|
||||
},
|
||||
unsetVoteEnd() {
|
||||
return {
|
||||
$unset: { 'vote.end': '' },
|
||||
};
|
||||
|
||||
async unsetVoteEnd() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { 'vote.end': '' } });
|
||||
},
|
||||
setVote(userId, forIt) {
|
||||
|
||||
async setVote(userId, forIt) {
|
||||
switch (forIt) {
|
||||
case true:
|
||||
// vote for it
|
||||
return {
|
||||
$pull: {
|
||||
'vote.negative': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'vote.positive': userId,
|
||||
},
|
||||
};
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$pull: { 'vote.negative': userId },
|
||||
$addToSet: { 'vote.positive': userId },
|
||||
});
|
||||
case false:
|
||||
// vote against
|
||||
return {
|
||||
$pull: {
|
||||
'vote.positive': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'vote.negative': userId,
|
||||
},
|
||||
};
|
||||
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$pull: { 'vote.positive': userId },
|
||||
$addToSet: { 'vote.negative': userId },
|
||||
});
|
||||
default:
|
||||
// Remove votes
|
||||
return {
|
||||
$pull: {
|
||||
'vote.positive': userId,
|
||||
'vote.negative': userId,
|
||||
},
|
||||
};
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$pull: { 'vote.positive': userId, 'vote.negative': userId },
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
setPokerQuestion(question, allowNonBoardMembers) {
|
||||
return {
|
||||
async setPokerQuestion(question, allowNonBoardMembers) {
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$set: {
|
||||
poker: {
|
||||
question,
|
||||
|
|
@ -2521,246 +2345,47 @@ Cards.mutations({
|
|||
unsure: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
setPokerEstimation(estimation) {
|
||||
return {
|
||||
$set: { 'poker.estimation': estimation },
|
||||
};
|
||||
|
||||
async setPokerEstimation(estimation) {
|
||||
return await Cards.updateAsync(this._id, { $set: { 'poker.estimation': estimation } });
|
||||
},
|
||||
unsetPokerEstimation() {
|
||||
return {
|
||||
$unset: { 'poker.estimation': '' },
|
||||
};
|
||||
|
||||
async unsetPokerEstimation() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { 'poker.estimation': '' } });
|
||||
},
|
||||
unsetPoker() {
|
||||
return {
|
||||
$unset: {
|
||||
poker: '',
|
||||
},
|
||||
};
|
||||
|
||||
async unsetPoker() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { poker: '' } });
|
||||
},
|
||||
setPokerEnd(end) {
|
||||
return {
|
||||
$set: { 'poker.end': end },
|
||||
};
|
||||
|
||||
async setPokerEnd(end) {
|
||||
return await Cards.updateAsync(this._id, { $set: { 'poker.end': end } });
|
||||
},
|
||||
unsetPokerEnd() {
|
||||
return {
|
||||
$unset: { 'poker.end': '' },
|
||||
};
|
||||
|
||||
async unsetPokerEnd() {
|
||||
return await Cards.updateAsync(this._id, { $unset: { 'poker.end': '' } });
|
||||
},
|
||||
setPoker(userId, state) {
|
||||
switch (state) {
|
||||
case 'one':
|
||||
// poker one
|
||||
return {
|
||||
$pull: {
|
||||
'poker.two': userId,
|
||||
'poker.three': userId,
|
||||
'poker.five': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.one': userId,
|
||||
},
|
||||
};
|
||||
case 'two':
|
||||
// poker two
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.three': userId,
|
||||
'poker.five': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.two': userId,
|
||||
},
|
||||
};
|
||||
|
||||
case 'three':
|
||||
// poker three
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.two': userId,
|
||||
'poker.five': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.three': userId,
|
||||
},
|
||||
};
|
||||
async setPoker(userId, state) {
|
||||
const pokerFields = ['one', 'two', 'three', 'five', 'eight', 'thirteen', 'twenty', 'forty', 'oneHundred', 'unsure'];
|
||||
const pullFields = {};
|
||||
pokerFields.forEach(f => { pullFields[`poker.${f}`] = userId; });
|
||||
|
||||
case 'five':
|
||||
// poker five
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.two': userId,
|
||||
'poker.three': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.five': userId,
|
||||
},
|
||||
};
|
||||
|
||||
case 'eight':
|
||||
// poker eight
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.two': userId,
|
||||
'poker.three': userId,
|
||||
'poker.five': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.eight': userId,
|
||||
},
|
||||
};
|
||||
|
||||
case 'thirteen':
|
||||
// poker thirteen
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.two': userId,
|
||||
'poker.three': userId,
|
||||
'poker.five': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.thirteen': userId,
|
||||
},
|
||||
};
|
||||
|
||||
case 'twenty':
|
||||
// poker twenty
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.two': userId,
|
||||
'poker.three': userId,
|
||||
'poker.five': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.twenty': userId,
|
||||
},
|
||||
};
|
||||
|
||||
case 'forty':
|
||||
// poker forty
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.two': userId,
|
||||
'poker.three': userId,
|
||||
'poker.five': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.forty': userId,
|
||||
},
|
||||
};
|
||||
|
||||
case 'oneHundred':
|
||||
// poker one hundred
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.two': userId,
|
||||
'poker.three': userId,
|
||||
'poker.five': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.oneHundred': userId,
|
||||
},
|
||||
};
|
||||
|
||||
case 'unsure':
|
||||
// poker unsure
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.two': userId,
|
||||
'poker.three': userId,
|
||||
'poker.five': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
},
|
||||
$addToSet: {
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
};
|
||||
|
||||
default:
|
||||
// Remove pokers
|
||||
return {
|
||||
$pull: {
|
||||
'poker.one': userId,
|
||||
'poker.two': userId,
|
||||
'poker.three': userId,
|
||||
'poker.five': userId,
|
||||
'poker.eight': userId,
|
||||
'poker.thirteen': userId,
|
||||
'poker.twenty': userId,
|
||||
'poker.forty': userId,
|
||||
'poker.oneHundred': userId,
|
||||
'poker.unsure': userId,
|
||||
},
|
||||
};
|
||||
if (pokerFields.includes(state)) {
|
||||
delete pullFields[`poker.${state}`];
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$pull: pullFields,
|
||||
$addToSet: { [`poker.${state}`]: userId },
|
||||
});
|
||||
} else {
|
||||
return await Cards.updateAsync(this._id, { $pull: pullFields });
|
||||
}
|
||||
},
|
||||
replayPoker() {
|
||||
return {
|
||||
|
||||
async replayPoker() {
|
||||
return await Cards.updateAsync(this._id, {
|
||||
$set: {
|
||||
'poker.one': [],
|
||||
'poker.two': [],
|
||||
|
|
@ -2773,7 +2398,7 @@ Cards.mutations({
|
|||
'poker.oneHundred': [],
|
||||
'poker.unsure': [],
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -4544,7 +4169,7 @@ JsonRoutes.add('GET', '/api/boards/:boardId/cards_count', function(
|
|||
JsonRoutes.add(
|
||||
'POST',
|
||||
'/api/boards/:boardId/lists/:listId/cards/:cardId/archive',
|
||||
function(req, res) {
|
||||
async function(req, res) {
|
||||
const paramBoardId = req.params.boardId;
|
||||
const paramCardId = req.params.cardId;
|
||||
const paramListId = req.params.listId;
|
||||
|
|
@ -4558,7 +4183,7 @@ JsonRoutes.add('GET', '/api/boards/:boardId/cards_count', function(
|
|||
if (!card) {
|
||||
throw new Meteor.Error(404, 'Card not found');
|
||||
}
|
||||
card.archive();
|
||||
await card.archive();
|
||||
JsonRoutes.sendResult(res, {
|
||||
code: 200,
|
||||
data: {
|
||||
|
|
@ -4583,7 +4208,7 @@ JsonRoutes.add('GET', '/api/boards/:boardId/cards_count', function(
|
|||
JsonRoutes.add(
|
||||
'POST',
|
||||
'/api/boards/:boardId/lists/:listId/cards/:cardId/unarchive',
|
||||
function(req, res) {
|
||||
async function(req, res) {
|
||||
const paramBoardId = req.params.boardId;
|
||||
const paramCardId = req.params.cardId;
|
||||
const paramListId = req.params.listId;
|
||||
|
|
@ -4597,7 +4222,7 @@ JsonRoutes.add('GET', '/api/boards/:boardId/cards_count', function(
|
|||
if (!card) {
|
||||
throw new Meteor.Error(404, 'Card not found');
|
||||
}
|
||||
card.restore();
|
||||
await card.restore();
|
||||
JsonRoutes.sendResult(res, {
|
||||
code: 200,
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -90,29 +90,24 @@ ChecklistItems.before.insert((userId, doc) => {
|
|||
}
|
||||
});
|
||||
|
||||
// Mutations
|
||||
ChecklistItems.mutations({
|
||||
setTitle(title) {
|
||||
return { $set: { title } };
|
||||
ChecklistItems.helpers({
|
||||
async setTitle(title) {
|
||||
return await ChecklistItems.updateAsync(this._id, { $set: { title } });
|
||||
},
|
||||
check() {
|
||||
return { $set: { isFinished: true } };
|
||||
async check() {
|
||||
return await ChecklistItems.updateAsync(this._id, { $set: { isFinished: true } });
|
||||
},
|
||||
uncheck() {
|
||||
return { $set: { isFinished: false } };
|
||||
async uncheck() {
|
||||
return await ChecklistItems.updateAsync(this._id, { $set: { isFinished: false } });
|
||||
},
|
||||
toggleItem() {
|
||||
return { $set: { isFinished: !this.isFinished } };
|
||||
async toggleItem() {
|
||||
return await ChecklistItems.updateAsync(this._id, { $set: { isFinished: !this.isFinished } });
|
||||
},
|
||||
move(checklistId, sortIndex) {
|
||||
async move(checklistId, sortIndex) {
|
||||
const cardId = ReactiveCache.getChecklist(checklistId).cardId;
|
||||
const mutatedFields = {
|
||||
cardId,
|
||||
checklistId,
|
||||
sort: sortIndex,
|
||||
};
|
||||
|
||||
return { $set: mutatedFields };
|
||||
return await ChecklistItems.updateAsync(this._id, {
|
||||
$set: { cardId, checklistId, sort: sortIndex },
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -150,22 +150,49 @@ Checklists.helpers({
|
|||
}
|
||||
return ret;
|
||||
},
|
||||
checkAllItems() {
|
||||
async checkAllItems() {
|
||||
const checkItems = ReactiveCache.getChecklistItems({ checklistId: this._id });
|
||||
checkItems.forEach(function(item) {
|
||||
item.check();
|
||||
});
|
||||
for (const item of checkItems) {
|
||||
await item.check();
|
||||
}
|
||||
},
|
||||
uncheckAllItems() {
|
||||
async uncheckAllItems() {
|
||||
const checkItems = ReactiveCache.getChecklistItems({ checklistId: this._id });
|
||||
checkItems.forEach(function(item) {
|
||||
item.uncheck();
|
||||
});
|
||||
for (const item of checkItems) {
|
||||
await item.uncheck();
|
||||
}
|
||||
},
|
||||
itemIndex(itemId) {
|
||||
const items = ReactiveCache.getChecklist({ _id: this._id }).items;
|
||||
return _.pluck(items, '_id').indexOf(itemId);
|
||||
},
|
||||
|
||||
async setTitle(title) {
|
||||
return await Checklists.updateAsync(this._id, { $set: { title } });
|
||||
},
|
||||
/** move the checklist to another card
|
||||
* @param newCardId move the checklist to this cardId
|
||||
*/
|
||||
async move(newCardId) {
|
||||
// Note: Activities and ChecklistItems updates are now handled server-side
|
||||
// in the moveChecklist Meteor method to avoid client-side permission issues
|
||||
return await Checklists.updateAsync(this._id, { $set: { cardId: newCardId } });
|
||||
},
|
||||
async toggleHideCheckedChecklistItems() {
|
||||
return await Checklists.updateAsync(this._id, {
|
||||
$set: { hideCheckedChecklistItems: !this.hideCheckedChecklistItems },
|
||||
});
|
||||
},
|
||||
async toggleHideAllChecklistItems() {
|
||||
return await Checklists.updateAsync(this._id, {
|
||||
$set: { hideAllChecklistItems: !this.hideAllChecklistItems },
|
||||
});
|
||||
},
|
||||
async toggleShowChecklistAtMinicard() {
|
||||
return await Checklists.updateAsync(this._id, {
|
||||
$set: { showChecklistAtMinicard: !this.showChecklistAtMinicard },
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Checklists.allow({
|
||||
|
|
@ -191,46 +218,6 @@ Checklists.before.insert((userId, doc) => {
|
|||
}
|
||||
});
|
||||
|
||||
Checklists.mutations({
|
||||
setTitle(title) {
|
||||
return { $set: { title } };
|
||||
},
|
||||
/** move the checklist to another card
|
||||
* @param newCardId move the checklist to this cardId
|
||||
*/
|
||||
move(newCardId) {
|
||||
// Note: Activities and ChecklistItems updates are now handled server-side
|
||||
// in the moveChecklist Meteor method to avoid client-side permission issues
|
||||
|
||||
// update the checklist itself
|
||||
return {
|
||||
$set: {
|
||||
cardId: newCardId,
|
||||
},
|
||||
};
|
||||
},
|
||||
toggleHideCheckedChecklistItems() {
|
||||
return {
|
||||
$set: {
|
||||
hideCheckedChecklistItems: !this.hideCheckedChecklistItems,
|
||||
}
|
||||
};
|
||||
},
|
||||
toggleHideAllChecklistItems() {
|
||||
return {
|
||||
$set: {
|
||||
hideAllChecklistItems: !this.hideAllChecklistItems,
|
||||
}
|
||||
};
|
||||
},
|
||||
toggleShowChecklistAtMinicard() {
|
||||
return {
|
||||
$set: {
|
||||
showChecklistAtMinicard: !this.showChecklistAtMinicard,
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Meteor.methods({
|
||||
|
|
|
|||
|
|
@ -382,14 +382,14 @@ export class CsvCreator {
|
|||
}
|
||||
}
|
||||
|
||||
create(board, currentBoardId) {
|
||||
async create(board, currentBoardId) {
|
||||
const isSandstorm =
|
||||
Meteor.settings &&
|
||||
Meteor.settings.public &&
|
||||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && currentBoardId) {
|
||||
const currentBoard = ReactiveCache.getBoard(currentBoardId);
|
||||
currentBoard.archive();
|
||||
await currentBoard.archive();
|
||||
}
|
||||
this.mapHeadertoCardFieldIndex(board[0]);
|
||||
const boardId = this.createBoard(board);
|
||||
|
|
|
|||
|
|
@ -152,17 +152,14 @@ CustomFields.addToAllCards = cf => {
|
|||
);
|
||||
};
|
||||
|
||||
CustomFields.mutations({
|
||||
addBoard(boardId) {
|
||||
CustomFields.helpers({
|
||||
async addBoard(boardId) {
|
||||
if (boardId) {
|
||||
return {
|
||||
$push: {
|
||||
boardIds: boardId,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
return await CustomFields.updateAsync(this._id, {
|
||||
$push: { boardIds: boardId },
|
||||
});
|
||||
}
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ Lists.helpers({
|
|||
});
|
||||
},
|
||||
|
||||
move(boardId, swimlaneId) {
|
||||
async move(boardId, swimlaneId) {
|
||||
const boardList = ReactiveCache.getList({
|
||||
boardId,
|
||||
title: this.title,
|
||||
|
|
@ -235,9 +235,9 @@ Lists.helpers({
|
|||
let listId;
|
||||
if (boardList) {
|
||||
listId = boardList._id;
|
||||
this.cards().forEach(card => {
|
||||
card.move(boardId, this._id, boardList._id);
|
||||
});
|
||||
for (const card of this.cards()) {
|
||||
await card.move(boardId, this._id, boardList._id);
|
||||
}
|
||||
} else {
|
||||
console.log('list.title:', this.title);
|
||||
console.log('boardList:', boardList);
|
||||
|
|
@ -251,9 +251,9 @@ Lists.helpers({
|
|||
});
|
||||
}
|
||||
|
||||
this.cards(swimlaneId).forEach(card => {
|
||||
card.move(boardId, swimlaneId, listId);
|
||||
});
|
||||
for (const card of this.cards(swimlaneId)) {
|
||||
await card.move(boardId, swimlaneId, listId);
|
||||
}
|
||||
},
|
||||
|
||||
cards(swimlaneId) {
|
||||
|
|
@ -339,64 +339,58 @@ Lists.helpers({
|
|||
const card = ReactiveCache.getCard({ listId: this._id });
|
||||
return card && card.originRelativeUrl();
|
||||
},
|
||||
remove() {
|
||||
Lists.remove({ _id: this._id });
|
||||
async remove() {
|
||||
return await Lists.removeAsync({ _id: this._id });
|
||||
},
|
||||
});
|
||||
|
||||
Lists.mutations({
|
||||
rename(title) {
|
||||
async rename(title) {
|
||||
// Basic client-side validation - server will handle full sanitization
|
||||
if (typeof title === 'string') {
|
||||
// Basic length check to prevent abuse
|
||||
const sanitizedTitle = title.length > 1000 ? title.substring(0, 1000) : title;
|
||||
return { $set: { title: sanitizedTitle } };
|
||||
return await Lists.updateAsync(this._id, { $set: { title: sanitizedTitle } });
|
||||
}
|
||||
return { $set: { title } };
|
||||
return await Lists.updateAsync(this._id, { $set: { title } });
|
||||
},
|
||||
star(enable = true) {
|
||||
return { $set: { starred: !!enable } };
|
||||
async star(enable = true) {
|
||||
return await Lists.updateAsync(this._id, { $set: { starred: !!enable } });
|
||||
},
|
||||
collapse(enable = true) {
|
||||
return { $set: { collapsed: !!enable } };
|
||||
async collapse(enable = true) {
|
||||
return await Lists.updateAsync(this._id, { $set: { collapsed: !!enable } });
|
||||
},
|
||||
|
||||
archive() {
|
||||
async archive() {
|
||||
if (this.isTemplateList()) {
|
||||
this.cards().forEach(card => {
|
||||
return card.archive();
|
||||
});
|
||||
for (const card of this.cards()) {
|
||||
await card.archive();
|
||||
}
|
||||
}
|
||||
return { $set: { archived: true, archivedAt: new Date() } };
|
||||
return await Lists.updateAsync(this._id, { $set: { archived: true, archivedAt: new Date() } });
|
||||
},
|
||||
|
||||
restore() {
|
||||
async restore() {
|
||||
if (this.isTemplateList()) {
|
||||
this.allCards().forEach(card => {
|
||||
return card.restore();
|
||||
});
|
||||
for (const card of this.allCards()) {
|
||||
await card.restore();
|
||||
}
|
||||
}
|
||||
return { $set: { archived: false } };
|
||||
return await Lists.updateAsync(this._id, { $set: { archived: false } });
|
||||
},
|
||||
|
||||
toggleSoftLimit(toggle) {
|
||||
return { $set: { 'wipLimit.soft': toggle } };
|
||||
async toggleSoftLimit(toggle) {
|
||||
return await Lists.updateAsync(this._id, { $set: { 'wipLimit.soft': toggle } });
|
||||
},
|
||||
|
||||
toggleWipLimit(toggle) {
|
||||
return { $set: { 'wipLimit.enabled': toggle } };
|
||||
async toggleWipLimit(toggle) {
|
||||
return await Lists.updateAsync(this._id, { $set: { 'wipLimit.enabled': toggle } });
|
||||
},
|
||||
|
||||
setWipLimit(limit) {
|
||||
return { $set: { 'wipLimit.value': limit } };
|
||||
async setWipLimit(limit) {
|
||||
return await Lists.updateAsync(this._id, { $set: { 'wipLimit.value': limit } });
|
||||
},
|
||||
|
||||
setColor(newColor) {
|
||||
return {
|
||||
$set: {
|
||||
color: newColor,
|
||||
},
|
||||
};
|
||||
async setColor(newColor) {
|
||||
return await Lists.updateAsync(this._id, { $set: { color: newColor } });
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -422,49 +416,49 @@ Lists.archivedListIds = () => {
|
|||
};
|
||||
|
||||
Meteor.methods({
|
||||
applyWipLimit(listId, limit) {
|
||||
async applyWipLimit(listId, limit) {
|
||||
check(listId, String);
|
||||
check(limit, Number);
|
||||
|
||||
|
||||
if (!this.userId) {
|
||||
throw new Meteor.Error('not-authorized', 'You must be logged in.');
|
||||
}
|
||||
|
||||
|
||||
const list = ReactiveCache.getList(listId);
|
||||
if (!list) {
|
||||
throw new Meteor.Error('list-not-found', 'List not found');
|
||||
}
|
||||
|
||||
|
||||
const board = ReactiveCache.getBoard(list.boardId);
|
||||
if (!board || !board.hasAdmin(this.userId)) {
|
||||
throw new Meteor.Error('not-authorized', 'You must be a board admin to modify WIP limits.');
|
||||
}
|
||||
|
||||
|
||||
if (limit === 0) {
|
||||
limit = 1;
|
||||
}
|
||||
list.setWipLimit(limit);
|
||||
await list.setWipLimit(limit);
|
||||
},
|
||||
|
||||
enableWipLimit(listId) {
|
||||
async enableWipLimit(listId) {
|
||||
check(listId, String);
|
||||
|
||||
|
||||
if (!this.userId) {
|
||||
throw new Meteor.Error('not-authorized', 'You must be logged in.');
|
||||
}
|
||||
|
||||
|
||||
const list = ReactiveCache.getList(listId);
|
||||
if (!list) {
|
||||
throw new Meteor.Error('list-not-found', 'List not found');
|
||||
}
|
||||
|
||||
|
||||
const board = ReactiveCache.getBoard(list.boardId);
|
||||
if (!board || !board.hasAdmin(this.userId)) {
|
||||
throw new Meteor.Error('not-authorized', 'You must be a board admin to modify WIP limits.');
|
||||
}
|
||||
|
||||
|
||||
if (list.getWipLimit('value') === 0) {
|
||||
list.setWipLimit(1);
|
||||
await list.setWipLimit(1);
|
||||
}
|
||||
list.toggleWipLimit(!list.getWipLimit('enabled'));
|
||||
},
|
||||
|
|
|
|||
|
|
@ -50,13 +50,10 @@ Rules.attachSchema(
|
|||
}),
|
||||
);
|
||||
|
||||
Rules.mutations({
|
||||
rename(description) {
|
||||
return { $set: { description } };
|
||||
},
|
||||
});
|
||||
|
||||
Rules.helpers({
|
||||
async rename(description) {
|
||||
return await Rules.updateAsync(this._id, { $set: { description } });
|
||||
},
|
||||
getAction() {
|
||||
return ReactiveCache.getAction(this.actionId);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -171,8 +171,8 @@ Swimlanes.helpers({
|
|||
});
|
||||
},
|
||||
|
||||
move(toBoardId) {
|
||||
this.lists().forEach(list => {
|
||||
async move(toBoardId) {
|
||||
for (const list of this.lists()) {
|
||||
const toList = ReactiveCache.getList({
|
||||
boardId: toBoardId,
|
||||
title: list.title,
|
||||
|
|
@ -183,25 +183,26 @@ Swimlanes.helpers({
|
|||
if (toList) {
|
||||
toListId = toList._id;
|
||||
} else {
|
||||
toListId = Lists.insert({
|
||||
toListId = await Lists.insertAsync({
|
||||
title: list.title,
|
||||
boardId: toBoardId,
|
||||
type: list.type,
|
||||
archived: false,
|
||||
wipLimit: list.wipLimit,
|
||||
swimlaneId: toSwimlaneId, // Set the target swimlane for the copied list
|
||||
swimlaneId: this._id,
|
||||
});
|
||||
}
|
||||
|
||||
ReactiveCache.getCards({
|
||||
const cards = ReactiveCache.getCards({
|
||||
listId: list._id,
|
||||
swimlaneId: this._id,
|
||||
}).forEach(card => {
|
||||
card.move(toBoardId, this._id, toListId);
|
||||
});
|
||||
});
|
||||
for (const card of cards) {
|
||||
await card.move(toBoardId, this._id, toListId);
|
||||
}
|
||||
}
|
||||
|
||||
Swimlanes.update(this._id, {
|
||||
await Swimlanes.updateAsync(this._id, {
|
||||
$set: {
|
||||
boardId: toBoardId,
|
||||
},
|
||||
|
|
@ -314,43 +315,37 @@ Swimlanes.helpers({
|
|||
return (user.profile || {}).boardTemplatesSwimlaneId === this._id;
|
||||
},
|
||||
|
||||
remove() {
|
||||
Swimlanes.remove({ _id: this._id });
|
||||
async remove() {
|
||||
return await Swimlanes.removeAsync({ _id: this._id });
|
||||
},
|
||||
});
|
||||
|
||||
Swimlanes.mutations({
|
||||
rename(title) {
|
||||
return { $set: { title } };
|
||||
async rename(title) {
|
||||
return await Swimlanes.updateAsync(this._id, { $set: { title } });
|
||||
},
|
||||
|
||||
// NOTE: collapse() removed - collapsed state is per-user only
|
||||
// Use user.setCollapsedSwimlane(boardId, swimlaneId, collapsed) instead
|
||||
|
||||
archive() {
|
||||
async archive() {
|
||||
if (this.isTemplateSwimlane()) {
|
||||
this.myLists().forEach(list => {
|
||||
return list.archive();
|
||||
});
|
||||
for (const list of this.myLists()) {
|
||||
await list.archive();
|
||||
}
|
||||
}
|
||||
return { $set: { archived: true, archivedAt: new Date() } };
|
||||
return await Swimlanes.updateAsync(this._id, { $set: { archived: true, archivedAt: new Date() } });
|
||||
},
|
||||
|
||||
restore() {
|
||||
async restore() {
|
||||
if (this.isTemplateSwimlane()) {
|
||||
this.myLists().forEach(list => {
|
||||
return list.restore();
|
||||
});
|
||||
for (const list of this.myLists()) {
|
||||
await list.restore();
|
||||
}
|
||||
}
|
||||
return { $set: { archived: false } };
|
||||
return await Swimlanes.updateAsync(this._id, { $set: { archived: false } });
|
||||
},
|
||||
|
||||
setColor(newColor) {
|
||||
return {
|
||||
$set: {
|
||||
color: newColor,
|
||||
},
|
||||
};
|
||||
async setColor(newColor) {
|
||||
return await Swimlanes.updateAsync(this._id, { $set: { color: newColor } });
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -767,7 +767,7 @@ export class TrelloCreator {
|
|||
}
|
||||
}
|
||||
|
||||
create(board, currentBoardId) {
|
||||
async create(board, currentBoardId) {
|
||||
// TODO : Make isSandstorm variable global
|
||||
const isSandstorm =
|
||||
Meteor.settings &&
|
||||
|
|
@ -775,7 +775,7 @@ export class TrelloCreator {
|
|||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && currentBoardId) {
|
||||
const currentBoard = ReactiveCache.getBoard(currentBoardId);
|
||||
currentBoard.archive();
|
||||
await currentBoard.archive();
|
||||
}
|
||||
this.parseActions(board.actions);
|
||||
const boardId = this.createBoardAndLabels(board);
|
||||
|
|
|
|||
|
|
@ -3,16 +3,6 @@ import { Meteor } from 'meteor/meteor';
|
|||
|
||||
Triggers = new Mongo.Collection('triggers');
|
||||
|
||||
Triggers.mutations({
|
||||
rename(description) {
|
||||
return {
|
||||
$set: {
|
||||
description,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
Triggers.before.insert((userId, doc) => {
|
||||
doc.createdAt = new Date();
|
||||
doc.updatedAt = doc.createdAt;
|
||||
|
|
@ -36,6 +26,12 @@ Triggers.allow({
|
|||
});
|
||||
|
||||
Triggers.helpers({
|
||||
async rename(description) {
|
||||
return await Triggers.updateAsync(this._id, {
|
||||
$set: { description },
|
||||
});
|
||||
},
|
||||
|
||||
description() {
|
||||
return this.desc;
|
||||
},
|
||||
|
|
|
|||
400
models/users.js
400
models/users.js
|
|
@ -1593,376 +1593,206 @@ Users.helpers({
|
|||
}
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
Users.mutations({
|
||||
/** set the confirmed board id/swimlane id/list id of a board
|
||||
* @param boardId the current board id
|
||||
* @param options an object with the confirmed field values
|
||||
*/
|
||||
setMoveAndCopyDialogOption(boardId, options) {
|
||||
async setMoveAndCopyDialogOption(boardId, options) {
|
||||
let currentOptions = this.getMoveAndCopyDialogOptions();
|
||||
currentOptions[boardId] = options;
|
||||
return {
|
||||
$set: {
|
||||
'profile.moveAndCopyDialog': currentOptions,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.moveAndCopyDialog': currentOptions } });
|
||||
},
|
||||
/** set the confirmed board id/swimlane id/list id/card id of a board (move checklist)
|
||||
* @param boardId the current board id
|
||||
* @param options an object with the confirmed field values
|
||||
*/
|
||||
setMoveChecklistDialogOption(boardId, options) {
|
||||
|
||||
async setMoveChecklistDialogOption(boardId, options) {
|
||||
let currentOptions = this.getMoveChecklistDialogOptions();
|
||||
currentOptions[boardId] = options;
|
||||
return {
|
||||
$set: {
|
||||
'profile.moveChecklistDialog': currentOptions,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.moveChecklistDialog': currentOptions } });
|
||||
},
|
||||
/** set the confirmed board id/swimlane id/list id/card id of a board (copy checklist)
|
||||
* @param boardId the current board id
|
||||
* @param options an object with the confirmed field values
|
||||
*/
|
||||
setCopyChecklistDialogOption(boardId, options) {
|
||||
|
||||
async setCopyChecklistDialogOption(boardId, options) {
|
||||
let currentOptions = this.getCopyChecklistDialogOptions();
|
||||
currentOptions[boardId] = options;
|
||||
return {
|
||||
$set: {
|
||||
'profile.copyChecklistDialog': currentOptions,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.copyChecklistDialog': currentOptions } });
|
||||
},
|
||||
toggleBoardStar(boardId) {
|
||||
|
||||
async toggleBoardStar(boardId) {
|
||||
const queryKind = this.hasStarred(boardId) ? '$pull' : '$addToSet';
|
||||
return {
|
||||
[queryKind]: {
|
||||
'profile.starredBoards': boardId,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { [queryKind]: { 'profile.starredBoards': boardId } });
|
||||
},
|
||||
/**
|
||||
* Set per-user board sort index for a board
|
||||
* Stored at profile.boardSortIndex[boardId] = sortIndex (Number)
|
||||
*/
|
||||
setBoardSortIndex(boardId, sortIndex) {
|
||||
|
||||
async setBoardSortIndex(boardId, sortIndex) {
|
||||
const mapping = (this.profile && this.profile.boardSortIndex) || {};
|
||||
mapping[boardId] = sortIndex;
|
||||
return {
|
||||
$set: {
|
||||
'profile.boardSortIndex': mapping,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.boardSortIndex': mapping } });
|
||||
},
|
||||
toggleAutoWidth(boardId) {
|
||||
|
||||
async toggleAutoWidth(boardId) {
|
||||
const { autoWidthBoards = {} } = this.profile || {};
|
||||
autoWidthBoards[boardId] = !autoWidthBoards[boardId];
|
||||
return {
|
||||
$set: {
|
||||
'profile.autoWidthBoards': autoWidthBoards,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.autoWidthBoards': autoWidthBoards } });
|
||||
},
|
||||
toggleKeyboardShortcuts() {
|
||||
|
||||
async toggleKeyboardShortcuts() {
|
||||
const { keyboardShortcuts = true } = this.profile || {};
|
||||
return {
|
||||
$set: {
|
||||
'profile.keyboardShortcuts': !keyboardShortcuts,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.keyboardShortcuts': !keyboardShortcuts } });
|
||||
},
|
||||
toggleVerticalScrollbars() {
|
||||
|
||||
async toggleVerticalScrollbars() {
|
||||
const { verticalScrollbars = true } = this.profile || {};
|
||||
return {
|
||||
$set: {
|
||||
'profile.verticalScrollbars': !verticalScrollbars,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.verticalScrollbars': !verticalScrollbars } });
|
||||
},
|
||||
toggleShowWeekOfYear() {
|
||||
|
||||
async toggleShowWeekOfYear() {
|
||||
const { showWeekOfYear = true } = this.profile || {};
|
||||
return {
|
||||
$set: {
|
||||
'profile.showWeekOfYear': !showWeekOfYear,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.showWeekOfYear': !showWeekOfYear } });
|
||||
},
|
||||
|
||||
addInvite(boardId) {
|
||||
return {
|
||||
$addToSet: {
|
||||
'profile.invitedBoards': boardId,
|
||||
},
|
||||
};
|
||||
async addInvite(boardId) {
|
||||
return await Users.updateAsync(this._id, { $addToSet: { 'profile.invitedBoards': boardId } });
|
||||
},
|
||||
|
||||
removeInvite(boardId) {
|
||||
return {
|
||||
$pull: {
|
||||
'profile.invitedBoards': boardId,
|
||||
},
|
||||
};
|
||||
async removeInvite(boardId) {
|
||||
return await Users.updateAsync(this._id, { $pull: { 'profile.invitedBoards': boardId } });
|
||||
},
|
||||
|
||||
addTag(tag) {
|
||||
return {
|
||||
$addToSet: {
|
||||
'profile.tags': tag,
|
||||
},
|
||||
};
|
||||
async addTag(tag) {
|
||||
return await Users.updateAsync(this._id, { $addToSet: { 'profile.tags': tag } });
|
||||
},
|
||||
|
||||
removeTag(tag) {
|
||||
return {
|
||||
$pull: {
|
||||
'profile.tags': tag,
|
||||
},
|
||||
};
|
||||
async removeTag(tag) {
|
||||
return await Users.updateAsync(this._id, { $pull: { 'profile.tags': tag } });
|
||||
},
|
||||
|
||||
toggleTag(tag) {
|
||||
if (this.hasTag(tag)) this.removeTag(tag);
|
||||
else this.addTag(tag);
|
||||
async toggleTag(tag) {
|
||||
if (this.hasTag(tag)) {
|
||||
return await this.removeTag(tag);
|
||||
} else {
|
||||
return await this.addTag(tag);
|
||||
}
|
||||
},
|
||||
|
||||
setListSortBy(value) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.listSortBy': value,
|
||||
},
|
||||
};
|
||||
async setListSortBy(value) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.listSortBy': value } });
|
||||
},
|
||||
|
||||
setName(value) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.fullname': value,
|
||||
},
|
||||
};
|
||||
async setName(value) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.fullname': value } });
|
||||
},
|
||||
|
||||
toggleDesktopHandles(value = false) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.showDesktopDragHandles': !value,
|
||||
},
|
||||
};
|
||||
async toggleDesktopHandles(value = false) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.showDesktopDragHandles': !value } });
|
||||
},
|
||||
|
||||
toggleFieldsGrid(value = false) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.customFieldsGrid': !value,
|
||||
},
|
||||
};
|
||||
async toggleFieldsGrid(value = false) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.customFieldsGrid': !value } });
|
||||
},
|
||||
|
||||
toggleCardMaximized(value = false) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.cardMaximized': !value,
|
||||
},
|
||||
};
|
||||
async toggleCardMaximized(value = false) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.cardMaximized': !value } });
|
||||
},
|
||||
|
||||
toggleCardCollapsed(value = false) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.cardCollapsed': !value,
|
||||
},
|
||||
};
|
||||
async toggleCardCollapsed(value = false) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.cardCollapsed': !value } });
|
||||
},
|
||||
|
||||
toggleShowActivities(value = false) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.showActivities': !value,
|
||||
},
|
||||
};
|
||||
async toggleShowActivities(value = false) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.showActivities': !value } });
|
||||
},
|
||||
|
||||
toggleLabelText(value = false) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.hiddenMinicardLabelText': !value,
|
||||
},
|
||||
};
|
||||
},
|
||||
toggleRescueCardDescription(value = false) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.rescueCardDescription': !value,
|
||||
},
|
||||
};
|
||||
},
|
||||
toggleGreyIcons(value = false) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.GreyIcons': !value,
|
||||
},
|
||||
};
|
||||
async toggleLabelText(value = false) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.hiddenMinicardLabelText': !value } });
|
||||
},
|
||||
|
||||
addNotification(activityId) {
|
||||
return {
|
||||
$addToSet: {
|
||||
'profile.notifications': {
|
||||
activity: activityId,
|
||||
read: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
async toggleRescueCardDescription(value = false) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.rescueCardDescription': !value } });
|
||||
},
|
||||
|
||||
removeNotification(activityId) {
|
||||
return {
|
||||
$pull: {
|
||||
'profile.notifications': {
|
||||
activity: activityId,
|
||||
},
|
||||
},
|
||||
};
|
||||
async toggleGreyIcons(value = false) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.GreyIcons': !value } });
|
||||
},
|
||||
|
||||
addEmailBuffer(text) {
|
||||
return {
|
||||
$addToSet: {
|
||||
'profile.emailBuffer': text,
|
||||
},
|
||||
};
|
||||
async addNotification(activityId) {
|
||||
return await Users.updateAsync(this._id, {
|
||||
$addToSet: { 'profile.notifications': { activity: activityId, read: null } },
|
||||
});
|
||||
},
|
||||
|
||||
clearEmailBuffer() {
|
||||
return {
|
||||
$set: {
|
||||
'profile.emailBuffer': [],
|
||||
},
|
||||
};
|
||||
async removeNotification(activityId) {
|
||||
return await Users.updateAsync(this._id, {
|
||||
$pull: { 'profile.notifications': { activity: activityId } },
|
||||
});
|
||||
},
|
||||
|
||||
setAvatarUrl(avatarUrl) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.avatarUrl': avatarUrl,
|
||||
},
|
||||
};
|
||||
async addEmailBuffer(text) {
|
||||
return await Users.updateAsync(this._id, { $addToSet: { 'profile.emailBuffer': text } });
|
||||
},
|
||||
|
||||
setShowCardsCountAt(limit) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.showCardsCountAt': limit,
|
||||
},
|
||||
};
|
||||
async clearEmailBuffer() {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.emailBuffer': [] } });
|
||||
},
|
||||
|
||||
setStartDayOfWeek(startDay) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.startDayOfWeek': startDay,
|
||||
},
|
||||
};
|
||||
async setAvatarUrl(avatarUrl) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.avatarUrl': avatarUrl } });
|
||||
},
|
||||
|
||||
setDateFormat(dateFormat) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.dateFormat': dateFormat,
|
||||
},
|
||||
};
|
||||
async setShowCardsCountAt(limit) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.showCardsCountAt': limit } });
|
||||
},
|
||||
|
||||
setBoardView(view) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.boardView': view,
|
||||
},
|
||||
};
|
||||
async setStartDayOfWeek(startDay) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.startDayOfWeek': startDay } });
|
||||
},
|
||||
|
||||
setListWidth(boardId, listId, width) {
|
||||
async setDateFormat(dateFormat) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.dateFormat': dateFormat } });
|
||||
},
|
||||
|
||||
async setBoardView(view) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.boardView': view } });
|
||||
},
|
||||
|
||||
async setListWidth(boardId, listId, width) {
|
||||
let currentWidths = this.getListWidths();
|
||||
if (!currentWidths[boardId]) {
|
||||
currentWidths[boardId] = {};
|
||||
}
|
||||
if (!currentWidths[boardId]) currentWidths[boardId] = {};
|
||||
currentWidths[boardId][listId] = width;
|
||||
return {
|
||||
$set: {
|
||||
'profile.listWidths': currentWidths,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.listWidths': currentWidths } });
|
||||
},
|
||||
|
||||
setListConstraint(boardId, listId, constraint) {
|
||||
async setListConstraint(boardId, listId, constraint) {
|
||||
let currentConstraints = this.getListConstraints();
|
||||
if (!currentConstraints[boardId]) {
|
||||
currentConstraints[boardId] = {};
|
||||
}
|
||||
if (!currentConstraints[boardId]) currentConstraints[boardId] = {};
|
||||
currentConstraints[boardId][listId] = constraint;
|
||||
return {
|
||||
$set: {
|
||||
'profile.listConstraints': currentConstraints,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.listConstraints': currentConstraints } });
|
||||
},
|
||||
|
||||
setSwimlaneHeight(boardId, swimlaneId, height) {
|
||||
async setSwimlaneHeight(boardId, swimlaneId, height) {
|
||||
let currentHeights = this.getSwimlaneHeights();
|
||||
if (!currentHeights[boardId]) {
|
||||
currentHeights[boardId] = {};
|
||||
}
|
||||
if (!currentHeights[boardId]) currentHeights[boardId] = {};
|
||||
currentHeights[boardId][swimlaneId] = height;
|
||||
return {
|
||||
$set: {
|
||||
'profile.swimlaneHeights': currentHeights,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.swimlaneHeights': currentHeights } });
|
||||
},
|
||||
setCollapsedList(boardId, listId, collapsed) {
|
||||
|
||||
async setCollapsedList(boardId, listId, collapsed) {
|
||||
const current = (this.profile && this.profile.collapsedLists) || {};
|
||||
if (!current[boardId]) current[boardId] = {};
|
||||
current[boardId][listId] = !!collapsed;
|
||||
return {
|
||||
$set: {
|
||||
'profile.collapsedLists': current,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.collapsedLists': current } });
|
||||
},
|
||||
setCollapsedSwimlane(boardId, swimlaneId, collapsed) {
|
||||
|
||||
async setCollapsedSwimlane(boardId, swimlaneId, collapsed) {
|
||||
const current = (this.profile && this.profile.collapsedSwimlanes) || {};
|
||||
if (!current[boardId]) current[boardId] = {};
|
||||
current[boardId][swimlaneId] = !!collapsed;
|
||||
return {
|
||||
$set: {
|
||||
'profile.collapsedSwimlanes': current,
|
||||
},
|
||||
};
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.collapsedSwimlanes': current } });
|
||||
},
|
||||
|
||||
setZoomLevel(level) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.zoomLevel': level,
|
||||
},
|
||||
};
|
||||
async setZoomLevel(level) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.zoomLevel': level } });
|
||||
},
|
||||
|
||||
setMobileMode(enabled) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.mobileMode': enabled,
|
||||
},
|
||||
};
|
||||
async setMobileMode(enabled) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.mobileMode': enabled } });
|
||||
},
|
||||
|
||||
setCardZoom(level) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.cardZoom': level,
|
||||
},
|
||||
};
|
||||
async setCardZoom(level) {
|
||||
return await Users.updateAsync(this._id, { $set: { 'profile.cardZoom': level } });
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -3340,7 +3170,7 @@ if (Meteor.isServer) {
|
|||
* @return_type {_id: string,
|
||||
* title: string}
|
||||
*/
|
||||
JsonRoutes.add('PUT', '/api/users/:userId', function (req, res) {
|
||||
JsonRoutes.add('PUT', '/api/users/:userId', async function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
const id = req.params.userId;
|
||||
|
|
@ -3350,7 +3180,7 @@ if (Meteor.isServer) {
|
|||
});
|
||||
if (data !== undefined) {
|
||||
if (action === 'takeOwnership') {
|
||||
data = ReactiveCache.getBoards(
|
||||
const boards = ReactiveCache.getBoards(
|
||||
{
|
||||
'members.userId': id,
|
||||
'members.isAdmin': true,
|
||||
|
|
@ -3360,16 +3190,18 @@ if (Meteor.isServer) {
|
|||
sort: 1 /* boards default sorting */,
|
||||
},
|
||||
},
|
||||
).map(function (board) {
|
||||
);
|
||||
data = [];
|
||||
for (const board of boards) {
|
||||
if (board.hasMember(req.userId)) {
|
||||
board.removeMember(req.userId);
|
||||
await board.removeMember(req.userId);
|
||||
}
|
||||
board.changeOwnership(id, req.userId);
|
||||
return {
|
||||
data.push({
|
||||
_id: board._id,
|
||||
title: board.title,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (action === 'disableLogin' && id !== req.userId) {
|
||||
Users.update(
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ const simpleWatchable = collection => {
|
|||
findWatcher(userId) {
|
||||
return _.contains(this.watchers, userId);
|
||||
},
|
||||
});
|
||||
|
||||
collection.mutations({
|
||||
setWatcher(userId, level) {
|
||||
async setWatcher(userId, level) {
|
||||
// if level undefined or null or false, then remove
|
||||
if (!level) return { $pull: { watchers: userId } };
|
||||
return { $addToSet: { watchers: userId } };
|
||||
if (!level) {
|
||||
return await collection.updateAsync(this._id, { $pull: { watchers: userId } });
|
||||
}
|
||||
return await collection.updateAsync(this._id, { $addToSet: { watchers: userId } });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -66,20 +66,20 @@ const complexWatchable = collection => {
|
|||
const watcher = this.findWatcher(userId);
|
||||
return watcher ? watcher.level : complexWatchDefault;
|
||||
},
|
||||
});
|
||||
|
||||
collection.mutations({
|
||||
setWatcher(userId, level) {
|
||||
async setWatcher(userId, level) {
|
||||
// if level undefined or null or false, then remove
|
||||
if (level === complexWatchDefault) level = null;
|
||||
if (!level) return { $pull: { watchers: { userId } } };
|
||||
if (!level) {
|
||||
return await collection.updateAsync(this._id, { $pull: { watchers: { userId } } });
|
||||
}
|
||||
const index = this.watcherIndex(userId);
|
||||
if (index < 0) return { $push: { watchers: { userId, level } } };
|
||||
return {
|
||||
$set: {
|
||||
[`watchers.${index}.level`]: level,
|
||||
},
|
||||
};
|
||||
if (index < 0) {
|
||||
return await collection.updateAsync(this._id, { $push: { watchers: { userId, level } } });
|
||||
}
|
||||
return await collection.updateAsync(this._id, {
|
||||
$set: { [`watchers.${index}.level`]: level },
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -970,7 +970,7 @@ export class WekanCreator {
|
|||
// }
|
||||
}
|
||||
|
||||
create(board, currentBoardId) {
|
||||
async create(board, currentBoardId) {
|
||||
// TODO : Make isSandstorm variable global
|
||||
const isSandstorm =
|
||||
Meteor.settings &&
|
||||
|
|
@ -978,7 +978,7 @@ export class WekanCreator {
|
|||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && currentBoardId) {
|
||||
const currentBoard = ReactiveCache.getBoard(currentBoardId);
|
||||
currentBoard.archive();
|
||||
await currentBoard.archive();
|
||||
}
|
||||
this.parseActivities(board);
|
||||
const boardId = this.createBoardAndLabels(board);
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ Meteor.methods({
|
|||
});
|
||||
|
||||
Meteor.methods({
|
||||
'boardRoutineOnLogin': function(info, oidcUserId)
|
||||
'boardRoutineOnLogin': async function(info, oidcUserId)
|
||||
{
|
||||
check(info, Object);
|
||||
check(oidcUserId, String);
|
||||
|
|
@ -333,8 +333,8 @@ Meteor.methods({
|
|||
const memberIndex = _.pluck(board?.members, 'userId').indexOf(userId);
|
||||
if(!board || !userId || memberIndex > -1) return
|
||||
|
||||
board.addMember(userId)
|
||||
board.setMemberPermission(
|
||||
await board.addMember(userId)
|
||||
await board.setMemberPermission(
|
||||
userId,
|
||||
defaultBoardParams.contains("isAdmin"),
|
||||
defaultBoardParams.contains("isNoComments"),
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ do
|
|||
# Latest fibers for Meteor sudo mkdir -p /usr/local/lib/node_modules/fibers/.node-gyp sudo npm -g install fibers
|
||||
sudo npm -g install @mapbox/node-pre-gyp
|
||||
# Install Meteor, if it's not yet installed
|
||||
sudo npm -g install meteor@2.14 --unsafe-perm
|
||||
sudo npm -g install meteor@2.16 --unsafe-perm
|
||||
#sudo chown -R $(id -u):$(id -g) $HOME/.npm $HOME/.meteor
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
echo "macOS"
|
||||
|
|
@ -89,7 +89,7 @@ do
|
|||
npm -g uninstall node-pre-gyp
|
||||
npm -g install @mapbox/node-pre-gyp
|
||||
npm -g install node-gyp
|
||||
npm -g install meteor@2.14
|
||||
npm -g install meteor@2.16
|
||||
export PATH=~/.meteor:$PATH
|
||||
exit;
|
||||
elif [[ "$OSTYPE" == "cygwin" ]]; then
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Meteor.methods({
|
||||
watch(watchableType, id, level) {
|
||||
async watch(watchableType, id, level) {
|
||||
check(watchableType, String);
|
||||
check(id, String);
|
||||
check(level, Match.OneOf(String, null));
|
||||
|
|
@ -29,7 +29,7 @@ Meteor.methods({
|
|||
if (board.permission === 'private' && !board.hasMember(userId))
|
||||
throw new Meteor.Error('error-board-notAMember');
|
||||
|
||||
watchableObj.setWatcher(userId, level);
|
||||
await watchableObj.setWatcher(userId, level);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Meteor.methods({
|
|||
return ret;
|
||||
},
|
||||
|
||||
moveSwimlane(swimlaneId, toBoardId) {
|
||||
async moveSwimlane(swimlaneId, toBoardId) {
|
||||
check(swimlaneId, String);
|
||||
check(toBoardId, String);
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ Meteor.methods({
|
|||
|
||||
let ret = false;
|
||||
if (swimlane && toBoard) {
|
||||
swimlane.move(toBoardId);
|
||||
await swimlane.move(toBoardId);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
RulesHelper = {
|
||||
executeRules(activity) {
|
||||
async executeRules(activity) {
|
||||
const matchingRules = this.findMatchingRules(activity);
|
||||
for (let i = 0; i < matchingRules.length; i++) {
|
||||
const action = matchingRules[i].getAction();
|
||||
if (action !== undefined) {
|
||||
this.performAction(activity, action);
|
||||
await this.performAction(activity, action);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -57,7 +57,7 @@ RulesHelper = {
|
|||
});
|
||||
return matchingMap;
|
||||
},
|
||||
performAction(activity, action) {
|
||||
async performAction(activity, action) {
|
||||
const card = ReactiveCache.getCard(activity.cardId);
|
||||
const boardId = activity.boardId;
|
||||
if (
|
||||
|
|
@ -112,12 +112,12 @@ RulesHelper = {
|
|||
const minOrder = _.min(
|
||||
list.cardsUnfiltered(swimlaneId).map(c => c.sort),
|
||||
);
|
||||
card.move(action.boardId, swimlaneId, listId, minOrder - 1);
|
||||
await card.move(action.boardId, swimlaneId, listId, minOrder - 1);
|
||||
} else {
|
||||
const maxOrder = _.max(
|
||||
list.cardsUnfiltered(swimlaneId).map(c => c.sort),
|
||||
);
|
||||
card.move(action.boardId, swimlaneId, listId, maxOrder + 1);
|
||||
await card.move(action.boardId, swimlaneId, listId, maxOrder + 1);
|
||||
}
|
||||
}
|
||||
if (action.actionType === 'sendEmail') {
|
||||
|
|
@ -247,13 +247,13 @@ RulesHelper = {
|
|||
}
|
||||
}
|
||||
if (action.actionType === 'archive') {
|
||||
card.archive();
|
||||
await card.archive();
|
||||
}
|
||||
if (action.actionType === 'unarchive') {
|
||||
card.restore();
|
||||
await card.restore();
|
||||
}
|
||||
if (action.actionType === 'setColor') {
|
||||
card.setColor(action.selectedColor);
|
||||
await card.setColor(action.selectedColor);
|
||||
}
|
||||
if (action.actionType === 'addLabel') {
|
||||
card.addLabel(action.labelId);
|
||||
|
|
@ -281,14 +281,14 @@ RulesHelper = {
|
|||
title: action.checklistName,
|
||||
cardId: card._id,
|
||||
});
|
||||
checkList.checkAllItems();
|
||||
await checkList.checkAllItems();
|
||||
}
|
||||
if (action.actionType === 'uncheckAll') {
|
||||
const checkList = ReactiveCache.getChecklist({
|
||||
title: action.checklistName,
|
||||
cardId: card._id,
|
||||
});
|
||||
checkList.uncheckAllItems();
|
||||
await checkList.uncheckAllItems();
|
||||
}
|
||||
if (action.actionType === 'checkItem') {
|
||||
const checkList = ReactiveCache.getChecklist({
|
||||
|
|
@ -299,7 +299,7 @@ RulesHelper = {
|
|||
title: action.checkItemName,
|
||||
checkListId: checkList._id,
|
||||
});
|
||||
checkItem.check();
|
||||
await checkItem.check();
|
||||
}
|
||||
if (action.actionType === 'uncheckItem') {
|
||||
const checkList = ReactiveCache.getChecklist({
|
||||
|
|
@ -310,7 +310,7 @@ RulesHelper = {
|
|||
title: action.checkItemName,
|
||||
checkListId: checkList._id,
|
||||
});
|
||||
checkItem.uncheck();
|
||||
await checkItem.uncheck();
|
||||
}
|
||||
if (action.actionType === 'addChecklist') {
|
||||
Checklists.insert({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue