From 1ea99a5dc8040fbfdc47fecac787f313ff849ef0 Mon Sep 17 00:00:00 2001 From: "John R. Supplee" Date: Wed, 6 Jan 2021 20:13:36 +0200 Subject: [PATCH 1/2] My Cards development * Add cards due view * Add input for selecting sort (not working) * Add methods to `Utils` to save sort to local browser storage * CSS updates to make lists display horizontally within swimlanes --- client/components/main/myCards.jade | 87 +++++++++++++++++++----- client/components/main/myCards.js | 102 +++++++++++++++++++++++----- client/components/main/myCards.styl | 28 +++++++- client/lib/utils.js | 17 +++++ i18n/en.i18n.json | 6 +- 5 files changed, 202 insertions(+), 38 deletions(-) diff --git a/client/components/main/myCards.jade b/client/components/main/myCards.jade index 3baa77662..9688f0967 100644 --- a/client/components/main/myCards.jade +++ b/client/components/main/myCards.jade @@ -1,9 +1,19 @@ template(name="myCardsHeaderBar") h1 - a.back-btn(href="{{pathFor 'home'}}") - i.fa.fa-chevron-left + //a.back-btn(href="{{pathFor 'home'}}") + // i.fa.fa-chevron-left | {{_ 'my-cards'}} + .board-header-btns.left + a.board-header-btn.js-toggle-my-cards-choose-sort(title="{{_ 'my-cards-sort'}}") + i.fa.fa-caret-down + if $eq myCardsSort 'board' + i.fa.fa-th-large + | {{_ 'my-cards-sort-board'}} + if $eq myCardsSort 'dueAt' + i.fa.fa-calendar + | {{_ 'my-cards-sort-dueat'}} + template(name="myCardsModalTitle") h2 i.fa.fa-keyboard-o @@ -11,20 +21,63 @@ template(name="myCardsModalTitle") template(name="myCards") .wrapper - each board in myBoards - .my-cards-board-wrapper - .board-title - +viewer - = board.title - each swimlane in board.mySwimlanes - .swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}") + if $eq myCardsSort 'board' + each board in myBoards + .my-cards-board-wrapper + .board-title +viewer - = swimlane.title - each list in swimlane.myLists - .my-cards-list-wrapper - .list-title(class=list.colorClass) + = board.title + each swimlane in board.mySwimlanes + .swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}") + +viewer + = swimlane.title + each list in swimlane.myLists + .my-cards-list-wrapper + .list-title(class=list.colorClass) + +viewer + = list.title + each card in list.myCards + a.minicard-wrapper.card-title(href=card.absoluteUrl) + +minicard(card) + else + .my-cards-dueat-list-wrapper + each card in myCardsList + .my-cards-card + a.minicard-wrapper.card-title(href=card.absoluteUrl) + +minicard(card) + ul.my-cards-context-list + li.my-cards-context(title="{{_ 'board'}}") +viewer - = list.title - each card in list.myCards - a.minicard-wrapper.card-title(href=card.absoluteUrl) - +minicard(card) + = card.board.title + li.my-cards-context + = ' ' + | {{_ 'context-separator'}} + = ' ' + li.my-cards-context(title="{{_ 'swimlane'}}") + +viewer + = card.swimlane.title + li.my-cards-context + = ' ' + | {{_ 'context-separator'}} + = ' ' + li.my-cards-context(title="{{_ 'list'}}") + +viewer + = card.list.title + + +template(name="myCardsSortPopup") + ul.pop-over-list + li + //with "my-cards-sort-board" + a.js-my-cards-sort-board + i.fa.fa-th-large.colorful + | {{_ 'my-cards-sort-board'}} + if $eq Utils.myCardsSort "board" + i.fa.fa-check + li + //with "my-cards-sort-dueat" + a.js-my-cards-sort-dueat + i.fa.fa-calendar.colorful + | {{_ 'my-cards-sort-dueat'}} + if $eq Utils.myCardsSort "dueAt" + i.fa.fa-check diff --git a/client/components/main/myCards.js b/client/components/main/myCards.js index cf2a7fe7c..c5e4dde33 100644 --- a/client/components/main/myCards.js +++ b/client/components/main/myCards.js @@ -1,22 +1,22 @@ -const subManager = new SubsManager(); -Meteor.subscribe('myCards'); -Meteor.subscribe('mySwimlanes'); -Meteor.subscribe('myLists'); +BlazeComponent.extendComponent({ + myCardsSort() { + // eslint-disable-next-line no-console + console.log('sort:', Utils.myCardsSort()); + return Utils.myCardsSort(); + }, -Template.myCardsHeaderBar.events({ - 'click .js-open-archived-board'() { - Modal.open('archivedBoards'); + events() { + return [ + { + 'click .js-toggle-my-cards-choose-sort'() { + Popup.open('myCardsSortPopup'); + // eslint-disable-next-line no-console + console.log('open sort'); + }, + }, + ]; }, -}); - -Template.myCardsHeaderBar.helpers({ - title() { - return FlowRouter.getRouteName() === 'home' ? 'my-boards' : 'public'; - }, - templatesUser() { - return Meteor.user(); - }, -}); +}).register('myCardsHeaderBar'); Template.myCards.helpers({ userId() { @@ -24,10 +24,34 @@ Template.myCards.helpers({ }, }); +Template.myCardsSortPopup.events({ + 'click .js-my-cards-sort-board'() { + Utils.setMyCardsSort('board'); + Popup.close(); + }, + + 'click .js-my-cards-sort-dueat'() { + Utils.setMyCardsSort('dueAt'); + Popup.close(); + }, +}); + BlazeComponent.extendComponent({ onCreated() { Meteor.subscribe('setting'); - // subManager.subscribe('myCards'); + Meteor.subscribe('myCards'); + Meteor.subscribe('mySwimlanes'); + Meteor.subscribe('myLists'); + }, + + myCardsSort() { + // eslint-disable-next-line no-console + console.log('sort:', Utils.myCardsSort()); + return Utils.myCardsSort(); + }, + + sortByBoard() { + return this.myCardsSort() === 'board'; }, myBoards() { @@ -145,6 +169,48 @@ BlazeComponent.extendComponent({ return boards; }, + myCardsList() { + const userId = Meteor.userId(); + + const cursor = Cards.find( + { + $or: [{ members: userId }, { assignees: userId }], + archived: false, + }, + { + sort: { + dueAt: -1, + boardId: 1, + swimlaneId: 1, + listId: 1, + sort: 1, + }, + }, + ); + + // eslint-disable-next-line no-console + // console.log('cursor:', cursor); + + const cards = []; + cursor.forEach(card => { + cards.push(card); + }); + + cards.sort((a, b) => { + const x = a.dueAt === null ? Date('2100-12-31') : a.dueAt; + const y = b.dueAt === null ? Date('2100-12-31') : b.dueAt; + + if (x > y) return 1; + else if (x < y) return -1; + + return 0; + }); + + // eslint-disable-next-line no-console + // console.log('cursor:', cards); + return cards; + }, + events() { return [ { diff --git a/client/components/main/myCards.styl b/client/components/main/myCards.styl index 7075c6fbb..410f02395 100644 --- a/client/components/main/myCards.styl +++ b/client/components/main/myCards.styl @@ -22,7 +22,7 @@ .my-cards-board-wrapper border-radius: 8px //padding: 0.5rem - max-width: 400px + min-width: 400px border-width: 8px border-color: grey border-style: solid @@ -71,6 +71,30 @@ border-radius: 5px padding: 1.5rem padding-top: 0.75rem + display: inline-block + min-width: 250px + max-width: 350px .card-title - margin-top: 5px + margin-top: 0 + margin-bottom: 10px + +.my-cards-dueat-list-wrapper + max-width: 500px + margin-right: auto + margin-left: auto + +.my-cards-field-name + font-weight: bold + +.my-cards-dueat-list + columns: 2 + +.my-cards-context + display: inline-block + +.my-cards-context-list + margin-bottom: 0.7rem + +.my-cards-context-item + display: inline-block diff --git a/client/lib/utils.js b/client/lib/utils.js index 2068e6d27..f697c84da 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -44,6 +44,23 @@ Utils = { } }, + myCardsSort() { + let sort = window.localStorage.getItem('myCardsSort'); + + if (!sort || !['board', 'dueAt'].includes(sort)) { + window.localStorage.setItem('myCardsSort', 'board'); + location.reload(); + sort = 'board'; + } + + return sort; + }, + + setMyCardsSort(sort) { + window.localStorage.setItem('myCardsSort', sort); + location.reload(); + }, + // XXX We should remove these two methods goBoardId(_id) { const board = Boards.findOne(_id); diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 306abe799..ec62e6a75 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -852,5 +852,9 @@ "my-cards": "My Cards", "card": "Card", "list": "List", - "board": "Board" + "board": "Board", + "context-separator": "/", + "my-cards-sort": "My Cards Sort", + "my-cards-sort-board": "By Board", + "my-cards-sort-dueat": "By Due Date" } From e55b50bc5ae66718f70b699d4963137a4399fddd Mon Sep 17 00:00:00 2001 From: "John R. Supplee" Date: Thu, 7 Jan 2021 12:04:14 +0200 Subject: [PATCH 2/2] My Cards development * Popup.open() not working so simply toggle between board sort and 'due by' * clean-up CSS classes * code clean-up --- client/components/main/myCards.jade | 55 ++++++++++++++++++----------- client/components/main/myCards.js | 53 +++++++++++++++------------ client/components/main/myCards.styl | 45 ++++------------------- client/lib/utils.js | 8 +++++ 4 files changed, 79 insertions(+), 82 deletions(-) diff --git a/client/components/main/myCards.jade b/client/components/main/myCards.jade index 9688f0967..e16fb8e98 100644 --- a/client/components/main/myCards.jade +++ b/client/components/main/myCards.jade @@ -6,7 +6,8 @@ template(name="myCardsHeaderBar") .board-header-btns.left a.board-header-btn.js-toggle-my-cards-choose-sort(title="{{_ 'my-cards-sort'}}") - i.fa.fa-caret-down + //i.fa.fa-caret-down + i.fa.fa-sort if $eq myCardsSort 'board' i.fa.fa-th-large | {{_ 'my-cards-sort-board'}} @@ -24,32 +25,33 @@ template(name="myCards") if $eq myCardsSort 'board' each board in myBoards .my-cards-board-wrapper - .board-title + .my-cards-board-title +viewer = board.title each swimlane in board.mySwimlanes - .swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}") + .my-cards-swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}") +viewer = swimlane.title each list in swimlane.myLists .my-cards-list-wrapper - .list-title(class=list.colorClass) + .my-cards-list-title(class=list.colorClass) +viewer = list.title each card in list.myCards - a.minicard-wrapper.card-title(href=card.absoluteUrl) - +minicard(card) + .my-cards-card-wrapper + a.minicard-wrapper(href=card.absoluteUrl) + +minicard(card) else .my-cards-dueat-list-wrapper each card in myCardsList - .my-cards-card + .my-cards-card-wrapper a.minicard-wrapper.card-title(href=card.absoluteUrl) +minicard(card) ul.my-cards-context-list li.my-cards-context(title="{{_ 'board'}}") +viewer = card.board.title - li.my-cards-context + li.my-cards-context.my-cards-context-separator = ' ' | {{_ 'context-separator'}} = ' ' @@ -65,19 +67,30 @@ template(name="myCards") = card.list.title -template(name="myCardsSortPopup") +template(name="myCardsSortChangePopup") ul.pop-over-list li - //with "my-cards-sort-board" - a.js-my-cards-sort-board - i.fa.fa-th-large.colorful - | {{_ 'my-cards-sort-board'}} - if $eq Utils.myCardsSort "board" - i.fa.fa-check + with "my-cards-sort-board" + a.js-my-cards-sort-board + i.fa.fa-th-large.colorful + | {{_ 'my-cards-sort-board'}} + if $eq Utils.myCardsSort "board" + i.fa.fa-check li - //with "my-cards-sort-dueat" - a.js-my-cards-sort-dueat - i.fa.fa-calendar.colorful - | {{_ 'my-cards-sort-dueat'}} - if $eq Utils.myCardsSort "dueAt" - i.fa.fa-check + with "my-cards-sort-dueat" + a.js-my-cards-sort-dueat + i.fa.fa-calendar.colorful + | {{_ 'my-cards-sort-dueat'}} + if $eq Utils.myCardsSort "dueAt" + i.fa.fa-check + +//template(name="myCardsSortChangePopup") +// ul.pop-over-list +// li +// a.js-my-cards-sort-board +// i.fa.fa-th-large.colorful +// | {{_ 'my-cards-sort-board'}} +// li +// a.js-my-cards-sort-dueat +// i.fa.fa-calendar.colorful +// | {{_ 'my-cards-sort-dueat'}} diff --git a/client/components/main/myCards.js b/client/components/main/myCards.js index c5e4dde33..7b562c2e5 100644 --- a/client/components/main/myCards.js +++ b/client/components/main/myCards.js @@ -1,7 +1,7 @@ BlazeComponent.extendComponent({ myCardsSort() { // eslint-disable-next-line no-console - console.log('sort:', Utils.myCardsSort()); + // console.log('sort:', Utils.myCardsSort()); return Utils.myCardsSort(); }, @@ -9,9 +9,10 @@ BlazeComponent.extendComponent({ return [ { 'click .js-toggle-my-cards-choose-sort'() { - Popup.open('myCardsSortPopup'); // eslint-disable-next-line no-console - console.log('open sort'); + // console.log('open sort'); + // Popup.open('myCardsSortChange'); + Utils.myCardsSortToggle(); }, }, ]; @@ -24,17 +25,23 @@ Template.myCards.helpers({ }, }); -Template.myCardsSortPopup.events({ - 'click .js-my-cards-sort-board'() { - Utils.setMyCardsSort('board'); - Popup.close(); - }, +BlazeComponent.extendComponent({ + events() { + return [ + { + 'click .js-my-cards-sort-board'() { + Utils.setMyCardsSort('board'); + Popup.close(); + }, - 'click .js-my-cards-sort-dueat'() { - Utils.setMyCardsSort('dueAt'); - Popup.close(); + 'click .js-my-cards-sort-dueat'() { + Utils.setMyCardsSort('dueAt'); + Popup.close(); + }, + }, + ]; }, -}); +}).register('myCardsSortChangePopup'); BlazeComponent.extendComponent({ onCreated() { @@ -214,17 +221,17 @@ BlazeComponent.extendComponent({ events() { return [ { - 'click .js-my-card'(evt) { - const card = this.currentData().card; - // eslint-disable-next-line no-console - console.log('currentData():', this.currentData()); - // eslint-disable-next-line no-console - console.log('card:', card); - if (card) { - Utils.goCardId(card._id); - } - evt.preventDefault(); - }, + // 'click .js-my-card'(evt) { + // const card = this.currentData().card; + // // eslint-disable-next-line no-console + // console.log('currentData():', this.currentData()); + // // eslint-disable-next-line no-console + // console.log('card:', card); + // if (card) { + // Utils.goCardId(card._id); + // } + // evt.preventDefault(); + // }, }, ]; }, diff --git a/client/components/main/myCards.styl b/client/components/main/myCards.styl index 410f02395..27cbdaa08 100644 --- a/client/components/main/myCards.styl +++ b/client/components/main/myCards.styl @@ -1,24 +1,3 @@ -.my-cards-list - .my-cards-list-item - border-bottom: 1px solid darken(white, 25%) - padding: 10px 5px - - &:last-child - border-bottom: none - - .my-cards-list-item-keys - margin-top: 5px - float: right - - kbd - padding: 5px 8px - margin: 5px - font-size: 18px - - .my-cards-list-item-action - font-size: 1.4em - margin: 5px - .my-cards-board-wrapper border-radius: 8px //padding: 0.5rem @@ -30,14 +9,14 @@ margin-right: auto margin-left: auto -.board-title +.my-cards-board-title font-size: 1.4rem font-weight: bold padding: 0.5rem background-color: grey color: white -.swimlane-title +.my-cards-swimlane-title font-size: 1.1rem font-weight: bold padding: 0.5rem @@ -51,7 +30,7 @@ .swimlane-default-color background-color: lightgrey -.list-title +.my-cards-list-title font-weight: bold font-size: 1.1rem //padding-bottom: 0 @@ -59,15 +38,8 @@ text-align: center margin-bottom: 0.7rem -.list-color-bar - //height: 0.3rem - margin-bottom: 0.3rem - margin-top: 0 - padding-top: 0 - .my-cards-list-wrapper margin: 1rem - margin-top: 1rem border-radius: 5px padding: 1.5rem padding-top: 0.75rem @@ -75,7 +47,7 @@ min-width: 250px max-width: 350px -.card-title +.my-cards-card-wrapper margin-top: 0 margin-bottom: 10px @@ -87,14 +59,11 @@ .my-cards-field-name font-weight: bold -.my-cards-dueat-list - columns: 2 - .my-cards-context display: inline-block +.my-cards-context-separator + font-weight: bold + .my-cards-context-list margin-bottom: 0.7rem - -.my-cards-context-item - display: inline-block diff --git a/client/lib/utils.js b/client/lib/utils.js index f697c84da..94d7ed017 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -56,6 +56,14 @@ Utils = { return sort; }, + myCardsSortToggle() { + if (this.myCardsSort() === 'board') { + this.setMyCardsSort('dueAt'); + } else { + this.setMyCardsSort('board'); + } + }, + setMyCardsSort(sort) { window.localStorage.setItem('myCardsSort', sort); location.reload();