From 4679db6ec44c5e0cc421f9db113438089b7a051b Mon Sep 17 00:00:00 2001 From: "John R. Supplee" Date: Sun, 10 Jan 2021 00:17:59 +0200 Subject: [PATCH 1/2] New Broken Cards page --- client/components/main/brokenCards.jade | 41 ++++++++++++++ client/components/main/brokenCards.js | 58 ++++++++++++++++++++ client/components/main/brokenCards.styl | 73 +++++++++++++++++++++++++ config/router.js | 20 +++++++ server/publications/cards.js | 57 +++++++++++++++++++ 5 files changed, 249 insertions(+) create mode 100644 client/components/main/brokenCards.jade create mode 100644 client/components/main/brokenCards.js create mode 100644 client/components/main/brokenCards.styl diff --git a/client/components/main/brokenCards.jade b/client/components/main/brokenCards.jade new file mode 100644 index 000000000..9f2ad5ca4 --- /dev/null +++ b/client/components/main/brokenCards.jade @@ -0,0 +1,41 @@ +template(name="brokenCardsHeaderBar") + h1 + | Broken Cards + +template(name="brokenCards") + .wrapper + .broken-cards-dueat-list-wrapper + each card in brokenCardsList + .broken-cards-card-wrapper + a.minicard-wrapper.card-title(href=card.absoluteUrl) + +minicard(card) + ul.broken-cards-context-list + li.broken-cards-context(title="{{_ 'board'}}") + if card.boardId + +viewer + = card.getBoard.title + else + .broken-cards-null + | NULL + li.broken-cards-context.broken-cards-context-separator + = ' ' + | {{_ 'context-separator'}} + = ' ' + li.broken-cards-context(title="{{_ 'swimlane'}}") + if card.swimlaneId + +viewer + = card.getSwimlane.title + else + .broken-cards-null + | NULL + li.broken-cards-context + = ' ' + | {{_ 'context-separator'}} + = ' ' + li.broken-cards-context(title="{{_ 'list'}}") + if card.listId + +viewer + = card.getList.title + else + .broken-cards-null + | NULL diff --git a/client/components/main/brokenCards.js b/client/components/main/brokenCards.js new file mode 100644 index 000000000..37bef9b60 --- /dev/null +++ b/client/components/main/brokenCards.js @@ -0,0 +1,58 @@ +BlazeComponent.extendComponent({}).register('brokenCardsHeaderBar'); + +Template.brokenCards.helpers({ + userId() { + return Meteor.userId(); + }, +}); + +BlazeComponent.extendComponent({ + onCreated() { + Meteor.subscribe('setting'); + Meteor.subscribe('brokenCards'); + }, + + brokenCardsList() { + const user = Meteor.user(); + + const permiitedBoards = [null]; + let selector = {}; + // if user is not an admin allow her to see cards only from boards where + // she is a member + if (!user.isAdmin) { + selector.$or = [ + { permission: 'public' }, + { members: { $elemMatch: { userId: user._id, isActive: true } } }, + ]; + } + Boards.find(selector).forEach(board => { + permiitedBoards.push(board._id); + }); + + selector = { + boardId: { $in: permiitedBoards }, + $or: [{ boardId: null }, { swimlaneId: null }, { listId: null }], + }; + + const cards = Cards.find(selector, { + fields: { + _id: 1, + archived: 1, + boardId: 1, + swimlaneId: 1, + listId: 1, + title: 1, + type: 1, + sort: 1, + members: 1, + assignees: 1, + colors: 1, + dueAt: 1, + }, + }); + + // eslint-disable-next-line no-console + // console.log('cards:', cards); + return cards; + }, +}).register('brokenCards'); diff --git a/client/components/main/brokenCards.styl b/client/components/main/brokenCards.styl new file mode 100644 index 000000000..e3913649b --- /dev/null +++ b/client/components/main/brokenCards.styl @@ -0,0 +1,73 @@ +.broken-cards-board-wrapper + border-radius: 8px + //padding: 0.5rem + min-width: 400px + border-width: 8px + border-color: grey + border-style: solid + margin-bottom: 2rem + margin-right: auto + margin-left: auto + +.broken-cards-board-title + font-size: 1.4rem + font-weight: bold + padding: 0.5rem + background-color: grey + color: white + +.broken-cards-swimlane-title + font-size: 1.1rem + font-weight: bold + padding: 0.5rem + padding-bottom: 0.4rem + margin-top: 0 + margin-bottom: 0.5rem + //border-top: black 1px solid + //border-bottom: black 1px solid + text-align: center + +.swimlane-default-color + background-color: lightgrey + +.broken-cards-list-title + font-weight: bold + font-size: 1.1rem + //padding-bottom: 0 + //margin-bottom: 0 + text-align: center + margin-bottom: 0.7rem + +.broken-cards-list-wrapper + margin: 1rem + border-radius: 5px + padding: 1.5rem + padding-top: 0.75rem + display: inline-block + min-width: 250px + max-width: 350px + +.broken-cards-card-wrapper + margin-top: 0 + margin-bottom: 10px + +.broken-cards-dueat-list-wrapper + max-width: 500px + margin-right: auto + margin-left: auto + +.broken-cards-field-name + font-weight: bold + +.broken-cards-context + display: inline-block + +.broken-cards-context-separator + font-weight: bold + +.broken-cards-context-list + margin-bottom: 0.7rem + +.broken-cards-null + //font-weight: bold + font-style: italic diff --git a/config/router.js b/config/router.js index a87817055..811f84e53 100644 --- a/config/router.js +++ b/config/router.js @@ -165,6 +165,26 @@ FlowRouter.route('/due-cards', { }, }); +FlowRouter.route('/broken-cards', { + name: 'broken-cards', + action() { + const brokenCardsTemplate = 'brokenCards'; + + Filter.reset(); + // EscapeActions.executeAll(); + EscapeActions.executeUpTo('popup-close'); + + Utils.manageCustomUI(); + Utils.manageMatomo(); + + BlazeLayout.render('defaultLayout', { + headerBar: 'brokenCardsHeaderBar', + content: brokenCardsTemplate, + }); + // } + }, +}); + FlowRouter.route('/import/:source', { name: 'import', triggersEnter: [AccountsTemplates.ensureSignedIn], diff --git a/server/publications/cards.js b/server/publications/cards.js index 54efe5684..9c5db6799 100644 --- a/server/publications/cards.js +++ b/server/publications/cards.js @@ -119,3 +119,60 @@ Meteor.publish('dueCards', function(allUsers = false) { Lists.find({ _id: { $in: lists } }), ]; }); + +Meteor.publish('brokenCards', function() { + const user = Users.findOne(this.userId); + + const permiitedBoards = [null]; + let selector = {}; + // if user is not an admin allow her to see cards only from boards where + // she is a member + if (!user.isAdmin) { + selector.$or = [ + { permission: 'public' }, + { members: { $elemMatch: { userId: user._id, isActive: true } } }, + ]; + } + Boards.find(selector).forEach(board => { + permiitedBoards.push(board._id); + }); + + selector = { + boardId: { $in: permiitedBoards }, + $or: [{ boardId: null }, { swimlaneId: null }, { listId: null }], + }; + + const cards = Cards.find(selector, { + fields: { + _id: 1, + archived: 1, + boardId: 1, + swimlaneId: 1, + listId: 1, + title: 1, + type: 1, + sort: 1, + members: 1, + assignees: 1, + colors: 1, + dueAt: 1, + }, + }); + + const boards = []; + const swimlanes = []; + const lists = []; + + cards.forEach(card => { + if (card.boardId) boards.push(card.boardId); + if (card.swimlaneId) swimlanes.push(card.swimlaneId); + if (card.listId) lists.push(card.listId); + }); + + return [ + cards, + Boards.find({ _id: { $in: boards } }), + Swimlanes.find({ _id: { $in: swimlanes } }), + Lists.find({ _id: { $in: lists } }), + ]; +}); From 986ab2967673206a1919b7ab90a28635b66417bd Mon Sep 17 00:00:00 2001 From: "John R. Supplee" Date: Sun, 10 Jan 2021 15:35:16 +0200 Subject: [PATCH 2/2] Broken Cards development * fix CSS and formatting * refine selection criteria --- client/components/main/brokenCards.jade | 6 +-- client/components/main/brokenCards.js | 46 +++--------------- client/components/main/brokenCards.styl | 64 +++++-------------------- server/publications/cards.js | 6 ++- 4 files changed, 26 insertions(+), 96 deletions(-) diff --git a/client/components/main/brokenCards.jade b/client/components/main/brokenCards.jade index 9f2ad5ca4..4d884629c 100644 --- a/client/components/main/brokenCards.jade +++ b/client/components/main/brokenCards.jade @@ -4,11 +4,11 @@ template(name="brokenCardsHeaderBar") template(name="brokenCards") .wrapper - .broken-cards-dueat-list-wrapper + .broken-cards-wrapper each card in brokenCardsList .broken-cards-card-wrapper - a.minicard-wrapper.card-title(href=card.absoluteUrl) - +minicard(card) + .broken-cards-card-title + = card.title ul.broken-cards-context-list li.broken-cards-context(title="{{_ 'board'}}") if card.boardId diff --git a/client/components/main/brokenCards.js b/client/components/main/brokenCards.js index 37bef9b60..c3eb06f77 100644 --- a/client/components/main/brokenCards.js +++ b/client/components/main/brokenCards.js @@ -13,46 +13,14 @@ BlazeComponent.extendComponent({ }, brokenCardsList() { - const user = Meteor.user(); - - const permiitedBoards = [null]; - let selector = {}; - // if user is not an admin allow her to see cards only from boards where - // she is a member - if (!user.isAdmin) { - selector.$or = [ - { permission: 'public' }, - { members: { $elemMatch: { userId: user._id, isActive: true } } }, - ]; - } - Boards.find(selector).forEach(board => { - permiitedBoards.push(board._id); - }); - - selector = { - boardId: { $in: permiitedBoards }, - $or: [{ boardId: null }, { swimlaneId: null }, { listId: null }], + const selector = { + $or: [ + { boardId: { $in: [null, ''] } }, + { swimlaneId: { $in: [null, ''] } }, + { listId: { $in: [null, ''] } }, + ], }; - const cards = Cards.find(selector, { - fields: { - _id: 1, - archived: 1, - boardId: 1, - swimlaneId: 1, - listId: 1, - title: 1, - type: 1, - sort: 1, - members: 1, - assignees: 1, - colors: 1, - dueAt: 1, - }, - }); - - // eslint-disable-next-line no-console - // console.log('cards:', cards); - return cards; + return Cards.find(selector); }, }).register('brokenCards'); diff --git a/client/components/main/brokenCards.styl b/client/components/main/brokenCards.styl index e3913649b..d9603cecb 100644 --- a/client/components/main/brokenCards.styl +++ b/client/components/main/brokenCards.styl @@ -1,63 +1,21 @@ -.broken-cards-board-wrapper - border-radius: 8px - //padding: 0.5rem - min-width: 400px - border-width: 8px - border-color: grey - border-style: solid - margin-bottom: 2rem - margin-right: auto - margin-left: auto - -.broken-cards-board-title - font-size: 1.4rem - font-weight: bold - padding: 0.5rem - background-color: grey - color: white - -.broken-cards-swimlane-title - font-size: 1.1rem - font-weight: bold - padding: 0.5rem - padding-bottom: 0.4rem - margin-top: 0 - margin-bottom: 0.5rem - //border-top: black 1px solid - //border-bottom: black 1px solid - text-align: center - -.swimlane-default-color - background-color: lightgrey - -.broken-cards-list-title - font-weight: bold - font-size: 1.1rem - //padding-bottom: 0 - //margin-bottom: 0 - text-align: center - margin-bottom: 0.7rem - -.broken-cards-list-wrapper - margin: 1rem - border-radius: 5px - padding: 1.5rem - padding-top: 0.75rem - display: inline-block - min-width: 250px - max-width: 350px - .broken-cards-card-wrapper margin-top: 0 margin-bottom: 10px + border-width: 3px !important + border-color: grey !important + border-style: solid + border-radius: 5px + padding: 1.5rem + background-color: white -.broken-cards-dueat-list-wrapper +.broken-cards-wrapper max-width: 500px margin-right: auto margin-left: auto -.broken-cards-field-name +.broken-cards-card-title font-weight: bold + //padding: 10px .broken-cards-context display: inline-block @@ -66,8 +24,8 @@ font-weight: bold .broken-cards-context-list - margin-bottom: 0.7rem + //margin-bottom: 0.7rem .broken-cards-null - //font-weight: bold + color: darkred font-style: italic diff --git a/server/publications/cards.js b/server/publications/cards.js index 9c5db6799..1031c84a5 100644 --- a/server/publications/cards.js +++ b/server/publications/cards.js @@ -139,7 +139,11 @@ Meteor.publish('brokenCards', function() { selector = { boardId: { $in: permiitedBoards }, - $or: [{ boardId: null }, { swimlaneId: null }, { listId: null }], + $or: [ + { boardId: { $in: [null, ''] } }, + { swimlaneId: { $in: [null, ''] } }, + { listId: { $in: [null, ''] } }, + ], }; const cards = Cards.find(selector, {