diff --git a/client/lib/utils.js b/client/lib/utils.js index 2d9e72fa5..85640dbe4 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -43,12 +43,12 @@ Utils = { }, getCurrentCard(ignorePopupCard) { const cardId = Utils.getCurrentCardId(ignorePopupCard); - const ret = Cards.findOne(cardId); + const ret = ReactiveCache.getCard(cardId); return ret; }, getPopupCard() { const cardId = Utils.getPopupCardId(); - const ret = Cards.findOne(cardId); + const ret = ReactiveCache.getCard(cardId); return ret; }, canModifyCard() { diff --git a/imports/jsons.js b/imports/jsons.js new file mode 100644 index 000000000..bdac54fcf --- /dev/null +++ b/imports/jsons.js @@ -0,0 +1,30 @@ +Jsons = { + stringify(value) { + const ret = JSON.stringify(value, this.replacer, 2); + return ret; + }, + + parse(value) { + const ret = JSON.parse(value, this.reviver); + return ret; + }, + + // https://stackoverflow.com/questions/12075927/serialization-of-regexp/33416684#33416684 + replacer(key, value) { + if (value instanceof RegExp) + return ("___REGEXP___ " + value.toString()); + else + return value; + }, + + // https://stackoverflow.com/questions/12075927/serialization-of-regexp/33416684#33416684 + reviver(key, value) { + if (value?.toString()?.indexOf("___REGEXP___ ") == 0) { + const m = value.split("___REGEXP___ ")[1].match(/\/(.*)\/(.*)?/); + return new RegExp(m[1], m[2] || ""); + } else + return value; + } +} + +export { Jsons } diff --git a/imports/reactiveCache.js b/imports/reactiveCache.js index 7aa13140a..44dc3f855 100644 --- a/imports/reactiveCache.js +++ b/imports/reactiveCache.js @@ -1,4 +1,5 @@ import { DataCache } from 'meteor-reactive-cache'; +import { Jsons } from './jsons'; // Server isn't reactive, so search for the data always. ReactiveCacheServer = { @@ -6,6 +7,30 @@ ReactiveCacheServer = { const ret = Boards.findOne(id); return ret; }, + getList(id) { + const ret = Lists.findOne(id); + return ret; + }, + getSwimlane(id) { + const ret = Swimlanes.findOne(id); + return ret; + }, + getChecklist(id) { + const ret = Checklists.findOne(id); + return ret; + }, + getCard(id) { + const ret = Cards.findOne(id); + return ret; + }, + getCustomField(id) { + const ret = CustomFields.findOne(id); + return ret; + }, + getCustomFields(selector) { + const ret = CustomFields.find(selector).fetch(); + return ret; + }, } // only the Client is reactive @@ -21,6 +46,66 @@ ReactiveCacheClient = { } const ret = this.__board.get(id); return ret; + }, + getList(id) { + if (!this.__list) { + this.__list = new DataCache(listId => { + const _ret = Lists.findOne(listId); + return _ret; + }); + } + const ret = this.__list.get(id); + return ret; + }, + getSwimlane(id) { + if (!this.__swimlane) { + this.__swimlane = new DataCache(swimlaneId => { + const _ret = Swimlanes.findOne(swimlaneId); + return _ret; + }); + } + const ret = this.__swimlane.get(id); + return ret; + }, + getChecklist(id) { + if (!this.__checklist) { + this.__checklist = new DataCache(checklistId => { + const _ret = Checklists.findOne(checklistId); + return _ret; + }); + } + const ret = this.__checklist.get(id); + return ret; + }, + getCard(id) { + if (!this.__card) { + this.__card = new DataCache(cardId => { + const _ret = Cards.findOne(cardId); + return _ret; + }); + } + const ret = this.__card.get(id); + return ret; + }, + getCustomField(id) { + if (!this.__customField) { + this.__customField = new DataCache(customFieldId => { + const _ret = CustomFields.findOne(customFieldId); + return _ret; + }); + } + const ret = this.__customField.get(id); + return ret; + }, + getCustomFields(selector) { + if (!this.__customFields) { + this.__customFields = new DataCache(sel => { + const _ret = CustomFields.find(Jsons.parse(sel)).fetch(); + return _ret; + }); + } + const ret = this.__customFields.get(Jsons.stringify(selector)); + return ret; } } @@ -40,6 +125,60 @@ ReactiveCache = { } return ret; }, + getList(id) { + let ret; + if (Meteor.isServer) { + ret = ReactiveCacheServer.getList(id); + } else { + ret = ReactiveCacheClient.getList(id); + } + return ret; + }, + getSwimlane(id) { + let ret; + if (Meteor.isServer) { + ret = ReactiveCacheServer.getSwimlane(id); + } else { + ret = ReactiveCacheClient.getSwimlane(id); + } + return ret; + }, + getChecklist(id) { + let ret; + if (Meteor.isServer) { + ret = ReactiveCacheServer.getChecklist(id); + } else { + ret = ReactiveCacheClient.getChecklist(id); + } + return ret; + }, + getCard(id) { + let ret; + if (Meteor.isServer) { + ret = ReactiveCacheServer.getCard(id); + } else { + ret = ReactiveCacheClient.getCard(id); + } + return ret; + }, + getCustomField(id) { + let ret; + if (Meteor.isServer) { + ret = ReactiveCacheServer.getCustomField(id); + } else { + ret = ReactiveCacheClient.getCustomField(id); + } + return ret; + }, + getCustomFields(selector) { + let ret; + if (Meteor.isServer) { + ret = ReactiveCacheServer.getCustomFields(selector); + } else { + ret = ReactiveCacheClient.getCustomFields(selector); + } + return ret; + }, } export { ReactiveCache }; diff --git a/models/cards.js b/models/cards.js index 70ebd5178..e59463b88 100644 --- a/models/cards.js +++ b/models/cards.js @@ -554,7 +554,7 @@ Cards.helpers({ // we must only copy the labels and custom fields if the target board // differs from the source board if (this.boardId !== boardId) { - const oldBoard = Boards.findOne(this.boardId); + const oldBoard = ReactiveCache.getBoard(this.boardId); const oldBoardLabels = oldBoard.labels; // Get old label names @@ -565,7 +565,7 @@ Cards.helpers({ 'name', ); - const newBoard = Boards.findOne(boardId); + const newBoard = ReactiveCache.getBoard(boardId); const newBoardLabels = newBoard.labels; const newCardLabels = _.pluck( _.filter(newBoardLabels, label => { @@ -582,7 +582,7 @@ Cards.helpers({ delete this._id; this.boardId = boardId; - this.cardNumber = Boards.findOne(boardId).getNextCardNumber(); + this.cardNumber = ReactiveCache.getBoard(boardId).getNextCardNumber(); this.swimlaneId = swimlaneId; this.listId = listId; const _id = Cards.insert(this); @@ -632,11 +632,11 @@ Cards.helpers({ }, list() { - return Lists.findOne(this.listId); + return ReactiveCache.getList(this.listId); }, swimlane() { - return Swimlanes.findOne(this.swimlaneId); + return ReactiveCache.getSwimlane(this.swimlaneId); }, board() { @@ -917,9 +917,9 @@ Cards.helpers({ // customFields with definitions customFieldsWD() { // get all definitions - const definitions = CustomFields.find({ + const definitions = ReactiveCache.getCustomFields({ boardIds: { $in: [this.boardId] }, - }).fetch(); + }); if (!definitions) { return {}; } @@ -986,9 +986,7 @@ Cards.helpers({ }, canBeRestored() { - const list = Lists.findOne({ - _id: this.listId, - }); + const list = ReactiveCache.getList(this.listId); if ( !list.getWipLimit('soft') && list.getWipLimit('enabled') && @@ -1009,7 +1007,7 @@ Cards.helpers({ parentCardName() { let result = ''; if (this.parentId !== '') { - const card = Cards.findOne(this.parentId); + const card = ReactiveCache.getCard(this.parentId); if (card) { result = card.title; } @@ -2724,7 +2722,7 @@ function cardMove( userId, oldListId, activityType: 'moveCard', - listName: Lists.findOne(doc.listId).title, + listName: ReactiveCache.getList(doc.listId).title, listId: doc.listId, boardId: doc.boardId, cardId: doc._id, @@ -2742,7 +2740,7 @@ function cardState(userId, doc, fieldNames) { Activities.insert({ userId, activityType: 'archivedCard', - listName: Lists.findOne(doc.listId).title, + listName: ReactiveCache.getList(doc.listId).title, boardId: doc.boardId, listId: doc.listId, cardId: doc._id, @@ -2753,7 +2751,7 @@ function cardState(userId, doc, fieldNames) { userId, activityType: 'restoredCard', boardId: doc.boardId, - listName: Lists.findOne(doc.listId).title, + listName: ReactiveCache.getList(doc.listId).title, listId: doc.listId, cardId: doc._id, swimlaneId: doc.swimlaneId, @@ -2937,7 +2935,7 @@ function cardCreation(userId, doc) { userId, activityType: 'createCard', boardId: doc.boardId, - listName: Lists.findOne(doc.listId).title, + listName: ReactiveCache.getList(doc.listId).title, listId: doc.listId, cardId: doc._id, cardTitle: doc.title,