diff options
Diffstat (limited to 'client/components')
25 files changed, 737 insertions, 800 deletions
diff --git a/client/components/activities/activities.js b/client/components/activities/activities.js index 400e3848..d6a0cf7f 100644 --- a/client/components/activities/activities.js +++ b/client/components/activities/activities.js @@ -1,99 +1,98 @@ -var activitiesPerPage = 20; +const activitiesPerPage = 20; BlazeComponent.extendComponent({ - template: function() { + template() { return 'activities'; }, - onCreated: function() { - var self = this; + onCreated() { // XXX Should we use ReactiveNumber? - self.page = new ReactiveVar(1); - self.loadNextPageLocked = false; - var sidebar = self.componentParent(); // XXX for some reason not working + this.page = new ReactiveVar(1); + this.loadNextPageLocked = false; + const sidebar = this.componentParent(); // XXX for some reason not working sidebar.callFirstWith(null, 'resetNextPeak'); - self.autorun(function() { - var mode = self.data().mode; - var capitalizedMode = Utils.capitalize(mode); - var id = Session.get('current' + capitalizedMode); - var limit = self.page.get() * activitiesPerPage; + this.autorun(() => { + const mode = this.data().mode; + const capitalizedMode = Utils.capitalize(mode); + const id = Session.get(`current${capitalizedMode}`); + const limit = this.page.get() * activitiesPerPage; if (id === null) return; - self.subscribe('activities', mode, id, limit, function() { - self.loadNextPageLocked = false; + this.subscribe('activities', mode, id, limit, () => { + this.loadNextPageLocked = false; // If the sibear peak hasn't increased, that mean that there are no more // activities, and we can stop calling new subscriptions. // XXX This is hacky! We need to know excatly and reactively how many // activities there are, we probably want to denormalize this number // dirrectly into card and board documents. - var a = sidebar.callFirstWith(null, 'getNextPeak'); + const nextPeakBefore = sidebar.callFirstWith(null, 'getNextPeak'); sidebar.calculateNextPeak(); - var b = sidebar.callFirstWith(null, 'getNextPeak'); - if (a === b) { + const nextPeakAfter = sidebar.callFirstWith(null, 'getNextPeak'); + if (nextPeakBefore === nextPeakAfter) { sidebar.callFirstWith(null, 'resetNextPeak'); } }); }); }, - loadNextPage: function() { + loadNextPage() { if (this.loadNextPageLocked === false) { this.page.set(this.page.get() + 1); this.loadNextPageLocked = true; } }, - boardLabel: function() { + boardLabel() { return TAPi18n.__('this-board'); }, - cardLabel: function() { + cardLabel() { return TAPi18n.__('this-card'); }, - cardLink: function() { - var card = this.currentData().card(); + cardLink() { + const card = this.currentData().card(); return card && Blaze.toHTML(HTML.A({ href: card.absoluteUrl(), - 'class': 'action-card' + 'class': 'action-card', }, card.title)); }, - memberLink: function() { + memberLink() { return Blaze.toHTMLWithData(Template.memberName, { - user: this.currentData().member() + user: this.currentData().member(), }); }, - attachmentLink: function() { - var attachment = this.currentData().attachment(); + attachmentLink() { + const attachment = this.currentData().attachment(); return attachment && Blaze.toHTML(HTML.A({ href: attachment.url(), - 'class': 'js-open-attachment-viewer' + 'class': 'js-open-attachment-viewer', }, attachment.name())); }, - events: function() { + events() { return [{ // XXX We should use Popup.afterConfirmation here - 'click .js-delete-comment': function() { - var commentId = this.currentData().commentId; + 'click .js-delete-comment'() { + const commentId = this.currentData().commentId; CardComments.remove(commentId); }, - 'submit .js-edit-comment': function(evt) { + 'submit .js-edit-comment'(evt) { evt.preventDefault(); - var commentText = this.currentComponent().getValue(); - var commentId = Template.parentData().commentId; + const commentText = this.currentComponent().getValue(); + const commentId = Template.parentData().commentId; if ($.trim(commentText)) { CardComments.update(commentId, { $set: { - text: commentText - } + text: commentText, + }, }); } - } + }, }]; - } + }, }).register('activities'); diff --git a/client/components/activities/comments.js b/client/components/activities/comments.js index e3a82c4b..08401caa 100644 --- a/client/components/activities/comments.js +++ b/client/components/activities/comments.js @@ -1,4 +1,4 @@ -let commentFormIsOpen = new ReactiveVar(false); +const commentFormIsOpen = new ReactiveVar(false); BlazeComponent.extendComponent({ template() { @@ -19,16 +19,16 @@ BlazeComponent.extendComponent({ events() { return [{ - 'click .js-new-comment:not(.focus)': function() { + 'click .js-new-comment:not(.focus)'() { commentFormIsOpen.set(true); }, - 'submit .js-new-comment-form': function(evt) { - let input = this.getInput(); + 'submit .js-new-comment-form'(evt) { + const input = this.getInput(); if ($.trim(input.val())) { CardComments.insert({ boardId: this.currentData().boardId, cardId: this.currentData()._id, - text: input.val() + text: input.val(), }); resetCommentInput(input); Tracker.flush(); @@ -37,13 +37,13 @@ BlazeComponent.extendComponent({ evt.preventDefault(); }, // Pressing Ctrl+Enter should submit the form - 'keydown form textarea': function(evt) { + 'keydown form textarea'(evt) { if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) { this.find('button[type=submit]').click(); } - } + }, }]; - } + }, }).register('commentForm'); // XXX This should be a static method of the `commentForm` component @@ -63,15 +63,15 @@ Tracker.autorun(() => { Tracker.afterFlush(() => { autosize.update($('.js-new-comment-input')); }); -}) +}); EscapeActions.register('inlinedForm', - function() { + () => { const draftKey = { fieldName: 'cardComment', - docId: Session.get('currentCard') + docId: Session.get('currentCard'), }; - let commentInput = $('.js-new-comment-input'); + const commentInput = $('.js-new-comment-input'); if ($.trim(commentInput.val())) { UnsavedEdits.set(draftKey, commentInput.val()); } else { @@ -79,7 +79,7 @@ EscapeActions.register('inlinedForm', } resetCommentInput(commentInput); }, - function() { return commentFormIsOpen.get(); }, { - noClickEscapeOn: '.js-new-comment' + () => { return commentFormIsOpen.get(); }, { + noClickEscapeOn: '.js-new-comment', } ); diff --git a/client/components/boards/boardArchive.js b/client/components/boards/boardArchive.js index 1ce1a593..9d7ca7f2 100644 --- a/client/components/boards/boardArchive.js +++ b/client/components/boards/boardArchive.js @@ -1,8 +1,8 @@ Template.headerTitle.events({ - 'click .js-open-archived-board': function() { - Modal.open('archivedBoards') - } -}) + 'click .js-open-archived-board'() { + Modal.open('archivedBoards'); + }, +}); BlazeComponent.extendComponent({ template() { @@ -10,26 +10,26 @@ BlazeComponent.extendComponent({ }, onCreated() { - this.subscribe('archivedBoards') + this.subscribe('archivedBoards'); }, archivedBoards() { return Boards.find({ archived: true }, { - sort: ['title'] - }) + sort: ['title'], + }); }, events() { return [{ - 'click .js-restore-board': function() { - let boardId = this.currentData()._id + 'click .js-restore-board'() { + const boardId = this.currentData()._id; Boards.update(boardId, { $set: { - archived: false - } - }) - Utils.goBoardId(boardId) - } - }] + archived: false, + }, + }); + Utils.goBoardId(boardId); + }, + }]; }, -}).register('archivedBoards') +}).register('archivedBoards'); diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index fd9ee6bc..980a9015 100644 --- a/client/components/boards/boardBody.js +++ b/client/components/boards/boardBody.js @@ -1,11 +1,11 @@ -var subManager = new SubsManager(); +const subManager = new SubsManager(); BlazeComponent.extendComponent({ - template: function() { + template() { return 'board'; }, - onCreated: function() { + onCreated() { this.draggingActive = new ReactiveVar(false); this.showOverlay = new ReactiveVar(false); this.isBoardReady = new ReactiveVar(false); @@ -15,15 +15,15 @@ BlazeComponent.extendComponent({ // XXX The boardId should be readed from some sort the component "props", // unfortunatly, Blaze doesn't have this notion. this.autorun(() => { - let currentBoardId = Session.get('currentBoard'); - if (! currentBoardId) + const currentBoardId = Session.get('currentBoard'); + if (!currentBoardId) return; - var handle = subManager.subscribe('board', currentBoardId); + const handle = subManager.subscribe('board', currentBoardId); Tracker.nonreactive(() => { Tracker.autorun(() => { this.isBoardReady.set(handle.ready()); - }) - }) + }); + }); }); this._isDragging = false; @@ -33,52 +33,52 @@ BlazeComponent.extendComponent({ this.mouseHasEnterCardDetails = false; }, - openNewListForm: function() { + openNewListForm() { this.componentChildren('addListForm')[0].open(); }, // XXX Flow components allow us to avoid creating these two setter methods by // exposing a public API to modify the component state. We need to investigate // best practices here. - setIsDragging: function(bool) { + setIsDragging(bool) { this.draggingActive.set(bool); }, - scrollLeft: function(position = 0) { + scrollLeft(position = 0) { this.$('.js-lists').animate({ - scrollLeft: position + scrollLeft: position, }); }, - currentCardIsInThisList: function() { - var currentCard = Cards.findOne(Session.get('currentCard')); - var listId = this.currentData()._id; + currentCardIsInThisList() { + const currentCard = Cards.findOne(Session.get('currentCard')); + const listId = this.currentData()._id; return currentCard && currentCard.listId === listId; }, - events: function() { + events() { return [{ // XXX The board-overlay div should probably be moved to the parent // component. - 'mouseenter .board-overlay': function() { + 'mouseenter .board-overlay'() { if (this.mouseHasEnterCardDetails) { this.showOverlay.set(false); } }, // Click-and-drag action - 'mousedown .board-canvas': function(evt) { + 'mousedown .board-canvas'(evt) { if ($(evt.target).closest('a,.js-list-header').length === 0) { this._isDragging = true; this._lastDragPositionX = evt.clientX; } }, - 'mouseup': function(evt) { + 'mouseup'() { if (this._isDragging) { this._isDragging = false; } }, - 'mousemove': function(evt) { + 'mousemove'(evt) { if (this._isDragging) { // Update the canvas position this.listsDom.scrollLeft -= evt.clientX - this._lastDragPositionX; @@ -91,40 +91,40 @@ BlazeComponent.extendComponent({ EscapeActions.executeUpTo('popup-close'); EscapeActions.preventNextClick(); } - } + }, }]; - } + }, }).register('board'); Template.boardBody.onRendered(function() { - var self = BlazeComponent.getComponentForElement(this.firstNode); + const self = BlazeComponent.getComponentForElement(this.firstNode); self.listsDom = this.find('.js-lists'); - if (! Session.get('currentCard')) { + if (!Session.get('currentCard')) { self.scrollLeft(); } // We want to animate the card details window closing. We rely on CSS // transition for the actual animation. self.listsDom._uihooks = { - removeElement: function(node) { - var removeNode = _.once(function() { + removeElement(node) { + const removeNode = _.once(() => { node.parentNode.removeChild(node); }); if ($(node).hasClass('js-card-details')) { $(node).css({ flexBasis: 0, - padding: 0 + padding: 0, }); $(self.listsDom).one(CSSEvents.transitionend, removeNode); } else { removeNode(); } - } + }, }; - if (! Meteor.user() || ! Meteor.user().isBoardMember()) + if (!Meteor.user() || !Meteor.user().isBoardMember()) return; self.$(self.listsDom).sortable({ @@ -134,63 +134,63 @@ Template.boardBody.onRendered(function() { items: '.js-list:not(.js-list-composer)', placeholder: 'list placeholder', distance: 7, - start: function(evt, ui) { + start(evt, ui) { ui.placeholder.height(ui.helper.height()); Popup.close(); }, - stop: function() { + stop() { self.$('.js-lists').find('.js-list:not(.js-list-composer)').each( - function(i, list) { - var data = Blaze.getData(list); + (i, list) => { + const data = Blaze.getData(list); Lists.update(data._id, { $set: { - sort: i - } + sort: i, + }, }); } ); - } + }, }); // Disable drag-dropping while in multi-selection mode - self.autorun(function() { + self.autorun(() => { self.$(self.listsDom).sortable('option', 'disabled', MultiSelection.isActive()); }); // If there is no data in the board (ie, no lists) we autofocus the list // creation form by clicking on the corresponding element. - var currentBoard = Boards.findOne(Session.get('currentBoard')); + const currentBoard = Boards.findOne(Session.get('currentBoard')); if (currentBoard.lists().count() === 0) { self.openNewListForm(); } }); BlazeComponent.extendComponent({ - template: function() { + template() { return 'addListForm'; }, // Proxy - open: function() { + open() { this.componentChildren('inlinedForm')[0].open(); }, - events: function() { + events() { return [{ - submit: function(evt) { + submit(evt) { evt.preventDefault(); - var title = this.find('.list-name-input'); + const title = this.find('.list-name-input'); if ($.trim(title.value)) { Lists.insert({ title: title.value, boardId: Session.get('currentBoard'), - sort: $('.list').length + sort: $('.list').length, }); title.value = ''; } - } + }, }]; - } + }, }).register('addListForm'); diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index d23dd5f2..5d13fa34 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -1,143 +1,143 @@ Template.boardMenuPopup.events({ 'click .js-rename-board': Popup.open('boardChangeTitle'), - 'click .js-open-archives': function() { + 'click .js-open-archives'() { Sidebar.setView('archives'); Popup.close(); }, 'click .js-change-board-color': Popup.open('boardChangeColor'), 'click .js-change-language': Popup.open('changeLanguage'), - 'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() { - var boardId = Session.get('currentBoard'); + 'click .js-archive-board ': Popup.afterConfirm('archiveBoard', () => { + const boardId = Session.get('currentBoard'); Boards.update(boardId, { $set: { archived: true }}); // XXX We should have some kind of notification on top of the page to // confirm that the board was successfully archived. FlowRouter.go('home'); - }) + }), }); Template.boardChangeTitlePopup.events({ - submit: function(evt, t) { - var title = t.$('.js-board-name').val().trim(); + submit(evt, tpl) { + const title = tpl.$('.js-board-name').val().trim(); if (title) { Boards.update(this._id, { $set: { - title: title - } + title, + }, }); Popup.close(); } evt.preventDefault(); - } + }, }); BlazeComponent.extendComponent({ - template: function() { + template() { return 'headerBoard'; }, - isStarred: function() { - var boardId = Session.get('currentBoard'); - var user = Meteor.user(); + isStarred() { + const boardId = Session.get('currentBoard'); + const user = Meteor.user(); return user && user.hasStarred(boardId); }, // Only show the star counter if the number of star is greater than 2 - showStarCounter: function() { - var currentBoard = this.currentData(); + showStarCounter() { + const currentBoard = this.currentData(); return currentBoard && currentBoard.stars >= 2; }, - events: function() { + events() { return [{ 'click .js-edit-board-title': Popup.open('boardChangeTitle'), - 'click .js-star-board': function() { + 'click .js-star-board'() { Meteor.user().toggleBoardStar(Session.get('currentBoard')); }, 'click .js-open-board-menu': Popup.open('boardMenu'), 'click .js-change-visibility': Popup.open('boardChangeVisibility'), - 'click .js-open-filter-view': function() { + 'click .js-open-filter-view'() { Sidebar.setView('filter'); }, - 'click .js-filter-reset': function(evt) { + 'click .js-filter-reset'(evt) { evt.stopPropagation(); Sidebar.setView(); Filter.reset(); }, - 'click .js-multiselection-activate': function() { - var currentCard = Session.get('currentCard'); + 'click .js-multiselection-activate'() { + const currentCard = Session.get('currentCard'); MultiSelection.activate(); if (currentCard) { MultiSelection.add(currentCard); } }, - 'click .js-multiselection-reset': function(evt) { + 'click .js-multiselection-reset'(evt) { evt.stopPropagation(); MultiSelection.disable(); - } + }, }]; - } + }, }).register('headerBoard'); BlazeComponent.extendComponent({ - template: function() { + template() { return 'boardChangeColorPopup'; }, - backgroundColors: function() { + backgroundColors() { return Boards.simpleSchema()._schema.color.allowedValues; }, - isSelected: function() { - var currentBoard = Boards.findOne(Session.get('currentBoard')); + isSelected() { + const currentBoard = Boards.findOne(Session.get('currentBoard')); return currentBoard.color === this.currentData().toString(); }, - events: function() { + events() { return [{ - 'click .js-select-background': function(evt) { - var currentBoardId = Session.get('currentBoard'); + 'click .js-select-background'(evt) { + const currentBoardId = Session.get('currentBoard'); Boards.update(currentBoardId, { $set: { - color: this.currentData().toString() - } + color: this.currentData().toString(), + }, }); evt.preventDefault(); - } + }, }]; - } + }, }).register('boardChangeColorPopup'); BlazeComponent.extendComponent({ - template: function() { + template() { return 'createBoardPopup'; }, - onCreated: function() { + onCreated() { this.visibilityMenuIsOpen = new ReactiveVar(false); this.visibility = new ReactiveVar('private'); }, - visibilityCheck: function() { + visibilityCheck() { return this.currentData() === this.visibility.get(); }, - setVisibility: function(visibility) { + setVisibility(visibility) { this.visibility.set(visibility); this.visibilityMenuIsOpen.set(false); }, - toogleVisibilityMenu: function() { - this.visibilityMenuIsOpen.set(! this.visibilityMenuIsOpen.get()); + toogleVisibilityMenu() { + this.visibilityMenuIsOpen.set(!this.visibilityMenuIsOpen.get()); }, - onSubmit: function(evt) { + onSubmit(evt) { evt.preventDefault(); - var title = this.find('.js-new-board-title').value; - var visibility = this.visibility.get(); + const title = this.find('.js-new-board-title').value; + const visibility = this.visibility.get(); - var boardId = Boards.insert({ - title: title, - permission: visibility + const boardId = Boards.insert({ + title, + permission: visibility, }); Utils.goBoardId(boardId); @@ -146,39 +146,39 @@ BlazeComponent.extendComponent({ Meteor.user().toggleBoardStar(boardId); }, - events: function() { + events() { return [{ - 'click .js-select-visibility': function() { + 'click .js-select-visibility'() { this.setVisibility(this.currentData()); }, 'click .js-change-visibility': this.toogleVisibilityMenu, - submit: this.onSubmit + submit: this.onSubmit, }]; - } + }, }).register('createBoardPopup'); BlazeComponent.extendComponent({ - template: function() { + template() { return 'boardChangeVisibilityPopup'; }, - visibilityCheck: function() { - var currentBoard = Boards.findOne(Session.get('currentBoard')); + visibilityCheck() { + const currentBoard = Boards.findOne(Session.get('currentBoard')); return this.currentData() === currentBoard.permission; }, - selectBoardVisibility: function() { + selectBoardVisibility() { Boards.update(Session.get('currentBoard'), { $set: { - permission: this.currentData() - } + permission: this.currentData(), + }, }); Popup.close(); }, - events: function() { + events() { return [{ - 'click .js-select-visibility': this.selectBoardVisibility + 'click .js-select-visibility': this.selectBoardVisibility, }]; - } + }, }).register('boardChangeVisibilityPopup'); diff --git a/client/components/boards/boardsList.js b/client/components/boards/boardsList.js index 2311e7d0..1a2d3c9a 100644 --- a/client/components/boards/boardsList.js +++ b/client/components/boards/boardsList.js @@ -1,30 +1,30 @@ BlazeComponent.extendComponent({ - template: function() { + template() { return 'boardList'; }, - boards: function() { + boards() { return Boards.find({ archived: false, - 'members.userId': Meteor.userId() + 'members.userId': Meteor.userId(), }, { - sort: ['title'] + sort: ['title'], }); }, - isStarred: function() { - var user = Meteor.user(); + isStarred() { + const user = Meteor.user(); return user && user.hasStarred(this.currentData()._id); }, - events: function() { + events() { return [{ 'click .js-add-board': Popup.open('createBoard'), - 'click .js-star-board': function(evt) { - var boardId = this.currentData()._id; + 'click .js-star-board'(evt) { + const boardId = this.currentData()._id; Meteor.user().toggleBoardStar(boardId); evt.preventDefault(); - } + }, }]; - } + }, }).register('boardList'); diff --git a/client/components/cards/attachments.js b/client/components/cards/attachments.js index 9e299cc0..ba56aa1a 100644 --- a/client/components/cards/attachments.js +++ b/client/components/cards/attachments.js @@ -1,32 +1,32 @@ Template.attachmentsGalery.events({ 'click .js-add-attachment': Popup.open('cardAttachments'), 'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', - function() { + () => { Attachments.remove(this._id); Popup.close(); } ), // If we let this event bubble, FlowRouter will handle it and empty the page // content, see #101. - 'click .js-download': function(event) { + 'click .js-download'(event) { event.stopPropagation(); }, - 'click .js-open-viewer': function() { + 'click .js-open-viewer'() { // XXX Not implemented! }, - 'click .js-add-cover': function() { + 'click .js-add-cover'() { Cards.update(this.cardId, { $set: { coverId: this._id } }); }, - 'click .js-remove-cover': function() { + 'click .js-remove-cover'() { Cards.update(this.cardId, { $unset: { coverId: '' } }); - } + }, }); Template.cardAttachmentsPopup.events({ - 'change .js-attach-file': function(evt) { - var card = this; - FS.Utility.eachFile(evt, function(f) { - var file = new FS.File(f); + 'change .js-attach-file'(evt) { + const card = this; + FS.Utility.eachFile(evt, (f) => { + const file = new FS.File(f); file.boardId = card.boardId; file.cardId = card._id; @@ -34,8 +34,8 @@ Template.cardAttachmentsPopup.events({ Popup.close(); }); }, - 'click .js-computer-upload': function(evt, tpl) { + 'click .js-computer-upload'(evt, tpl) { tpl.find('.js-attach-file').click(); evt.preventDefault(); - } + }, }); diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index aba7254a..69e0cfdd 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -1,39 +1,39 @@ BlazeComponent.extendComponent({ - template: function() { + template() { return 'cardDetails'; }, - mixins: function() { + mixins() { return [Mixins.InfiniteScrolling, Mixins.PerfectScrollbar]; }, - calculateNextPeak: function() { - var altitude = this.find('.js-card-details').scrollHeight; + calculateNextPeak() { + const altitude = this.find('.js-card-details').scrollHeight; this.callFirstWith(this, 'setNextPeak', altitude); }, - reachNextPeak: function() { - var activitiesComponent = this.componentChildren('activities')[0]; + reachNextPeak() { + const activitiesComponent = this.componentChildren('activities')[0]; activitiesComponent.loadNextPage(); }, - onCreated: function() { + onCreated() { this.isLoaded = new ReactiveVar(false); this.componentParent().showOverlay.set(true); this.componentParent().mouseHasEnterCardDetails = false; }, - scrollParentContainer: function() { + scrollParentContainer() { const cardPanelWidth = 510; - let bodyBoardComponent = this.componentParent(); + const bodyBoardComponent = this.componentParent(); - let $cardContainer = bodyBoardComponent.$('.js-lists'); - let $cardView = this.$(this.firstNode()); - let cardContainerScroll = $cardContainer.scrollLeft(); - let cardContainerWidth = $cardContainer.width(); + const $cardContainer = bodyBoardComponent.$('.js-lists'); + const $cardView = this.$(this.firstNode()); + const cardContainerScroll = $cardContainer.scrollLeft(); + const cardContainerWidth = $cardContainer.width(); - let cardViewStart = $cardView.offset().left; - let cardViewEnd = cardViewStart + cardPanelWidth; + const cardViewStart = $cardView.offset().left; + const cardViewEnd = cardViewStart + cardPanelWidth; let offset = false; if (cardViewStart < 0) { @@ -47,53 +47,53 @@ BlazeComponent.extendComponent({ } }, - onRendered: function() { + onRendered() { this.scrollParentContainer(); }, - onDestroyed: function() { + onDestroyed() { this.componentParent().showOverlay.set(false); }, - updateCard: function(modifier) { + updateCard(modifier) { Cards.update(this.data()._id, { - $set: modifier + $set: modifier, }); }, - events: function() { - var events = { - [CSSEvents.animationend + ' .js-card-details']: function() { + events() { + const events = { + [`${CSSEvents.animationend} .js-card-details`]() { this.isLoaded.set(true); - } + }, }; return [_.extend(events, { - 'click .js-close-card-details': function() { + 'click .js-close-card-details'() { Utils.goBoardId(this.data().boardId); }, 'click .js-open-card-details-menu': Popup.open('cardDetailsActions'), - 'submit .js-card-description': function(evt) { + 'submit .js-card-description'(evt) { evt.preventDefault(); - var description = this.currentComponent().getValue(); - this.updateCard({ description: description }); + const description = this.currentComponent().getValue(); + this.updateCard({ description }); }, - 'submit .js-card-details-title': function(evt) { + 'submit .js-card-details-title'(evt) { evt.preventDefault(); - var title = this.currentComponent().getValue(); + const title = this.currentComponent().getValue(); if ($.trim(title)) { - this.updateCard({ title: title }); + this.updateCard({ title }); } }, 'click .js-member': Popup.open('cardMember'), 'click .js-add-members': Popup.open('cardMembers'), 'click .js-add-labels': Popup.open('cardLabels'), - 'mouseenter .js-card-details': function() { + 'mouseenter .js-card-details'() { this.componentParent().showOverlay.set(true); this.componentParent().mouseHasEnterCardDetails = true; - } + }, })]; - } + }, }).register('cardDetails'); // We extends the normal InlinedForm component to support UnsavedEdits draft @@ -103,12 +103,12 @@ BlazeComponent.extendComponent({ return { fieldName: 'cardDescription', docId: Session.get('currentCard'), - } + }; } close(isReset = false) { - if (this.isOpen.get() && ! isReset) { - let draft = $.trim(this.getValue()); + if (this.isOpen.get() && !isReset) { + const draft = $.trim(this.getValue()); if (draft !== Cards.findOne(Session.get('currentCard')).description) { UnsavedEdits.set(this._getUnsavedEditKey(), this.getValue()); } @@ -136,45 +136,45 @@ Template.cardDetailsActionsPopup.events({ 'click .js-attachments': Popup.open('cardAttachments'), 'click .js-move-card': Popup.open('moveCard'), // 'click .js-copy': Popup.open(), - 'click .js-archive': function(evt) { + 'click .js-archive'(evt) { evt.preventDefault(); Cards.update(this._id, { $set: { - archived: true - } + archived: true, + }, }); Popup.close(); }, - 'click .js-more': Popup.open('cardMore') + 'click .js-more': Popup.open('cardMore'), }); Template.moveCardPopup.events({ - 'click .js-select-list': function() { + 'click .js-select-list'() { // XXX We should *not* get the currentCard from the global state, but // instead from a “component” state. - var cardId = Session.get('currentCard'); - var newListId = this._id; + const cardId = Session.get('currentCard'); + const newListId = this._id; Cards.update(cardId, { $set: { - listId: newListId - } + listId: newListId, + }, }); Popup.close(); - } + }, }); Template.cardMorePopup.events({ - 'click .js-delete': Popup.afterConfirm('cardDelete', function() { + 'click .js-delete': Popup.afterConfirm('cardDelete', () => { Popup.close(); Cards.remove(this._id); Utils.goBoardId(this.board()._id); - }) + }), }); // Close the card details pane by pressing escape EscapeActions.register('detailsPane', - function() { Utils.goBoardId(Session.get('currentBoard')); }, - function() { return ! Session.equals('currentCard', null); }, { - noClickEscapeOn: '.js-card-details,.board-sidebar,#header' + () => { Utils.goBoardId(Session.get('currentBoard')); }, + () => { return !Session.equals('currentCard', null); }, { + noClickEscapeOn: '.js-card-details,.board-sidebar,#header', } ); diff --git a/client/components/cards/labels.js b/client/components/cards/labels.js index 4e6ceb3a..2da3b80b 100644 --- a/client/components/cards/labels.js +++ b/client/components/cards/labels.js @@ -1,136 +1,136 @@ - -var labelColors; -Meteor.startup(function() { +let labelColors; +Meteor.startup(() => { labelColors = Boards.simpleSchema()._schema['labels.$.color'].allowedValues; }); BlazeComponent.extendComponent({ - template: function() { + template() { return 'formLabel'; }, - onCreated: function() { + onCreated() { this.currentColor = new ReactiveVar(this.data().color); }, - labels: function() { - return _.map(labelColors, function(color) { - return { color: color, name: '' }; + labels() { + return _.map(labelColors, (color) => { + return { color, name: '' }; }); }, - isSelected: function(color) { + isSelected(color) { return this.currentColor.get() === color; }, - events: function() { + events() { return [{ - 'click .js-palette-color': function() { + 'click .js-palette-color'() { this.currentColor.set(this.currentData().color); - } + }, }]; - } + }, }).register('formLabel'); Template.createLabelPopup.helpers({ // This is the default color for a new label. We search the first color that // is not already used in the board (although it's not a problem if two // labels have the same color). - defaultColor: function() { - var labels = Boards.findOne(Session.get('currentBoard')).labels; - var usedColors = _.pluck(labels, 'color'); - var availableColors = _.difference(labelColors, usedColors); + defaultColor() { + const labels = Boards.findOne(Session.get('currentBoard')).labels; + const usedColors = _.pluck(labels, 'color'); + const availableColors = _.difference(labelColors, usedColors); return availableColors.length > 1 ? availableColors[0] : labelColors[0]; - } + }, }); Template.cardLabelsPopup.events({ - 'click .js-select-label': function(evt) { - var cardId = Template.parentData(2).data._id; - var labelId = this._id; - var operation; + 'click .js-select-label'(evt) { + const cardId = Template.parentData(2).data._id; + const labelId = this._id; + let operation; if (Cards.find({ _id: cardId, labelIds: labelId}).count() === 0) operation = '$addToSet'; else operation = '$pull'; - var query = {}; - query[operation] = { - labelIds: labelId - }; - Cards.update(cardId, query); + Cards.update(cardId, { + [operation]: { + labelIds: labelId, + }, + }); evt.preventDefault(); }, 'click .js-edit-label': Popup.open('editLabel'), - 'click .js-add-label': Popup.open('createLabel') + 'click .js-add-label': Popup.open('createLabel'), }); Template.formLabel.events({ - 'click .js-palette-color': function(evt) { - var $this = $(evt.currentTarget); + 'click .js-palette-color'(evt) { + const $this = $(evt.currentTarget); // hide selected ll colors $('.js-palette-select').addClass('hide'); // show select color $this.find('.js-palette-select').removeClass('hide'); - } + }, }); Template.createLabelPopup.events({ // Create the new label - 'submit .create-label': function(evt, tpl) { - var name = tpl.$('#labelName').val().trim(); - var boardId = Session.get('currentBoard'); - var color = Blaze.getData(tpl.find('.fa-check')).color; + 'submit .create-label'(evt, tpl) { + const name = tpl.$('#labelName').val().trim(); + const boardId = Session.get('currentBoard'); + const color = Blaze.getData(tpl.find('.fa-check')).color; Boards.update(boardId, { $push: { labels: { + name, + color, _id: Random.id(6), - name: name, - color: color - } - } + }, + }, }); Popup.back(); evt.preventDefault(); - } + }, }); Template.editLabelPopup.events({ 'click .js-delete-label': Popup.afterConfirm('deleteLabel', function() { - var boardId = Session.get('currentBoard'); + const boardId = Session.get('currentBoard'); Boards.update(boardId, { $pull: { labels: { - _id: this._id - } - } + _id: this._id, + }, + }, }); Popup.back(2); }), - 'submit .edit-label': function(evt, tpl) { + 'submit .edit-label'(evt, tpl) { evt.preventDefault(); - var name = tpl.$('#labelName').val().trim(); - var boardId = Session.get('currentBoard'); - var getLabel = Utils.getLabelIndex(boardId, this._id); - var color = Blaze.getData(tpl.find('.fa-check')).color; + const name = tpl.$('#labelName').val().trim(); + const boardId = Session.get('currentBoard'); + const getLabel = Utils.getLabelIndex(boardId, this._id); + const color = Blaze.getData(tpl.find('.fa-check')).color; - var $set = {}; - $set[getLabel.key('name')] = name; - $set[getLabel.key('color')] = color; - - Boards.update(boardId, { $set: $set }); + Boards.update(boardId, { + $set: { + [getLabel.key('name')]: name, + [getLabel.key('color')]: color, + }, + }); Popup.back(); - } + }, }); Template.cardLabelsPopup.helpers({ - isLabelSelected: function(cardId) { + isLabelSelected(cardId) { return _.contains(Cards.findOne(cardId).labelIds, this._id); - } + }, }); diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index 70751152..a98b5730 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -3,7 +3,7 @@ // }); BlazeComponent.extendComponent({ - template: function() { + template() { return 'minicard'; - } + }, }).register('minicard'); diff --git a/client/components/lists/list.js b/client/components/lists/list.js index 3b602f43..1b54741c 100644 --- a/client/components/lists/list.js +++ b/client/components/lists/list.js @@ -1,14 +1,16 @@ +const { calculateIndex } = Utils; + BlazeComponent.extendComponent({ - template: function() { + template() { return 'list'; }, - // Proxies - openForm: function(options) { + // Proxy + openForm(options) { this.componentChildren('listBody')[0].openForm(options); }, - onCreated: function() { + onCreated() { this.newCardFormIsVisible = new ReactiveVar(true); }, @@ -19,28 +21,27 @@ BlazeComponent.extendComponent({ // By calling asking the sortable library to cancel its move on the `stop` // callback, we basically solve all issues related to reactive updates. A // comment below provides further details. - onRendered: function() { - var self = this; - if (! Meteor.user() || ! Meteor.user().isBoardMember()) + onRendered() { + if (!Meteor.user() || !Meteor.user().isBoardMember()) return; - var boardComponent = self.componentParent(); - var itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)'; - var $cards = self.$('.js-minicards'); + const boardComponent = this.componentParent(); + const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)'; + const $cards = this.$('.js-minicards'); $cards.sortable({ connectWith: '.js-minicards', tolerance: 'pointer', appendTo: 'body', - helper: function(evt, item) { - var helper = item.clone(); + helper(evt, item) { + const helper = item.clone(); if (MultiSelection.isActive()) { - var andNOthers = $cards.find('.js-minicard.is-checked').length - 1; + const andNOthers = $cards.find('.js-minicard.is-checked').length - 1; if (andNOthers > 0) { helper.append($(Blaze.toHTML(HTML.DIV( // XXX Super bad class name {'class': 'and-n-other'}, // XXX Need to translate - 'and ' + andNOthers + ' other cards.' + `and ${andNOthers} other cards.` )))); } } @@ -50,19 +51,19 @@ BlazeComponent.extendComponent({ items: itemsSelector, scroll: false, placeholder: 'minicard-wrapper placeholder', - start: function(evt, ui) { + start(evt, ui) { ui.placeholder.height(ui.helper.height()); EscapeActions.executeUpTo('popup'); boardComponent.setIsDragging(true); }, - stop: function(evt, ui) { + stop(evt, ui) { // To attribute the new index number, we need to get the DOM element // of the previous and the following card -- if any. - var prevCardDom = ui.item.prev('.js-minicard').get(0); - var nextCardDom = ui.item.next('.js-minicard').get(0); - var nCards = MultiSelection.isActive() ? MultiSelection.count() : 1; - var sortIndex = Utils.calculateIndex(prevCardDom, nextCardDom, nCards); - var listId = Blaze.getData(ui.item.parents('.list').get(0))._id; + const prevCardDom = ui.item.prev('.js-minicard').get(0); + const nextCardDom = ui.item.next('.js-minicard').get(0); + const nCards = MultiSelection.isActive() ? MultiSelection.count() : 1; + const sortIndex = calculateIndex(prevCardDom, nextCardDom, nCards); + const listId = Blaze.getData(ui.item.parents('.list').get(0))._id; // Normally the jquery-ui sortable library moves the dragged DOM element // to its new position, which disrupts Blaze reactive updates mechanism @@ -74,53 +75,53 @@ BlazeComponent.extendComponent({ $cards.sortable('cancel'); if (MultiSelection.isActive()) { - Cards.find(MultiSelection.getMongoSelector()).forEach(function(c, i) { + Cards.find(MultiSelection.getMongoSelector()).forEach((c, i) => { Cards.update(c._id, { $set: { - listId: listId, - sort: sortIndex.base + i * sortIndex.increment - } + listId, + sort: sortIndex.base + i * sortIndex.increment, + }, }); }); } else { - var cardDomElement = ui.item.get(0); - var cardId = Blaze.getData(cardDomElement)._id; + const cardDomElement = ui.item.get(0); + const cardId = Blaze.getData(cardDomElement)._id; Cards.update(cardId, { $set: { - listId: listId, - sort: sortIndex.base - } + listId, + sort: sortIndex.base, + }, }); } boardComponent.setIsDragging(false); - } + }, }); // We want to re-run this function any time a card is added. - self.autorun(function() { - var currentBoardId = Tracker.nonreactive(function() { + this.autorun(() => { + const currentBoardId = Tracker.nonreactive(() => { return Session.get('currentBoard'); }); Cards.find({ boardId: currentBoardId }).fetch(); - Tracker.afterFlush(function() { + Tracker.afterFlush(() => { $cards.find(itemsSelector).droppable({ hoverClass: 'draggable-hover-card', accept: '.js-member,.js-label', - drop: function(event, ui) { - var cardId = Blaze.getData(this)._id; - var addToSet; + drop(event, ui) { + const cardId = Blaze.getData(this)._id; + let addToSet; if (ui.draggable.hasClass('js-member')) { - var memberId = Blaze.getData(ui.draggable.get(0)).userId; + const memberId = Blaze.getData(ui.draggable.get(0)).userId; addToSet = { members: memberId }; } else { - var labelId = Blaze.getData(ui.draggable.get(0))._id; + const labelId = Blaze.getData(ui.draggable.get(0))._id; addToSet = { labelIds: labelId }; } Cards.update(cardId, { $addToSet: addToSet }); - } + }, }); }); }); - } + }, }).register('list'); diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 2b561ae3..cc8c94cc 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -1,46 +1,46 @@ BlazeComponent.extendComponent({ - template: function() { + template() { return 'listBody'; }, - mixins: function() { + mixins() { return [Mixins.PerfectScrollbar]; }, - openForm: function(options) { + openForm(options) { options = options || {}; options.position = options.position || 'top'; - var forms = this.componentChildren('inlinedForm'); - var form = _.find(forms, function(component) { + const forms = this.componentChildren('inlinedForm'); + let form = _.find(forms, (component) => { return component.data().position === options.position; }); - if (! form && forms.length > 0) { + if (!form && forms.length > 0) { form = forms[0]; } form.open(); }, - addCard: function(evt) { + addCard(evt) { evt.preventDefault(); - var textarea = $(evt.currentTarget).find('textarea'); - var title = textarea.val(); - var position = Blaze.getData(evt.currentTarget).position; - var sortIndex; - var firstCard = this.find('.js-minicard:first'); - var lastCard = this.find('.js-minicard:last'); + const firstCardDom = this.find('.js-minicard:first'); + const lastCardDom = this.find('.js-minicard:last'); + const textarea = $(evt.currentTarget).find('textarea'); + const title = textarea.val(); + const position = Blaze.getData(evt.currentTarget).position; + let sortIndex; if (position === 'top') { - sortIndex = Utils.calculateIndex(null, firstCard).base; + sortIndex = Utils.calculateIndex(null, firstCardDom).base; } else if (position === 'bottom') { - sortIndex = Utils.calculateIndex(lastCard, null).base; + sortIndex = Utils.calculateIndex(lastCardDom, null).base; } if ($.trim(title)) { - var _id = Cards.insert({ - title: title, + const _id = Cards.insert({ + title, listId: this.data()._id, boardId: this.data().board()._id, - sort: sortIndex + sort: sortIndex, }); // In case the filter is active we need to add the newly inserted card in // the list of exceptions -- cards that are not filtered. Otherwise the @@ -56,18 +56,18 @@ BlazeComponent.extendComponent({ } }, - scrollToBottom: function() { - var container = this.firstNode(); + scrollToBottom() { + const container = this.firstNode(); $(container).animate({ - scrollTop: container.scrollHeight + scrollTop: container.scrollHeight, }); }, - clickOnMiniCard: function(evt) { + clickOnMiniCard(evt) { if (MultiSelection.isActive() || evt.shiftKey) { evt.stopImmediatePropagation(); evt.preventDefault(); - var methodName = evt.shiftKey ? 'toogleRange' : 'toogle'; + const methodName = evt.shiftKey ? 'toogleRange' : 'toogle'; MultiSelection[methodName](this.currentData()._id); // If the card is already selected, we want to de-select it. @@ -80,36 +80,36 @@ BlazeComponent.extendComponent({ } }, - cardIsSelected: function() { + cardIsSelected() { return Session.equals('currentCard', this.currentData()._id); }, - toggleMultiSelection: function(evt) { + toggleMultiSelection(evt) { evt.stopPropagation(); evt.preventDefault(); MultiSelection.toogle(this.currentData()._id); }, - events: function() { + events() { return [{ 'click .js-minicard': this.clickOnMiniCard, 'click .js-toggle-multi-selection': this.toggleMultiSelection, 'click .open-minicard-composer': this.scrollToBottom, - submit: this.addCard + submit: this.addCard, }]; - } + }, }).register('listBody'); BlazeComponent.extendComponent({ - template: function() { + template() { return 'addCardForm'; }, - pressKey: function(evt) { + pressKey(evt) { // Pressing Enter should submit the card if (evt.keyCode === 13) { evt.preventDefault(); - var $form = $(evt.currentTarget).closest('form'); + const $form = $(evt.currentTarget).closest('form'); // XXX For some reason $form.submit() does not work (it's probably a bug // of blaze-component related to the fact that the submit event is non- // bubbling). This is why we click on the submit button instead -- which @@ -120,24 +120,24 @@ BlazeComponent.extendComponent({ // in the reverse order } else if (evt.keyCode === 9) { evt.preventDefault(); - var isReverse = evt.shiftKey; - var list = $('#js-list-' + this.data().listId); - var listSelector = '.js-list:not(.js-list-composer)'; - var nextList = list[isReverse ? 'prev' : 'next'](listSelector).get(0); + const isReverse = evt.shiftKey; + const list = $(`#js-list-${this.data().listId}`); + const listSelector = '.js-list:not(.js-list-composer)'; + let nextList = list[isReverse ? 'prev' : 'next'](listSelector).get(0); // If there is no next list, loop back to the beginning. - if (! nextList) { + if (!nextList) { nextList = $(listSelector + (isReverse ? ':last' : ':first')).get(0); } BlazeComponent.getComponentForElement(nextList).openForm({ - position:this.data().position + position:this.data().position, }); } }, - events: function() { + events() { return [{ - keydown: this.pressKey + keydown: this.pressKey, }]; - } + }, }).register('addCardForm'); diff --git a/client/components/lists/listHeader.js b/client/components/lists/listHeader.js index cd4df276..9431b461 100644 --- a/client/components/lists/listHeader.js +++ b/client/components/lists/listHeader.js @@ -1,78 +1,78 @@ BlazeComponent.extendComponent({ - template: function() { + template() { return 'listHeader'; }, - editTitle: function(evt) { + editTitle(evt) { evt.preventDefault(); - var form = this.componentChildren('inlinedForm')[0]; - var newTitle = form.getValue(); + const form = this.componentChildren('inlinedForm')[0]; + const newTitle = form.getValue(); if ($.trim(newTitle)) { Lists.update(this.currentData()._id, { $set: { - title: newTitle - } + title: newTitle, + }, }); } }, - events: function() { + events() { return [{ 'click .js-open-list-menu': Popup.open('listAction'), - submit: this.editTitle + submit: this.editTitle, }]; - } + }, }).register('listHeader'); Template.listActionPopup.events({ - 'click .js-add-card': function() { - var listDom = document.getElementById('js-list-' + this._id); - var listComponent = BlazeComponent.getComponentForElement(listDom); + 'click .js-add-card'() { + const listDom = document.getElementById(`js-list-${this._id}`); + const listComponent = BlazeComponent.getComponentForElement(listDom); listComponent.openForm({ position: 'top' }); Popup.close(); }, - 'click .js-list-subscribe': function() {}, - 'click .js-select-cards': function() { - var cardIds = Cards.find( + 'click .js-list-subscribe'() {}, + 'click .js-select-cards'() { + const cardIds = Cards.find( {listId: this._id}, {fields: { _id: 1 }} - ).map(function(card) { return card._id; }); + ).map((card) => card._id); MultiSelection.add(cardIds); Popup.close(); }, 'click .js-move-cards': Popup.open('listMoveCards'), - 'click .js-archive-cards': Popup.afterConfirm('listArchiveCards', function() { - Cards.find({listId: this._id}).forEach(function(card) { + 'click .js-archive-cards': Popup.afterConfirm('listArchiveCards', () => { + Cards.find({listId: this._id}).forEach((card) => { Cards.update(card._id, { $set: { - archived: true - } + archived: true, + }, }); }); Popup.close(); }), - 'click .js-close-list': function(evt) { + 'click .js-close-list'(evt) { evt.preventDefault(); Lists.update(this._id, { $set: { - archived: true - } + archived: true, + }, }); Popup.close(); - } + }, }); Template.listMoveCardsPopup.events({ - 'click .js-select-list': function() { - var fromList = Template.parentData(2).data._id; - var toList = this._id; - Cards.find({listId: fromList}).forEach(function(card) { + 'click .js-select-list'() { + const fromList = Template.parentData(2).data._id; + const toList = this._id; + Cards.find({ listId: fromList }).forEach((card) => { Cards.update(card._id, { $set: { - listId: toList - } + listId: toList, + }, }); }); Popup.close(); - } + }, }); diff --git a/client/components/main/editor.js b/client/components/main/editor.js index 7966ff60..c34539b3 100644 --- a/client/components/main/editor.js +++ b/client/components/main/editor.js @@ -1,7 +1,7 @@ -var dropdownMenuIsOpened = false; +let dropdownMenuIsOpened = false; -Template.editor.onRendered(function() { - var $textarea = this.$('textarea'); +Template.editor.onRendered(() => { + const $textarea = this.$('textarea'); autosize($textarea); @@ -9,39 +9,40 @@ Template.editor.onRendered(function() { // Emojies { match: /\B:([\-+\w]*)$/, - search: function(term, callback) { - callback($.map(Emoji.values, function(emoji) { + search(term, callback) { + callback($.map(Emoji.values, (emoji) => { return emoji.indexOf(term) === 0 ? emoji : null; })); }, - template: function(value) { - var image = '<img src="' + Emoji.baseImagePath + value + '.png"></img>'; + template(value) { + const imgSrc = Emoji.baseImagePath + value; + const image = `<img src="${imgSrc}.png" />`; return image + value; }, - replace: function(value) { - return ':' + value + ':'; + replace(value) { + return `:${value}:`; }, - index: 1 + index: 1, }, // User mentions { match: /\B@(\w*)$/, - search: function(term, callback) { - var currentBoard = Boards.findOne(Session.get('currentBoard')); - callback($.map(currentBoard.members, function(member) { - var username = Users.findOne(member.userId).username; + search(term, callback) { + const currentBoard = Boards.findOne(Session.get('currentBoard')); + callback($.map(currentBoard.members, (member) => { + const username = Users.findOne(member.userId).username; return username.indexOf(term) === 0 ? username : null; })); }, - template: function(value) { + template(value) { return value; }, - replace: function(username) { - return '@' + username + ' '; + replace(username) { + return `@${username} `; }, - index: 1 - } + index: 1, + }, ]); // Since commit d474017 jquery-textComplete automatically closes a potential @@ -51,27 +52,27 @@ Template.editor.onRendered(function() { // 'open' and 'hide' events, and create a ghost escapeAction when the dropdown // is opened (and rely on textComplete to execute the actual action). $textarea.on({ - 'textComplete:show': function() { + 'textComplete:show'() { dropdownMenuIsOpened = true; }, - 'textComplete:hide': function() { - Tracker.afterFlush(function() { + 'textComplete:hide'() { + Tracker.afterFlush(() => { dropdownMenuIsOpened = false; }); - } + }, }); }); EscapeActions.register('textcomplete', - function() {}, - function() { return dropdownMenuIsOpened; } + () => {}, + () => dropdownMenuIsOpened ); Template.viewer.events({ // Viewer sometimes have click-able wrapper around them (for instance to edit // the corresponding text). Clicking a link shouldn't fire these actions, stop // we stop these event at the viewer component level. - 'click a': function(evt) { + 'click a'(evt) { evt.stopPropagation(); // XXX We hijack the build-in browser action because we currently don't have @@ -79,7 +80,7 @@ Template.viewer.events({ // handled by a third party package that we can't configure easily. Fix that // by using directly `_blank` attribute in the rendered HTML. evt.preventDefault(); - let href = evt.currentTarget.href; + const href = evt.currentTarget.href; window.open(href, '_blank'); - } + }, }); diff --git a/client/components/main/header.js b/client/components/main/header.js index 7b7e431f..30cb2d8f 100644 --- a/client/components/main/header.js +++ b/client/components/main/header.js @@ -1,14 +1,14 @@ Template.header.helpers({ // Reactively set the color of the page from the color of the current board. - headerTemplate: function() { + headerTemplate() { return 'headerBoard'; }, - wrappedHeader: function() { - return ! Session.get('currentBoard'); - } + wrappedHeader() { + return !Session.get('currentBoard'); + }, }); Template.header.events({ - 'click .js-create-board': Popup.open('createBoard') + 'click .js-create-board': Popup.open('createBoard'), }); diff --git a/client/components/main/helpers.js b/client/components/main/helpers.js deleted file mode 100644 index 91205351..00000000 --- a/client/components/main/helpers.js +++ /dev/null @@ -1,65 +0,0 @@ -var Helpers = { - error: function() { - return Session.get('error'); - }, - - toLowerCase: function(text) { - return text && text.toLowerCase(); - }, - - toUpperCase: function(text) { - return text && text.toUpperCase(); - }, - - firstChar: function(text) { - return text && text[0].toUpperCase(); - }, - - session: function(prop) { - return Session.get(prop); - }, - - getUser: function(userId) { - return Users.findOne(userId); - } -}; - -// Register all Helpers -_.each(Helpers, function(fn, name) { Blaze.registerHelper(name, fn); }); - -// XXX I believe we should compute a HTML rendered field on the server that -// would handle markdown, emojies and user mentions. We can simply have two -// fields, one source, and one compiled version (in HTML) and send only the -// compiled version to most users -- who don't need to edit. -// In the meantime, all the transformation are done on the client using the -// Blaze API. -var at = HTML.CharRef({html: '@', str: '@'}); -Blaze.Template.registerHelper('mentions', new Template('mentions', function() { - var view = this; - var content = Blaze.toHTML(view.templateContentBlock); - var currentBoard = Session.get('currentBoard'); - var knowedUsers = _.map(currentBoard.members, function(member) { - member.username = Users.findOne(member.userId).username; - return member; - }); - - var mentionRegex = /\B@(\w*)/gi; - var currentMention, knowedUser, href, linkClass, linkValue, link; - while (!! (currentMention = mentionRegex.exec(content))) { - - knowedUser = _.findWhere(knowedUsers, { username: currentMention[1] }); - if (! knowedUser) - continue; - - linkValue = [' ', at, knowedUser.username]; - href = Router.url('Profile', { username: knowedUser.username }); - linkClass = 'atMention'; - if (knowedUser.userId === Meteor.userId()) - linkClass += ' me'; - link = HTML.A({ href: href, 'class': linkClass }, linkValue); - - content = content.replace(currentMention[0], Blaze.toHTML(link)); - } - - return HTML.Raw(content); -})); diff --git a/client/components/main/layouts.js b/client/components/main/layouts.js index 11a43313..ab62e76a 100644 --- a/client/components/main/layouts.js +++ b/client/components/main/layouts.js @@ -1,13 +1,13 @@ -Meteor.subscribe('boards') +Meteor.subscribe('boards'); -BlazeLayout.setRoot('body') +BlazeLayout.setRoot('body'); -Template.userFormsLayout.onRendered(function() { - EscapeActions.executeAll() -}) +Template.userFormsLayout.onRendered(() => { + EscapeActions.executeAll(); +}); Template.defaultLayout.events({ 'click .js-close-modal': () => { - Modal.close() - } -}) + Modal.close(); + }, +}); diff --git a/client/components/main/popup.js b/client/components/main/popup.js index 5fc4e979..ba20a6d3 100644 --- a/client/components/main/popup.js +++ b/client/components/main/popup.js @@ -1,11 +1,11 @@ Popup.template.events({ - 'click .js-back-view': function() { + 'click .js-back-view'() { Popup.back(); }, - 'click .js-close-pop-over': function() { + 'click .js-close-pop-over'() { Popup.close(); }, - 'click .js-confirm': function() { + 'click .js-confirm'() { this.__afterConfirmAction.call(this); }, // This handler intends to solve a pretty tricky bug with our popup @@ -18,22 +18,22 @@ Popup.template.events({ // in moving the whole popup container outside of the popup wrapper. To // disable this behavior we have to manually reset the scrollLeft position // whenever it is modified. - 'scroll .content-wrapper': function(evt) { + 'scroll .content-wrapper'(evt) { evt.currentTarget.scrollLeft = 0; - } + }, }); // When a popup content is removed (ie, when the user press the "back" button), // we need to wait for the container translation to end before removing the // actual DOM element. For that purpose we use the undocumented `_uihooks` API. -Popup.template.onRendered(function() { - var container = this.find('.content-container'); +Popup.template.onRendered(() => { + const container = this.find('.content-container'); container._uihooks = { - removeElement: function(node) { + removeElement(node) { $(node).addClass('no-height'); - $(container).one(CSSEvents.transitionend, function() { + $(container).one(CSSEvents.transitionend, () => { node.parentNode.removeChild(node); }); - } + }, }; }); diff --git a/client/components/mixins/infiniteScrolling.js b/client/components/mixins/infiniteScrolling.js index df3b8901..0afb33f9 100644 --- a/client/components/mixins/infiniteScrolling.js +++ b/client/components/mixins/infiniteScrolling.js @@ -1,37 +1,37 @@ -var peakAnticipation = 200; +const peakAnticipation = 200; Mixins.InfiniteScrolling = BlazeComponent.extendComponent({ - onCreated: function() { + onCreated() { this._nextPeak = Infinity; }, - setNextPeak: function(v) { + setNextPeak(v) { this._nextPeak = v; }, - getNextPeak: function() { + getNextPeak() { return this._nextPeak; }, - resetNextPeak: function() { + resetNextPeak() { this._nextPeak = Infinity; }, // To be overwritten by consumers of this mixin - reachNextPeak: function() { + reachNextPeak() { }, - events: function() { + events() { return [{ - scroll: function(evt) { - var domElement = evt.currentTarget; - var altitude = domElement.scrollTop + domElement.offsetHeight; + scroll(evt) { + const domElement = evt.currentTarget; + let altitude = domElement.scrollTop + domElement.offsetHeight; altitude += peakAnticipation; if (altitude >= this.callFirstWith(null, 'getNextPeak')) { this.callFirstWith(null, 'reachNextPeak'); } - } + }, }]; - } + }, }); diff --git a/client/components/mixins/perfectScrollbar.js b/client/components/mixins/perfectScrollbar.js index 510a4563..f652f043 100644 --- a/client/components/mixins/perfectScrollbar.js +++ b/client/components/mixins/perfectScrollbar.js @@ -1,14 +1,12 @@ Mixins.PerfectScrollbar = BlazeComponent.extendComponent({ - onRendered: function() { - var component = this.mixinParent(); - var domElement = component.find('.js-perfect-scrollbar'); + onRendered() { + const component = this.mixinParent(); + const domElement = component.find('.js-perfect-scrollbar'); Ps.initialize(domElement); // XXX We should create an event map to be consistent with other components // but since BlazeComponent doesn't merge Mixins events transparently I // prefered to use a jQuery event (which is what an event map ends up doing) - component.$(domElement).on('mouseenter', function() { - Ps.update(domElement); - }); - } + component.$(domElement).on('mouseenter', () => Ps.update(domElement)); + }, }); diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js index 97b6f2de..51f3e0e4 100644 --- a/client/components/sidebar/sidebar.js +++ b/client/components/sidebar/sidebar.js @@ -1,76 +1,76 @@ Sidebar = null; -var defaultView = 'home'; +const defaultView = 'home'; -var viewTitles = { +const viewTitles = { filter: 'filter-cards', multiselection: 'multi-selection', - archives: 'archives' + archives: 'archives', }; BlazeComponent.extendComponent({ - template: function() { + template() { return 'sidebar'; }, - mixins: function() { + mixins() { return [Mixins.InfiniteScrolling, Mixins.PerfectScrollbar]; }, - onCreated: function() { - this._isOpen = new ReactiveVar(! Session.get('currentCard')); + onCreated() { + this._isOpen = new ReactiveVar(!Session.get('currentCard')); this._view = new ReactiveVar(defaultView); Sidebar = this; }, - onDestroyed: function() { + onDestroyed() { Sidebar = null; }, - isOpen: function() { + isOpen() { return this._isOpen.get(); }, - open: function() { - if (! this._isOpen.get()) { + open() { + if (!this._isOpen.get()) { this._isOpen.set(true); EscapeActions.executeUpTo('detailsPane'); } }, - hide: function() { + hide() { if (this._isOpen.get()) { this._isOpen.set(false); } }, - toogle: function() { - this._isOpen.set(! this._isOpen.get()); + toogle() { + this._isOpen.set(!this._isOpen.get()); }, - calculateNextPeak: function() { - var altitude = this.find('.js-board-sidebar-content').scrollHeight; + calculateNextPeak() { + const altitude = this.find('.js-board-sidebar-content').scrollHeight; this.callFirstWith(this, 'setNextPeak', altitude); }, - reachNextPeak: function() { - var activitiesComponent = this.componentChildren('activities')[0]; + reachNextPeak() { + const activitiesComponent = this.componentChildren('activities')[0]; activitiesComponent.loadNextPage(); }, - isTongueHidden: function() { + isTongueHidden() { return this.isOpen() && this.getView() !== defaultView; }, - scrollTop: function() { + scrollTop() { this.$('.js-board-sidebar-content').scrollTop(0); }, - getView: function() { + getView() { return this._view.get(); }, - setView: function(view) { + setView(view) { view = _.isString(view) ? view : defaultView; if (this._view.get() !== view) { this._view.set(view); @@ -80,83 +80,84 @@ BlazeComponent.extendComponent({ this.open(); }, - isDefaultView: function() { + isDefaultView() { return this.getView() === defaultView; }, - getViewTemplate: function() { - return this.getView() + 'Sidebar'; + getViewTemplate() { + return `${this.getView()}Sidebar`; }, - getViewTitle: function() { + getViewTitle() { return TAPi18n.__(viewTitles[this.getView()]); }, - events: function() { + events() { // XXX Hacky, we need some kind of `super` - var mixinEvents = this.getMixin(Mixins.InfiniteScrolling).events(); + const mixinEvents = this.getMixin(Mixins.InfiniteScrolling).events(); return mixinEvents.concat([{ 'click .js-toogle-sidebar': this.toogle, - 'click .js-back-home': this.setView + 'click .js-back-home': this.setView, }]); - } + }, }).register('sidebar'); -Blaze.registerHelper('Sidebar', function() { - return Sidebar; -}); +Blaze.registerHelper('Sidebar', () => Sidebar); EscapeActions.register('sidebarView', - function() { Sidebar.setView(defaultView); }, - function() { return Sidebar && Sidebar.getView() !== defaultView; } + () => { Sidebar.setView(defaultView); }, + () => { return Sidebar && Sidebar.getView() !== defaultView; } ); -var getMemberIndex = function(board, searchId) { - for (var i = 0; i < board.members.length; i++) { +function getMemberIndex(board, searchId) { + for (let i = 0; i < board.members.length; i++) { if (board.members[i].userId === searchId) return i; } throw new Meteor.Error('Member not found'); -}; +} Template.memberPopup.helpers({ - user: function() { + user() { return Users.findOne(this.userId); }, - memberType: function() { - var type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal'; + memberType() { + const type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal'; return TAPi18n.__(type).toLowerCase(); - } + }, }); Template.memberPopup.events({ - 'click .js-filter-member': function() { + 'click .js-filter-member'() { Filter.members.toogle(this.userId); Popup.close(); }, 'click .js-change-role': Popup.open('changePermissions'), 'click .js-remove-member': Popup.afterConfirm('removeMember', function() { - var currentBoard = Boards.findOne(Session.get('currentBoard')); - var memberIndex = getMemberIndex(currentBoard, this.userId); - var setQuery = {}; - setQuery[['members', memberIndex, 'isActive'].join('.')] = false; - Boards.update(currentBoard._id, { $set: setQuery }); + const currentBoard = Boards.findOne(Session.get('currentBoard')); + const memberIndex = getMemberIndex(currentBoard, this.userId); + + Boards.update(currentBoard._id, { + $set: { + [`members.${memberIndex}.isActive`]: false, + }, + }); Popup.close(); }), - 'click .js-leave-member': function() { + 'click .js-leave-member'() { // XXX Not implemented Popup.close(); - } + }, }); Template.membersWidget.events({ 'click .js-member': Popup.open('member'), - 'click .js-manage-board-members': Popup.open('addMember') + 'click .js-manage-board-members': Popup.open('addMember'), }); Template.labelsWidget.events({ 'click .js-label': Popup.open('editLabel'), - 'click .js-add-label': Popup.open('createLabel') + 'click .js-add-label': Popup.open('createLabel'), }); // Board members can assign people or labels by drag-dropping elements from the @@ -164,99 +165,102 @@ Template.labelsWidget.events({ // plugin any time a draggable member or label is modified or removed we use a // autorun function and register a dependency on the both members and labels // fields of the current board document. -var draggableMembersLabelsWidgets = function() { - var self = this; - if (! Meteor.user() || ! Meteor.user().isBoardMember()) +function draggableMembersLabelsWidgets() { + if (!Meteor.user() || !Meteor.user().isBoardMember()) return; - self.autorun(function() { - var currentBoardId = Tracker.nonreactive(function() { + this.autorun(() => { + const currentBoardId = Tracker.nonreactive(() => { return Session.get('currentBoard'); }); Boards.findOne(currentBoardId, { fields: { members: 1, - labels: 1 - } + labels: 1, + }, }); - Tracker.afterFlush(function() { - self.$('.js-member,.js-label').draggable({ + Tracker.afterFlush(() => { + this.$('.js-member,.js-label').draggable({ appendTo: 'body', helper: 'clone', revert: 'invalid', revertDuration: 150, snap: false, snapMode: 'both', - start: function() { + start() { EscapeActions.executeUpTo('popup-back'); - } + }, }); }); }); -}; +} Template.membersWidget.onRendered(draggableMembersLabelsWidgets); Template.labelsWidget.onRendered(draggableMembersLabelsWidgets); Template.addMemberPopup.helpers({ - isBoardMember: function() { - var user = Users.findOne(this._id); + isBoardMember() { + const user = Users.findOne(this._id); return user && user.isBoardMember(); - } + }, }); Template.addMemberPopup.events({ - 'click .pop-over-member-list li:not(.disabled)': function() { - var userId = this._id; - var currentBoard = Boards.findOne(Session.get('currentBoard')); - var currentMembersIds = _.pluck(currentBoard.members, 'userId'); + 'click .pop-over-member-list li:not(.disabled)'() { + const userId = this._id; + const currentBoard = Boards.findOne(Session.get('currentBoard')); + const currentMembersIds = _.pluck(currentBoard.members, 'userId'); if (currentMembersIds.indexOf(userId) === -1) { Boards.update(currentBoard._id, { $push: { members: { - userId: userId, + userId, isAdmin: false, - isActive: true - } - } + isActive: true, + }, + }, }); } else { - var memberIndex = getMemberIndex(currentBoard, userId); - var setQuery = {}; - setQuery[['members', memberIndex, 'isActive'].join('.')] = true; - Boards.update(currentBoard._id, { $set: setQuery }); + const memberIndex = getMemberIndex(currentBoard, userId); + + Boards.update(currentBoard._id, { + $set: { + [`members.${memberIndex}.isActive`]: true, + }, + }); } Popup.close(); - } + }, }); -Template.addMemberPopup.onRendered(function() { +Template.addMemberPopup.onRendered(() => { this.find('.js-search-member input').focus(); }); Template.changePermissionsPopup.events({ - 'click .js-set-admin, click .js-set-normal': function(event) { - var currentBoard = Boards.findOne(Session.get('currentBoard')); - var memberIndex = getMemberIndex(currentBoard, this.user._id); - var isAdmin = $(event.currentTarget).hasClass('js-set-admin'); - var setQuery = {}; - setQuery[['members', memberIndex, 'isAdmin'].join('.')] = isAdmin; + 'click .js-set-admin, click .js-set-normal'(event) { + const currentBoard = Boards.findOne(Session.get('currentBoard')); + const memberIndex = getMemberIndex(currentBoard, this.user._id); + const isAdmin = $(event.currentTarget).hasClass('js-set-admin'); + Boards.update(currentBoard._id, { - $set: setQuery + $set: { + [`members.${memberIndex}.isAdmin`]: isAdmin, + }, }); Popup.back(1); - } + }, }); Template.changePermissionsPopup.helpers({ - isAdmin: function() { + isAdmin() { return this.user.isBoardAdmin(); }, - isLastAdmin: function() { - if (! this.user.isBoardAdmin()) + isLastAdmin() { + if (!this.user.isBoardAdmin()) return false; - var currentBoard = Boards.findOne(Session.get('currentBoard')); - var nbAdmins = _.where(currentBoard.members, { isAdmin: true }).length; + const currentBoard = Boards.findOne(Session.get('currentBoard')); + const nbAdmins = _.where(currentBoard.members, { isAdmin: true }).length; return nbAdmins === 1; - } + }, }); diff --git a/client/components/sidebar/sidebarArchives.js b/client/components/sidebar/sidebarArchives.js index 4e44f3f4..f2597c3c 100644 --- a/client/components/sidebar/sidebarArchives.js +++ b/client/components/sidebar/sidebarArchives.js @@ -1,46 +1,46 @@ BlazeComponent.extendComponent({ - template: function() { + template() { return 'archivesSidebar'; }, - tabs: function() { + tabs() { return [ { name: TAPi18n.__('cards'), slug: 'cards' }, - { name: TAPi18n.__('lists'), slug: 'lists' } - ] + { name: TAPi18n.__('lists'), slug: 'lists' }, + ]; }, - archivedCards: function() { + archivedCards() { return Cards.find({ archived: true }); }, - archivedLists: function() { + archivedLists() { return Lists.find({ archived: true }); }, - cardIsInArchivedList: function() { + cardIsInArchivedList() { return this.currentData().list().archived; }, - onRendered: function() { - //XXX We should support dragging a card from the sidebar to the board + onRendered() { + // XXX We should support dragging a card from the sidebar to the board }, - events: function() { + events() { return [{ - 'click .js-restore-card': function() { - var cardId = this.currentData()._id; + 'click .js-restore-card'() { + const cardId = this.currentData()._id; Cards.update(cardId, {$set: {archived: false}}); }, 'click .js-delete-card': Popup.afterConfirm('cardDelete', function() { - var cardId = this._id; + const cardId = this._id; Cards.remove(cardId); Popup.close(); }), - 'click .js-restore-list': function() { - var listId = this.currentData()._id; + 'click .js-restore-list'() { + const listId = this.currentData()._id; Lists.update(listId, {$set: {archived: false}}); - } + }, }]; - } + }, }).register('archivesSidebar'); diff --git a/client/components/sidebar/sidebarFilters.js b/client/components/sidebar/sidebarFilters.js index c7b28443..7fce7286 100644 --- a/client/components/sidebar/sidebarFilters.js +++ b/client/components/sidebar/sidebarFilters.js @@ -1,136 +1,136 @@ BlazeComponent.extendComponent({ - template: function() { + template() { return 'filterSidebar'; }, - events: function() { + events() { return [{ - 'click .js-toggle-label-filter': function(evt) { + 'click .js-toggle-label-filter'(evt) { evt.preventDefault(); Filter.labelIds.toogle(this.currentData()._id); Filter.resetExceptions(); }, - 'click .js-toogle-member-filter': function(evt) { + 'click .js-toogle-member-filter'(evt) { evt.preventDefault(); Filter.members.toogle(this.currentData()._id); Filter.resetExceptions(); }, - 'click .js-clear-all': function(evt) { + 'click .js-clear-all'(evt) { evt.preventDefault(); Filter.reset(); }, - 'click .js-filter-to-selection': function(evt) { + 'click .js-filter-to-selection'(evt) { evt.preventDefault(); - var selectedCards = Cards.find(Filter.mongoSelector()).map(function(c) { + const selectedCards = Cards.find(Filter.mongoSelector()).map((c) => { return c._id; }); MultiSelection.add(selectedCards); - } + }, }]; - } + }, }).register('filterSidebar'); -var updateSelectedCards = function(query) { - Cards.find(MultiSelection.getMongoSelector()).forEach(function(card) { +function updateSelectedCards(query) { + Cards.find(MultiSelection.getMongoSelector()).forEach((card) => { Cards.update(card._id, query); }); -}; +} BlazeComponent.extendComponent({ - template: function() { + template() { return 'multiselectionSidebar'; }, - mapSelection: function(kind, _id) { - return Cards.find(MultiSelection.getMongoSelector()).map(function(card) { - var methodName = kind === 'label' ? 'hasLabel' : 'isAssigned'; + mapSelection(kind, _id) { + return Cards.find(MultiSelection.getMongoSelector()).map((card) => { + const methodName = kind === 'label' ? 'hasLabel' : 'isAssigned'; return card[methodName](_id); }); }, - allSelectedElementHave: function(kind, _id) { + allSelectedElementHave(kind, _id) { if (MultiSelection.isEmpty()) return false; else return _.every(this.mapSelection(kind, _id)); }, - someSelectedElementHave: function(kind, _id) { + someSelectedElementHave(kind, _id) { if (MultiSelection.isEmpty()) return false; else return _.some(this.mapSelection(kind, _id)); }, - events: function() { + events() { return [{ - 'click .js-toggle-label-multiselection': function(evt) { - var labelId = this.currentData()._id; - var mappedSelection = this.mapSelection('label', labelId); - var operation; + 'click .js-toggle-label-multiselection'(evt) { + const labelId = this.currentData()._id; + const mappedSelection = this.mapSelection('label', labelId); + let operation; if (_.every(mappedSelection)) operation = '$pull'; - else if (_.every(mappedSelection, function(bool) { return ! bool; })) + else if (_.every(mappedSelection, (bool) => !bool)) operation = '$addToSet'; else { - var popup = Popup.open('disambiguateMultiLabel'); + const popup = Popup.open('disambiguateMultiLabel'); // XXX We need to have a better integration between the popup and the // UI components systems. return popup.call(this.currentData(), evt); } - var query = {}; - query[operation] = { - labelIds: labelId - }; - updateSelectedCards(query); + updateSelectedCards({ + [operation]: { + labelIds: labelId, + }, + }); }, - 'click .js-toogle-member-multiselection': function(evt) { - var memberId = this.currentData()._id; - var mappedSelection = this.mapSelection('member', memberId); - var operation; + 'click .js-toogle-member-multiselection'(evt) { + const memberId = this.currentData()._id; + const mappedSelection = this.mapSelection('member', memberId); + let operation; if (_.every(mappedSelection)) operation = '$pull'; - else if (_.every(mappedSelection, function(bool) { return ! bool; })) + else if (_.every(mappedSelection, (bool) => !bool)) operation = '$addToSet'; else { - var popup = Popup.open('disambiguateMultiMember'); + const popup = Popup.open('disambiguateMultiMember'); // XXX We need to have a better integration between the popup and the // UI components systems. return popup.call(this.currentData(), evt); } - var query = {}; - query[operation] = { - members: memberId - }; - updateSelectedCards(query); + updateSelectedCards({ + [operation]: { + members: memberId, + }, + }); }, - 'click .js-archive-selection': function() { + 'click .js-archive-selection'() { updateSelectedCards({$set: {archived: true}}); - } + }, }]; - } + }, }).register('multiselectionSidebar'); Template.disambiguateMultiLabelPopup.events({ - 'click .js-remove-label': function() { + 'click .js-remove-label'() { updateSelectedCards({$pull: {labelIds: this._id}}); Popup.close(); }, - 'click .js-add-label': function() { + 'click .js-add-label'() { updateSelectedCards({$addToSet: {labelIds: this._id}}); Popup.close(); - } + }, }); Template.disambiguateMultiMemberPopup.events({ - 'click .js-unassign-member': function() { + 'click .js-unassign-member'() { updateSelectedCards({$pull: {members: this._id}}); Popup.close(); }, - 'click .js-assign-member': function() { + 'click .js-assign-member'() { updateSelectedCards({$addToSet: {members: this._id}}); Popup.close(); - } + }, }); diff --git a/client/components/users/userAvatar.js b/client/components/users/userAvatar.js index a35415e2..b0702468 100644 --- a/client/components/users/userAvatar.js +++ b/client/components/users/userAvatar.js @@ -1,98 +1,98 @@ Meteor.subscribe('my-avatars'); Template.userAvatar.helpers({ - userData: function() { + userData() { return Users.findOne(this.userId, { fields: { profile: 1, - username: 1 - } + username: 1, + }, }); }, - memberType: function() { - var user = Users.findOne(this.userId); + memberType() { + const user = Users.findOne(this.userId); return user && user.isBoardAdmin() ? 'admin' : 'normal'; }, - presenceStatusClassName: function() { - var userPresence = Presences.findOne({ userId: this.userId }); - if (! userPresence) + presenceStatusClassName() { + const userPresence = Presences.findOne({ userId: this.userId }); + if (!userPresence) return 'disconnected'; else if (Session.equals('currentBoard', userPresence.state.currentBoardId)) return 'active'; else return 'idle'; - } + }, }); Template.userAvatar.events({ - 'click .js-change-avatar': Popup.open('changeAvatar') + 'click .js-change-avatar': Popup.open('changeAvatar'), }); Template.userAvatarInitials.helpers({ - initials: function() { - var user = Users.findOne(this.userId); + initials() { + const user = Users.findOne(this.userId); return user && user.getInitials(); }, - viewPortWidth: function() { - var user = Users.findOne(this.userId); + viewPortWidth() { + const user = Users.findOne(this.userId); return (user && user.getInitials().length || 1) * 12; - } + }, }); BlazeComponent.extendComponent({ - template: function() { + template() { return 'changeAvatarPopup'; }, - onCreated: function() { + onCreated() { this.error = new ReactiveVar(''); }, - avatarUrlOptions: function() { + avatarUrlOptions() { return { auth: false, - brokenIsFine: true + brokenIsFine: true, }; }, - uploadedAvatars: function() { + uploadedAvatars() { return Avatars.find({userId: Meteor.userId()}); }, - isSelected: function() { - var userProfile = Meteor.user().profile; - var avatarUrl = userProfile && userProfile.avatarUrl; - var currentAvatarUrl = this.currentData().url(this.avatarUrlOptions()); + isSelected() { + const userProfile = Meteor.user().profile; + const avatarUrl = userProfile && userProfile.avatarUrl; + const currentAvatarUrl = this.currentData().url(this.avatarUrlOptions()); return avatarUrl === currentAvatarUrl; }, - noAvatarUrl: function() { - var userProfile = Meteor.user().profile; - var avatarUrl = userProfile && userProfile.avatarUrl; - return ! avatarUrl; + noAvatarUrl() { + const userProfile = Meteor.user().profile; + const avatarUrl = userProfile && userProfile.avatarUrl; + return !avatarUrl; }, - setAvatar: function(avatarUrl) { + setAvatar(avatarUrl) { Meteor.users.update(Meteor.userId(), { $set: { - 'profile.avatarUrl': avatarUrl - } + 'profile.avatarUrl': avatarUrl, + }, }); }, - setError: function(error) { + setError(error) { this.error.set(error); }, - events: function() { + events() { return [{ - 'click .js-upload-avatar': function() { + 'click .js-upload-avatar'() { this.$('.js-upload-avatar-input').click(); }, - 'change .js-upload-avatar-input': function(evt) { + 'change .js-upload-avatar-input'(evt) { let file, fileUrl; FS.Utility.eachFile(evt, (f) => { @@ -106,71 +106,71 @@ BlazeComponent.extendComponent({ if (fileUrl) { this.setError(''); - let fetchAvatarInterval = window.setInterval(() => { + const fetchAvatarInterval = window.setInterval(() => { $.ajax({ url: fileUrl, success: () => { this.setAvatar(file.url(this.avatarUrlOptions())); window.clearInterval(fetchAvatarInterval); - } + }, }); }, 100); } }, - 'click .js-select-avatar': function() { - var avatarUrl = this.currentData().url(this.avatarUrlOptions()); + 'click .js-select-avatar'() { + const avatarUrl = this.currentData().url(this.avatarUrlOptions()); this.setAvatar(avatarUrl); }, - 'click .js-select-initials': function() { + 'click .js-select-initials'() { this.setAvatar(''); }, - 'click .js-delete-avatar': function() { + 'click .js-delete-avatar'() { Avatars.remove(this.currentData()._id); - } + }, }]; - } + }, }).register('changeAvatarPopup'); Template.cardMembersPopup.helpers({ - isCardMember: function() { - var cardId = Template.parentData()._id; - var cardMembers = Cards.findOne(cardId).members || []; + isCardMember() { + const cardId = Template.parentData()._id; + const cardMembers = Cards.findOne(cardId).members || []; return _.contains(cardMembers, this.userId); }, - user: function() { + user() { return Users.findOne(this.userId); - } + }, }); Template.cardMembersPopup.events({ - 'click .js-select-member': function(evt) { - var cardId = Template.parentData(2).data._id; - var memberId = this.userId; - var operation; + 'click .js-select-member'(evt) { + const cardId = Template.parentData(2).data._id; + const memberId = this.userId; + let operation; if (Cards.find({ _id: cardId, members: memberId}).count() === 0) operation = '$addToSet'; else operation = '$pull'; - var query = {}; - query[operation] = { - members: memberId - }; - Cards.update(cardId, query); + Cards.update(cardId, { + [operation]: { + members: memberId, + }, + }); evt.preventDefault(); - } + }, }); Template.cardMemberPopup.helpers({ - user: function() { + user() { return Users.findOne(this.userId); - } + }, }); Template.cardMemberPopup.events({ - 'click .js-remove-member': function() { + 'click .js-remove-member'() { Cards.update(this.cardId, {$pull: {members: this.userId}}); Popup.close(); }, - 'click .js-edit-profile': Popup.open('editProfile') + 'click .js-edit-profile': Popup.open('editProfile'), }); diff --git a/client/components/users/userHeader.js b/client/components/users/userHeader.js index 2110faa6..d8b1ee48 100644 --- a/client/components/users/userHeader.js +++ b/client/components/users/userHeader.js @@ -1,6 +1,6 @@ Template.headerUserBar.events({ 'click .js-open-header-member-menu': Popup.open('memberMenu'), - 'click .js-change-avatar': Popup.open('changeAvatar') + 'click .js-change-avatar': Popup.open('changeAvatar'), }); Template.memberMenuPopup.events({ @@ -8,58 +8,57 @@ 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-logout': function(evt) { + 'click .js-logout'(evt) { evt.preventDefault(); AccountsTemplates.logout(); - } + }, }); Template.editProfilePopup.events({ - submit: function(evt, tpl) { + submit(evt, tpl) { evt.preventDefault(); - var fullname = $.trim(tpl.find('.js-profile-fullname').value); - var username = $.trim(tpl.find('.js-profile-username').value); - var initials = $.trim(tpl.find('.js-profile-initials').value); + const fullname = $.trim(tpl.find('.js-profile-fullname').value); + const username = $.trim(tpl.find('.js-profile-username').value); + const initials = $.trim(tpl.find('.js-profile-initials').value); Users.update(Meteor.userId(), {$set: { 'profile.fullname': fullname, - 'profile.initials': initials + 'profile.initials': initials, }}); // XXX We should report the error to the user. if (username !== Meteor.user().username) { Meteor.call('setUsername', username); } Popup.back(); - } + }, }); // 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() { +Template.changePasswordPopup.onRendered(() => { this.find('#at-field-current_password').focus(); }); Template.changeLanguagePopup.helpers({ - languages: function() { - return _.map(TAPi18n.getLanguages(), function(lang, tag) { - return { - tag: tag, - name: lang.name - }; + languages() { + return _.map(TAPi18n.getLanguages(), (lang, tag) => { + const name = lang.name; + return { tag, name }; }); }, - isCurrentLanguage: function() { + + isCurrentLanguage() { return this.tag === TAPi18n.getLanguage(); - } + }, }); Template.changeLanguagePopup.events({ - 'click .js-set-language': function(evt) { + 'click .js-set-language'(evt) { Users.update(Meteor.userId(), { $set: { - 'profile.language': this.tag - } + 'profile.language': this.tag, + }, }); evt.preventDefault(); - } + }, }); |