diff --git a/client/components/lists/listHeader.jade b/client/components/lists/listHeader.jade index e724cdaa4..4a0bda786 100644 --- a/client/components/lists/listHeader.jade +++ b/client/components/lists/listHeader.jade @@ -6,15 +6,15 @@ template(name="listHeader") +editListTitleForm else unless isMiniScreen - if collapsed - a.js-collapse(title="{{_ 'uncollapse'}}") + if listCollapsed + a.js-collapse-list(title="{{_ 'uncollapse'}}") i.fa.fa-arrow-left.list-header-uncollapse-left i.fa.fa-arrow-right.list-header-uncollapse-right if isMiniScreen if currentList a.list-header-left-icon.fa.fa-angle-left.js-unselect-list unless isMiniScreen - if collapsed + if listCollapsed if showCardsCountForList cards.length br span.cardCount {{cardsCount}} @@ -29,7 +29,7 @@ template(name="listHeader") span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}} |/#{wipLimit.value}) unless isMiniScreen - div(class="{{#if collapsed}}list-rotated{{/if}}") + div(class="{{#if listCollapsed}}list-rotated{{/if}}") h2.list-header-name( title="{{ moment modifiedAt 'LLL' }}" class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}") @@ -39,7 +39,7 @@ template(name="listHeader") | ( span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}} |/#{wipLimit.value}) - unless collapsed + unless listCollapsed if showCardsCountForList cards.length span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}} if isMiniScreen @@ -57,14 +57,14 @@ template(name="listHeader") else if currentUser.isBoardMember if isWatching i.list-header-watch-icon.fa.fa-eye - unless collapsed + unless listCollapsed div.list-header-menu unless currentUser.isCommentOnly //if isBoardAdmin // a.fa.js-list-star.list-header-plus-top(class="fa-star{{#unless starred}}-o{{/unless}}") if canSeeAddCard a.js-add-card.fa.fa-plus.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}") - a.js-collapse(title="{{_ 'collapse'}}") + a.js-collapse-list(title="{{_ 'collapse'}}") i.fa.fa-arrow-right.list-header-collapse-right i.fa.fa-arrow-left.list-header-collapse-left a.fa.fa-navicon.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") diff --git a/client/components/lists/listHeader.js b/client/components/lists/listHeader.js index a8f63900a..a40c551ab 100644 --- a/client/components/lists/listHeader.js +++ b/client/components/lists/listHeader.js @@ -31,14 +31,14 @@ BlazeComponent.extendComponent({ return !status; } }, - collapsed(check = undefined) { - const list = Template.currentData(); - const status = list.isCollapsed(); + listCollapsed(check = undefined) { + const user = Meteor.user(); + const status = user.hasCollapsedList(this._id); if (check === undefined) { // just check return status; } else { - list.collapse(!status); + user.toggleCollapseList(this._id); return !status; } }, @@ -115,9 +115,9 @@ BlazeComponent.extendComponent({ event.preventDefault(); this.starred(!this.starred()); }, - 'click .js-collapse'(event) { + 'click .js-collapse-list'(event) { event.preventDefault(); - this.collapsed(!this.collapsed()); + this.listCollapsed(!this.listCollapsed()); }, 'click .js-open-list-menu': Popup.open('listAction'), 'click .js-add-card.list-header-plus-top'(event) { diff --git a/models/lists.js b/models/lists.js index 126b7ea1e..49b456f2a 100644 --- a/models/lists.js +++ b/models/lists.js @@ -156,13 +156,6 @@ Lists.attachSchema( type: String, defaultValue: 'list', }, - collapsed: { - /** - * is the list collapsed - */ - type: Boolean, - defaultValue: false, - }, }), ); @@ -293,10 +286,6 @@ Lists.helpers({ return this.starred === true; }, - isCollapsed() { - return this.collapsed === true; - }, - absoluteUrl() { const card = ReactiveCache.getCard({ listId: this._id }); return card && card.absoluteUrl(); @@ -317,9 +306,6 @@ Lists.mutations({ star(enable = true) { return { $set: { starred: !!enable } }; }, - collapse(enable = true) { - return { $set: { collapsed: !!enable } }; - }, archive() { if (this.isTemplateList()) { diff --git a/models/swimlanes.js b/models/swimlanes.js index 1e94b3c97..7c8cac595 100644 --- a/models/swimlanes.js +++ b/models/swimlanes.js @@ -107,13 +107,6 @@ Swimlanes.attachSchema( type: String, defaultValue: 'swimlane', }, - collapsed: { - /** - * is the swimlane collapsed - */ - type: Boolean, - defaultValue: false, - }, }), ); @@ -239,10 +232,6 @@ Swimlanes.helpers({ return ret; }, - isCollapsed() { - return this.collapsed === true; - }, - board() { return ReactiveCache.getBoard(this.boardId); }, @@ -285,10 +274,6 @@ Swimlanes.mutations({ return { $set: { title } }; }, - collapse(enable = true) { - return { $set: { collapsed: !!enable } }; - }, - archive() { if (this.isTemplateSwimlane()) { this.myLists().forEach(list => { diff --git a/models/users.js b/models/users.js index b6bf53793..510ae6eab 100644 --- a/models/users.js +++ b/models/users.js @@ -440,6 +440,20 @@ Users.attachSchema( defaultValue: {}, blackbox: true, }, + 'profile.listCollapsed': { + /** + * User-specific list of collapsed list IDs + */ + type: [String], + optional: true, + }, + 'profile.swimlaneCollapsed': { + /** + * User-specific list of collapsed swimlane IDs + */ + type: [String], + optional: true, + }, services: { /** * services field of the user @@ -736,6 +750,36 @@ Users.helpers({ return _.contains(starredBoards, boardId); }, + collapsedLists() { + const { collapsedLists = [] } = this.profile || {}; + return Lists.userLists( + this._id, + false, + { _id: { $in: collapsedLists } }, + { sort: { sort: 1 } }, + ); + }, + + hasCollapsedList(listId) { + const { collapsedLists = [] } = this.profile || {}; + return _.contains(collapsedLists, listId); + }, + + collapsedSwimlanes() { + const { collapsedSwimlanes = [] } = this.profile || {}; + return Swimlanes.userSwimlanes( + this._id, + false, + { _id: { $in: collapsedSwimlanes } }, + { sort: { sort: 1 } }, + ); + }, + + hasCollapsedSwimlane(swimlaneId) { + const { collapsedSwimlanes = [] } = this.profile || {}; + return _.contains(collapsedSwimlanes, swimlaneId); + }, + invitedBoards() { const { invitedBoards = [] } = this.profile || {}; return Boards.userBoards( @@ -1004,6 +1048,22 @@ Users.mutations({ }, }; }, + toggleCollapseList(listId) { + const queryKind = this.hasCollapsedList(listId) ? '$pull' : '$addToSet'; + return { + [queryKind]: { + 'profile.listCollapsed': listId, + }, + }; + }, + toggleCollapseSwimlane(swimlaneId) { + const queryKind = this.hasCollapsedSwimlane(swimlaneId) ? '$pull' : '$addToSet'; + return { + [queryKind]: { + 'profile.swimlaneCollapsed': swimlaneId, + }, + }; + }, addInvite(boardId) { return { diff --git a/server/publications/boards.js b/server/publications/boards.js index 4b7df1762..dee05959f 100644 --- a/server/publications/boards.js +++ b/server/publications/boards.js @@ -61,7 +61,6 @@ Meteor.publishRelations('boards', function() { title: 1, boardId: 1, archived: 1, - collapsed: 1, sort: 1 } }, diff --git a/server/publications/cards.js b/server/publications/cards.js index 8dc3a03dc..877c77d85 100644 --- a/server/publications/cards.js +++ b/server/publications/cards.js @@ -785,7 +785,7 @@ function findCards(sessionId, query) { ), ReactiveCache.getSwimlanes( { _id: { $in: swimlanes } }, - { fields: { ...fields, color: 1, collapsed: 1 } }, + { fields: { ...fields, color: 1 } }, true, ), ReactiveCache.getLists({ _id: { $in: lists } }, { fields }, true),