From ab4fec0f3c6d5a613b309ae6fac41dbb31f1765d Mon Sep 17 00:00:00 2001 From: wekan Date: Mon, 13 May 2019 11:01:50 +0200 Subject: Fixed #2338 -> Slow opening of big boards with too many archived items --- client/components/boards/boardBody.js | 2 +- client/components/boards/boardsList.js | 4 +- client/components/cards/cardDetails.js | 6 +- client/components/lists/listBody.js | 12 ++-- client/components/sidebar/sidebarArchives.jade | 96 +++++++++++++------------- client/components/sidebar/sidebarArchives.js | 22 ++++++ server/publications/boards.js | 12 ++-- server/publications/fast-render.js | 2 +- 8 files changed, 92 insertions(+), 64 deletions(-) diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index 301c0742..dc5e0ede 100644 --- a/client/components/boards/boardBody.js +++ b/client/components/boards/boardBody.js @@ -14,7 +14,7 @@ BlazeComponent.extendComponent({ const currentBoardId = Session.get('currentBoard'); if (!currentBoardId) return; - const handle = subManager.subscribe('board', currentBoardId); + const handle = subManager.subscribe('board', currentBoardId, false); Tracker.nonreactive(() => { Tracker.autorun(() => { this.isBoardReady.set(handle.ready()); diff --git a/client/components/boards/boardsList.js b/client/components/boards/boardsList.js index e97070ee..0fb80230 100644 --- a/client/components/boards/boardsList.js +++ b/client/components/boards/boardsList.js @@ -33,12 +33,12 @@ BlazeComponent.extendComponent({ }, hasOvertimeCards() { - subManager.subscribe('board', this.currentData()._id); + subManager.subscribe('board', this.currentData()._id, false); return this.currentData().hasOvertimeCards(); }, hasSpentTimeCards() { - subManager.subscribe('board', this.currentData()._id); + subManager.subscribe('board', this.currentData()._id, false); return this.currentData().hasSpentTimeCards(); }, diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 79e9e311..c9254751 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -424,7 +424,7 @@ Template.moveCardPopup.events({ }); BlazeComponent.extendComponent({ onCreated() { - subManager.subscribe('board', Session.get('currentBoard')); + subManager.subscribe('board', Session.get('currentBoard'), false); this.selectedBoardId = new ReactiveVar(Session.get('currentBoard')); }, @@ -453,7 +453,7 @@ BlazeComponent.extendComponent({ return [{ 'change .js-select-boards'(evt) { this.selectedBoardId.set($(evt.currentTarget).val()); - subManager.subscribe('board', this.selectedBoardId.get()); + subManager.subscribe('board', this.selectedBoardId.get(), false); }, }]; }, @@ -676,7 +676,7 @@ BlazeComponent.extendComponent({ if (selection === 'none') { this.parentBoard.set(null); } else { - subManager.subscribe('board', $(evt.currentTarget).val()); + subManager.subscribe('board', $(evt.currentTarget).val(), false); this.parentBoard.set(selection); list.prop('disabled', false); } diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index a5ccba3f..bce350dd 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -348,7 +348,7 @@ BlazeComponent.extendComponent({ this.boardId = Session.get('currentBoard'); // In order to get current board info - subManager.subscribe('board', this.boardId); + subManager.subscribe('board', this.boardId, false); this.board = Boards.findOne(this.boardId); // List where to insert card const list = $(Popup._getTopStack().openerElement).closest('.js-list'); @@ -414,7 +414,7 @@ BlazeComponent.extendComponent({ events() { return [{ 'change .js-select-boards'(evt) { - subManager.subscribe('board', $(evt.currentTarget).val()); + subManager.subscribe('board', $(evt.currentTarget).val(), false); this.selectedBoardId.set($(evt.currentTarget).val()); }, 'change .js-select-swimlanes'(evt) { @@ -500,13 +500,13 @@ BlazeComponent.extendComponent({ } const boardId = board._id; // Subscribe to this board - subManager.subscribe('board', boardId); + subManager.subscribe('board', boardId, false); this.selectedBoardId = new ReactiveVar(boardId); if (!this.isBoardTemplateSearch) { this.boardId = Session.get('currentBoard'); // In order to get current board info - subManager.subscribe('board', this.boardId); + subManager.subscribe('board', this.boardId, false); this.swimlaneId = ''; // Swimlane where to insert card const swimlane = $(Popup._getTopStack().openerElement).parents('.js-swimlane'); @@ -547,7 +547,7 @@ BlazeComponent.extendComponent({ } else if (this.isBoardTemplateSearch) { const boards = board.searchBoards(this.term.get()); boards.forEach((board) => { - subManager.subscribe('board', board.linkedId); + subManager.subscribe('board', board.linkedId, false); }); return boards; } else { @@ -558,7 +558,7 @@ BlazeComponent.extendComponent({ events() { return [{ 'change .js-select-boards'(evt) { - subManager.subscribe('board', $(evt.currentTarget).val()); + subManager.subscribe('board', $(evt.currentTarget).val(), false); this.selectedBoardId.set($(evt.currentTarget).val()); }, 'submit .js-search-term-form'(evt) { diff --git a/client/components/sidebar/sidebarArchives.jade b/client/components/sidebar/sidebarArchives.jade index e2f3e395..466d2cb0 100644 --- a/client/components/sidebar/sidebarArchives.jade +++ b/client/components/sidebar/sidebarArchives.jade @@ -1,54 +1,56 @@ template(name="archivesSidebar") - +basicTabs(tabs=tabs) - - +tabContent(slug="cards") - p.quiet - a.js-restore-all-cards {{_ 'restore-all'}} - | - - a.js-delete-all-cards {{_ 'delete-all'}} - each archivedCards - .minicard-wrapper.js-minicard - +minicard(this) - if currentUser.isBoardMember + if isArchiveReady.get + +basicTabs(tabs=tabs) + +tabContent(slug="cards") p.quiet - a.js-restore-card {{_ 'restore'}} + a.js-restore-all-cards {{_ 'restore-all'}} | - - a.js-delete-card {{_ 'delete'}} - if cardIsInArchivedList - p.quiet.small ({{_ 'warn-list-archived'}}) - else - p.no-items-message {{_ 'no-archived-cards'}} - - +tabContent(slug="lists") - p.quiet - a.js-restore-all-lists {{_ 'restore-all'}} - | - - a.js-delete-all-lists {{_ 'delete-all'}} - ul.archived-lists - each archivedLists - li.archived-lists-item - = title + a.js-delete-all-cards {{_ 'delete-all'}} + each archivedCards + .minicard-wrapper.js-minicard + +minicard(this) if currentUser.isBoardMember p.quiet - a.js-restore-list {{_ 'restore'}} + a.js-restore-card {{_ 'restore'}} | - - a.js-delete-list {{_ 'delete'}} - else - li.no-items-message {{_ 'no-archived-lists'}} + a.js-delete-card {{_ 'delete'}} + if cardIsInArchivedList + p.quiet.small ({{_ 'warn-list-archived'}}) + else + p.no-items-message {{_ 'no-archived-cards'}} - +tabContent(slug="swimlanes") - p.quiet - a.js-restore-all-swimlanes {{_ 'restore-all'}} - | - - a.js-delete-all-swimlanes {{_ 'delete-all'}} - ul.archived-lists - each archivedSwimlanes - li.archived-lists-item - = title - if currentUser.isBoardMember - p.quiet - a.js-restore-swimlane {{_ 'restore'}} - | - - a.js-delete-swimlane {{_ 'delete'}} - else - li.no-items-message {{_ 'no-archived-swimlanes'}} + +tabContent(slug="lists") + p.quiet + a.js-restore-all-lists {{_ 'restore-all'}} + | - + a.js-delete-all-lists {{_ 'delete-all'}} + ul.archived-lists + each archivedLists + li.archived-lists-item + = title + if currentUser.isBoardMember + p.quiet + a.js-restore-list {{_ 'restore'}} + | - + a.js-delete-list {{_ 'delete'}} + else + li.no-items-message {{_ 'no-archived-lists'}} + + +tabContent(slug="swimlanes") + p.quiet + a.js-restore-all-swimlanes {{_ 'restore-all'}} + | - + a.js-delete-all-swimlanes {{_ 'delete-all'}} + ul.archived-lists + each archivedSwimlanes + li.archived-lists-item + = title + if currentUser.isBoardMember + p.quiet + a.js-restore-swimlane {{_ 'restore'}} + | - + a.js-delete-swimlane {{_ 'delete'}} + else + li.no-items-message {{_ 'no-archived-swimlanes'}} + else + +spinner diff --git a/client/components/sidebar/sidebarArchives.js b/client/components/sidebar/sidebarArchives.js index b50043fd..546d7e1a 100644 --- a/client/components/sidebar/sidebarArchives.js +++ b/client/components/sidebar/sidebarArchives.js @@ -1,4 +1,26 @@ +const subManager = new SubsManager(); + BlazeComponent.extendComponent({ + onCreated() { + this.isArchiveReady = new ReactiveVar(false); + + // The pattern we use to manually handle data loading is described here: + // https://kadira.io/academy/meteor-routing-guide/content/subscriptions-and-data-management/using-subs-manager + // XXX The boardId should be readed from some sort the component "props", + // unfortunatly, Blaze doesn't have this notion. + this.autorun(() => { + const currentBoardId = Session.get('currentBoard'); + if (!currentBoardId) + return; + const handle = subManager.subscribe('board', currentBoardId, true); + Tracker.nonreactive(() => { + Tracker.autorun(() => { + this.isArchiveReady.set( handle.ready() ); + }); + }); + }); + }, + tabs() { return [ { name: TAPi18n.__('cards'), slug: 'cards' }, diff --git a/server/publications/boards.js b/server/publications/boards.js index 52940739..f11e776b 100644 --- a/server/publications/boards.js +++ b/server/publications/boards.js @@ -59,9 +59,12 @@ Meteor.publish('archivedBoards', function() { }); }); -Meteor.publishRelations('board', function(boardId) { +// If isArchived = false, this will only return board elements which are not archived. +// If isArchived = true, this will only return board elements which are archived. +Meteor.publishRelations('board', function(boardId, isArchived) { this.unblock(); check(boardId, String); + check(isArchived, Boolean); const thisUserId = this.userId; this.cursor(Boards.find({ @@ -75,8 +78,8 @@ Meteor.publishRelations('board', function(boardId) { ], // Sort required to ensure oplog usage }, { limit: 1, sort: { _id: 1 } }), function(boardId, board) { - this.cursor(Lists.find({ boardId })); - this.cursor(Swimlanes.find({ boardId })); + this.cursor(Lists.find({ boardId: boardId, archived: isArchived })); + this.cursor(Swimlanes.find({ boardId: boardId, archived: isArchived })); this.cursor(Integrations.find({ boardId })); this.cursor(CustomFields.find({ boardIds: {$in: [boardId]} }, { sort: { name: 1 } })); @@ -115,8 +118,9 @@ Meteor.publishRelations('board', function(boardId) { parentCards.selector = (_ids) => ({ parentId: _ids }); const boards = this.join(Boards); const subCards = this.join(Cards); + subCards.selector = (_ids) => ({ archived: isArchived }); - this.cursor(Cards.find({ boardId: {$in: [boardId, board.subtasksDefaultBoardId]}}), function(cardId, card) { + this.cursor(Cards.find({ boardId: {$in: [boardId, board.subtasksDefaultBoardId]}, archived: isArchived }), function(cardId, card) { if (card.type === 'cardType-linkedCard') { const impCardId = card.linkedId; subCards.push(impCardId); diff --git a/server/publications/fast-render.js b/server/publications/fast-render.js index 7c54c686..4829ad57 100644 --- a/server/publications/fast-render.js +++ b/server/publications/fast-render.js @@ -5,5 +5,5 @@ FastRender.onAllRoutes(function() { }); FastRender.route('/b/:id/:slug', function({ id }) { - this.subscribe('board', id); + this.subscribe('board', id, false); }); -- cgit v1.2.3-1-g7c22