Return data on client (sync) and Promise on server (async) naturally, without wrapping in an extra Promise

This commit is contained in:
Harry Adel 2026-02-18 18:24:55 +02:00
parent 2b15a8ff09
commit f934aea2a5
21 changed files with 405 additions and 3760 deletions

View file

@ -64,7 +64,7 @@ ReactiveCacheServer = {
return ret;
},
async getCards(selector = {}, options = {}, getQuery = false) {
let ret = Cards.find(selector, options, options);
let ret = Cards.find(selector, options);
if (getQuery !== true) {
ret = await ret.fetchAsync();
}
@ -997,68 +997,69 @@ ReactiveCacheClient = {
// - The Programmer hasn't to care about in which context he call's this class
// - having all queries together in 1 class to make it possible to see which queries in Wekan happens, e.g. with console.log
//
// All methods are async for Meteor 3.0 compatibility.
// Server path uses async MongoDB operations; Client path uses sync Minimongo (wrapped in Promise).
// Methods are NOT async - they return a Promise on server (from async ReactiveCacheServer)
// and synchronous data on client (from ReactiveCacheClient).
// Server callers must await; client code uses the return value directly.
ReactiveCache = {
async getBoard(idOrFirstObjectSelector = {}, options = {}) {
getBoard(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getBoard(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getBoard(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getBoard(idOrFirstObjectSelector, options);
}
},
async getBoards(selector = {}, options = {}, getQuery = false) {
getBoards(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getBoards(selector, options, getQuery);
return ReactiveCacheServer.getBoards(selector, options, getQuery);
} else {
return ReactiveCacheClient.getBoards(selector, options, getQuery);
}
},
async getList(idOrFirstObjectSelector = {}, options = {}) {
getList(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getList(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getList(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getList(idOrFirstObjectSelector, options);
}
},
async getLists(selector = {}, options = {}, getQuery = false) {
getLists(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getLists(selector, options, getQuery);
return ReactiveCacheServer.getLists(selector, options, getQuery);
} else {
return ReactiveCacheClient.getLists(selector, options, getQuery);
}
},
async getSwimlane(idOrFirstObjectSelector = {}, options = {}) {
getSwimlane(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getSwimlane(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getSwimlane(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getSwimlane(idOrFirstObjectSelector, options);
}
},
async getSwimlanes(selector = {}, options = {}, getQuery = false) {
getSwimlanes(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getSwimlanes(selector, options, getQuery);
return ReactiveCacheServer.getSwimlanes(selector, options, getQuery);
} else {
return ReactiveCacheClient.getSwimlanes(selector, options, getQuery);
}
},
async getChecklist(idOrFirstObjectSelector = {}, options = {}) {
getChecklist(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getChecklist(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getChecklist(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getChecklist(idOrFirstObjectSelector, options);
}
},
async getChecklists(selector = {}, options = {}, getQuery = false) {
getChecklists(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getChecklists(selector, options, getQuery);
return ReactiveCacheServer.getChecklists(selector, options, getQuery);
} else {
return ReactiveCacheClient.getChecklists(selector, options, getQuery);
}
},
async getChecklistItem(idOrFirstObjectSelector = {}, options = {}) {
getChecklistItem(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getChecklistItem(
return ReactiveCacheServer.getChecklistItem(
idOrFirstObjectSelector,
options,
);
@ -1069,30 +1070,30 @@ ReactiveCache = {
);
}
},
async getChecklistItems(selector = {}, options = {}, getQuery = false) {
getChecklistItems(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getChecklistItems(selector, options, getQuery);
return ReactiveCacheServer.getChecklistItems(selector, options, getQuery);
} else {
return ReactiveCacheClient.getChecklistItems(selector, options, getQuery);
}
},
async getCard(idOrFirstObjectSelector = {}, options = {}, noCache = false) {
getCard(idOrFirstObjectSelector = {}, options = {}, noCache = false) {
if (Meteor.isServer || noCache === true) {
return await ReactiveCacheServer.getCard(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getCard(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getCard(idOrFirstObjectSelector, options);
}
},
async getCards(selector = {}, options = {}, getQuery = false) {
getCards(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getCards(selector, options, getQuery);
return ReactiveCacheServer.getCards(selector, options, getQuery);
} else {
return ReactiveCacheClient.getCards(selector, options, getQuery);
}
},
async getCardComment(idOrFirstObjectSelector = {}, options = {}) {
getCardComment(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getCardComment(
return ReactiveCacheServer.getCardComment(
idOrFirstObjectSelector,
options,
);
@ -1103,16 +1104,16 @@ ReactiveCache = {
);
}
},
async getCardComments(selector = {}, options = {}, getQuery = false) {
getCardComments(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getCardComments(selector, options, getQuery);
return ReactiveCacheServer.getCardComments(selector, options, getQuery);
} else {
return ReactiveCacheClient.getCardComments(selector, options, getQuery);
}
},
async getCardCommentReaction(idOrFirstObjectSelector = {}, options = {}) {
getCardCommentReaction(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getCardCommentReaction(
return ReactiveCacheServer.getCardCommentReaction(
idOrFirstObjectSelector,
options,
);
@ -1123,9 +1124,9 @@ ReactiveCache = {
);
}
},
async getCardCommentReactions(selector = {}, options = {}, getQuery = false) {
getCardCommentReactions(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getCardCommentReactions(
return ReactiveCacheServer.getCardCommentReactions(
selector,
options,
getQuery,
@ -1138,9 +1139,9 @@ ReactiveCache = {
);
}
},
async getCustomField(idOrFirstObjectSelector = {}, options = {}) {
getCustomField(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getCustomField(
return ReactiveCacheServer.getCustomField(
idOrFirstObjectSelector,
options,
);
@ -1151,142 +1152,142 @@ ReactiveCache = {
);
}
},
async getCustomFields(selector = {}, options = {}, getQuery = false) {
getCustomFields(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getCustomFields(selector, options, getQuery);
return ReactiveCacheServer.getCustomFields(selector, options, getQuery);
} else {
return ReactiveCacheClient.getCustomFields(selector, options, getQuery);
}
},
async getAttachment(idOrFirstObjectSelector = {}, options = {}) {
getAttachment(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getAttachment(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getAttachment(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getAttachment(idOrFirstObjectSelector, options);
}
},
async getAttachments(selector = {}, options = {}, getQuery = false) {
getAttachments(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getAttachments(selector, options, getQuery);
return ReactiveCacheServer.getAttachments(selector, options, getQuery);
} else {
return ReactiveCacheClient.getAttachments(selector, options, getQuery);
}
},
async getAvatar(idOrFirstObjectSelector = {}, options = {}) {
getAvatar(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getAvatar(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getAvatar(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getAvatar(idOrFirstObjectSelector, options);
}
},
async getAvatars(selector = {}, options = {}, getQuery = false) {
getAvatars(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getAvatars(selector, options, getQuery);
return ReactiveCacheServer.getAvatars(selector, options, getQuery);
} else {
return ReactiveCacheClient.getAvatars(selector, options, getQuery);
}
},
async getUser(idOrFirstObjectSelector = {}, options = {}) {
getUser(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getUser(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getUser(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getUser(idOrFirstObjectSelector, options);
}
},
async getUsers(selector = {}, options = {}, getQuery = false) {
getUsers(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getUsers(selector, options, getQuery);
return ReactiveCacheServer.getUsers(selector, options, getQuery);
} else {
return ReactiveCacheClient.getUsers(selector, options, getQuery);
}
},
async getOrg(idOrFirstObjectSelector = {}, options = {}) {
getOrg(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getOrg(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getOrg(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getOrg(idOrFirstObjectSelector, options);
}
},
async getOrgs(selector = {}, options = {}, getQuery = false) {
getOrgs(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getOrgs(selector, options, getQuery);
return ReactiveCacheServer.getOrgs(selector, options, getQuery);
} else {
return ReactiveCacheClient.getOrgs(selector, options, getQuery);
}
},
async getTeam(idOrFirstObjectSelector = {}, options = {}) {
getTeam(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getTeam(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getTeam(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getTeam(idOrFirstObjectSelector, options);
}
},
async getTeams(selector = {}, options = {}, getQuery = false) {
getTeams(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getTeams(selector, options, getQuery);
return ReactiveCacheServer.getTeams(selector, options, getQuery);
} else {
return ReactiveCacheClient.getTeams(selector, options, getQuery);
}
},
async getActivity(idOrFirstObjectSelector = {}, options = {}) {
getActivity(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getActivity(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getActivity(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getActivity(idOrFirstObjectSelector, options);
}
},
async getActivities(selector = {}, options = {}, getQuery = false) {
getActivities(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getActivities(selector, options, getQuery);
return ReactiveCacheServer.getActivities(selector, options, getQuery);
} else {
return ReactiveCacheClient.getActivities(selector, options, getQuery);
}
},
async getRule(idOrFirstObjectSelector = {}, options = {}) {
getRule(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getRule(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getRule(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getRule(idOrFirstObjectSelector, options);
}
},
async getRules(selector = {}, options = {}, getQuery = false) {
getRules(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getRules(selector, options, getQuery);
return ReactiveCacheServer.getRules(selector, options, getQuery);
} else {
return ReactiveCacheClient.getRules(selector, options, getQuery);
}
},
async getAction(idOrFirstObjectSelector = {}, options = {}) {
getAction(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getAction(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getAction(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getAction(idOrFirstObjectSelector, options);
}
},
async getActions(selector = {}, options = {}, getQuery = false) {
getActions(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getActions(selector, options, getQuery);
return ReactiveCacheServer.getActions(selector, options, getQuery);
} else {
return ReactiveCacheClient.getActions(selector, options, getQuery);
}
},
async getTrigger(idOrFirstObjectSelector = {}, options = {}) {
getTrigger(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getTrigger(idOrFirstObjectSelector, options);
return ReactiveCacheServer.getTrigger(idOrFirstObjectSelector, options);
} else {
return ReactiveCacheClient.getTrigger(idOrFirstObjectSelector, options);
}
},
async getTriggers(selector = {}, options = {}, getQuery = false) {
getTriggers(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getTriggers(selector, options, getQuery);
return ReactiveCacheServer.getTriggers(selector, options, getQuery);
} else {
return ReactiveCacheClient.getTriggers(selector, options, getQuery);
}
},
async getImpersonatedUser(idOrFirstObjectSelector = {}, options = {}) {
getImpersonatedUser(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getImpersonatedUser(
return ReactiveCacheServer.getImpersonatedUser(
idOrFirstObjectSelector,
options,
);
@ -1297,9 +1298,9 @@ ReactiveCache = {
);
}
},
async getImpersonatedUsers(selector = {}, options = {}, getQuery = false) {
getImpersonatedUsers(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getImpersonatedUsers(
return ReactiveCacheServer.getImpersonatedUsers(
selector,
options,
getQuery,
@ -1312,9 +1313,9 @@ ReactiveCache = {
);
}
},
async getIntegration(idOrFirstObjectSelector = {}, options = {}) {
getIntegration(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getIntegration(
return ReactiveCacheServer.getIntegration(
idOrFirstObjectSelector,
options,
);
@ -1325,27 +1326,27 @@ ReactiveCache = {
);
}
},
async getIntegrations(selector = {}, options = {}, getQuery = false) {
getIntegrations(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getIntegrations(selector, options, getQuery);
return ReactiveCacheServer.getIntegrations(selector, options, getQuery);
} else {
return ReactiveCacheClient.getIntegrations(selector, options, getQuery);
}
},
async getSessionData(idOrFirstObjectSelector = {}, options = {}) {
getSessionData(idOrFirstObjectSelector = {}, options = {}) {
// no reactive cache, otherwise global search will not work anymore
return await ReactiveCacheServer.getSessionData(
return ReactiveCacheServer.getSessionData(
idOrFirstObjectSelector,
options,
);
},
async getSessionDatas(selector = {}, options = {}, getQuery = false) {
getSessionDatas(selector = {}, options = {}, getQuery = false) {
// no reactive cache, otherwise global search will not work anymore
return await ReactiveCacheServer.getSessionDatas(selector, options, getQuery);
return ReactiveCacheServer.getSessionDatas(selector, options, getQuery);
},
async getInvitationCode(idOrFirstObjectSelector = {}, options = {}) {
getInvitationCode(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getInvitationCode(
return ReactiveCacheServer.getInvitationCode(
idOrFirstObjectSelector,
options,
);
@ -1356,30 +1357,30 @@ ReactiveCache = {
);
}
},
async getInvitationCodes(selector = {}, options = {}, getQuery = false) {
getInvitationCodes(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getInvitationCodes(selector, options, getQuery);
return ReactiveCacheServer.getInvitationCodes(selector, options, getQuery);
} else {
return ReactiveCacheClient.getInvitationCodes(selector, options, getQuery);
}
},
async getCurrentSetting() {
getCurrentSetting() {
if (Meteor.isServer) {
return await ReactiveCacheServer.getCurrentSetting();
return ReactiveCacheServer.getCurrentSetting();
} else {
return ReactiveCacheClient.getCurrentSetting();
}
},
async getCurrentUser() {
getCurrentUser() {
if (Meteor.isServer) {
return await ReactiveCacheServer.getCurrentUser();
return ReactiveCacheServer.getCurrentUser();
} else {
return ReactiveCacheClient.getCurrentUser();
}
},
async getTranslation(idOrFirstObjectSelector = {}, options = {}) {
getTranslation(idOrFirstObjectSelector = {}, options = {}) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getTranslation(
return ReactiveCacheServer.getTranslation(
idOrFirstObjectSelector,
options,
);
@ -1390,9 +1391,9 @@ ReactiveCache = {
);
}
},
async getTranslations(selector = {}, options = {}, getQuery = false) {
getTranslations(selector = {}, options = {}, getQuery = false) {
if (Meteor.isServer) {
return await ReactiveCacheServer.getTranslations(selector, options, getQuery);
return ReactiveCacheServer.getTranslations(selector, options, getQuery);
} else {
return ReactiveCacheClient.getTranslations(selector, options, getQuery);
}
@ -1401,41 +1402,41 @@ ReactiveCache = {
// Server isn't reactive, so search for the data always.
ReactiveMiniMongoIndexServer = {
getSubTasksWithParentId(parentId, addSelect = {}, options = {}) {
async getSubTasksWithParentId(parentId, addSelect = {}, options = {}) {
let ret = [];
if (parentId) {
ret = ReactiveCache.getCards({ parentId, ...addSelect }, options);
ret = await ReactiveCache.getCards({ parentId, ...addSelect }, options);
}
return ret;
},
getChecklistsWithCardId(cardId, addSelect = {}, options = {}) {
async getChecklistsWithCardId(cardId, addSelect = {}, options = {}) {
let ret = [];
if (cardId) {
ret = ReactiveCache.getChecklists({ cardId, ...addSelect }, options);
ret = await ReactiveCache.getChecklists({ cardId, ...addSelect }, options);
}
return ret;
},
getChecklistItemsWithChecklistId(checklistId, addSelect = {}, options = {}) {
async getChecklistItemsWithChecklistId(checklistId, addSelect = {}, options = {}) {
let ret = [];
if (checklistId) {
ret = ReactiveCache.getChecklistItems(
ret = await ReactiveCache.getChecklistItems(
{ checklistId, ...addSelect },
options,
);
}
return ret;
},
getCardCommentsWithCardId(cardId, addSelect = {}, options = {}) {
async getCardCommentsWithCardId(cardId, addSelect = {}, options = {}) {
let ret = [];
if (cardId) {
ret = ReactiveCache.getCardComments({ cardId, ...addSelect }, options);
ret = await ReactiveCache.getCardComments({ cardId, ...addSelect }, options);
}
return ret;
},
getActivityWithId(activityId, addSelect = {}, options = {}) {
async getActivityWithId(activityId, addSelect = {}, options = {}) {
let ret = [];
if (activityId) {
ret = ReactiveCache.getActivities(
ret = await ReactiveCache.getActivities(
{ _id: activityId, ...addSelect },
options,
);
@ -1507,12 +1508,6 @@ ReactiveMiniMongoIndexClient = {
}
ret = this.__checklistItemsWithId.get(EJSON.stringify(select));
if (ret) {
if (Meteor.isServer) {
ret[checklistId] = ReactiveCache.getChecklistItems(
{ checklistId: checklistId, ...addSelect },
options,
);
}
ret = ret[checklistId] || [];
}
}

View file

@ -13,54 +13,54 @@ import { ReactiveCache } from '/imports/reactiveCache';
Activities = new Mongo.Collection('activities');
Activities.helpers({
async board() {
return await ReactiveCache.getBoard(this.boardId);
board() {
return ReactiveCache.getBoard(this.boardId);
},
async oldBoard() {
return await ReactiveCache.getBoard(this.oldBoardId);
oldBoard() {
return ReactiveCache.getBoard(this.oldBoardId);
},
async user() {
return await ReactiveCache.getUser(this.userId);
user() {
return ReactiveCache.getUser(this.userId);
},
async member() {
return await ReactiveCache.getUser(this.memberId);
member() {
return ReactiveCache.getUser(this.memberId);
},
async list() {
return await ReactiveCache.getList(this.listId);
list() {
return ReactiveCache.getList(this.listId);
},
async swimlane() {
return await ReactiveCache.getSwimlane(this.swimlaneId);
swimlane() {
return ReactiveCache.getSwimlane(this.swimlaneId);
},
async oldSwimlane() {
return await ReactiveCache.getSwimlane(this.oldSwimlaneId);
oldSwimlane() {
return ReactiveCache.getSwimlane(this.oldSwimlaneId);
},
async oldList() {
return await ReactiveCache.getList(this.oldListId);
oldList() {
return ReactiveCache.getList(this.oldListId);
},
async card() {
return await ReactiveCache.getCard(this.cardId);
card() {
return ReactiveCache.getCard(this.cardId);
},
async comment() {
return await ReactiveCache.getCardComment(this.commentId);
comment() {
return ReactiveCache.getCardComment(this.commentId);
},
async attachment() {
return await ReactiveCache.getAttachment(this.attachmentId);
attachment() {
return ReactiveCache.getAttachment(this.attachmentId);
},
async checklist() {
return await ReactiveCache.getChecklist(this.checklistId);
checklist() {
return ReactiveCache.getChecklist(this.checklistId);
},
async checklistItem() {
return await ReactiveCache.getChecklistItem(this.checklistItemId);
checklistItem() {
return ReactiveCache.getChecklistItem(this.checklistItemId);
},
async subtasks() {
return await ReactiveCache.getCard(this.subtaskId);
subtasks() {
return ReactiveCache.getCard(this.subtaskId);
},
async customField() {
return await ReactiveCache.getCustomField(this.customFieldId);
customField() {
return ReactiveCache.getCustomField(this.customFieldId);
},
async label() {
label() {
// Label activity did not work yet, unable to edit labels when tried this.
return await ReactiveCache.getCard(this.labelId);
return ReactiveCache.getCard(this.labelId);
},
});

View file

@ -829,8 +829,8 @@ Boards.helpers({
},
async cards() {
const ret = await ReactiveCache.getCards(
cards() {
const ret = ReactiveCache.getCards(
{ boardId: this._id, archived: false },
{ sort: { title: 1 } },
);
@ -841,12 +841,12 @@ Boards.helpers({
return this.draggableLists();
},
async newestLists() {
newestLists() {
// sorted lists from newest to the oldest, by its creation date or its cards' last modification date
const user = await ReactiveCache.getCurrentUser();
const user = ReactiveCache.getCurrentUser();
const value = user._getListSortBy();
const sortKey = { starred: -1, [value[0]]: value[1] }; // [["starred",-1],value];
return await ReactiveCache.getLists(
return ReactiveCache.getLists(
{
boardId: this._id,
archived: false,
@ -855,8 +855,8 @@ Boards.helpers({
);
},
async draggableLists() {
return await ReactiveCache.getLists(
draggableLists() {
return ReactiveCache.getLists(
{
boardId: this._id,
},
@ -867,28 +867,28 @@ Boards.helpers({
/** returns the last list
* @returns Document the last list
*/
async getLastList() {
const ret = await ReactiveCache.getList({ boardId: this._id }, { sort: { sort: 'desc' } });
getLastList() {
const ret = ReactiveCache.getList({ boardId: this._id }, { sort: { sort: 'desc' } });
return ret;
},
async nullSortLists() {
return await ReactiveCache.getLists({
nullSortLists() {
return ReactiveCache.getLists({
boardId: this._id,
archived: false,
sort: { $eq: null },
});
},
async swimlanes() {
return await ReactiveCache.getSwimlanes(
swimlanes() {
return ReactiveCache.getSwimlanes(
{ boardId: this._id, archived: false },
{ sort: { sort: 1 } },
);
},
async nextSwimlane(swimlane) {
return await ReactiveCache.getSwimlane(
nextSwimlane(swimlane) {
return ReactiveCache.getSwimlane(
{
boardId: this._id,
archived: false,
@ -901,16 +901,16 @@ Boards.helpers({
);
},
async nullSortSwimlanes() {
return await ReactiveCache.getSwimlanes({
nullSortSwimlanes() {
return ReactiveCache.getSwimlanes({
boardId: this._id,
archived: false,
sort: { $eq: null },
});
},
async hasOvertimeCards() {
const card = await ReactiveCache.getCard({
hasOvertimeCards() {
const card = ReactiveCache.getCard({
isOvertime: true,
boardId: this._id,
archived: false,
@ -918,8 +918,8 @@ Boards.helpers({
return card !== undefined;
},
async hasSpentTimeCards() {
const card = await ReactiveCache.getCard({
hasSpentTimeCards() {
const card = ReactiveCache.getCard({
spentTime: { $gt: 0 },
boardId: this._id,
archived: false,
@ -927,20 +927,19 @@ Boards.helpers({
return card !== undefined;
},
async activities() {
activities() {
let linkedBoardId = [this._id];
const cards = await ReactiveCache.getCards({
ReactiveCache.getCards({
"type": "cardType-linkedBoard",
"boardId": this._id
});
for (const card of cards) {
}).forEach(card => {
linkedBoardId.push(card.linkedId);
}
const ret = await ReactiveCache.getActivities({ boardId: { $in: linkedBoardId } }, { sort: { createdAt: -1 } });
});
const ret = ReactiveCache.getActivities({ boardId: { $in: linkedBoardId } }, { sort: { createdAt: -1 } });
return ret;
},
async activeMembers(){
activeMembers(){
// Depend on the users collection for reactivity when users are loaded
const memberUserIds = _.pluck(this.members, 'userId');
// Use findOne with limit for reactivity trigger instead of count() which loads all users
@ -954,19 +953,14 @@ Boards.helpers({
return selected;
});
// Filter out members where user is not loaded
const filteredMembers = [];
for (const member of uniqueMembers) {
const user = await ReactiveCache.getUser(member.userId);
if (user !== undefined) {
filteredMembers.push(member);
}
}
const filteredMembers = uniqueMembers.filter(member => {
const user = ReactiveCache.getUser(member.userId);
return user !== undefined;
});
// Sort by role priority first (admin, normal, normal-assigned, no-comments, comment-only, comment-assigned, worker, read-only, read-assigned), then by fullname
// Build sort keys with async user lookup
const membersWithSortKey = [];
for (const member of filteredMembers) {
const user = await ReactiveCache.getUser(member.userId);
return _.sortBy(filteredMembers, member => {
const user = ReactiveCache.getUser(member.userId);
let rolePriority = 8; // Default for normal
if (member.isAdmin) rolePriority = 0;
@ -980,9 +974,8 @@ Boards.helpers({
else rolePriority = 1; // Normal
const fullname = user ? user.profile.fullname : '';
membersWithSortKey.push({ member, sortKey: rolePriority + '-' + fullname });
}
return _.sortBy(membersWithSortKey, 'sortKey').map(item => item.member);
return rolePriority + '-' + fullname;
});
},
activeOrgs() {
@ -1005,8 +998,8 @@ Boards.helpers({
return _.where(this.members, { isActive: true, isAdmin: true });
},
async memberUsers() {
return await ReactiveCache.getUsers({ _id: { $in: _.pluck(this.members, 'userId') } });
memberUsers() {
return ReactiveCache.getUsers({ _id: { $in: _.pluck(this.members, 'userId') } });
},
getLabel(name, color) {
@ -1126,8 +1119,8 @@ Boards.helpers({
return `board-color-${this.color}`;
},
async customFields() {
const ret = await ReactiveCache.getCustomFields(
customFields() {
const ret = ReactiveCache.getCustomFields(
{ boardIds: { $in: [this._id] } },
{ sort: { name: 1 } },
);
@ -1156,7 +1149,7 @@ Boards.helpers({
}
},
async searchBoards(term) {
searchBoards(term) {
check(term, Match.OneOf(String, null, undefined));
const query = { boardId: this._id };
@ -1171,11 +1164,11 @@ Boards.helpers({
query.$or = [{ title: regex }, { description: regex }];
}
const ret = await ReactiveCache.getCards(query, projection);
const ret = ReactiveCache.getCards(query, projection);
return ret;
},
async searchSwimlanes(term) {
searchSwimlanes(term) {
check(term, Match.OneOf(String, null, undefined));
const query = { boardId: this._id };
@ -1193,10 +1186,10 @@ Boards.helpers({
query.$or = [{ title: regex }, { description: regex }];
}
return await ReactiveCache.getSwimlanes(query, projection);
return ReactiveCache.getSwimlanes(query, projection);
},
async searchLists(term) {
searchLists(term) {
let ret = null;
if (term) {
check(term, Match.OneOf(String));
@ -1218,12 +1211,12 @@ Boards.helpers({
query.$or = [{ title: regex }, { description: regex }];
}
ret = await ReactiveCache.getLists(query, projection);
ret = ReactiveCache.getLists(query, projection);
}
return ret;
},
async searchCards(term, excludeLinked) {
searchCards(term, excludeLinked) {
let ret = null;
if (term) {
check(term, Match.OneOf(String));
@ -1249,7 +1242,7 @@ Boards.helpers({
{ description: regex },
{ customFields: { $elemMatch: { value: regex } } },
];
ret = await ReactiveCache.getCards(query, projection);
ret = ReactiveCache.getCards(query, projection);
}
return ret;
},
@ -1283,8 +1276,8 @@ Boards.helpers({
return this.subtasksDefaultBoardId;
},
async getDefaultSubtasksBoard() {
return await ReactiveCache.getBoard(this.getDefaultSubtasksBoardId());
getDefaultSubtasksBoard() {
return ReactiveCache.getBoard(this.getDefaultSubtasksBoardId());
},
//Date Settings option such as received date, start date and so on.
@ -1316,8 +1309,8 @@ Boards.helpers({
return this.dateSettingsDefaultBoardId;
},
async getDefaultDateSettingsBoard() {
return await ReactiveCache.getBoard(this.getDefaultDateSettingsBoardId());
getDefaultDateSettingsBoard() {
return ReactiveCache.getBoard(this.getDefaultDateSettingsBoardId());
},
getDefaultSubtasksListId() {
@ -1335,8 +1328,8 @@ Boards.helpers({
return this.subtasksDefaultListId;
},
async getDefaultSubtasksList() {
return await ReactiveCache.getList(this.getDefaultSubtasksListId());
getDefaultSubtasksList() {
return ReactiveCache.getList(this.getDefaultSubtasksListId());
},
getDefaultDateSettingsListId() {
@ -1354,15 +1347,15 @@ Boards.helpers({
return this.dateSettingsDefaultListId;
},
async getDefaultDateSettingsList() {
return await ReactiveCache.getList(this.getDefaultDateSettingsListId());
getDefaultDateSettingsList() {
return ReactiveCache.getList(this.getDefaultDateSettingsListId());
},
async getDefaultSwimline() {
let result = await ReactiveCache.getSwimlane({ boardId: this._id });
getDefaultSwimline() {
let result = ReactiveCache.getSwimlane({ boardId: this._id });
if (result === undefined) {
// Check if any swimlane exists for this board to avoid duplicates
const existingSwimlanes = await ReactiveCache.getSwimlanes({ boardId: this._id });
const existingSwimlanes = ReactiveCache.getSwimlanes({ boardId: this._id });
if (existingSwimlanes.length > 0) {
// Use the first existing swimlane
result = existingSwimlanes[0];
@ -1373,14 +1366,14 @@ Boards.helpers({
title: title,
boardId: this._id,
});
result = await ReactiveCache.getSwimlane({ boardId: this._id });
result = ReactiveCache.getSwimlane({ boardId: this._id });
}
}
return result;
},
async getNextCardNumber() {
const boardCards = await ReactiveCache.getCard(
getNextCardNumber() {
const boardCards = ReactiveCache.getCard(
{
boardId: this._id
},
@ -1399,16 +1392,16 @@ Boards.helpers({
return maxCardNr + 1;
},
async cardsDueInBetween(start, end) {
const ret = await ReactiveCache.getCards({
cardsDueInBetween(start, end) {
const ret = ReactiveCache.getCards({
boardId: this._id,
dueAt: { $gte: start, $lte: end },
});
return ret;
},
async cardsInInterval(start, end) {
const ret = await ReactiveCache.getCards({
cardsInInterval(start, end) {
const ret = ReactiveCache.getCards({
boardId: this._id,
$or: [
{
@ -1756,7 +1749,9 @@ Boards.uniqueTitle = async title => {
return title;
};
Boards.userSearch = async (
// Non-async: returns data on client, Promise on server.
// Server callers must await.
Boards.userSearch = (
userId,
selector = {},
projection = {},
@ -1770,36 +1765,44 @@ Boards.userSearch = async (
if (userId) {
selector.$or.push({ members: { $elemMatch: { userId, isActive: true } } });
}
const ret = await ReactiveCache.getBoards(selector, projection);
return ret;
return ReactiveCache.getBoards(selector, projection);
};
Boards.userBoards = async (
// Non-async: returns data on client (for Blaze templates), Promise on server.
// Server callers must await.
Boards.userBoards = (
userId,
archived = false,
selector = {},
projection = {},
) => {
const user = await ReactiveCache.getUser(userId);
if (!user) {
return [];
}
const _buildSelector = (user) => {
if (!user) return null;
if (typeof archived === 'boolean') {
selector.archived = archived;
}
if (!selector.type) {
selector.type = 'board';
}
selector.$or = [
{ permission: 'public' },
{ members: { $elemMatch: { userId, isActive: true } } },
{ orgs: { $elemMatch: { orgId: { $in: user.orgIds() }, isActive: true } } },
{ teams: { $elemMatch: { teamId: { $in: user.teamIds() }, isActive: true } } },
];
return selector;
};
if (typeof archived === 'boolean') {
selector.archived = archived;
if (Meteor.isServer) {
return (async () => {
const user = await ReactiveCache.getUser(userId);
if (!_buildSelector(user)) return [];
return await ReactiveCache.getBoards(selector, projection);
})();
}
if (!selector.type) {
selector.type = 'board';
}
selector.$or = [
{ permission: 'public' },
{ members: { $elemMatch: { userId, isActive: true } } },
{ orgs: { $elemMatch: { orgId: { $in: user.orgIds() }, isActive: true } } },
{ teams: { $elemMatch: { teamId: { $in: user.teamIds() }, isActive: true } } },
];
return await ReactiveCache.getBoards(selector, projection);
const user = ReactiveCache.getUser(userId);
if (!_buildSelector(user)) return [];
return ReactiveCache.getBoards(selector, projection);
};
Boards.userBoardIds = async (userId, archived = false, selector = {}) => {

View file

@ -101,21 +101,21 @@ CardComments.helpers({
CardComments.insert(this);
},
async user() {
return await ReactiveCache.getUser(this.userId);
user() {
return ReactiveCache.getUser(this.userId);
},
async reactions() {
const cardCommentReactions = await ReactiveCache.getCardCommentReaction({cardCommentId: this._id});
reactions() {
const cardCommentReactions = ReactiveCache.getCardCommentReaction({cardCommentId: this._id});
return !!cardCommentReactions ? cardCommentReactions.reactions : [];
},
async toggleReaction(reactionCodepoint) {
toggleReaction(reactionCodepoint) {
if (reactionCodepoint !== sanitizeText(reactionCodepoint)) {
return false;
} else {
const cardCommentReactions = await ReactiveCache.getCardCommentReaction({cardCommentId: this._id});
const cardCommentReactions = ReactiveCache.getCardCommentReaction({cardCommentId: this._id});
const reactions = !!cardCommentReactions ? cardCommentReactions.reactions : [];
const userId = Meteor.userId();
const reaction = reactions.find(r => r.reactionCodepoint === reactionCodepoint);

View file

@ -701,16 +701,16 @@ Cards.helpers({
return Cards.insert(linkCard);
},
async list() {
return await ReactiveCache.getList(this.listId);
list() {
return ReactiveCache.getList(this.listId);
},
async swimlane() {
return await ReactiveCache.getSwimlane(this.swimlaneId);
swimlane() {
return ReactiveCache.getSwimlane(this.swimlaneId);
},
async board() {
const ret = await ReactiveCache.getBoard(this.boardId);
board() {
const ret = ReactiveCache.getBoard(this.boardId);
return ret;
},
@ -725,8 +725,8 @@ Cards.helpers({
return this.__id;
},
async getList() {
const list = await this.list();
getList() {
const list = this.list();
if (!list) {
return {
_id: this.listId,
@ -738,8 +738,8 @@ Cards.helpers({
return list;
},
async getSwimlane() {
const swimlane = await this.swimlane();
getSwimlane() {
const swimlane = this.swimlane();
if (!swimlane) {
return {
_id: this.swimlaneId,
@ -751,8 +751,8 @@ Cards.helpers({
return swimlane;
},
async getBoard() {
const board = await this.board();
getBoard() {
const board = this.board();
if (!board) {
return {
_id: this.boardId,
@ -764,9 +764,8 @@ Cards.helpers({
return board;
},
async labels() {
const board = await this.board();
const boardLabels = board.labels;
labels() {
const boardLabels = this.board().labels;
const cardLabels = _.filter(boardLabels, label => {
return _.contains(this.labelIds, label._id);
});
@ -782,7 +781,7 @@ Cards.helpers({
* @param swimlaneId a swimlane id
* top sorting of the card at the top if true, or from the bottom if false
*/
async getSort(listId, swimlaneId, top) {
getSort(listId, swimlaneId, top) {
if (!_.isBoolean(top)) {
top = true;
}
@ -798,7 +797,7 @@ Cards.helpers({
archived: false,
};
const sorting = top ? 1 : -1;
const card = await ReactiveCache.getCard(selector, { sort: { sort: sorting } }, true);
const card = ReactiveCache.getCard(selector, { sort: { sort: sorting } }, true);
let ret = null
if (card) {
ret = card.sort;
@ -810,8 +809,8 @@ Cards.helpers({
* @param listId a list id
* @param swimlaneId a swimlane id
*/
async getMinSort(listId, swimlaneId) {
const ret = await this.getSort(listId, swimlaneId, true);
getMinSort(listId, swimlaneId) {
const ret = this.getSort(listId, swimlaneId, true);
return ret;
},
@ -819,40 +818,40 @@ Cards.helpers({
* @param listId a list id
* @param swimlaneId a swimlane id
*/
async getMaxSort(listId, swimlaneId) {
const ret = await this.getSort(listId, swimlaneId, false);
getMaxSort(listId, swimlaneId) {
const ret = this.getSort(listId, swimlaneId, false);
return ret;
},
async user() {
return await ReactiveCache.getUser(this.userId);
user() {
return ReactiveCache.getUser(this.userId);
},
async isAssigned(memberId) {
return _.contains(await this.getMembers(), memberId);
isAssigned(memberId) {
return _.contains(this.getMembers(), memberId);
},
async isAssignee(assigneeId) {
return _.contains(await this.getAssignees(), assigneeId);
isAssignee(assigneeId) {
return _.contains(this.getAssignees(), assigneeId);
},
async activities() {
activities() {
let ret;
if (this.isLinkedBoard()) {
ret = await ReactiveCache.getActivities(
ret = ReactiveCache.getActivities(
{ boardId: this.linkedId },
{ sort: { createdAt: -1 } },
);
} else {
ret = await ReactiveCache.getActivities({ cardId: this.getRealId() }, { sort: { createdAt: -1 } });
ret = ReactiveCache.getActivities({ cardId: this.getRealId() }, { sort: { createdAt: -1 } });
}
return ret;
},
async comments() {
comments() {
let ret
if (this.isLinkedBoard()) {
ret = await ReactiveCache.getCardComments(
ret = ReactiveCache.getCardComments(
{ boardId: this.linkedId },
{ sort: { createdAt: -1 } },
);
@ -866,18 +865,18 @@ Cards.helpers({
return ret;
},
async attachments() {
const ret = (await ReactiveCache.getAttachments(
attachments() {
const ret = ReactiveCache.getAttachments(
{ 'meta.cardId': this.getRealId() },
{ sort: { uploadedAt: -1 } },
true,
)).each();
).each();
return ret;
},
async cover() {
cover() {
if (!this.coverId) return false;
const cover = await ReactiveCache.getAttachment(this.coverId);
const cover = ReactiveCache.getAttachment(this.coverId);
// if we return a cover before it is fully stored, we will get errors when we try to display it
// todo XXX we could return a default "upload pending" image in the meantime?
return cover && cover.link() && cover;
@ -983,9 +982,9 @@ Cards.helpers({
},
// customFields with definitions
async customFieldsWD() {
customFieldsWD() {
// get all definitions
const definitions = await ReactiveCache.getCustomFields({
const definitions = ReactiveCache.getCustomFields({
boardIds: { $in: [this.boardId] },
});
if (!definitions) {

View file

@ -163,7 +163,10 @@ async function publishChekListCompleted(userId, doc) {
const boardId = card.boardId;
const checklistId = doc.checklistId;
const checkList = await ReactiveCache.getChecklist(checklistId);
if (checkList.isFinished()) {
const checklistItems = await ReactiveCache.getChecklistItems({ checklistId });
const isChecklistFinished = checkList.hideAllChecklistItems ||
(checklistItems.length > 0 && checklistItems.length === checklistItems.filter(i => i.isFinished).length);
if (isChecklistFinished) {
const act = {
userId,
activityType: 'completeChecklist',
@ -187,7 +190,7 @@ async function publishChekListUncompleted(userId, doc) {
// Currently in checklist all are set as uncompleted/not checked,
// IFTTT Rule does not move card to other list.
// If following line is negated/changed to:
// if(!checkList.isFinished()){
// if(!isChecklistFinished){
// then unchecking of any checkbox will move card to other list,
// even when all checkboxes are not yet unchecked.
// What is correct code for only moving when all in list is unchecked?
@ -196,7 +199,10 @@ async function publishChekListUncompleted(userId, doc) {
// find . | xargs grep 'count' -sl | grep -v .meteor | grep -v node_modules | grep -v .build
// Maybe something related here?
// wekan/client/components/rules/triggers/checklistTriggers.js
if (checkList.isFinished()) {
const uncheckItems = await ReactiveCache.getChecklistItems({ checklistId });
const isChecklistFinished = checkList.hideAllChecklistItems ||
(uncheckItems.length > 0 && uncheckItems.length === uncheckItems.filter(i => i.isFinished).length);
if (isChecklistFinished) {
const act = {
userId,
activityType: 'uncompleteChecklist',

View file

@ -161,9 +161,8 @@ Checklists.helpers({
await item.uncheck();
}
},
async itemIndex(itemId) {
const checklist = await ReactiveCache.getChecklist({ _id: this._id });
const items = checklist.items;
itemIndex(itemId) {
const items = ReactiveCache.getChecklist({ _id: this._id }).items;
return _.pluck(items, '_id').indexOf(itemId);
},

View file

@ -55,8 +55,8 @@ InvitationCodes.attachSchema(
);
InvitationCodes.helpers({
async author() {
return await ReactiveCache.getUser(this.authorId);
author() {
return ReactiveCache.getUser(this.authorId);
},
});

View file

@ -259,37 +259,37 @@ Lists.helpers({
}
},
async cards(swimlaneId) {
cards(swimlaneId) {
const selector = {
listId: this._id,
archived: false,
};
if (swimlaneId) selector.swimlaneId = swimlaneId;
const ret = await ReactiveCache.getCards(Filter.mongoSelector(selector), { sort: ['sort'] });
const ret = ReactiveCache.getCards(Filter.mongoSelector(selector), { sort: ['sort'] });
return ret;
},
async cardsUnfiltered(swimlaneId) {
cardsUnfiltered(swimlaneId) {
const selector = {
listId: this._id,
archived: false,
};
if (swimlaneId) selector.swimlaneId = swimlaneId;
const ret = await ReactiveCache.getCards(selector, { sort: ['sort'] });
const ret = ReactiveCache.getCards(selector, { sort: ['sort'] });
return ret;
},
async allCards() {
const ret = await ReactiveCache.getCards({ listId: this._id });
allCards() {
const ret = ReactiveCache.getCards({ listId: this._id });
return ret;
},
async board() {
return await ReactiveCache.getBoard(this.boardId);
board() {
return ReactiveCache.getBoard(this.boardId);
},
async getWipLimit(option) {
const list = await ReactiveCache.getList(this._id);
getWipLimit(option) {
const list = ReactiveCache.getList(this._id);
if (!list.wipLimit) {
// Necessary check to avoid exceptions for the case where the doc doesn't have the wipLimit field yet set
return 0;
@ -313,9 +313,9 @@ Lists.helpers({
return this.starred === true;
},
async isCollapsed() {
isCollapsed() {
if (Meteor.isClient) {
const user = await ReactiveCache.getCurrentUser();
const user = ReactiveCache.getCurrentUser();
// Logged-in users: prefer profile/cookie-backed state
if (user && user.getCollapsedListFromStorage) {
const stored = user.getCollapsedListFromStorage(this.boardId, this._id);
@ -334,13 +334,13 @@ Lists.helpers({
return this.collapsed === true;
},
async absoluteUrl() {
const card = await ReactiveCache.getCard({ listId: this._id });
return card && (await card.absoluteUrl());
absoluteUrl() {
const card = ReactiveCache.getCard({ listId: this._id });
return card && card.absoluteUrl();
},
async originRelativeUrl() {
const card = await ReactiveCache.getCard({ listId: this._id });
return card && (await card.originRelativeUrl());
originRelativeUrl() {
const card = ReactiveCache.getCard({ listId: this._id });
return card && card.originRelativeUrl();
},
async remove() {
return await Lists.removeAsync({ _id: this._id });
@ -492,7 +492,7 @@ Meteor.methods({
// my lists
const lists = await ReactiveCache.getLists(
{
boardId: { $in: Boards.userBoardIds(this.userId) },
boardId: { $in: await Boards.userBoardIds(this.userId) },
archived: false,
},
{

View file

@ -54,20 +54,20 @@ Rules.helpers({
async rename(description) {
return await Rules.updateAsync(this._id, { $set: { description } });
},
async getAction() {
return await ReactiveCache.getAction(this.actionId);
getAction() {
return ReactiveCache.getAction(this.actionId);
},
async getTrigger() {
return await ReactiveCache.getTrigger(this.triggerId);
getTrigger() {
return ReactiveCache.getTrigger(this.triggerId);
},
async board() {
return await ReactiveCache.getBoard(this.boardId);
board() {
return ReactiveCache.getBoard(this.boardId);
},
async trigger() {
return await ReactiveCache.getTrigger(this.triggerId);
trigger() {
return ReactiveCache.getTrigger(this.triggerId);
},
async action() {
return await ReactiveCache.getAction(this.actionId);
action() {
return ReactiveCache.getAction(this.actionId);
},
});

View file

@ -215,8 +215,8 @@ Swimlanes.helpers({
(await this.board()).getDefaultSwimline();
},
async cards() {
const ret = await ReactiveCache.getCards(
cards() {
const ret = ReactiveCache.getCards(
Filter.mongoSelector({
swimlaneId: this._id,
archived: false,
@ -226,12 +226,12 @@ Swimlanes.helpers({
return ret;
},
async lists() {
return await this.draggableLists();
lists() {
return this.draggableLists();
},
async newestLists() {
newestLists() {
// Revert to shared lists across swimlanes: filter by board only
return await ReactiveCache.getLists(
return ReactiveCache.getLists(
{
boardId: this.boardId,
archived: false,
@ -239,9 +239,9 @@ Swimlanes.helpers({
{ sort: { modifiedAt: -1 } },
);
},
async draggableLists() {
draggableLists() {
// Revert to shared lists across swimlanes: filter by board only
return await ReactiveCache.getLists(
return ReactiveCache.getLists(
{
boardId: this.boardId,
//archived: false,
@ -250,9 +250,9 @@ Swimlanes.helpers({
);
},
async myLists() {
myLists() {
// Return per-swimlane lists: provide lists specific to this swimlane
return await ReactiveCache.getLists(
return ReactiveCache.getLists(
{
boardId: this.boardId,
swimlaneId: this._id,
@ -262,14 +262,14 @@ Swimlanes.helpers({
);
},
async allCards() {
const ret = await ReactiveCache.getCards({ swimlaneId: this._id });
allCards() {
const ret = ReactiveCache.getCards({ swimlaneId: this._id });
return ret;
},
async isCollapsed() {
isCollapsed() {
if (Meteor.isClient) {
const user = await ReactiveCache.getCurrentUser();
const user = ReactiveCache.getCurrentUser();
if (user && user.getCollapsedSwimlaneFromStorage) {
const stored = user.getCollapsedSwimlaneFromStorage(this.boardId, this._id);
if (typeof stored === 'boolean') {
@ -286,8 +286,8 @@ Swimlanes.helpers({
return this.collapsed === true;
},
async board() {
return await ReactiveCache.getBoard(this.boardId);
board() {
return ReactiveCache.getBoard(this.boardId);
},
colorClass() {
@ -303,18 +303,18 @@ Swimlanes.helpers({
return this.type === 'template-container';
},
async isListTemplatesSwimlane() {
const user = await ReactiveCache.getCurrentUser();
isListTemplatesSwimlane() {
const user = ReactiveCache.getCurrentUser();
return (user.profile || {}).listTemplatesSwimlaneId === this._id;
},
async isCardTemplatesSwimlane() {
const user = await ReactiveCache.getCurrentUser();
isCardTemplatesSwimlane() {
const user = ReactiveCache.getCurrentUser();
return (user.profile || {}).cardTemplatesSwimlaneId === this._id;
},
async isBoardTemplatesSwimlane() {
const user = await ReactiveCache.getCurrentUser();
isBoardTemplatesSwimlane() {
const user = ReactiveCache.getCurrentUser();
return (user.profile || {}).boardTemplatesSwimlaneId === this._id;
},

View file

@ -181,7 +181,7 @@ export class TrelloCreator {
}
// You must call parseActions before calling this one.
createBoardAndLabels(trelloBoard) {
async createBoardAndLabels(trelloBoard) {
let color = 'blue';
if (this.getColor(trelloBoard.prefs.background) !== undefined) {
color = this.getColor(trelloBoard.prefs.background);
@ -207,7 +207,7 @@ export class TrelloCreator {
permission: this.getPermission(trelloBoard.prefs.permissionLevel),
slug: getSlug(trelloBoard.name) || 'board',
stars: 0,
title: Boards.uniqueTitle(trelloBoard.name),
title: await Boards.uniqueTitle(trelloBoard.name),
};
// now add other members
if (trelloBoard.memberships) {
@ -779,7 +779,7 @@ export class TrelloCreator {
await currentBoard.archive();
}
this.parseActions(board.actions);
const boardId = this.createBoardAndLabels(board);
const boardId = await this.createBoardAndLabels(board);
this.createLists(board.lists, boardId);
this.createSwimlanes(boardId);
this.createCards(board.cards, boardId);

View file

@ -36,20 +36,20 @@ Triggers.helpers({
return this.desc;
},
async getRule() {
return await ReactiveCache.getRule({ triggerId: this._id });
getRule() {
return ReactiveCache.getRule({ triggerId: this._id });
},
async fromList() {
return await ReactiveCache.getList(this.fromId);
fromList() {
return ReactiveCache.getList(this.fromId);
},
async toList() {
return await ReactiveCache.getList(this.toId);
toList() {
return ReactiveCache.getList(this.toId);
},
async findList(title) {
return await ReactiveCache.getList({
findList(title) {
return ReactiveCache.getList({
title,
});
},

View file

@ -902,10 +902,10 @@ if (Meteor.isClient) {
return board && board.hasWorker(this._id);
},
async isBoardAdmin(boardId) {
isBoardAdmin(boardId) {
let board;
if (boardId) {
board = await ReactiveCache.getBoard(boardId);
board = ReactiveCache.getBoard(boardId);
} else {
board = Utils.getCurrentBoard();
}

View file

@ -280,7 +280,7 @@ export class WekanCreator {
}
// You must call parseActions before calling this one.
createBoardAndLabels(boardToImport) {
async createBoardAndLabels(boardToImport) {
const boardToCreate = {
archived: boardToImport.archived,
color: boardToImport.color,
@ -304,7 +304,7 @@ export class WekanCreator {
permission: boardToImport.permission,
slug: getSlug(boardToImport.title) || 'board',
stars: 0,
title: Boards.uniqueTitle(boardToImport.title),
title: await Boards.uniqueTitle(boardToImport.title),
};
// now add other members
if (boardToImport.members) {
@ -982,7 +982,7 @@ export class WekanCreator {
await currentBoard.archive();
}
this.parseActivities(board);
const boardId = this.createBoardAndLabels(board);
const boardId = await this.createBoardAndLabels(board);
this.createLists(board.lists, boardId);
this.createSwimlanes(board.swimlanes, boardId);
this.createCustomFields(board.customFields, boardId);

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@
"plugins": [
"meteor"
],
"parser": "babel-eslint",
"parser": "@babel/eslint-parser",
"rules": {
"meteor/audit-argument-checks": 0,
"import/no-extraneous-dependencies": 0,
@ -22,18 +22,19 @@
}
},
"dependencies": {
"@babel/runtime": "^7.1.5",
"meteor-node-stubs": "0.4.1",
"@babel/runtime": "^7.26.0",
"meteor-node-stubs": "^1.2.13",
"meteor-reactive-cache": "^1.0.1"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "5.9.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-meteor": "5.1.0",
"@babel/core": "^7.26.0",
"@babel/eslint-parser": "^7.25.9",
"chai": "^4.5.0",
"eslint": "^8.57.1",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-meteor": "^7.3.0",
"lodash.isequal": "^4.5.0",
"mocha": "^5.2.0",
"nightmare": "3.0.1"
"mocha": "^10.8.2"
}
}

View file

@ -20,7 +20,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const swimlane = Swimlanes.findOne(swimlaneId);
const swimlane = await Swimlanes.findOneAsync(swimlaneId);
if (!swimlane) {
throw new Meteor.Error('swimlane-not-found', 'Swimlane not found');
}
@ -43,7 +43,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const list = Lists.findOne(listId);
const list = await Lists.findOneAsync(listId);
if (!list) {
throw new Meteor.Error('list-not-found', 'List not found');
}
@ -66,7 +66,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const card = Cards.findOne(cardId);
const card = await Cards.findOneAsync(cardId);
if (!card) {
throw new Meteor.Error('card-not-found', 'Card not found');
}
@ -89,7 +89,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const swimlane = Swimlanes.findOne(swimlaneId);
const swimlane = await Swimlanes.findOneAsync(swimlaneId);
if (!swimlane) {
throw new Meteor.Error('swimlane-not-found', 'Swimlane not found');
}
@ -112,7 +112,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const list = Lists.findOne(listId);
const list = await Lists.findOneAsync(listId);
if (!list) {
throw new Meteor.Error('list-not-found', 'List not found');
}
@ -135,7 +135,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const card = Cards.findOne(cardId);
const card = await Cards.findOneAsync(cardId);
if (!card) {
throw new Meteor.Error('card-not-found', 'Card not found');
}
@ -158,7 +158,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const swimlane = Swimlanes.findOne(swimlaneId);
const swimlane = await Swimlanes.findOneAsync(swimlaneId);
if (!swimlane) {
throw new Meteor.Error('swimlane-not-found', 'Swimlane not found');
}
@ -181,7 +181,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const list = Lists.findOne(listId);
const list = await Lists.findOneAsync(listId);
if (!list) {
throw new Meteor.Error('list-not-found', 'List not found');
}
@ -204,7 +204,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const card = Cards.findOne(cardId);
const card = await Cards.findOneAsync(cardId);
if (!card) {
throw new Meteor.Error('card-not-found', 'Card not found');
}
@ -227,7 +227,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const swimlane = Swimlanes.findOne(swimlaneId);
const swimlane = await Swimlanes.findOneAsync(swimlaneId);
if (!swimlane) {
throw new Meteor.Error('swimlane-not-found', 'Swimlane not found');
}
@ -250,7 +250,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const list = Lists.findOne(listId);
const list = await Lists.findOneAsync(listId);
if (!list) {
throw new Meteor.Error('list-not-found', 'List not found');
}
@ -273,7 +273,7 @@ Meteor.methods({
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const card = Cards.findOne(cardId);
const card = await Cards.findOneAsync(cardId);
if (!card) {
throw new Meteor.Error('card-not-found', 'Card not found');
}
@ -305,7 +305,7 @@ Meteor.methods({
boardId: boardId,
}, {
sort: { createdAt: -1 }
}).fetch();
}).fetchAsync();
},
/**
@ -333,6 +333,6 @@ Meteor.methods({
entityType: entityType,
}, {
sort: { createdAt: -1 }
}).fetch();
}).fetchAsync();
},
});

View file

@ -22,7 +22,7 @@ publishComposite('boards', function() {
return await ReactiveCache.getBoards(
{
archived: false,
_id: { $in: Boards.userBoardIds(userId, false) },
_id: { $in: await Boards.userBoardIds(userId, false) },
},
{
sort: { sort: 1 /* boards default sorting */ },
@ -82,7 +82,7 @@ Meteor.publish('boardsReport', async function() {
const boards = await ReactiveCache.getBoards(
{
_id: { $in: Boards.userBoardIds(userId, null) },
_id: { $in: await Boards.userBoardIds(userId, null) },
},
{
fields: {
@ -142,7 +142,7 @@ Meteor.publish('archivedBoards', async function() {
const ret = await ReactiveCache.getBoards(
{
_id: { $in: Boards.userBoardIds(userId, true)},
_id: { $in: await Boards.userBoardIds(userId, true)},
archived: true,
members: {
$elemMatch: {

View file

@ -387,13 +387,13 @@ async function buildSelector(queryParams) {
if (archived !== null) {
if (archived) {
selector.boardId = {
$in: Boards.userBoardIds(userId, null, boardsSelector),
$in: await Boards.userBoardIds(userId, null, boardsSelector),
};
selector.$and.push({
$or: [
{
boardId: {
$in: Boards.userBoardIds(userId, archived, boardsSelector),
$in: await Boards.userBoardIds(userId, archived, boardsSelector),
},
},
{ swimlaneId: { $in: Swimlanes.userArchivedSwimlaneIds(userId) } },
@ -403,14 +403,14 @@ async function buildSelector(queryParams) {
});
} else {
selector.boardId = {
$in: Boards.userBoardIds(userId, false, boardsSelector),
$in: await Boards.userBoardIds(userId, false, boardsSelector),
};
selector.swimlaneId = { $nin: Swimlanes.archivedSwimlaneIds() };
selector.listId = { $nin: Lists.archivedListIds() };
selector.archived = false;
}
} else {
const userBoardIds = Boards.userBoardIds(userId, null, boardsSelector);
const userBoardIds = await Boards.userBoardIds(userId, null, boardsSelector);
if (process.env.DEBUG === 'true') {
console.log('buildSelector - userBoardIds:', userBoardIds);
}
@ -424,8 +424,8 @@ async function buildSelector(queryParams) {
if (queryParams.hasOperator(OPERATOR_BOARD)) {
const queryBoards = [];
queryParams.getPredicates(OPERATOR_BOARD).forEach(query => {
const boards = Boards.userSearch(userId, {
for (const query of queryParams.getPredicates(OPERATOR_BOARD)) {
const boards = await Boards.userSearch(userId, {
title: new RegExp(escapeForRegex(query), 'i'),
});
if (boards.length) {
@ -435,7 +435,7 @@ async function buildSelector(queryParams) {
} else {
errors.addNotFound(OPERATOR_BOARD, query);
}
});
}
selector.boardId.$in = queryBoards;
}
@ -550,17 +550,13 @@ async function buildSelector(queryParams) {
if (queryParams.hasOperator(OPERATOR_LABEL)) {
const queryLabels = [];
queryParams.getPredicates(OPERATOR_LABEL).forEach(label => {
let boards = Boards.userBoards(userId, null, {
for (const label of queryParams.getPredicates(OPERATOR_LABEL)) {
let boards = await Boards.userBoards(userId, null, {
labels: { $elemMatch: { color: label.toLowerCase() } },
});
if (boards.length) {
boards.forEach(board => {
// eslint-disable-next-line no-console
// console.log('board:', board);
// eslint-disable-next-line no-console
// console.log('board.labels:', board.labels);
board.labels
.filter(boardLabel => {
return boardLabel.color === label.toLowerCase();
@ -570,12 +566,8 @@ async function buildSelector(queryParams) {
});
});
} else {
// eslint-disable-next-line no-console
// console.log('label:', label);
const reLabel = new RegExp(escapeForRegex(label), 'i');
// eslint-disable-next-line no-console
// console.log('reLabel:', reLabel);
boards = Boards.userBoards(userId, null, {
boards = await Boards.userBoards(userId, null, {
labels: { $elemMatch: { name: reLabel } },
});
@ -596,7 +588,7 @@ async function buildSelector(queryParams) {
errors.addNotFound(OPERATOR_LABEL, label);
}
}
});
}
if (queryLabels.length) {
// eslint-disable-next-line no-console
// console.log('queryLabels:', queryLabels);

View file

@ -340,13 +340,14 @@ RulesHelper = {
sort: 0,
});
const itemsArray = action.checklistItems.split(',');
const checkList = await ReactiveCache.getChecklist(checkListId);
const existingItems = await ReactiveCache.getChecklistItems({ checklistId: checkListId });
const sortBase = existingItems.length;
for (let i = 0; i < itemsArray.length; i++) {
ChecklistItems.insert({
title: itemsArray[i],
checklistId: checkListId,
cardId: card._id,
sort: checkList.itemCount(),
sort: sortBase + i,
});
}
}