From 9bbdacc79a89667e0d6f1ed30c415e5350ad468b Mon Sep 17 00:00:00 2001 From: Liming Xie Date: Tue, 5 Jan 2016 23:26:02 +0800 Subject: Add notification, allow watch boards / lists / cards --- client/components/activities/activities.js | 2 +- client/components/boards/boardHeader.jade | 49 ++++++++++++++++++++++++++++++ client/components/boards/boardHeader.js | 28 +++++++++++++++++ client/components/cards/cardDetails.jade | 5 +++ client/components/cards/cardDetails.js | 18 +++++++++++ client/components/cards/cardDetails.styl | 5 +++ client/components/lists/list.styl | 4 +++ client/components/lists/listHeader.jade | 5 +++ client/components/lists/listHeader.js | 18 +++++++++++ client/components/main/header.styl | 3 ++ client/components/main/layouts.styl | 5 ++- client/components/users/userHeader.jade | 18 +++++++++++ client/components/users/userHeader.js | 20 ++++++++++++ 13 files changed, 178 insertions(+), 2 deletions(-) (limited to 'client') diff --git a/client/components/activities/activities.js b/client/components/activities/activities.js index f6417380..0bd6a272 100644 --- a/client/components/activities/activities.js +++ b/client/components/activities/activities.js @@ -51,7 +51,7 @@ BlazeComponent.extendComponent({ cardLink() { const card = this.currentData().card(); return card && Blaze.toHTML(HTML.A({ - href: FlowRouter.path(card.absoluteUrl()), + href: card.absoluteUrl(), 'class': 'action-card', }, card.title)); }, diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade index fe6b56e6..ce8999c3 100644 --- a/client/components/boards/boardHeader.jade +++ b/client/components/boards/boardHeader.jade @@ -19,6 +19,17 @@ template(name="boardHeaderBar") i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") span {{_ currentBoard.permission}} + a.board-header-btn.js-watch-board + if $eq watchLevel "watching" + i.fa.fa-eye + span {{_ 'watching'}} + if $eq watchLevel "tracking" + i.fa.fa-user + span {{_ 'tracking'}} + if $eq watchLevel "muted" + i.fa.fa-times-circle + span {{_ 'muted'}} + .board-header-btns.right if isMiniScreen unless isSandstorm @@ -34,6 +45,17 @@ template(name="boardHeaderBar") i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") span {{_ currentBoard.permission}} + a.board-header-btn.js-watch-board + if $eq watchLevel "watching" + i.fa.fa-eye + span {{_ 'watching'}} + if $eq watchLevel "tracking" + i.fa.fa-user + span {{_ 'tracking'}} + if $eq watchLevel "muted" + i.fa.fa-times-circle + span {{_ 'muted'}} + a.board-header-btn.js-open-filter-view( title="{{#if Filter.isActive}}{{_ 'filter-on-desc'}}{{/if}}" class="{{#if Filter.isActive}}emphasis{{/if}}") @@ -97,6 +119,33 @@ template(name="boardVisibilityList") template(name="boardChangeVisibilityPopup") +boardVisibilityList +template(name="boardChangeWatchPopup") + ul.pop-over-list + li + with "watching" + a.js-select-watch + i.fa.fa-eye.colorful + | {{_ 'watching'}} + if watchCheck + i.fa.fa-check + span.sub-name {{_ 'watching-info'}} + li + with "tracking" + a.js-select-watch + i.fa.fa-user.colorful + | {{_ 'tracking'}} + if watchCheck + i.fa.fa-check + span.sub-name {{_ 'tracking-info'}} + li + with "muted" + a.js-select-watch + i.fa.fa-times-circle.colorful + | {{_ 'muted'}} + if watchCheck + i.fa.fa-check + span.sub-name {{_ 'muted-info'}} + template(name="boardChangeColorPopup") .board-backgrounds-list.clearfix each backgroundColors diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index acf40f44..567f14ac 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -41,6 +41,11 @@ Template.boardChangeTitlePopup.events({ }); BlazeComponent.extendComponent({ + watchLevel() { + const currentBoard = Boards.findOne(Session.get('currentBoard')); + return currentBoard.getWatchLevel(Meteor.userId()); + }, + isStarred() { const boardId = Session.get('currentBoard'); const user = Meteor.user(); @@ -65,6 +70,7 @@ BlazeComponent.extendComponent({ }, 'click .js-open-board-menu': Popup.open('boardMenu'), 'click .js-change-visibility': Popup.open('boardChangeVisibility'), + 'click .js-watch-board': Popup.open('boardChangeWatch'), 'click .js-open-filter-view'() { Sidebar.setView('filter'); }, @@ -176,3 +182,25 @@ BlazeComponent.extendComponent({ }]; }, }).register('boardChangeVisibilityPopup'); + +BlazeComponent.extendComponent({ + watchLevel() { + const currentBoard = Boards.findOne(Session.get('currentBoard')); + return currentBoard.getWatchLevel(Meteor.userId()); + }, + + watchCheck() { + return this.currentData() === this.watchLevel(); + }, + + events() { + return [{ + 'click .js-select-watch'() { + const level = this.currentData(); + Meteor.call('watch', 'board', Session.get('currentBoard'), level, (err, ret) => { + if (!err && ret) Popup.close(); + }); + }, + }]; + }, +}).register('boardChangeWatchPopup'); diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 3f2ae34a..2ca032ef 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -10,6 +10,8 @@ template(name="cardDetails") h2.card-details-title.js-card-title( class="{{#if currentUser.isBoardMember}}js-open-inlined-form is-editable{{/if}}") = title + if isWatching + i.fa.fa-eye.card-details-watch if archived p.warning {{_ 'card-archived'}} @@ -82,6 +84,9 @@ template(name="editCardTitleForm") a.fa.fa-times-thin.js-close-inlined-form template(name="cardDetailsActionsPopup") + ul.pop-over-list + li: a.js-toggle-watch-card {{#if isWatching}}{{_ 'unwatch'}}{{else}}{{_ 'watch'}}{{/if}} + hr ul.pop-over-list li: a.js-members {{_ 'card-edit-members'}} li: a.js-labels {{_ 'card-edit-labels'}} diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 2b04adad..d8323393 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -23,6 +23,11 @@ BlazeComponent.extendComponent({ this.calculateNextPeak(); }, + isWatching() { + const card = this.currentData(); + return card.findWatcher(Meteor.userId()); + }, + scrollParentContainer() { const cardPanelWidth = 510; const bodyBoardComponent = this.parentComponent(); @@ -128,6 +133,12 @@ BlazeComponent.extendComponent({ } }).register('inlinedCardDescription'); +Template.cardDetailsActionsPopup.helpers({ + isWatching() { + return this.findWatcher(Meteor.userId()); + }, +}); + Template.cardDetailsActionsPopup.events({ 'click .js-members': Popup.open('cardMembers'), 'click .js-labels': Popup.open('cardLabels'), @@ -139,6 +150,13 @@ Template.cardDetailsActionsPopup.events({ Popup.close(); }, 'click .js-more': Popup.open('cardMore'), + 'click .js-toggle-watch-card'() { + const currentCard = this; + const level = currentCard.findWatcher(Meteor.userId()) ? null : 'watching'; + Meteor.call('watch', 'card', currentCard._id, level, (err, ret) => { + if (!err && ret) Popup.close(); + }); + }, }); Template.editCardTitleForm.onRendered(function() { diff --git a/client/components/cards/cardDetails.styl b/client/components/cards/cardDetails.styl index 4ac0578b..d7d29551 100644 --- a/client/components/cards/cardDetails.styl +++ b/client/components/cards/cardDetails.styl @@ -36,6 +36,11 @@ font-size: 17px padding: 10px + .card-details-watch + font-size: 17px + padding-left: 7px + color: #a6a6a6 + .card-details-title font-weight: bold font-size: 1.33em diff --git a/client/components/lists/list.styl b/client/components/lists/list.styl index 1848459c..cf939a6e 100644 --- a/client/components/lists/list.styl +++ b/client/components/lists/list.styl @@ -65,6 +65,10 @@ text-overflow: ellipsis word-wrap: break-word + .list-header-watch-icon + padding-left: 10px + color: #a6a6a6 + .list-header-menu-icon position: absolute padding: 7px diff --git a/client/components/lists/listHeader.jade b/client/components/lists/listHeader.jade index 34824085..f9fe065f 100644 --- a/client/components/lists/listHeader.jade +++ b/client/components/lists/listHeader.jade @@ -7,6 +7,8 @@ template(name="listHeader") class="{{#if currentUser.isBoardMember}}js-open-inlined-form is-editable{{/if}}") = title if currentUser.isBoardMember + if isWatching + i.list-header-watch-icon.fa.fa-eye a.list-header-menu-icon.fa.fa-navicon.js-open-list-menu template(name="editListTitleForm") @@ -17,6 +19,9 @@ template(name="editListTitleForm") a.fa.fa-times-thin.js-close-inlined-form template(name="listActionPopup") + ul.pop-over-list + li: a.js-toggle-watch-list {{#if isWatching}}{{_ 'unwatch'}}{{else}}{{_ 'watch'}}{{/if}} + hr ul.pop-over-list li: a.js-add-card {{_ 'add-card'}} if cards.count diff --git a/client/components/lists/listHeader.js b/client/components/lists/listHeader.js index c9eaee12..c7ae8e62 100644 --- a/client/components/lists/listHeader.js +++ b/client/components/lists/listHeader.js @@ -8,6 +8,11 @@ BlazeComponent.extendComponent({ } }, + isWatching() { + const list = this.currentData(); + return list.findWatcher(Meteor.userId()); + }, + events() { return [{ 'click .js-open-list-menu': Popup.open('listAction'), @@ -16,6 +21,12 @@ BlazeComponent.extendComponent({ }, }).register('listHeader'); +Template.listActionPopup.helpers({ + isWatching() { + return this.findWatcher(Meteor.userId()); + }, +}); + Template.listActionPopup.events({ 'click .js-add-card'() { const listDom = document.getElementById(`js-list-${this._id}`); @@ -29,6 +40,13 @@ Template.listActionPopup.events({ MultiSelection.add(cardIds); Popup.close(); }, + 'click .js-toggle-watch-list'() { + const currentList = this; + const level = currentList.findWatcher(Meteor.userId()) ? null : 'watching'; + Meteor.call('watch', 'list', currentList._id, level, (err, ret) => { + if (!err && ret) Popup.close(); + }); + }, 'click .js-close-list'(evt) { evt.preventDefault(); this.archive(); diff --git a/client/components/main/header.styl b/client/components/main/header.styl index fbf2992d..0b2ad860 100644 --- a/client/components/main/header.styl +++ b/client/components/main/header.styl @@ -18,6 +18,9 @@ float: left border-radius: 3px + .board-header-watch-icon + padding-left: 7px + a.fa, a i.fa color: white diff --git a/client/components/main/layouts.styl b/client/components/main/layouts.styl index b364d91b..7ab4d8ce 100644 --- a/client/components/main/layouts.styl +++ b/client/components/main/layouts.styl @@ -279,9 +279,12 @@ kbd .fa.fa-globe.colorful color: #4caf50 -.fa.fa-lock.colorful +.fa.fa-lock.colorful, .fa.fa-times-circle.colorful color: #f44336 +.fa.fa-user.colorful, .fa.fa-eye.colorful, .fa.fa-circle.colorful + color: #4336f4 + .pop-over .pop-over-list li a:not(.disabled):hover .fa, .fa.colorful color: white diff --git a/client/components/users/userHeader.jade b/client/components/users/userHeader.jade index 8e988c8e..cae768fb 100644 --- a/client/components/users/userHeader.jade +++ b/client/components/users/userHeader.jade @@ -15,6 +15,7 @@ template(name="memberMenuPopup") li: a.js-change-avatar {{_ 'edit-avatar'}} li: a.js-change-password {{_ 'changePasswordPopup-title'}} li: a.js-change-language {{_ 'changeLanguagePopup-title'}} + li: a.js-edit-notification {{_ 'editNotificationPopup-title'}} hr ul.pop-over-list li: a.js-logout {{_ 'log-out'}} @@ -32,6 +33,23 @@ template(name="editProfilePopup") input.js-profile-initials(type="text" value=profile.initials) input.primary.wide(type="submit" value="{{_ 'save'}}") +template(name="editNotificationPopup") + ul.pop-over-list + li + a.js-toggle-tag-notify-watch + i.fa.fa-eye.colorful + | {{_ 'watching'}} + if hasTag "notify-watch" + i.fa.fa-check + span.sub-name {{_ 'notify-watch'}} + li + a.js-toggle-tag-notify-participate + i.fa.fa-user.colorful + | {{_ 'tracking'}} + if hasTag "notify-participate" + i.fa.fa-check + span.sub-name {{_ 'notify-participate'}} + template(name="changePasswordPopup") +atForm(state='changePwd') diff --git a/client/components/users/userHeader.js b/client/components/users/userHeader.js index a478da0c..10fdf699 100644 --- a/client/components/users/userHeader.js +++ b/client/components/users/userHeader.js @@ -8,6 +8,7 @@ Template.memberMenuPopup.events({ 'click .js-change-avatar': Popup.open('changeAvatar'), 'click .js-change-password': Popup.open('changePassword'), 'click .js-change-language': Popup.open('changeLanguage'), + 'click .js-edit-notification': Popup.open('editNotification'), 'click .js-logout'(evt) { evt.preventDefault(); @@ -33,6 +34,25 @@ Template.editProfilePopup.events({ }, }); +Template.editNotificationPopup.helpers({ + hasTag(tag) { + const user = Meteor.user(); + return user && user.hasTag(tag); + }, +}); + +// we defined github like rules, see: https://github.com/settings/notifications +Template.editNotificationPopup.events({ + 'click .js-toggle-tag-notify-participate'() { + const user = Meteor.user(); + if (user) user.toggleTag('notify-participate'); + }, + 'click .js-toggle-tag-notify-watch'() { + const user = Meteor.user(); + if (user) user.toggleTag('notify-watch'); + }, +}); + // XXX For some reason the useraccounts autofocus isnt working in this case. // See https://github.com/meteor-useraccounts/core/issues/384 Template.changePasswordPopup.onRendered(function() { -- cgit v1.2.3-1-g7c22