From 3eb4d2c341b712268bd321173909e0a7b19a88c9 Mon Sep 17 00:00:00 2001 From: Justin Reynolds Date: Fri, 28 Jun 2019 12:52:09 -0500 Subject: Prettier & eslint project style update --- .eslintrc.json | 13 +- client/components/activities/activities.js | 148 +- client/components/activities/comments.js | 76 +- client/components/boards/boardArchive.js | 63 +- client/components/boards/boardBody.js | 138 +- client/components/boards/boardHeader.js | 206 +-- client/components/boards/boardsList.js | 94 +- client/components/cards/attachments.js | 39 +- client/components/cards/cardCustomFields.js | 95 +- client/components/cards/cardDate.js | 186 +-- client/components/cards/cardDetails.js | 389 ++--- client/components/cards/cardTime.js | 62 +- client/components/cards/checklists.js | 70 +- client/components/cards/labels.js | 42 +- client/components/cards/minicard.js | 15 +- client/components/cards/subtasks.js | 56 +- client/components/import/import.js | 85 +- client/components/import/trelloMembersMapper.js | 2 +- client/components/import/wekanMembersMapper.js | 4 +- client/components/lists/list.js | 42 +- client/components/lists/listBody.js | 546 ++++--- client/components/lists/listHeader.js | 142 +- client/components/main/editor.js | 111 +- client/components/main/header.js | 4 +- client/components/main/layouts.js | 72 +- client/components/mixins/infiniteScrolling.js | 20 +- client/components/rules/actions/boardActions.js | 275 ++-- client/components/rules/actions/cardActions.js | 285 ++-- .../components/rules/actions/checklistActions.js | 261 ++-- client/components/rules/actions/mailActions.js | 57 +- client/components/rules/ruleDetails.js | 2 - client/components/rules/rulesActions.js | 28 +- client/components/rules/rulesMain.js | 136 +- client/components/rules/rulesTriggers.js | 22 +- client/components/rules/triggers/boardTriggers.js | 182 +-- client/components/rules/triggers/cardTriggers.js | 226 +-- .../components/rules/triggers/checklistTriggers.js | 275 ++-- client/components/settings/connectionMethod.js | 10 +- client/components/settings/peopleBody.js | 120 +- client/components/settings/settingBody.js | 143 +- client/components/sidebar/sidebar.js | 323 ++-- client/components/sidebar/sidebarArchives.js | 133 +- client/components/sidebar/sidebarCustomFields.js | 215 +-- client/components/sidebar/sidebarFilters.js | 154 +- client/components/sidebar/sidebarSearches.js | 12 +- client/components/swimlanes/swimlaneHeader.js | 110 +- client/components/swimlanes/swimlanes.js | 163 ++- client/components/users/userAvatar.js | 95 +- client/components/users/userHeader.js | 84 +- client/config/blazeHelpers.js | 2 +- client/lib/accessibility.js | 5 +- client/lib/cssEvents.js | 20 +- client/lib/datepicker.js | 102 +- client/lib/dropImage.js | 13 +- client/lib/escapeActions.js | 48 +- client/lib/filter.js | 434 +++--- client/lib/i18n.js | 2 +- client/lib/inlinedform.js | 50 +- client/lib/keyboard.js | 67 +- client/lib/modal.js | 16 +- client/lib/multiSelection.js | 48 +- client/lib/pasteImage.js | 16 +- client/lib/popup.js | 31 +- client/lib/textComplete.js | 9 +- client/lib/unsavedEdits.js | 6 +- client/lib/utils.js | 78 +- config/accounts.js | 60 +- config/router.js | 16 +- models/accountSettings.js | 11 +- models/actions.js | 5 - models/activities.js | 19 +- models/announcements.js | 7 +- models/attachments.js | 4 +- models/boards.js | 55 +- models/cardComments.js | 17 +- models/cards.js | 1548 +++++++++++--------- models/checklistItems.js | 17 +- models/checklists.js | 23 +- models/customFields.js | 31 +- models/export.js | 125 +- models/import.js | 18 +- models/integrations.js | 43 +- models/invitationCodes.js | 7 +- models/lists.js | 21 +- models/rules.js | 7 +- models/settings.js | 25 +- models/swimlanes.js | 27 +- models/trelloCreator.js | 360 ++--- models/triggers.js | 7 +- models/unsavedEdits.js | 9 +- models/users.js | 40 +- models/watchable.js | 12 +- models/wekanCreator.js | 579 ++++---- models/wekanmapper.js | 4 +- package.json | 2 +- sandstorm.js | 226 +-- server/accounts-lockout.js | 19 +- server/authentication.js | 27 +- server/cors.js | 18 +- server/header-login.js | 10 +- server/lib/utils.js | 2 +- server/migrations.js | 129 +- server/notifications/email.js | 10 +- server/notifications/notifications.js | 11 +- server/notifications/outgoing.js | 39 +- server/notifications/watch.js | 5 +- server/policy.js | 9 +- server/publications/activities.js | 15 +- server/publications/boards.js | 290 ++-- server/publications/cards.js | 2 +- server/publications/people.js | 27 +- server/publications/rules.js | 2 +- server/publications/settings.js | 32 +- server/publications/users.js | 13 +- server/rulesHelper.js | 306 ++-- server/triggersDef.js | 59 +- 116 files changed, 6152 insertions(+), 5176 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index c6d68748..ca29e181 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,11 +12,8 @@ "meteor": true }, "parserOptions": { - "ecmaVersion": 2017, - "sourceType": "module", - "ecmaFeatures": { - "experimentalObjectRestSpread": true - } + "ecmaVersion": 2018, + "sourceType": "module" }, "rules": { "strict": 0, @@ -26,7 +23,7 @@ "consistent-return": 2, "dot-notation": 2, "eqeqeq": 2, - "indent": [2, 2], + "indent": 0, "no-cond-assign": 2, "no-constant-condition": 2, "no-eval": 2, @@ -50,7 +47,6 @@ "quotes": [2, "single"], "semi-spacing": 2, "space-unary-ops": 2, - "arrow-parens": 2, "arrow-spacing": 2, "no-class-assign": 2, "no-dupe-class-members": 2, @@ -69,7 +65,8 @@ "singleQuote": true, "trailingComma": "all" } - ] + ], + "meteor/no-session": 0 }, "settings": { "import/resolver": { diff --git a/client/components/activities/activities.js b/client/components/activities/activities.js index 0476897f..05149826 100644 --- a/client/components/activities/activities.js +++ b/client/components/activities/activities.js @@ -13,7 +13,7 @@ BlazeComponent.extendComponent({ let thisId, searchId; if (mode === 'linkedcard' || mode === 'linkedboard') { thisId = Session.get('currentCard'); - searchId = Cards.findOne({_id: thisId}).linkedId; + searchId = Cards.findOne({ _id: thisId }).linkedId; mode = mode.replace('linked', ''); } else { thisId = Session.get(`current${capitalizedMode}`); @@ -22,8 +22,7 @@ BlazeComponent.extendComponent({ const limit = this.page.get() * activitiesPerPage; const user = Meteor.user(); const hideSystem = user ? user.hasHiddenSystemMessages() : false; - if (searchId === null) - return; + if (searchId === null) return; this.subscribe('activities', mode, searchId, limit, hideSystem, () => { this.loadNextPageLocked = false; @@ -50,9 +49,9 @@ BlazeComponent.extendComponent({ } }, - checkItem(){ + checkItem() { const checkItemId = this.currentData().checklistItemId; - const checkItem = ChecklistItems.findOne({_id:checkItemId}); + const checkItem = ChecklistItems.findOne({ _id: checkItemId }); return checkItem.title; }, @@ -66,42 +65,58 @@ BlazeComponent.extendComponent({ cardLink() { const card = this.currentData().card(); - return card && Blaze.toHTML(HTML.A({ - href: card.absoluteUrl(), - 'class': 'action-card', - }, card.title)); + return ( + card && + Blaze.toHTML( + HTML.A( + { + href: card.absoluteUrl(), + class: 'action-card', + }, + card.title, + ), + ) + ); }, - lastLabel(){ + lastLabel() { const lastLabelId = this.currentData().labelId; - if (!lastLabelId) - return null; - const lastLabel = Boards.findOne(Session.get('currentBoard')).getLabelById(lastLabelId); - if(lastLabel.name === undefined || lastLabel.name === ''){ + if (!lastLabelId) return null; + const lastLabel = Boards.findOne(Session.get('currentBoard')).getLabelById( + lastLabelId, + ); + if (lastLabel.name === undefined || lastLabel.name === '') { return lastLabel.color; - }else{ + } else { return lastLabel.name; } }, - lastCustomField(){ - const lastCustomField = CustomFields.findOne(this.currentData().customFieldId); - if (!lastCustomField) - return null; + lastCustomField() { + const lastCustomField = CustomFields.findOne( + this.currentData().customFieldId, + ); + if (!lastCustomField) return null; return lastCustomField.name; }, - lastCustomFieldValue(){ - const lastCustomField = CustomFields.findOne(this.currentData().customFieldId); - if (!lastCustomField) - return null; + lastCustomFieldValue() { + const lastCustomField = CustomFields.findOne( + this.currentData().customFieldId, + ); + if (!lastCustomField) return null; const value = this.currentData().value; - if (lastCustomField.settings.dropdownItems && lastCustomField.settings.dropdownItems.length > 0) { - const dropDownValue = _.find(lastCustomField.settings.dropdownItems, (item) => { - return item._id === value; - }); - if (dropDownValue) - return dropDownValue.name; + if ( + lastCustomField.settings.dropdownItems && + lastCustomField.settings.dropdownItems.length > 0 + ) { + const dropDownValue = _.find( + lastCustomField.settings.dropdownItems, + item => { + return item._id === value; + }, + ); + if (dropDownValue) return dropDownValue.name; } return value; }, @@ -112,11 +127,16 @@ BlazeComponent.extendComponent({ sourceLink() { const source = this.currentData().source; - if(source) { - if(source.url) { - return Blaze.toHTML(HTML.A({ - href: source.url, - }, source.system)); + if (source) { + if (source.url) { + return Blaze.toHTML( + HTML.A( + { + href: source.url, + }, + source.system, + ), + ); } else { return source.system; } @@ -133,38 +153,50 @@ BlazeComponent.extendComponent({ attachmentLink() { const attachment = this.currentData().attachment(); // trying to display url before file is stored generates js errors - return attachment && attachment.url({ download: true }) && Blaze.toHTML(HTML.A({ - href: attachment.url({ download: true }), - target: '_blank', - }, attachment.name())); + return ( + attachment && + attachment.url({ download: true }) && + Blaze.toHTML( + HTML.A( + { + href: attachment.url({ download: true }), + target: '_blank', + }, + attachment.name(), + ), + ) + ); }, customField() { const customField = this.currentData().customField(); - if (!customField) - return null; + if (!customField) return null; return customField.name; }, events() { - return [{ - // XXX We should use Popup.afterConfirmation here - 'click .js-delete-comment'() { - const commentId = this.currentData().commentId; - CardComments.remove(commentId); - }, - 'submit .js-edit-comment'(evt) { - evt.preventDefault(); - const commentText = this.currentComponent().getValue().trim(); - const commentId = Template.parentData().commentId; - if (commentText) { - CardComments.update(commentId, { - $set: { - text: commentText, - }, - }); - } + return [ + { + // XXX We should use Popup.afterConfirmation here + 'click .js-delete-comment'() { + const commentId = this.currentData().commentId; + CardComments.remove(commentId); + }, + 'submit .js-edit-comment'(evt) { + evt.preventDefault(); + const commentText = this.currentComponent() + .getValue() + .trim(); + const commentId = Template.parentData().commentId; + if (commentText) { + CardComments.update(commentId, { + $set: { + text: commentText, + }, + }); + } + }, }, - }]; + ]; }, }).register('activities'); diff --git a/client/components/activities/comments.js b/client/components/activities/comments.js index 34b6402c..3fc5770c 100644 --- a/client/components/activities/comments.js +++ b/client/components/activities/comments.js @@ -14,39 +14,41 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-new-comment:not(.focus)'() { - commentFormIsOpen.set(true); + return [ + { + 'click .js-new-comment:not(.focus)'() { + commentFormIsOpen.set(true); + }, + 'submit .js-new-comment-form'(evt) { + const input = this.getInput(); + const text = input.val().trim(); + const card = this.currentData(); + let boardId = card.boardId; + let cardId = card._id; + if (card.isLinkedCard()) { + boardId = Cards.findOne(card.linkedId).boardId; + cardId = card.linkedId; + } + if (text) { + CardComments.insert({ + text, + boardId, + cardId, + }); + resetCommentInput(input); + Tracker.flush(); + autosize.update(input); + } + evt.preventDefault(); + }, + // Pressing Ctrl+Enter should submit the form + 'keydown form textarea'(evt) { + if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) { + this.find('button[type=submit]').click(); + } + }, }, - 'submit .js-new-comment-form'(evt) { - const input = this.getInput(); - const text = input.val().trim(); - const card = this.currentData(); - let boardId = card.boardId; - let cardId = card._id; - if (card.isLinkedCard()) { - boardId = Cards.findOne(card.linkedId).boardId; - cardId = card.linkedId; - } - if (text) { - CardComments.insert({ - text, - boardId, - cardId, - }); - resetCommentInput(input); - Tracker.flush(); - autosize.update(input); - } - evt.preventDefault(); - }, - // Pressing Ctrl+Enter should submit the form - 'keydown form textarea'(evt) { - if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) { - this.find('button[type=submit]').click(); - } - }, - }]; + ]; }, }).register('commentForm'); @@ -69,7 +71,8 @@ Tracker.autorun(() => { }); }); -EscapeActions.register('inlinedForm', +EscapeActions.register( + 'inlinedForm', () => { const draftKey = { fieldName: 'cardComment', @@ -84,7 +87,10 @@ EscapeActions.register('inlinedForm', } resetCommentInput(commentInput); }, - () => { return commentFormIsOpen.get(); }, { + () => { + return commentFormIsOpen.get(); + }, + { noClickEscapeOn: '.js-new-comment', - } + }, ); diff --git a/client/components/boards/boardArchive.js b/client/components/boards/boardArchive.js index c8bbb341..d3e65bd8 100644 --- a/client/components/boards/boardArchive.js +++ b/client/components/boards/boardArchive.js @@ -4,36 +4,45 @@ BlazeComponent.extendComponent({ }, archivedBoards() { - return Boards.find({ archived: true }, { - sort: ['title'], - }); + return Boards.find( + { archived: true }, + { + sort: ['title'], + }, + ); }, events() { - return [{ - 'click .js-restore-board'() { - // TODO : Make isSandstorm variable global - const isSandstorm = Meteor.settings && Meteor.settings.public && - Meteor.settings.public.sandstorm; - if (isSandstorm && Session.get('currentBoard')) { - const currentBoard = Boards.findOne(Session.get('currentBoard')); - currentBoard.archive(); - } - const board = this.currentData(); - board.restore(); - Utils.goBoardId(board._id); + return [ + { + 'click .js-restore-board'() { + // TODO : Make isSandstorm variable global + const isSandstorm = + Meteor.settings && + Meteor.settings.public && + Meteor.settings.public.sandstorm; + if (isSandstorm && Session.get('currentBoard')) { + const currentBoard = Boards.findOne(Session.get('currentBoard')); + currentBoard.archive(); + } + const board = this.currentData(); + board.restore(); + Utils.goBoardId(board._id); + }, + 'click .js-delete-board': Popup.afterConfirm('boardDelete', function() { + Popup.close(); + const isSandstorm = + Meteor.settings && + Meteor.settings.public && + Meteor.settings.public.sandstorm; + if (isSandstorm && Session.get('currentBoard')) { + const currentBoard = Boards.findOne(Session.get('currentBoard')); + Boards.remove(currentBoard._id); + } + Boards.remove(this._id); + FlowRouter.go('home'); + }), }, - 'click .js-delete-board': Popup.afterConfirm('boardDelete', function() { - Popup.close(); - const isSandstorm = Meteor.settings && Meteor.settings.public && - Meteor.settings.public.sandstorm; - if (isSandstorm && Session.get('currentBoard')) { - const currentBoard = Boards.findOne(Session.get('currentBoard')); - Boards.remove(currentBoard._id); - } - Boards.remove(this._id); - FlowRouter.go('home'); - }), - }]; + ]; }, }).register('archivedBoards'); diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index e9b9f88a..81fa3d87 100644 --- a/client/components/boards/boardBody.js +++ b/client/components/boards/boardBody.js @@ -12,8 +12,7 @@ BlazeComponent.extendComponent({ // unfortunatly, Blaze doesn't have this notion. this.autorun(() => { const currentBoardId = Session.get('currentBoard'); - if (!currentBoardId) - return; + if (!currentBoardId) return; const handle = subManager.subscribe('board', currentBoardId, false); Tracker.nonreactive(() => { Tracker.autorun(() => { @@ -30,7 +29,6 @@ BlazeComponent.extendComponent({ goHome() { FlowRouter.go('home'); }, - }).register('board'); BlazeComponent.extendComponent({ @@ -47,7 +45,7 @@ BlazeComponent.extendComponent({ if (nullSortSwimlanes.count() > 0) { const swimlanes = currentBoardData.swimlanes(); let count = 0; - swimlanes.forEach((s) => { + swimlanes.forEach(s => { Swimlanes.update(s._id, { $set: { sort: count, @@ -62,7 +60,7 @@ BlazeComponent.extendComponent({ if (nullSortLists.count() > 0) { const lists = currentBoardData.lists(); let count = 0; - lists.forEach((l) => { + lists.forEach(l => { Lists.update(l._id, { $set: { sort: count, @@ -110,12 +108,15 @@ BlazeComponent.extendComponent({ // resize all swimlanes + headers to be a total of 150 px per row // this could be achieved by setIsDragging(true) but we want immediate // result - ui.item.siblings('.js-swimlane').css('height', `${swimlaneWhileSortingHeight - 26}px`); + ui.item + .siblings('.js-swimlane') + .css('height', `${swimlaneWhileSortingHeight - 26}px`); // set the new scroll height after the resize and insertion of // the placeholder. We want the element under the cursor to stay // at the same place on the screen - ui.item.parent().get(0).scrollTop = ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY; + ui.item.parent().get(0).scrollTop = + ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY; }, beforeStop(evt, ui) { const parentOffset = ui.item.parent().offset(); @@ -124,7 +125,8 @@ BlazeComponent.extendComponent({ // compute the new scroll height after the resize and removal of // the placeholder - const scrollTop = ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY; + const scrollTop = + ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY; // then reset the original view of the swimlane siblings.removeClass('moving-swimlane'); @@ -154,11 +156,14 @@ BlazeComponent.extendComponent({ sort(evt, ui) { // get the mouse position in the sortable const parentOffset = ui.item.parent().offset(); - const cursorY = evt.pageY - parentOffset.top + ui.item.parent().scrollTop(); + const cursorY = + evt.pageY - parentOffset.top + ui.item.parent().scrollTop(); // compute the intended index of the placeholder (we need to skip the // slots between the headers and the list of cards) - const newplaceholderIndex = Math.floor(cursorY / swimlaneWhileSortingHeight); + const newplaceholderIndex = Math.floor( + cursorY / swimlaneWhileSortingHeight, + ); let destPlaceholderIndex = (newplaceholderIndex + 1) * 2; // if we are scrolling far away from the bottom of the list @@ -169,9 +174,17 @@ BlazeComponent.extendComponent({ // update the placeholder position in the DOM tree if (destPlaceholderIndex !== ui.placeholder.index()) { if (destPlaceholderIndex < boardComponent.origPlaceholderIndex) { - ui.placeholder.insertBefore(ui.placeholder.siblings().slice(destPlaceholderIndex - 2, destPlaceholderIndex - 1)); + ui.placeholder.insertBefore( + ui.placeholder + .siblings() + .slice(destPlaceholderIndex - 2, destPlaceholderIndex - 1), + ); } else { - ui.placeholder.insertAfter(ui.placeholder.siblings().slice(destPlaceholderIndex - 1, destPlaceholderIndex)); + ui.placeholder.insertAfter( + ui.placeholder + .siblings() + .slice(destPlaceholderIndex - 1, destPlaceholderIndex), + ); } } }, @@ -181,7 +194,11 @@ BlazeComponent.extendComponent({ enableClickOnTouch('.js-swimlane:not(.placeholder)'); function userIsMember() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); } // If there is no data in the board (ie, no lists) we autofocus the list @@ -195,45 +212,49 @@ BlazeComponent.extendComponent({ isViewSwimlanes() { const currentUser = Meteor.user(); if (!currentUser) return false; - return ((currentUser.profile || {}).boardView === 'board-view-swimlanes'); + return (currentUser.profile || {}).boardView === 'board-view-swimlanes'; }, isViewLists() { const currentUser = Meteor.user(); if (!currentUser) return true; - return ((currentUser.profile || {}).boardView === 'board-view-lists'); + return (currentUser.profile || {}).boardView === 'board-view-lists'; }, isViewCalendar() { const currentUser = Meteor.user(); if (!currentUser) return false; - return ((currentUser.profile || {}).boardView === 'board-view-cal'); + return (currentUser.profile || {}).boardView === 'board-view-cal'; }, openNewListForm() { if (this.isViewSwimlanes()) { this.childComponents('swimlane')[0] - .childComponents('addListAndSwimlaneForm')[0].open(); + .childComponents('addListAndSwimlaneForm')[0] + .open(); } else if (this.isViewLists()) { this.childComponents('listsGroup')[0] - .childComponents('addListForm')[0].open(); + .childComponents('addListForm')[0] + .open(); } }, events() { - return [{ - // XXX The board-overlay div should probably be moved to the parent - // component. - 'mouseenter .board-overlay'() { - if (this.mouseHasEnterCardDetails) { - this.showOverlay.set(false); - } - }, - 'mouseup'() { - if (this._isDragging) { - this._isDragging = false; - } + return [ + { + // XXX The board-overlay div should probably be moved to the parent + // component. + 'mouseenter .board-overlay'() { + if (this.mouseHasEnterCardDetails) { + this.showOverlay.set(false); + } + }, + mouseup() { + if (this._isDragging) { + this._isDragging = false; + } + }, }, - }]; + ]; }, // XXX Flow components allow us to avoid creating these two setter methods by @@ -245,23 +266,24 @@ BlazeComponent.extendComponent({ scrollLeft(position = 0) { const swimlanes = this.$('.js-swimlanes'); - swimlanes && swimlanes.animate({ - scrollLeft: position, - }); + swimlanes && + swimlanes.animate({ + scrollLeft: position, + }); }, scrollTop(position = 0) { const swimlanes = this.$('.js-swimlanes'); - swimlanes && swimlanes.animate({ - scrollTop: position, - }); + swimlanes && + swimlanes.animate({ + scrollTop: position, + }); }, - }).register('boardBody'); BlazeComponent.extendComponent({ onRendered() { - this.autorun(function(){ + this.autorun(function() { $('#calendar-view').fullCalendar('refetchEvents'); }); }, @@ -273,7 +295,8 @@ BlazeComponent.extendComponent({ timezone: 'local', header: { left: 'title today prev,next', - center: 'agendaDay,listDay,timelineDay agendaWeek,listWeek,timelineWeek month,timelineMonth timelineYear', + center: + 'agendaDay,listDay,timelineDay agendaWeek,listWeek,timelineWeek month,timelineMonth timelineYear', right: '', }, // height: 'parent', nope, doesn't work as the parent might be small @@ -283,7 +306,7 @@ BlazeComponent.extendComponent({ nowIndicator: true, businessHours: { // days of week. an array of zero-based day of week integers (0=Sunday) - dow: [ 1, 2, 3, 4, 5 ], // Monday - Friday + dow: [1, 2, 3, 4, 5], // Monday - Friday start: '8:00', end: '18:00', }, @@ -291,20 +314,25 @@ BlazeComponent.extendComponent({ events(start, end, timezone, callback) { const currentBoard = Boards.findOne(Session.get('currentBoard')); const events = []; - currentBoard.cardsInInterval(start.toDate(), end.toDate()).forEach(function(card){ - events.push({ - id: card._id, - title: card.title, - start: card.startAt, - end: card.endAt, - allDay: Math.abs(card.endAt.getTime() - card.startAt.getTime()) / 1000 === 24*3600, - url: FlowRouter.url('card', { - boardId: currentBoard._id, - slug: currentBoard.slug, - cardId: card._id, - }), + currentBoard + .cardsInInterval(start.toDate(), end.toDate()) + .forEach(function(card) { + events.push({ + id: card._id, + title: card.title, + start: card.startAt, + end: card.endAt, + allDay: + Math.abs(card.endAt.getTime() - card.startAt.getTime()) / + 1000 === + 24 * 3600, + url: FlowRouter.url('card', { + boardId: currentBoard._id, + slug: currentBoard.slug, + cardId: card._id, + }), + }); }); - }); callback(events); }, eventResize(event, delta, revertFunc) { @@ -339,6 +367,6 @@ BlazeComponent.extendComponent({ isViewCalendar() { const currentUser = Meteor.user(); if (!currentUser) return false; - return ((currentUser.profile || {}).boardView === 'board-view-cal'); + return (currentUser.profile || {}).boardView === 'board-view-cal'; }, }).register('calendarView'); diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index f2b5c4f5..cb84c233 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -45,15 +45,21 @@ Template.boardMenuPopup.helpers({ }); Template.boardChangeTitlePopup.events({ - submit(evt, tpl) { - const newTitle = tpl.$('.js-board-name').val().trim(); - const newDesc = tpl.$('.js-board-desc').val().trim(); + submit(event, templateInstance) { + const newTitle = templateInstance + .$('.js-board-name') + .val() + .trim(); + const newDesc = templateInstance + .$('.js-board-desc') + .val() + .trim(); if (newTitle) { this.rename(newTitle); this.setDescription(newDesc); Popup.close(); } - evt.preventDefault(); + event.preventDefault(); }, }); @@ -76,67 +82,79 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-edit-board-title': Popup.open('boardChangeTitle'), - 'click .js-star-board'() { - Meteor.user().toggleBoardStar(Session.get('currentBoard')); + return [ + { + 'click .js-edit-board-title': Popup.open('boardChangeTitle'), + '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-watch-board': Popup.open('boardChangeWatch'), + 'click .js-open-archived-board'() { + Modal.open('archivedBoards'); + }, + 'click .js-toggle-board-view'() { + const currentUser = Meteor.user(); + if ( + (currentUser.profile || {}).boardView === 'board-view-swimlanes' + ) { + currentUser.setBoardView('board-view-cal'); + } else if ( + (currentUser.profile || {}).boardView === 'board-view-lists' + ) { + currentUser.setBoardView('board-view-swimlanes'); + } else if ( + (currentUser.profile || {}).boardView === 'board-view-cal' + ) { + currentUser.setBoardView('board-view-lists'); + } else { + currentUser.setBoardView('board-view-swimlanes'); + } + }, + 'click .js-toggle-sidebar'() { + Sidebar.toggle(); + }, + 'click .js-open-filter-view'() { + Sidebar.setView('filter'); + }, + 'click .js-filter-reset'(event) { + event.stopPropagation(); + Sidebar.setView(); + Filter.reset(); + }, + 'click .js-open-search-view'() { + Sidebar.setView('search'); + }, + 'click .js-open-rules-view'() { + Modal.openWide('rulesMain'); + }, + 'click .js-multiselection-activate'() { + const currentCard = Session.get('currentCard'); + MultiSelection.activate(); + if (currentCard) { + MultiSelection.add(currentCard); + } + }, + 'click .js-multiselection-reset'(event) { + event.stopPropagation(); + MultiSelection.disable(); + }, + 'click .js-log-in'() { + FlowRouter.go('atSignIn'); + }, }, - '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-archived-board'() { - Modal.open('archivedBoards'); - }, - 'click .js-toggle-board-view'() { - const currentUser = Meteor.user(); - if ((currentUser.profile || {}).boardView === 'board-view-swimlanes') { - currentUser.setBoardView('board-view-cal'); - } else if ((currentUser.profile || {}).boardView === 'board-view-lists') { - currentUser.setBoardView('board-view-swimlanes'); - } else if ((currentUser.profile || {}).boardView === 'board-view-cal') { - currentUser.setBoardView('board-view-lists'); - } else { - currentUser.setBoardView('board-view-swimlanes'); - } - }, - 'click .js-toggle-sidebar'() { - Sidebar.toggle(); - }, - 'click .js-open-filter-view'() { - Sidebar.setView('filter'); - }, - 'click .js-filter-reset'(evt) { - evt.stopPropagation(); - Sidebar.setView(); - Filter.reset(); - }, - 'click .js-open-search-view'() { - Sidebar.setView('search'); - }, - 'click .js-open-rules-view'() { - Modal.openWide('rulesMain'); - }, - 'click .js-multiselection-activate'() { - const currentCard = Session.get('currentCard'); - MultiSelection.activate(); - if (currentCard) { - MultiSelection.add(currentCard); - } - }, - 'click .js-multiselection-reset'(evt) { - evt.stopPropagation(); - MultiSelection.disable(); - }, - 'click .js-log-in'() { - FlowRouter.go('atSignIn'); - }, - }]; + ]; }, }).register('boardHeaderBar'); Template.boardHeaderBar.helpers({ canModifyBoard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }); @@ -164,15 +182,17 @@ const CreateBoard = BlazeComponent.extendComponent({ this.visibilityMenuIsOpen.set(!this.visibilityMenuIsOpen.get()); }, - onSubmit(evt) { - evt.preventDefault(); + onSubmit(event) { + event.preventDefault(); const title = this.find('.js-new-board-title').value; const visibility = this.visibility.get(); - this.boardId.set(Boards.insert({ - title, - permission: visibility, - })); + this.boardId.set( + Boards.insert({ + title, + permission: visibility, + }), + ); Swimlanes.insert({ title: 'Default', @@ -183,26 +203,28 @@ const CreateBoard = BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-select-visibility'() { - this.setVisibility(this.currentData()); + return [ + { + 'click .js-select-visibility'() { + this.setVisibility(this.currentData()); + }, + 'click .js-change-visibility': this.toggleVisibilityMenu, + 'click .js-import': Popup.open('boardImportBoard'), + submit: this.onSubmit, + 'click .js-import-board': Popup.open('chooseBoardSource'), + 'click .js-board-template': Popup.open('searchElement'), }, - 'click .js-change-visibility': this.toggleVisibilityMenu, - 'click .js-import': Popup.open('boardImportBoard'), - submit: this.onSubmit, - 'click .js-import-board': Popup.open('chooseBoardSource'), - 'click .js-board-template': Popup.open('searchElement'), - }]; + ]; }, }).register('createBoardPopup'); (class HeaderBarCreateBoard extends CreateBoard { - onSubmit(evt) { - super.onSubmit(evt); + onSubmit(event) { + super.onSubmit(event); // Immediately star boards crated with the headerbar popup. Meteor.user().toggleBoardStar(this.boardId.get()); } -}).register('headerBarCreateBoardPopup'); +}.register('headerBarCreateBoardPopup')); BlazeComponent.extendComponent({ visibilityCheck() { @@ -218,9 +240,11 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-select-visibility': this.selectBoardVisibility, - }]; + return [ + { + 'click .js-select-visibility': this.selectBoardVisibility, + }, + ]; }, }).register('boardChangeVisibilityPopup'); @@ -235,13 +259,21 @@ BlazeComponent.extendComponent({ }, 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(); - }); + 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/boards/boardsList.js b/client/components/boards/boardsList.js index 0fb80230..cc586b1f 100644 --- a/client/components/boards/boardsList.js +++ b/client/components/boards/boardsList.js @@ -21,11 +21,14 @@ BlazeComponent.extendComponent({ }, boards() { - return Boards.find({ - archived: false, - 'members.userId': Meteor.userId(), - type: 'board', - }, { sort: ['title'] }); + return Boards.find( + { + archived: false, + 'members.userId': Meteor.userId(), + type: 'board', + }, + { sort: ['title'] }, + ); }, isStarred() { const user = Meteor.user(); @@ -48,46 +51,49 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-add-board': Popup.open('createBoard'), - 'click .js-star-board'(evt) { - const boardId = this.currentData()._id; - Meteor.user().toggleBoardStar(boardId); - evt.preventDefault(); - }, - 'click .js-clone-board'(evt) { - Meteor.call('cloneBoard', - this.currentData()._id, - Session.get('fromBoard'), - (err, res) => { - if (err) { - this.setError(err.error); - } else { - Session.set('fromBoard', null); - Utils.goBoardId(res); + return [ + { + 'click .js-add-board': Popup.open('createBoard'), + 'click .js-star-board'(evt) { + const boardId = this.currentData()._id; + Meteor.user().toggleBoardStar(boardId); + evt.preventDefault(); + }, + 'click .js-clone-board'(evt) { + Meteor.call( + 'cloneBoard', + this.currentData()._id, + Session.get('fromBoard'), + (err, res) => { + if (err) { + this.setError(err.error); + } else { + Session.set('fromBoard', null); + Utils.goBoardId(res); + } + }, + ); + evt.preventDefault(); + }, + 'click .js-archive-board'(evt) { + const boardId = this.currentData()._id; + Meteor.call('archiveBoard', boardId); + evt.preventDefault(); + }, + 'click .js-accept-invite'() { + const boardId = this.currentData()._id; + Meteor.user().removeInvite(boardId); + }, + 'click .js-decline-invite'() { + const boardId = this.currentData()._id; + Meteor.call('quitBoard', boardId, (err, ret) => { + if (!err && ret) { + Meteor.user().removeInvite(boardId); + FlowRouter.go('home'); } - } - ); - evt.preventDefault(); - }, - 'click .js-archive-board'(evt) { - const boardId = this.currentData()._id; - Meteor.call('archiveBoard', boardId); - evt.preventDefault(); - }, - 'click .js-accept-invite'() { - const boardId = this.currentData()._id; - Meteor.user().removeInvite(boardId); - }, - 'click .js-decline-invite'() { - const boardId = this.currentData()._id; - Meteor.call('quitBoard', boardId, (err, ret) => { - if (!err && ret) { - Meteor.user().removeInvite(boardId); - FlowRouter.go('home'); - } - }); + }); + }, }, - }]; + ]; }, }).register('boardList'); diff --git a/client/components/cards/attachments.js b/client/components/cards/attachments.js index e3dc143a..6b3e38a5 100644 --- a/client/components/cards/attachments.js +++ b/client/components/cards/attachments.js @@ -1,10 +1,11 @@ Template.attachmentsGalery.events({ 'click .js-add-attachment': Popup.open('cardAttachments'), - 'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', + '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. @@ -17,8 +18,8 @@ Template.attachmentsGalery.events({ 'click .js-remove-cover'() { Cards.findOne(this.cardId).unsetCover(); }, - 'click .js-preview-image'(evt) { - Popup.open('previewAttachedImage').call(this, evt); + 'click .js-preview-image'(event) { + Popup.open('previewAttachedImage').call(this, event); // when multiple thumbnails, if click one then another very fast, // we might get a wrong width from previous img. // when popup reused, onRendered() won't be called, so we cannot get there. @@ -31,31 +32,29 @@ Template.attachmentsGalery.events({ // if the image is too large, we resize & center the popup. if (w > 300) { $('div.pop-over').css({ - width: (w + 20), + width: w + 20, position: 'absolute', - left: (window.innerWidth - w)/2, - top: (window.innerHeight - h)/2, + left: (window.innerWidth - w) / 2, + top: (window.innerHeight - h) / 2, }); } }; - const url = $(evt.currentTarget).attr('src'); - if (img.src === url && img.complete) - rePosPopup(); - else - img.onload = rePosPopup; + const url = $(event.currentTarget).attr('src'); + if (img.src === url && img.complete) rePosPopup(); + else img.onload = rePosPopup; }, }); Template.previewAttachedImagePopup.events({ - 'click .js-large-image-clicked'(){ + 'click .js-large-image-clicked'() { Popup.close(); }, }); Template.cardAttachmentsPopup.events({ - 'change .js-attach-file'(evt) { + 'change .js-attach-file'(event) { const card = this; - FS.Utility.eachFile(evt, (f) => { + FS.Utility.eachFile(event, f => { const file = new FS.File(f); if (card.isLinkedCard()) { file.boardId = Cards.findOne(card.linkedId).boardId; @@ -77,9 +76,9 @@ Template.cardAttachmentsPopup.events({ Popup.close(); }); }, - 'click .js-computer-upload'(evt, tpl) { - tpl.find('.js-attach-file').click(); - evt.preventDefault(); + 'click .js-computer-upload'(event, templateInstance) { + templateInstance.find('.js-attach-file').click(); + event.preventDefault(); }, 'click .js-upload-clipboard-image': Popup.open('previewClipboardImage'), }); @@ -88,7 +87,7 @@ let pastedResults = null; Template.previewClipboardImagePopup.onRendered(() => { // we can paste image from clipboard - $(document.body).pasteImageReader((results) => { + $(document.body).pasteImageReader(results => { if (results.dataURL.startsWith('data:image/')) { $('img.preview-clipboard-image').attr('src', results.dataURL); pastedResults = results; @@ -96,7 +95,7 @@ Template.previewClipboardImagePopup.onRendered(() => { }); // we can also drag & drop image file to it - $(document.body).dropImageReader((results) => { + $(document.body).dropImageReader(results => { if (results.dataURL.startsWith('data:image/')) { $('img.preview-clipboard-image').attr('src', results.dataURL); pastedResults = results; diff --git a/client/components/cards/cardCustomFields.js b/client/components/cards/cardCustomFields.js index aa50caec..d0b9c72d 100644 --- a/client/components/cards/cardCustomFields.js +++ b/client/components/cards/cardCustomFields.js @@ -7,22 +7,21 @@ Template.cardCustomFieldsPopup.helpers({ }); Template.cardCustomFieldsPopup.events({ - 'click .js-select-field'(evt) { + 'click .js-select-field'(event) { const card = Cards.findOne(Session.get('currentCard')); const customFieldId = this._id; card.toggleCustomField(customFieldId); - evt.preventDefault(); + event.preventDefault(); }, - 'click .js-settings'(evt) { + 'click .js-settings'(event) { EscapeActions.executeUpTo('detailsPane'); Sidebar.setView('customFields'); - evt.preventDefault(); + event.preventDefault(); }, }); // cardCustomField const CardCustomField = BlazeComponent.extendComponent({ - getTemplate() { return `cardCustomField-${this.data().definition.type}`; }, @@ -34,52 +33,55 @@ const CardCustomField = BlazeComponent.extendComponent({ }, canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }); CardCustomField.register('cardCustomField'); // cardCustomField-text (class extends CardCustomField { - onCreated() { super.onCreated(); } events() { - return [{ - 'submit .js-card-customfield-text'(evt) { - evt.preventDefault(); - const value = this.currentComponent().getValue(); - this.card.setCustomField(this.customFieldId, value); + return [ + { + 'submit .js-card-customfield-text'(event) { + event.preventDefault(); + const value = this.currentComponent().getValue(); + this.card.setCustomField(this.customFieldId, value); + }, }, - }]; + ]; } - -}).register('cardCustomField-text'); +}.register('cardCustomField-text')); // cardCustomField-number (class extends CardCustomField { - onCreated() { super.onCreated(); } events() { - return [{ - 'submit .js-card-customfield-number'(evt) { - evt.preventDefault(); - const value = parseInt(this.find('input').value, 10); - this.card.setCustomField(this.customFieldId, value); + return [ + { + 'submit .js-card-customfield-number'(event) { + event.preventDefault(); + const value = parseInt(this.find('input').value, 10); + this.card.setCustomField(this.customFieldId, value); + }, }, - }]; + ]; } - -}).register('cardCustomField-number'); +}.register('cardCustomField-number')); // cardCustomField-date (class extends CardCustomField { - onCreated() { super.onCreated(); const self = this; @@ -108,8 +110,10 @@ CardCustomField.register('cardCustomField'); } classes() { - if (this.date.get().isBefore(this.now.get(), 'minute') && - this.now.get().isBefore(this.data().value)) { + if ( + this.date.get().isBefore(this.now.get(), 'minute') && + this.now.get().isBefore(this.data().value) + ) { return 'current'; } return ''; @@ -120,12 +124,13 @@ CardCustomField.register('cardCustomField'); } events() { - return [{ - 'click .js-edit-date': Popup.open('cardCustomField-date'), - }]; + return [ + { + 'click .js-edit-date': Popup.open('cardCustomField-date'), + }, + ]; } - -}).register('cardCustomField-date'); +}.register('cardCustomField-date')); // cardCustomField-datePopup (class extends DatePicker { @@ -144,11 +149,10 @@ CardCustomField.register('cardCustomField'); _deleteDate() { this.card.setCustomField(this.customFieldId, ''); } -}).register('cardCustomField-datePopup'); +}.register('cardCustomField-datePopup')); // cardCustomField-dropdown (class extends CardCustomField { - onCreated() { super.onCreated(); this._items = this.data().definition.settings.dropdownItems; @@ -160,20 +164,23 @@ CardCustomField.register('cardCustomField'); } selectedItem() { - const selected = this._items.find((item) => { + const selected = this._items.find(item => { return item._id === this.data().value; }); - return (selected) ? selected.name : TAPi18n.__('custom-field-dropdown-unknown'); + return selected + ? selected.name + : TAPi18n.__('custom-field-dropdown-unknown'); } events() { - return [{ - 'submit .js-card-customfield-dropdown'(evt) { - evt.preventDefault(); - const value = this.find('select').value; - this.card.setCustomField(this.customFieldId, value); + return [ + { + 'submit .js-card-customfield-dropdown'(event) { + event.preventDefault(); + const value = this.find('select').value; + this.card.setCustomField(this.customFieldId, value); + }, }, - }]; + ]; } - -}).register('cardCustomField-dropdown'); +}.register('cardCustomField-dropdown')); diff --git a/client/components/cards/cardDate.js b/client/components/cards/cardDate.js index 182705d5..91205f1c 100644 --- a/client/components/cards/cardDate.js +++ b/client/components/cards/cardDate.js @@ -11,15 +11,20 @@ BlazeComponent.extendComponent({ }, onRendered() { - const $picker = this.$('.js-datepicker').datepicker({ - todayHighlight: true, - todayBtn: 'linked', - language: TAPi18n.getLanguage(), - }).on('changeDate', function(evt) { - this.find('#date').value = moment(evt.date).format('L'); - this.error.set(''); - this.find('#time').focus(); - }.bind(this)); + const $picker = this.$('.js-datepicker') + .datepicker({ + todayHighlight: true, + todayBtn: 'linked', + language: TAPi18n.getLanguage(), + }) + .on( + 'changeDate', + function(evt) { + this.find('#date').value = moment(evt.date).format('L'); + this.error.set(''); + this.find('#time').focus(); + }.bind(this), + ); if (this.date.get().isValid()) { $picker.datepicker('update', this.date.get().toDate()); @@ -27,13 +32,11 @@ BlazeComponent.extendComponent({ }, showDate() { - if (this.date.get().isValid()) - return this.date.get().format('L'); + if (this.date.get().isValid()) return this.date.get().format('L'); return ''; }, showTime() { - if (this.date.get().isValid()) - return this.date.get().format('LT'); + if (this.date.get().isValid()) return this.date.get().format('LT'); return ''; }, dateFormat() { @@ -44,51 +47,58 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'keyup .js-date-field'() { - // parse for localized date format in strict mode - const dateMoment = moment(this.find('#date').value, 'L', true); - if (dateMoment.isValid()) { - this.error.set(''); - this.$('.js-datepicker').datepicker('update', dateMoment.toDate()); - } - }, - 'keyup .js-time-field'() { - // parse for localized time format in strict mode - const dateMoment = moment(this.find('#time').value, 'LT', true); - if (dateMoment.isValid()) { - this.error.set(''); - } - }, - 'submit .edit-date'(evt) { - evt.preventDefault(); - - // if no time was given, init with 12:00 - const time = evt.target.time.value || moment(new Date().setHours(12, 0, 0)).format('LT'); - - const dateString = `${evt.target.date.value} ${time}`; - const newDate = moment(dateString, 'L LT', true); - if (newDate.isValid()) { - this._storeDate(newDate.toDate()); + return [ + { + 'keyup .js-date-field'() { + // parse for localized date format in strict mode + const dateMoment = moment(this.find('#date').value, 'L', true); + if (dateMoment.isValid()) { + this.error.set(''); + this.$('.js-datepicker').datepicker('update', dateMoment.toDate()); + } + }, + 'keyup .js-time-field'() { + // parse for localized time format in strict mode + const dateMoment = moment(this.find('#time').value, 'LT', true); + if (dateMoment.isValid()) { + this.error.set(''); + } + }, + 'submit .edit-date'(evt) { + evt.preventDefault(); + + // if no time was given, init with 12:00 + const time = + evt.target.time.value || + moment(new Date().setHours(12, 0, 0)).format('LT'); + + const dateString = `${evt.target.date.value} ${time}`; + const newDate = moment(dateString, 'L LT', true); + if (newDate.isValid()) { + this._storeDate(newDate.toDate()); + Popup.close(); + } else { + this.error.set('invalid-date'); + evt.target.date.focus(); + } + }, + 'click .js-delete-date'(evt) { + evt.preventDefault(); + this._deleteDate(); Popup.close(); - } - else { - this.error.set('invalid-date'); - evt.target.date.focus(); - } - }, - 'click .js-delete-date'(evt) { - evt.preventDefault(); - this._deleteDate(); - Popup.close(); + }, }, - }]; + ]; }, }); Template.dateBadge.helpers({ canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }); @@ -96,7 +106,8 @@ Template.dateBadge.helpers({ (class extends DatePicker { onCreated() { super.onCreated(); - this.data().getReceived() && this.date.set(moment(this.data().getReceived())); + this.data().getReceived() && + this.date.set(moment(this.data().getReceived())); } _storeDate(date) { @@ -106,8 +117,7 @@ Template.dateBadge.helpers({ _deleteDate() { this.card.setReceived(null); } -}).register('editCardReceivedDatePopup'); - +}.register('editCardReceivedDatePopup')); // editCardStartDatePopup (class extends DatePicker { @@ -119,7 +129,10 @@ Template.dateBadge.helpers({ onRendered() { super.onRendered(); if (moment.isDate(this.card.getReceived())) { - this.$('.js-datepicker').datepicker('setStartDate', this.card.getReceived()); + this.$('.js-datepicker').datepicker( + 'setStartDate', + this.card.getReceived(), + ); } } @@ -130,7 +143,7 @@ Template.dateBadge.helpers({ _deleteDate() { this.card.setStart(null); } -}).register('editCardStartDatePopup'); +}.register('editCardStartDatePopup')); // editCardDueDatePopup (class extends DatePicker { @@ -153,7 +166,7 @@ Template.dateBadge.helpers({ _deleteDate() { this.card.setDue(null); } -}).register('editCardDueDatePopup'); +}.register('editCardDueDatePopup')); // editCardEndDatePopup (class extends DatePicker { @@ -176,8 +189,7 @@ Template.dateBadge.helpers({ _deleteDate() { this.card.setEnd(null); } -}).register('editCardEndDatePopup'); - +}.register('editCardEndDatePopup')); // Display received, start, due & end dates const CardDate = BlazeComponent.extendComponent({ @@ -224,17 +236,20 @@ class CardReceivedDate extends CardDate { const startAt = this.data().getStart(); const theDate = this.date.get(); // if dueAt, endAt and startAt exist & are > receivedAt, receivedAt doesn't need to be flagged - if (((startAt) && (theDate.isAfter(dueAt))) || - ((endAt) && (theDate.isAfter(endAt))) || - ((dueAt) && (theDate.isAfter(dueAt)))) + if ( + (startAt && theDate.isAfter(dueAt)) || + (endAt && theDate.isAfter(endAt)) || + (dueAt && theDate.isAfter(dueAt)) + ) classes += 'long-overdue'; - else - classes += 'current'; + else classes += 'current'; return classes; } showTitle() { - return `${TAPi18n.__('card-received-on')} ${this.date.get().format('LLLL')}`; + return `${TAPi18n.__('card-received-on')} ${this.date + .get() + .format('LLLL')}`; } events() { @@ -261,13 +276,10 @@ class CardStartDate extends CardDate { const theDate = this.date.get(); const now = this.now.get(); // if dueAt or endAt exist & are > startAt, startAt doesn't need to be flagged - if (((endAt) && (theDate.isAfter(endAt))) || - ((dueAt) && (theDate.isAfter(dueAt)))) + if ((endAt && theDate.isAfter(endAt)) || (dueAt && theDate.isAfter(dueAt))) classes += 'long-overdue'; - else if (theDate.isBefore(now, 'minute')) - classes += 'almost-due'; - else - classes += 'current'; + else if (theDate.isBefore(now, 'minute')) classes += 'almost-due'; + else classes += 'current'; return classes; } @@ -298,17 +310,12 @@ class CardDueDate extends CardDate { const theDate = this.date.get(); const now = this.now.get(); // if the due date is after the end date, green - done early - if ((endAt) && (theDate.isAfter(endAt))) - classes += 'current'; + if (endAt && theDate.isAfter(endAt)) classes += 'current'; // if there is an end date, don't need to flag the due date - else if (endAt) - classes += ''; - else if (now.diff(theDate, 'days') >= 2) - classes += 'long-overdue'; - else if (now.diff(theDate, 'minute') >= 0) - classes += 'due'; - else if (now.diff(theDate, 'days') >= -1) - classes += 'almost-due'; + else if (endAt) classes += ''; + else if (now.diff(theDate, 'days') >= 2) classes += 'long-overdue'; + else if (now.diff(theDate, 'minute') >= 0) classes += 'due'; + else if (now.diff(theDate, 'days') >= -1) classes += 'almost-due'; return classes; } @@ -337,12 +344,9 @@ class CardEndDate extends CardDate { let classes = 'end-date' + ' '; const dueAt = this.data().getDue(); const theDate = this.date.get(); - if (theDate.diff(dueAt, 'days') >= 2) - classes += 'long-overdue'; - else if (theDate.diff(dueAt, 'days') >= 0) - classes += 'due'; - else if (theDate.diff(dueAt, 'days') >= -2) - classes += 'almost-due'; + if (theDate.diff(dueAt, 'days') >= 2) classes += 'long-overdue'; + else if (theDate.diff(dueAt, 'days') >= 0) classes += 'due'; + else if (theDate.diff(dueAt, 'days') >= -2) classes += 'almost-due'; return classes; } @@ -362,22 +366,22 @@ CardEndDate.register('cardEndDate'); showDate() { return this.date.get().format('l'); } -}).register('minicardReceivedDate'); +}.register('minicardReceivedDate')); (class extends CardStartDate { showDate() { return this.date.get().format('l'); } -}).register('minicardStartDate'); +}.register('minicardStartDate')); (class extends CardDueDate { showDate() { return this.date.get().format('l'); } -}).register('minicardDueDate'); +}.register('minicardDueDate')); (class extends CardEndDate { showDate() { return this.date.get().format('l'); } -}).register('minicardEndDate'); +}.register('minicardEndDate')); diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 2d875ca2..781967ae 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -27,7 +27,7 @@ BlazeComponent.extendComponent({ onCreated() { this.currentBoard = Boards.findOne(Session.get('currentBoard')); this.isLoaded = new ReactiveVar(false); - const boardBody = this.parentComponent().parentComponent(); + const boardBody = this.parentComponent().parentComponent(); //in Miniview parent is Board, not BoardBody. if (boardBody !== null) { boardBody.showOverlay.set(true); @@ -48,7 +48,11 @@ BlazeComponent.extendComponent({ }, canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, scrollParentContainer() { @@ -80,18 +84,17 @@ BlazeComponent.extendComponent({ const cardContainerScrollTop = $cardContainer.scrollTop(); let topOffset = false; - if(cardViewStartTop !== 100){ + if (cardViewStartTop !== 100) { topOffset = cardViewStartTop - 100; } - if(topOffset !== false) { + if (topOffset !== false) { bodyBoardComponent.scrollTop(cardContainerScrollTop + topOffset); } - }, presentParentTask() { let result = this.currentBoard.presentParentTask; - if ((result === null) || (result === undefined)) { + if (result === null || result === undefined) { result = 'no-parent'; } return result; @@ -116,7 +119,13 @@ BlazeComponent.extendComponent({ onRendered() { if (!Utils.isMiniScreen()) { Meteor.setTimeout(() => { - $('.card-details').mCustomScrollbar({theme:'minimal-dark', setWidth: false, setLeft: 0, scrollbarPosition: 'outside', mouseWheel: true }); + $('.card-details').mCustomScrollbar({ + theme: 'minimal-dark', + setWidth: false, + setLeft: 0, + scrollbarPosition: 'outside', + mouseWheel: true, + }); this.scrollParentContainer(); }, 500); } @@ -212,7 +221,7 @@ BlazeComponent.extendComponent({ }, onDestroyed() { - const parentComponent = this.parentComponent().parentComponent(); + const parentComponent = this.parentComponent().parentComponent(); //on mobile view parent is Board, not board body. if (parentComponent === null) return; parentComponent.showOverlay.set(false); @@ -228,56 +237,64 @@ BlazeComponent.extendComponent({ }, }; - return [{ - ...events, - 'click .js-close-card-details' () { - Utils.goBoardId(this.data().boardId); - }, - 'click .js-open-card-details-menu': Popup.open('cardDetailsActions'), - 'submit .js-card-description' (evt) { - evt.preventDefault(); - const description = this.currentComponent().getValue(); - this.data().setDescription(description); - }, - 'submit .js-card-details-title' (evt) { - evt.preventDefault(); - const title = this.currentComponent().getValue().trim(); - if (title) { - this.data().setTitle(title); - } - }, - 'submit .js-card-details-assigner'(evt) { - evt.preventDefault(); - const assigner = this.currentComponent().getValue().trim(); - if (assigner) { - this.data().setAssignedBy(assigner); - } - }, - 'submit .js-card-details-requester'(evt) { - evt.preventDefault(); - const requester = this.currentComponent().getValue().trim(); - if (requester) { - this.data().setRequestedBy(requester); - } - }, - 'click .js-member': Popup.open('cardMember'), - 'click .js-add-members': Popup.open('cardMembers'), - 'click .js-add-labels': Popup.open('cardLabels'), - 'click .js-received-date': Popup.open('editCardReceivedDate'), - 'click .js-start-date': Popup.open('editCardStartDate'), - 'click .js-due-date': Popup.open('editCardDueDate'), - 'click .js-end-date': Popup.open('editCardEndDate'), - 'mouseenter .js-card-details' () { - const parentComponent = this.parentComponent().parentComponent(); - //on mobile view parent is Board, not BoardBody. - if (parentComponent === null) return; - parentComponent.showOverlay.set(true); - parentComponent.mouseHasEnterCardDetails = true; - }, - 'click #toggleButton'() { - Meteor.call('toggleSystemMessages'); + return [ + { + ...events, + 'click .js-close-card-details'() { + Utils.goBoardId(this.data().boardId); + }, + 'click .js-open-card-details-menu': Popup.open('cardDetailsActions'), + 'submit .js-card-description'(event) { + event.preventDefault(); + const description = this.currentComponent().getValue(); + this.data().setDescription(description); + }, + 'submit .js-card-details-title'(event) { + event.preventDefault(); + const title = this.currentComponent() + .getValue() + .trim(); + if (title) { + this.data().setTitle(title); + } + }, + 'submit .js-card-details-assigner'(event) { + event.preventDefault(); + const assigner = this.currentComponent() + .getValue() + .trim(); + if (assigner) { + this.data().setAssignedBy(assigner); + } + }, + 'submit .js-card-details-requester'(event) { + event.preventDefault(); + const requester = this.currentComponent() + .getValue() + .trim(); + if (requester) { + this.data().setRequestedBy(requester); + } + }, + 'click .js-member': Popup.open('cardMember'), + 'click .js-add-members': Popup.open('cardMembers'), + 'click .js-add-labels': Popup.open('cardLabels'), + 'click .js-received-date': Popup.open('editCardReceivedDate'), + 'click .js-start-date': Popup.open('editCardStartDate'), + 'click .js-due-date': Popup.open('editCardDueDate'), + 'click .js-end-date': Popup.open('editCardEndDate'), + 'mouseenter .js-card-details'() { + const parentComponent = this.parentComponent().parentComponent(); + //on mobile view parent is Board, not BoardBody. + if (parentComponent === null) return; + parentComponent.showOverlay.set(true); + parentComponent.mouseHasEnterCardDetails = true; + }, + 'click #toggleButton'() { + Meteor.call('toggleSystemMessages'); + }, }, - }]; + ]; }, }).register('cardDetails'); @@ -297,7 +314,9 @@ BlazeComponent.extendComponent({ close(isReset = false) { if (this.isOpen.get() && !isReset) { const draft = this.getValue().trim(); - if (draft !== Cards.findOne(Session.get('currentCard')).getDescription()) { + if ( + draft !== Cards.findOne(Session.get('currentCard')).getDescription() + ) { UnsavedEdits.set(this._getUnsavedEditKey(), this.getValue()); } } @@ -311,12 +330,14 @@ BlazeComponent.extendComponent({ events() { const parentEvents = InlinedForm.prototype.events()[0]; - return [{ - ...parentEvents, - 'click .js-close-inlined-form': this.reset, - }]; + return [ + { + ...parentEvents, + 'click .js-close-inlined-form': this.reset, + }, + ]; } -}).register('inlinedCardDescription'); +}.register('inlinedCardDescription')); Template.cardDetailsActionsPopup.helpers({ isWatching() { @@ -324,7 +345,11 @@ Template.cardDetailsActionsPopup.helpers({ }, canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }); @@ -342,23 +367,31 @@ Template.cardDetailsActionsPopup.events({ 'click .js-copy-card': Popup.open('copyCard'), 'click .js-copy-checklist-cards': Popup.open('copyChecklistToManyCards'), 'click .js-set-card-color': Popup.open('setCardColor'), - 'click .js-move-card-to-top' (evt) { - evt.preventDefault(); - const minOrder = _.min(this.list().cards(this.swimlaneId).map((c) => c.sort)); + 'click .js-move-card-to-top'(event) { + event.preventDefault(); + const minOrder = _.min( + this.list() + .cards(this.swimlaneId) + .map(c => c.sort), + ); this.move(this.boardId, this.swimlaneId, this.listId, minOrder - 1); }, - 'click .js-move-card-to-bottom' (evt) { - evt.preventDefault(); - const maxOrder = _.max(this.list().cards(this.swimlaneId).map((c) => c.sort)); + 'click .js-move-card-to-bottom'(event) { + event.preventDefault(); + const maxOrder = _.max( + this.list() + .cards(this.swimlaneId) + .map(c => c.sort), + ); this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1); }, - 'click .js-archive' (evt) { - evt.preventDefault(); + 'click .js-archive'(event) { + event.preventDefault(); this.archive(); Popup.close(); }, 'click .js-more': Popup.open('cardMore'), - 'click .js-toggle-watch-card' () { + '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) => { @@ -367,15 +400,15 @@ Template.cardDetailsActionsPopup.events({ }, }); -Template.editCardTitleForm.onRendered(function () { +Template.editCardTitleForm.onRendered(function() { autosize(this.$('.js-edit-card-title')); }); Template.editCardTitleForm.events({ - 'keydown .js-edit-card-title' (evt) { + 'keydown .js-edit-card-title'(event) { // If enter key was pressed, submit the data // Unless the shift key is also being pressed - if (evt.keyCode === 13 && !evt.shiftKey) { + if (event.keyCode === 13 && !event.shiftKey) { $('.js-submit-edit-card-title-form').click(); } }, @@ -386,9 +419,9 @@ Template.editCardRequesterForm.onRendered(function() { }); Template.editCardRequesterForm.events({ - 'keydown .js-edit-card-requester'(evt) { + 'keydown .js-edit-card-requester'(event) { // If enter key was pressed, submit the data - if (evt.keyCode === 13) { + if (event.keyCode === 13) { $('.js-submit-edit-card-requester-form').click(); } }, @@ -399,16 +432,16 @@ Template.editCardAssignerForm.onRendered(function() { }); Template.editCardAssignerForm.events({ - 'keydown .js-edit-card-assigner'(evt) { + 'keydown .js-edit-card-assigner'(event) { // If enter key was pressed, submit the data - if (evt.keyCode === 13) { + if (event.keyCode === 13) { $('.js-submit-edit-card-assigner-form').click(); } }, }); Template.moveCardPopup.events({ - 'click .js-done' () { + 'click .js-done'() { // XXX We should *not* get the currentCard from the global state, but // instead from a “component” state. const card = Cards.findOne(Session.get('currentCard')); @@ -429,13 +462,16 @@ BlazeComponent.extendComponent({ }, boards() { - const boards = Boards.find({ - archived: false, - 'members.userId': Meteor.userId(), - _id: {$ne: Meteor.user().getTemplatesBoardId()}, - }, { - sort: ['title'], - }); + const boards = Boards.find( + { + archived: false, + 'members.userId': Meteor.userId(), + _id: { $ne: Meteor.user().getTemplatesBoardId() }, + }, + { + sort: ['title'], + }, + ); return boards; }, @@ -450,12 +486,14 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'change .js-select-boards'(evt) { - this.selectedBoardId.set($(evt.currentTarget).val()); - subManager.subscribe('board', this.selectedBoardId.get(), false); + return [ + { + 'change .js-select-boards'(event) { + this.selectedBoardId.set($(event.currentTarget).val()); + subManager.subscribe('board', this.selectedBoardId.get(), false); + }, }, - }]; + ]; }, }).register('boardsAndLists'); @@ -471,7 +509,9 @@ Template.copyCardPopup.events({ const textarea = $('#copy-card-title'); const title = textarea.val().trim(); // insert new card to the bottom of new list - card.sort = Lists.findOne(card.listId).cards().count(); + card.sort = Lists.findOne(card.listId) + .cards() + .count(); if (title) { card.title = title; @@ -489,7 +529,7 @@ Template.copyCardPopup.events({ }); Template.copyChecklistToManyCardsPopup.events({ - 'click .js-done' () { + 'click .js-done'() { const card = Cards.findOne(Session.get('currentCard')); const oldId = card._id; card._id = null; @@ -502,11 +542,13 @@ Template.copyChecklistToManyCardsPopup.events({ const textarea = $('#copy-card-title'); const titleEntry = textarea.val().trim(); // insert new card to the bottom of new list - card.sort = Lists.findOne(card.listId).cards().count(); + card.sort = Lists.findOne(card.listId) + .cards() + .count(); if (titleEntry) { const titleList = JSON.parse(titleEntry); - for (let i = 0; i < titleList.length; i++){ + for (let i = 0; i < titleList.length; i++) { const obj = titleList[i]; card.title = obj.title; card.description = obj.description; @@ -519,12 +561,12 @@ Template.copyChecklistToManyCardsPopup.events({ Filter.addException(_id); // copy checklists - Checklists.find({cardId: oldId}).forEach((ch) => { + Checklists.find({ cardId: oldId }).forEach(ch => { ch.copy(_id); }); // copy subtasks - cursor = Cards.find({parentId: oldId}); + cursor = Cards.find({ parentId: oldId }); cursor.forEach(function() { 'use strict'; const subtask = arguments[0]; @@ -534,7 +576,7 @@ Template.copyChecklistToManyCardsPopup.events({ }); // copy card comments - CardComments.find({cardId: oldId}).forEach((cmt) => { + CardComments.find({ cardId: oldId }).forEach(cmt => { cmt.copy(_id); }); } @@ -550,7 +592,7 @@ BlazeComponent.extendComponent({ }, colors() { - return cardColors.map((color) => ({ color, name: '' })); + return cardColors.map(color => ({ color, name: '' })); }, isSelected(color) { @@ -561,19 +603,21 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-palette-color'() { - this.currentColor.set(this.currentData().color); - }, - 'click .js-submit' () { - this.currentCard.setColor(this.currentColor.get()); - Popup.close(); + return [ + { + 'click .js-palette-color'() { + this.currentColor.set(this.currentData().color); + }, + 'click .js-submit'() { + this.currentCard.setColor(this.currentColor.get()); + Popup.close(); + }, + 'click .js-remove-color'() { + this.currentCard.setColor(null); + Popup.close(); + }, }, - 'click .js-remove-color'() { - this.currentCard.setColor(null); - Popup.close(); - }, - }]; + ]; }, }).register('setCardColorPopup'); @@ -592,15 +636,18 @@ BlazeComponent.extendComponent({ }, boards() { - const boards = Boards.find({ - archived: false, - 'members.userId': Meteor.userId(), - _id: { - $ne: Meteor.user().getTemplatesBoardId(), + const boards = Boards.find( + { + archived: false, + 'members.userId': Meteor.userId(), + _id: { + $ne: Meteor.user().getTemplatesBoardId(), + }, }, - }, { - sort: ['title'], - }); + { + sort: ['title'], + }, + ); return boards; }, @@ -609,7 +656,7 @@ BlazeComponent.extendComponent({ if (this.parentBoard.get()) { return Cards.find({ boardId: this.parentBoard.get(), - _id: {$ne: currentId}, + _id: { $ne: currentId }, }); } else { return []; @@ -642,63 +689,69 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-copy-card-link-to-clipboard' () { - // Clipboard code from: - // https://stackoverflow.com/questions/6300213/copy-selected-text-to-the-clipboard-without-using-flash-must-be-cross-browser - const StringToCopyElement = document.getElementById('cardURL'); - StringToCopyElement.select(); - if (document.execCommand('copy')) { - StringToCopyElement.blur(); - } else { - document.getElementById('cardURL').selectionStart = 0; - document.getElementById('cardURL').selectionEnd = 999; - document.execCommand('copy'); - if (window.getSelection) { - if (window.getSelection().empty) { // Chrome - window.getSelection().empty(); - } else if (window.getSelection().removeAllRanges) { // Firefox - window.getSelection().removeAllRanges(); + return [ + { + 'click .js-copy-card-link-to-clipboard'() { + // Clipboard code from: + // https://stackoverflow.com/questions/6300213/copy-selected-text-to-the-clipboard-without-using-flash-must-be-cross-browser + const StringToCopyElement = document.getElementById('cardURL'); + StringToCopyElement.select(); + if (document.execCommand('copy')) { + StringToCopyElement.blur(); + } else { + document.getElementById('cardURL').selectionStart = 0; + document.getElementById('cardURL').selectionEnd = 999; + document.execCommand('copy'); + if (window.getSelection) { + if (window.getSelection().empty) { + // Chrome + window.getSelection().empty(); + } else if (window.getSelection().removeAllRanges) { + // Firefox + window.getSelection().removeAllRanges(); + } + } else if (document.selection) { + // IE? + document.selection.empty(); } - } else if (document.selection) { // IE? - document.selection.empty(); } - } - }, - 'click .js-delete': Popup.afterConfirm('cardDelete', function () { - Popup.close(); - Cards.remove(this._id); - Utils.goBoardId(this.boardId); - }), - 'change .js-field-parent-board'(evt) { - const selection = $(evt.currentTarget).val(); - const list = $('.js-field-parent-card'); - if (selection === 'none') { - this.parentBoard.set(null); - } else { - subManager.subscribe('board', $(evt.currentTarget).val(), false); - this.parentBoard.set(selection); - list.prop('disabled', false); - } - this.setParentCardId(null); - }, - 'change .js-field-parent-card'(evt) { - const selection = $(evt.currentTarget).val(); - this.setParentCardId(selection); + }, + 'click .js-delete': Popup.afterConfirm('cardDelete', function() { + Popup.close(); + Cards.remove(this._id); + Utils.goBoardId(this.boardId); + }), + 'change .js-field-parent-board'(event) { + const selection = $(event.currentTarget).val(); + const list = $('.js-field-parent-card'); + if (selection === 'none') { + this.parentBoard.set(null); + } else { + subManager.subscribe('board', $(event.currentTarget).val(), false); + this.parentBoard.set(selection); + list.prop('disabled', false); + } + this.setParentCardId(null); + }, + 'change .js-field-parent-card'(event) { + const selection = $(event.currentTarget).val(); + this.setParentCardId(selection); + }, }, - }]; + ]; }, }).register('cardMorePopup'); - // Close the card details pane by pressing escape -EscapeActions.register('detailsPane', +EscapeActions.register( + 'detailsPane', () => { Utils.goBoardId(Session.get('currentBoard')); }, () => { return !Session.equals('currentCard', null); - }, { + }, + { noClickEscapeOn: '.js-card-details,.board-sidebar,#header', - } + }, ); diff --git a/client/components/cards/cardTime.js b/client/components/cards/cardTime.js index 80b7fc84..d8a41aaa 100644 --- a/client/components/cards/cardTime.js +++ b/client/components/cards/cardTime.js @@ -20,29 +20,31 @@ BlazeComponent.extendComponent({ this.card.setSpentTime(null); }, events() { - return [{ - //TODO : need checking this portion - 'submit .edit-time'(evt) { - evt.preventDefault(); + return [ + { + //TODO : need checking this portion + 'submit .edit-time'(evt) { + evt.preventDefault(); - const spentTime = parseFloat(evt.target.time.value); - const isOvertime = this.card.getIsOvertime(); + const spentTime = parseFloat(evt.target.time.value); + const isOvertime = this.card.getIsOvertime(); - if (spentTime >= 0) { - this.storeTime(spentTime, isOvertime); + if (spentTime >= 0) { + this.storeTime(spentTime, isOvertime); + Popup.close(); + } else { + this.error.set('invalid-time'); + evt.target.time.focus(); + } + }, + 'click .js-delete-time'(evt) { + evt.preventDefault(); + this.deleteTime(); Popup.close(); - } else { - this.error.set('invalid-time'); - evt.target.time.focus(); - } + }, + 'click a.js-toggle-overtime': this.toggleOvertime, }, - 'click .js-delete-time'(evt) { - evt.preventDefault(); - this.deleteTime(); - Popup.close(); - }, - 'click a.js-toggle-overtime': this.toggleOvertime, - }]; + ]; }, }).register('editCardSpentTimePopup'); @@ -56,23 +58,33 @@ BlazeComponent.extendComponent({ }, showTitle() { if (this.data().getIsOvertime()) { - return `${TAPi18n.__('overtime')} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`; + return `${TAPi18n.__( + 'overtime', + )} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`; } else { - return `${TAPi18n.__('card-spent')} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`; + return `${TAPi18n.__( + 'card-spent', + )} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`; } }, showTime() { return this.data().getSpentTime(); }, events() { - return [{ - 'click .js-edit-time': Popup.open('editCardSpentTime'), - }]; + return [ + { + 'click .js-edit-time': Popup.open('editCardSpentTime'), + }, + ]; }, }).register('cardSpentTime'); Template.timeBadge.helpers({ canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }); diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js index 5d789351..57939eb8 100644 --- a/client/components/cards/checklists.js +++ b/client/components/cards/checklists.js @@ -64,20 +64,22 @@ BlazeComponent.extendComponent({ }, canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }).register('checklistDetail'); BlazeComponent.extendComponent({ - addChecklist(event) { event.preventDefault(); const textarea = this.find('textarea.js-add-checklist-item'); const title = textarea.value.trim(); let cardId = this.currentData().cardId; const card = Cards.findOne(cardId); - if (card.isLinked()) - cardId = card.linkedId; + if (card.isLinked()) cardId = card.linkedId; if (title) { Checklists.insert({ @@ -86,7 +88,9 @@ BlazeComponent.extendComponent({ sort: card.checklists().count(), }); setTimeout(() => { - this.$('.add-checklist-item').last().click(); + this.$('.add-checklist-item') + .last() + .click(); }, 100); } textarea.value = ''; @@ -113,7 +117,11 @@ BlazeComponent.extendComponent({ }, canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, deleteChecklist() { @@ -167,37 +175,43 @@ BlazeComponent.extendComponent({ events() { const events = { 'click .toggle-delete-checklist-dialog'(event) { - if($(event.target).hasClass('js-delete-checklist')){ + if ($(event.target).hasClass('js-delete-checklist')) { this.checklistToDelete = this.currentData().checklist; //Store data context } this.toggleDeleteDialog.set(!this.toggleDeleteDialog.get()); }, }; - return [{ - ...events, - 'submit .js-add-checklist': this.addChecklist, - 'submit .js-edit-checklist-title': this.editChecklist, - 'submit .js-add-checklist-item': this.addChecklistItem, - 'submit .js-edit-checklist-item': this.editChecklistItem, - 'click .js-delete-checklist-item': this.deleteItem, - 'click .confirm-checklist-delete': this.deleteChecklist, - keydown: this.pressKey, - }]; + return [ + { + ...events, + 'submit .js-add-checklist': this.addChecklist, + 'submit .js-edit-checklist-title': this.editChecklist, + 'submit .js-add-checklist-item': this.addChecklistItem, + 'submit .js-edit-checklist-item': this.editChecklistItem, + 'click .js-delete-checklist-item': this.deleteItem, + 'click .confirm-checklist-delete': this.deleteChecklist, + keydown: this.pressKey, + }, + ]; }, }).register('checklists'); Template.checklistDeleteDialog.onCreated(() => { const $cardDetails = this.$('.card-details'); - this.scrollState = { position: $cardDetails.scrollTop(), //save current scroll position + this.scrollState = { + position: $cardDetails.scrollTop(), //save current scroll position top: false, //required for smooth scroll animation }; //Callback's purpose is to only prevent scrolling after animation is complete - $cardDetails.animate({ scrollTop: 0 }, 500, () => { this.scrollState.top = true; }); + $cardDetails.animate({ scrollTop: 0 }, 500, () => { + this.scrollState.top = true; + }); //Prevent scrolling while dialog is open $cardDetails.on('scroll', () => { - if(this.scrollState.top) { //If it's already in position, keep it there. Otherwise let animation scroll + if (this.scrollState.top) { + //If it's already in position, keep it there. Otherwise let animation scroll $cardDetails.scrollTop(0); } }); @@ -206,12 +220,16 @@ Template.checklistDeleteDialog.onCreated(() => { Template.checklistDeleteDialog.onDestroyed(() => { const $cardDetails = this.$('.card-details'); $cardDetails.off('scroll'); //Reactivate scrolling - $cardDetails.animate( { scrollTop: this.scrollState.position }); + $cardDetails.animate({ scrollTop: this.scrollState.position }); }); Template.checklistItemDetail.helpers({ canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }); @@ -224,8 +242,10 @@ BlazeComponent.extendComponent({ } }, events() { - return [{ - 'click .js-checklist-item .check-box': this.toggleItem, - }]; + return [ + { + 'click .js-checklist-item .check-box': this.toggleItem, + }, + ]; }, }).register('checklistItemDetail'); diff --git a/client/components/cards/labels.js b/client/components/cards/labels.js index cdd5a700..1e156f54 100644 --- a/client/components/cards/labels.js +++ b/client/components/cards/labels.js @@ -9,7 +9,7 @@ BlazeComponent.extendComponent({ }, labels() { - return labelColors.map((color) => ({ color, name: '' })); + return labelColors.map(color => ({ color, name: '' })); }, isSelected(color) { @@ -17,11 +17,13 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-palette-color'() { - this.currentColor.set(this.currentData().color); + return [ + { + 'click .js-palette-color'() { + this.currentColor.set(this.currentData().color); + }, }, - }]; + ]; }, }).register('formLabel'); @@ -38,19 +40,19 @@ Template.createLabelPopup.helpers({ }); Template.cardLabelsPopup.events({ - 'click .js-select-label'(evt) { + 'click .js-select-label'(event) { const card = Cards.findOne(Session.get('currentCard')); const labelId = this._id; card.toggleLabel(labelId); - evt.preventDefault(); + event.preventDefault(); }, 'click .js-edit-label': Popup.open('editLabel'), 'click .js-add-label': Popup.open('createLabel'), }); Template.formLabel.events({ - 'click .js-palette-color'(evt) { - const $this = $(evt.currentTarget); + 'click .js-palette-color'(event) { + const $this = $(event.currentTarget); // hide selected ll colors $('.js-palette-select').addClass('hide'); @@ -62,11 +64,14 @@ Template.formLabel.events({ Template.createLabelPopup.events({ // Create the new label - 'submit .create-label'(evt, tpl) { - evt.preventDefault(); + 'submit .create-label'(event, templateInstance) { + event.preventDefault(); const board = Boards.findOne(Session.get('currentBoard')); - const name = tpl.$('#labelName').val().trim(); - const color = Blaze.getData(tpl.find('.fa-check')).color; + const name = templateInstance + .$('#labelName') + .val() + .trim(); + const color = Blaze.getData(templateInstance.find('.fa-check')).color; board.addLabel(name, color); Popup.back(); }, @@ -78,11 +83,14 @@ Template.editLabelPopup.events({ board.removeLabel(this._id); Popup.back(2); }), - 'submit .edit-label'(evt, tpl) { - evt.preventDefault(); + 'submit .edit-label'(event, templateInstance) { + event.preventDefault(); const board = Boards.findOne(Session.get('currentBoard')); - const name = tpl.$('#labelName').val().trim(); - const color = Blaze.getData(tpl.find('.fa-check')).color; + const name = templateInstance + .$('#labelName') + .val() + .trim(); + const color = Blaze.getData(templateInstance.find('.fa-check')).color; board.editLabel(this._id, name, color); Popup.back(); }, diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index da7f9e01..0718c629 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -8,13 +8,14 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-linked-link' () { - if (this.data().isLinkedCard()) - Utils.goCardId(this.data().linkedId); - else if (this.data().isLinkedBoard()) - Utils.goBoardId(this.data().linkedId); + return [ + { + 'click .js-linked-link'() { + if (this.data().isLinkedCard()) Utils.goCardId(this.data().linkedId); + else if (this.data().isLinkedBoard()) + Utils.goBoardId(this.data().linkedId); + }, }, - }]; + ]; }, }).register('minicard'); diff --git a/client/components/cards/subtasks.js b/client/components/cards/subtasks.js index 1651d449..fab860bb 100644 --- a/client/components/cards/subtasks.js +++ b/client/components/cards/subtasks.js @@ -1,11 +1,14 @@ BlazeComponent.extendComponent({ canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }).register('subtaskDetail'); BlazeComponent.extendComponent({ - addSubtask(event) { event.preventDefault(); const textarea = this.find('textarea.js-add-subtask-item'); @@ -38,9 +41,10 @@ BlazeComponent.extendComponent({ // See https://github.com/wekan/wekan/issues/80 Filter.addException(_id); - setTimeout(() => { - this.$('.add-subtask-item').last().click(); + this.$('.add-subtask-item') + .last() + .click(); }, 100); } textarea.value = ''; @@ -48,7 +52,11 @@ BlazeComponent.extendComponent({ }, canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, deleteSubtask() { @@ -85,13 +93,13 @@ BlazeComponent.extendComponent({ events() { const events = { 'click .toggle-delete-subtask-dialog'(event) { - if($(event.target).hasClass('js-delete-subtask')){ + if ($(event.target).hasClass('js-delete-subtask')) { this.subtaskToDelete = this.currentData().subtask; //Store data context } this.toggleDeleteDialog.set(!this.toggleDeleteDialog.get()); }, 'click .js-view-subtask'(event) { - if($(event.target).hasClass('js-view-subtask')){ + if ($(event.target).hasClass('js-view-subtask')) { const subtask = this.currentData().subtask; const board = subtask.board(); FlowRouter.go('card', { @@ -103,27 +111,33 @@ BlazeComponent.extendComponent({ }, }; - return [{ - ...events, - 'submit .js-add-subtask': this.addSubtask, - 'submit .js-edit-subtask-title': this.editSubtask, - 'click .confirm-subtask-delete': this.deleteSubtask, - keydown: this.pressKey, - }]; + return [ + { + ...events, + 'submit .js-add-subtask': this.addSubtask, + 'submit .js-edit-subtask-title': this.editSubtask, + 'click .confirm-subtask-delete': this.deleteSubtask, + keydown: this.pressKey, + }, + ]; }, }).register('subtasks'); Template.subtaskDeleteDialog.onCreated(() => { const $cardDetails = this.$('.card-details'); - this.scrollState = { position: $cardDetails.scrollTop(), //save current scroll position + this.scrollState = { + position: $cardDetails.scrollTop(), //save current scroll position top: false, //required for smooth scroll animation }; //Callback's purpose is to only prevent scrolling after animation is complete - $cardDetails.animate({ scrollTop: 0 }, 500, () => { this.scrollState.top = true; }); + $cardDetails.animate({ scrollTop: 0 }, 500, () => { + this.scrollState.top = true; + }); //Prevent scrolling while dialog is open $cardDetails.on('scroll', () => { - if(this.scrollState.top) { //If it's already in position, keep it there. Otherwise let animation scroll + if (this.scrollState.top) { + //If it's already in position, keep it there. Otherwise let animation scroll $cardDetails.scrollTop(0); } }); @@ -132,12 +146,16 @@ Template.subtaskDeleteDialog.onCreated(() => { Template.subtaskDeleteDialog.onDestroyed(() => { const $cardDetails = this.$('.card-details'); $cardDetails.off('scroll'); //Reactivate scrolling - $cardDetails.animate( { scrollTop: this.scrollState.position }); + $cardDetails.animate({ scrollTop: this.scrollState.position }); }); Template.subtaskItemDetail.helpers({ canModifyCard() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }); diff --git a/client/components/import/import.js b/client/components/import/import.js index 64170c1d..62c7e525 100644 --- a/client/components/import/import.js +++ b/client/components/import/import.js @@ -56,7 +56,7 @@ BlazeComponent.extendComponent({ const membersMapping = this.membersToMap.get(); if (membersMapping) { const mappingById = {}; - membersMapping.forEach((member) => { + membersMapping.forEach(member => { if (member.wekanId) { mappingById[member.id] = member.wekanId; } @@ -64,7 +64,8 @@ BlazeComponent.extendComponent({ additionalData.membersMapping = mappingById; } this.membersToMap.set([]); - Meteor.call('importBoard', + Meteor.call( + 'importBoard', this.importedData.get(), additionalData, this.importSource, @@ -76,7 +77,7 @@ BlazeComponent.extendComponent({ Session.set('fromBoard', null); Utils.goBoardId(res); } - } + }, ); }, @@ -84,12 +85,12 @@ BlazeComponent.extendComponent({ const importSource = Session.get('importSource'); let membersToMap; switch (importSource) { - case 'trello': - membersToMap = trelloMembersMapper.getMembersToMap(dataObject); - break; - case 'wekan': - membersToMap = wekanMembersMapper.getMembersToMap(dataObject); - break; + case 'trello': + membersToMap = trelloMembersMapper.getMembersToMap(dataObject); + break; + case 'wekan': + membersToMap = wekanMembersMapper.getMembersToMap(dataObject); + break; } return membersToMap; }, @@ -109,22 +110,26 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - submit(evt) { - return this.parentComponent().importData(evt); + return [ + { + submit(evt) { + return this.parentComponent().importData(evt); + }, }, - }]; + ]; }, }).register('importTextarea'); BlazeComponent.extendComponent({ onCreated() { this.autorun(() => { - this.parentComponent().membersToMap.get().forEach(({ wekanId }) => { - if (wekanId) { - this.subscribe('user-miniprofile', wekanId); - } - }); + this.parentComponent() + .membersToMap.get() + .forEach(({ wekanId }) => { + if (wekanId) { + this.subscribe('user-miniprofile', wekanId); + } + }); }); }, @@ -149,23 +154,23 @@ BlazeComponent.extendComponent({ _setPropertyForMember(property, value, memberId, unset = false) { const listOfMembers = this.members(); let finder = null; - if(memberId) { - finder = (member) => member.id === memberId; + if (memberId) { + finder = member => member.id === memberId; } else { - finder = (member) => member.selected; + finder = member => member.selected; } - listOfMembers.forEach((member) => { - if(finder(member)) { - if(value !== null) { + listOfMembers.forEach(member => { + if (finder(member)) { + if (value !== null) { member[property] = value; } else { delete member[property]; } - if(!unset) { + if (!unset) { // we shortcut if we don't care about unsetting the others return false; } - } else if(unset) { + } else if (unset) { delete member[property]; } return true; @@ -186,9 +191,9 @@ BlazeComponent.extendComponent({ const allMembers = this.members(); let finder = null; if (memberId) { - finder = (user) => user.id === memberId; + finder = user => user.id === memberId; } else { - finder = (user) => user.selected; + finder = user => user.selected; } return allMembers.find(finder); }, @@ -197,7 +202,7 @@ BlazeComponent.extendComponent({ return this._setPropertyForMember('wekanId', wekanId, null); }, - unmapMember(memberId){ + unmapMember(memberId) { return this._setPropertyForMember('wekanId', null, memberId); }, @@ -208,7 +213,7 @@ BlazeComponent.extendComponent({ onMapMember(evt) { const memberToMap = this.currentData(); - if(memberToMap.wekan) { + if (memberToMap.wekan) { // todo xxx ask for confirmation? this.unmapMember(memberToMap.id); } else { @@ -218,10 +223,12 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'submit': this.onSubmit, - 'click .js-select-member': this.onMapMember, - }]; + return [ + { + submit: this.onSubmit, + 'click .js-select-member': this.onMapMember, + }, + ]; }, }).register('importMapMembers'); @@ -230,14 +237,16 @@ BlazeComponent.extendComponent({ this.find('.js-map-member input').focus(); }, - onSelectUser(){ + onSelectUser() { Popup.getOpenerComponent().mapSelectedMember(this.currentData()._id); Popup.back(); }, events() { - return [{ - 'click .js-select-import': this.onSelectUser, - }]; + return [ + { + 'click .js-select-import': this.onSelectUser, + }, + ]; }, }).register('importMapMembersAddPopup'); diff --git a/client/components/import/trelloMembersMapper.js b/client/components/import/trelloMembersMapper.js index 0f353bf1..b5d59d93 100644 --- a/client/components/import/trelloMembersMapper.js +++ b/client/components/import/trelloMembersMapper.js @@ -4,7 +4,7 @@ export function getMembersToMap(data) { // imported member const membersToMap = data.members; // auto-map based on username - membersToMap.forEach((importedMember) => { + membersToMap.forEach(importedMember => { const wekanUser = Users.findOne({ username: importedMember.username }); if (wekanUser) { importedMember.wekanId = wekanUser._id; diff --git a/client/components/import/wekanMembersMapper.js b/client/components/import/wekanMembersMapper.js index f4c110f7..8db3aacd 100644 --- a/client/components/import/wekanMembersMapper.js +++ b/client/components/import/wekanMembersMapper.js @@ -5,10 +5,10 @@ export function getMembersToMap(data) { const membersToMap = data.members; const users = data.users; // auto-map based on username - membersToMap.forEach((importedMember) => { + membersToMap.forEach(importedMember => { importedMember.id = importedMember.userId; delete importedMember.userId; - const user = users.filter((user) => { + const user = users.filter(user => { return user._id === importedMember.id; })[0]; if (user.profile && user.profile.fullname) { diff --git a/client/components/lists/list.js b/client/components/lists/list.js index ea0068eb..c2b39be9 100644 --- a/client/components/lists/list.js +++ b/client/components/lists/list.js @@ -21,14 +21,18 @@ BlazeComponent.extendComponent({ const boardComponent = this.parentComponent().parentComponent(); function userIsMember() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); } const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)'; const $cards = this.$('.js-minicards'); - if(window.matchMedia('(max-width: 1199px)').matches) { - $( '.js-minicards' ).sortable({ + if (window.matchMedia('(max-width: 1199px)').matches) { + $('.js-minicards').sortable({ handle: '.handle', }); } @@ -42,10 +46,16 @@ BlazeComponent.extendComponent({ if (MultiSelection.isActive()) { const andNOthers = $cards.find('.js-minicard.is-checked').length - 1; if (andNOthers > 0) { - helper.append($(Blaze.toHTML(HTML.DIV( - { 'class': 'and-n-other' }, - TAPi18n.__('and-n-other-card', { count: andNOthers }) - )))); + helper.append( + $( + Blaze.toHTML( + HTML.DIV( + { class: 'and-n-other' }, + TAPi18n.__('and-n-other-card', { count: andNOthers }), + ), + ), + ), + ); } } return helper; @@ -70,9 +80,16 @@ BlazeComponent.extendComponent({ const currentBoard = Boards.findOne(Session.get('currentBoard')); let swimlaneId = ''; const boardView = (Meteor.user().profile || {}).boardView; - if (boardView === 'board-view-swimlanes' || currentBoard.isTemplatesBoard()) + if ( + boardView === 'board-view-swimlanes' || + currentBoard.isTemplatesBoard() + ) swimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0))._id; - else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal') || !boardView) + else if ( + boardView === 'board-view-lists' || + boardView === 'board-view-cal' || + !boardView + ) swimlaneId = currentBoard.getDefaultSwimline()._id; // Normally the jquery-ui sortable library moves the dragged DOM element @@ -86,7 +103,12 @@ BlazeComponent.extendComponent({ if (MultiSelection.isActive()) { Cards.find(MultiSelection.getMongoSelector()).forEach((card, i) => { - card.move(currentBoard._id, swimlaneId, listId, sortIndex.base + i * sortIndex.increment); + card.move( + currentBoard._id, + swimlaneId, + listId, + sortIndex.base + i * sortIndex.increment, + ); }); } else { const cardDomElement = ui.item.get(0); diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index bce350dd..7d9e358b 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -16,7 +16,7 @@ BlazeComponent.extendComponent({ options.position = options.position || 'top'; const forms = this.childComponents('inlinedForm'); - let form = forms.find((component) => { + let form = forms.find(component => { return component.data().position === options.position; }); if (!form && forms.length > 0) { @@ -52,11 +52,12 @@ BlazeComponent.extendComponent({ let cardType = 'cardType-card'; if (title) { if (board.isTemplatesBoard()) { - swimlaneId = this.parentComponent().parentComponent().data()._id; // Always swimlanes view + swimlaneId = this.parentComponent() + .parentComponent() + .data()._id; // Always swimlanes view const swimlane = Swimlanes.findOne(swimlaneId); // If this is the card templates swimlane, insert a card template - if (swimlane.isCardTemplatesSwimlane()) - cardType = 'template-card'; + if (swimlane.isCardTemplatesSwimlane()) cardType = 'template-card'; // If this is the board templates swimlane, insert a board template and a linked card else if (swimlane.isBoardTemplatesSwimlane()) { linkedId = Boards.insert({ @@ -71,8 +72,14 @@ BlazeComponent.extendComponent({ cardType = 'cardType-linkedBoard'; } } else if (boardView === 'board-view-swimlanes') - swimlaneId = this.parentComponent().parentComponent().data()._id; - else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal') || !boardView) + swimlaneId = this.parentComponent() + .parentComponent() + .data()._id; + else if ( + boardView === 'board-view-lists' || + boardView === 'board-view-cal' || + !boardView + ) swimlaneId = board.getDefaultSwimline()._id; const _id = Cards.insert({ @@ -91,7 +98,9 @@ BlazeComponent.extendComponent({ // if the displayed card count is less than the total cards in the list, // we need to increment the displayed card count to prevent the spinner // to appear - const cardCount = this.data().cards(this.idOrNull(swimlaneId)).count(); + const cardCount = this.data() + .cards(this.idOrNull(swimlaneId)) + .count(); if (this.cardlimit.get() < cardCount) { this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter); } @@ -149,8 +158,12 @@ BlazeComponent.extendComponent({ idOrNull(swimlaneId) { const currentUser = Meteor.user(); - if ((currentUser.profile || {}).boardView === 'board-view-swimlanes' || - this.data().board().isTemplatesBoard()) + if ( + (currentUser.profile || {}).boardView === 'board-view-swimlanes' || + this.data() + .board() + .isTemplatesBoard() + ) return swimlaneId; return undefined; }, @@ -161,8 +174,7 @@ BlazeComponent.extendComponent({ listId: this.currentData()._id, archived: false, }; - if (swimlaneId) - selector.swimlaneId = swimlaneId; + if (swimlaneId) selector.swimlaneId = swimlaneId; return Cards.find(Filter.mongoSelector(selector), { sort: ['sort'], limit, @@ -175,21 +187,32 @@ BlazeComponent.extendComponent({ }, canSeeAddCard() { - return !this.reachedWipLimit() && Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + !this.reachedWipLimit() && + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, reachedWipLimit() { const list = Template.currentData(); - return !list.getWipLimit('soft') && list.getWipLimit('enabled') && list.getWipLimit('value') <= list.cards().count(); + return ( + !list.getWipLimit('soft') && + list.getWipLimit('enabled') && + list.getWipLimit('value') <= list.cards().count() + ); }, events() { - return [{ - 'click .js-minicard': this.clickOnMiniCard, - 'click .js-toggle-multi-selection': this.toggleMultiSelection, - 'click .open-minicard-composer': this.scrollToBottom, - submit: this.addCard, - }]; + return [ + { + 'click .js-minicard': this.clickOnMiniCard, + 'click .js-toggle-multi-selection': this.toggleMultiSelection, + 'click .open-minicard-composer': this.scrollToBottom, + submit: this.addCard, + }, + ]; }, }).register('listBody'); @@ -212,10 +235,15 @@ BlazeComponent.extendComponent({ const currentBoardId = Session.get('currentBoard'); arr = []; - _.forEach(Boards.findOne(currentBoardId).customFields().fetch(), function(field){ - if(field.automaticallyOnCard) - arr.push({_id: field._id, value: null}); - }); + _.forEach( + Boards.findOne(currentBoardId) + .customFields() + .fetch(), + function(field) { + if (field.automaticallyOnCard) + arr.push({ _id: field._id, value: null }); + }, + ); this.customFields.set(arr); }, @@ -227,7 +255,7 @@ BlazeComponent.extendComponent({ getLabels() { const currentBoardId = Session.get('currentBoard'); - return Boards.findOne(currentBoardId).labels.filter((label) => { + return Boards.findOne(currentBoardId).labels.filter(label => { return this.labels.get().indexOf(label._id) > -1; }); }, @@ -257,18 +285,20 @@ BlazeComponent.extendComponent({ } BlazeComponent.getComponentForElement(nextList).openForm({ - position:this.data().position, + position: this.data().position, }); } }, events() { - return [{ - keydown: this.pressKey, - 'click .js-link': Popup.open('linkCard'), - 'click .js-search': Popup.open('searchElement'), - 'click .js-card-template': Popup.open('searchElement'), - }]; + return [ + { + keydown: this.pressKey, + 'click .js-link': Popup.open('linkCard'), + 'click .js-search': Popup.open('searchElement'), + 'click .js-card-template': Popup.open('searchElement'), + }, + ]; }, onRendered() { @@ -277,66 +307,75 @@ BlazeComponent.extendComponent({ autosize($textarea); - $textarea.escapeableTextComplete([ - // User mentions - { - match: /\B@([\w.]*)$/, - search(term, callback) { - const currentBoard = Boards.findOne(Session.get('currentBoard')); - callback($.map(currentBoard.activeMembers(), (member) => { - const user = Users.findOne(member.userId); - return user.username.indexOf(term) === 0 ? user : null; - })); - }, - template(user) { - return user.username; - }, - replace(user) { - toggleValueInReactiveArray(editor.members, user._id); - return ''; + $textarea.escapeableTextComplete( + [ + // User mentions + { + match: /\B@([\w.]*)$/, + search(term, callback) { + const currentBoard = Boards.findOne(Session.get('currentBoard')); + callback( + $.map(currentBoard.activeMembers(), member => { + const user = Users.findOne(member.userId); + return user.username.indexOf(term) === 0 ? user : null; + }), + ); + }, + template(user) { + return user.username; + }, + replace(user) { + toggleValueInReactiveArray(editor.members, user._id); + return ''; + }, + index: 1, }, - index: 1, - }, - // Labels - { - match: /\B#(\w*)$/, - search(term, callback) { - const currentBoard = Boards.findOne(Session.get('currentBoard')); - callback($.map(currentBoard.labels, (label) => { - if (label.name.indexOf(term) > -1 || - label.color.indexOf(term) > -1) { - return label; - } - return null; - })); - }, - template(label) { - return Blaze.toHTMLWithData(Template.autocompleteLabelLine, { - hasNoName: !label.name, - colorName: label.color, - labelName: label.name || label.color, - }); + // Labels + { + match: /\B#(\w*)$/, + search(term, callback) { + const currentBoard = Boards.findOne(Session.get('currentBoard')); + callback( + $.map(currentBoard.labels, label => { + if ( + label.name.indexOf(term) > -1 || + label.color.indexOf(term) > -1 + ) { + return label; + } + return null; + }), + ); + }, + template(label) { + return Blaze.toHTMLWithData(Template.autocompleteLabelLine, { + hasNoName: !label.name, + colorName: label.color, + labelName: label.name || label.color, + }); + }, + replace(label) { + toggleValueInReactiveArray(editor.labels, label._id); + return ''; + }, + index: 1, }, - replace(label) { - toggleValueInReactiveArray(editor.labels, label._id); - return ''; + ], + { + // When the autocomplete menu is shown we want both a press of both `Tab` + // or `Enter` to validation the auto-completion. We also need to stop the + // event propagation to prevent the card from submitting (on `Enter`) or + // going on the next column (on `Tab`). + onKeydown(evt, commands) { + if (evt.keyCode === 9 || evt.keyCode === 13) { + evt.stopPropagation(); + return commands.KEY_ENTER; + } + return null; }, - index: 1, }, - ], { - // When the autocomplete menu is shown we want both a press of both `Tab` - // or `Enter` to validation the auto-completion. We also need to stop the - // event propagation to prevent the card from submitting (on `Enter`) or - // going on the next column (on `Tab`). - onKeydown(evt, commands) { - if (evt.keyCode === 9 || evt.keyCode === 13) { - evt.stopPropagation(); - return commands.KEY_ENTER; - } - return null; - }, - }); + ); }, }).register('addCardForm'); @@ -354,24 +393,29 @@ BlazeComponent.extendComponent({ const list = $(Popup._getTopStack().openerElement).closest('.js-list'); this.listId = Blaze.getData(list[0])._id; // Swimlane where to insert card - const swimlane = $(Popup._getTopStack().openerElement).closest('.js-swimlane'); + const swimlane = $(Popup._getTopStack().openerElement).closest( + '.js-swimlane', + ); this.swimlaneId = ''; const boardView = (Meteor.user().profile || {}).boardView; if (boardView === 'board-view-swimlanes') this.swimlaneId = Blaze.getData(swimlane[0])._id; else if (boardView === 'board-view-lists' || !boardView) - this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id; + this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id; }, boards() { - const boards = Boards.find({ - archived: false, - 'members.userId': Meteor.userId(), - _id: {$ne: Session.get('currentBoard')}, - type: 'board', - }, { - sort: ['title'], - }); + const boards = Boards.find( + { + archived: false, + 'members.userId': Meteor.userId(), + _id: { $ne: Session.get('currentBoard') }, + type: 'board', + }, + { + sort: ['title'], + }, + ); return boards; }, @@ -379,7 +423,7 @@ BlazeComponent.extendComponent({ if (!this.selectedBoardId.get()) { return []; } - const swimlanes = Swimlanes.find({boardId: this.selectedBoardId.get()}); + const swimlanes = Swimlanes.find({ boardId: this.selectedBoardId.get() }); if (swimlanes.count()) this.selectedSwimlaneId.set(swimlanes.fetch()[0]._id); return swimlanes; @@ -389,9 +433,8 @@ BlazeComponent.extendComponent({ if (!this.selectedBoardId.get()) { return []; } - const lists = Lists.find({boardId: this.selectedBoardId.get()}); - if (lists.count()) - this.selectedListId.set(lists.fetch()[0]._id); + const lists = Lists.find({ boardId: this.selectedBoardId.get() }); + if (lists.count()) this.selectedListId.set(lists.fetch()[0]._id); return lists; }, @@ -399,73 +442,84 @@ BlazeComponent.extendComponent({ if (!this.board) { return []; } - const ownCardsIds = this.board.cards().map((card) => { return card.linkedId || card._id; }); + const ownCardsIds = this.board.cards().map(card => { + return card.linkedId || card._id; + }); return Cards.find({ boardId: this.selectedBoardId.get(), swimlaneId: this.selectedSwimlaneId.get(), listId: this.selectedListId.get(), archived: false, - linkedId: {$nin: ownCardsIds}, - _id: {$nin: ownCardsIds}, - type: {$nin: ['template-card']}, + linkedId: { $nin: ownCardsIds }, + _id: { $nin: ownCardsIds }, + type: { $nin: ['template-card'] }, }); }, events() { - return [{ - 'change .js-select-boards'(evt) { - subManager.subscribe('board', $(evt.currentTarget).val(), false); - this.selectedBoardId.set($(evt.currentTarget).val()); - }, - 'change .js-select-swimlanes'(evt) { - this.selectedSwimlaneId.set($(evt.currentTarget).val()); - }, - 'change .js-select-lists'(evt) { - this.selectedListId.set($(evt.currentTarget).val()); - }, - 'click .js-done' (evt) { - // LINK CARD - evt.stopPropagation(); - evt.preventDefault(); - const linkedId = $('.js-select-cards option:selected').val(); - if (!linkedId) { + return [ + { + 'change .js-select-boards'(evt) { + subManager.subscribe('board', $(evt.currentTarget).val(), false); + this.selectedBoardId.set($(evt.currentTarget).val()); + }, + 'change .js-select-swimlanes'(evt) { + this.selectedSwimlaneId.set($(evt.currentTarget).val()); + }, + 'change .js-select-lists'(evt) { + this.selectedListId.set($(evt.currentTarget).val()); + }, + 'click .js-done'(evt) { + // LINK CARD + evt.stopPropagation(); + evt.preventDefault(); + const linkedId = $('.js-select-cards option:selected').val(); + if (!linkedId) { + Popup.close(); + return; + } + const _id = Cards.insert({ + title: $('.js-select-cards option:selected').text(), //dummy + listId: this.listId, + swimlaneId: this.swimlaneId, + boardId: this.boardId, + sort: Lists.findOne(this.listId) + .cards() + .count(), + type: 'cardType-linkedCard', + linkedId, + }); + Filter.addException(_id); Popup.close(); - return; - } - const _id = Cards.insert({ - title: $('.js-select-cards option:selected').text(), //dummy - listId: this.listId, - swimlaneId: this.swimlaneId, - boardId: this.boardId, - sort: Lists.findOne(this.listId).cards().count(), - type: 'cardType-linkedCard', - linkedId, - }); - Filter.addException(_id); - Popup.close(); - }, - 'click .js-link-board' (evt) { - //LINK BOARD - evt.stopPropagation(); - evt.preventDefault(); - const impBoardId = $('.js-select-boards option:selected').val(); - if (!impBoardId || Cards.findOne({linkedId: impBoardId, archived: false})) { + }, + 'click .js-link-board'(evt) { + //LINK BOARD + evt.stopPropagation(); + evt.preventDefault(); + const impBoardId = $('.js-select-boards option:selected').val(); + if ( + !impBoardId || + Cards.findOne({ linkedId: impBoardId, archived: false }) + ) { + Popup.close(); + return; + } + const _id = Cards.insert({ + title: $('.js-select-boards option:selected').text(), //dummy + listId: this.listId, + swimlaneId: this.swimlaneId, + boardId: this.boardId, + sort: Lists.findOne(this.listId) + .cards() + .count(), + type: 'cardType-linkedBoard', + linkedId: impBoardId, + }); + Filter.addException(_id); Popup.close(); - return; - } - const _id = Cards.insert({ - title: $('.js-select-boards option:selected').text(), //dummy - listId: this.listId, - swimlaneId: this.swimlaneId, - boardId: this.boardId, - sort: Lists.findOne(this.listId).cards().count(), - type: 'cardType-linkedBoard', - linkedId: impBoardId, - }); - Filter.addException(_id); - Popup.close(); + }, }, - }]; + ]; }, }).register('linkCardPopup'); @@ -475,11 +529,20 @@ BlazeComponent.extendComponent({ }, onCreated() { - this.isCardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-card-template'); - this.isListTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-list-template'); - this.isSwimlaneTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-open-add-swimlane-menu'); - this.isBoardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-add-board'); - this.isTemplateSearch = this.isCardTemplateSearch || + this.isCardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass( + 'js-card-template', + ); + this.isListTemplateSearch = $(Popup._getTopStack().openerElement).hasClass( + 'js-list-template', + ); + this.isSwimlaneTemplateSearch = $( + Popup._getTopStack().openerElement, + ).hasClass('js-open-add-swimlane-menu'); + this.isBoardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass( + 'js-add-board', + ); + this.isTemplateSearch = + this.isCardTemplateSearch || this.isListTemplateSearch || this.isSwimlaneTemplateSearch || this.isBoardTemplateSearch; @@ -491,7 +554,12 @@ BlazeComponent.extendComponent({ board = Boards.findOne({ archived: false, 'members.userId': Meteor.userId(), - _id: {$nin: [Session.get('currentBoard'), (Meteor.user().profile || {}).templatesBoardId]}, + _id: { + $nin: [ + Session.get('currentBoard'), + (Meteor.user().profile || {}).templatesBoardId, + ], + }, }); } if (!board) { @@ -509,11 +577,12 @@ BlazeComponent.extendComponent({ subManager.subscribe('board', this.boardId, false); this.swimlaneId = ''; // Swimlane where to insert card - const swimlane = $(Popup._getTopStack().openerElement).parents('.js-swimlane'); + const swimlane = $(Popup._getTopStack().openerElement).parents( + '.js-swimlane', + ); if ((Meteor.user().profile || {}).boardView === 'board-view-swimlanes') this.swimlaneId = Blaze.getData(swimlane[0])._id; - else - this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id; + else this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id; // List where to insert card const list = $(Popup._getTopStack().openerElement).closest('.js-list'); this.listId = Blaze.getData(list[0])._id; @@ -522,14 +591,17 @@ BlazeComponent.extendComponent({ }, boards() { - const boards = Boards.find({ - archived: false, - 'members.userId': Meteor.userId(), - _id: {$ne: Session.get('currentBoard')}, - type: 'board', - }, { - sort: ['title'], - }); + const boards = Boards.find( + { + archived: false, + 'members.userId': Meteor.userId(), + _id: { $ne: Session.get('currentBoard') }, + type: 'board', + }, + { + sort: ['title'], + }, + ); return boards; }, @@ -546,7 +618,7 @@ BlazeComponent.extendComponent({ return board.searchSwimlanes(this.term.get()); } else if (this.isBoardTemplateSearch) { const boards = board.searchBoards(this.term.get()); - boards.forEach((board) => { + boards.forEach(board => { subManager.subscribe('board', board.linkedId, false); }); return boards; @@ -556,60 +628,69 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'change .js-select-boards'(evt) { - subManager.subscribe('board', $(evt.currentTarget).val(), false); - this.selectedBoardId.set($(evt.currentTarget).val()); - }, - 'submit .js-search-term-form'(evt) { - evt.preventDefault(); - this.term.set(evt.target.searchTerm.value); - }, - 'click .js-minicard'(evt) { - // 0. Common - const title = $('.js-element-title').val().trim(); - if (!title) - return; - const element = Blaze.getData(evt.currentTarget); - element.title = title; - let _id = ''; - if (!this.isTemplateSearch || this.isCardTemplateSearch) { - // Card insertion - // 1. Common - element.sort = Lists.findOne(this.listId).cards().count(); - // 1.A From template - if (this.isTemplateSearch) { - element.type = 'cardType-card'; - element.linkedId = ''; - _id = element.copy(this.boardId, this.swimlaneId, this.listId); - // 1.B Linked card - } else { - delete element._id; - element.type = 'cardType-linkedCard'; - element.linkedId = element.linkedId || element._id; - _id = Cards.insert(element); + return [ + { + 'change .js-select-boards'(evt) { + subManager.subscribe('board', $(evt.currentTarget).val(), false); + this.selectedBoardId.set($(evt.currentTarget).val()); + }, + 'submit .js-search-term-form'(evt) { + evt.preventDefault(); + this.term.set(evt.target.searchTerm.value); + }, + 'click .js-minicard'(evt) { + // 0. Common + const title = $('.js-element-title') + .val() + .trim(); + if (!title) return; + const element = Blaze.getData(evt.currentTarget); + element.title = title; + let _id = ''; + if (!this.isTemplateSearch || this.isCardTemplateSearch) { + // Card insertion + // 1. Common + element.sort = Lists.findOne(this.listId) + .cards() + .count(); + // 1.A From template + if (this.isTemplateSearch) { + element.type = 'cardType-card'; + element.linkedId = ''; + _id = element.copy(this.boardId, this.swimlaneId, this.listId); + // 1.B Linked card + } else { + delete element._id; + element.type = 'cardType-linkedCard'; + element.linkedId = element.linkedId || element._id; + _id = Cards.insert(element); + } + Filter.addException(_id); + // List insertion + } else if (this.isListTemplateSearch) { + element.sort = Swimlanes.findOne(this.swimlaneId) + .lists() + .count(); + element.type = 'list'; + _id = element.copy(this.boardId, this.swimlaneId); + } else if (this.isSwimlaneTemplateSearch) { + element.sort = Boards.findOne(this.boardId) + .swimlanes() + .count(); + element.type = 'swimlalne'; + _id = element.copy(this.boardId); + } else if (this.isBoardTemplateSearch) { + board = Boards.findOne(element.linkedId); + board.sort = Boards.find({ archived: false }).count(); + board.type = 'board'; + board.title = element.title; + delete board.slug; + _id = board.copy(); } - Filter.addException(_id); - // List insertion - } else if (this.isListTemplateSearch) { - element.sort = Swimlanes.findOne(this.swimlaneId).lists().count(); - element.type = 'list'; - _id = element.copy(this.boardId, this.swimlaneId); - } else if (this.isSwimlaneTemplateSearch) { - element.sort = Boards.findOne(this.boardId).swimlanes().count(); - element.type = 'swimlalne'; - _id = element.copy(this.boardId); - } else if (this.isBoardTemplateSearch) { - board = Boards.findOne(element.linkedId); - board.sort = Boards.find({archived: false}).count(); - board.type = 'board'; - board.title = element.title; - delete board.slug; - _id = board.copy(); - } - Popup.close(); + Popup.close(); + }, }, - }]; + ]; }, }).register('searchElementPopup'); @@ -622,15 +703,23 @@ BlazeComponent.extendComponent({ const boardView = (Meteor.user().profile || {}).boardView; if (boardView === 'board-view-swimlanes') - this.swimlaneId = this.parentComponent().parentComponent().parentComponent().data()._id; + this.swimlaneId = this.parentComponent() + .parentComponent() + .parentComponent() + .data()._id; }, onRendered() { this.spinner = this.find('.sk-spinner-list'); this.container = this.$(this.spinner).parents('.js-perfect-scrollbar')[0]; - $(this.container).on(`scroll.spinner_${this.swimlaneId}_${this.listId}`, () => this.updateList()); - $(window).on(`resize.spinner_${this.swimlaneId}_${this.listId}`, () => this.updateList()); + $(this.container).on( + `scroll.spinner_${this.swimlaneId}_${this.listId}`, + () => this.updateList(), + ); + $(window).on(`resize.spinner_${this.swimlaneId}_${this.listId}`, () => + this.updateList(), + ); this.updateList(); }, @@ -660,5 +749,4 @@ BlazeComponent.extendComponent({ return bottomViewPosition > threshold; }, - }).register('spinnerList'); diff --git a/client/components/lists/listHeader.js b/client/components/lists/listHeader.js index 923d6063..e8a82499 100644 --- a/client/components/lists/listHeader.js +++ b/client/components/lists/listHeader.js @@ -6,12 +6,18 @@ Meteor.startup(() => { BlazeComponent.extendComponent({ canSeeAddCard() { const list = Template.currentData(); - return !list.getWipLimit('enabled') || list.getWipLimit('soft') || !this.reachedWipLimit(); - }, - - editTitle(evt) { - evt.preventDefault(); - const newTitle = this.childComponents('inlinedForm')[0].getValue().trim(); + return ( + !list.getWipLimit('enabled') || + list.getWipLimit('soft') || + !this.reachedWipLimit() + ); + }, + + editTitle(event) { + event.preventDefault(); + const newTitle = this.childComponents('inlinedForm')[0] + .getValue() + .trim(); const list = this.currentData(); if (newTitle) { list.rename(newTitle.trim()); @@ -32,14 +38,19 @@ BlazeComponent.extendComponent({ let swimlaneId = ''; const boardView = (Meteor.user().profile || {}).boardView; if (boardView === 'board-view-swimlanes') - swimlaneId = this.parentComponent().parentComponent().data()._id; + swimlaneId = this.parentComponent() + .parentComponent() + .data()._id; return list.cards(swimlaneId).count(); }, reachedWipLimit() { const list = Template.currentData(); - return list.getWipLimit('enabled') && list.getWipLimit('value') <= list.cards().count(); + return ( + list.getWipLimit('enabled') && + list.getWipLimit('value') <= list.cards().count() + ); }, showCardsCountForList(count) { @@ -48,20 +59,24 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-open-list-menu': Popup.open('listAction'), - 'click .js-add-card' (evt) { - const listDom = $(evt.target).parents(`#js-list-${this.currentData()._id}`)[0]; - const listComponent = BlazeComponent.getComponentForElement(listDom); - listComponent.openForm({ - position: 'top', - }); + return [ + { + 'click .js-open-list-menu': Popup.open('listAction'), + 'click .js-add-card'(event) { + const listDom = $(event.target).parents( + `#js-list-${this.currentData()._id}`, + )[0]; + const listComponent = BlazeComponent.getComponentForElement(listDom); + listComponent.openForm({ + position: 'top', + }); + }, + 'click .js-unselect-list'() { + Session.set('currentList', null); + }, + submit: this.editTitle, }, - 'click .js-unselect-list'() { - Session.set('currentList', null); - }, - submit: this.editTitle, - }]; + ]; }, }).register('listHeader'); @@ -76,22 +91,22 @@ Template.listActionPopup.helpers({ }); Template.listActionPopup.events({ - 'click .js-list-subscribe' () {}, + 'click .js-list-subscribe'() {}, 'click .js-set-color-list': Popup.open('setListColor'), - 'click .js-select-cards' () { - const cardIds = this.allCards().map((card) => card._id); + 'click .js-select-cards'() { + const cardIds = this.allCards().map(card => card._id); MultiSelection.add(cardIds); Popup.close(); }, - 'click .js-toggle-watch-list' () { + '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(); + 'click .js-close-list'(event) { + event.preventDefault(); this.archive(); Popup.close(); }, @@ -102,10 +117,17 @@ Template.listActionPopup.events({ BlazeComponent.extendComponent({ applyWipLimit() { const list = Template.currentData(); - const limit = parseInt(Template.instance().$('.wip-limit-value').val(), 10); - - if(limit < list.cards().count() && !list.getWipLimit('soft')){ - Template.instance().$('.wip-limit-error').click(); + const limit = parseInt( + Template.instance() + .$('.wip-limit-value') + .val(), + 10, + ); + + if (limit < list.cards().count() && !list.getWipLimit('soft')) { + Template.instance() + .$('.wip-limit-error') + .click(); } else { Meteor.call('applyWipLimit', list._id, limit); Popup.back(); @@ -115,7 +137,10 @@ BlazeComponent.extendComponent({ enableSoftLimit() { const list = Template.currentData(); - if(list.getWipLimit('soft') && list.getWipLimit('value') < list.cards().count()){ + if ( + list.getWipLimit('soft') && + list.getWipLimit('value') < list.cards().count() + ) { list.setWipLimit(list.cards().count()); } Meteor.call('enableSoftLimit', Template.currentData()._id); @@ -124,7 +149,10 @@ BlazeComponent.extendComponent({ enableWipLimit() { const list = Template.currentData(); // Prevent user from using previously stored wipLimit.value if it is less than the current number of cards in the list - if(!list.getWipLimit('enabled') && list.getWipLimit('value') < list.cards().count()){ + if ( + !list.getWipLimit('enabled') && + list.getWipLimit('value') < list.cards().count() + ) { list.setWipLimit(list.cards().count()); } Meteor.call('enableWipLimit', list._id); @@ -138,24 +166,26 @@ BlazeComponent.extendComponent({ return Template.currentData().getWipLimit('enabled'); }, - wipLimitValue(){ + wipLimitValue() { return Template.currentData().getWipLimit('value'); }, events() { - return [{ - 'click .js-enable-wip-limit': this.enableWipLimit, - 'click .wip-limit-apply': this.applyWipLimit, - 'click .wip-limit-error': Popup.open('wipLimitError'), - 'click .materialCheckBox': this.enableSoftLimit, - }]; + return [ + { + 'click .js-enable-wip-limit': this.enableWipLimit, + 'click .wip-limit-apply': this.applyWipLimit, + 'click .wip-limit-error': Popup.open('wipLimitError'), + 'click .materialCheckBox': this.enableSoftLimit, + }, + ]; }, }).register('setWipLimitPopup'); Template.listMorePopup.events({ - 'click .js-delete': Popup.afterConfirm('listDelete', function () { + 'click .js-delete': Popup.afterConfirm('listDelete', function() { Popup.close(); - this.allCards().map((card) => Cards.remove(card._id)); + this.allCards().map(card => Cards.remove(card._id)); Lists.remove(this._id); Utils.goBoardId(this.boardId); }), @@ -168,7 +198,7 @@ BlazeComponent.extendComponent({ }, colors() { - return listsColors.map((color) => ({ color, name: '' })); + return listsColors.map(color => ({ color, name: '' })); }, isSelected(color) { @@ -176,18 +206,20 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-palette-color'() { - this.currentColor.set(this.currentData().color); - }, - 'click .js-submit' () { - this.currentList.setColor(this.currentColor.get()); - Popup.close(); - }, - 'click .js-remove-color'() { - this.currentList.setColor(null); - Popup.close(); + return [ + { + 'click .js-palette-color'() { + this.currentColor.set(this.currentData().color); + }, + 'click .js-submit'() { + this.currentList.setColor(this.currentColor.get()); + Popup.close(); + }, + 'click .js-remove-color'() { + this.currentList.setColor(null); + Popup.close(); + }, }, - }]; + ]; }, }).register('setListColorPopup'); diff --git a/client/components/main/editor.js b/client/components/main/editor.js index 88d8abf0..2824723d 100755 --- a/client/components/main/editor.js +++ b/client/components/main/editor.js @@ -9,10 +9,15 @@ Template.editor.onRendered(() => { match: /\B@([\w.]*)$/, search(term, callback) { const currentBoard = Boards.findOne(Session.get('currentBoard')); - callback(currentBoard.activeMembers().map((member) => { - const username = Users.findOne(member.userId).username; - return username.includes(term) ? username : null; - }).filter(Boolean)); + callback( + currentBoard + .activeMembers() + .map(member => { + const username = Users.findOne(member.userId).username; + return username.includes(term) ? username : null; + }) + .filter(Boolean), + ); }, template(value) { return value; @@ -33,69 +38,73 @@ import sanitizeXss from 'xss'; // 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. -const at = HTML.CharRef({html: '@', str: '@'}); -Blaze.Template.registerHelper('mentions', new Template('mentions', function() { - const view = this; - let content = Blaze.toHTML(view.templateContentBlock); - const currentBoard = Boards.findOne(Session.get('currentBoard')); - if (!currentBoard) - return HTML.Raw(sanitizeXss(content)); - const knowedUsers = currentBoard.members.map((member) => { - const u = Users.findOne(member.userId); - if(u){ - member.username = u.username; - } - return member; - }); - const mentionRegex = /\B@([\w.]*)/gi; +const at = HTML.CharRef({ html: '@', str: '@' }); +Blaze.Template.registerHelper( + 'mentions', + new Template('mentions', function() { + const view = this; + let content = Blaze.toHTML(view.templateContentBlock); + const currentBoard = Boards.findOne(Session.get('currentBoard')); + if (!currentBoard) return HTML.Raw(sanitizeXss(content)); + const knowedUsers = currentBoard.members.map(member => { + const u = Users.findOne(member.userId); + if (u) { + member.username = u.username; + } + return member; + }); + const mentionRegex = /\B@([\w.]*)/gi; - let currentMention; - while ((currentMention = mentionRegex.exec(content)) !== null) { - const [fullMention, username] = currentMention; - const knowedUser = _.findWhere(knowedUsers, { username }); - if (!knowedUser) { - continue; - } + let currentMention; + while ((currentMention = mentionRegex.exec(content)) !== null) { + const [fullMention, username] = currentMention; + const knowedUser = _.findWhere(knowedUsers, { username }); + if (!knowedUser) { + continue; + } - const linkValue = [' ', at, knowedUser.username]; - let linkClass = 'atMention js-open-member'; - if (knowedUser.userId === Meteor.userId()) { - linkClass += ' me'; - } - const link = HTML.A({ - 'class': linkClass, - // XXX Hack. Since we stringify this render function result below with - // `Blaze.toHTML` we can't rely on blaze data contexts to pass the - // `userId` to the popup as usual, and we need to store it in the DOM - // using a data attribute. - 'data-userId': knowedUser.userId, - }, linkValue); + const linkValue = [' ', at, knowedUser.username]; + let linkClass = 'atMention js-open-member'; + if (knowedUser.userId === Meteor.userId()) { + linkClass += ' me'; + } + const link = HTML.A( + { + class: linkClass, + // XXX Hack. Since we stringify this render function result below with + // `Blaze.toHTML` we can't rely on blaze data contexts to pass the + // `userId` to the popup as usual, and we need to store it in the DOM + // using a data attribute. + 'data-userId': knowedUser.userId, + }, + linkValue, + ); - content = content.replace(fullMention, Blaze.toHTML(link)); - } + content = content.replace(fullMention, Blaze.toHTML(link)); + } - return HTML.Raw(sanitizeXss(content)); -})); + return HTML.Raw(sanitizeXss(content)); + }), +); 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'(evt, tpl) { - evt.stopPropagation(); + 'click a'(event, templateInstance) { + event.stopPropagation(); // XXX We hijack the build-in browser action because we currently don't have // `_blank` attributes in viewer links, and the transformer function is // 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(); + event.preventDefault(); - const userId = evt.currentTarget.dataset.userid; + const userId = event.currentTarget.dataset.userid; if (userId) { - Popup.open('member').call({ userId }, evt, tpl); - } - else { - const href = evt.currentTarget.href; + Popup.open('member').call({ userId }, event, templateInstance); + } else { + const href = event.currentTarget.href; if (href) { window.open(href, '_blank'); } diff --git a/client/components/main/header.js b/client/components/main/header.js index c05b1c3c..957a1285 100644 --- a/client/components/main/header.js +++ b/client/components/main/header.js @@ -20,13 +20,13 @@ Template.header.helpers({ }, hasAnnouncement() { - const announcements = Announcements.findOne(); + const announcements = Announcements.findOne(); return announcements && announcements.enabled; }, announcement() { $('.announcement').show(); - const announcements = Announcements.findOne(); + const announcements = Announcements.findOne(); return announcements && announcements.body; }, }); diff --git a/client/components/main/layouts.js b/client/components/main/layouts.js index fe51a7d6..ec4a35cc 100644 --- a/client/components/main/layouts.js +++ b/client/components/main/layouts.js @@ -1,6 +1,6 @@ BlazeLayout.setRoot('body'); -const i18nTagToT9n = (i18nTag) => { +const i18nTagToT9n = i18nTag => { // t9n/i18n tags are same now, see: https://github.com/softwarerero/meteor-accounts-t9n/pull/129 // but we keep this conversion function here, to be aware that that they are different system. return i18nTag; @@ -21,20 +21,23 @@ const validator = { }; Template.userFormsLayout.onCreated(function() { - const instance = this; - instance.currentSetting = new ReactiveVar(); - instance.isLoading = new ReactiveVar(false); + const templateInstance = this; + templateInstance.currentSetting = new ReactiveVar(); + templateInstance.isLoading = new ReactiveVar(false); Meteor.subscribe('setting', { onReady() { - instance.currentSetting.set(Settings.findOne()); + templateInstance.currentSetting.set(Settings.findOne()); return this.stop(); }, }); }); Template.userFormsLayout.onRendered(() => { - AccountsTemplates.state.form.keys = new Proxy(AccountsTemplates.state.form.keys, validator); + AccountsTemplates.state.form.keys = new Proxy( + AccountsTemplates.state.form.keys, + validator, + ); const i18nTag = navigator.language; if (i18nTag) { @@ -89,18 +92,17 @@ Template.userFormsLayout.helpers({ }); Template.userFormsLayout.events({ - 'change .js-userform-set-language'(evt) { - const i18nTag = $(evt.currentTarget).val(); + 'change .js-userform-set-language'(event) { + const i18nTag = $(event.currentTarget).val(); T9n.setLanguage(i18nTagToT9n(i18nTag)); - evt.preventDefault(); + event.preventDefault(); }, - 'click #at-btn'(event, instance) { + 'click #at-btn'(event, templateInstance) { if (FlowRouter.getRouteName() === 'atSignIn') { - instance.isLoading.set(true); - authentication(event, instance) - .then(() => { - instance.isLoading.set(false); - }); + templateInstance.isLoading.set(true); + authentication(event, templateInstance).then(() => { + templateInstance.isLoading.set(false); + }); } }, }); @@ -111,13 +113,16 @@ Template.defaultLayout.events({ }, }); -async function authentication(event, instance) { +async function authentication(event, templateInstance) { const match = $('#at-field-username_and_email').val(); const password = $('#at-field-password').val(); if (!match || !password) return undefined; - const result = await getAuthenticationMethod(instance.currentSetting.get(), match); + const result = await getAuthenticationMethod( + templateInstance.currentSetting.get(), + match, + ); if (result === 'password') return undefined; @@ -126,26 +131,29 @@ async function authentication(event, instance) { event.stopImmediatePropagation(); switch (result) { - case 'ldap': - return new Promise((resolve) => { - Meteor.loginWithLDAP(match, password, function() { - resolve(FlowRouter.go('/')); + case 'ldap': + return new Promise(resolve => { + Meteor.loginWithLDAP(match, password, function() { + resolve(FlowRouter.go('/')); + }); }); - }); - case 'cas': - return new Promise((resolve) => { - Meteor.loginWithCas(match, password, function() { - resolve(FlowRouter.go('/')); + case 'cas': + return new Promise(resolve => { + Meteor.loginWithCas(match, password, function() { + resolve(FlowRouter.go('/')); + }); }); - }); - default: - return undefined; + default: + return undefined; } } -function getAuthenticationMethod({displayAuthenticationMethod, defaultAuthenticationMethod}, match) { +function getAuthenticationMethod( + { displayAuthenticationMethod, defaultAuthenticationMethod }, + match, +) { if (displayAuthenticationMethod) { return $('.select-authentication').val(); } @@ -153,7 +161,7 @@ function getAuthenticationMethod({displayAuthenticationMethod, defaultAuthentica } function getUserAuthenticationMethod(defaultAuthenticationMethod, match) { - return new Promise((resolve) => { + return new Promise(resolve => { try { Meteor.subscribe('user-authenticationMethod', match, { onReady() { @@ -166,7 +174,7 @@ function getUserAuthenticationMethod(defaultAuthenticationMethod, match) { resolve(authenticationMethod); }, }); - } catch(error) { + } catch (error) { resolve(defaultAuthenticationMethod); } }); diff --git a/client/components/mixins/infiniteScrolling.js b/client/components/mixins/infiniteScrolling.js index eb02b76f..722774c4 100644 --- a/client/components/mixins/infiniteScrolling.js +++ b/client/components/mixins/infiniteScrolling.js @@ -18,15 +18,17 @@ Mixins.InfiniteScrolling = BlazeComponent.extendComponent({ }, events() { - return [{ - scroll(evt) { - const domElement = evt.currentTarget; - let altitude = domElement.scrollTop + domElement.offsetHeight; - altitude += peakAnticipation; - if (altitude >= this.callFirstWith(null, 'getNextPeak')) { - this.mixinParent().callFirstWith(null, 'reachNextPeak'); - } + return [ + { + scroll(evt) { + const domElement = evt.currentTarget; + let altitude = domElement.scrollTop + domElement.offsetHeight; + altitude += peakAnticipation; + if (altitude >= this.callFirstWith(null, 'getNextPeak')) { + this.mixinParent().callFirstWith(null, 'reachNextPeak'); + } + }, }, - }]; + ]; }, }); diff --git a/client/components/rules/actions/boardActions.js b/client/components/rules/actions/boardActions.js index e0b8edc9..8568d2bf 100644 --- a/client/components/rules/actions/boardActions.js +++ b/client/components/rules/actions/boardActions.js @@ -1,68 +1,23 @@ BlazeComponent.extendComponent({ - onCreated() { - - }, + onCreated() {}, events() { - return [{ - 'click .js-create-card-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const cardName = this.find('#card-name').value; - const listName = this.find('#list-name').value; - const swimlaneName = this.find('#swimlane-name2').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'createCard', - swimlaneName, - cardName, - listName, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - - }, - 'click .js-add-swimlane-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const swimlaneName = this.find('#swimlane-name').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'addSwimlane', - swimlaneName, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - - }, - 'click .js-add-spec-move-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const actionSelected = this.find('#move-spec-action').value; - const listTitle = this.find('#listName').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - if (actionSelected === 'top') { + return [ + { + 'click .js-create-card-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const cardName = this.find('#card-name').value; + const listName = this.find('#list-name').value; + const swimlaneName = this.find('#swimlane-name2').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); const triggerId = Triggers.insert(trigger); const actionId = Actions.insert({ - actionType: 'moveCardToTop', - listTitle, + actionType: 'createCard', + swimlaneName, + cardName, + listName, boardId, desc, }); @@ -72,12 +27,17 @@ BlazeComponent.extendComponent({ actionId, boardId, }); - } - if (actionSelected === 'bottom') { + }, + 'click .js-add-swimlane-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const swimlaneName = this.find('#swimlane-name').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); const triggerId = Triggers.insert(trigger); const actionId = Actions.insert({ - actionType: 'moveCardToBottom', - listTitle, + actionType: 'addSwimlane', + swimlaneName, boardId, desc, }); @@ -87,82 +47,119 @@ BlazeComponent.extendComponent({ actionId, boardId, }); - } + }, + 'click .js-add-spec-move-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const actionSelected = this.find('#move-spec-action').value; + const listTitle = this.find('#listName').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); + if (actionSelected === 'top') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'moveCardToTop', + listTitle, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + if (actionSelected === 'bottom') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'moveCardToBottom', + listTitle, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + }, + 'click .js-add-gen-move-action'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const boardId = Session.get('currentBoard'); + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const actionSelected = this.find('#move-gen-action').value; + if (actionSelected === 'top') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'moveCardToTop', + listTitle: '*', + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + if (actionSelected === 'bottom') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'moveCardToBottom', + listTitle: '*', + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + }, + 'click .js-add-arch-action'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const boardId = Session.get('currentBoard'); + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const actionSelected = this.find('#arch-action').value; + if (actionSelected === 'archive') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'archive', + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + if (actionSelected === 'unarchive') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'unarchive', + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + }, }, - 'click .js-add-gen-move-action' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const boardId = Session.get('currentBoard'); - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const actionSelected = this.find('#move-gen-action').value; - if (actionSelected === 'top') { - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'moveCardToTop', - 'listTitle': '*', - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - } - if (actionSelected === 'bottom') { - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'moveCardToBottom', - 'listTitle': '*', - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - } - }, - 'click .js-add-arch-action' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const boardId = Session.get('currentBoard'); - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const actionSelected = this.find('#arch-action').value; - if (actionSelected === 'archive') { - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'archive', - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - } - if (actionSelected === 'unarchive') { - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'unarchive', - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - } - }, - }]; + ]; }, - }).register('boardActions'); /* eslint-no-undef */ diff --git a/client/components/rules/actions/cardActions.js b/client/components/rules/actions/cardActions.js index d6e11eea..7dc6c2b5 100644 --- a/client/components/rules/actions/cardActions.js +++ b/client/components/rules/actions/cardActions.js @@ -14,7 +14,7 @@ BlazeComponent.extendComponent({ }, cardColorButtonText() { - return `color-${ this.cardColorButtonValue.get() }`; + return `color-${this.cardColorButtonValue.get()}`; }, labels() { @@ -28,106 +28,143 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-set-date-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const triggerId = Triggers.insert(trigger); - const actionSelected = this.find('#setdate-action').value; - const dateFieldSelected = this.find('#setdate-datefield').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - - const actionId = Actions.insert({ - actionType: actionSelected, - dateField: dateFieldSelected, - boardId, - desc, - }); - - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - desc, - }); - }, - - 'click .js-remove-datevalue-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const triggerId = Triggers.insert(trigger); - const dateFieldSelected = this.find('#setdate-removedatefieldvalue').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - - const actionId = Actions.insert({ - actionType: 'removeDate', - dateField: dateFieldSelected, - boardId, - desc, - }); - - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - desc, - }); - }, - 'click .js-add-label-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const actionSelected = this.find('#label-action').value; - const labelId = this.find('#label-id').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - if (actionSelected === 'add') { + return [ + { + 'click .js-set-date-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); const triggerId = Triggers.insert(trigger); + const actionSelected = this.find('#setdate-action').value; + const dateFieldSelected = this.find('#setdate-datefield').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); + const actionId = Actions.insert({ - actionType: 'addLabel', - labelId, + actionType: actionSelected, + dateField: dateFieldSelected, boardId, desc, }); + Rules.insert({ title: ruleName, triggerId, actionId, boardId, + desc, }); - } - if (actionSelected === 'remove') { + }, + + 'click .js-remove-datevalue-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); const triggerId = Triggers.insert(trigger); + const dateFieldSelected = this.find('#setdate-removedatefieldvalue') + .value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); + const actionId = Actions.insert({ - actionType: 'removeLabel', - labelId, + actionType: 'removeDate', + dateField: dateFieldSelected, boardId, desc, }); + Rules.insert({ title: ruleName, triggerId, actionId, boardId, + desc, }); - } - - }, - 'click .js-add-member-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const actionSelected = this.find('#member-action').value; - const username = this.find('#member-name').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - if (actionSelected === 'add') { + }, + 'click .js-add-label-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const actionSelected = this.find('#label-action').value; + const labelId = this.find('#label-id').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); + if (actionSelected === 'add') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'addLabel', + labelId, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + if (actionSelected === 'remove') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'removeLabel', + labelId, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + }, + 'click .js-add-member-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const actionSelected = this.find('#member-action').value; + const username = this.find('#member-name').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); + if (actionSelected === 'add') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'addMember', + username, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + desc, + }); + } + if (actionSelected === 'remove') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'removeMember', + username, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + }, + 'click .js-add-removeall-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); const triggerId = Triggers.insert(trigger); + const desc = Utils.getTriggerActionDesc(event, this); + const boardId = Session.get('currentBoard'); const actionId = Actions.insert({ - actionType: 'addMember', - username, + actionType: 'removeMember', + username: '*', boardId, desc, }); @@ -136,14 +173,26 @@ BlazeComponent.extendComponent({ triggerId, actionId, boardId, - desc, }); - } - if (actionSelected === 'remove') { + }, + 'click .js-show-color-palette'(event) { + const funct = Popup.open('setCardActionsColor'); + const colorButton = this.find('#color-action'); + if (colorButton.value === '') { + colorButton.value = 'green'; + } + funct.call(this, event); + }, + 'click .js-set-color-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const selectedColor = this.cardColorButtonValue.get(); + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); const triggerId = Triggers.insert(trigger); const actionId = Actions.insert({ - actionType: 'removeMember', - username, + actionType: 'setColor', + selectedColor, boardId, desc, }); @@ -153,58 +202,10 @@ BlazeComponent.extendComponent({ actionId, boardId, }); - } - }, - 'click .js-add-removeall-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const triggerId = Triggers.insert(trigger); - const desc = Utils.getTriggerActionDesc(event, this); - const boardId = Session.get('currentBoard'); - const actionId = Actions.insert({ - actionType: 'removeMember', - 'username': '*', - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - }, - 'click .js-show-color-palette'(event){ - const funct = Popup.open('setCardActionsColor'); - const colorButton = this.find('#color-action'); - if (colorButton.value === '') { - colorButton.value = 'green'; - } - funct.call(this, event); + }, }, - 'click .js-set-color-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const selectedColor = this.cardColorButtonValue.get(); - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'setColor', - selectedColor, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - }, - }]; + ]; }, - }).register('cardActions'); BlazeComponent.extendComponent({ @@ -215,7 +216,7 @@ BlazeComponent.extendComponent({ }, colors() { - return cardColors.map((color) => ({ color, name: '' })); + return cardColors.map(color => ({ color, name: '' })); }, isSelected(color) { @@ -223,14 +224,16 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-palette-color'() { - this.currentColor.set(this.currentData().color); - }, - 'click .js-submit' () { - this.colorButtonValue.set(this.currentColor.get()); - Popup.close(); + return [ + { + 'click .js-palette-color'() { + this.currentColor.set(this.currentData().color); + }, + 'click .js-submit'() { + this.colorButtonValue.set(this.currentColor.get()); + Popup.close(); + }, }, - }]; + ]; }, }).register('setCardActionsColorPopup'); diff --git a/client/components/rules/actions/checklistActions.js b/client/components/rules/actions/checklistActions.js index 3e79b075..64908ab1 100644 --- a/client/components/rules/actions/checklistActions.js +++ b/client/components/rules/actions/checklistActions.js @@ -3,137 +3,20 @@ BlazeComponent.extendComponent({ this.subscribe('allRules'); }, events() { - return [{ - 'click .js-add-checklist-items-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const checklistName = this.find('#checklist-name-3').value; - const checklistItems = this.find('#checklist-items').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'addChecklistWithItems', - checklistName, - checklistItems, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - - }, - 'click .js-add-checklist-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const actionSelected = this.find('#check-action').value; - const checklistName = this.find('#checklist-name').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - if (actionSelected === 'add') { - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'addChecklist', - checklistName, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - } - if (actionSelected === 'remove') { - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'removeChecklist', - checklistName, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - } - - }, - 'click .js-add-checkall-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const actionSelected = this.find('#checkall-action').value; - const checklistName = this.find('#checklist-name2').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - if (actionSelected === 'check') { - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'checkAll', - checklistName, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - } - if (actionSelected === 'uncheck') { - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'uncheckAll', - checklistName, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - } - }, - 'click .js-add-check-item-action' (event) { - const ruleName = this.data().ruleName.get(); - const trigger = this.data().triggerVar.get(); - const checkItemName = this.find('#checkitem-name'); - const checklistName = this.find('#checklist-name3'); - const actionSelected = this.find('#check-item-action').value; - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - if (actionSelected === 'check') { - const triggerId = Triggers.insert(trigger); - const actionId = Actions.insert({ - actionType: 'checkItem', - checklistName, - checkItemName, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); - } - if (actionSelected === 'uncheck') { + return [ + { + 'click .js-add-checklist-items-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const checklistName = this.find('#checklist-name-3').value; + const checklistItems = this.find('#checklist-items').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); const triggerId = Triggers.insert(trigger); const actionId = Actions.insert({ - actionType: 'uncheckItem', + actionType: 'addChecklistWithItems', checklistName, - checkItemName, + checklistItems, boardId, desc, }); @@ -143,9 +26,125 @@ BlazeComponent.extendComponent({ actionId, boardId, }); - } + }, + 'click .js-add-checklist-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const actionSelected = this.find('#check-action').value; + const checklistName = this.find('#checklist-name').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); + if (actionSelected === 'add') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'addChecklist', + checklistName, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + if (actionSelected === 'remove') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'removeChecklist', + checklistName, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + }, + 'click .js-add-checkall-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const actionSelected = this.find('#checkall-action').value; + const checklistName = this.find('#checklist-name2').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); + if (actionSelected === 'check') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'checkAll', + checklistName, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + if (actionSelected === 'uncheck') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'uncheckAll', + checklistName, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + }, + 'click .js-add-check-item-action'(event) { + const ruleName = this.data().ruleName.get(); + const trigger = this.data().triggerVar.get(); + const checkItemName = this.find('#checkitem-name'); + const checklistName = this.find('#checklist-name3'); + const actionSelected = this.find('#check-item-action').value; + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); + if (actionSelected === 'check') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'checkItem', + checklistName, + checkItemName, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + if (actionSelected === 'uncheck') { + const triggerId = Triggers.insert(trigger); + const actionId = Actions.insert({ + actionType: 'uncheckItem', + checklistName, + checkItemName, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + } + }, }, - }]; + ]; }, - }).register('checklistActions'); diff --git a/client/components/rules/actions/mailActions.js b/client/components/rules/actions/mailActions.js index 40cbc280..87cb925c 100644 --- a/client/components/rules/actions/mailActions.js +++ b/client/components/rules/actions/mailActions.js @@ -1,35 +1,34 @@ BlazeComponent.extendComponent({ - onCreated() { - - }, + onCreated() {}, events() { - return [{ - 'click .js-mail-action' (event) { - const emailTo = this.find('#email-to').value; - const emailSubject = this.find('#email-subject').value; - const emailMsg = this.find('#email-msg').value; - const trigger = this.data().triggerVar.get(); - const ruleName = this.data().ruleName.get(); - const triggerId = Triggers.insert(trigger); - const boardId = Session.get('currentBoard'); - const desc = Utils.getTriggerActionDesc(event, this); - const actionId = Actions.insert({ - actionType: 'sendEmail', - emailTo, - emailSubject, - emailMsg, - boardId, - desc, - }); - Rules.insert({ - title: ruleName, - triggerId, - actionId, - boardId, - }); + return [ + { + 'click .js-mail-action'(event) { + const emailTo = this.find('#email-to').value; + const emailSubject = this.find('#email-subject').value; + const emailMsg = this.find('#email-msg').value; + const trigger = this.data().triggerVar.get(); + const ruleName = this.data().ruleName.get(); + const triggerId = Triggers.insert(trigger); + const boardId = Session.get('currentBoard'); + const desc = Utils.getTriggerActionDesc(event, this); + const actionId = Actions.insert({ + actionType: 'sendEmail', + emailTo, + emailSubject, + emailMsg, + boardId, + desc, + }); + Rules.insert({ + title: ruleName, + triggerId, + actionId, + boardId, + }); + }, }, - }]; + ]; }, - }).register('mailActions'); diff --git a/client/components/rules/ruleDetails.js b/client/components/rules/ruleDetails.js index 17c86dc3..f0e13de3 100644 --- a/client/components/rules/ruleDetails.js +++ b/client/components/rules/ruleDetails.js @@ -3,7 +3,6 @@ BlazeComponent.extendComponent({ this.subscribe('allRules'); this.subscribe('allTriggers'); this.subscribe('allActions'); - }, trigger() { @@ -34,5 +33,4 @@ BlazeComponent.extendComponent({ events() { return [{}]; }, - }).register('ruleDetails'); diff --git a/client/components/rules/rulesActions.js b/client/components/rules/rulesActions.js index 64a5c70e..9b4f3a71 100644 --- a/client/components/rules/rulesActions.js +++ b/client/components/rules/rulesActions.js @@ -40,19 +40,21 @@ BlazeComponent.extendComponent({ // console.log(this.data()); }, events() { - return [{ - 'click .js-set-board-actions'(){ - this.setBoardActions(); + return [ + { + 'click .js-set-board-actions'() { + this.setBoardActions(); + }, + 'click .js-set-card-actions'() { + this.setCardActions(); + }, + 'click .js-set-mail-actions'() { + this.setMailActions(); + }, + 'click .js-set-checklist-actions'() { + this.setChecklistActions(); + }, }, - 'click .js-set-card-actions'() { - this.setCardActions(); - }, - 'click .js-set-mail-actions'() { - this.setMailActions(); - }, - 'click .js-set-checklist-actions'() { - this.setChecklistActions(); - }, - }]; + ]; }, }).register('rulesActions'); diff --git a/client/components/rules/rulesMain.js b/client/components/rules/rulesMain.js index d4af38f4..99091490 100644 --- a/client/components/rules/rulesMain.js +++ b/client/components/rules/rulesMain.js @@ -9,12 +9,12 @@ BlazeComponent.extendComponent({ setTrigger() { this.rulesCurrentTab.set('trigger'); }, - sanitizeObject(obj){ - Object.keys(obj).forEach((key) => { - if(obj[key] === '' || obj[key] === undefined){ + sanitizeObject(obj) { + Object.keys(obj).forEach(key => { + if (obj[key] === '' || obj[key] === undefined) { obj[key] = '*'; - }} - ); + } + }); }, setRulesList() { this.rulesCurrentTab.set('rulesList'); @@ -29,69 +29,73 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-delete-rule' () { - const rule = this.currentData(); - Rules.remove(rule._id); - Actions.remove(rule.actionId); - Triggers.remove(rule.triggerId); - - }, - 'click .js-goto-trigger' (event) { - event.preventDefault(); - const ruleTitle = this.find('#ruleTitle').value; - if(ruleTitle !== undefined && ruleTitle !== ''){ - this.find('#ruleTitle').value = ''; - this.ruleName.set(ruleTitle); - this.setTrigger(); - } - }, - 'click .js-goto-action' (event) { - event.preventDefault(); - // Add user to the trigger - const username = $(event.currentTarget.offsetParent).find('.user-name').val(); - let trigger = this.triggerVar.get(); - trigger.userId = '*'; - if(username !== undefined ){ - const userFound = Users.findOne({username}); - if(userFound !== undefined){ - trigger.userId = userFound._id; - this.triggerVar.set(trigger); + return [ + { + 'click .js-delete-rule'() { + const rule = this.currentData(); + Rules.remove(rule._id); + Actions.remove(rule.actionId); + Triggers.remove(rule.triggerId); + }, + 'click .js-goto-trigger'(event) { + event.preventDefault(); + const ruleTitle = this.find('#ruleTitle').value; + if (ruleTitle !== undefined && ruleTitle !== '') { + this.find('#ruleTitle').value = ''; + this.ruleName.set(ruleTitle); + this.setTrigger(); } - } - // Sanitize trigger - trigger = this.triggerVar.get(); - this.sanitizeObject(trigger); - this.triggerVar.set(trigger); - this.setAction(); - }, - 'click .js-show-user-field' (event) { - event.preventDefault(); - $(event.currentTarget.offsetParent).find('.user-details').removeClass('hide-element'); - }, - 'click .js-goto-rules' (event) { - event.preventDefault(); - this.setRulesList(); - }, - 'click .js-goback' (event) { - event.preventDefault(); - if(this.rulesCurrentTab.get() === 'trigger' || this.rulesCurrentTab.get() === 'ruleDetails' ){ + }, + 'click .js-goto-action'(event) { + event.preventDefault(); + // Add user to the trigger + const username = $(event.currentTarget.offsetParent) + .find('.user-name') + .val(); + let trigger = this.triggerVar.get(); + trigger.userId = '*'; + if (username !== undefined) { + const userFound = Users.findOne({ username }); + if (userFound !== undefined) { + trigger.userId = userFound._id; + this.triggerVar.set(trigger); + } + } + // Sanitize trigger + trigger = this.triggerVar.get(); + this.sanitizeObject(trigger); + this.triggerVar.set(trigger); + this.setAction(); + }, + 'click .js-show-user-field'(event) { + event.preventDefault(); + $(event.currentTarget.offsetParent) + .find('.user-details') + .removeClass('hide-element'); + }, + 'click .js-goto-rules'(event) { + event.preventDefault(); this.setRulesList(); - } - if(this.rulesCurrentTab.get() === 'action'){ - this.setTrigger(); - } - }, - 'click .js-goto-details' (event) { - event.preventDefault(); - const rule = this.currentData(); - this.ruleId.set(rule._id); - this.setRuleDetails(); + }, + 'click .js-goback'(event) { + event.preventDefault(); + if ( + this.rulesCurrentTab.get() === 'trigger' || + this.rulesCurrentTab.get() === 'ruleDetails' + ) { + this.setRulesList(); + } + if (this.rulesCurrentTab.get() === 'action') { + this.setTrigger(); + } + }, + 'click .js-goto-details'(event) { + event.preventDefault(); + const rule = this.currentData(); + this.ruleId.set(rule._id); + this.setRuleDetails(); + }, }, - - }]; + ]; }, - }).register('rulesMain'); - - diff --git a/client/components/rules/rulesTriggers.js b/client/components/rules/rulesTriggers.js index e3c16221..a502fd37 100644 --- a/client/components/rules/rulesTriggers.js +++ b/client/components/rules/rulesTriggers.js @@ -38,16 +38,18 @@ BlazeComponent.extendComponent({ // console.log(this.data()); }, events() { - return [{ - 'click .js-set-board-triggers' () { - this.setBoardTriggers(); + return [ + { + 'click .js-set-board-triggers'() { + this.setBoardTriggers(); + }, + 'click .js-set-card-triggers'() { + this.setCardTriggers(); + }, + 'click .js-set-checklist-triggers'() { + this.setChecklistTriggers(); + }, }, - 'click .js-set-card-triggers' () { - this.setCardTriggers(); - }, - 'click .js-set-checklist-triggers' () { - this.setChecklistTriggers(); - }, - }]; + ]; }, }).register('rulesTriggers'); diff --git a/client/components/rules/triggers/boardTriggers.js b/client/components/rules/triggers/boardTriggers.js index 1dc5c437..66ee337a 100644 --- a/client/components/rules/triggers/boardTriggers.js +++ b/client/components/rules/triggers/boardTriggers.js @@ -4,116 +4,118 @@ BlazeComponent.extendComponent({ this.currentPopupTriggerId = 'def'; this.cardTitleFilters = {}; }, - setNameFilter(name){ - this.cardTitleFilters[this.currentPopupTriggerId] = name; + setNameFilter(name) { + this.cardTitleFilters[this.currentPopupTriggerId] = name; }, events() { - return [{ - 'click .js-open-card-title-popup'(event){ - const funct = Popup.open('boardCardTitle'); - const divId = $(event.currentTarget.parentNode.parentNode).attr('id'); - //console.log('current popup'); - //console.log(this.currentPopupTriggerId); - this.currentPopupTriggerId = divId; - funct.call(this, event); - }, - 'click .js-add-create-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const listName = this.find('#create-list-name').value; - const swimlaneName = this.find('#create-swimlane-name').value; - const boardId = Session.get('currentBoard'); - const divId = $(event.currentTarget.parentNode).attr('id'); - const cardTitle = this.cardTitleFilters[divId]; - // move to generic funciont - datas.triggerVar.set({ - activityType: 'createCard', - boardId, - cardTitle, - swimlaneName, - listName, - desc, - }); - }, - 'click .js-add-moved-trigger' (event) { - const datas = this.data(); - const desc = Utils.getTriggerActionDesc(event, this); - const swimlaneName = this.find('#create-swimlane-name-2').value; - const actionSelected = this.find('#move-action').value; - const listName = this.find('#move-list-name').value; - const boardId = Session.get('currentBoard'); - const divId = $(event.currentTarget.parentNode).attr('id'); - const cardTitle = this.cardTitleFilters[divId]; - if (actionSelected === 'moved-to') { + return [ + { + 'click .js-open-card-title-popup'(event) { + const funct = Popup.open('boardCardTitle'); + const divId = $(event.currentTarget.parentNode.parentNode).attr('id'); + //console.log('current popup'); + //console.log(this.currentPopupTriggerId); + this.currentPopupTriggerId = divId; + funct.call(this, event); + }, + 'click .js-add-create-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const listName = this.find('#create-list-name').value; + const swimlaneName = this.find('#create-swimlane-name').value; + const boardId = Session.get('currentBoard'); + const divId = $(event.currentTarget.parentNode).attr('id'); + const cardTitle = this.cardTitleFilters[divId]; + // move to generic funciont datas.triggerVar.set({ - activityType: 'moveCard', - boardId, - listName, - cardTitle, - swimlaneName, - 'oldListName': '*', - desc, - }); - } - if (actionSelected === 'moved-from') { - datas.triggerVar.set({ - activityType: 'moveCard', + activityType: 'createCard', boardId, cardTitle, swimlaneName, - 'listName': '*', - 'oldListName': listName, + listName, desc, }); - } - }, - 'click .js-add-gen-moved-trigger' (event){ - const datas = this.data(); - const desc = Utils.getTriggerActionDesc(event, this); - const boardId = Session.get('currentBoard'); + }, + 'click .js-add-moved-trigger'(event) { + const datas = this.data(); + const desc = Utils.getTriggerActionDesc(event, this); + const swimlaneName = this.find('#create-swimlane-name-2').value; + const actionSelected = this.find('#move-action').value; + const listName = this.find('#move-list-name').value; + const boardId = Session.get('currentBoard'); + const divId = $(event.currentTarget.parentNode).attr('id'); + const cardTitle = this.cardTitleFilters[divId]; + if (actionSelected === 'moved-to') { + datas.triggerVar.set({ + activityType: 'moveCard', + boardId, + listName, + cardTitle, + swimlaneName, + oldListName: '*', + desc, + }); + } + if (actionSelected === 'moved-from') { + datas.triggerVar.set({ + activityType: 'moveCard', + boardId, + cardTitle, + swimlaneName, + listName: '*', + oldListName: listName, + desc, + }); + } + }, + 'click .js-add-gen-moved-trigger'(event) { + const datas = this.data(); + const desc = Utils.getTriggerActionDesc(event, this); + const boardId = Session.get('currentBoard'); - datas.triggerVar.set({ - 'activityType': 'moveCard', - boardId, - 'swimlaneName': '*', - 'listName':'*', - 'oldListName': '*', - desc, - }); - }, - 'click .js-add-arc-trigger' (event) { - const datas = this.data(); - const desc = Utils.getTriggerActionDesc(event, this); - const actionSelected = this.find('#arch-action').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'archived') { datas.triggerVar.set({ - activityType: 'archivedCard', - boardId, - desc, - }); - } - if (actionSelected === 'unarchived') { - datas.triggerVar.set({ - activityType: 'restoredCard', + activityType: 'moveCard', boardId, + swimlaneName: '*', + listName: '*', + oldListName: '*', desc, }); - } + }, + 'click .js-add-arc-trigger'(event) { + const datas = this.data(); + const desc = Utils.getTriggerActionDesc(event, this); + const actionSelected = this.find('#arch-action').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'archived') { + datas.triggerVar.set({ + activityType: 'archivedCard', + boardId, + desc, + }); + } + if (actionSelected === 'unarchived') { + datas.triggerVar.set({ + activityType: 'restoredCard', + boardId, + desc, + }); + } + }, }, - - }]; + ]; }, - }).register('boardTriggers'); - Template.boardCardTitlePopup.events({ - submit(evt, tpl) { - const title = tpl.$('.js-card-filter-name').val().trim(); + submit(event, templateInstance) { + const title = templateInstance + .$('.js-card-filter-name') + .val() + .trim(); Popup.getOpenerComponent().setNameFilter(title); - evt.preventDefault(); + event.preventDefault(); Popup.close(); }, }); diff --git a/client/components/rules/triggers/cardTriggers.js b/client/components/rules/triggers/cardTriggers.js index 82b21d61..8d4ec52e 100644 --- a/client/components/rules/triggers/cardTriggers.js +++ b/client/components/rules/triggers/cardTriggers.js @@ -7,7 +7,7 @@ BlazeComponent.extendComponent({ for (let i = 0; i < labels.length; i++) { if (labels[i].name === '' || labels[i].name === undefined) { labels[i].name = labels[i].color; - labels[i].translatedname = `${TAPi18n.__(`color-${ labels[i].color}`)}`; + labels[i].translatedname = `${TAPi18n.__(`color-${labels[i].color}`)}`; } else { labels[i].translatedname = labels[i].name; } @@ -15,117 +15,119 @@ BlazeComponent.extendComponent({ return labels; }, events() { - return [{ - 'click .js-add-gen-label-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#label-action').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'added') { - datas.triggerVar.set({ - activityType: 'addedLabel', - boardId, - 'labelId': '*', - desc, - }); - } - if (actionSelected === 'removed') { - datas.triggerVar.set({ - activityType: 'removedLabel', - boardId, - 'labelId': '*', - desc, - }); - } + return [ + { + 'click .js-add-gen-label-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#label-action').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'added') { + datas.triggerVar.set({ + activityType: 'addedLabel', + boardId, + labelId: '*', + desc, + }); + } + if (actionSelected === 'removed') { + datas.triggerVar.set({ + activityType: 'removedLabel', + boardId, + labelId: '*', + desc, + }); + } + }, + 'click .js-add-spec-label-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#spec-label-action').value; + const labelId = this.find('#spec-label').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'added') { + datas.triggerVar.set({ + activityType: 'addedLabel', + boardId, + labelId, + desc, + }); + } + if (actionSelected === 'removed') { + datas.triggerVar.set({ + activityType: 'removedLabel', + boardId, + labelId, + desc, + }); + } + }, + 'click .js-add-gen-member-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#gen-member-action').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'added') { + datas.triggerVar.set({ + activityType: 'joinMember', + boardId, + username: '*', + desc, + }); + } + if (actionSelected === 'removed') { + datas.triggerVar.set({ + activityType: 'unjoinMember', + boardId, + username: '*', + desc, + }); + } + }, + 'click .js-add-spec-member-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#spec-member-action').value; + const username = this.find('#spec-member').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'added') { + datas.triggerVar.set({ + activityType: 'joinMember', + boardId, + username, + desc, + }); + } + if (actionSelected === 'removed') { + datas.triggerVar.set({ + activityType: 'unjoinMember', + boardId, + username, + desc, + }); + } + }, + 'click .js-add-attachment-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#attach-action').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'added') { + datas.triggerVar.set({ + activityType: 'addAttachment', + boardId, + desc, + }); + } + if (actionSelected === 'removed') { + datas.triggerVar.set({ + activityType: 'deleteAttachment', + boardId, + desc, + }); + } + }, }, - 'click .js-add-spec-label-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#spec-label-action').value; - const labelId = this.find('#spec-label').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'added') { - datas.triggerVar.set({ - activityType: 'addedLabel', - boardId, - labelId, - desc, - }); - } - if (actionSelected === 'removed') { - datas.triggerVar.set({ - activityType: 'removedLabel', - boardId, - labelId, - desc, - }); - } - }, - 'click .js-add-gen-member-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#gen-member-action').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'added') { - datas.triggerVar.set({ - activityType: 'joinMember', - boardId, - 'username': '*', - desc, - }); - } - if (actionSelected === 'removed') { - datas.triggerVar.set({ - activityType: 'unjoinMember', - boardId, - 'username': '*', - desc, - }); - } - }, - 'click .js-add-spec-member-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#spec-member-action').value; - const username = this.find('#spec-member').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'added') { - datas.triggerVar.set({ - activityType: 'joinMember', - boardId, - username, - desc, - }); - } - if (actionSelected === 'removed') { - datas.triggerVar.set({ - activityType: 'unjoinMember', - boardId, - username, - desc, - }); - } - }, - 'click .js-add-attachment-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#attach-action').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'added') { - datas.triggerVar.set({ - activityType: 'addAttachment', - boardId, - desc, - }); - } - if (actionSelected === 'removed') { - datas.triggerVar.set({ - activityType: 'deleteAttachment', - boardId, - desc, - }); - } - }, - }]; + ]; }, }).register('cardTriggers'); diff --git a/client/components/rules/triggers/checklistTriggers.js b/client/components/rules/triggers/checklistTriggers.js index 2272be29..9b2cd99c 100644 --- a/client/components/rules/triggers/checklistTriggers.js +++ b/client/components/rules/triggers/checklistTriggers.js @@ -3,144 +3,145 @@ BlazeComponent.extendComponent({ this.subscribe('allRules'); }, events() { - return [{ - 'click .js-add-gen-check-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#gen-check-action').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'created') { - datas.triggerVar.set({ - activityType: 'addChecklist', - boardId, - 'checklistName': '*', - desc, - }); - } - if (actionSelected === 'removed') { - datas.triggerVar.set({ - activityType: 'removeChecklist', - boardId, - 'checklistName': '*', - desc, - }); - } - }, - 'click .js-add-spec-check-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#spec-check-action').value; - const checklistId = this.find('#check-name').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'created') { - datas.triggerVar.set({ - activityType: 'addChecklist', - boardId, - 'checklistName': checklistId, - desc, - }); - } - if (actionSelected === 'removed') { - datas.triggerVar.set({ - activityType: 'removeChecklist', - boardId, - 'checklistName': checklistId, - desc, - }); - } - }, - 'click .js-add-gen-comp-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); + return [ + { + 'click .js-add-gen-check-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#gen-check-action').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'created') { + datas.triggerVar.set({ + activityType: 'addChecklist', + boardId, + checklistName: '*', + desc, + }); + } + if (actionSelected === 'removed') { + datas.triggerVar.set({ + activityType: 'removeChecklist', + boardId, + checklistName: '*', + desc, + }); + } + }, + 'click .js-add-spec-check-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#spec-check-action').value; + const checklistId = this.find('#check-name').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'created') { + datas.triggerVar.set({ + activityType: 'addChecklist', + boardId, + checklistName: checklistId, + desc, + }); + } + if (actionSelected === 'removed') { + datas.triggerVar.set({ + activityType: 'removeChecklist', + boardId, + checklistName: checklistId, + desc, + }); + } + }, + 'click .js-add-gen-comp-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#gen-comp-check-action').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'completed') { - datas.triggerVar.set({ - activityType: 'completeChecklist', - boardId, - 'checklistName': '*', - desc, - }); - } - if (actionSelected === 'uncompleted') { - datas.triggerVar.set({ - activityType: 'uncompleteChecklist', - boardId, - 'checklistName': '*', - desc, - }); - } - }, - 'click .js-add-spec-comp-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#spec-comp-check-action').value; - const checklistId = this.find('#spec-comp-check-name').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'completed') { - datas.triggerVar.set({ - activityType: 'completeChecklist', - boardId, - 'checklistName': checklistId, - desc, - }); - } - if (actionSelected === 'uncompleted') { - datas.triggerVar.set({ - activityType: 'uncompleteChecklist', - boardId, - 'checklistName': checklistId, - desc, - }); - } + const datas = this.data(); + const actionSelected = this.find('#gen-comp-check-action').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'completed') { + datas.triggerVar.set({ + activityType: 'completeChecklist', + boardId, + checklistName: '*', + desc, + }); + } + if (actionSelected === 'uncompleted') { + datas.triggerVar.set({ + activityType: 'uncompleteChecklist', + boardId, + checklistName: '*', + desc, + }); + } + }, + 'click .js-add-spec-comp-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#spec-comp-check-action').value; + const checklistId = this.find('#spec-comp-check-name').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'completed') { + datas.triggerVar.set({ + activityType: 'completeChecklist', + boardId, + checklistName: checklistId, + desc, + }); + } + if (actionSelected === 'uncompleted') { + datas.triggerVar.set({ + activityType: 'uncompleteChecklist', + boardId, + checklistName: checklistId, + desc, + }); + } + }, + 'click .js-add-gen-check-item-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#check-item-gen-action').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'checked') { + datas.triggerVar.set({ + activityType: 'checkedItem', + boardId, + checklistItemName: '*', + desc, + }); + } + if (actionSelected === 'unchecked') { + datas.triggerVar.set({ + activityType: 'uncheckedItem', + boardId, + checklistItemName: '*', + desc, + }); + } + }, + 'click .js-add-spec-check-item-trigger'(event) { + const desc = Utils.getTriggerActionDesc(event, this); + const datas = this.data(); + const actionSelected = this.find('#check-item-spec-action').value; + const checklistItemId = this.find('#check-item-name').value; + const boardId = Session.get('currentBoard'); + if (actionSelected === 'checked') { + datas.triggerVar.set({ + activityType: 'checkedItem', + boardId, + checklistItemName: checklistItemId, + desc, + }); + } + if (actionSelected === 'unchecked') { + datas.triggerVar.set({ + activityType: 'uncheckedItem', + boardId, + checklistItemName: checklistItemId, + desc, + }); + } + }, }, - 'click .js-add-gen-check-item-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#check-item-gen-action').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'checked') { - datas.triggerVar.set({ - activityType: 'checkedItem', - boardId, - 'checklistItemName': '*', - desc, - }); - } - if (actionSelected === 'unchecked') { - datas.triggerVar.set({ - activityType: 'uncheckedItem', - boardId, - 'checklistItemName': '*', - desc, - }); - } - }, - 'click .js-add-spec-check-item-trigger' (event) { - const desc = Utils.getTriggerActionDesc(event, this); - const datas = this.data(); - const actionSelected = this.find('#check-item-spec-action').value; - const checklistItemId = this.find('#check-item-name').value; - const boardId = Session.get('currentBoard'); - if (actionSelected === 'checked') { - datas.triggerVar.set({ - activityType: 'checkedItem', - boardId, - 'checklistItemName': checklistItemId, - desc, - }); - } - if (actionSelected === 'unchecked') { - datas.triggerVar.set({ - activityType: 'uncheckedItem', - boardId, - 'checklistItemName': checklistItemId, - desc, - }); - } - }, - }]; + ]; }, - }).register('checklistTriggers'); diff --git a/client/components/settings/connectionMethod.js b/client/components/settings/connectionMethod.js index db9da25f..6abfd743 100644 --- a/client/components/settings/connectionMethod.js +++ b/client/components/settings/connectionMethod.js @@ -6,9 +6,11 @@ Template.connectionMethod.onCreated(function() { // TODO : add a management of different languages // (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')}) this.authenticationMethods.set([ - {value: 'password'}, + { value: 'password' }, // Gets only the authentication methods availables - ...Object.entries(result).filter((e) => e[1]).map((e) => ({value: e[0]})), + ...Object.entries(result) + .filter(e => e[1]) + .map(e => ({ value: e[0] })), ]); } @@ -24,7 +26,9 @@ Template.connectionMethod.onCreated(function() { Template.connectionMethod.onRendered(() => { // Moves the select boxe in the first place of the at-pwd-form div - $('.at-form-authentication').detach().prependTo('.at-pwd-form'); + $('.at-form-authentication') + .detach() + .prependTo('.at-pwd-form'); }); Template.connectionMethod.helpers({ diff --git a/client/components/settings/peopleBody.js b/client/components/settings/peopleBody.js index 83cf14fa..b09f6599 100644 --- a/client/components/settings/peopleBody.js +++ b/client/components/settings/peopleBody.js @@ -29,19 +29,23 @@ BlazeComponent.extendComponent({ }); }, events() { - return [{ - 'click #searchButton'() { - this.filterPeople(); - }, - 'keydown #searchInput'(event) { - if (event.keyCode === 13 && !event.shiftKey) { + return [ + { + 'click #searchButton'() { this.filterPeople(); - } + }, + 'keydown #searchInput'(event) { + if (event.keyCode === 13 && !event.shiftKey) { + this.filterPeople(); + } + }, }, - }]; + ]; }, filterPeople() { - const value = $('#searchInput').first().val(); + const value = $('#searchInput') + .first() + .val(); if (value === '') { this.findUsersOptions.set({}); } else { @@ -79,7 +83,7 @@ BlazeComponent.extendComponent({ }, peopleList() { const users = Users.find(this.findUsersOptions.get(), { - fields: {_id: true}, + fields: { _id: true }, }); this.number.set(users.count()); return users; @@ -105,9 +109,11 @@ Template.editUserPopup.onCreated(function() { // TODO : add a management of different languages // (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')}) this.authenticationMethods.set([ - {value: 'password'}, + { value: 'password' }, // Gets only the authentication methods availables - ...Object.entries(result).filter((e) => e[1]).map((e) => ({value: e[0]})), + ...Object.entries(result) + .filter(e => e[1]) + .map(e => ({ value: e[0] })), ]); } }); @@ -136,69 +142,79 @@ Template.editUserPopup.helpers({ }); BlazeComponent.extendComponent({ - onCreated() { - }, + onCreated() {}, user() { return Users.findOne(this.userId); }, events() { - return [{ - 'click a.edit-user': Popup.open('editUser'), - }]; + return [ + { + 'click a.edit-user': Popup.open('editUser'), + }, + ]; }, }).register('peopleRow'); Template.editUserPopup.events({ - submit(evt, tpl) { - evt.preventDefault(); + submit(event, templateInstance) { + event.preventDefault(); const user = Users.findOne(this.userId); - const fullname = tpl.find('.js-profile-fullname').value.trim(); - const username = tpl.find('.js-profile-username').value.trim(); - const password = tpl.find('.js-profile-password').value; - const isAdmin = tpl.find('.js-profile-isadmin').value.trim(); - const isActive = tpl.find('.js-profile-isactive').value.trim(); - const email = tpl.find('.js-profile-email').value.trim(); - const authentication = tpl.find('.js-authenticationMethod').value.trim(); + const fullname = templateInstance.find('.js-profile-fullname').value.trim(); + const username = templateInstance.find('.js-profile-username').value.trim(); + const password = templateInstance.find('.js-profile-password').value; + const isAdmin = templateInstance.find('.js-profile-isadmin').value.trim(); + const isActive = templateInstance.find('.js-profile-isactive').value.trim(); + const email = templateInstance.find('.js-profile-email').value.trim(); + const authentication = templateInstance + .find('.js-authenticationMethod') + .value.trim(); const isChangePassword = password.length > 0; const isChangeUserName = username !== user.username; - const isChangeEmail = email.toLowerCase() !== user.emails[0].address.toLowerCase(); + const isChangeEmail = + email.toLowerCase() !== user.emails[0].address.toLowerCase(); Users.update(this.userId, { $set: { 'profile.fullname': fullname, - 'isAdmin': isAdmin === 'true', - 'loginDisabled': isActive === 'true', - 'authenticationMethod': authentication, + isAdmin: isAdmin === 'true', + loginDisabled: isActive === 'true', + authenticationMethod: authentication, }, }); - if(isChangePassword){ + if (isChangePassword) { Meteor.call('setPassword', password, this.userId); } if (isChangeUserName && isChangeEmail) { - Meteor.call('setUsernameAndEmail', username, email.toLowerCase(), this.userId, function (error) { - const usernameMessageElement = tpl.$('.username-taken'); - const emailMessageElement = tpl.$('.email-taken'); - if (error) { - const errorElement = error.error; - if (errorElement === 'username-already-taken') { - usernameMessageElement.show(); - emailMessageElement.hide(); - } else if (errorElement === 'email-already-taken') { + Meteor.call( + 'setUsernameAndEmail', + username, + email.toLowerCase(), + this.userId, + function(error) { + const usernameMessageElement = templateInstance.$('.username-taken'); + const emailMessageElement = templateInstance.$('.email-taken'); + if (error) { + const errorElement = error.error; + if (errorElement === 'username-already-taken') { + usernameMessageElement.show(); + emailMessageElement.hide(); + } else if (errorElement === 'email-already-taken') { + usernameMessageElement.hide(); + emailMessageElement.show(); + } + } else { usernameMessageElement.hide(); - emailMessageElement.show(); + emailMessageElement.hide(); + Popup.close(); } - } else { - usernameMessageElement.hide(); - emailMessageElement.hide(); - Popup.close(); - } - }); + }, + ); } else if (isChangeUserName) { - Meteor.call('setUsername', username, this.userId, function (error) { - const usernameMessageElement = tpl.$('.username-taken'); + Meteor.call('setUsername', username, this.userId, function(error) { + const usernameMessageElement = templateInstance.$('.username-taken'); if (error) { const errorElement = error.error; if (errorElement === 'username-already-taken') { @@ -210,8 +226,10 @@ Template.editUserPopup.events({ } }); } else if (isChangeEmail) { - Meteor.call('setEmail', email.toLowerCase(), this.userId, function (error) { - const emailMessageElement = tpl.$('.email-taken'); + Meteor.call('setEmail', email.toLowerCase(), this.userId, function( + error, + ) { + const emailMessageElement = templateInstance.$('.email-taken'); if (error) { const errorElement = error.error; if (errorElement === 'email-already-taken') { diff --git a/client/components/settings/settingBody.js b/client/components/settings/settingBody.js index 8279a092..4ec0c759 100644 --- a/client/components/settings/settingBody.js +++ b/client/components/settings/settingBody.js @@ -25,7 +25,9 @@ BlazeComponent.extendComponent({ checkField(selector) { const value = $(selector).val(); if (!value || value.trim() === '') { - $(selector).parents('li.smtp-form').addClass('has-error'); + $(selector) + .parents('li.smtp-form') + .addClass('has-error'); throw Error('blank field'); } else { return value; @@ -37,18 +39,23 @@ BlazeComponent.extendComponent({ }, boards() { - return Boards.find({ - archived: false, - 'members.userId': Meteor.userId(), - 'members.isAdmin': true, - }, { - sort: ['title'], - }); + return Boards.find( + { + archived: false, + 'members.userId': Meteor.userId(), + 'members.isAdmin': true, + }, + { + sort: ['title'], + }, + ); }, toggleRegistration() { this.setLoading(true); const registrationClosed = this.currentSetting().disableRegistration; - Settings.update(Settings.findOne()._id, {$set: {disableRegistration: !registrationClosed}}); + Settings.update(Settings.findOne()._id, { + $set: { disableRegistration: !registrationClosed }, + }); this.setLoading(false); if (registrationClosed) { $('.invite-people').slideUp(); @@ -90,13 +97,19 @@ BlazeComponent.extendComponent({ }, inviteThroughEmail() { - const emails = $('#email-to-invite').val().toLowerCase().trim().split('\n').join(',').split(','); + const emails = $('#email-to-invite') + .val() + .toLowerCase() + .trim() + .split('\n') + .join(',') + .split(','); const boardsToInvite = []; - $('.js-toggle-board-choose .materialCheckBox.is-checked').each(function () { + $('.js-toggle-board-choose .materialCheckBox.is-checked').each(function() { boardsToInvite.push($(this).data('id')); }); const validEmails = []; - emails.forEach((email) => { + emails.forEach(email => { if (email && SimpleSchema.RegEx.Email.test(email.trim())) { validEmails.push(email.trim()); } @@ -119,14 +132,22 @@ BlazeComponent.extendComponent({ try { const host = this.checkField('#mail-server-host'); const port = this.checkField('#mail-server-port'); - const username = $('#mail-server-username').val().trim(); - const password = $('#mail-server-password').val().trim(); + const username = $('#mail-server-username') + .val() + .trim(); + const password = $('#mail-server-password') + .val() + .trim(); const from = this.checkField('#mail-server-from'); const tls = $('#mail-server-tls.is-checked').length > 0; Settings.update(Settings.findOne()._id, { $set: { - 'mailServer.host': host, 'mailServer.port': port, 'mailServer.username': username, - 'mailServer.password': password, 'mailServer.enableTLS': tls, 'mailServer.from': from, + 'mailServer.host': host, + 'mailServer.port': port, + 'mailServer.username': username, + 'mailServer.password': password, + 'mailServer.enableTLS': tls, + 'mailServer.from': from, }, }); } catch (e) { @@ -134,19 +155,25 @@ BlazeComponent.extendComponent({ } finally { this.setLoading(false); } - }, saveLayout() { this.setLoading(true); $('li').removeClass('has-error'); - const productName = $('#product-name').val().trim(); - const hideLogoChange = ($('input[name=hideLogo]:checked').val() === 'true'); - const displayAuthenticationMethod = ($('input[name=displayAuthenticationMethod]:checked').val() === 'true'); + const productName = $('#product-name') + .val() + .trim(); + const hideLogoChange = $('input[name=hideLogo]:checked').val() === 'true'; + const displayAuthenticationMethod = + $('input[name=displayAuthenticationMethod]:checked').val() === 'true'; const defaultAuthenticationMethod = $('#defaultAuthenticationMethod').val(); - const customHTMLafterBodyStart = $('#customHTMLafterBodyStart').val().trim(); - const customHTMLbeforeBodyEnd = $('#customHTMLbeforeBodyEnd').val().trim(); + const customHTMLafterBodyStart = $('#customHTMLafterBodyStart') + .val() + .trim(); + const customHTMLbeforeBodyEnd = $('#customHTMLbeforeBodyEnd') + .val() + .trim(); try { Settings.update(Settings.findOne()._id, { @@ -166,7 +193,6 @@ BlazeComponent.extendComponent({ } DocHead.setTitle(productName); - }, sendSMTPTestEmail() { @@ -183,31 +209,35 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click a.js-toggle-registration': this.toggleRegistration, - 'click a.js-toggle-tls': this.toggleTLS, - 'click a.js-setting-menu': this.switchMenu, - 'click a.js-toggle-board-choose': this.checkBoard, - 'click button.js-email-invite': this.inviteThroughEmail, - 'click button.js-save': this.saveMailServerInfo, - 'click button.js-send-smtp-test-email': this.sendSMTPTestEmail, - 'click a.js-toggle-hide-logo': this.toggleHideLogo, - 'click button.js-save-layout': this.saveLayout, - 'click a.js-toggle-display-authentication-method': this.toggleDisplayAuthenticationMethod, - }]; + return [ + { + 'click a.js-toggle-registration': this.toggleRegistration, + 'click a.js-toggle-tls': this.toggleTLS, + 'click a.js-setting-menu': this.switchMenu, + 'click a.js-toggle-board-choose': this.checkBoard, + 'click button.js-email-invite': this.inviteThroughEmail, + 'click button.js-save': this.saveMailServerInfo, + 'click button.js-send-smtp-test-email': this.sendSMTPTestEmail, + 'click a.js-toggle-hide-logo': this.toggleHideLogo, + 'click button.js-save-layout': this.saveLayout, + 'click a.js-toggle-display-authentication-method': this + .toggleDisplayAuthenticationMethod, + }, + ]; }, }).register('setting'); BlazeComponent.extendComponent({ - saveAccountsChange() { - const allowEmailChange = ($('input[name=allowEmailChange]:checked').val() === 'true'); - const allowUserNameChange = ($('input[name=allowUserNameChange]:checked').val() === 'true'); + const allowEmailChange = + $('input[name=allowEmailChange]:checked').val() === 'true'; + const allowUserNameChange = + $('input[name=allowUserNameChange]:checked').val() === 'true'; AccountSettings.update('accounts-allowEmailChange', { - $set: {'booleanValue': allowEmailChange}, + $set: { booleanValue: allowEmailChange }, }); AccountSettings.update('accounts-allowUserNameChange', { - $set: {'booleanValue': allowUserNameChange}, + $set: { booleanValue: allowUserNameChange }, }); }, @@ -219,9 +249,11 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click button.js-accounts-save': this.saveAccountsChange, - }]; + return [ + { + 'click button.js-accounts-save': this.saveAccountsChange, + }, + ]; }, }).register('accountSettings'); @@ -239,9 +271,11 @@ BlazeComponent.extendComponent({ }, saveMessage() { - const message = $('#admin-announcement').val().trim(); + const message = $('#admin-announcement') + .val() + .trim(); Announcements.update(Announcements.findOne()._id, { - $set: {'body': message}, + $set: { body: message }, }); }, @@ -249,7 +283,7 @@ BlazeComponent.extendComponent({ this.setLoading(true); const isActive = this.currentSetting().enabled; Announcements.update(Announcements.findOne()._id, { - $set: {'enabled': !isActive}, + $set: { enabled: !isActive }, }); this.setLoading(false); if (isActive) { @@ -260,14 +294,15 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click a.js-toggle-activemessage': this.toggleActive, - 'click button.js-announcement-save': this.saveMessage, - }]; + return [ + { + 'click a.js-toggle-activemessage': this.toggleActive, + 'click button.js-announcement-save': this.saveMessage, + }, + ]; }, }).register('announcementSettings'); - Template.selectAuthenticationMethod.onCreated(function() { this.authenticationMethods = new ReactiveVar([]); @@ -276,9 +311,11 @@ Template.selectAuthenticationMethod.onCreated(function() { // TODO : add a management of different languages // (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')}) this.authenticationMethods.set([ - {value: 'password'}, + { value: 'password' }, // Gets only the authentication methods availables - ...Object.entries(result).filter((e) => e[1]).map((e) => ({value: e[0]})), + ...Object.entries(result) + .filter(e => e[1]) + .map(e => ({ value: e[0] })), ]); } }); diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js index e8de3c96..8468595a 100644 --- a/client/components/sidebar/sidebar.js +++ b/client/components/sidebar/sidebar.js @@ -91,29 +91,34 @@ BlazeComponent.extendComponent({ }, showTongueTitle() { - if (this.isOpen()) - return `${TAPi18n.__('sidebar-close')}`; - else - return `${TAPi18n.__('sidebar-open')}`; + if (this.isOpen()) return `${TAPi18n.__('sidebar-close')}`; + else return `${TAPi18n.__('sidebar-open')}`; }, events() { - return [{ - 'click .js-hide-sidebar': this.hide, - 'click .js-toggle-sidebar': this.toggle, - 'click .js-back-home': this.setView, - 'click .js-shortcuts'() { - FlowRouter.go('shortcuts'); + return [ + { + 'click .js-hide-sidebar': this.hide, + 'click .js-toggle-sidebar': this.toggle, + 'click .js-back-home': this.setView, + 'click .js-shortcuts'() { + FlowRouter.go('shortcuts'); + }, }, - }]; + ]; }, }).register('sidebar'); Blaze.registerHelper('Sidebar', () => Sidebar); -EscapeActions.register('sidebarView', - () => { Sidebar.setView(defaultView); }, - () => { return Sidebar && Sidebar.getView() !== defaultView; } +EscapeActions.register( + 'sidebarView', + () => { + Sidebar.setView(defaultView); + }, + () => { + return Sidebar && Sidebar.getView() !== defaultView; + }, ); Template.memberPopup.helpers({ @@ -122,13 +127,13 @@ Template.memberPopup.helpers({ }, memberType() { const type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal'; - if(type === 'normal'){ + if (type === 'normal') { const currentBoard = Boards.findOne(Session.get('currentBoard')); const commentOnly = currentBoard.hasCommentOnly(this.userId); const noComments = currentBoard.hasNoComments(this.userId); - if(commentOnly){ + if (commentOnly) { return TAPi18n.__('comment-only').toLowerCase(); - } else if(noComments) { + } else if (noComments) { return TAPi18n.__('no-comments').toLowerCase(); } else { return TAPi18n.__(type).toLowerCase(); @@ -197,7 +202,7 @@ Template.memberPopup.events({ 'click .js-remove-member': Popup.afterConfirm('removeMember', function() { const boardId = Session.get('currentBoard'); const memberId = this.userId; - Cards.find({ boardId, members: memberId }).forEach((card) => { + Cards.find({ boardId, members: memberId }).forEach(card => { card.unassignMember(memberId); }); Boards.findOne(boardId).removeMember(memberId); @@ -274,38 +279,40 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'submit'(evt) { - evt.preventDefault(); - const url = evt.target.url.value; - const boardId = Session.get('currentBoard'); - let id = null; - let integration = null; - if (evt.target.id) { - id = evt.target.id.value; - integration = this.integration(id); - if (url) { - Integrations.update(integration._id, { - $set: { - url: `${url}`, - }, + return [ + { + submit(evt) { + evt.preventDefault(); + const url = evt.target.url.value; + const boardId = Session.get('currentBoard'); + let id = null; + let integration = null; + if (evt.target.id) { + id = evt.target.id.value; + integration = this.integration(id); + if (url) { + Integrations.update(integration._id, { + $set: { + url: `${url}`, + }, + }); + } else { + Integrations.remove(integration._id); + } + } else if (url) { + Integrations.insert({ + userId: Meteor.userId(), + enabled: true, + type: 'outgoing-webhooks', + url: `${url}`, + boardId: `${boardId}`, + activities: ['all'], }); - } else { - Integrations.remove(integration._id); } - } else if (url) { - Integrations.insert({ - userId: Meteor.userId(), - enabled: true, - type: 'outgoing-webhooks', - url: `${url}`, - boardId: `${boardId}`, - activities: ['all'], - }); - } - Popup.close(); + Popup.close(); + }, }, - }]; + ]; }, }).register('outgoingWebhooksPopup'); @@ -375,14 +382,16 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-select-background'(evt) { - const currentBoard = Boards.findOne(Session.get('currentBoard')); - const newColor = this.currentData().toString(); - currentBoard.setColor(newColor); - evt.preventDefault(); + return [ + { + 'click .js-select-background'(evt) { + const currentBoard = Boards.findOne(Session.get('currentBoard')); + const newColor = this.currentData().toString(); + currentBoard.setColor(newColor); + evt.preventDefault(); + }, }, - }]; + ]; }, }).register('boardChangeColorPopup'); @@ -400,25 +409,34 @@ BlazeComponent.extendComponent({ }, isNullBoardSelected() { - return (this.currentBoard.subtasksDefaultBoardId === null) || (this.currentBoard.subtasksDefaultBoardId === undefined); + return ( + this.currentBoard.subtasksDefaultBoardId === null || + this.currentBoard.subtasksDefaultBoardId === undefined + ); }, boards() { - return Boards.find({ - archived: false, - 'members.userId': Meteor.userId(), - }, { - sort: ['title'], - }); + return Boards.find( + { + archived: false, + 'members.userId': Meteor.userId(), + }, + { + sort: ['title'], + }, + ); }, lists() { - return Lists.find({ - boardId: this.currentBoard._id, - archived: false, - }, { - sort: ['title'], - }); + return Lists.find( + { + boardId: this.currentBoard._id, + archived: false, + }, + { + sort: ['title'], + }, + ); }, hasLists() { @@ -431,54 +449,74 @@ BlazeComponent.extendComponent({ presentParentTask() { let result = this.currentBoard.presentParentTask; - if ((result === null) || (result === undefined)) { + if (result === null || result === undefined) { result = 'no-parent'; } return result; }, events() { - return [{ - 'click .js-field-has-subtasks'(evt) { - evt.preventDefault(); - this.currentBoard.allowsSubtasks = !this.currentBoard.allowsSubtasks; - this.currentBoard.setAllowsSubtasks(this.currentBoard.allowsSubtasks); - $('.js-field-has-subtasks .materialCheckBox').toggleClass('is-checked', this.currentBoard.allowsSubtasks); - $('.js-field-has-subtasks').toggleClass('is-checked', this.currentBoard.allowsSubtasks); - $('.js-field-deposit-board').prop('disabled', !this.currentBoard.allowsSubtasks); - }, - 'change .js-field-deposit-board'(evt) { - let value = evt.target.value; - if (value === 'null') { - value = null; - } - this.currentBoard.setSubtasksDefaultBoardId(value); - evt.preventDefault(); - }, - 'change .js-field-deposit-list'(evt) { - this.currentBoard.setSubtasksDefaultListId(evt.target.value); - evt.preventDefault(); - }, - 'click .js-field-show-parent-in-minicard'(evt) { - const value = evt.target.id || $(evt.target).parent()[0].id || $(evt.target).parent()[0].parent()[0].id; - const options = [ - 'prefix-with-full-path', - 'prefix-with-parent', - 'subtext-with-full-path', - 'subtext-with-parent', - 'no-parent']; - options.forEach(function(element) { - if (element !== value) { - $(`#${element} .materialCheckBox`).toggleClass('is-checked', false); - $(`#${element}`).toggleClass('is-checked', false); + return [ + { + 'click .js-field-has-subtasks'(evt) { + evt.preventDefault(); + this.currentBoard.allowsSubtasks = !this.currentBoard.allowsSubtasks; + this.currentBoard.setAllowsSubtasks(this.currentBoard.allowsSubtasks); + $('.js-field-has-subtasks .materialCheckBox').toggleClass( + 'is-checked', + this.currentBoard.allowsSubtasks, + ); + $('.js-field-has-subtasks').toggleClass( + 'is-checked', + this.currentBoard.allowsSubtasks, + ); + $('.js-field-deposit-board').prop( + 'disabled', + !this.currentBoard.allowsSubtasks, + ); + }, + 'change .js-field-deposit-board'(evt) { + let value = evt.target.value; + if (value === 'null') { + value = null; } - }); - $(`#${value} .materialCheckBox`).toggleClass('is-checked', true); - $(`#${value}`).toggleClass('is-checked', true); - this.currentBoard.setPresentParentTask(value); - evt.preventDefault(); + this.currentBoard.setSubtasksDefaultBoardId(value); + evt.preventDefault(); + }, + 'change .js-field-deposit-list'(evt) { + this.currentBoard.setSubtasksDefaultListId(evt.target.value); + evt.preventDefault(); + }, + 'click .js-field-show-parent-in-minicard'(evt) { + const value = + evt.target.id || + $(evt.target).parent()[0].id || + $(evt.target) + .parent()[0] + .parent()[0].id; + const options = [ + 'prefix-with-full-path', + 'prefix-with-parent', + 'subtext-with-full-path', + 'subtext-with-parent', + 'no-parent', + ]; + options.forEach(function(element) { + if (element !== value) { + $(`#${element} .materialCheckBox`).toggleClass( + 'is-checked', + false, + ); + $(`#${element}`).toggleClass('is-checked', false); + } + }); + $(`#${value} .materialCheckBox`).toggleClass('is-checked', true); + $(`#${value}`).toggleClass('is-checked', true); + this.currentBoard.setPresentParentTask(value); + evt.preventDefault(); + }, }, - }]; + ]; }, }).register('boardSubtaskSettingsPopup'); @@ -528,35 +566,46 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'keyup input'() { - this.setError(''); - }, - 'click .js-select-member'() { - const userId = this.currentData()._id; - const currentBoard = Boards.findOne(Session.get('currentBoard')); - if (!currentBoard.hasMember(userId)) { - this.inviteUser(userId); - } - }, - 'click .js-email-invite'() { - const idNameEmail = $('.js-search-member input').val(); - if (idNameEmail.indexOf('@')<0 || this.isValidEmail(idNameEmail)) { - this.inviteUser(idNameEmail); - } else this.setError('email-invalid'); + return [ + { + 'keyup input'() { + this.setError(''); + }, + 'click .js-select-member'() { + const userId = this.currentData()._id; + const currentBoard = Boards.findOne(Session.get('currentBoard')); + if (!currentBoard.hasMember(userId)) { + this.inviteUser(userId); + } + }, + 'click .js-email-invite'() { + const idNameEmail = $('.js-search-member input').val(); + if (idNameEmail.indexOf('@') < 0 || this.isValidEmail(idNameEmail)) { + this.inviteUser(idNameEmail); + } else this.setError('email-invalid'); + }, }, - }]; + ]; }, }).register('addMemberPopup'); Template.changePermissionsPopup.events({ - 'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only'(event) { + 'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only'( + event, + ) { const currentBoard = Boards.findOne(Session.get('currentBoard')); const memberId = this.userId; const isAdmin = $(event.currentTarget).hasClass('js-set-admin'); - const isCommentOnly = $(event.currentTarget).hasClass('js-set-comment-only'); + const isCommentOnly = $(event.currentTarget).hasClass( + 'js-set-comment-only', + ); const isNoComments = $(event.currentTarget).hasClass('js-set-no-comments'); - currentBoard.setMemberPermission(memberId, isAdmin, isNoComments, isCommentOnly); + currentBoard.setMemberPermission( + memberId, + isAdmin, + isNoComments, + isCommentOnly, + ); Popup.back(1); }, }); @@ -569,21 +618,33 @@ Template.changePermissionsPopup.helpers({ isNormal() { const currentBoard = Boards.findOne(Session.get('currentBoard')); - return !currentBoard.hasAdmin(this.userId) && !currentBoard.hasNoComments(this.userId) && !currentBoard.hasCommentOnly(this.userId); + return ( + !currentBoard.hasAdmin(this.userId) && + !currentBoard.hasNoComments(this.userId) && + !currentBoard.hasCommentOnly(this.userId) + ); }, isNoComments() { const currentBoard = Boards.findOne(Session.get('currentBoard')); - return !currentBoard.hasAdmin(this.userId) && currentBoard.hasNoComments(this.userId); + return ( + !currentBoard.hasAdmin(this.userId) && + currentBoard.hasNoComments(this.userId) + ); }, isCommentOnly() { const currentBoard = Boards.findOne(Session.get('currentBoard')); - return !currentBoard.hasAdmin(this.userId) && currentBoard.hasCommentOnly(this.userId); + return ( + !currentBoard.hasAdmin(this.userId) && + currentBoard.hasCommentOnly(this.userId) + ); }, isLastAdmin() { const currentBoard = Boards.findOne(Session.get('currentBoard')); - return currentBoard.hasAdmin(this.userId) && (currentBoard.activeAdmins() === 1); + return ( + currentBoard.hasAdmin(this.userId) && currentBoard.activeAdmins() === 1 + ); }, }); diff --git a/client/components/sidebar/sidebarArchives.js b/client/components/sidebar/sidebarArchives.js index 546d7e1a..53fc29b9 100644 --- a/client/components/sidebar/sidebarArchives.js +++ b/client/components/sidebar/sidebarArchives.js @@ -10,12 +10,11 @@ BlazeComponent.extendComponent({ // unfortunatly, Blaze doesn't have this notion. this.autorun(() => { const currentBoardId = Session.get('currentBoard'); - if (!currentBoardId) - return; + if (!currentBoardId) return; const handle = subManager.subscribe('board', currentBoardId, true); Tracker.nonreactive(() => { Tracker.autorun(() => { - this.isArchiveReady.set( handle.ready() ); + this.isArchiveReady.set(handle.ready()); }); }); }); @@ -59,74 +58,82 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-restore-card'() { - const card = this.currentData(); - if(card.canBeRestored()){ - card.restore(); - } - }, - 'click .js-restore-all-cards'() { - this.archivedCards().forEach((card) => { - if(card.canBeRestored()){ + return [ + { + 'click .js-restore-card'() { + const card = this.currentData(); + if (card.canBeRestored()) { card.restore(); } - }); - }, + }, + 'click .js-restore-all-cards'() { + this.archivedCards().forEach(card => { + if (card.canBeRestored()) { + card.restore(); + } + }); + }, - 'click .js-delete-card': Popup.afterConfirm('cardDelete', function() { - const cardId = this._id; - Cards.remove(cardId); - Popup.close(); - }), - 'click .js-delete-all-cards': Popup.afterConfirm('cardDelete', () => { - this.archivedCards().forEach((card) => { - Cards.remove(card._id); - }); - Popup.close(); - }), + 'click .js-delete-card': Popup.afterConfirm('cardDelete', function() { + const cardId = this._id; + Cards.remove(cardId); + Popup.close(); + }), + 'click .js-delete-all-cards': Popup.afterConfirm('cardDelete', () => { + this.archivedCards().forEach(card => { + Cards.remove(card._id); + }); + Popup.close(); + }), - 'click .js-restore-list'() { - const list = this.currentData(); - list.restore(); - }, - 'click .js-restore-all-lists'() { - this.archivedLists().forEach((list) => { + 'click .js-restore-list'() { + const list = this.currentData(); list.restore(); - }); - }, + }, + 'click .js-restore-all-lists'() { + this.archivedLists().forEach(list => { + list.restore(); + }); + }, - 'click .js-delete-list': Popup.afterConfirm('listDelete', function() { - this.remove(); - Popup.close(); - }), - 'click .js-delete-all-lists': Popup.afterConfirm('listDelete', () => { - this.archivedLists().forEach((list) => { - list.remove(); - }); - Popup.close(); - }), + 'click .js-delete-list': Popup.afterConfirm('listDelete', function() { + this.remove(); + Popup.close(); + }), + 'click .js-delete-all-lists': Popup.afterConfirm('listDelete', () => { + this.archivedLists().forEach(list => { + list.remove(); + }); + Popup.close(); + }), - 'click .js-restore-swimlane'() { - const swimlane = this.currentData(); - swimlane.restore(); - }, - 'click .js-restore-all-swimlanes'() { - this.archivedSwimlanes().forEach((swimlane) => { + 'click .js-restore-swimlane'() { + const swimlane = this.currentData(); swimlane.restore(); - }); - }, + }, + 'click .js-restore-all-swimlanes'() { + this.archivedSwimlanes().forEach(swimlane => { + swimlane.restore(); + }); + }, - 'click .js-delete-swimlane': Popup.afterConfirm('swimlaneDelete', function() { - this.remove(); - Popup.close(); - }), - 'click .js-delete-all-swimlanes': Popup.afterConfirm('swimlaneDelete', () => { - this.archivedSwimlanes().forEach((swimlane) => { - swimlane.remove(); - }); - Popup.close(); - }), - }]; + 'click .js-delete-swimlane': Popup.afterConfirm( + 'swimlaneDelete', + function() { + this.remove(); + Popup.close(); + }, + ), + 'click .js-delete-all-swimlanes': Popup.afterConfirm( + 'swimlaneDelete', + () => { + this.archivedSwimlanes().forEach(swimlane => { + swimlane.remove(); + }); + Popup.close(); + }, + ), + }, + ]; }, }).register('archivesSidebar'); diff --git a/client/components/sidebar/sidebarCustomFields.js b/client/components/sidebar/sidebarCustomFields.js index 28af973b..92e93641 100644 --- a/client/components/sidebar/sidebarCustomFields.js +++ b/client/components/sidebar/sidebarCustomFields.js @@ -1,37 +1,43 @@ BlazeComponent.extendComponent({ - customFields() { return CustomFields.find({ - boardIds: {$in: [Session.get('currentBoard')]}, + boardIds: { $in: [Session.get('currentBoard')] }, }); }, events() { - return [{ - 'click .js-open-create-custom-field': Popup.open('createCustomField'), - 'click .js-edit-custom-field': Popup.open('editCustomField'), - }]; + return [ + { + 'click .js-open-create-custom-field': Popup.open('createCustomField'), + 'click .js-edit-custom-field': Popup.open('editCustomField'), + }, + ]; }, - }).register('customFieldsSidebar'); const CreateCustomFieldPopup = BlazeComponent.extendComponent({ - _types: ['text', 'number', 'date', 'dropdown'], onCreated() { - this.type = new ReactiveVar((this.data().type) ? this.data().type : this._types[0]); - this.dropdownItems = new ReactiveVar((this.data().settings && this.data().settings.dropdownItems) ? this.data().settings.dropdownItems : []); + this.type = new ReactiveVar( + this.data().type ? this.data().type : this._types[0], + ); + this.dropdownItems = new ReactiveVar( + this.data().settings && this.data().settings.dropdownItems + ? this.data().settings.dropdownItems + : [], + ); }, types() { const currentType = this.data().type; - return this._types. - map((type) => {return { + return this._types.map(type => { + return { value: type, name: TAPi18n.__(`custom-field-${type}`), selected: type === currentType, - };}); + }; + }); }, isTypeNotSelected(type) { @@ -40,113 +46,122 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({ getDropdownItems() { const items = this.dropdownItems.get(); - Array.from(this.findAll('.js-field-settings-dropdown input')).forEach((el, index) => { - //console.log('each item!', index, el.value); - if (!items[index]) items[index] = { - _id: Random.id(6), - }; - items[index].name = el.value.trim(); - }); + Array.from(this.findAll('.js-field-settings-dropdown input')).forEach( + (el, index) => { + //console.log('each item!', index, el.value); + if (!items[index]) + items[index] = { + _id: Random.id(6), + }; + items[index].name = el.value.trim(); + }, + ); return items; }, getSettings() { const settings = {}; switch (this.type.get()) { - case 'dropdown': { - const dropdownItems = this.getDropdownItems().filter((item) => !!item.name.trim()); - settings.dropdownItems = dropdownItems; - break; - } + case 'dropdown': { + const dropdownItems = this.getDropdownItems().filter( + item => !!item.name.trim(), + ); + settings.dropdownItems = dropdownItems; + break; + } } return settings; }, events() { - return [{ - 'change .js-field-type'(evt) { - const value = evt.target.value; - this.type.set(value); - }, - 'keydown .js-dropdown-item.last'(evt) { - if (evt.target.value.trim() && evt.keyCode === 13) { - const items = this.getDropdownItems(); - this.dropdownItems.set(items); - evt.target.value = ''; - } + return [ + { + 'change .js-field-type'(evt) { + const value = evt.target.value; + this.type.set(value); + }, + 'keydown .js-dropdown-item.last'(evt) { + if (evt.target.value.trim() && evt.keyCode === 13) { + const items = this.getDropdownItems(); + this.dropdownItems.set(items); + evt.target.value = ''; + } + }, + 'click .js-field-show-on-card'(evt) { + let $target = $(evt.target); + if (!$target.hasClass('js-field-show-on-card')) { + $target = $target.parent(); + } + $target.find('.materialCheckBox').toggleClass('is-checked'); + $target.toggleClass('is-checked'); + }, + 'click .js-field-automatically-on-card'(evt) { + let $target = $(evt.target); + if (!$target.hasClass('js-field-automatically-on-card')) { + $target = $target.parent(); + } + $target.find('.materialCheckBox').toggleClass('is-checked'); + $target.toggleClass('is-checked'); + }, + 'click .js-field-showLabel-on-card'(evt) { + let $target = $(evt.target); + if (!$target.hasClass('js-field-showLabel-on-card')) { + $target = $target.parent(); + } + $target.find('.materialCheckBox').toggleClass('is-checked'); + $target.toggleClass('is-checked'); + }, + 'click .primary'(evt) { + evt.preventDefault(); + + const data = { + name: this.find('.js-field-name').value.trim(), + type: this.type.get(), + settings: this.getSettings(), + showOnCard: this.find('.js-field-show-on-card.is-checked') !== null, + showLabelOnMiniCard: + this.find('.js-field-showLabel-on-card.is-checked') !== null, + automaticallyOnCard: + this.find('.js-field-automatically-on-card.is-checked') !== null, + }; + + // insert or update + if (!this.data()._id) { + data.boardIds = [Session.get('currentBoard')]; + CustomFields.insert(data); + } else { + CustomFields.update(this.data()._id, { $set: data }); + } + + Popup.back(); + }, + 'click .js-delete-custom-field': Popup.afterConfirm( + 'deleteCustomField', + function() { + const customField = CustomFields.findOne(this._id); + if (customField.boardIds.length > 1) { + CustomFields.update(customField._id, { + $pull: { + boardIds: Session.get('currentBoard'), + }, + }); + } else { + CustomFields.remove(customField._id); + } + Popup.close(); + }, + ), }, - 'click .js-field-show-on-card'(evt) { - let $target = $(evt.target); - if(!$target.hasClass('js-field-show-on-card')){ - $target = $target.parent(); - } - $target.find('.materialCheckBox').toggleClass('is-checked'); - $target.toggleClass('is-checked'); - }, - 'click .js-field-automatically-on-card'(evt) { - let $target = $(evt.target); - if(!$target.hasClass('js-field-automatically-on-card')){ - $target = $target.parent(); - } - $target.find('.materialCheckBox').toggleClass('is-checked'); - $target.toggleClass('is-checked'); - }, - 'click .js-field-showLabel-on-card'(evt) { - let $target = $(evt.target); - if(!$target.hasClass('js-field-showLabel-on-card')){ - $target = $target.parent(); - } - $target.find('.materialCheckBox').toggleClass('is-checked'); - $target.toggleClass('is-checked'); - }, - 'click .primary'(evt) { - evt.preventDefault(); - - const data = { - name: this.find('.js-field-name').value.trim(), - type: this.type.get(), - settings: this.getSettings(), - showOnCard: this.find('.js-field-show-on-card.is-checked') !== null, - showLabelOnMiniCard: this.find('.js-field-showLabel-on-card.is-checked') !== null, - automaticallyOnCard: this.find('.js-field-automatically-on-card.is-checked') !== null, - }; - - // insert or update - if (!this.data()._id) { - data.boardIds = [Session.get('currentBoard')]; - CustomFields.insert(data); - } else { - CustomFields.update(this.data()._id, {$set: data}); - } - - Popup.back(); - }, - 'click .js-delete-custom-field': Popup.afterConfirm('deleteCustomField', function() { - const customField = CustomFields.findOne(this._id); - if (customField.boardIds.length > 1) { - CustomFields.update(customField._id, { - $pull: { - boardIds: Session.get('currentBoard'), - }, - }); - } else { - CustomFields.remove(customField._id); - } - Popup.close(); - }), - }]; + ]; }, - }); CreateCustomFieldPopup.register('createCustomFieldPopup'); (class extends CreateCustomFieldPopup { - template() { return 'createCustomFieldPopup'; } - -}).register('editCustomFieldPopup'); +}.register('editCustomFieldPopup')); /*Template.deleteCustomFieldPopup.events({ 'submit'(evt) { diff --git a/client/components/sidebar/sidebarFilters.js b/client/components/sidebar/sidebarFilters.js index fd8229e4..88438a7a 100644 --- a/client/components/sidebar/sidebarFilters.js +++ b/client/components/sidebar/sidebarFilters.js @@ -1,106 +1,108 @@ BlazeComponent.extendComponent({ events() { - return [{ - 'click .js-toggle-label-filter'(evt) { - evt.preventDefault(); - Filter.labelIds.toggle(this.currentData()._id); - Filter.resetExceptions(); + return [ + { + 'click .js-toggle-label-filter'(evt) { + evt.preventDefault(); + Filter.labelIds.toggle(this.currentData()._id); + Filter.resetExceptions(); + }, + 'click .js-toggle-member-filter'(evt) { + evt.preventDefault(); + Filter.members.toggle(this.currentData()._id); + Filter.resetExceptions(); + }, + 'click .js-toggle-custom-fields-filter'(evt) { + evt.preventDefault(); + Filter.customFields.toggle(this.currentData()._id); + Filter.resetExceptions(); + }, + 'change .js-field-advanced-filter'(evt) { + evt.preventDefault(); + Filter.advanced.set( + this.find('.js-field-advanced-filter').value.trim(), + ); + Filter.resetExceptions(); + }, + 'click .js-clear-all'(evt) { + evt.preventDefault(); + Filter.reset(); + }, + 'click .js-filter-to-selection'(evt) { + evt.preventDefault(); + const selectedCards = Cards.find(Filter.mongoSelector()).map(c => { + return c._id; + }); + MultiSelection.add(selectedCards); + }, }, - 'click .js-toggle-member-filter'(evt) { - evt.preventDefault(); - Filter.members.toggle(this.currentData()._id); - Filter.resetExceptions(); - }, - 'click .js-toggle-custom-fields-filter'(evt) { - evt.preventDefault(); - Filter.customFields.toggle(this.currentData()._id); - Filter.resetExceptions(); - }, - 'change .js-field-advanced-filter'(evt) { - evt.preventDefault(); - Filter.advanced.set(this.find('.js-field-advanced-filter').value.trim()); - Filter.resetExceptions(); - }, - 'click .js-clear-all'(evt) { - evt.preventDefault(); - Filter.reset(); - }, - 'click .js-filter-to-selection'(evt) { - evt.preventDefault(); - const selectedCards = Cards.find(Filter.mongoSelector()).map((c) => { - return c._id; - }); - MultiSelection.add(selectedCards); - }, - }]; + ]; }, }).register('filterSidebar'); function mutateSelectedCards(mutationName, ...args) { - Cards.find(MultiSelection.getMongoSelector()).forEach((card) => { + Cards.find(MultiSelection.getMongoSelector()).forEach(card => { card[mutationName](...args); }); } BlazeComponent.extendComponent({ mapSelection(kind, _id) { - return Cards.find(MultiSelection.getMongoSelector()).map((card) => { + return Cards.find(MultiSelection.getMongoSelector()).map(card => { const methodName = kind === 'label' ? 'hasLabel' : 'isAssigned'; return card[methodName](_id); }); }, allSelectedElementHave(kind, _id) { - if (MultiSelection.isEmpty()) - return false; - else - return _.every(this.mapSelection(kind, _id)); + if (MultiSelection.isEmpty()) return false; + else return _.every(this.mapSelection(kind, _id)); }, someSelectedElementHave(kind, _id) { - if (MultiSelection.isEmpty()) - return false; - else - return _.some(this.mapSelection(kind, _id)); + if (MultiSelection.isEmpty()) return false; + else return _.some(this.mapSelection(kind, _id)); }, events() { - return [{ - 'click .js-toggle-label-multiselection'(evt) { - const labelId = this.currentData()._id; - const mappedSelection = this.mapSelection('label', labelId); + return [ + { + 'click .js-toggle-label-multiselection'(evt) { + const labelId = this.currentData()._id; + const mappedSelection = this.mapSelection('label', labelId); - if (_.every(mappedSelection)) { - mutateSelectedCards('removeLabel', labelId); - } else if (_.every(mappedSelection, (bool) => !bool)) { - mutateSelectedCards('addLabel', labelId); - } else { - const popup = Popup.open('disambiguateMultiLabel'); - // XXX We need to have a better integration between the popup and the - // UI components systems. - popup.call(this.currentData(), evt); - } - }, - 'click .js-toggle-member-multiselection'(evt) { - const memberId = this.currentData()._id; - const mappedSelection = this.mapSelection('member', memberId); - if (_.every(mappedSelection)) { - mutateSelectedCards('unassignMember', memberId); - } else if (_.every(mappedSelection, (bool) => !bool)) { - mutateSelectedCards('assignMember', memberId); - } else { - const popup = Popup.open('disambiguateMultiMember'); - // XXX We need to have a better integration between the popup and the - // UI components systems. - popup.call(this.currentData(), evt); - } - }, - 'click .js-move-selection': Popup.open('moveSelection'), - 'click .js-archive-selection'() { - mutateSelectedCards('archive'); - EscapeActions.executeUpTo('multiselection'); + if (_.every(mappedSelection)) { + mutateSelectedCards('removeLabel', labelId); + } else if (_.every(mappedSelection, bool => !bool)) { + mutateSelectedCards('addLabel', labelId); + } else { + const popup = Popup.open('disambiguateMultiLabel'); + // XXX We need to have a better integration between the popup and the + // UI components systems. + popup.call(this.currentData(), evt); + } + }, + 'click .js-toggle-member-multiselection'(evt) { + const memberId = this.currentData()._id; + const mappedSelection = this.mapSelection('member', memberId); + if (_.every(mappedSelection)) { + mutateSelectedCards('unassignMember', memberId); + } else if (_.every(mappedSelection, bool => !bool)) { + mutateSelectedCards('assignMember', memberId); + } else { + const popup = Popup.open('disambiguateMultiMember'); + // XXX We need to have a better integration between the popup and the + // UI components systems. + popup.call(this.currentData(), evt); + } + }, + 'click .js-move-selection': Popup.open('moveSelection'), + 'click .js-archive-selection'() { + mutateSelectedCards('archive'); + EscapeActions.executeUpTo('multiselection'); + }, }, - }]; + ]; }, }).register('multiselectionSidebar'); diff --git a/client/components/sidebar/sidebarSearches.js b/client/components/sidebar/sidebarSearches.js index 111a86b8..8944c04e 100644 --- a/client/components/sidebar/sidebarSearches.js +++ b/client/components/sidebar/sidebarSearches.js @@ -9,11 +9,13 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'submit .js-search-term-form'(evt) { - evt.preventDefault(); - this.term.set(evt.target.searchTerm.value); + return [ + { + 'submit .js-search-term-form'(evt) { + evt.preventDefault(); + this.term.set(evt.target.searchTerm.value); + }, }, - }]; + ]; }, }).register('searchSidebar'); diff --git a/client/components/swimlanes/swimlaneHeader.js b/client/components/swimlanes/swimlaneHeader.js index e7f3cc76..ee21d100 100644 --- a/client/components/swimlanes/swimlaneHeader.js +++ b/client/components/swimlanes/swimlaneHeader.js @@ -6,9 +6,11 @@ Meteor.startup(() => { }); BlazeComponent.extendComponent({ - editTitle(evt) { - evt.preventDefault(); - const newTitle = this.childComponents('inlinedForm')[0].getValue().trim(); + editTitle(event) { + event.preventDefault(); + const newTitle = this.childComponents('inlinedForm')[0] + .getValue() + .trim(); const swimlane = this.currentData(); if (newTitle) { swimlane.rename(newTitle.trim()); @@ -16,18 +18,20 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-open-swimlane-menu': Popup.open('swimlaneAction'), - 'click .js-open-add-swimlane-menu': Popup.open('swimlaneAdd'), - submit: this.editTitle, - }]; + return [ + { + 'click .js-open-swimlane-menu': Popup.open('swimlaneAction'), + 'click .js-open-add-swimlane-menu': Popup.open('swimlaneAdd'), + submit: this.editTitle, + }, + ]; }, }).register('swimlaneHeader'); Template.swimlaneActionPopup.events({ 'click .js-set-swimlane-color': Popup.open('setSwimlaneColor'), - 'click .js-close-swimlane' (evt) { - evt.preventDefault(); + 'click .js-close-swimlane'(event) { + event.preventDefault(); this.archive(); Popup.close(); }, @@ -39,34 +43,42 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - submit(evt) { - evt.preventDefault(); - const currentBoard = Boards.findOne(Session.get('currentBoard')); - const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane); - const titleInput = this.find('.swimlane-name-input'); - const title = titleInput.value.trim(); - const sortValue = calculateIndexData(this.currentSwimlane, nextSwimlane, 1); - const swimlaneType = (currentBoard.isTemplatesBoard())?'template-swimlane':'swimlane'; + return [ + { + submit(event) { + event.preventDefault(); + const currentBoard = Boards.findOne(Session.get('currentBoard')); + const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane); + const titleInput = this.find('.swimlane-name-input'); + const title = titleInput.value.trim(); + const sortValue = calculateIndexData( + this.currentSwimlane, + nextSwimlane, + 1, + ); + const swimlaneType = currentBoard.isTemplatesBoard() + ? 'template-swimlane' + : 'swimlane'; - if (title) { - Swimlanes.insert({ - title, - boardId: Session.get('currentBoard'), - sort: sortValue.base, - type: swimlaneType, - }); + if (title) { + Swimlanes.insert({ + title, + boardId: Session.get('currentBoard'), + sort: sortValue.base, + type: swimlaneType, + }); - titleInput.value = ''; - titleInput.focus(); - } - // XXX ideally, we should move the popup to the newly - // created swimlane so a user can add more than one swimlane - // with a minimum of interactions - Popup.close(); + titleInput.value = ''; + titleInput.focus(); + } + // XXX ideally, we should move the popup to the newly + // created swimlane so a user can add more than one swimlane + // with a minimum of interactions + Popup.close(); + }, + 'click .js-swimlane-template': Popup.open('searchElement'), }, - 'click .js-swimlane-template': Popup.open('searchElement'), - }]; + ]; }, }).register('swimlaneAddPopup'); @@ -77,7 +89,7 @@ BlazeComponent.extendComponent({ }, colors() { - return swimlaneColors.map((color) => ({ color, name: '' })); + return swimlaneColors.map(color => ({ color, name: '' })); }, isSelected(color) { @@ -85,18 +97,20 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-palette-color'() { - this.currentColor.set(this.currentData().color); - }, - 'click .js-submit' () { - this.currentSwimlane.setColor(this.currentColor.get()); - Popup.close(); - }, - 'click .js-remove-color'() { - this.currentSwimlane.setColor(null); - Popup.close(); + return [ + { + 'click .js-palette-color'() { + this.currentColor.set(this.currentData().color); + }, + 'click .js-submit'() { + this.currentSwimlane.setColor(this.currentColor.get()); + Popup.close(); + }, + 'click .js-remove-color'() { + this.currentSwimlane.setColor(null); + Popup.close(); + }, }, - }]; + ]; }, }).register('setSwimlaneColorPopup'); diff --git a/client/components/swimlanes/swimlanes.js b/client/components/swimlanes/swimlanes.js index d0ec3f4a..568c0bbe 100644 --- a/client/components/swimlanes/swimlanes.js +++ b/client/components/swimlanes/swimlanes.js @@ -2,16 +2,27 @@ const { calculateIndex, enableClickOnTouch } = Utils; function currentListIsInThisSwimlane(swimlaneId) { const currentList = Lists.findOne(Session.get('currentList')); - return currentList && (currentList.swimlaneId === swimlaneId || currentList.swimlaneId === ''); + return ( + currentList && + (currentList.swimlaneId === swimlaneId || currentList.swimlaneId === '') + ); } function currentCardIsInThisList(listId, swimlaneId) { const currentCard = Cards.findOne(Session.get('currentCard')); const currentUser = Meteor.user(); - if (currentUser && currentUser.profile && currentUser.profile.boardView === 'board-view-swimlanes') - return currentCard && currentCard.listId === listId && currentCard.swimlaneId === swimlaneId; - else // Default view: board-view-lists - return currentCard && currentCard.listId === listId; + if ( + currentUser && + currentUser.profile && + currentUser.profile.boardView === 'board-view-swimlanes' + ) + return ( + currentCard && + currentCard.listId === listId && + currentCard.swimlaneId === swimlaneId + ); + // Default view: board-view-lists + else return currentCard && currentCard.listId === listId; // https://github.com/wekan/wekan/issues/1623 // https://github.com/ChronikEwok/wekan/commit/cad9b20451bb6149bfb527a99b5001873b06c3de // TODO: In public board, if you would like to switch between List/Swimlane view, you could @@ -79,7 +90,11 @@ function initSortable(boardComponent, $listsDom) { enableClickOnTouch('.js-list:not(.js-list-composer)'); function userIsMember() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); } // Disable drag-dropping while in multi-selection mode, or if the current user @@ -87,8 +102,11 @@ function initSortable(boardComponent, $listsDom) { boardComponent.autorun(() => { const $listDom = $listsDom; if ($listDom.data('sortable')) { - $listsDom.sortable('option', 'disabled', - MultiSelection.isActive() || !userIsMember()); + $listsDom.sortable( + 'option', + 'disabled', + MultiSelection.isActive() || !userIsMember(), + ); } }); } @@ -124,47 +142,60 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - // Click-and-drag action - 'mousedown .board-canvas'(evt) { - // Translating the board canvas using the click-and-drag action can - // conflict with the build-in browser mechanism to select text. We - // define a list of elements in which we disable the dragging because - // the user will legitimately expect to be able to select some text with - // his mouse. - const noDragInside = ['a', 'input', 'textarea', 'p', '.js-list-header']; - if ($(evt.target).closest(noDragInside.join(',')).length === 0 && this.$('.swimlane').prop('clientHeight') > evt.offsetY) { - this._isDragging = true; - this._lastDragPositionX = evt.clientX; - } - }, - 'mouseup'() { - if (this._isDragging) { - this._isDragging = false; - } - }, - 'mousemove'(evt) { - if (this._isDragging) { - // Update the canvas position - this.listsDom.scrollLeft -= evt.clientX - this._lastDragPositionX; - this._lastDragPositionX = evt.clientX; - // Disable browser text selection while dragging - evt.stopPropagation(); - evt.preventDefault(); - // Don't close opened card or inlined form at the end of the - // click-and-drag. - EscapeActions.executeUpTo('popup-close'); - EscapeActions.preventNextClick(); - } + return [ + { + // Click-and-drag action + 'mousedown .board-canvas'(evt) { + // Translating the board canvas using the click-and-drag action can + // conflict with the build-in browser mechanism to select text. We + // define a list of elements in which we disable the dragging because + // the user will legitimately expect to be able to select some text with + // his mouse. + const noDragInside = [ + 'a', + 'input', + 'textarea', + 'p', + '.js-list-header', + ]; + if ( + $(evt.target).closest(noDragInside.join(',')).length === 0 && + this.$('.swimlane').prop('clientHeight') > evt.offsetY + ) { + this._isDragging = true; + this._lastDragPositionX = evt.clientX; + } + }, + mouseup() { + if (this._isDragging) { + this._isDragging = false; + } + }, + mousemove(evt) { + if (this._isDragging) { + // Update the canvas position + this.listsDom.scrollLeft -= evt.clientX - this._lastDragPositionX; + this._lastDragPositionX = evt.clientX; + // Disable browser text selection while dragging + evt.stopPropagation(); + evt.preventDefault(); + // Don't close opened card or inlined form at the end of the + // click-and-drag. + EscapeActions.executeUpTo('popup-close'); + EscapeActions.preventNextClick(); + } + }, }, - }]; + ]; }, }).register('swimlane'); BlazeComponent.extendComponent({ onCreated() { this.currentBoard = Boards.findOne(Session.get('currentBoard')); - this.isListTemplatesSwimlane = this.currentBoard.isTemplatesBoard() && this.currentData().isListTemplatesSwimlane(); + this.isListTemplatesSwimlane = + this.currentBoard.isTemplatesBoard() && + this.currentData().isListTemplatesSwimlane(); this.currentSwimlane = this.currentData(); }, @@ -174,32 +205,40 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - submit(evt) { - evt.preventDefault(); - const titleInput = this.find('.list-name-input'); - const title = titleInput.value.trim(); - if (title) { - Lists.insert({ - title, - boardId: Session.get('currentBoard'), - sort: $('.list').length, - type: (this.isListTemplatesSwimlane)?'template-list':'list', - swimlaneId: (this.currentBoard.isTemplatesBoard())?this.currentSwimlane._id:'', - }); - - titleInput.value = ''; - titleInput.focus(); - } + return [ + { + submit(evt) { + evt.preventDefault(); + const titleInput = this.find('.list-name-input'); + const title = titleInput.value.trim(); + if (title) { + Lists.insert({ + title, + boardId: Session.get('currentBoard'), + sort: $('.list').length, + type: this.isListTemplatesSwimlane ? 'template-list' : 'list', + swimlaneId: this.currentBoard.isTemplatesBoard() + ? this.currentSwimlane._id + : '', + }); + + titleInput.value = ''; + titleInput.focus(); + } + }, + 'click .js-list-template': Popup.open('searchElement'), }, - 'click .js-list-template': Popup.open('searchElement'), - }]; + ]; }, }).register('addListForm'); Template.swimlane.helpers({ canSeeAddList() { - return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); + return ( + Meteor.user() && + Meteor.user().isBoardMember() && + !Meteor.user().isCommentOnly() + ); }, }); diff --git a/client/components/users/userAvatar.js b/client/components/users/userAvatar.js index 91cad237..262a63af 100644 --- a/client/components/users/userAvatar.js +++ b/client/components/users/userAvatar.js @@ -22,14 +22,11 @@ Template.userAvatar.helpers({ presenceStatusClassName() { const user = Users.findOne(this.userId); const userPresence = presences.findOne({ userId: this.userId }); - if (user && user.isInvitedTo(Session.get('currentBoard'))) - return 'pending'; - else if (!userPresence) - return 'disconnected'; + if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending'; + else if (!userPresence) return 'disconnected'; else if (Session.equals('currentBoard', userPresence.state.currentBoardId)) return 'active'; - else - return 'idle'; + else return 'idle'; }, }); @@ -45,7 +42,7 @@ Template.userAvatarInitials.helpers({ viewPortWidth() { const user = Users.findOne(this.userId); - return (user && user.getInitials().length || 1) * 12; + return ((user && user.getInitials().length) || 1) * 12; }, }); @@ -64,7 +61,7 @@ BlazeComponent.extendComponent({ }, uploadedAvatars() { - return Avatars.find({userId: Meteor.userId()}); + return Avatars.find({ userId: Meteor.userId() }); }, isSelected() { @@ -89,46 +86,48 @@ BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-upload-avatar'() { - this.$('.js-upload-avatar-input').click(); - }, - 'change .js-upload-avatar-input'(evt) { - let file, fileUrl; - - FS.Utility.eachFile(evt, (f) => { - try { - file = Avatars.insert(new FS.File(f)); - fileUrl = file.url(this.avatarUrlOptions()); - } catch (e) { - this.setError('avatar-too-big'); + return [ + { + 'click .js-upload-avatar'() { + this.$('.js-upload-avatar-input').click(); + }, + 'change .js-upload-avatar-input'(event) { + let file, fileUrl; + + FS.Utility.eachFile(event, f => { + try { + file = Avatars.insert(new FS.File(f)); + fileUrl = file.url(this.avatarUrlOptions()); + } catch (e) { + this.setError('avatar-too-big'); + } + }); + + if (fileUrl) { + this.setError(''); + const fetchAvatarInterval = window.setInterval(() => { + $.ajax({ + url: fileUrl, + success: () => { + this.setAvatar(file.url(this.avatarUrlOptions())); + window.clearInterval(fetchAvatarInterval); + }, + }); + }, 100); } - }); - - if (fileUrl) { - this.setError(''); - const fetchAvatarInterval = window.setInterval(() => { - $.ajax({ - url: fileUrl, - success: () => { - this.setAvatar(file.url(this.avatarUrlOptions())); - window.clearInterval(fetchAvatarInterval); - }, - }); - }, 100); - } - }, - 'click .js-select-avatar'() { - const avatarUrl = this.currentData().url(this.avatarUrlOptions()); - this.setAvatar(avatarUrl); - }, - 'click .js-select-initials'() { - this.setAvatar(''); - }, - 'click .js-delete-avatar'() { - Avatars.remove(this.currentData()._id); + }, + 'click .js-select-avatar'() { + const avatarUrl = this.currentData().url(this.avatarUrlOptions()); + this.setAvatar(avatarUrl); + }, + 'click .js-select-initials'() { + this.setAvatar(''); + }, + 'click .js-delete-avatar'() { + Avatars.remove(this.currentData()._id); + }, }, - }]; + ]; }, }).register('changeAvatarPopup'); @@ -146,11 +145,11 @@ Template.cardMembersPopup.helpers({ }); Template.cardMembersPopup.events({ - 'click .js-select-member'(evt) { + 'click .js-select-member'(event) { const card = Cards.findOne(Session.get('currentCard')); const memberId = this.userId; card.toggleMember(memberId); - evt.preventDefault(); + event.preventDefault(); }, }); diff --git a/client/components/users/userHeader.js b/client/components/users/userHeader.js index d5353152..0434f647 100644 --- a/client/components/users/userHeader.js +++ b/client/components/users/userHeader.js @@ -18,8 +18,8 @@ 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'(evt) { - evt.preventDefault(); + 'click .js-logout'(event) { + event.preventDefault(); AccountsTemplates.logout(); }, @@ -38,12 +38,12 @@ Template.editProfilePopup.helpers({ }); Template.editProfilePopup.events({ - submit(evt, tpl) { - evt.preventDefault(); - const fullname = tpl.find('.js-profile-fullname').value.trim(); - const username = tpl.find('.js-profile-username').value.trim(); - const initials = tpl.find('.js-profile-initials').value.trim(); - const email = tpl.find('.js-profile-email').value.trim(); + submit(event, templateInstance) { + event.preventDefault(); + const fullname = templateInstance.find('.js-profile-fullname').value.trim(); + const username = templateInstance.find('.js-profile-username').value.trim(); + const initials = templateInstance.find('.js-profile-initials').value.trim(); + const email = templateInstance.find('.js-profile-email').value.trim(); let isChangeUserName = false; let isChangeEmail = false; Users.update(Meteor.userId(), { @@ -53,29 +53,36 @@ Template.editProfilePopup.events({ }, }); isChangeUserName = username !== Meteor.user().username; - isChangeEmail = email.toLowerCase() !== Meteor.user().emails[0].address.toLowerCase(); + isChangeEmail = + email.toLowerCase() !== Meteor.user().emails[0].address.toLowerCase(); if (isChangeUserName && isChangeEmail) { - Meteor.call('setUsernameAndEmail', username, email.toLowerCase(), Meteor.userId(), function (error) { - const usernameMessageElement = tpl.$('.username-taken'); - const emailMessageElement = tpl.$('.email-taken'); - if (error) { - const errorElement = error.error; - if (errorElement === 'username-already-taken') { - usernameMessageElement.show(); - emailMessageElement.hide(); - } else if (errorElement === 'email-already-taken') { + Meteor.call( + 'setUsernameAndEmail', + username, + email.toLowerCase(), + Meteor.userId(), + function(error) { + const usernameMessageElement = templateInstance.$('.username-taken'); + const emailMessageElement = templateInstance.$('.email-taken'); + if (error) { + const errorElement = error.error; + if (errorElement === 'username-already-taken') { + usernameMessageElement.show(); + emailMessageElement.hide(); + } else if (errorElement === 'email-already-taken') { + usernameMessageElement.hide(); + emailMessageElement.show(); + } + } else { usernameMessageElement.hide(); - emailMessageElement.show(); + emailMessageElement.hide(); + Popup.back(); } - } else { - usernameMessageElement.hide(); - emailMessageElement.hide(); - Popup.back(); - } - }); + }, + ); } else if (isChangeUserName) { - Meteor.call('setUsername', username, Meteor.userId(), function (error) { - const messageElement = tpl.$('.username-taken'); + Meteor.call('setUsername', username, Meteor.userId(), function(error) { + const messageElement = templateInstance.$('.username-taken'); if (error) { messageElement.show(); } else { @@ -84,8 +91,10 @@ Template.editProfilePopup.events({ } }); } else if (isChangeEmail) { - Meteor.call('setEmail', email.toLowerCase(), Meteor.userId(), function (error) { - const messageElement = tpl.$('.email-taken'); + Meteor.call('setEmail', email.toLowerCase(), Meteor.userId(), function( + error, + ) { + const messageElement = templateInstance.$('.email-taken'); if (error) { messageElement.show(); } else { @@ -104,7 +113,7 @@ Template.editProfilePopup.events({ // 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(function() { this.find('#at-field-current_password').focus(); }); @@ -123,7 +132,7 @@ Template.changeLanguagePopup.helpers({ name = 'Occitan'; } return { tag, name }; - }).sort(function (a, b) { + }).sort(function(a, b) { if (a.name === b.name) { return 0; } else { @@ -138,13 +147,13 @@ Template.changeLanguagePopup.helpers({ }); Template.changeLanguagePopup.events({ - 'click .js-set-language'(evt) { + 'click .js-set-language'(event) { Users.update(Meteor.userId(), { $set: { 'profile.language': this.tag, }, }); - evt.preventDefault(); + event.preventDefault(); }, }); @@ -161,9 +170,12 @@ Template.changeSettingsPopup.events({ 'click .js-toggle-system-messages'() { Meteor.call('toggleSystemMessages'); }, - 'click .js-apply-show-cards-at'(evt, tpl) { - evt.preventDefault(); - const minLimit = parseInt(tpl.$('#show-cards-count-at').val(), 10); + 'click .js-apply-show-cards-at'(event, templateInstance) { + event.preventDefault(); + const minLimit = parseInt( + templateInstance.$('#show-cards-count-at').val(), + 10, + ); if (!isNaN(minLimit)) { Meteor.call('changeLimitToShowCardsCount', minLimit); Popup.back(); diff --git a/client/config/blazeHelpers.js b/client/config/blazeHelpers.js index e058d722..3a857314 100644 --- a/client/config/blazeHelpers.js +++ b/client/config/blazeHelpers.js @@ -25,7 +25,7 @@ Blaze.registerHelper('currentList', () => { } }); -Blaze.registerHelper('getUser', (userId) => Users.findOne(userId)); +Blaze.registerHelper('getUser', userId => Users.findOne(userId)); Blaze.registerHelper('concat', (...args) => args.slice(0, -1).join('')); diff --git a/client/lib/accessibility.js b/client/lib/accessibility.js index 52b771d4..3776e937 100644 --- a/client/lib/accessibility.js +++ b/client/lib/accessibility.js @@ -27,10 +27,7 @@ function copyTitleInAriaLabel(attributes) { // which is a little bit hacky -- but still reasonable with our ES6 usage. If we // end up switching to React we will probably create lower level small // components to handle that without overwriting any build-in function. -const { - A: superA, - I: superI, -} = HTML; +const { A: superA, I: superI } = HTML; HTML.A = (attributes, ...others) => { return superA(copyTitleInAriaLabel(enforceHref(attributes)), ...others); diff --git a/client/lib/cssEvents.js b/client/lib/cssEvents.js index 04f5707e..1cf6b8e8 100644 --- a/client/lib/cssEvents.js +++ b/client/lib/cssEvents.js @@ -3,11 +3,11 @@ function whichTransitionEvent() { const el = document.createElement('fakeelement'); const transitions = { - transition:'transitionend', - OTransition:'oTransitionEnd', - MSTransition:'msTransitionEnd', - MozTransition:'transitionend', - WebkitTransition:'webkitTransitionEnd', + transition: 'transitionend', + OTransition: 'oTransitionEnd', + MSTransition: 'msTransitionEnd', + MozTransition: 'transitionend', + WebkitTransition: 'webkitTransitionEnd', }; for (const t in transitions) { @@ -21,11 +21,11 @@ function whichTransitionEvent() { function whichAnimationEvent() { const el = document.createElement('fakeelement'); const transitions = { - animation:'animationend', - OAnimation:'oAnimationEnd', - MSTransition:'msAnimationEnd', - MozAnimation:'animationend', - WebkitAnimation:'webkitAnimationEnd', + animation: 'animationend', + OAnimation: 'oAnimationEnd', + MSTransition: 'msAnimationEnd', + MozAnimation: 'animationend', + WebkitAnimation: 'webkitAnimationEnd', }; for (const t in transitions) { diff --git a/client/lib/datepicker.js b/client/lib/datepicker.js index ab2da0bd..eb5b60b8 100644 --- a/client/lib/datepicker.js +++ b/client/lib/datepicker.js @@ -10,15 +10,20 @@ DatePicker = BlazeComponent.extendComponent({ }, onRendered() { - const $picker = this.$('.js-datepicker').datepicker({ - todayHighlight: true, - todayBtn: 'linked', - language: TAPi18n.getLanguage(), - }).on('changeDate', function(evt) { - this.find('#date').value = moment(evt.date).format('L'); - this.error.set(''); - this.find('#time').focus(); - }.bind(this)); + const $picker = this.$('.js-datepicker') + .datepicker({ + todayHighlight: true, + todayBtn: 'linked', + language: TAPi18n.getLanguage(), + }) + .on( + 'changeDate', + function(evt) { + this.find('#date').value = moment(evt.date).format('L'); + this.error.set(''); + this.find('#time').focus(); + }.bind(this), + ); if (this.date.get().isValid()) { $picker.datepicker('update', this.date.get().toDate()); @@ -26,13 +31,11 @@ DatePicker = BlazeComponent.extendComponent({ }, showDate() { - if (this.date.get().isValid()) - return this.date.get().format('L'); + if (this.date.get().isValid()) return this.date.get().format('L'); return ''; }, showTime() { - if (this.date.get().isValid()) - return this.date.get().format('LT'); + if (this.date.get().isValid()) return this.date.get().format('LT'); return ''; }, dateFormat() { @@ -43,44 +46,47 @@ DatePicker = BlazeComponent.extendComponent({ }, events() { - return [{ - 'keyup .js-date-field'() { - // parse for localized date format in strict mode - const dateMoment = moment(this.find('#date').value, 'L', true); - if (dateMoment.isValid()) { - this.error.set(''); - this.$('.js-datepicker').datepicker('update', dateMoment.toDate()); - } - }, - 'keyup .js-time-field'() { - // parse for localized time format in strict mode - const dateMoment = moment(this.find('#time').value, 'LT', true); - if (dateMoment.isValid()) { - this.error.set(''); - } - }, - 'submit .edit-date'(evt) { - evt.preventDefault(); + return [ + { + 'keyup .js-date-field'() { + // parse for localized date format in strict mode + const dateMoment = moment(this.find('#date').value, 'L', true); + if (dateMoment.isValid()) { + this.error.set(''); + this.$('.js-datepicker').datepicker('update', dateMoment.toDate()); + } + }, + 'keyup .js-time-field'() { + // parse for localized time format in strict mode + const dateMoment = moment(this.find('#time').value, 'LT', true); + if (dateMoment.isValid()) { + this.error.set(''); + } + }, + 'submit .edit-date'(evt) { + evt.preventDefault(); - // if no time was given, init with 12:00 - const time = evt.target.time.value || moment(new Date().setHours(12, 0, 0)).format('LT'); + // if no time was given, init with 12:00 + const time = + evt.target.time.value || + moment(new Date().setHours(12, 0, 0)).format('LT'); - const dateString = `${evt.target.date.value} ${time}`; - const newDate = moment(dateString, 'L LT', true); - if (newDate.isValid()) { - this._storeDate(newDate.toDate()); + const dateString = `${evt.target.date.value} ${time}`; + const newDate = moment(dateString, 'L LT', true); + if (newDate.isValid()) { + this._storeDate(newDate.toDate()); + Popup.close(); + } else { + this.error.set('invalid-date'); + evt.target.date.focus(); + } + }, + 'click .js-delete-date'(evt) { + evt.preventDefault(); + this._deleteDate(); Popup.close(); - } - else { - this.error.set('invalid-date'); - evt.target.date.focus(); - } - }, - 'click .js-delete-date'(evt) { - evt.preventDefault(); - this._deleteDate(); - Popup.close(); + }, }, - }]; + ]; }, }); diff --git a/client/lib/dropImage.js b/client/lib/dropImage.js index 592d5c8f..f4e1d8ab 100644 --- a/client/lib/dropImage.js +++ b/client/lib/dropImage.js @@ -11,7 +11,10 @@ $.event.fix = (function(originalFix) { return function(event) { event = originalFix.apply(this, arguments); - if (event.type.indexOf('drag') === 0 || event.type.indexOf('drop') === 0) { + if ( + event.type.indexOf('drag') === 0 || + event.type.indexOf('drop') === 0 + ) { event.dataTransfer = event.originalEvent.dataTransfer; } return event; @@ -23,7 +26,7 @@ matchType: /image.*/, }; - return $.fn.dropImageReader = function(options) { + return ($.fn.dropImageReader = function(options) { if (typeof options === 'function') { options = { callback: options, @@ -40,9 +43,9 @@ return $(element).bind('drop', function(event) { stopFn(event); const files = event.dataTransfer.files; - for(let i=0; i action.priority); + this._actions = _.sortBy( + [ + ...this._actions, + { + priority, + condition, + action, + noClickEscapeOn, + enabledOnClick, + }, + ], + action => action.priority, + ); }, executeLowest() { @@ -80,10 +86,8 @@ EscapeActions = { }, _stopClick(action, clickTarget) { - if (!_.isString(action.noClickEscapeOn)) - return false; - else - return $(clickTarget).closest(action.noClickEscapeOn).length > 0; + if (!_.isString(action.noClickEscapeOn)) return false; + else return $(clickTarget).closest(action.noClickEscapeOn).length > 0; }, _execute(options) { @@ -95,14 +99,11 @@ EscapeActions = { let executedAtLeastOne = false; let maxPriority; - if (!maxLabel) - maxPriority = Infinity; - else - maxPriority = this.hierarchy.indexOf(maxLabel); + if (!maxLabel) maxPriority = Infinity; + else maxPriority = this.hierarchy.indexOf(maxLabel); for (const currentAction of this._actions) { - if (currentAction.priority > maxPriority) - return executedAtLeastOne; + if (currentAction.priority > maxPriority) return executedAtLeastOne; if (isClick && this._stopClick(currentAction, clickTarget)) return executedAtLeastOne; @@ -111,8 +112,7 @@ EscapeActions = { if (isEnabled && currentAction.condition()) { currentAction.action(); executedAtLeastOne = true; - if (!multipleActions) - return executedAtLeastOne; + if (!multipleActions) return executedAtLeastOne; } } return executedAtLeastOne; @@ -128,13 +128,15 @@ Mousetrap.bindGlobal('esc', () => { // On a left click on the document, we try to exectute one escape action (eg, // close the popup). We don't execute any action if the user has clicked on a // link or a button. -$(document).on('click', (evt) => { - if (evt.button === 0 && - $(evt.target).closest('a,button,.is-editable').length === 0) { +$(document).on('click', evt => { + if ( + evt.button === 0 && + $(evt.target).closest('a,button,.is-editable').length === 0 + ) { EscapeActions.clickExecute(evt.target, 'multiselection'); } }); -$(document).on('click', 'a[href=\\#]', (evt) => { +$(document).on('click', 'a[href=\\#]', evt => { evt.preventDefault(); }); diff --git a/client/lib/filter.js b/client/lib/filter.js index c3c1b070..f19dc617 100644 --- a/client/lib/filter.js +++ b/client/lib/filter.js @@ -71,18 +71,19 @@ class SetFilter { _getEmptySelector() { this._dep.depend(); let includeEmpty = false; - this._selectedElements.forEach((el) => { + this._selectedElements.forEach(el => { if (el === undefined) { includeEmpty = true; } }); - return includeEmpty ? { - $eq: [], - } : null; + return includeEmpty + ? { + $eq: [], + } + : null; } } - // Advanced filter forms a MongoSelector from a users String. // Build by: Ignatz 19.05.2018 (github feuerball11) class AdvancedFilter { @@ -128,7 +129,8 @@ class AdvancedFilter { current += char; continue; } - if (char === '\'') { + // eslint-disable-next-line quotes + if (char === "'") { string = !string; if (string) wasString = true; continue; @@ -139,8 +141,8 @@ class AdvancedFilter { } if (char === ' ' && !string) { commands.push({ - 'cmd': current, - 'string': wasString, + cmd: current, + string: wasString, regex, }); wasString = false; @@ -151,8 +153,8 @@ class AdvancedFilter { } if (current !== '') { commands.push({ - 'cmd': current, - 'string': wasString, + cmd: current, + string: wasString, regex, }); } @@ -161,16 +163,19 @@ class AdvancedFilter { _fieldNameToId(field) { const found = CustomFields.findOne({ - 'name': field, + name: field, }); return found._id; } _fieldValueToId(field, value) { const found = CustomFields.findOne({ - 'name': field, + name: field, }); - if (found.settings.dropdownItems && found.settings.dropdownItems.length > 0) { + if ( + found.settings.dropdownItems && + found.settings.dropdownItems.length > 0 + ) { for (let i = 0; i < found.settings.dropdownItems.length; i++) { if (found.settings.dropdownItems[i].name === value) { return found.settings.dropdownItems[i]._id; @@ -202,37 +207,32 @@ class AdvancedFilter { for (let i = 0; i < commands.length; i++) { if (commands[i].cmd) { switch (commands[i].cmd) { - case '(': - { - level++; - if (start === -1) start = i; - continue; - } - case ')': - { - level--; - commands.splice(i, 1); - i--; - continue; - } - default: - { - if (level > 0) { - subcommands.push(commands[i]); + case '(': { + level++; + if (start === -1) start = i; + continue; + } + case ')': { + level--; commands.splice(i, 1); i--; continue; } - } + default: { + if (level > 0) { + subcommands.push(commands[i]); + commands.splice(i, 1); + i--; + continue; + } + } } } } if (start !== -1) { this._processSubCommands(subcommands); - if (subcommands.length === 1) - commands.splice(start, 0, subcommands[0]); - else - commands.splice(start, 0, subcommands); + if (subcommands.length === 1) commands.splice(start, 0, subcommands[0]); + else commands.splice(start, 0, subcommands); } this._processConditions(commands); this._processLogicalOperators(commands); @@ -242,149 +242,139 @@ class AdvancedFilter { for (let i = 0; i < commands.length; i++) { if (!commands[i].string && commands[i].cmd) { switch (commands[i].cmd) { - case '=': - case '==': - case '===': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - if (commands[i + 1].regex) { - const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); - let regex = null; - if (match.length > 2) - regex = new RegExp(match[1], match[2]); - else - regex = new RegExp(match[1]); + case '=': + case '==': + case '===': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + if (commands[i + 1].regex) { + const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); + let regex = null; + if (match.length > 2) regex = new RegExp(match[1], match[2]); + else regex = new RegExp(match[1]); + commands[i] = { + 'customFields._id': this._fieldNameToId(field), + 'customFields.value': regex, + }; + } else { + commands[i] = { + 'customFields._id': this._fieldNameToId(field), + 'customFields.value': { + $in: [this._fieldValueToId(field, str), parseInt(str, 10)], + }, + }; + } + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case '!=': + case '!==': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + if (commands[i + 1].regex) { + const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); + let regex = null; + if (match.length > 2) regex = new RegExp(match[1], match[2]); + else regex = new RegExp(match[1]); + commands[i] = { + 'customFields._id': this._fieldNameToId(field), + 'customFields.value': { + $not: regex, + }, + }; + } else { + commands[i] = { + 'customFields._id': this._fieldNameToId(field), + 'customFields.value': { + $not: { + $in: [this._fieldValueToId(field, str), parseInt(str, 10)], + }, + }, + }; + } + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case '>': + case 'gt': + case 'Gt': + case 'GT': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; commands[i] = { 'customFields._id': this._fieldNameToId(field), - 'customFields.value': regex, + 'customFields.value': { + $gt: parseInt(str, 10), + }, }; - } else { + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case '>=': + case '>==': + case 'gte': + case 'Gte': + case 'GTE': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { - $in: [this._fieldValueToId(field, str), parseInt(str, 10)], + $gte: parseInt(str, 10), }, }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; } - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '!=': - case '!==': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - if (commands[i + 1].regex) { - const match = str.match(new RegExp('^/(.*?)/([gimy]*)$')); - let regex = null; - if (match.length > 2) - regex = new RegExp(match[1], match[2]); - else - regex = new RegExp(match[1]); + case '<': + case 'lt': + case 'Lt': + case 'LT': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { - $not: regex, + $lt: parseInt(str, 10), }, }; - } else { + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case '<=': + case '<==': + case 'lte': + case 'Lte': + case 'LTE': { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { - $not: { - $in: [this._fieldValueToId(field, str), parseInt(str, 10)], - }, + $lte: parseInt(str, 10), }, }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; } - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '>': - case 'gt': - case 'Gt': - case 'GT': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { - 'customFields._id': this._fieldNameToId(field), - 'customFields.value': { - $gt: parseInt(str, 10), - }, - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '>=': - case '>==': - case 'gte': - case 'Gte': - case 'GTE': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { - 'customFields._id': this._fieldNameToId(field), - 'customFields.value': { - $gte: parseInt(str, 10), - }, - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '<': - case 'lt': - case 'Lt': - case 'LT': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { - 'customFields._id': this._fieldNameToId(field), - 'customFields.value': { - $lt: parseInt(str, 10), - }, - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case '<=': - case '<==': - case 'lte': - case 'Lte': - case 'LTE': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { - 'customFields._id': this._fieldNameToId(field), - 'customFields.value': { - $lte: parseInt(str, 10), - }, - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } } } } @@ -394,54 +384,51 @@ class AdvancedFilter { for (let i = 0; i < commands.length; i++) { if (!commands[i].string && commands[i].cmd) { switch (commands[i].cmd) { - case 'or': - case 'Or': - case 'OR': - case '|': - case '||': - { - const op1 = commands[i - 1]; - const op2 = commands[i + 1]; - commands[i] = { - $or: [op1, op2], - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case 'and': - case 'And': - case 'AND': - case '&': - case '&&': - { - const op1 = commands[i - 1]; - const op2 = commands[i + 1]; - commands[i] = { - $and: [op1, op2], - }; - commands.splice(i - 1, 1); - commands.splice(i, 1); - //changed = true; - i--; - break; - } - case 'not': - case 'Not': - case 'NOT': - case '!': - { - const op1 = commands[i + 1]; - commands[i] = { - $not: op1, - }; - commands.splice(i + 1, 1); - //changed = true; - i--; - break; - } + case 'or': + case 'Or': + case 'OR': + case '|': + case '||': { + const op1 = commands[i - 1]; + const op2 = commands[i + 1]; + commands[i] = { + $or: [op1, op2], + }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case 'and': + case 'And': + case 'AND': + case '&': + case '&&': { + const op1 = commands[i - 1]; + const op2 = commands[i + 1]; + commands[i] = { + $and: [op1, op2], + }; + commands.splice(i - 1, 1); + commands.splice(i, 1); + //changed = true; + i--; + break; + } + case 'not': + case 'Not': + case 'NOT': + case '!': { + const op1 = commands[i + 1]; + commands[i] = { + $not: op1, + }; + commands.splice(i + 1, 1); + //changed = true; + i--; + break; + } } } } @@ -452,7 +439,6 @@ class AdvancedFilter { const commands = this._filterToCommands(); return this._arrayToSelector(commands); } - } // The global Filter object. @@ -477,23 +463,26 @@ Filter = { _exceptionsDep: new Tracker.Dependency(), isActive() { - return _.any(this._fields, (fieldName) => { - return this[fieldName]._isActive(); - }) || this.advanced._isActive(); + return ( + _.any(this._fields, fieldName => { + return this[fieldName]._isActive(); + }) || this.advanced._isActive() + ); }, _getMongoSelector() { - if (!this.isActive()) - return {}; + if (!this.isActive()) return {}; const filterSelector = {}; const emptySelector = {}; let includeEmptySelectors = false; - this._fields.forEach((fieldName) => { + this._fields.forEach(fieldName => { const filter = this[fieldName]; if (filter._isActive()) { if (filter.subField !== '') { - filterSelector[`${fieldName}.${filter.subField}`] = filter._getMongoSelector(); + filterSelector[ + `${fieldName}.${filter.subField}` + ] = filter._getMongoSelector(); } else { filterSelector[fieldName] = filter._getMongoSelector(); } @@ -513,11 +502,15 @@ Filter = { const selectors = [exceptionsSelector]; - if (_.any(this._fields, (fieldName) => { - return this[fieldName]._isActive(); - })) selectors.push(filterSelector); + if ( + _.any(this._fields, fieldName => { + return this[fieldName]._isActive(); + }) + ) + selectors.push(filterSelector); if (includeEmptySelectors) selectors.push(emptySelector); - if (this.advanced._isActive()) selectors.push(this.advanced._getMongoSelector()); + if (this.advanced._isActive()) + selectors.push(this.advanced._getMongoSelector()); return { $or: selectors, @@ -526,8 +519,7 @@ Filter = { mongoSelector(additionalSelector) { const filterSelector = this._getMongoSelector(); - if (_.isUndefined(additionalSelector)) - return filterSelector; + if (_.isUndefined(additionalSelector)) return filterSelector; else return { $and: [filterSelector, additionalSelector], @@ -535,7 +527,7 @@ Filter = { }, reset() { - this._fields.forEach((fieldName) => { + this._fields.forEach(fieldName => { const filter = this[fieldName]; filter.reset(); }); diff --git a/client/lib/i18n.js b/client/lib/i18n.js index 97a91375..b4a95eae 100644 --- a/client/lib/i18n.js +++ b/client/lib/i18n.js @@ -12,7 +12,7 @@ Meteor.startup(() => { } if (!language) { - if(navigator.languages) { + if (navigator.languages) { language = navigator.languages[0]; } else { language = navigator.language || navigator.userLanguage; diff --git a/client/lib/inlinedform.js b/client/lib/inlinedform.js index d33786ae..f2ebe31e 100644 --- a/client/lib/inlinedform.js +++ b/client/lib/inlinedform.js @@ -48,35 +48,43 @@ InlinedForm = BlazeComponent.extendComponent({ }, events() { - return [{ - 'click .js-close-inlined-form': this.close, - 'click .js-open-inlined-form': this.open, + return [ + { + 'click .js-close-inlined-form': this.close, + 'click .js-open-inlined-form': this.open, - // Pressing Ctrl+Enter should submit the form - 'keydown form textarea'(evt) { - if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) { - this.find('button[type=submit]').click(); - } - }, + // Pressing Ctrl+Enter should submit the form + 'keydown form textarea'(evt) { + if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) { + this.find('button[type=submit]').click(); + } + }, - // Close the inlined form when after its submission - submit() { - if (this.currentData().autoclose !== false) { - Tracker.afterFlush(() => { - this.close(); - }); - } + // Close the inlined form when after its submission + submit() { + if (this.currentData().autoclose !== false) { + Tracker.afterFlush(() => { + this.close(); + }); + } + }, }, - }]; + ]; }, }).register('inlinedForm'); // Press escape to close the currently opened inlinedForm -EscapeActions.register('inlinedForm', - () => { currentlyOpenedForm.get().close(); }, - () => { return currentlyOpenedForm.get() !== null; }, { +EscapeActions.register( + 'inlinedForm', + () => { + currentlyOpenedForm.get().close(); + }, + () => { + return currentlyOpenedForm.get() !== null; + }, + { enabledOnClick: false, - } + }, ); // submit on click outside diff --git a/client/lib/keyboard.js b/client/lib/keyboard.js index 7abfa88d..d3f974be 100755 --- a/client/lib/keyboard.js +++ b/client/lib/keyboard.js @@ -40,8 +40,10 @@ Mousetrap.bind(['down', 'up'], (evt, key) => { return; } - const nextFunc = (key === 'down' ? 'next' : 'prev'); - const nextCard = $('.js-minicard.is-selected')[nextFunc]('.js-minicard').get(0); + const nextFunc = key === 'down' ? 'next' : 'prev'; + const nextCard = $('.js-minicard.is-selected') + [nextFunc]('.js-minicard') + .get(0); if (nextCard) { const nextCardId = Blaze.getData(nextCard)._id; Utils.goCardId(nextCardId); @@ -49,7 +51,7 @@ Mousetrap.bind(['down', 'up'], (evt, key) => { }); // XXX This shortcut should also work when hovering over a card in board view -Mousetrap.bind('space', (evt) => { +Mousetrap.bind('space', evt => { if (!Session.get('currentCard')) { return; } @@ -69,29 +71,38 @@ Mousetrap.bind('space', (evt) => { }); Template.keyboardShortcuts.helpers({ - mapping: [{ - keys: ['W'], - action: 'shortcut-toggle-sidebar', - }, { - keys: ['Q'], - action: 'shortcut-filter-my-cards', - }, { - keys: ['F'], - action: 'shortcut-toggle-filterbar', - }, { - keys: ['X'], - action: 'shortcut-clear-filters', - }, { - keys: ['?'], - action: 'shortcut-show-shortcuts', - }, { - keys: ['ESC'], - action: 'shortcut-close-dialog', - }, { - keys: ['@'], - action: 'shortcut-autocomplete-members', - }, { - keys: ['SPACE'], - action: 'shortcut-assign-self', - }], + mapping: [ + { + keys: ['W'], + action: 'shortcut-toggle-sidebar', + }, + { + keys: ['Q'], + action: 'shortcut-filter-my-cards', + }, + { + keys: ['F'], + action: 'shortcut-toggle-filterbar', + }, + { + keys: ['X'], + action: 'shortcut-clear-filters', + }, + { + keys: ['?'], + action: 'shortcut-show-shortcuts', + }, + { + keys: ['ESC'], + action: 'shortcut-close-dialog', + }, + { + keys: ['@'], + action: 'shortcut-autocomplete-members', + }, + { + keys: ['SPACE'], + action: 'shortcut-assign-self', + }, + ], }); diff --git a/client/lib/modal.js b/client/lib/modal.js index 3c27a179..1086734e 100644 --- a/client/lib/modal.js +++ b/client/lib/modal.js @@ -1,6 +1,6 @@ const closedValue = null; -window.Modal = new class { +window.Modal = new (class { constructor() { this._currentModal = new ReactiveVar(closedValue); this._onCloseGoTo = ''; @@ -21,7 +21,7 @@ window.Modal = new class { return this.getTemplateName() !== closedValue; } - isWide(){ + isWide() { return this._isWideModal; } @@ -32,23 +32,23 @@ window.Modal = new class { } } - openWide(modalName, { header = '', onCloseGoTo = ''} = {}) { + openWide(modalName, { header = '', onCloseGoTo = '' } = {}) { this._currentModal.set({ header, modalName }); this._onCloseGoTo = onCloseGoTo; this._isWideModal = true; } - open(modalName, { header = '', onCloseGoTo = ''} = {}) { + open(modalName, { header = '', onCloseGoTo = '' } = {}) { this._currentModal.set({ header, modalName }); this._onCloseGoTo = onCloseGoTo; - } -}(); +})(); Blaze.registerHelper('Modal', Modal); -EscapeActions.register('modalWindow', +EscapeActions.register( + 'modalWindow', () => Modal.close(), () => Modal.isOpen(), - { noClickEscapeOn: '.modal-container' } + { noClickEscapeOn: '.modal-container' }, ); diff --git a/client/lib/multiSelection.js b/client/lib/multiSelection.js index 30577fd4..ab6a046f 100644 --- a/client/lib/multiSelection.js +++ b/client/lib/multiSelection.js @@ -1,6 +1,4 @@ - function getCardsBetween(idA, idB) { - function pluckId(doc) { return doc._id; } @@ -15,7 +13,7 @@ function getCardsBetween(idA, idB) { }).map(pluckId); } - const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], (c) => { + const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], c => { return c.sort; }); @@ -31,17 +29,21 @@ function getCardsBetween(idA, idB) { }; } else { selector = { - $or: [{ - listId: cards[0].listId, - sort: { $lte: cards[0].sort }, - }, { - listId: { - $in: getListsStrictlyBetween(cards[0].listId, cards[1].listId), + $or: [ + { + listId: cards[0].listId, + sort: { $lte: cards[0].sort }, + }, + { + listId: { + $in: getListsStrictlyBetween(cards[0].listId, cards[1].listId), + }, }, - }, { - listId: cards[1].listId, - sort: { $gte: cards[1].sort }, - }], + { + listId: cards[1].listId, + sort: { $gte: cards[1].sort }, + }, + ], archived: false, }; } @@ -133,14 +135,12 @@ MultiSelection = { const selectedCards = this._selectedCards.get(); - cardIds.forEach((cardId) => { + cardIds.forEach(cardId => { const indexOfCard = selectedCards.indexOf(cardId); if (options.remove && indexOfCard > -1) selectedCards.splice(indexOfCard, 1); - - else if (options.add) - selectedCards.push(cardId); + else if (options.add) selectedCards.push(cardId); }); this._selectedCards.set(selectedCards); @@ -153,9 +153,15 @@ MultiSelection = { Blaze.registerHelper('MultiSelection', MultiSelection); -EscapeActions.register('multiselection', - () => { MultiSelection.disable(); }, - () => { return MultiSelection.isActive(); }, { +EscapeActions.register( + 'multiselection', + () => { + MultiSelection.disable(); + }, + () => { + return MultiSelection.isActive(); + }, + { noClickEscapeOn: '.js-minicard,.js-board-sidebar-content', - } + }, ); diff --git a/client/lib/pasteImage.js b/client/lib/pasteImage.js index 264d77ac..e6f8c6c2 100644 --- a/client/lib/pasteImage.js +++ b/client/lib/pasteImage.js @@ -11,7 +11,10 @@ $.event.fix = (function(originalFix) { return function(event) { event = originalFix.apply(this, arguments); - if (event.type.indexOf('copy') === 0 || event.type.indexOf('paste') === 0) { + if ( + event.type.indexOf('copy') === 0 || + event.type.indexOf('paste') === 0 + ) { event.clipboardData = event.originalEvent.clipboardData; } return event; @@ -23,7 +26,7 @@ matchType: /image.*/, }; - return $.fn.pasteImageReader = function(options) { + return ($.fn.pasteImageReader = function(options) { if (typeof options === 'function') { options = { callback: options, @@ -35,8 +38,11 @@ return $(element).bind('paste', function(event) { const types = event.clipboardData.types; const items = event.clipboardData.items; - for(let i=0; i { - self._dep.depend(); - return { ...self._getTopStack(), stack: self._stack }; - }, document.body); - + self.current = Blaze.renderWithData( + self.template, + () => { + self._dep.depend(); + return { ...self._getTopStack(), stack: self._stack }; + }, + document.body, + ); } else { self._dep.changed(); } @@ -101,7 +104,7 @@ window.Popup = new class { const self = this; return function(evt, tpl) { - const context = this.currentData && this.currentData() || this; + const context = (this.currentData && this.currentData()) || this; context.__afterConfirmAction = action; self.open(name).call(context, evt, tpl); }; @@ -136,7 +139,6 @@ window.Popup = new class { const openerElement = this._getTopStack().openerElement; $(openerElement).removeClass('is-active'); - this._stack = []; } } @@ -159,7 +161,7 @@ window.Popup = new class { return () => { Utils.windowResizeDep.depend(); - if(Utils.isMiniScreen()) return { left:0, top:0 }; + if (Utils.isMiniScreen()) return { left: 0, top: 0 }; const offset = $element.offset(); const popupWidth = 300 + 15; @@ -188,18 +190,19 @@ window.Popup = new class { return title !== translationKey ? title : defaultTitle; }; } -}(); +})(); // We close a potential opened popup on any left click on the document, or go // one step back by pressing escape. const escapeActions = ['back', 'close']; -escapeActions.forEach((actionName) => { - EscapeActions.register(`popup-${actionName}`, +escapeActions.forEach(actionName => { + EscapeActions.register( + `popup-${actionName}`, () => Popup[actionName](), () => Popup.isOpen(), { noClickEscapeOn: '.js-pop-over,.js-open-card-title-popup', enabledOnClick: actionName === 'close', - } + }, ); }); diff --git a/client/lib/textComplete.js b/client/lib/textComplete.js index 69820514..0261d7f6 100644 --- a/client/lib/textComplete.js +++ b/client/lib/textComplete.js @@ -47,9 +47,6 @@ $.fn.escapeableTextComplete = function(strategies, options, ...otherArgs) { }); }; -EscapeActions.register('textcomplete', - () => {}, - () => dropdownMenuIsOpened, { - noClickEscapeOn: '.textcomplete-dropdown', - } -); +EscapeActions.register('textcomplete', () => {}, () => dropdownMenuIsOpened, { + noClickEscapeOn: '.textcomplete-dropdown', +}); diff --git a/client/lib/unsavedEdits.js b/client/lib/unsavedEdits.js index 9c02eb84..a67d0eef 100644 --- a/client/lib/unsavedEdits.js +++ b/client/lib/unsavedEdits.js @@ -34,13 +34,13 @@ UnsavedEdits = { }, has({ fieldName, docId }) { - return Boolean(this.get({fieldName, docId})); + return Boolean(this.get({ fieldName, docId })); }, set({ fieldName, docId }, value) { const currentDoc = this._getCollectionDocument(fieldName, docId); if (currentDoc) { - UnsavedEditCollection.update(currentDoc._id, { $set: { value }}); + UnsavedEditCollection.update(currentDoc._id, { $set: { value } }); } else { UnsavedEditCollection.insert({ fieldName, @@ -58,7 +58,7 @@ UnsavedEdits = { }, _getCollectionDocument(fieldName, docId) { - return UnsavedEditCollection.findOne({fieldName, docId}); + return UnsavedEditCollection.findOne({ fieldName, docId }); }, }; diff --git a/client/lib/utils.js b/client/lib/utils.js index e2339763..5681273e 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -2,20 +2,26 @@ Utils = { // XXX We should remove these two methods goBoardId(_id) { const board = Boards.findOne(_id); - return board && FlowRouter.go('board', { - id: board._id, - slug: board.slug, - }); + return ( + board && + FlowRouter.go('board', { + id: board._id, + slug: board.slug, + }) + ); }, goCardId(_id) { const card = Cards.findOne(_id); const board = Boards.findOne(card.boardId); - return board && FlowRouter.go('card', { - cardId: card._id, - boardId: board._id, - slug: board.slug, - }); + return ( + board && + FlowRouter.go('card', { + cardId: card._id, + boardId: board._id, + slug: board.slug, + }) + ); }, capitalize(string) { @@ -104,13 +110,21 @@ Utils = { return window.matchMedia(query).matches; }; - if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) { + if ( + 'ontouchstart' in window || + (window.DocumentTouch && document instanceof window.DocumentTouch) + ) { return true; } // include the 'heartz' as a way to have a non matching MQ to help terminate the join // https://git.io/vznFH - const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''); + const query = [ + '(', + prefixes.join('touch-enabled),('), + 'heartz', + ')', + ].join(''); return mq(query); })(); Utils.isTouchDevice = () => isTouchable; @@ -120,7 +134,7 @@ Utils = { calculateTouchDistance(touchA, touchB) { return Math.sqrt( Math.pow(touchA.screenX - touchB.screenX, 2) + - Math.pow(touchA.screenY - touchB.screenY, 2) + Math.pow(touchA.screenY - touchB.screenY, 2), ); }, @@ -136,7 +150,11 @@ Utils = { lastTouch = touches[touches.length - 1]; }); $(document).on('touchend', selector, function(e) { - if (touchStart && lastTouch && Utils.calculateTouchDistance(touchStart, lastTouch) <= 20) { + if ( + touchStart && + lastTouch && + Utils.calculateTouchDistance(touchStart, lastTouch) <= 20 + ) { e.preventDefault(); const clickEvent = document.createEvent('MouseEvents'); clickEvent.initEvent('click', true, true); @@ -145,30 +163,30 @@ Utils = { }); }, - manageCustomUI(){ + manageCustomUI() { Meteor.call('getCustomUI', (err, data) => { - if (err && err.error[0] === 'var-not-exist'){ + if (err && err.error[0] === 'var-not-exist') { Session.set('customUI', false); // siteId || address server not defined } - if (!err){ + if (!err) { Utils.setCustomUI(data); } }); }, - setCustomUI(data){ + setCustomUI(data) { const currentBoard = Boards.findOne(Session.get('currentBoard')); if (currentBoard) { - DocHead.setTitle(`${currentBoard.title } - ${ data.productName}`); + DocHead.setTitle(`${currentBoard.title} - ${data.productName}`); } else { DocHead.setTitle(`${data.productName}`); } }, - setMatomo(data){ + setMatomo(data) { window._paq = window._paq || []; window._paq.push(['setDoNotTrack', data.doNotTrack]); - if (data.withUserName){ + if (data.withUserName) { window._paq.push(['setUserId', Meteor.user().username]); } window._paq.push(['trackPageView']); @@ -196,12 +214,12 @@ Utils = { manageMatomo() { const matomo = Session.get('matomo'); - if (matomo === undefined){ + if (matomo === undefined) { Meteor.call('getMatomoConf', (err, data) => { - if (err && err.error[0] === 'var-not-exist'){ + if (err && err.error[0] === 'var-not-exist') { Session.set('matomo', false); // siteId || address server not defined } - if (!err){ + if (!err) { Utils.setMatomo(data); } }); @@ -220,15 +238,21 @@ Utils = { finalString += element.text().toLowerCase(); } else if (element.hasClass('user-details')) { let username = element.find('input').val(); - if(username === undefined || username === ''){ + if (username === undefined || username === '') { username = '*'; } - finalString += `${element.find('.trigger-text').text().toLowerCase() } ${ username}`; + finalString += `${element + .find('.trigger-text') + .text() + .toLowerCase()} ${username}`; } else if (element.find('select').length > 0) { - finalString += element.find('select option:selected').text().toLowerCase(); + finalString += element + .find('select option:selected') + .text() + .toLowerCase(); } else if (element.find('input').length > 0) { let inputvalue = element.find('input').val(); - if(inputvalue === undefined || inputvalue === ''){ + if (inputvalue === undefined || inputvalue === '') { inputvalue = '*'; } finalString += inputvalue; diff --git a/config/accounts.js b/config/accounts.js index e7faa4cd..f88f2d83 100644 --- a/config/accounts.js +++ b/config/accounts.js @@ -1,20 +1,25 @@ const passwordField = AccountsTemplates.removeField('password'); const emailField = AccountsTemplates.removeField('email'); -AccountsTemplates.addFields([{ - _id: 'username', - type: 'text', - displayName: 'username', - required: true, - minLength: 2, -}, emailField, passwordField, { - _id: 'invitationcode', - type: 'text', - displayName: 'Invitation Code', - required: false, - minLength: 6, - template: 'invitationCode', -}]); +AccountsTemplates.addFields([ + { + _id: 'username', + type: 'text', + displayName: 'username', + required: true, + minLength: 2, + }, + emailField, + passwordField, + { + _id: 'invitationcode', + type: 'text', + displayName: 'Invitation Code', + required: false, + minLength: 6, + template: 'invitationCode', + }, +]); AccountsTemplates.configure({ defaultLayout: 'userFormsLayout', @@ -34,7 +39,8 @@ AccountsTemplates.configure({ }); ['signIn', 'signUp', 'resetPwd', 'forgotPwd', 'enrollAccount'].forEach( - (routeName) => AccountsTemplates.configureRoute(routeName)); + routeName => AccountsTemplates.configureRoute(routeName), +); // We display the form to change the password in a popup window that already // have a title, so we unset the title automatically displayed by useraccounts. @@ -56,15 +62,25 @@ AccountsTemplates.configureRoute('changePwd', { }); if (Meteor.isServer) { - - ['resetPassword-subject', 'resetPassword-text', 'verifyEmail-subject', 'verifyEmail-text', 'enrollAccount-subject', 'enrollAccount-text'].forEach((str) => { + [ + 'resetPassword-subject', + 'resetPassword-text', + 'verifyEmail-subject', + 'verifyEmail-text', + 'enrollAccount-subject', + 'enrollAccount-text', + ].forEach(str => { const [templateName, field] = str.split('-'); Accounts.emailTemplates[templateName][field] = (user, url) => { - return TAPi18n.__(`email-${str}`, { - url, - user: user.getName(), - siteName: Accounts.emailTemplates.siteName, - }, user.getLanguage()); + return TAPi18n.__( + `email-${str}`, + { + url, + user: user.getName(), + siteName: Accounts.emailTemplates.siteName, + }, + user.getLanguage(), + ); }; }); } diff --git a/config/router.js b/config/router.js index 80e89e4c..ad76035b 100644 --- a/config/router.js +++ b/config/router.js @@ -1,7 +1,9 @@ let previousPath; -FlowRouter.triggers.exit([({path}) => { - previousPath = path; -}]); +FlowRouter.triggers.exit([ + ({ path }) => { + previousPath = path; + }, +]); FlowRouter.route('/', { name: 'home', @@ -192,9 +194,11 @@ const redirections = { _.each(redirections, (newPath, oldPath) => { FlowRouter.route(oldPath, { - triggersEnter: [(context, redirect) => { - redirect(FlowRouter.path(newPath, context.params)); - }], + triggersEnter: [ + (context, redirect) => { + redirect(FlowRouter.path(newPath, context.params)); + }, + ], }); }); diff --git a/models/accountSettings.js b/models/accountSettings.js index c4240f84..c68e905c 100644 --- a/models/accountSettings.js +++ b/models/accountSettings.js @@ -37,7 +37,7 @@ AccountSettings.attachSchema( } }, }, - }) + }), ); AccountSettings.allow({ @@ -47,11 +47,6 @@ AccountSettings.allow({ }, }); -AccountSettings.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - if (Meteor.isServer) { Meteor.startup(() => { AccountSettings._collection._ensureIndex({ modifiedAt: -1 }); @@ -62,7 +57,7 @@ if (Meteor.isServer) { booleanValue: false, sort: 0, }, - } + }, ); AccountSettings.upsert( { _id: 'accounts-allowUserNameChange' }, @@ -71,7 +66,7 @@ if (Meteor.isServer) { booleanValue: false, sort: 1, }, - } + }, ); }); } diff --git a/models/actions.js b/models/actions.js index 8ac764aa..e9fa9114 100644 --- a/models/actions.js +++ b/models/actions.js @@ -20,11 +20,6 @@ Actions.helpers({ }, }); -Actions.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - if (Meteor.isServer) { Meteor.startup(() => { Actions._collection._ensureIndex({ modifiedAt: -1 }); diff --git a/models/activities.js b/models/activities.js index 0e158802..e76f3ad1 100644 --- a/models/activities.js +++ b/models/activities.js @@ -71,11 +71,6 @@ Activities.after.insert((userId, doc) => { RulesHelper.executeRules(activity); }); -Activities.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - if (Meteor.isServer) { // For efficiency create indexes on the date of creation, and on the date of // creation in conjunction with the card or board id, as corresponding views @@ -87,15 +82,15 @@ if (Meteor.isServer) { Activities._collection._ensureIndex({ boardId: 1, createdAt: -1 }); Activities._collection._ensureIndex( { commentId: 1 }, - { partialFilterExpression: { commentId: { $exists: true } } } + { partialFilterExpression: { commentId: { $exists: true } } }, ); Activities._collection._ensureIndex( { attachmentId: 1 }, - { partialFilterExpression: { attachmentId: { $exists: true } } } + { partialFilterExpression: { attachmentId: { $exists: true } } }, ); Activities._collection._ensureIndex( { customFieldId: 1 }, - { partialFilterExpression: { customFieldId: { $exists: true } } } + { partialFilterExpression: { customFieldId: { $exists: true } } }, ); // Label activity did not work yet, unable to edit labels when tried this. //Activities._collection._dropIndex({ labelId: 1 }, { "indexKey": -1 }); @@ -205,20 +200,20 @@ if (Meteor.isServer) { if (board) { const watchingUsers = _.pluck( _.where(board.watchers, { level: 'watching' }), - 'userId' + 'userId', ); const trackingUsers = _.pluck( _.where(board.watchers, { level: 'tracking' }), - 'userId' + 'userId', ); watchers = _.union( watchers, watchingUsers, - _.intersection(participants, trackingUsers) + _.intersection(participants, trackingUsers), ); } - Notifications.getUsers(watchers).forEach((user) => { + Notifications.getUsers(watchers).forEach(user => { Notifications.notify(user, title, description, params); }); diff --git a/models/announcements.js b/models/announcements.js index f3a62244..c08710b8 100644 --- a/models/announcements.js +++ b/models/announcements.js @@ -42,7 +42,7 @@ Announcements.attachSchema( } }, }, - }) + }), ); Announcements.allow({ @@ -52,11 +52,6 @@ Announcements.allow({ }, }); -Announcements.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - if (Meteor.isServer) { Meteor.startup(() => { Announcements._collection._ensureIndex({ modifiedAt: -1 }); diff --git a/models/attachments.js b/models/attachments.js index 893b5aca..0616c79f 100644 --- a/models/attachments.js +++ b/models/attachments.js @@ -12,7 +12,7 @@ Attachments = new FS.Collection('attachments', { // XXX Should we use `beforeWrite` option of CollectionFS instead of // collection-hooks? // We should use `beforeWrite`. - beforeWrite: (fileObj) => { + beforeWrite: fileObj => { if (!fileObj.isImage()) { return { type: 'application/octet-stream', @@ -84,7 +84,7 @@ if (Meteor.isServer) { $unset: { source: '', }, - } + }, ); } }); diff --git a/models/boards.js b/models/boards.js index 2792f80a..5c0b58e7 100644 --- a/models/boards.js +++ b/models/boards.js @@ -101,7 +101,7 @@ Boards.attachSchema( const colors = Boards.simpleSchema()._schema['labels.$.color'] .allowedValues; const defaultLabelsColors = _.clone(colors).splice(0, 6); - return defaultLabelsColors.map((color) => ({ + return defaultLabelsColors.map(color => ({ color, _id: Random.id(6), name: '', @@ -342,7 +342,7 @@ Boards.attachSchema( type: String, defaultValue: 'board', }, - }) + }), ); Boards.helpers({ @@ -355,7 +355,7 @@ Boards.helpers({ Swimlanes.find({ boardId: oldId, archived: false, - }).forEach((swimlane) => { + }).forEach(swimlane => { swimlane.type = 'swimlane'; swimlane.copy(_id); }); @@ -382,7 +382,7 @@ Boards.helpers({ isActiveMember(userId) { if (userId) { return this.members.find( - (member) => member.userId === userId && member.isActive + member => member.userId === userId && member.isActive, ); } else { return false; @@ -396,14 +396,14 @@ Boards.helpers({ cards() { return Cards.find( { boardId: this._id, archived: false }, - { sort: { title: 1 } } + { sort: { title: 1 } }, ); }, lists() { return Lists.find( { boardId: this._id, archived: false }, - { sort: { sort: 1 } } + { sort: { sort: 1 } }, ); }, @@ -418,7 +418,7 @@ Boards.helpers({ swimlanes() { return Swimlanes.find( { boardId: this._id, archived: false }, - { sort: { sort: 1 } } + { sort: { sort: 1 } }, ); }, @@ -432,7 +432,7 @@ Boards.helpers({ }, { sort: { sort: 1 }, - } + }, ); }, @@ -535,7 +535,7 @@ Boards.helpers({ customFields() { return CustomFields.find( { boardIds: { $in: [this._id] } }, - { sort: { name: 1 } } + { sort: { name: 1 } }, ); }, @@ -848,7 +848,7 @@ Boards.mutations({ isAdmin, isNoComments, isCommentOnly, - currentUserId = Meteor.userId() + currentUserId = Meteor.userId(), ) { const memberIndex = this.memberIndex(memberId); // do not allow change permission of self @@ -884,9 +884,9 @@ Boards.mutations({ function boardRemover(userId, doc) { [Cards, Lists, Swimlanes, Integrations, Rules, Activities].forEach( - (element) => { + element => { element.remove({ boardId: doc._id }); - } + }, ); } @@ -927,7 +927,7 @@ if (Meteor.isServer) { _.findWhere(doc.members, { userId: removedMemberId, isAdmin: true, - }) + }), ); }, fetch: ['members'], @@ -973,7 +973,7 @@ if (Meteor.isServer) { _id: 1, 'members.userId': 1, }, - { unique: true } + { unique: true }, ); Boards._collection._ensureIndex({ 'members.userId': 1 }); }); @@ -1009,12 +1009,12 @@ if (Meteor.isServer) { labelIds: removedLabelId, }, }, - { multi: true } + { multi: true }, ); }); const foreachRemovedMember = (doc, modifier, callback) => { - Object.keys(modifier).forEach((set) => { + Object.keys(modifier).forEach(set => { if (modifier[set] !== false) { return; } @@ -1030,11 +1030,6 @@ if (Meteor.isServer) { }); }; - Boards.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); - }); - // Remove a member from all objects of the board before leaving the board Boards.before.update((userId, doc, fieldNames, modifier) => { if (!_.contains(fieldNames, 'members')) { @@ -1043,7 +1038,7 @@ if (Meteor.isServer) { if (modifier.$set) { const boardId = doc._id; - foreachRemovedMember(doc, modifier.$set, (memberId) => { + foreachRemovedMember(doc, modifier.$set, memberId => { Cards.update( { boardId }, { @@ -1052,7 +1047,7 @@ if (Meteor.isServer) { watchers: memberId, }, }, - { multi: true } + { multi: true }, ); Lists.update( @@ -1062,7 +1057,7 @@ if (Meteor.isServer) { watchers: memberId, }, }, - { multi: true } + { multi: true }, ); const board = Boards._transform(doc); @@ -1112,7 +1107,7 @@ if (Meteor.isServer) { // Say goodbye to the former member if (modifier.$set) { - foreachRemovedMember(doc, modifier.$set, (memberId) => { + foreachRemovedMember(doc, modifier.$set, memberId => { Activities.insert({ userId, memberId, @@ -1143,7 +1138,7 @@ if (Meteor.isServer) { // admins can access boards of any user Authentication.checkAdminOrCondition( req.userId, - req.userId === paramUserId + req.userId === paramUserId, ); const data = Boards.find( @@ -1153,7 +1148,7 @@ if (Meteor.isServer) { }, { sort: ['title'], - } + }, ).map(function(board) { return { _id: board._id, @@ -1332,7 +1327,7 @@ if (Meteor.isServer) { if (!board.getLabel(name, color)) { Boards.direct.update( { _id: id }, - { $push: { labels: { _id: labelId, name, color } } } + { $push: { labels: { _id: labelId, name, color } } }, ); JsonRoutes.sendResult(res, { code: 200, @@ -1364,7 +1359,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('POST', '/api/boards/:boardId/members/:memberId', function( req, - res + res, ) { try { const boardId = req.params.boardId; @@ -1384,7 +1379,7 @@ if (Meteor.isServer) { isTrue(isAdmin), isTrue(isNoComments), isTrue(isCommentOnly), - req.userId + req.userId, ); JsonRoutes.sendResult(res, { diff --git a/models/cardComments.js b/models/cardComments.js index 8f727aa0..40723582 100644 --- a/models/cardComments.js +++ b/models/cardComments.js @@ -64,7 +64,7 @@ CardComments.attachSchema( } }, }, - }) + }), ); CardComments.allow({ @@ -107,11 +107,6 @@ function commentCreation(userId, doc) { }); } -CardComments.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - if (Meteor.isServer) { // Comments are often fetched within a card, so we create an index to make these // queries more efficient. @@ -125,7 +120,6 @@ if (Meteor.isServer) { }); CardComments.after.update((userId, doc) => { - const activity = Activities.findOne({ commentId: doc._id }); const card = Cards.findOne(doc.cardId); Activities.insert({ userId, @@ -139,7 +133,6 @@ if (Meteor.isServer) { }); CardComments.before.remove((userId, doc) => { - const activity = Activities.findOne({ commentId: doc._id }); const card = Cards.findOne(doc.cardId); Activities.insert({ userId, @@ -174,7 +167,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/comments', function( req, - res + res, ) { try { Authentication.checkUserId(req.userId); @@ -233,7 +226,7 @@ if (Meteor.isServer) { data: error, }); } - } + }, ); /** @@ -280,7 +273,7 @@ if (Meteor.isServer) { data: error, }); } - } + }, ); /** @@ -318,7 +311,7 @@ if (Meteor.isServer) { data: error, }); } - } + }, ); } diff --git a/models/cards.js b/models/cards.js index b873c086..211618a1 100644 --- a/models/cards.js +++ b/models/cards.js @@ -3,273 +3,298 @@ Cards = new Mongo.Collection('cards'); // XXX To improve pub/sub performances a card document should include a // de-normalized number of comments so we don't have to publish the whole list // of comments just to display the number of them in the board view. -Cards.attachSchema(new SimpleSchema({ - title: { - /** - * the title of the card - */ - type: String, - optional: true, - defaultValue: '', - }, - archived: { - /** - * is the card archived - */ - type: Boolean, - autoValue() { // eslint-disable-line consistent-return - if (this.isInsert && !this.isSet) { - return false; - } +Cards.attachSchema( + new SimpleSchema({ + title: { + /** + * the title of the card + */ + type: String, + optional: true, + defaultValue: '', }, - }, - parentId: { - /** - * ID of the parent card - */ - type: String, - optional: true, - defaultValue: '', - }, - listId: { - /** - * List ID where the card is - */ - type: String, - optional: true, - defaultValue: '', - }, - swimlaneId: { - /** - * Swimlane ID where the card is - */ - type: String, - }, - // The system could work without this `boardId` information (we could deduce - // the board identifier from the card), but it would make the system more - // difficult to manage and less efficient. - boardId: { - /** - * Board ID of the card - */ - type: String, - optional: true, - defaultValue: '', - }, - coverId: { - /** - * Cover ID of the card - */ - type: String, - optional: true, - defaultValue: '', - - }, - color: { - type: String, - optional: true, - allowedValues: [ - 'white', 'green', 'yellow', 'orange', 'red', 'purple', - 'blue', 'sky', 'lime', 'pink', 'black', - 'silver', 'peachpuff', 'crimson', 'plum', 'darkgreen', - 'slateblue', 'magenta', 'gold', 'navy', 'gray', - 'saddlebrown', 'paleturquoise', 'mistyrose', 'indigo', - ], - }, - createdAt: { - /** - * creation date - */ - type: Date, - // eslint-disable-next-line consistent-return - autoValue() { - if (this.isInsert) { - return new Date(); - } else { - this.unset(); - } + archived: { + /** + * is the card archived + */ + type: Boolean, + // eslint-disable-next-line consistent-return + autoValue() { + // eslint-disable-line consistent-return + if (this.isInsert && !this.isSet) { + return false; + } + }, }, - }, - modifiedAt: { - type: Date, - denyUpdate: false, - // eslint-disable-next-line consistent-return - autoValue() { - if (this.isInsert || this.isUpsert || this.isUpdate) { - return new Date(); - } else { - this.unset(); - } + parentId: { + /** + * ID of the parent card + */ + type: String, + optional: true, + defaultValue: '', }, - }, - customFields: { - /** - * list of custom fields - */ - type: [Object], - optional: true, - defaultValue: [], - }, - 'customFields.$': { - type: new SimpleSchema({ - _id: { - /** - * the ID of the related custom field - */ - type: String, - optional: true, - defaultValue: '', + listId: { + /** + * List ID where the card is + */ + type: String, + optional: true, + defaultValue: '', + }, + swimlaneId: { + /** + * Swimlane ID where the card is + */ + type: String, + }, + // The system could work without this `boardId` information (we could deduce + // the board identifier from the card), but it would make the system more + // difficult to manage and less efficient. + boardId: { + /** + * Board ID of the card + */ + type: String, + optional: true, + defaultValue: '', + }, + coverId: { + /** + * Cover ID of the card + */ + type: String, + optional: true, + defaultValue: '', + }, + color: { + type: String, + optional: true, + allowedValues: [ + 'white', + 'green', + 'yellow', + 'orange', + 'red', + 'purple', + 'blue', + 'sky', + 'lime', + 'pink', + 'black', + 'silver', + 'peachpuff', + 'crimson', + 'plum', + 'darkgreen', + 'slateblue', + 'magenta', + 'gold', + 'navy', + 'gray', + 'saddlebrown', + 'paleturquoise', + 'mistyrose', + 'indigo', + ], + }, + createdAt: { + /** + * creation date + */ + type: Date, + // eslint-disable-next-line consistent-return + autoValue() { + if (this.isInsert) { + return new Date(); + } else { + this.unset(); + } + }, + }, + modifiedAt: { + type: Date, + denyUpdate: false, + // eslint-disable-next-line consistent-return + autoValue() { + if (this.isInsert || this.isUpsert || this.isUpdate) { + return new Date(); + } else { + this.unset(); + } }, - value: { - /** - * value attached to the custom field - */ - type: Match.OneOf(String, Number, Boolean, Date), - optional: true, - defaultValue: '', + }, + customFields: { + /** + * list of custom fields + */ + type: [Object], + optional: true, + defaultValue: [], + }, + 'customFields.$': { + type: new SimpleSchema({ + _id: { + /** + * the ID of the related custom field + */ + type: String, + optional: true, + defaultValue: '', + }, + value: { + /** + * value attached to the custom field + */ + type: Match.OneOf(String, Number, Boolean, Date), + optional: true, + defaultValue: '', + }, + }), + }, + dateLastActivity: { + /** + * Date of last activity + */ + type: Date, + autoValue() { + return new Date(); }, - }), - }, - dateLastActivity: { - /** - * Date of last activity - */ - type: Date, - autoValue() { - return new Date(); }, - }, - description: { - /** - * description of the card - */ - type: String, - optional: true, - defaultValue: '', - }, - requestedBy: { - /** - * who requested the card (ID of the user) - */ - type: String, - optional: true, - defaultValue: '', - }, - assignedBy: { - /** - * who assigned the card (ID of the user) - */ - type: String, - optional: true, - defaultValue: '', - }, - labelIds: { - /** - * list of labels ID the card has - */ - type: [String], - optional: true, - defaultValue: [], - }, - members: { - /** - * list of members (user IDs) - */ - type: [String], - optional: true, - defaultValue: [], - }, - receivedAt: { - /** - * Date the card was received - */ - type: Date, - optional: true, - }, - startAt: { - /** - * Date the card was started to be worked on - */ - type: Date, - optional: true, - }, - dueAt: { - /** - * Date the card is due - */ - type: Date, - optional: true, - }, - endAt: { - /** - * Date the card ended - */ - type: Date, - optional: true, - }, - spentTime: { - /** - * How much time has been spent on this - */ - type: Number, - decimal: true, - optional: true, - defaultValue: 0, - }, - isOvertime: { - /** - * is the card over time? - */ - type: Boolean, - defaultValue: false, - optional: true, - }, - // XXX Should probably be called `authorId`. Is it even needed since we have - // the `members` field? - userId: { - /** - * user ID of the author of the card - */ - type: String, - autoValue() { // eslint-disable-line consistent-return - if (this.isInsert && !this.isSet) { - return this.userId; - } + description: { + /** + * description of the card + */ + type: String, + optional: true, + defaultValue: '', }, - }, - sort: { - /** - * Sort value - */ - type: Number, - decimal: true, - defaultValue: '', - }, - subtaskSort: { - /** - * subtask sort value - */ - type: Number, - decimal: true, - defaultValue: -1, - optional: true, - }, - type: { - /** - * type of the card - */ - type: String, - defaultValue: 'cardType-card', - }, - linkedId: { - /** - * ID of the linked card - */ - type: String, - optional: true, - defaultValue: '', - }, -})); + requestedBy: { + /** + * who requested the card (ID of the user) + */ + type: String, + optional: true, + defaultValue: '', + }, + assignedBy: { + /** + * who assigned the card (ID of the user) + */ + type: String, + optional: true, + defaultValue: '', + }, + labelIds: { + /** + * list of labels ID the card has + */ + type: [String], + optional: true, + defaultValue: [], + }, + members: { + /** + * list of members (user IDs) + */ + type: [String], + optional: true, + defaultValue: [], + }, + receivedAt: { + /** + * Date the card was received + */ + type: Date, + optional: true, + }, + startAt: { + /** + * Date the card was started to be worked on + */ + type: Date, + optional: true, + }, + dueAt: { + /** + * Date the card is due + */ + type: Date, + optional: true, + }, + endAt: { + /** + * Date the card ended + */ + type: Date, + optional: true, + }, + spentTime: { + /** + * How much time has been spent on this + */ + type: Number, + decimal: true, + optional: true, + defaultValue: 0, + }, + isOvertime: { + /** + * is the card over time? + */ + type: Boolean, + defaultValue: false, + optional: true, + }, + // XXX Should probably be called `authorId`. Is it even needed since we have + // the `members` field? + userId: { + /** + * user ID of the author of the card + */ + type: String, + // eslint-disable-next-line consistent-return + autoValue() { + // eslint-disable-line consistent-return + if (this.isInsert && !this.isSet) { + return this.userId; + } + }, + }, + sort: { + /** + * Sort value + */ + type: Number, + decimal: true, + defaultValue: '', + }, + subtaskSort: { + /** + * subtask sort value + */ + type: Number, + decimal: true, + defaultValue: -1, + optional: true, + }, + type: { + /** + * type of the card + */ + type: String, + defaultValue: 'cardType-card', + }, + linkedId: { + /** + * ID of the linked card + */ + type: String, + optional: true, + defaultValue: '', + }, + }), +); Cards.allow({ insert(userId, doc) { @@ -289,15 +314,21 @@ Cards.helpers({ const oldBoard = Boards.findOne(this.boardId); const oldBoardLabels = oldBoard.labels; // Get old label names - const oldCardLabels = _.pluck(_.filter(oldBoardLabels, (label) => { - return _.contains(this.labelIds, label._id); - }), 'name'); + const oldCardLabels = _.pluck( + _.filter(oldBoardLabels, label => { + return _.contains(this.labelIds, label._id); + }), + 'name', + ); const newBoard = Boards.findOne(boardId); const newBoardLabels = newBoard.labels; - const newCardLabels = _.pluck(_.filter(newBoardLabels, (label) => { - return _.contains(oldCardLabels, label.name); - }), '_id'); + const newCardLabels = _.pluck( + _.filter(newBoardLabels, label => { + return _.contains(oldCardLabels, label.name); + }), + '_id', + ); const oldId = this._id; const oldCard = Cards.findOne(oldId); @@ -305,10 +336,13 @@ Cards.helpers({ // Copy Custom Fields if (oldBoard._id !== boardId) { CustomFields.find({ - _id: {$in: oldCard.customFields.map((cf) => { return cf._id; })}, - }).forEach((cf) => { - if (!_.contains(cf.boardIds, boardId)) - cf.addBoard(boardId); + _id: { + $in: oldCard.customFields.map(cf => { + return cf._id; + }), + }, + }).forEach(cf => { + if (!_.contains(cf.boardIds, boardId)) cf.addBoard(boardId); }); } @@ -321,26 +355,26 @@ Cards.helpers({ const _id = Cards.insert(this); // Copy attachments - oldCard.attachments().forEach((att) => { + oldCard.attachments().forEach(att => { att.cardId = _id; delete att._id; return Attachments.insert(att); }); // copy checklists - Checklists.find({cardId: oldId}).forEach((ch) => { + Checklists.find({ cardId: oldId }).forEach(ch => { ch.copy(_id); }); // copy subtasks - Cards.find({parentId: oldId}).forEach((subtask) => { + Cards.find({ parentId: oldId }).forEach(subtask => { subtask.parentId = _id; subtask._id = null; Cards.insert(subtask); }); // copy card comments - CardComments.find({cardId: oldId}).forEach((cmt) => { + CardComments.find({ cardId: oldId }).forEach(cmt => { cmt.copy(_id); }); @@ -357,7 +391,7 @@ Cards.helpers({ labels() { const boardLabels = this.board().labels; - const cardLabels = _.filter(boardLabels, (label) => { + const cardLabels = _.filter(boardLabels, label => { return _.contains(this.labelIds, label._id); }); return cardLabels; @@ -377,27 +411,45 @@ Cards.helpers({ activities() { if (this.isLinkedCard()) { - return Activities.find({cardId: this.linkedId}, {sort: {createdAt: -1}}); + return Activities.find( + { cardId: this.linkedId }, + { sort: { createdAt: -1 } }, + ); } else if (this.isLinkedBoard()) { - return Activities.find({boardId: this.linkedId}, {sort: {createdAt: -1}}); + return Activities.find( + { boardId: this.linkedId }, + { sort: { createdAt: -1 } }, + ); } else { - return Activities.find({cardId: this._id}, {sort: {createdAt: -1}}); + return Activities.find({ cardId: this._id }, { sort: { createdAt: -1 } }); } }, comments() { if (this.isLinkedCard()) { - return CardComments.find({cardId: this.linkedId}, {sort: {createdAt: -1}}); + return CardComments.find( + { cardId: this.linkedId }, + { sort: { createdAt: -1 } }, + ); } else { - return CardComments.find({cardId: this._id}, {sort: {createdAt: -1}}); + return CardComments.find( + { cardId: this._id }, + { sort: { createdAt: -1 } }, + ); } }, attachments() { if (this.isLinkedCard()) { - return Attachments.find({cardId: this.linkedId}, {sort: {uploadedAt: -1}}); + return Attachments.find( + { cardId: this.linkedId }, + { sort: { uploadedAt: -1 } }, + ); } else { - return Attachments.find({cardId: this._id}, {sort: {uploadedAt: -1}}); + return Attachments.find( + { cardId: this._id }, + { sort: { uploadedAt: -1 } }, + ); } }, @@ -410,32 +462,39 @@ Cards.helpers({ checklists() { if (this.isLinkedCard()) { - return Checklists.find({cardId: this.linkedId}, {sort: { sort: 1 } }); + return Checklists.find({ cardId: this.linkedId }, { sort: { sort: 1 } }); } else { - return Checklists.find({cardId: this._id}, {sort: { sort: 1 } }); + return Checklists.find({ cardId: this._id }, { sort: { sort: 1 } }); } }, checklistItemCount() { const checklists = this.checklists().fetch(); - return checklists.map((checklist) => { - return checklist.itemCount(); - }).reduce((prev, next) => { - return prev + next; - }, 0); + return checklists + .map(checklist => { + return checklist.itemCount(); + }) + .reduce((prev, next) => { + return prev + next; + }, 0); }, checklistFinishedCount() { const checklists = this.checklists().fetch(); - return checklists.map((checklist) => { - return checklist.finishedCount(); - }).reduce((prev, next) => { - return prev + next; - }, 0); + return checklists + .map(checklist => { + return checklist.finishedCount(); + }) + .reduce((prev, next) => { + return prev + next; + }, 0); }, checklistFinished() { - return this.hasChecklist() && this.checklistItemCount() === this.checklistFinishedCount(); + return ( + this.hasChecklist() && + this.checklistItemCount() === this.checklistFinishedCount() + ); }, hasChecklist() { @@ -443,25 +502,31 @@ Cards.helpers({ }, subtasks() { - return Cards.find({ - parentId: this._id, - archived: false, - }, { - sort: { - sort: 1, + return Cards.find( + { + parentId: this._id, + archived: false, }, - }); + { + sort: { + sort: 1, + }, + }, + ); }, allSubtasks() { - return Cards.find({ - parentId: this._id, - archived: false, - }, { - sort: { - sort: 1, + return Cards.find( + { + parentId: this._id, + archived: false, }, - }); + { + sort: { + sort: 1, + }, + }, + ); }, subtasksCount() { @@ -493,16 +558,15 @@ Cards.helpers({ // customFields with definitions customFieldsWD() { - // get all definitions const definitions = CustomFields.find({ - boardIds: {$in: [this.boardId]}, + boardIds: { $in: [this.boardId] }, }).fetch(); // match right definition to each field if (!this.customFields) return []; - return this.customFields.map((customField) => { - const definition = definitions.find((definition) => { + return this.customFields.map(customField => { + const definition = definitions.find(definition => { return definition._id === customField._id; }); if (!definition) { @@ -510,7 +574,10 @@ Cards.helpers({ } //search for "True Value" which is for DropDowns other then the Value (which is the id) let trueValue = customField.value; - if (definition.settings.dropdownItems && definition.settings.dropdownItems.length > 0) { + if ( + definition.settings.dropdownItems && + definition.settings.dropdownItems.length > 0 + ) { for (let i = 0; i < definition.settings.dropdownItems.length; i++) { if (definition.settings.dropdownItems[i]._id === customField.value) { trueValue = definition.settings.dropdownItems[i].name; @@ -527,8 +594,7 @@ Cards.helpers({ }, colorClass() { - if (this.color) - return this.color; + if (this.color) return this.color; return ''; }, @@ -545,7 +611,11 @@ Cards.helpers({ const list = Lists.findOne({ _id: this.listId, }); - if (!list.getWipLimit('soft') && list.getWipLimit('enabled') && list.getWipLimit('value') === list.cards().count()) { + if ( + !list.getWipLimit('soft') && + list.getWipLimit('enabled') && + list.getWipLimit('value') === list.cards().count() + ) { return false; } return true; @@ -574,7 +644,7 @@ Cards.helpers({ let crtParentId = this.parentId; while (crtParentId !== '') { const crt = Cards.findOne(crtParentId); - if ((crt === null) || (crt === undefined)) { + if (crt === null || crt === undefined) { // maybe it has been deleted break; } @@ -594,7 +664,7 @@ Cards.helpers({ let crtParentId = this.parentId; while (crtParentId !== '') { const crt = Cards.findOne(crtParentId); - if ((crt === null) || (crt === undefined)) { + if (crt === null || crt === undefined) { // maybe it has been deleted break; } @@ -610,9 +680,11 @@ Cards.helpers({ }, parentString(sep) { - return this.parentList().map(function(elem) { - return elem.title; - }).join(sep); + return this.parentList() + .map(function(elem) { + return elem.title; + }) + .join(sep); }, isTopLevel() { @@ -633,30 +705,23 @@ Cards.helpers({ setDescription(description) { if (this.isLinkedCard()) { - return Cards.update({_id: this.linkedId}, {$set: {description}}); + return Cards.update({ _id: this.linkedId }, { $set: { description } }); } else if (this.isLinkedBoard()) { - return Boards.update({_id: this.linkedId}, {$set: {description}}); + return Boards.update({ _id: this.linkedId }, { $set: { description } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {description}} - ); + return Cards.update({ _id: this._id }, { $set: { description } }); } }, getDescription() { if (this.isLinkedCard()) { - const card = Cards.findOne({_id: this.linkedId}); - if (card && card.description) - return card.description; - else - return null; + const card = Cards.findOne({ _id: this.linkedId }); + if (card && card.description) return card.description; + else return null; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({_id: this.linkedId}); - if (board && board.description) - return board.description; - else - return null; + const board = Boards.findOne({ _id: this.linkedId }); + if (board && board.description) return board.description; + else return null; } else if (this.description) { return this.description; } else { @@ -666,11 +731,11 @@ Cards.helpers({ getMembers() { if (this.isLinkedCard()) { - const card = Cards.findOne({_id: this.linkedId}); + const card = Cards.findOne({ _id: this.linkedId }); return card.members; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({_id: this.linkedId}); - return board.activeMembers().map((member) => { + const board = Boards.findOne({ _id: this.linkedId }); + return board.activeMembers().map(member => { return member.userId; }); } else { @@ -682,15 +747,15 @@ Cards.helpers({ if (this.isLinkedCard()) { return Cards.update( { _id: this.linkedId }, - { $addToSet: { members: memberId }} + { $addToSet: { members: memberId } }, ); } else if (this.isLinkedBoard()) { - const board = Boards.findOne({_id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.addMember(memberId); } else { return Cards.update( { _id: this._id }, - { $addToSet: { members: memberId}} + { $addToSet: { members: memberId } }, ); } }, @@ -699,16 +764,13 @@ Cards.helpers({ if (this.isLinkedCard()) { return Cards.update( { _id: this.linkedId }, - { $pull: { members: memberId }} + { $pull: { members: memberId } }, ); } else if (this.isLinkedBoard()) { - const board = Boards.findOne({_id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.removeMember(memberId); } else { - return Cards.update( - { _id: this._id }, - { $pull: { members: memberId}} - ); + return Cards.update({ _id: this._id }, { $pull: { members: memberId } }); } }, @@ -722,7 +784,7 @@ Cards.helpers({ getReceived() { if (this.isLinkedCard()) { - const card = Cards.findOne({_id: this.linkedId}); + const card = Cards.findOne({ _id: this.linkedId }); return card.receivedAt; } else { return this.receivedAt; @@ -731,24 +793,18 @@ Cards.helpers({ setReceived(receivedAt) { if (this.isLinkedCard()) { - return Cards.update( - {_id: this.linkedId}, - {$set: {receivedAt}} - ); + return Cards.update({ _id: this.linkedId }, { $set: { receivedAt } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {receivedAt}} - ); + return Cards.update({ _id: this._id }, { $set: { receivedAt } }); } }, getStart() { if (this.isLinkedCard()) { - const card = Cards.findOne({_id: this.linkedId}); + const card = Cards.findOne({ _id: this.linkedId }); return card.startAt; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({_id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.startAt; } else { return this.startAt; @@ -757,29 +813,20 @@ Cards.helpers({ setStart(startAt) { if (this.isLinkedCard()) { - return Cards.update( - { _id: this.linkedId }, - {$set: {startAt}} - ); + return Cards.update({ _id: this.linkedId }, { $set: { startAt } }); } else if (this.isLinkedBoard()) { - return Boards.update( - {_id: this.linkedId}, - {$set: {startAt}} - ); + return Boards.update({ _id: this.linkedId }, { $set: { startAt } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {startAt}} - ); + return Cards.update({ _id: this._id }, { $set: { startAt } }); } }, getDue() { if (this.isLinkedCard()) { - const card = Cards.findOne({_id: this.linkedId}); + const card = Cards.findOne({ _id: this.linkedId }); return card.dueAt; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({_id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.dueAt; } else { return this.dueAt; @@ -788,29 +835,20 @@ Cards.helpers({ setDue(dueAt) { if (this.isLinkedCard()) { - return Cards.update( - { _id: this.linkedId }, - {$set: {dueAt}} - ); + return Cards.update({ _id: this.linkedId }, { $set: { dueAt } }); } else if (this.isLinkedBoard()) { - return Boards.update( - {_id: this.linkedId}, - {$set: {dueAt}} - ); + return Boards.update({ _id: this.linkedId }, { $set: { dueAt } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {dueAt}} - ); + return Cards.update({ _id: this._id }, { $set: { dueAt } }); } }, getEnd() { if (this.isLinkedCard()) { - const card = Cards.findOne({_id: this.linkedId}); + const card = Cards.findOne({ _id: this.linkedId }); return card.endAt; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({_id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.endAt; } else { return this.endAt; @@ -819,20 +857,11 @@ Cards.helpers({ setEnd(endAt) { if (this.isLinkedCard()) { - return Cards.update( - { _id: this.linkedId }, - {$set: {endAt}} - ); + return Cards.update({ _id: this.linkedId }, { $set: { endAt } }); } else if (this.isLinkedBoard()) { - return Boards.update( - {_id: this.linkedId}, - {$set: {endAt}} - ); + return Boards.update({ _id: this.linkedId }, { $set: { endAt } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {endAt}} - ); + return Cards.update({ _id: this._id }, { $set: { endAt } }); } }, @@ -841,7 +870,7 @@ Cards.helpers({ const card = Cards.findOne({ _id: this.linkedId }); return card.isOvertime; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({ _id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.isOvertime; } else { return this.isOvertime; @@ -850,20 +879,11 @@ Cards.helpers({ setIsOvertime(isOvertime) { if (this.isLinkedCard()) { - return Cards.update( - { _id: this.linkedId }, - {$set: {isOvertime}} - ); + return Cards.update({ _id: this.linkedId }, { $set: { isOvertime } }); } else if (this.isLinkedBoard()) { - return Boards.update( - {_id: this.linkedId}, - {$set: {isOvertime}} - ); + return Boards.update({ _id: this.linkedId }, { $set: { isOvertime } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {isOvertime}} - ); + return Cards.update({ _id: this._id }, { $set: { isOvertime } }); } }, @@ -872,7 +892,7 @@ Cards.helpers({ const card = Cards.findOne({ _id: this.linkedId }); return card.spentTime; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({ _id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.spentTime; } else { return this.spentTime; @@ -881,20 +901,11 @@ Cards.helpers({ setSpentTime(spentTime) { if (this.isLinkedCard()) { - return Cards.update( - { _id: this.linkedId }, - {$set: {spentTime}} - ); + return Cards.update({ _id: this.linkedId }, { $set: { spentTime } }); } else if (this.isLinkedBoard()) { - return Boards.update( - {_id: this.linkedId}, - {$set: {spentTime}} - ); + return Boards.update({ _id: this.linkedId }, { $set: { spentTime } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {spentTime}} - ); + return Cards.update({ _id: this._id }, { $set: { spentTime } }); } }, @@ -911,7 +922,7 @@ Cards.helpers({ const card = Cards.findOne({ _id: this.linkedId }); return card.title; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({ _id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.title; } else { return this.title; @@ -924,7 +935,7 @@ Cards.helpers({ const board = Boards.findOne({ _id: card.boardId }); return board.title; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({ _id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.title; } else { const board = Boards.findOne({ _id: this.boardId }); @@ -934,20 +945,11 @@ Cards.helpers({ setTitle(title) { if (this.isLinkedCard()) { - return Cards.update( - { _id: this.linkedId }, - {$set: {title}} - ); + return Cards.update({ _id: this.linkedId }, { $set: { title } }); } else if (this.isLinkedBoard()) { - return Boards.update( - {_id: this.linkedId}, - {$set: {title}} - ); + return Boards.update({ _id: this.linkedId }, { $set: { title } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {title}} - ); + return Cards.update({ _id: this._id }, { $set: { title } }); } }, @@ -956,7 +958,7 @@ Cards.helpers({ const card = Cards.findOne({ _id: this.linkedId }); return card.archived; } else if (this.isLinkedBoard()) { - const board = Boards.findOne({ _id: this.linkedId}); + const board = Boards.findOne({ _id: this.linkedId }); return board.archived; } else { return this.archived; @@ -965,15 +967,9 @@ Cards.helpers({ setRequestedBy(requestedBy) { if (this.isLinkedCard()) { - return Cards.update( - { _id: this.linkedId }, - {$set: {requestedBy}} - ); + return Cards.update({ _id: this.linkedId }, { $set: { requestedBy } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {requestedBy}} - ); + return Cards.update({ _id: this._id }, { $set: { requestedBy } }); } }, @@ -981,22 +977,16 @@ Cards.helpers({ if (this.isLinkedCard()) { const card = Cards.findOne({ _id: this.linkedId }); return card.requestedBy; - } else { + } else { return this.requestedBy; } }, setAssignedBy(assignedBy) { if (this.isLinkedCard()) { - return Cards.update( - { _id: this.linkedId }, - {$set: {assignedBy}} - ); + return Cards.update({ _id: this.linkedId }, { $set: { assignedBy } }); } else { - return Cards.update( - {_id: this._id}, - {$set: {assignedBy}} - ); + return Cards.update({ _id: this._id }, { $set: { assignedBy } }); } }, @@ -1004,7 +994,7 @@ Cards.helpers({ if (this.isLinkedCard()) { const card = Cards.findOne({ _id: this.linkedId }); return card.assignedBy; - } else { + } else { return this.assignedBy; } }, @@ -1018,13 +1008,13 @@ Cards.mutations({ applyToChildren(funct) { Cards.find({ parentId: this._id, - }).forEach((card) => { + }).forEach(card => { funct(card); }); }, archive() { - this.applyToChildren((card) => { + this.applyToChildren(card => { return card.archive(); }); return { @@ -1035,7 +1025,7 @@ Cards.mutations({ }, restore() { - this.applyToChildren((card) => { + this.applyToChildren(card => { return card.restore(); }); return { @@ -1049,25 +1039,34 @@ Cards.mutations({ // Copy Custom Fields if (this.boardId !== boardId) { CustomFields.find({ - _id: {$in: this.customFields.map((cf) => { return cf._id; })}, - }).forEach((cf) => { - if (!_.contains(cf.boardIds, boardId)) - cf.addBoard(boardId); + _id: { + $in: this.customFields.map(cf => { + return cf._id; + }), + }, + }).forEach(cf => { + if (!_.contains(cf.boardIds, boardId)) cf.addBoard(boardId); }); } // Get label names const oldBoard = Boards.findOne(this.boardId); const oldBoardLabels = oldBoard.labels; - const oldCardLabels = _.pluck(_.filter(oldBoardLabels, (label) => { - return _.contains(this.labelIds, label._id); - }), 'name'); + const oldCardLabels = _.pluck( + _.filter(oldBoardLabels, label => { + return _.contains(this.labelIds, label._id); + }), + 'name', + ); const newBoard = Boards.findOne(boardId); const newBoardLabels = newBoard.labels; - const newCardLabelIds = _.pluck(_.filter(newBoardLabels, (label) => { - return label.name && _.contains(oldCardLabels, label.name); - }), '_id'); + const newCardLabelIds = _.pluck( + _.filter(newBoardLabels, label => { + return label.name && _.contains(oldCardLabels, label.name); + }), + '_id', + ); const mutatedFields = { boardId, @@ -1306,7 +1305,7 @@ function updateActivities(doc, fieldNames, modifier) { Activities.find({ activityType: 'addedLabel', cardId: doc._id, - }).forEach((a) => { + }).forEach(a => { const lidx = doc.labelIds.indexOf(a.labelId); if (lidx !== -1 && modifier.$set.labelIds.length > lidx) { Activities.update(a._id, { @@ -1327,8 +1326,15 @@ function updateActivities(doc, fieldNames, modifier) { } } -function cardMove(userId, doc, fieldNames, oldListId, oldSwimlaneId, oldBoardId) { - if (_.contains(fieldNames, 'boardId') && (doc.boardId !== oldBoardId)) { +function cardMove( + userId, + doc, + fieldNames, + oldListId, + oldSwimlaneId, + oldBoardId, +) { + if (_.contains(fieldNames, 'boardId') && doc.boardId !== oldBoardId) { Activities.insert({ userId, activityType: 'moveCardBoard', @@ -1341,8 +1347,10 @@ function cardMove(userId, doc, fieldNames, oldListId, oldSwimlaneId, oldBoardId) swimlaneId: doc.swimlaneId, oldSwimlaneId, }); - } else if ((_.contains(fieldNames, 'listId') && doc.listId !== oldListId) || - (_.contains(fieldNames, 'swimlaneId') && doc.swimlaneId !== oldSwimlaneId)){ + } else if ( + (_.contains(fieldNames, 'listId') && doc.listId !== oldListId) || + (_.contains(fieldNames, 'swimlaneId') && doc.swimlaneId !== oldSwimlaneId) + ) { Activities.insert({ userId, oldListId, @@ -1351,7 +1359,7 @@ function cardMove(userId, doc, fieldNames, oldListId, oldSwimlaneId, oldBoardId) listId: doc.listId, boardId: doc.boardId, cardId: doc._id, - cardTitle:doc.title, + cardTitle: doc.title, swimlaneName: Swimlanes.findOne(doc.swimlaneId).title, swimlaneId: doc.swimlaneId, oldSwimlaneId, @@ -1386,8 +1394,7 @@ function cardState(userId, doc, fieldNames) { } function cardMembers(userId, doc, fieldNames, modifier) { - if (!_.contains(fieldNames, 'members')) - return; + if (!_.contains(fieldNames, 'members')) return; let memberId; // Say hello to the new member if (modifier.$addToSet && modifier.$addToSet.members) { @@ -1428,8 +1435,7 @@ function cardMembers(userId, doc, fieldNames, modifier) { } function cardLabels(userId, doc, fieldNames, modifier) { - if (!_.contains(fieldNames, 'labelIds')) - return; + if (!_.contains(fieldNames, 'labelIds')) return; let labelId; // Say hello to the new label if (modifier.$addToSet && modifier.$addToSet.labelIds) { @@ -1467,8 +1473,7 @@ function cardLabels(userId, doc, fieldNames, modifier) { } function cardCustomFields(userId, doc, fieldNames, modifier) { - if (!_.contains(fieldNames, 'customFields')) - return; + if (!_.contains(fieldNames, 'customFields')) return; // Say hello to the new customField value if (modifier.$set) { @@ -1524,7 +1529,7 @@ function cardCreation(userId, doc) { listName: Lists.findOne(doc.listId).title, listId: doc.listId, cardId: doc._id, - cardTitle:doc.title, + cardTitle: doc.title, swimlaneName: Swimlanes.findOne(doc.swimlaneId).title, swimlaneId: doc.swimlaneId, }); @@ -1559,7 +1564,7 @@ if (Meteor.isServer) { // When loading a board, mongodb is searching for every cards, the id of the parent (in the swinglanes collection). // With a huge database, this result in a very slow app and high CPU on the mongodb side. // To correct it, add Index to parentId: - Cards._collection._ensureIndex({parentId: 1}); + Cards._collection._ensureIndex({ parentId: 1 }); }); Cards.after.insert((userId, doc) => { @@ -1595,11 +1600,6 @@ if (Meteor.isServer) { cardCustomFields(userId, doc, fieldNames, modifier); }); - Cards.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); - }); - // Remove all activities associated with a card if we remove the card // Remove also card_comments / checklists / attachments Cards.before.remove((userId, doc) => { @@ -1619,26 +1619,30 @@ if (Meteor.isServer) { * description: string, * listId: string}] */ - JsonRoutes.add('GET', '/api/boards/:boardId/swimlanes/:swimlaneId/cards', function(req, res) { - const paramBoardId = req.params.boardId; - const paramSwimlaneId = req.params.swimlaneId; - Authentication.checkBoardAccess(req.userId, paramBoardId); - JsonRoutes.sendResult(res, { - code: 200, - data: Cards.find({ - boardId: paramBoardId, - swimlaneId: paramSwimlaneId, - archived: false, - }).map(function(doc) { - return { - _id: doc._id, - title: doc.title, - description: doc.description, - listId: doc.listId, - }; - }), - }); - }); + JsonRoutes.add( + 'GET', + '/api/boards/:boardId/swimlanes/:swimlaneId/cards', + function(req, res) { + const paramBoardId = req.params.boardId; + const paramSwimlaneId = req.params.swimlaneId; + Authentication.checkBoardAccess(req.userId, paramBoardId); + JsonRoutes.sendResult(res, { + code: 200, + data: Cards.find({ + boardId: paramBoardId, + swimlaneId: paramSwimlaneId, + archived: false, + }).map(function(doc) { + return { + _id: doc._id, + title: doc.title, + description: doc.description, + listId: doc.listId, + }; + }), + }); + }, + ); } //LISTS REST API if (Meteor.isServer) { @@ -1652,7 +1656,10 @@ if (Meteor.isServer) { * title: string, * description: string}] */ - JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards', function(req, res) { + JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards', function( + req, + res, + ) { const paramBoardId = req.params.boardId; const paramListId = req.params.listId; Authentication.checkBoardAccess(req.userId, paramBoardId); @@ -1681,21 +1688,25 @@ if (Meteor.isServer) { * @param {string} cardId the card ID * @return_type Cards */ - JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards/:cardId', function(req, res) { - const paramBoardId = req.params.boardId; - const paramListId = req.params.listId; - const paramCardId = req.params.cardId; - Authentication.checkBoardAccess(req.userId, paramBoardId); - JsonRoutes.sendResult(res, { - code: 200, - data: Cards.findOne({ - _id: paramCardId, - listId: paramListId, - boardId: paramBoardId, - archived: false, - }), - }); - }); + JsonRoutes.add( + 'GET', + '/api/boards/:boardId/lists/:listId/cards/:cardId', + function(req, res) { + const paramBoardId = req.params.boardId; + const paramListId = req.params.listId; + const paramCardId = req.params.cardId; + Authentication.checkBoardAccess(req.userId, paramBoardId); + JsonRoutes.sendResult(res, { + code: 200, + data: Cards.findOne({ + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }), + }); + }, + ); /** * @operation new_card @@ -1711,15 +1722,21 @@ if (Meteor.isServer) { * @param {string} [members] the member IDs list of the new card * @return_type {_id: string} */ - JsonRoutes.add('POST', '/api/boards/:boardId/lists/:listId/cards', function(req, res) { + JsonRoutes.add('POST', '/api/boards/:boardId/lists/:listId/cards', function( + req, + res, + ) { Authentication.checkUserId(req.userId); const paramBoardId = req.params.boardId; const paramListId = req.params.listId; const paramParentId = req.params.parentId; - const currentCards = Cards.find({ - listId: paramListId, - archived: false, - }, { sort: ['sort'] }); + const currentCards = Cards.find( + { + listId: paramListId, + archived: false, + }, + { sort: ['sort'] }, + ); const check = Users.findOne({ _id: req.body.authorId, }); @@ -1747,7 +1764,6 @@ if (Meteor.isServer) { _id: id, }); cardCreation(req.body.authorId, card); - } else { JsonRoutes.sendResult(res, { code: 401, @@ -1800,168 +1816,273 @@ if (Meteor.isServer) { * @param {string} [color] the new color of the card * @return_type {_id: string} */ - JsonRoutes.add('PUT', '/api/boards/:boardId/lists/:listId/cards/:cardId', function(req, res) { - Authentication.checkUserId(req.userId); - const paramBoardId = req.params.boardId; - const paramCardId = req.params.cardId; - const paramListId = req.params.listId; - - if (req.body.hasOwnProperty('title')) { - const newTitle = req.body.title; - Cards.direct.update({ - _id: paramCardId, - listId: paramListId, - boardId: paramBoardId, - archived: false, - }, { - $set: { - title: newTitle, - }, - }); - } - if (req.body.hasOwnProperty('listId')) { - const newParamListId = req.body.listId; - Cards.direct.update({ - _id: paramCardId, - listId: paramListId, - boardId: paramBoardId, - archived: false, - }, { - $set: { - listId: newParamListId, - }, - }); - - const card = Cards.findOne({ - _id: paramCardId, - }); - cardMove(req.body.authorId, card, { - fieldName: 'listId', - }, paramListId); + JsonRoutes.add( + 'PUT', + '/api/boards/:boardId/lists/:listId/cards/:cardId', + function(req, res) { + Authentication.checkUserId(req.userId); + const paramBoardId = req.params.boardId; + const paramCardId = req.params.cardId; + const paramListId = req.params.listId; + + if (req.body.hasOwnProperty('title')) { + const newTitle = req.body.title; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { + $set: { + title: newTitle, + }, + }, + ); + } + if (req.body.hasOwnProperty('listId')) { + const newParamListId = req.body.listId; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { + $set: { + listId: newParamListId, + }, + }, + ); - } - if (req.body.hasOwnProperty('parentId')) { - const newParentId = req.body.parentId; - Cards.direct.update({ - _id: paramCardId, - listId: paramListId, - boardId: paramBoardId, - archived: false, - }, { - $set: { - parentId: newParentId, - }, - }); - } - if (req.body.hasOwnProperty('description')) { - const newDescription = req.body.description; - Cards.direct.update({ - _id: paramCardId, - listId: paramListId, - boardId: paramBoardId, - archived: false, - }, { - $set: { - description: newDescription, - }, - }); - } - if (req.body.hasOwnProperty('color')) { - const newColor = req.body.color; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {color: newColor}}); - } - if (req.body.hasOwnProperty('labelIds')) { - let newlabelIds = req.body.labelIds; - if (_.isString(newlabelIds)) { - if (newlabelIds === '') { - newlabelIds = null; + const card = Cards.findOne({ + _id: paramCardId, + }); + cardMove( + req.body.authorId, + card, + { + fieldName: 'listId', + }, + paramListId, + ); + } + if (req.body.hasOwnProperty('parentId')) { + const newParentId = req.body.parentId; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { + $set: { + parentId: newParentId, + }, + }, + ); + } + if (req.body.hasOwnProperty('description')) { + const newDescription = req.body.description; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { + $set: { + description: newDescription, + }, + }, + ); + } + if (req.body.hasOwnProperty('color')) { + const newColor = req.body.color; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { color: newColor } }, + ); + } + if (req.body.hasOwnProperty('labelIds')) { + let newlabelIds = req.body.labelIds; + if (_.isString(newlabelIds)) { + if (newlabelIds === '') { + newlabelIds = null; + } else { + newlabelIds = [newlabelIds]; + } } - else { - newlabelIds = [newlabelIds]; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { + $set: { + labelIds: newlabelIds, + }, + }, + ); + } + if (req.body.hasOwnProperty('requestedBy')) { + const newrequestedBy = req.body.requestedBy; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { requestedBy: newrequestedBy } }, + ); + } + if (req.body.hasOwnProperty('assignedBy')) { + const newassignedBy = req.body.assignedBy; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { assignedBy: newassignedBy } }, + ); + } + if (req.body.hasOwnProperty('receivedAt')) { + const newreceivedAt = req.body.receivedAt; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { receivedAt: newreceivedAt } }, + ); + } + if (req.body.hasOwnProperty('startAt')) { + const newstartAt = req.body.startAt; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { startAt: newstartAt } }, + ); + } + if (req.body.hasOwnProperty('dueAt')) { + const newdueAt = req.body.dueAt; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { dueAt: newdueAt } }, + ); + } + if (req.body.hasOwnProperty('endAt')) { + const newendAt = req.body.endAt; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { endAt: newendAt } }, + ); + } + if (req.body.hasOwnProperty('spentTime')) { + const newspentTime = req.body.spentTime; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { spentTime: newspentTime } }, + ); + } + if (req.body.hasOwnProperty('isOverTime')) { + const newisOverTime = req.body.isOverTime; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { isOverTime: newisOverTime } }, + ); + } + if (req.body.hasOwnProperty('customFields')) { + const newcustomFields = req.body.customFields; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { customFields: newcustomFields } }, + ); + } + if (req.body.hasOwnProperty('members')) { + let newmembers = req.body.members; + if (_.isString(newmembers)) { + if (newmembers === '') { + newmembers = null; + } else { + newmembers = [newmembers]; + } } + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { members: newmembers } }, + ); } - Cards.direct.update({ - _id: paramCardId, - listId: paramListId, - boardId: paramBoardId, - archived: false, - }, { - $set: { - labelIds: newlabelIds, + if (req.body.hasOwnProperty('swimlaneId')) { + const newParamSwimlaneId = req.body.swimlaneId; + Cards.direct.update( + { + _id: paramCardId, + listId: paramListId, + boardId: paramBoardId, + archived: false, + }, + { $set: { swimlaneId: newParamSwimlaneId } }, + ); + } + JsonRoutes.sendResult(res, { + code: 200, + data: { + _id: paramCardId, }, }); - } - if (req.body.hasOwnProperty('requestedBy')) { - const newrequestedBy = req.body.requestedBy; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {requestedBy: newrequestedBy}}); - } - if (req.body.hasOwnProperty('assignedBy')) { - const newassignedBy = req.body.assignedBy; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {assignedBy: newassignedBy}}); - } - if (req.body.hasOwnProperty('receivedAt')) { - const newreceivedAt = req.body.receivedAt; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {receivedAt: newreceivedAt}}); - } - if (req.body.hasOwnProperty('startAt')) { - const newstartAt = req.body.startAt; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {startAt: newstartAt}}); - } - if (req.body.hasOwnProperty('dueAt')) { - const newdueAt = req.body.dueAt; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {dueAt: newdueAt}}); - } - if (req.body.hasOwnProperty('endAt')) { - const newendAt = req.body.endAt; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {endAt: newendAt}}); - } - if (req.body.hasOwnProperty('spentTime')) { - const newspentTime = req.body.spentTime; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {spentTime: newspentTime}}); - } - if (req.body.hasOwnProperty('isOverTime')) { - const newisOverTime = req.body.isOverTime; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {isOverTime: newisOverTime}}); - } - if (req.body.hasOwnProperty('customFields')) { - const newcustomFields = req.body.customFields; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {customFields: newcustomFields}}); - } - if (req.body.hasOwnProperty('members')) { - let newmembers = req.body.members; - if (_.isString(newmembers)) { - if (newmembers === '') { - newmembers = null; - } - else { - newmembers = [newmembers]; - } - } - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {members: newmembers}}); - } - if (req.body.hasOwnProperty('swimlaneId')) { - const newParamSwimlaneId = req.body.swimlaneId; - Cards.direct.update({_id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false}, - {$set: {swimlaneId: newParamSwimlaneId}}); - } - JsonRoutes.sendResult(res, { - code: 200, - data: { - _id: paramCardId, - }, - }); - }); + }, + ); /** * @operation delete_card @@ -1975,29 +2096,32 @@ if (Meteor.isServer) { * @param {string} cardId the ID of the card * @return_type {_id: string} */ - JsonRoutes.add('DELETE', '/api/boards/:boardId/lists/:listId/cards/:cardId', function(req, res) { - Authentication.checkUserId(req.userId); - const paramBoardId = req.params.boardId; - const paramListId = req.params.listId; - const paramCardId = req.params.cardId; - - Cards.direct.remove({ - _id: paramCardId, - listId: paramListId, - boardId: paramBoardId, - }); - const card = Cards.find({ - _id: paramCardId, - }); - cardRemover(req.body.authorId, card); - JsonRoutes.sendResult(res, { - code: 200, - data: { + JsonRoutes.add( + 'DELETE', + '/api/boards/:boardId/lists/:listId/cards/:cardId', + function(req, res) { + Authentication.checkUserId(req.userId); + const paramBoardId = req.params.boardId; + const paramListId = req.params.listId; + const paramCardId = req.params.cardId; + + Cards.direct.remove({ _id: paramCardId, - }, - }); - - }); + listId: paramListId, + boardId: paramBoardId, + }); + const card = Cards.find({ + _id: paramCardId, + }); + cardRemover(req.body.authorId, card); + JsonRoutes.sendResult(res, { + code: 200, + data: { + _id: paramCardId, + }, + }); + }, + ); } export default Cards; diff --git a/models/checklistItems.js b/models/checklistItems.js index d548e681..e6451fbf 100644 --- a/models/checklistItems.js +++ b/models/checklistItems.js @@ -61,7 +61,7 @@ ChecklistItems.attachSchema( } }, }, - }) + }), ); ChecklistItems.allow({ @@ -225,11 +225,6 @@ if (Meteor.isServer) { publishChekListUncompleted(userId, doc, fieldNames); }); - ChecklistItems.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); - }); - ChecklistItems.after.insert((userId, doc) => { itemCreation(userId, doc); }); @@ -281,7 +276,7 @@ if (Meteor.isServer) { code: 500, }); } - } + }, ); /** @@ -308,13 +303,13 @@ if (Meteor.isServer) { if (req.body.hasOwnProperty('isFinished')) { ChecklistItems.direct.update( { _id: paramItemId }, - { $set: { isFinished: req.body.isFinished } } + { $set: { isFinished: req.body.isFinished } }, ); } if (req.body.hasOwnProperty('title')) { ChecklistItems.direct.update( { _id: paramItemId }, - { $set: { title: req.body.title } } + { $set: { title: req.body.title } }, ); } @@ -324,7 +319,7 @@ if (Meteor.isServer) { _id: paramItemId, }, }); - } + }, ); /** @@ -353,7 +348,7 @@ if (Meteor.isServer) { _id: paramItemId, }, }); - } + }, ); } diff --git a/models/checklists.js b/models/checklists.js index 6fd22702..f139192e 100644 --- a/models/checklists.js +++ b/models/checklists.js @@ -59,7 +59,7 @@ Checklists.attachSchema( type: Number, decimal: true, }, - }) + }), ); Checklists.helpers({ @@ -68,7 +68,7 @@ Checklists.helpers({ this._id = null; this.cardId = newCardId; const newChecklistId = Checklists.insert(this); - ChecklistItems.find({ checklistId: oldChecklistId }).forEach((item) => { + ChecklistItems.find({ checklistId: oldChecklistId }).forEach(item => { item._id = null; item.checklistId = newChecklistId; item.cardId = newCardId; @@ -84,7 +84,7 @@ Checklists.helpers({ { checklistId: this._id, }, - { sort: ['sort'] } + { sort: ['sort'] }, ); }, finishedCount() { @@ -160,16 +160,11 @@ if (Meteor.isServer) { }); }); - Checklists.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); - }); - Checklists.before.remove((userId, doc) => { const activities = Activities.find({ checklistId: doc._id }); const card = Cards.findOne(doc.cardId); if (activities) { - activities.forEach((activity) => { + activities.forEach(activity => { Activities.remove(activity._id); }); } @@ -203,7 +198,7 @@ if (Meteor.isServer) { Authentication.checkUserId(req.userId); const paramCardId = req.params.cardId; const checklists = Checklists.find({ cardId: paramCardId }).map(function( - doc + doc, ) { return { _id: doc._id, @@ -220,7 +215,7 @@ if (Meteor.isServer) { code: 500, }); } - } + }, ); /** @@ -269,7 +264,7 @@ if (Meteor.isServer) { code: 500, }); } - } + }, ); /** @@ -313,7 +308,7 @@ if (Meteor.isServer) { code: 400, }); } - } + }, ); /** @@ -340,7 +335,7 @@ if (Meteor.isServer) { _id: paramChecklistId, }, }); - } + }, ); } diff --git a/models/customFields.js b/models/customFields.js index 8b51c0a3..1ca2fb90 100644 --- a/models/customFields.js +++ b/models/customFields.js @@ -95,7 +95,7 @@ CustomFields.attachSchema( } }, }, - }) + }), ); CustomFields.mutations({ @@ -118,7 +118,7 @@ CustomFields.allow({ userId, Boards.find({ _id: { $in: doc.boardIds }, - }).fetch() + }).fetch(), ); }, update(userId, doc) { @@ -126,7 +126,7 @@ CustomFields.allow({ userId, Boards.find({ _id: { $in: doc.boardIds }, - }).fetch() + }).fetch(), ); }, remove(userId, doc) { @@ -134,7 +134,7 @@ CustomFields.allow({ userId, Boards.find({ _id: { $in: doc.boardIds }, - }).fetch() + }).fetch(), ); }, fetch: ['userId', 'boardIds'], @@ -152,7 +152,7 @@ function customFieldCreation(userId, doc) { }); } -function customFieldDeletion(userId, doc){ +function customFieldDeletion(userId, doc) { Activities.insert({ userId, activityType: 'deleteCustomField', @@ -163,7 +163,7 @@ function customFieldDeletion(userId, doc){ // This has some bug, it does not show edited customField value at Outgoing Webhook, // instead it shows undefined, and no listId and swimlaneId. -function customFieldEdit(userId, doc){ +function customFieldEdit(userId, doc) { const card = Cards.findOne(doc.cardId); Activities.insert({ userId, @@ -185,17 +185,12 @@ if (Meteor.isServer) { customFieldCreation(userId, doc); }); - CustomFields.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); - }); - CustomFields.before.update((userId, doc, fieldNames, modifier) => { if (_.contains(fieldNames, 'boardIds') && modifier.$pull) { Cards.update( { boardId: modifier.$pull.boardIds, 'customFields._id': doc._id }, { $pull: { customFields: { _id: doc._id } } }, - { multi: true } + { multi: true }, ); customFieldEdit(userId, doc); Activities.remove({ @@ -223,7 +218,7 @@ if (Meteor.isServer) { Cards.update( { boardId: { $in: doc.boardIds }, 'customFields._id': doc._id }, { $pull: { customFields: { _id: doc._id } } }, - { multi: true } + { multi: true }, ); }); } @@ -241,7 +236,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('GET', '/api/boards/:boardId/custom-fields', function( req, - res + res, ) { Authentication.checkUserId(req.userId); const paramBoardId = req.params.boardId; @@ -254,7 +249,7 @@ if (Meteor.isServer) { name: cf.name, type: cf.type, }; - } + }, ), }); }); @@ -281,7 +276,7 @@ if (Meteor.isServer) { boardIds: { $in: [paramBoardId] }, }), }); - } + }, ); /** @@ -299,7 +294,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('POST', '/api/boards/:boardId/custom-fields', function( req, - res + res, ) { Authentication.checkUserId(req.userId); const paramBoardId = req.params.boardId; @@ -351,7 +346,7 @@ if (Meteor.isServer) { _id: id, }, }); - } + }, ); } diff --git a/models/export.js b/models/export.js index 8e5ce786..a69be970 100644 --- a/models/export.js +++ b/models/export.js @@ -57,7 +57,10 @@ export class Exporter { build() { const byBoard = { boardId: this._boardId }; - const byBoardNoLinked = { boardId: this._boardId, linkedId: {$in: ['', null] } }; + const byBoardNoLinked = { + boardId: this._boardId, + linkedId: { $in: ['', null] }, + }; // we do not want to retrieve boardId in related elements const noBoardId = { fields: { @@ -67,15 +70,21 @@ export class Exporter { const result = { _format: 'wekan-board-1.0.0', }; - _.extend(result, Boards.findOne(this._boardId, { - fields: { - stars: 0, - }, - })); + _.extend( + result, + Boards.findOne(this._boardId, { + fields: { + stars: 0, + }, + }), + ); result.lists = Lists.find(byBoard, noBoardId).fetch(); result.cards = Cards.find(byBoardNoLinked, noBoardId).fetch(); result.swimlanes = Swimlanes.find(byBoard, noBoardId).fetch(); - result.customFields = CustomFields.find({boardIds: {$in: [this.boardId]}}, {fields: {boardId: 0}}).fetch(); + result.customFields = CustomFields.find( + { boardIds: { $in: [this.boardId] } }, + { fields: { boardId: 0 } }, + ).fetch(); result.comments = CardComments.find(byBoard, noBoardId).fetch(); result.activities = Activities.find(byBoard, noBoardId).fetch(); result.rules = Rules.find(byBoard, noBoardId).fetch(); @@ -84,24 +93,40 @@ export class Exporter { result.subtaskItems = []; result.triggers = []; result.actions = []; - result.cards.forEach((card) => { - result.checklists.push(...Checklists.find({ - cardId: card._id, - }).fetch()); - result.checklistItems.push(...ChecklistItems.find({ - cardId: card._id, - }).fetch()); - result.subtaskItems.push(...Cards.find({ - parentid: card._id, - }).fetch()); + result.cards.forEach(card => { + result.checklists.push( + ...Checklists.find({ + cardId: card._id, + }).fetch(), + ); + result.checklistItems.push( + ...ChecklistItems.find({ + cardId: card._id, + }).fetch(), + ); + result.subtaskItems.push( + ...Cards.find({ + parentid: card._id, + }).fetch(), + ); }); - result.rules.forEach((rule) => { - result.triggers.push(...Triggers.find({ - _id: rule.triggerId, - }, noBoardId).fetch()); - result.actions.push(...Actions.find({ - _id: rule.actionId, - }, noBoardId).fetch()); + result.rules.forEach(rule => { + result.triggers.push( + ...Triggers.find( + { + _id: rule.triggerId, + }, + noBoardId, + ).fetch(), + ); + result.actions.push( + ...Actions.find( + { + _id: rule.actionId, + }, + noBoardId, + ).fetch(), + ); }); // [Old] for attachments we only export IDs and absolute url to original doc @@ -122,43 +147,45 @@ export class Exporter { }); }; const getBase64DataSync = Meteor.wrapAsync(getBase64Data); - result.attachments = Attachments.find(byBoard).fetch().map((attachment) => { - return { - _id: attachment._id, - cardId: attachment.cardId, - // url: FlowRouter.url(attachment.url()), - file: getBase64DataSync(attachment), - name: attachment.original.name, - type: attachment.original.type, - }; - }); + result.attachments = Attachments.find(byBoard) + .fetch() + .map(attachment => { + return { + _id: attachment._id, + cardId: attachment.cardId, + // url: FlowRouter.url(attachment.url()), + file: getBase64DataSync(attachment), + name: attachment.original.name, + type: attachment.original.type, + }; + }); // we also have to export some user data - as the other elements only // include id but we have to be careful: // 1- only exports users that are linked somehow to that board // 2- do not export any sensitive information const users = {}; - result.members.forEach((member) => { + result.members.forEach(member => { users[member.userId] = true; }); - result.lists.forEach((list) => { + result.lists.forEach(list => { users[list.userId] = true; }); - result.cards.forEach((card) => { + result.cards.forEach(card => { users[card.userId] = true; if (card.members) { - card.members.forEach((memberId) => { + card.members.forEach(memberId => { users[memberId] = true; }); } }); - result.comments.forEach((comment) => { + result.comments.forEach(comment => { users[comment.userId] = true; }); - result.activities.forEach((activity) => { + result.activities.forEach(activity => { users[activity.userId] = true; }); - result.checklists.forEach((checklist) => { + result.checklists.forEach(checklist => { users[checklist.userId] = true; }); const byUserIds = { @@ -177,13 +204,15 @@ export class Exporter { 'profile.avatarUrl': 1, }, }; - result.users = Users.find(byUserIds, userFields).fetch().map((user) => { - // user avatar is stored as a relative url, we export absolute - if ((user.profile || {}).avatarUrl) { - user.profile.avatarUrl = FlowRouter.url(user.profile.avatarUrl); - } - return user; - }); + result.users = Users.find(byUserIds, userFields) + .fetch() + .map(user => { + // user avatar is stored as a relative url, we export absolute + if ((user.profile || {}).avatarUrl) { + user.profile.avatarUrl = FlowRouter.url(user.profile.avatarUrl); + } + return user; + }); return result; } diff --git a/models/import.js b/models/import.js index 5e433669..fbfb1483 100644 --- a/models/import.js +++ b/models/import.js @@ -1,6 +1,6 @@ import { TrelloCreator } from './trelloCreator'; import { WekanCreator } from './wekanCreator'; -import {Exporter} from './export'; +import { Exporter } from './export'; import wekanMembersMapper from './wekanmapper'; Meteor.methods({ @@ -11,12 +11,12 @@ Meteor.methods({ check(currentBoard, Match.Maybe(String)); let creator; switch (importSource) { - case 'trello': - creator = new TrelloCreator(data); - break; - case 'wekan': - creator = new WekanCreator(data); - break; + case 'trello': + creator = new TrelloCreator(data); + break; + case 'wekan': + creator = new WekanCreator(data); + break; } // 1. check all parameters are ok from a syntax point of view @@ -38,11 +38,9 @@ Meteor.methods({ const data = exporter.build(); const addData = {}; addData.membersMapping = wekanMembersMapper.getMembersToMap(data); - const creator = new WekanCreator(addData); + const creator = new WekanCreator(addData); //data.title = `${data.title } - ${ TAPi18n.__('copy-tag')}`; data.title = `${data.title}`; return creator.create(data, currentBoardId); }, }); - - diff --git a/models/integrations.js b/models/integrations.js index bb36d6e8..0b2e08c6 100644 --- a/models/integrations.js +++ b/models/integrations.js @@ -86,14 +86,9 @@ Integrations.attachSchema( */ type: String, }, - }) + }), ); -Integrations.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - Integrations.allow({ insert(userId, doc) { return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId)); @@ -123,7 +118,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('GET', '/api/boards/:boardId/integrations', function( req, - res + res, ) { try { const paramBoardId = req.params.boardId; @@ -131,7 +126,7 @@ if (Meteor.isServer) { const data = Integrations.find( { boardId: paramBoardId }, - { fields: { token: 0 } } + { fields: { token: 0 } }, ).map(function(doc) { return doc; }); @@ -155,7 +150,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('GET', '/api/boards/:boardId/integrations/:intId', function( req, - res + res, ) { try { const paramBoardId = req.params.boardId; @@ -166,7 +161,7 @@ if (Meteor.isServer) { code: 200, data: Integrations.findOne( { _id: paramIntId, boardId: paramBoardId }, - { fields: { token: 0 } } + { fields: { token: 0 } }, ), }); } catch (error) { @@ -187,7 +182,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('POST', '/api/boards/:boardId/integrations', function( req, - res + res, ) { try { const paramBoardId = req.params.boardId; @@ -228,7 +223,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('PUT', '/api/boards/:boardId/integrations/:intId', function( req, - res + res, ) { try { const paramBoardId = req.params.boardId; @@ -239,35 +234,35 @@ if (Meteor.isServer) { const newEnabled = req.body.enabled; Integrations.direct.update( { _id: paramIntId, boardId: paramBoardId }, - { $set: { enabled: newEnabled } } + { $set: { enabled: newEnabled } }, ); } if (req.body.hasOwnProperty('title')) { const newTitle = req.body.title; Integrations.direct.update( { _id: paramIntId, boardId: paramBoardId }, - { $set: { title: newTitle } } + { $set: { title: newTitle } }, ); } if (req.body.hasOwnProperty('url')) { const newUrl = req.body.url; Integrations.direct.update( { _id: paramIntId, boardId: paramBoardId }, - { $set: { url: newUrl } } + { $set: { url: newUrl } }, ); } if (req.body.hasOwnProperty('token')) { const newToken = req.body.token; Integrations.direct.update( { _id: paramIntId, boardId: paramBoardId }, - { $set: { token: newToken } } + { $set: { token: newToken } }, ); } if (req.body.hasOwnProperty('activities')) { const newActivities = req.body.activities; Integrations.direct.update( { _id: paramIntId, boardId: paramBoardId }, - { $set: { activities: newActivities } } + { $set: { activities: newActivities } }, ); } @@ -306,14 +301,14 @@ if (Meteor.isServer) { Integrations.direct.update( { _id: paramIntId, boardId: paramBoardId }, - { $pullAll: { activities: newActivities } } + { $pullAll: { activities: newActivities } }, ); JsonRoutes.sendResult(res, { code: 200, data: Integrations.findOne( { _id: paramIntId, boardId: paramBoardId }, - { fields: { _id: 1, activities: 1 } } + { fields: { _id: 1, activities: 1 } }, ), }); } catch (error) { @@ -322,7 +317,7 @@ if (Meteor.isServer) { data: error, }); } - } + }, ); /** @@ -346,14 +341,14 @@ if (Meteor.isServer) { Integrations.direct.update( { _id: paramIntId, boardId: paramBoardId }, - { $addToSet: { activities: { $each: newActivities } } } + { $addToSet: { activities: { $each: newActivities } } }, ); JsonRoutes.sendResult(res, { code: 200, data: Integrations.findOne( { _id: paramIntId, boardId: paramBoardId }, - { fields: { _id: 1, activities: 1 } } + { fields: { _id: 1, activities: 1 } }, ), }); } catch (error) { @@ -362,7 +357,7 @@ if (Meteor.isServer) { data: error, }); } - } + }, ); /** @@ -375,7 +370,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('DELETE', '/api/boards/:boardId/integrations/:intId', function( req, - res + res, ) { try { const paramBoardId = req.params.boardId; diff --git a/models/invitationCodes.js b/models/invitationCodes.js index 5cdfc744..75db5708 100644 --- a/models/invitationCodes.js +++ b/models/invitationCodes.js @@ -47,7 +47,7 @@ InvitationCodes.attachSchema( type: Boolean, defaultValue: true, }, - }) + }), ); InvitationCodes.helpers({ @@ -56,11 +56,6 @@ InvitationCodes.helpers({ }, }); -InvitationCodes.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - // InvitationCodes.before.insert((userId, doc) => { // doc.createdAt = new Date(); // doc.authorId = userId; diff --git a/models/lists.js b/models/lists.js index 6d77d7aa..e57849d7 100644 --- a/models/lists.js +++ b/models/lists.js @@ -156,7 +156,7 @@ Lists.attachSchema( type: String, defaultValue: 'list', }, - }) + }), ); Lists.allow({ @@ -198,7 +198,7 @@ Lists.helpers({ swimlaneId: oldSwimlaneId, listId: oldId, archived: false, - }).forEach((card) => { + }).forEach(card => { card.copy(boardId, swimlaneId, _id); }); }, @@ -262,7 +262,7 @@ Lists.mutations({ archive() { if (this.isTemplateList()) { - this.cards().forEach((card) => { + this.cards().forEach(card => { return card.archive(); }); } @@ -271,7 +271,7 @@ Lists.mutations({ restore() { if (this.isTemplateList()) { - this.allCards().forEach((card) => { + this.allCards().forEach(card => { return card.restore(); }); } @@ -346,15 +346,10 @@ if (Meteor.isServer) { }); }); - Lists.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); - }); - Lists.before.remove((userId, doc) => { const cards = Cards.find({ listId: doc._id }); if (cards) { - cards.forEach((card) => { + cards.forEach(card => { Cards.remove(card._id); }); } @@ -404,7 +399,7 @@ if (Meteor.isServer) { _id: doc._id, title: doc.title, }; - } + }, ), }); } catch (error) { @@ -425,7 +420,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId', function( req, - res + res, ) { try { const paramBoardId = req.params.boardId; @@ -492,7 +487,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('DELETE', '/api/boards/:boardId/lists/:listId', function( req, - res + res, ) { try { Authentication.checkUserId(req.userId); diff --git a/models/rules.js b/models/rules.js index 76170b33..202071fc 100644 --- a/models/rules.js +++ b/models/rules.js @@ -44,7 +44,7 @@ Rules.attachSchema( } }, }, - }) + }), ); Rules.mutations({ @@ -74,11 +74,6 @@ Rules.allow({ }, }); -Rules.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - if (Meteor.isServer) { Meteor.startup(() => { Rules._collection._ensureIndex({ modifiedAt: -1 }); diff --git a/models/settings.js b/models/settings.js index b97961eb..4a0359d5 100644 --- a/models/settings.js +++ b/models/settings.js @@ -76,7 +76,7 @@ Settings.attachSchema( } }, }, - }) + }), ); Settings.helpers({ mailUrl() { @@ -88,7 +88,7 @@ Settings.helpers({ return `${protocol}${this.mailServer.host}:${this.mailServer.port}/`; } return `${protocol}${this.mailServer.username}:${encodeURIComponent( - this.mailServer.password + this.mailServer.password, )}@${this.mailServer.host}:${this.mailServer.port}/`; }, }); @@ -99,11 +99,6 @@ Settings.allow({ }, }); -Settings.before.update((userId, doc, fieldNames, modifier) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = new Date(); -}); - if (Meteor.isServer) { Meteor.startup(() => { Settings._collection._ensureIndex({ modifiedAt: -1 }); @@ -111,7 +106,7 @@ if (Meteor.isServer) { if (!setting) { const now = new Date(); const domain = process.env.ROOT_URL.match( - /\/\/(?:www\.)?(.*)?(?:\/)?/ + /\/\/(?:www\.)?(.*)?(?:\/)?/, )[1]; const from = `Boards Support `; const defaultSetting = { @@ -143,9 +138,7 @@ if (Meteor.isServer) { if (_.contains(fieldNames, 'mailServer') && doc.mailServer.host) { const protocol = doc.mailServer.enableTLS ? 'smtps://' : 'smtp://'; if (!doc.mailServer.username && !doc.mailServer.password) { - process.env.MAIL_URL = `${protocol}${doc.mailServer.host}:${ - doc.mailServer.port - }/`; + process.env.MAIL_URL = `${protocol}${doc.mailServer.host}:${doc.mailServer.port}/`; } else { process.env.MAIL_URL = `${protocol}${ doc.mailServer.username @@ -220,14 +213,14 @@ if (Meteor.isServer) { if (!user.isAdmin) { throw new Meteor.Error('not-allowed'); } - emails.forEach((email) => { + emails.forEach(email => { if (email && SimpleSchema.RegEx.Email.test(email)) { // Checks if the email is already link to an account. const userExist = Users.findOne({ email }); if (userExist) { throw new Meteor.Error( 'user-exist', - `The user with the email ${email} has already an account.` + `The user with the email ${email} has already an account.`, ); } // Checks if the email is already link to an invitation. @@ -253,10 +246,10 @@ if (Meteor.isServer) { } else { throw new Meteor.Error( 'invitation-generated-fail', - err.message + err.message, ); } - } + }, ); } } @@ -284,7 +277,7 @@ if (Meteor.isServer) { throw new Meteor.Error( 'email-fail', `${TAPi18n.__('email-fail-text', { lng: lang })}: ${message}`, - message + message, ); } return { diff --git a/models/swimlanes.js b/models/swimlanes.js index 82f73f79..769aaed3 100644 --- a/models/swimlanes.js +++ b/models/swimlanes.js @@ -120,7 +120,7 @@ Swimlanes.attachSchema( type: String, defaultValue: 'swimlane', }, - }) + }), ); Swimlanes.allow({ @@ -153,7 +153,7 @@ Swimlanes.helpers({ } // Copy all lists in swimlane - Lists.find(query).forEach((list) => { + Lists.find(query).forEach(list => { list.type = 'list'; list.swimlaneId = oldId; list.boardId = boardId; @@ -167,7 +167,7 @@ Swimlanes.helpers({ swimlaneId: this._id, archived: false, }), - { sort: ['sort'] } + { sort: ['sort'] }, ); }, @@ -178,7 +178,7 @@ Swimlanes.helpers({ swimlaneId: { $in: [this._id, ''] }, archived: false, }, - { sort: ['sort'] } + { sort: ['sort'] }, ); }, @@ -234,7 +234,7 @@ Swimlanes.mutations({ archive() { if (this.isTemplateSwimlane()) { - this.myLists().forEach((list) => { + this.myLists().forEach(list => { return list.archive(); }); } @@ -243,7 +243,7 @@ Swimlanes.mutations({ restore() { if (this.isTemplateSwimlane()) { - this.myLists().forEach((list) => { + this.myLists().forEach(list => { return list.restore(); }); } @@ -262,11 +262,6 @@ Swimlanes.mutations({ }, }); -Swimlanes.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - Swimlanes.hookOptions.after.update = { fetchPrevious: false }; if (Meteor.isServer) { @@ -292,11 +287,11 @@ if (Meteor.isServer) { swimlaneId: { $in: [doc._id, ''] }, archived: false, }, - { sort: ['sort'] } + { sort: ['sort'] }, ); if (lists.count() < 2) { - lists.forEach((list) => { + lists.forEach(list => { list.remove(); }); } else { @@ -350,7 +345,7 @@ if (Meteor.isServer) { _id: doc._id, title: doc.title, }; - } + }, ), }); } catch (error) { @@ -372,7 +367,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('GET', '/api/boards/:boardId/swimlanes/:swimlaneId', function( req, - res + res, ) { try { const paramBoardId = req.params.boardId; @@ -459,7 +454,7 @@ if (Meteor.isServer) { data: error, }); } - } + }, ); } diff --git a/models/trelloCreator.js b/models/trelloCreator.js index 3ac511a5..0472fe31 100644 --- a/models/trelloCreator.js +++ b/models/trelloCreator.js @@ -1,4 +1,4 @@ -const DateString = Match.Where(function (dateAsString) { +const DateString = Match.Where(function(dateAsString) { check(dateAsString, String); return moment(dateAsString, moment.ISO_8601).isValid(); }); @@ -52,10 +52,10 @@ export class TrelloCreator { * @param {String} dateString a properly formatted Date */ _now(dateString) { - if(dateString) { + if (dateString) { return new Date(dateString); } - if(!this._nowDate) { + if (!this._nowDate) { this._nowDate = new Date(); } return this._nowDate; @@ -67,75 +67,90 @@ export class TrelloCreator { * Otherwise return current logged user. * @param trelloUserId * @private - */ + */ _user(trelloUserId) { - if(trelloUserId && this.members[trelloUserId]) { + if (trelloUserId && this.members[trelloUserId]) { return this.members[trelloUserId]; } return Meteor.userId(); } checkActions(trelloActions) { - check(trelloActions, [Match.ObjectIncluding({ - data: Object, - date: DateString, - type: String, - })]); + check(trelloActions, [ + Match.ObjectIncluding({ + data: Object, + date: DateString, + type: String, + }), + ]); // XXX we could perform more thorough checks based on action type } checkBoard(trelloBoard) { - check(trelloBoard, Match.ObjectIncluding({ - closed: Boolean, - name: String, - prefs: Match.ObjectIncluding({ - // XXX refine control by validating 'background' against a list of - // allowed values (is it worth the maintenance?) - background: String, - permissionLevel: Match.Where((value) => { - return ['org', 'private', 'public'].indexOf(value)>= 0; + check( + trelloBoard, + Match.ObjectIncluding({ + closed: Boolean, + name: String, + prefs: Match.ObjectIncluding({ + // XXX refine control by validating 'background' against a list of + // allowed values (is it worth the maintenance?) + background: String, + permissionLevel: Match.Where(value => { + return ['org', 'private', 'public'].indexOf(value) >= 0; + }), }), }), - })); + ); } checkCards(trelloCards) { - check(trelloCards, [Match.ObjectIncluding({ - closed: Boolean, - dateLastActivity: DateString, - desc: String, - idLabels: [String], - idMembers: [String], - name: String, - pos: Number, - })]); + check(trelloCards, [ + Match.ObjectIncluding({ + closed: Boolean, + dateLastActivity: DateString, + desc: String, + idLabels: [String], + idMembers: [String], + name: String, + pos: Number, + }), + ]); } checkLabels(trelloLabels) { - check(trelloLabels, [Match.ObjectIncluding({ - // XXX refine control by validating 'color' against a list of allowed - // values (is it worth the maintenance?) - name: String, - })]); + check(trelloLabels, [ + Match.ObjectIncluding({ + // XXX refine control by validating 'color' against a list of allowed + // values (is it worth the maintenance?) + name: String, + }), + ]); } checkLists(trelloLists) { - check(trelloLists, [Match.ObjectIncluding({ - closed: Boolean, - name: String, - })]); + check(trelloLists, [ + Match.ObjectIncluding({ + closed: Boolean, + name: String, + }), + ]); } checkChecklists(trelloChecklists) { - check(trelloChecklists, [Match.ObjectIncluding({ - idBoard: String, - idCard: String, - name: String, - checkItems: [Match.ObjectIncluding({ - state: String, + check(trelloChecklists, [ + Match.ObjectIncluding({ + idBoard: String, + idCard: String, name: String, - })], - })]); + checkItems: [ + Match.ObjectIncluding({ + state: String, + name: String, + }), + ], + }), + ]); } // You must call parseActions before calling this one. @@ -146,31 +161,35 @@ export class TrelloCreator { // very old boards won't have a creation activity so no creation date createdAt: this._now(this.createdAt.board), labels: [], - members: [{ - userId: Meteor.userId(), - isAdmin: true, - isActive: true, - isNoComments: false, - isCommentOnly: false, - swimlaneId: false, - }], + members: [ + { + userId: Meteor.userId(), + isAdmin: true, + isActive: true, + isNoComments: false, + isCommentOnly: false, + swimlaneId: false, + }, + ], permission: this.getPermission(trelloBoard.prefs.permissionLevel), slug: getSlug(trelloBoard.name) || 'board', stars: 0, title: trelloBoard.name, }; // now add other members - if(trelloBoard.memberships) { - trelloBoard.memberships.forEach((trelloMembership) => { + if (trelloBoard.memberships) { + trelloBoard.memberships.forEach(trelloMembership => { const trelloId = trelloMembership.idMember; // do we have a mapping? - if(this.members[trelloId]) { + if (this.members[trelloId]) { const wekanId = this.members[trelloId]; // do we already have it in our list? - const wekanMember = boardToCreate.members.find((wekanMember) => wekanMember.userId === wekanId); - if(wekanMember) { + const wekanMember = boardToCreate.members.find( + wekanMember => wekanMember.userId === wekanId, + ); + if (wekanMember) { // we're already mapped, but maybe with lower rights - if(!wekanMember.isAdmin) { + if (!wekanMember.isAdmin) { wekanMember.isAdmin = this.getAdmin(trelloMembership.memberType); } } else { @@ -186,7 +205,7 @@ export class TrelloCreator { } }); } - trelloBoard.labels.forEach((label) => { + trelloBoard.labels.forEach(label => { const labelToCreate = { _id: Random.id(6), color: label.color ? label.color : 'black', @@ -198,7 +217,7 @@ export class TrelloCreator { boardToCreate.labels.push(labelToCreate); }); const boardId = Boards.direct.insert(boardToCreate); - Boards.direct.update(boardId, {$set: {modifiedAt: this._now()}}); + Boards.direct.update(boardId, { $set: { modifiedAt: this._now() } }); // log activity Activities.direct.insert({ activityType: 'importBoard', @@ -225,7 +244,7 @@ export class TrelloCreator { */ createCards(trelloCards, boardId) { const result = []; - trelloCards.forEach((card) => { + trelloCards.forEach(card => { const cardToCreate = { archived: card.closed, boardId, @@ -243,26 +262,26 @@ export class TrelloCreator { }; // add labels if (card.idLabels) { - cardToCreate.labelIds = card.idLabels.map((trelloId) => { + cardToCreate.labelIds = card.idLabels.map(trelloId => { return this.labels[trelloId]; }); } // add members { - if(card.idMembers) { + if (card.idMembers) { const wekanMembers = []; // we can't just map, as some members may not have been mapped - card.idMembers.forEach((trelloId) => { - if(this.members[trelloId]) { + card.idMembers.forEach(trelloId => { + if (this.members[trelloId]) { const wekanId = this.members[trelloId]; // we may map multiple Trello members to the same wekan user // in which case we risk adding the same user multiple times - if(!wekanMembers.find((wId) => wId === wekanId)){ + if (!wekanMembers.find(wId => wId === wekanId)) { wekanMembers.push(wekanId); } } return true; }); - if(wekanMembers.length>0) { + if (wekanMembers.length > 0) { cardToCreate.members = wekanMembers; } } @@ -289,7 +308,7 @@ export class TrelloCreator { // add comments const comments = this.comments[card.id]; if (comments) { - comments.forEach((comment) => { + comments.forEach(comment => { const commentToCreate = { boardId, cardId, @@ -318,15 +337,15 @@ export class TrelloCreator { const attachments = this.attachments[card.id]; const trelloCoverId = card.idAttachmentCover; if (attachments) { - attachments.forEach((att) => { + attachments.forEach(att => { const file = new FS.File(); // Simulating file.attachData on the client generates multiple errors // - HEAD returns null, which causes exception down the line // - the template then tries to display the url to the attachment which causes other errors // so we make it server only, and let UI catch up once it is done, forget about latency comp. const self = this; - if(Meteor.isServer) { - file.attachData(att.url, function (error) { + if (Meteor.isServer) { + file.attachData(att.url, function(error) { file.boardId = boardId; file.cardId = cardId; file.userId = self._user(att.idMemberCreator); @@ -334,15 +353,17 @@ export class TrelloCreator { // attachments' related activities automatically file.source = 'import'; if (error) { - throw(error); + throw error; } else { const wekanAtt = Attachments.insert(file, () => { // we do nothing }); self.attachmentIds[att.id] = wekanAtt._id; // - if(trelloCoverId === att.id) { - Cards.direct.update(cardId, { $set: {coverId: wekanAtt._id}}); + if (trelloCoverId === att.id) { + Cards.direct.update(cardId, { + $set: { coverId: wekanAtt._id }, + }); } } }); @@ -357,7 +378,7 @@ export class TrelloCreator { // Create labels if they do not exist and load this.labels. createLabels(trelloLabels, board) { - trelloLabels.forEach((label) => { + trelloLabels.forEach(label => { const color = label.color; const name = label.name; const existingLabel = board.getLabel(name, color); @@ -371,7 +392,7 @@ export class TrelloCreator { } createLists(trelloLists, boardId) { - trelloLists.forEach((list) => { + trelloLists.forEach(list => { const listToCreate = { archived: list.closed, boardId, @@ -384,7 +405,7 @@ export class TrelloCreator { sort: list.pos, }; const listId = Lists.direct.insert(listToCreate); - Lists.direct.update(listId, {$set: {'updatedAt': this._now()}}); + Lists.direct.update(listId, { $set: { updatedAt: this._now() } }); this.lists[list.id] = listId; // log activity // Activities.direct.insert({ @@ -416,12 +437,12 @@ export class TrelloCreator { sort: 1, }; const swimlaneId = Swimlanes.direct.insert(swimlaneToCreate); - Swimlanes.direct.update(swimlaneId, {$set: {'updatedAt': this._now()}}); + Swimlanes.direct.update(swimlaneId, { $set: { updatedAt: this._now() } }); this.swimlane = swimlaneId; } createChecklists(trelloChecklists) { - trelloChecklists.forEach((checklist) => { + trelloChecklists.forEach(checklist => { if (this.cards[checklist.idCard]) { // Create the checklist const checklistToCreate = { @@ -435,7 +456,7 @@ export class TrelloCreator { this.checklists[checklist.id] = checklistId; // Now add the items to the checklistItems let counter = 0; - checklist.checkItems.forEach((item) => { + checklist.checkItems.forEach(item => { counter++; const checklistItemTocreate = { _id: checklistId + counter, @@ -458,15 +479,15 @@ export class TrelloCreator { getColor(trelloColorCode) { // trello color name => wekan color const mapColors = { - 'blue': 'belize', - 'orange': 'pumpkin', - 'green': 'nephritis', - 'red': 'pomegranate', - 'purple': 'wisteria', - 'pink': 'pomegranate', - 'lime': 'nephritis', - 'sky': 'belize', - 'grey': 'midnight', + blue: 'belize', + orange: 'pumpkin', + green: 'nephritis', + red: 'pomegranate', + purple: 'wisteria', + pink: 'pomegranate', + lime: 'nephritis', + sky: 'belize', + grey: 'midnight', }; const wekanColor = mapColors[trelloColorCode]; return wekanColor || Boards.simpleSchema()._schema.color.allowedValues[0]; @@ -482,7 +503,7 @@ export class TrelloCreator { } parseActions(trelloActions) { - trelloActions.forEach((action) => { + trelloActions.forEach(action => { if (action.type === 'addAttachmentToCard') { // We have to be cautious, because the attachment could have been removed later. // In that case Trello still reports its addition, but removes its 'url' field. @@ -490,11 +511,11 @@ export class TrelloCreator { const trelloAttachment = action.data.attachment; // We need the idMemberCreator trelloAttachment.idMemberCreator = action.idMemberCreator; - if(trelloAttachment.url) { + if (trelloAttachment.url) { // we cannot actually create the Wekan attachment, because we don't yet // have the cards to attach it to, so we store it in the instance variable. const trelloCardId = action.data.card.id; - if(!this.attachments[trelloCardId]) { + if (!this.attachments[trelloCardId]) { this.attachments[trelloCardId] = []; } this.attachments[trelloCardId].push(trelloAttachment); @@ -520,88 +541,89 @@ export class TrelloCreator { } importActions(actions, boardId) { - actions.forEach((action) => { + actions.forEach(action => { switch (action.type) { - // Board related actions - // TODO: addBoardMember, removeBoardMember - case 'createBoard': { - Activities.direct.insert({ - userId: this._user(action.idMemberCreator), - type: 'board', - activityTypeId: boardId, - activityType: 'createBoard', - boardId, - createdAt: this._now(action.date), - }); - break; - } - // List related activities - // TODO: removeList, archivedList - case 'createList': { - Activities.direct.insert({ - userId: this._user(action.idMemberCreator), - type: 'list', - activityType: 'createList', - listId: this.lists[action.data.list.id], - boardId, - createdAt: this._now(action.date), - }); - break; - } - // Card related activities - // TODO: archivedCard, restoredCard, joinMember, unjoinMember - case 'createCard': { - Activities.direct.insert({ - userId: this._user(action.idMemberCreator), - activityType: 'createCard', - listId: this.lists[action.data.list.id], - cardId: this.cards[action.data.card.id], - boardId, - createdAt: this._now(action.date), - }); - break; - } - case 'updateCard': { - if (action.data.old.idList) { + // Board related actions + // TODO: addBoardMember, removeBoardMember + case 'createBoard': { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + type: 'board', + activityTypeId: boardId, + activityType: 'createBoard', + boardId, + createdAt: this._now(action.date), + }); + break; + } + // List related activities + // TODO: removeList, archivedList + case 'createList': { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + type: 'list', + activityType: 'createList', + listId: this.lists[action.data.list.id], + boardId, + createdAt: this._now(action.date), + }); + break; + } + // Card related activities + // TODO: archivedCard, restoredCard, joinMember, unjoinMember + case 'createCard': { Activities.direct.insert({ userId: this._user(action.idMemberCreator), - oldListId: this.lists[action.data.old.idList], - activityType: 'moveCard', - listId: this.lists[action.data.listAfter.id], + activityType: 'createCard', + listId: this.lists[action.data.list.id], cardId: this.cards[action.data.card.id], boardId, createdAt: this._now(action.date), }); + break; + } + case 'updateCard': { + if (action.data.old.idList) { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + oldListId: this.lists[action.data.old.idList], + activityType: 'moveCard', + listId: this.lists[action.data.listAfter.id], + cardId: this.cards[action.data.card.id], + boardId, + createdAt: this._now(action.date), + }); + } + break; + } + // Comment related activities + // Trello doesn't export the comment id + // Attachment related activities + case 'addAttachmentToCard': { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + type: 'card', + activityType: 'addAttachment', + attachmentId: this.attachmentIds[action.data.attachment.id], + cardId: this.cards[action.data.card.id], + boardId, + createdAt: this._now(action.date), + }); + break; + } + // Checklist related activities + case 'addChecklistToCard': { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + activityType: 'addChecklist', + cardId: this.cards[action.data.card.id], + checklistId: this.checklists[action.data.checklist.id], + boardId, + createdAt: this._now(action.date), + }); + break; } - break; - } - // Comment related activities - // Trello doesn't export the comment id - // Attachment related activities - case 'addAttachmentToCard': { - Activities.direct.insert({ - userId: this._user(action.idMemberCreator), - type: 'card', - activityType: 'addAttachment', - attachmentId: this.attachmentIds[action.data.attachment.id], - cardId: this.cards[action.data.card.id], - boardId, - createdAt: this._now(action.date), - }); - break; } - // Checklist related activities - case 'addChecklistToCard': { - Activities.direct.insert({ - userId: this._user(action.idMemberCreator), - activityType: 'addChecklist', - cardId: this.cards[action.data.card.id], - checklistId: this.checklists[action.data.checklist.id], - boardId, - createdAt: this._now(action.date), - }); - break; - }} // Trello doesn't have an add checklist item action }); } @@ -624,7 +646,9 @@ export class TrelloCreator { create(board, currentBoardId) { // TODO : Make isSandstorm variable global - const isSandstorm = Meteor.settings && Meteor.settings.public && + const isSandstorm = + Meteor.settings && + Meteor.settings.public && Meteor.settings.public.sandstorm; if (isSandstorm && currentBoardId) { const currentBoard = Boards.findOne(currentBoardId); diff --git a/models/triggers.js b/models/triggers.js index 8f2448c4..45f5e6fc 100644 --- a/models/triggers.js +++ b/models/triggers.js @@ -51,18 +51,13 @@ Triggers.helpers({ labels() { const boardLabels = this.board().labels; - const cardLabels = _.filter(boardLabels, (label) => { + const cardLabels = _.filter(boardLabels, label => { return _.contains(this.labelIds, label._id); }); return cardLabels; }, }); -Triggers.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - if (Meteor.isServer) { Meteor.startup(() => { Triggers._collection._ensureIndex({ modifiedAt: -1 }); diff --git a/models/unsavedEdits.js b/models/unsavedEdits.js index 122b2cd2..89418bfb 100644 --- a/models/unsavedEdits.js +++ b/models/unsavedEdits.js @@ -46,14 +46,7 @@ UnsavedEditCollection.attachSchema( } }, }, - }) -); - -UnsavedEditCollection.before.update( - (userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); - } + }), ); if (Meteor.isServer) { diff --git a/models/users.js b/models/users.js index 306193aa..79b83fe6 100644 --- a/models/users.js +++ b/models/users.js @@ -247,7 +247,7 @@ Users.attachSchema( optional: false, defaultValue: 'password', }, - }) + }), ); Users.allow({ @@ -259,7 +259,7 @@ Users.allow({ const adminsNumber = Users.find({ isAdmin: true }).count(); const { isAdmin } = Users.findOne( { _id: userId }, - { fields: { isAdmin: 1 } } + { fields: { isAdmin: 1 } }, ); // Prevents remove of the only one administrator @@ -533,7 +533,7 @@ Meteor.methods({ check(email, String); const existingUser = Users.findOne( { 'emails.address': email }, - { fields: { _id: 1 } } + { fields: { _id: 1 } }, ); if (existingUser) { throw new Meteor.Error('email-already-taken'); @@ -700,7 +700,7 @@ if (Meteor.isServer) { if (!options || !options.profile) { throw new Meteor.Error( 'error-invitation-code-blank', - 'The invitation code is required' + 'The invitation code is required', ); } const invitationCode = InvitationCodes.findOne({ @@ -711,7 +711,8 @@ if (Meteor.isServer) { if (!invitationCode) { throw new Meteor.Error( 'error-invitation-code-not-exist', - 'The invitation code doesn\'t exist' + // eslint-disable-next-line quotes + "The invitation code doesn't exist", ); } else { user.profile = { icode: options.profile.invitationcode }; @@ -722,18 +723,13 @@ if (Meteor.isServer) { Meteor.bindEnvironment(() => { InvitationCodes.remove({ _id: invitationCode._id }); }), - 200 + 200, ); return user; } }); } -Users.before.update((userId, doc, fieldNames, modifier, options) => { - modifier.$set = modifier.$set || {}; - modifier.$set.modifiedAt = Date.now(); -}); - if (Meteor.isServer) { // Let mongoDB ensure username unicity Meteor.startup(() => { @@ -742,7 +738,7 @@ if (Meteor.isServer) { { username: 1, }, - { unique: true } + { unique: true }, ); }); @@ -786,7 +782,7 @@ if (Meteor.isServer) { // b. We use it to find deleted and newly inserted ids by using it in one // direction and then in the other. function incrementBoards(boardsIds, inc) { - boardsIds.forEach((boardId) => { + boardsIds.forEach(boardId => { Boards.update(boardId, { $inc: { stars: inc } }); }); } @@ -855,7 +851,7 @@ if (Meteor.isServer) { Users.update(fakeUserId.get(), { $set: { 'profile.cardTemplatesSwimlaneId': swimlaneId }, }); - } + }, ); // Insert the list templates swimlane @@ -872,7 +868,7 @@ if (Meteor.isServer) { Users.update(fakeUserId.get(), { $set: { 'profile.listTemplatesSwimlaneId': swimlaneId }, }); - } + }, ); // Insert the board templates swimlane @@ -889,9 +885,9 @@ if (Meteor.isServer) { Users.update(fakeUserId.get(), { $set: { 'profile.boardTemplatesSwimlaneId': swimlaneId }, }); - } + }, ); - } + }, ); }); }); @@ -921,7 +917,7 @@ if (Meteor.isServer) { if (!invitationCode) { throw new Meteor.Error('error-invitation-code-not-exist'); } else { - invitationCode.boardsToBeInvited.forEach((boardId) => { + invitationCode.boardsToBeInvited.forEach(boardId => { const board = Boards.findOne(boardId); board.addMember(doc._id); }); @@ -1071,7 +1067,7 @@ if (Meteor.isServer) { loginDisabled: true, 'services.resume.loginTokens': '', }, - } + }, ); } else if (action === 'enableLogin') { Users.update({ _id: id }, { $set: { loginDisabled: '' } }); @@ -1112,7 +1108,7 @@ if (Meteor.isServer) { */ JsonRoutes.add('POST', '/api/boards/:boardId/members/:userId/add', function( req, - res + res, ) { try { Authentication.checkUserId(req.userId); @@ -1136,7 +1132,7 @@ if (Meteor.isServer) { isTrue(isAdmin), isTrue(isNoComments), isTrue(isCommentOnly), - userId + userId, ); } return { @@ -1207,7 +1203,7 @@ if (Meteor.isServer) { data: error, }); } - } + }, ); /** diff --git a/models/watchable.js b/models/watchable.js index 6821f847..7dbacb59 100644 --- a/models/watchable.js +++ b/models/watchable.js @@ -1,5 +1,5 @@ // simple version, only toggle watch / unwatch -const simpleWatchable = (collection) => { +const simpleWatchable = collection => { collection.attachSchema({ watchers: { type: [String], @@ -24,8 +24,8 @@ const simpleWatchable = (collection) => { collection.mutations({ setWatcher(userId, level) { // if level undefined or null or false, then remove - if (!level) return { $pull: { watchers: userId }}; - return { $addToSet: { watchers: userId }}; + if (!level) return { $pull: { watchers: userId } }; + return { $addToSet: { watchers: userId } }; }, }); }; @@ -34,7 +34,7 @@ const simpleWatchable = (collection) => { const complexWatchOptions = ['watching', 'tracking', 'muted']; const complexWatchDefault = 'muted'; -const complexWatchable = (collection) => { +const complexWatchable = collection => { collection.attachSchema({ 'watchers.$.userId': { type: String, @@ -72,9 +72,9 @@ const complexWatchable = (collection) => { setWatcher(userId, level) { // if level undefined or null or false, then remove if (level === complexWatchDefault) level = null; - if (!level) return { $pull: { watchers: { userId }}}; + if (!level) return { $pull: { watchers: { userId } } }; const index = this.watcherIndex(userId); - if (index<0) return { $push: { watchers: { userId, level }}}; + if (index < 0) return { $push: { watchers: { userId, level } } }; return { $set: { [`watchers.${index}.level`]: level, diff --git a/models/wekanCreator.js b/models/wekanCreator.js index 0f6a9d17..ec85d93f 100644 --- a/models/wekanCreator.js +++ b/models/wekanCreator.js @@ -87,99 +87,120 @@ export class WekanCreator { } checkActivities(wekanActivities) { - check(wekanActivities, [Match.ObjectIncluding({ - activityType: String, - createdAt: DateString, - })]); + check(wekanActivities, [ + Match.ObjectIncluding({ + activityType: String, + createdAt: DateString, + }), + ]); // XXX we could perform more thorough checks based on action type } checkBoard(wekanBoard) { - check(wekanBoard, Match.ObjectIncluding({ - archived: Boolean, - title: String, - // XXX refine control by validating 'color' against a list of - // allowed values (is it worth the maintenance?) - color: String, - permission: Match.Where((value) => { - return ['private', 'public'].indexOf(value) >= 0; + check( + wekanBoard, + Match.ObjectIncluding({ + archived: Boolean, + title: String, + // XXX refine control by validating 'color' against a list of + // allowed values (is it worth the maintenance?) + color: String, + permission: Match.Where(value => { + return ['private', 'public'].indexOf(value) >= 0; + }), }), - })); + ); } checkCards(wekanCards) { - check(wekanCards, [Match.ObjectIncluding({ - archived: Boolean, - dateLastActivity: DateString, - labelIds: [String], - title: String, - sort: Number, - })]); + check(wekanCards, [ + Match.ObjectIncluding({ + archived: Boolean, + dateLastActivity: DateString, + labelIds: [String], + title: String, + sort: Number, + }), + ]); } checkLabels(wekanLabels) { - check(wekanLabels, [Match.ObjectIncluding({ - // XXX refine control by validating 'color' against a list of allowed - // values (is it worth the maintenance?) - color: String, - })]); + check(wekanLabels, [ + Match.ObjectIncluding({ + // XXX refine control by validating 'color' against a list of allowed + // values (is it worth the maintenance?) + color: String, + }), + ]); } checkLists(wekanLists) { - check(wekanLists, [Match.ObjectIncluding({ - archived: Boolean, - title: String, - })]); + check(wekanLists, [ + Match.ObjectIncluding({ + archived: Boolean, + title: String, + }), + ]); } checkSwimlanes(wekanSwimlanes) { - check(wekanSwimlanes, [Match.ObjectIncluding({ - archived: Boolean, - title: String, - })]); + check(wekanSwimlanes, [ + Match.ObjectIncluding({ + archived: Boolean, + title: String, + }), + ]); } checkChecklists(wekanChecklists) { - check(wekanChecklists, [Match.ObjectIncluding({ - cardId: String, - title: String, - })]); + check(wekanChecklists, [ + Match.ObjectIncluding({ + cardId: String, + title: String, + }), + ]); } checkChecklistItems(wekanChecklistItems) { - check(wekanChecklistItems, [Match.ObjectIncluding({ - cardId: String, - title: String, - })]); + check(wekanChecklistItems, [ + Match.ObjectIncluding({ + cardId: String, + title: String, + }), + ]); } checkRules(wekanRules) { - check(wekanRules, [Match.ObjectIncluding({ - triggerId: String, - actionId: String, - title: String, - })]); + check(wekanRules, [ + Match.ObjectIncluding({ + triggerId: String, + actionId: String, + title: String, + }), + ]); } checkTriggers(wekanTriggers) { // XXX More check based on trigger type - check(wekanTriggers, [Match.ObjectIncluding({ - activityType: String, - desc: String, - })]); + check(wekanTriggers, [ + Match.ObjectIncluding({ + activityType: String, + desc: String, + }), + ]); } getMembersToMap(data) { - // we will work on the list itself (an ordered array of objects) when a - // mapping is done, we add a 'wekan' field to the object representing the - // imported member + // we will work on the list itself (an ordered array of objects) when a + // mapping is done, we add a 'wekan' field to the object representing the + // imported member const membersToMap = data.members; const users = data.users; // auto-map based on username - membersToMap.forEach((importedMember) => { + membersToMap.forEach(importedMember => { importedMember.id = importedMember.userId; delete importedMember.userId; - const user = users.filter((user) => { + const user = users.filter(user => { return user._id === importedMember.id; })[0]; if (user.profile && user.profile.fullname) { @@ -196,10 +217,12 @@ export class WekanCreator { checkActions(wekanActions) { // XXX More check based on action type - check(wekanActions, [Match.ObjectIncluding({ - actionType: String, - desc: String, - })]); + check(wekanActions, [ + Match.ObjectIncluding({ + actionType: String, + desc: String, + }), + ]); } // You must call parseActions before calling this one. @@ -210,15 +233,17 @@ export class WekanCreator { // very old boards won't have a creation activity so no creation date createdAt: this._now(boardToImport.createdAt), labels: [], - members: [{ - userId: Meteor.userId(), - wekanId: Meteor.userId(), - isActive: true, - isAdmin: true, - isNoComments: false, - isCommentOnly: false, - swimlaneId: false, - }], + members: [ + { + userId: Meteor.userId(), + wekanId: Meteor.userId(), + isActive: true, + isAdmin: true, + isNoComments: false, + isCommentOnly: false, + swimlaneId: false, + }, + ], // Standalone Export has modifiedAt missing, adding modifiedAt to fix it modifiedAt: this._now(boardToImport.modifiedAt), permission: boardToImport.permission, @@ -228,16 +253,20 @@ export class WekanCreator { }; // now add other members if (boardToImport.members) { - boardToImport.members.forEach((wekanMember) => { + boardToImport.members.forEach(wekanMember => { // do we already have it in our list? - if (!boardToCreate.members.some((member) => member.wekanId === wekanMember.wekanId)) + if ( + !boardToCreate.members.some( + member => member.wekanId === wekanMember.wekanId, + ) + ) boardToCreate.members.push({ ...wekanMember, userId: wekanMember.wekanId, }); }); } - boardToImport.labels.forEach((label) => { + boardToImport.labels.forEach(label => { const labelToCreate = { _id: Random.id(6), color: label.color, @@ -279,7 +308,7 @@ export class WekanCreator { */ createCards(wekanCards, boardId) { const result = []; - wekanCards.forEach((card) => { + wekanCards.forEach(card => { const cardToCreate = { archived: card.archived, boardId, @@ -300,7 +329,7 @@ export class WekanCreator { }; // add labels if (card.labelIds) { - cardToCreate.labelIds = card.labelIds.map((wekanId) => { + cardToCreate.labelIds = card.labelIds.map(wekanId => { return this.labels[wekanId]; }); } @@ -308,12 +337,12 @@ export class WekanCreator { if (card.members) { const wekanMembers = []; // we can't just map, as some members may not have been mapped - card.members.forEach((sourceMemberId) => { + card.members.forEach(sourceMemberId => { if (this.members[sourceMemberId]) { const wekanId = this.members[sourceMemberId]; // we may map multiple Wekan members to the same wekan user // in which case we risk adding the same user multiple times - if (!wekanMembers.find((wId) => wId === wekanId)) { + if (!wekanMembers.find(wId => wId === wekanId)) { wekanMembers.push(wekanId); } } @@ -349,7 +378,7 @@ export class WekanCreator { // add comments const comments = this.comments[card._id]; if (comments) { - comments.forEach((comment) => { + comments.forEach(comment => { const commentToCreate = { boardId, cardId, @@ -377,7 +406,7 @@ export class WekanCreator { const attachments = this.attachments[card._id]; const wekanCoverId = card.coverId; if (attachments) { - attachments.forEach((att) => { + attachments.forEach(att => { const file = new FS.File(); // Simulating file.attachData on the client generates multiple errors // - HEAD returns null, which causes exception down the line @@ -394,7 +423,7 @@ export class WekanCreator { // attachments' related activities automatically file.source = 'import'; if (error) { - throw (error); + throw error; } else { const wekanAtt = Attachments.insert(file, () => { // we do nothing @@ -411,33 +440,37 @@ export class WekanCreator { } }); } else if (att.file) { - file.attachData(new Buffer(att.file, 'base64'), { - type: att.type, - }, (error) => { - file.name(att.name); - file.boardId = boardId; - file.cardId = cardId; - file.userId = self._user(att.userId); - // The field source will only be used to prevent adding - // attachments' related activities automatically - file.source = 'import'; - if (error) { - throw (error); - } else { - const wekanAtt = Attachments.insert(file, () => { - // we do nothing - }); - this.attachmentIds[att._id] = wekanAtt._id; - // - if (wekanCoverId === att._id) { - Cards.direct.update(cardId, { - $set: { - coverId: wekanAtt._id, - }, + file.attachData( + new Buffer(att.file, 'base64'), + { + type: att.type, + }, + error => { + file.name(att.name); + file.boardId = boardId; + file.cardId = cardId; + file.userId = self._user(att.userId); + // The field source will only be used to prevent adding + // attachments' related activities automatically + file.source = 'import'; + if (error) { + throw error; + } else { + const wekanAtt = Attachments.insert(file, () => { + // we do nothing }); + this.attachmentIds[att._id] = wekanAtt._id; + // + if (wekanCoverId === att._id) { + Cards.direct.update(cardId, { + $set: { + coverId: wekanAtt._id, + }, + }); + } } - } - }); + }, + ); } } // todo XXX set cover - if need be @@ -450,7 +483,7 @@ export class WekanCreator { // Create labels if they do not exist and load this.labels. createLabels(wekanLabels, board) { - wekanLabels.forEach((label) => { + wekanLabels.forEach(label => { const color = label.color; const name = label.name; const existingLabel = board.getLabel(name, color); @@ -479,7 +512,7 @@ export class WekanCreator { const listId = Lists.direct.insert(listToCreate); Lists.direct.update(listId, { $set: { - 'updatedAt': this._now(), + updatedAt: this._now(), }, }); this.lists[list._id] = listId; @@ -520,7 +553,7 @@ export class WekanCreator { const swimlaneId = Swimlanes.direct.insert(swimlaneToCreate); Swimlanes.direct.update(swimlaneId, { $set: { - 'updatedAt': this._now(), + updatedAt: this._now(), }, }); this.swimlanes[swimlane._id] = swimlaneId; @@ -545,7 +578,7 @@ export class WekanCreator { } createTriggers(wekanTriggers, boardId) { - wekanTriggers.forEach((trigger) => { + wekanTriggers.forEach(trigger => { if (trigger.hasOwnProperty('labelId')) { trigger.labelId = this.labels[trigger.labelId]; } @@ -560,7 +593,7 @@ export class WekanCreator { } createActions(wekanActions, boardId) { - wekanActions.forEach((action) => { + wekanActions.forEach(action => { if (action.hasOwnProperty('labelId')) { action.labelId = this.labels[action.labelId]; } @@ -575,7 +608,7 @@ export class WekanCreator { } createRules(wekanRules, boardId) { - wekanRules.forEach((rule) => { + wekanRules.forEach(rule => { // Create the rule rule.boardId = boardId; rule.triggerId = this.triggers[rule.triggerId]; @@ -595,189 +628,178 @@ export class WekanCreator { sort: checklistitem.sort ? checklistitem.sort : checklistitemIndex, isFinished: checklistitem.isFinished, }; - const checklistItemId = ChecklistItems.direct.insert(checklistItemTocreate); + const checklistItemId = ChecklistItems.direct.insert( + checklistItemTocreate, + ); this.checklistItems[checklistitem._id] = checklistItemId; }); } parseActivities(wekanBoard) { - wekanBoard.activities.forEach((activity) => { + wekanBoard.activities.forEach(activity => { switch (activity.activityType) { - case 'addAttachment': - { - // We have to be cautious, because the attachment could have been removed later. - // In that case Wekan still reports its addition, but removes its 'url' field. - // So we test for that - const wekanAttachment = wekanBoard.attachments.filter((attachment) => { - return attachment._id === activity.attachmentId; - })[0]; - - if (typeof wekanAttachment !== 'undefined' && wekanAttachment) { - if (wekanAttachment.url || wekanAttachment.file) { - // we cannot actually create the Wekan attachment, because we don't yet - // have the cards to attach it to, so we store it in the instance variable. - const wekanCardId = activity.cardId; - if (!this.attachments[wekanCardId]) { - this.attachments[wekanCardId] = []; + case 'addAttachment': { + // We have to be cautious, because the attachment could have been removed later. + // In that case Wekan still reports its addition, but removes its 'url' field. + // So we test for that + const wekanAttachment = wekanBoard.attachments.filter(attachment => { + return attachment._id === activity.attachmentId; + })[0]; + + if (typeof wekanAttachment !== 'undefined' && wekanAttachment) { + if (wekanAttachment.url || wekanAttachment.file) { + // we cannot actually create the Wekan attachment, because we don't yet + // have the cards to attach it to, so we store it in the instance variable. + const wekanCardId = activity.cardId; + if (!this.attachments[wekanCardId]) { + this.attachments[wekanCardId] = []; + } + this.attachments[wekanCardId].push(wekanAttachment); } - this.attachments[wekanCardId].push(wekanAttachment); } + break; } - break; - } - case 'addComment': - { - const wekanComment = wekanBoard.comments.filter((comment) => { - return comment._id === activity.commentId; - })[0]; - const id = activity.cardId; - if (!this.comments[id]) { - this.comments[id] = []; + case 'addComment': { + const wekanComment = wekanBoard.comments.filter(comment => { + return comment._id === activity.commentId; + })[0]; + const id = activity.cardId; + if (!this.comments[id]) { + this.comments[id] = []; + } + this.comments[id].push(wekanComment); + break; + } + case 'createBoard': { + this.createdAt.board = activity.createdAt; + break; + } + case 'createCard': { + const cardId = activity.cardId; + this.createdAt.cards[cardId] = activity.createdAt; + this.createdBy.cards[cardId] = activity.userId; + break; + } + case 'createList': { + const listId = activity.listId; + this.createdAt.lists[listId] = activity.createdAt; + break; + } + case 'createSwimlane': { + const swimlaneId = activity.swimlaneId; + this.createdAt.swimlanes[swimlaneId] = activity.createdAt; + break; } - this.comments[id].push(wekanComment); - break; - } - case 'createBoard': - { - this.createdAt.board = activity.createdAt; - break; - } - case 'createCard': - { - const cardId = activity.cardId; - this.createdAt.cards[cardId] = activity.createdAt; - this.createdBy.cards[cardId] = activity.userId; - break; - } - case 'createList': - { - const listId = activity.listId; - this.createdAt.lists[listId] = activity.createdAt; - break; - } - case 'createSwimlane': - { - const swimlaneId = activity.swimlaneId; - this.createdAt.swimlanes[swimlaneId] = activity.createdAt; - break; - } } }); } importActivities(activities, boardId) { - activities.forEach((activity) => { + activities.forEach(activity => { switch (activity.activityType) { - // Board related activities - // TODO: addBoardMember, removeBoardMember - case 'createBoard': - { - Activities.direct.insert({ - userId: this._user(activity.userId), - type: 'board', - activityTypeId: boardId, - activityType: activity.activityType, - boardId, - createdAt: this._now(activity.createdAt), - }); - break; - } - // List related activities - // TODO: removeList, archivedList - case 'createList': - { - Activities.direct.insert({ - userId: this._user(activity.userId), - type: 'list', - activityType: activity.activityType, - listId: this.lists[activity.listId], - boardId, - createdAt: this._now(activity.createdAt), - }); - break; - } - // Card related activities - // TODO: archivedCard, restoredCard, joinMember, unjoinMember - case 'createCard': - { - Activities.direct.insert({ - userId: this._user(activity.userId), - activityType: activity.activityType, - listId: this.lists[activity.listId], - cardId: this.cards[activity.cardId], - boardId, - createdAt: this._now(activity.createdAt), - }); - break; - } - case 'moveCard': - { - Activities.direct.insert({ - userId: this._user(activity.userId), - oldListId: this.lists[activity.oldListId], - activityType: activity.activityType, - listId: this.lists[activity.listId], - cardId: this.cards[activity.cardId], - boardId, - createdAt: this._now(activity.createdAt), - }); - break; - } - // Comment related activities - case 'addComment': - { - Activities.direct.insert({ - userId: this._user(activity.userId), - activityType: activity.activityType, - cardId: this.cards[activity.cardId], - commentId: this.commentIds[activity.commentId], - boardId, - createdAt: this._now(activity.createdAt), - }); - break; - } - // Attachment related activities - case 'addAttachment': - { - Activities.direct.insert({ - userId: this._user(activity.userId), - type: 'card', - activityType: activity.activityType, - attachmentId: this.attachmentIds[activity.attachmentId], - cardId: this.cards[activity.cardId], - boardId, - createdAt: this._now(activity.createdAt), - }); - break; - } - // Checklist related activities - case 'addChecklist': - { - Activities.direct.insert({ - userId: this._user(activity.userId), - activityType: activity.activityType, - cardId: this.cards[activity.cardId], - checklistId: this.checklists[activity.checklistId], - boardId, - createdAt: this._now(activity.createdAt), - }); - break; - } - case 'addChecklistItem': - { - Activities.direct.insert({ - userId: this._user(activity.userId), - activityType: activity.activityType, - cardId: this.cards[activity.cardId], - checklistId: this.checklists[activity.checklistId], - checklistItemId: activity.checklistItemId.replace( - activity.checklistId, - this.checklists[activity.checklistId]), - boardId, - createdAt: this._now(activity.createdAt), - }); - break; - } + // Board related activities + // TODO: addBoardMember, removeBoardMember + case 'createBoard': { + Activities.direct.insert({ + userId: this._user(activity.userId), + type: 'board', + activityTypeId: boardId, + activityType: activity.activityType, + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + // List related activities + // TODO: removeList, archivedList + case 'createList': { + Activities.direct.insert({ + userId: this._user(activity.userId), + type: 'list', + activityType: activity.activityType, + listId: this.lists[activity.listId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + // Card related activities + // TODO: archivedCard, restoredCard, joinMember, unjoinMember + case 'createCard': { + Activities.direct.insert({ + userId: this._user(activity.userId), + activityType: activity.activityType, + listId: this.lists[activity.listId], + cardId: this.cards[activity.cardId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + case 'moveCard': { + Activities.direct.insert({ + userId: this._user(activity.userId), + oldListId: this.lists[activity.oldListId], + activityType: activity.activityType, + listId: this.lists[activity.listId], + cardId: this.cards[activity.cardId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + // Comment related activities + case 'addComment': { + Activities.direct.insert({ + userId: this._user(activity.userId), + activityType: activity.activityType, + cardId: this.cards[activity.cardId], + commentId: this.commentIds[activity.commentId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + // Attachment related activities + case 'addAttachment': { + Activities.direct.insert({ + userId: this._user(activity.userId), + type: 'card', + activityType: activity.activityType, + attachmentId: this.attachmentIds[activity.attachmentId], + cardId: this.cards[activity.cardId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + // Checklist related activities + case 'addChecklist': { + Activities.direct.insert({ + userId: this._user(activity.userId), + activityType: activity.activityType, + cardId: this.cards[activity.cardId], + checklistId: this.checklists[activity.checklistId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + case 'addChecklistItem': { + Activities.direct.insert({ + userId: this._user(activity.userId), + activityType: activity.activityType, + cardId: this.cards[activity.cardId], + checklistId: this.checklists[activity.checklistId], + checklistItemId: activity.checklistItemId.replace( + activity.checklistId, + this.checklists[activity.checklistId], + ), + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } } }); } @@ -788,7 +810,6 @@ export class WekanCreator { // check(data, { // membersMapping: Match.Optional(Object), // }); - // this.checkActivities(board.activities); // this.checkBoard(board); // this.checkLabels(board.labels); @@ -807,7 +828,9 @@ export class WekanCreator { create(board, currentBoardId) { // TODO : Make isSandstorm variable global - const isSandstorm = Meteor.settings && Meteor.settings.public && + const isSandstorm = + Meteor.settings && + Meteor.settings.public && Meteor.settings.public.sandstorm; if (isSandstorm && currentBoardId) { const currentBoard = Boards.findOne(currentBoardId); diff --git a/models/wekanmapper.js b/models/wekanmapper.js index f4c110f7..8db3aacd 100644 --- a/models/wekanmapper.js +++ b/models/wekanmapper.js @@ -5,10 +5,10 @@ export function getMembersToMap(data) { const membersToMap = data.members; const users = data.users; // auto-map based on username - membersToMap.forEach((importedMember) => { + membersToMap.forEach(importedMember => { importedMember.id = importedMember.userId; delete importedMember.userId; - const user = users.filter((user) => { + const user = users.filter(user => { return user._id === importedMember.id; })[0]; if (user.profile && user.profile.fullname) { diff --git a/package.json b/package.json index 0c0312b6..3ce73f89 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "lint:eslint:fix": "eslint --ext .js --ignore-path .eslintignore --fix .", "lint:staged": "lint-staged", "prettify": "prettier --write '**/*.js' '**/*.jsx'", - "test": "npm run --silent lint" + "test": "npm run lint" }, "lint-staged": { "*.js": [ diff --git a/sandstorm.js b/sandstorm.js index de003a6f..d6d25713 100644 --- a/sandstorm.js +++ b/sandstorm.js @@ -1,7 +1,7 @@ // Sandstorm context is detected using the METEOR_SETTINGS environment variable // in the package definition. -const isSandstorm = Meteor.settings && Meteor.settings.public && - Meteor.settings.public.sandstorm; +const isSandstorm = + Meteor.settings && Meteor.settings.public && Meteor.settings.public.sandstorm; // In sandstorm we only have one board per sandstorm instance. Since we want to // keep most of our code unchanged, we simply hard-code a board `_id` and @@ -28,15 +28,17 @@ if (isSandstorm && Meteor.isServer) { const Package = Capnp.importSystem('sandstorm/package.capnp'); const Powerbox = Capnp.importSystem('sandstorm/powerbox.capnp'); const Identity = Capnp.importSystem('sandstorm/identity.capnp'); - const SandstormHttpBridge = - Capnp.importSystem('sandstorm/sandstorm-http-bridge.capnp').SandstormHttpBridge; + const SandstormHttpBridge = Capnp.importSystem( + 'sandstorm/sandstorm-http-bridge.capnp', + ).SandstormHttpBridge; let httpBridge = null; let capnpConnection = null; const bridgeConfig = Capnp.parse( Package.BridgeConfig, - fs.readFileSync('/sandstorm-http-bridge-config')); + fs.readFileSync('/sandstorm-http-bridge-config'), + ); function getHttpBridge() { if (!httpBridge) { @@ -54,9 +56,13 @@ if (isSandstorm && Meteor.isServer) { const parsedDescriptor = Capnp.parse( Powerbox.PowerboxDescriptor, new Buffer(descriptor, 'base64'), - { packed: true }); + { packed: true }, + ); - const tag = Capnp.parse(Identity.Identity.PowerboxTag, parsedDescriptor.tags[0].value); + const tag = Capnp.parse( + Identity.Identity.PowerboxTag, + parsedDescriptor.tags[0].value, + ); const permissions = []; if (tag.permissions[1]) { permissions.push('configure'); @@ -71,35 +77,43 @@ if (isSandstorm && Meteor.isServer) { const session = httpBridge.getSessionContext(sessionId).context; const api = httpBridge.getSandstormApi(sessionId).api; - Meteor.wrapAsync((done) => { - session.claimRequest(token).then((response) => { - const identity = response.cap.castAs(Identity.Identity); - const promises = [api.getIdentityId(identity), identity.getProfile(), - httpBridge.saveIdentity(identity)]; - return Promise.all(promises).then((responses) => { - const identityId = responses[0].id.toString('hex').slice(0, 32); - const profile = responses[1].profile; - return profile.picture.getUrl().then((response) => { - const sandstormInfo = { - id: identityId, - name: profile.displayName.defaultText, - permissions, - picture: `${response.protocol}://${response.hostPath}`, - preferredHandle: profile.preferredHandle, - pronouns: profile.pronouns, - }; - - const login = Accounts.updateOrCreateUserFromExternalService( - 'sandstorm', sandstormInfo, - { profile: { name: sandstormInfo.name } }); - - updateUserPermissions(login.userId, permissions); - done(); + Meteor.wrapAsync(done => { + session + .claimRequest(token) + .then(response => { + const identity = response.cap.castAs(Identity.Identity); + const promises = [ + api.getIdentityId(identity), + identity.getProfile(), + httpBridge.saveIdentity(identity), + ]; + return Promise.all(promises).then(responses => { + const identityId = responses[0].id.toString('hex').slice(0, 32); + const profile = responses[1].profile; + return profile.picture.getUrl().then(response => { + const sandstormInfo = { + id: identityId, + name: profile.displayName.defaultText, + permissions, + picture: `${response.protocol}://${response.hostPath}`, + preferredHandle: profile.preferredHandle, + pronouns: profile.pronouns, + }; + + const login = Accounts.updateOrCreateUserFromExternalService( + 'sandstorm', + sandstormInfo, + { profile: { name: sandstormInfo.name } }, + ); + + updateUserPermissions(login.userId, permissions); + done(); + }); }); + }) + .catch(e => { + done(e, null); }); - }).catch((e) => { - done(e, null); - }); })(); }, }); @@ -107,32 +121,39 @@ if (isSandstorm && Meteor.isServer) { function reportActivity(sessionId, path, type, users, caption) { const httpBridge = getHttpBridge(); const session = httpBridge.getSessionContext(sessionId).context; - Meteor.wrapAsync((done) => { - return Promise.all(users.map((user) => { - return httpBridge.getSavedIdentity(user.id).then((response) => { - // Call getProfile() to make sure that the identity successfully resolves. - // (In C++ we would instead call whenResolved() here.) - const identity = response.identity; - return identity.getProfile().then(() => { - return { identity, - mentioned: !!user.mentioned, - subscribed: !!user.subscribed, - }; - }); - }).catch(() => { - // Ignore identities that fail to restore. Either they were added before we set - // `saveIdentityCaps` to true, or they have lost access to the board. - }); - })).then((maybeUsers) => { - const users = maybeUsers.filter((u) => !!u); - const event = { path, type, users }; - if (caption) { - event.notification = { caption }; - } + Meteor.wrapAsync(done => { + return Promise.all( + users.map(user => { + return httpBridge + .getSavedIdentity(user.id) + .then(response => { + // Call getProfile() to make sure that the identity successfully resolves. + // (In C++ we would instead call whenResolved() here.) + const identity = response.identity; + return identity.getProfile().then(() => { + return { + identity, + mentioned: !!user.mentioned, + subscribed: !!user.subscribed, + }; + }); + }) + .catch(() => { + // Ignore identities that fail to restore. Either they were added before we set + // `saveIdentityCaps` to true, or they have lost access to the board. + }); + }), + ) + .then(maybeUsers => { + const users = maybeUsers.filter(u => !!u); + const event = { path, type, users }; + if (caption) { + event.notification = { caption }; + } - return session.activity(event); - }).then(() => done(), - (e) => done(e)); + return session.activity(event); + }) + .then(() => done(), e => done(e)); })(); } @@ -146,7 +167,9 @@ if (isSandstorm && Meteor.isServer) { const eventTypes = bridgeConfig.viewInfo.eventTypes; - const defIdx = eventTypes.findIndex((def) => def.name === doc.activityType ); + const defIdx = eventTypes.findIndex( + def => def.name === doc.activityType, + ); if (defIdx >= 0) { const users = {}; function ensureUserListed(userId) { @@ -188,10 +211,14 @@ if (isSandstorm && Meteor.isServer) { if (doc.activityType === 'addComment') { const comment = CardComments.findOne(doc.commentId); caption = { defaultText: comment.text }; - const activeMembers = - _.pluck(Boards.findOne(sandstormBoard._id).activeMembers(), 'userId'); - (comment.text.match(/\B@([\w.]*)/g) || []).forEach((username) => { - const user = Meteor.users.findOne({ username: username.slice(1)}); + const activeMembers = _.pluck( + Boards.findOne(sandstormBoard._id).activeMembers(), + 'userId', + ); + (comment.text.match(/\B@([\w.]*)/g) || []).forEach(username => { + const user = Meteor.users.findOne({ + username: username.slice(1), + }); if (user && activeMembers.indexOf(user._id) !== -1) { mentionedUser(user._id); } @@ -209,18 +236,22 @@ if (isSandstorm && Meteor.isServer) { const isAdmin = permissions.indexOf('configure') > -1; const isCommentOnly = false; const isNoComments = false; - const permissionDoc = { userId, isActive, isAdmin, isNoComments, isCommentOnly }; + const permissionDoc = { + userId, + isActive, + isAdmin, + isNoComments, + isCommentOnly, + }; const boardMembers = Boards.findOne(sandstormBoard._id).members; const memberIndex = _.pluck(boardMembers, 'userId').indexOf(userId); let modifier; if (memberIndex > -1) - modifier = { $set: { [`members.${memberIndex}`]: permissionDoc }}; - else if (!isActive) - modifier = {}; - else - modifier = { $push: { members: permissionDoc }}; + modifier = { $set: { [`members.${memberIndex}`]: permissionDoc } }; + else if (!isActive) modifier = {}; + else modifier = { $push: { members: permissionDoc } }; Boards.update(sandstormBoard._id, modifier); } @@ -259,7 +290,7 @@ if (isSandstorm && Meteor.isServer) { }); Activities.update( { activityTypeId: sandstormBoard._id }, - { $set: { userId: doc._id }} + { $set: { userId: doc._id } }, ); } @@ -274,10 +305,12 @@ if (isSandstorm && Meteor.isServer) { const username = doc.services.sandstorm.preferredHandle; let appendNumber = 0; - while (Users.findOne({ - _id: { $ne: doc._id }, - username: generateUniqueUsername(username, appendNumber), - })) { + while ( + Users.findOne({ + _id: { $ne: doc._id }, + username: generateUniqueUsername(username, appendNumber), + }) + ) { appendNumber += 1; } @@ -321,40 +354,43 @@ if (isSandstorm && Meteor.isServer) { // is now handled by Sandstorm. // See https://github.com/wekan/wekan/issues/346 Migrations.add('enforce-public-visibility-for-sandstorm', () => { - Boards.update('sandstorm', { $set: { permission: 'public' }}); + Boards.update('sandstorm', { $set: { permission: 'public' } }); }); // Monkey patch to work around the problem described in // https://github.com/sandstorm-io/meteor-accounts-sandstorm/pull/31 const _httpMethods = HTTP.methods; - HTTP.methods = (newMethods) => { - Object.keys(newMethods).forEach((key) => { + HTTP.methods = newMethods => { + Object.keys(newMethods).forEach(key => { if (newMethods[key].auth) { newMethods[key].auth = function() { const sandstormID = this.req.headers['x-sandstorm-user-id']; - const user = Meteor.users.findOne({'services.sandstorm.id': sandstormID}); + const user = Meteor.users.findOne({ + 'services.sandstorm.id': sandstormID, + }); return user && user._id; }; } }); _httpMethods(newMethods); }; - } if (isSandstorm && Meteor.isClient) { let rpcCounter = 0; const rpcs = {}; - window.addEventListener('message', (event) => { + window.addEventListener('message', event => { if (event.source === window) { // Meteor likes to postmessage itself. return; } - if ((event.source !== window.parent) || - typeof event.data !== 'object' || - typeof event.data.rpcId !== 'number') { + if ( + event.source !== window.parent || + typeof event.data !== 'object' || + typeof event.data.rpcId !== 'number' + ) { throw new Error(`got unexpected postMessage: ${event}`); } @@ -374,7 +410,7 @@ if (isSandstorm && Meteor.isClient) { obj[name] = message; window.parent.postMessage(obj, '*'); return new Promise((resolve, reject) => { - rpcs[id] = (response) => { + rpcs[id] = response => { if (response.error) { reject(new Error(response.error)); } else { @@ -401,16 +437,20 @@ if (isSandstorm && Meteor.isClient) { function doRequest(serializedPowerboxDescriptor, onSuccess) { return sendRpc('powerboxRequest', { query: [serializedPowerboxDescriptor], - }).then((response) => { + }).then(response => { if (!response.canceled) { onSuccess(response); } }); } - window.sandstormRequestIdentity = function () { - doRequest(powerboxDescriptors.identity, (response) => { - Meteor.call('sandstormClaimIdentityRequest', response.token, response.descriptor); + window.sandstormRequestIdentity = function() { + doRequest(powerboxDescriptors.identity, response => { + Meteor.call( + 'sandstormClaimIdentityRequest', + response.token, + response.descriptor, + ); }); }; @@ -422,9 +462,11 @@ if (isSandstorm && Meteor.isClient) { return window.parent.postMessage(msg, '*'); } - FlowRouter.triggers.enter([({ path }) => { - updateSandstormMetaData({ setPath: path }); - }]); + FlowRouter.triggers.enter([ + ({ path }) => { + updateSandstormMetaData({ setPath: path }); + }, + ]); Tracker.autorun(() => { updateSandstormMetaData({ setTitle: DocHead.getTitle() }); diff --git a/server/accounts-lockout.js b/server/accounts-lockout.js index a9b9e311..2eb0409b 100644 --- a/server/accounts-lockout.js +++ b/server/accounts-lockout.js @@ -2,15 +2,20 @@ // server import { AccountsLockout } from 'meteor/lucasantoniassi:accounts-lockout'; -(new AccountsLockout({ +new AccountsLockout({ knownUsers: { - failuresBeforeLockout: process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE || 3, + failuresBeforeLockout: + process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE || 3, lockoutPeriod: process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD || 60, - failureWindow: process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW || 15, + failureWindow: + process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW || 15, }, unknownUsers: { - failuresBeforeLockout: process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE || 3, - lockoutPeriod: process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD || 60, - failureWindow: process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW || 15, + failuresBeforeLockout: + process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE || 3, + lockoutPeriod: + process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD || 60, + failureWindow: + process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW || 15, }, -})).startup(); +}).startup(); diff --git a/server/authentication.js b/server/authentication.js index 217647bd..20477bc5 100644 --- a/server/authentication.js +++ b/server/authentication.js @@ -1,21 +1,20 @@ import Fiber from 'fibers'; Meteor.startup(() => { - // Node Fibers 100% CPU usage issue // https://github.com/wekan/wekan-mongodb/issues/2#issuecomment-381453161 // https://github.com/meteor/meteor/issues/9796#issuecomment-381676326 // https://github.com/sandstorm-io/sandstorm/blob/0f1fec013fe7208ed0fd97eb88b31b77e3c61f42/shell/server/00-startup.js#L99-L129 Fiber.poolSize = 1e9; - Accounts.validateLoginAttempt(function (options) { + Accounts.validateLoginAttempt(function(options) { const user = options.user || {}; return !user.loginDisabled; }); Authentication = {}; - Authentication.checkUserId = function (userId) { + Authentication.checkUserId = function(userId) { if (userId === undefined) { const error = new Meteor.Error('Unauthorized', 'Unauthorized'); error.statusCode = 401; @@ -28,13 +27,12 @@ Meteor.startup(() => { error.statusCode = 403; throw error; } - }; // This will only check if the user is logged in. // The authorization checks for the user will have to be done inside each API endpoint Authentication.checkLoggedIn = function(userId) { - if(userId === undefined) { + if (userId === undefined) { const error = new Meteor.Error('Unauthorized', 'Unauthorized'); error.statusCode = 401; throw error; @@ -44,7 +42,7 @@ Meteor.startup(() => { // An admin should be authorized to access everything, so we use a separate check for admins // This throws an error if otherReq is false and the user is not an admin Authentication.checkAdminOrCondition = function(userId, otherReq) { - if(otherReq) return; + if (otherReq) return; const admin = Users.findOne({ _id: userId, isAdmin: true }); if (admin === undefined) { const error = new Meteor.Error('Forbidden', 'Forbidden'); @@ -58,14 +56,16 @@ Meteor.startup(() => { Authentication.checkLoggedIn(userId); const board = Boards.findOne({ _id: boardId }); - const normalAccess = board.permission === 'public' || board.members.some((e) => e.userId === userId); + const normalAccess = + board.permission === 'public' || + board.members.some(e => e.userId === userId); Authentication.checkAdminOrCondition(userId, normalAccess); }; if (Meteor.isServer) { - if(process.env.OAUTH2_CLIENT_ID !== '') { - - ServiceConfiguration.configurations.upsert( // eslint-disable-line no-undef + if (process.env.OAUTH2_CLIENT_ID !== '') { + ServiceConfiguration.configurations.upsert( + // eslint-disable-line no-undef { service: 'oidc' }, { $set: { @@ -76,15 +76,14 @@ Meteor.startup(() => { authorizationEndpoint: process.env.OAUTH2_AUTH_ENDPOINT, userinfoEndpoint: process.env.OAUTH2_USERINFO_ENDPOINT, tokenEndpoint: process.env.OAUTH2_TOKEN_ENDPOINT, - idTokenWhitelistFields: process.env.OAUTH2_ID_TOKEN_WHITELIST_FIELDS || [], + idTokenWhitelistFields: + process.env.OAUTH2_ID_TOKEN_WHITELIST_FIELDS || [], requestPermissions: process.env.OAUTH2_REQUEST_PERMISSIONS, }, // OAUTH2_ID_TOKEN_WHITELIST_FIELDS || [], // OAUTH2_REQUEST_PERMISSIONS || 'openid profile email', - } + }, ); } } - }); - diff --git a/server/cors.js b/server/cors.js index 0db38d9b..4badba9f 100644 --- a/server/cors.js +++ b/server/cors.js @@ -1,23 +1,27 @@ Meteor.startup(() => { - - if ( process.env.CORS ) { + if (process.env.CORS) { // Listen to incoming HTTP requests, can only be used on the server WebApp.rawConnectHandlers.use(function(req, res, next) { res.setHeader('Access-Control-Allow-Origin', process.env.CORS); return next(); }); } - if ( process.env.CORS_ALLOW_HEADERS ) { + if (process.env.CORS_ALLOW_HEADERS) { WebApp.rawConnectHandlers.use(function(req, res, next) { - res.setHeader('Access-Control-Allow-Headers', process.env.CORS_ALLOW_HEADERS); + res.setHeader( + 'Access-Control-Allow-Headers', + process.env.CORS_ALLOW_HEADERS, + ); return next(); }); } - if ( process.env.CORS_EXPOSE_HEADERS ) { + if (process.env.CORS_EXPOSE_HEADERS) { WebApp.rawConnectHandlers.use(function(req, res, next) { - res.setHeader('Access-Control-Expose-Headers', process.env.CORS_EXPOSE_HEADERS); + res.setHeader( + 'Access-Control-Expose-Headers', + process.env.CORS_EXPOSE_HEADERS, + ); return next(); }); } - }); diff --git a/server/header-login.js b/server/header-login.js index 51144c2d..88d1a1a6 100644 --- a/server/header-login.js +++ b/server/header-login.js @@ -1,10 +1,10 @@ Meteor.startup(() => { - - if ( process.env.HEADER_LOGIN_ID ) { + if (process.env.HEADER_LOGIN_ID) { Meteor.settings.public.headerLoginId = process.env.HEADER_LOGIN_ID; Meteor.settings.public.headerLoginEmail = process.env.HEADER_LOGIN_EMAIL; - Meteor.settings.public.headerLoginFirstname = process.env.HEADER_LOGIN_FIRSTNAME; - Meteor.settings.public.headerLoginLastname = process.env.HEADER_LOGIN_LASTNAME; + Meteor.settings.public.headerLoginFirstname = + process.env.HEADER_LOGIN_FIRSTNAME; + Meteor.settings.public.headerLoginLastname = + process.env.HEADER_LOGIN_LASTNAME; } - }); diff --git a/server/lib/utils.js b/server/lib/utils.js index 3b4412fe..2d19f6de 100644 --- a/server/lib/utils.js +++ b/server/lib/utils.js @@ -7,7 +7,7 @@ allowIsBoardMember = function(userId, board) { }; allowIsAnyBoardMember = function(userId, boards) { - return _.some(boards, (board) => { + return _.some(boards, board => { return board && board.hasMember(userId); }); }; diff --git a/server/migrations.js b/server/migrations.js index eefda9c8..3bc93434 100644 --- a/server/migrations.js +++ b/server/migrations.js @@ -62,16 +62,16 @@ Migrations.add('board-background-color', () => { }, }, }, - noValidateMulti + noValidateMulti, ); }); Migrations.add('lowercase-board-permission', () => { - ['Public', 'Private'].forEach((permission) => { + ['Public', 'Private'].forEach(permission => { Boards.update( { permission }, { $set: { permission: permission.toLowerCase() } }, - noValidateMulti + noValidateMulti, ); }); }); @@ -79,7 +79,7 @@ Migrations.add('lowercase-board-permission', () => { // Security migration: see https://github.com/wekan/wekan/issues/99 Migrations.add('change-attachments-type-for-non-images', () => { const newTypeForNonImage = 'application/octet-stream'; - Attachments.find().forEach((file) => { + Attachments.find().forEach(file => { if (!file.isImage()) { Attachments.update( file._id, @@ -89,14 +89,14 @@ Migrations.add('change-attachments-type-for-non-images', () => { 'copies.attachments.type': newTypeForNonImage, }, }, - noValidate + noValidate, ); } }); }); Migrations.add('card-covers', () => { - Cards.find().forEach((card) => { + Cards.find().forEach(card => { const cover = Attachments.findOne({ cardId: card._id, cover: true }); if (cover) { Cards.update(card._id, { $set: { coverId: cover._id } }, noValidate); @@ -114,7 +114,7 @@ Migrations.add('use-css-class-for-boards-colors', () => { '#2C3E50': 'midnight', '#E67E22': 'pumpkin', }; - Boards.find().forEach((board) => { + Boards.find().forEach(board => { const oldBoardColor = board.background.color; const newBoardColor = associationTable[oldBoardColor]; Boards.update( @@ -123,13 +123,13 @@ Migrations.add('use-css-class-for-boards-colors', () => { $set: { color: newBoardColor }, $unset: { background: '' }, }, - noValidate + noValidate, ); }); }); Migrations.add('denormalize-star-number-per-board', () => { - Boards.find().forEach((board) => { + Boards.find().forEach(board => { const nStars = Users.find({ 'profile.starredBoards': board._id }).count(); Boards.update(board._id, { $set: { stars: nStars } }, noValidate); }); @@ -138,9 +138,12 @@ Migrations.add('denormalize-star-number-per-board', () => { // We want to keep a trace of former members so we can efficiently publish their // infos in the general board publication. Migrations.add('add-member-isactive-field', () => { - Boards.find({}, { fields: { members: 1 } }).forEach((board) => { + Boards.find({}, { fields: { members: 1 } }).forEach(board => { const allUsersWithSomeActivity = _.chain( - Activities.find({ boardId: board._id }, { fields: { userId: 1 } }).fetch() + Activities.find( + { boardId: board._id }, + { fields: { userId: 1 } }, + ).fetch(), ) .pluck('userId') .uniq() @@ -149,11 +152,11 @@ Migrations.add('add-member-isactive-field', () => { const formerUsers = _.difference(allUsersWithSomeActivity, currentUsers); const newMemberSet = []; - board.members.forEach((member) => { + board.members.forEach(member => { member.isActive = true; newMemberSet.push(member); }); - formerUsers.forEach((userId) => { + formerUsers.forEach(userId => { newMemberSet.push({ userId, isAdmin: false, @@ -170,7 +173,7 @@ Migrations.add('add-sort-checklists', () => { Checklists.direct.update( checklist._id, { $set: { sort: index } }, - noValidate + noValidate, ); } checklist.items.forEach((item, index) => { @@ -178,7 +181,7 @@ Migrations.add('add-sort-checklists', () => { Checklists.direct.update( { _id: checklist._id, 'items._id': item._id }, { $set: { 'items.$.sort': index } }, - noValidate + noValidate, ); } }); @@ -186,14 +189,14 @@ Migrations.add('add-sort-checklists', () => { }); Migrations.add('add-swimlanes', () => { - Boards.find().forEach((board) => { + Boards.find().forEach(board => { const swimlaneId = board.getDefaultSwimline()._id; - Cards.find({ boardId: board._id }).forEach((card) => { + Cards.find({ boardId: board._id }).forEach(card => { if (!card.hasOwnProperty('swimlaneId')) { Cards.direct.update( { _id: card._id }, { $set: { swimlaneId } }, - noValidate + noValidate, ); } }); @@ -201,19 +204,19 @@ Migrations.add('add-swimlanes', () => { }); Migrations.add('add-views', () => { - Boards.find().forEach((board) => { + Boards.find().forEach(board => { if (!board.hasOwnProperty('view')) { Boards.direct.update( { _id: board._id }, { $set: { view: 'board-view-swimlanes' } }, - noValidate + noValidate, ); } }); }); Migrations.add('add-checklist-items', () => { - Checklists.find().forEach((checklist) => { + Checklists.find().forEach(checklist => { // Create new items _.sortBy(checklist.items, 'sort').forEach((item, index) => { ChecklistItems.direct.insert({ @@ -229,26 +232,26 @@ Migrations.add('add-checklist-items', () => { Checklists.direct.update( { _id: checklist._id }, { $unset: { items: 1 } }, - noValidate + noValidate, ); }); }); Migrations.add('add-profile-view', () => { - Users.find().forEach((user) => { + Users.find().forEach(user => { if (!user.hasOwnProperty('profile.boardView')) { // Set default view Users.direct.update( { _id: user._id }, { $set: { 'profile.boardView': 'board-view-lists' } }, - noValidate + noValidate, ); } }); }); Migrations.add('add-card-types', () => { - Cards.find().forEach((card) => { + Cards.find().forEach(card => { Cards.direct.update( { _id: card._id }, { @@ -257,7 +260,7 @@ Migrations.add('add-card-types', () => { linkedId: null, }, }, - noValidate + noValidate, ); }); }); @@ -274,7 +277,7 @@ Migrations.add('add-custom-fields-to-cards', () => { customFields: [], }, }, - noValidateMulti + noValidateMulti, ); }); @@ -290,7 +293,7 @@ Migrations.add('add-requester-field', () => { requestedBy: '', }, }, - noValidateMulti + noValidateMulti, ); }); @@ -306,7 +309,7 @@ Migrations.add('add-assigner-field', () => { assignedBy: '', }, }, - noValidateMulti + noValidateMulti, ); }); @@ -322,7 +325,7 @@ Migrations.add('add-parent-field-to-cards', () => { parentId: '', }, }, - noValidateMulti + noValidateMulti, ); }); @@ -339,7 +342,7 @@ Migrations.add('add-subtasks-boards', () => { subtasksDefaultListId: null, }, }, - noValidateMulti + noValidateMulti, ); }); @@ -355,7 +358,7 @@ Migrations.add('add-subtasks-sort', () => { subtaskSort: -1, }, }, - noValidateMulti + noValidateMulti, ); }); @@ -371,7 +374,7 @@ Migrations.add('add-subtasks-allowed', () => { allowsSubtasks: true, }, }, - noValidateMulti + noValidateMulti, ); }); @@ -387,7 +390,7 @@ Migrations.add('add-subtasks-allowed', () => { presentParentTask: 'no-parent', }, }, - noValidateMulti + noValidateMulti, ); }); @@ -403,7 +406,7 @@ Migrations.add('add-authenticationMethod', () => { authenticationMethod: 'password', }, }, - noValidateMulti + noValidateMulti, ); }); @@ -415,7 +418,7 @@ Migrations.add('remove-tag', () => { 'profile.tags': 1, }, }, - noValidateMulti + noValidateMulti, ); }); @@ -427,7 +430,7 @@ Migrations.add('remove-customFields-references-broken', () => { customFields: { value: null }, }, }, - noValidateMulti + noValidateMulti, ); }); @@ -443,7 +446,7 @@ Migrations.add('add-product-name', () => { productName: '', }, }, - noValidateMulti + noValidateMulti, ); }); @@ -459,7 +462,7 @@ Migrations.add('add-hide-logo', () => { hideLogo: false, }, }, - noValidateMulti + noValidateMulti, ); }); @@ -475,7 +478,7 @@ Migrations.add('add-custom-html-after-body-start', () => { customHTMLafterBodyStart: '', }, }, - noValidateMulti + noValidateMulti, ); }); @@ -491,7 +494,7 @@ Migrations.add('add-custom-html-before-body-end', () => { customHTMLbeforeBodyEnd: '', }, }, - noValidateMulti + noValidateMulti, ); }); @@ -507,7 +510,7 @@ Migrations.add('add-displayAuthenticationMethod', () => { displayAuthenticationMethod: true, }, }, - noValidateMulti + noValidateMulti, ); }); @@ -523,7 +526,7 @@ Migrations.add('add-defaultAuthenticationMethod', () => { defaultAuthenticationMethod: 'password', }, }, - noValidateMulti + noValidateMulti, ); }); @@ -539,7 +542,7 @@ Migrations.add('add-templates', () => { type: 'board', }, }, - noValidateMulti + noValidateMulti, ); Swimlanes.update( { @@ -552,7 +555,7 @@ Migrations.add('add-templates', () => { type: 'swimlane', }, }, - noValidateMulti + noValidateMulti, ); Lists.update( { @@ -569,13 +572,13 @@ Migrations.add('add-templates', () => { swimlaneId: '', }, }, - noValidateMulti + noValidateMulti, ); Users.find({ 'profile.templatesBoardId': { $exists: false, }, - }).forEach((user) => { + }).forEach(user => { // Create board and swimlanes Boards.insert( { @@ -611,7 +614,7 @@ Migrations.add('add-templates', () => { Users.update(user._id, { $set: { 'profile.cardTemplatesSwimlaneId': swimlaneId }, }); - } + }, ); // Insert the list templates swimlane @@ -627,7 +630,7 @@ Migrations.add('add-templates', () => { Users.update(user._id, { $set: { 'profile.listTemplatesSwimlaneId': swimlaneId }, }); - } + }, ); // Insert the board templates swimlane @@ -643,15 +646,15 @@ Migrations.add('add-templates', () => { Users.update(user._id, { $set: { 'profile.boardTemplatesSwimlaneId': swimlaneId }, }); - } + }, ); - } + }, ); }); }); Migrations.add('fix-circular-reference_', () => { - Cards.find().forEach((card) => { + Cards.find().forEach(card => { if (card.parentId === card._id) { Cards.update(card._id, { $set: { parentId: '' } }, noValidateMulti); } @@ -659,7 +662,7 @@ Migrations.add('fix-circular-reference_', () => { }); Migrations.add('mutate-boardIds-in-customfields', () => { - CustomFields.find().forEach((cf) => { + CustomFields.find().forEach(cf => { CustomFields.update( cf, { @@ -670,7 +673,7 @@ Migrations.add('mutate-boardIds-in-customfields', () => { boardId: '', }, }, - noValidateMulti + noValidateMulti, ); }); }); @@ -696,13 +699,13 @@ const firstBatchOfDbsToAddCreatedAndUpdated = [ UnsavedEdits, ]; -firstBatchOfDbsToAddCreatedAndUpdated.forEach((db) => { +firstBatchOfDbsToAddCreatedAndUpdated.forEach(db => { db.before.insert((userId, doc) => { doc.createdAt = Date.now(); doc.updatedAt = doc.createdAt; }); - db.before.update((userId, doc, fieldNames, modifier, options) => { + db.before.update((userId, doc, fieldNames, modifier) => { modifier.$set = modifier.$set || {}; modifier.$set.updatedAt = new Date(); }); @@ -732,13 +735,13 @@ const modifiedAtTables = [ Migrations.add('add-missing-created-and-modified', () => { Promise.all( - modifiedAtTables.map((db) => + modifiedAtTables.map(db => db .rawCollection() .update( { modifiedAt: { $exists: false } }, { $set: { modifiedAt: new Date() } }, - { multi: true } + { multi: true }, ) .then(() => db @@ -746,16 +749,16 @@ Migrations.add('add-missing-created-and-modified', () => { .update( { createdAt: { $exists: false } }, { $set: { createdAt: new Date() } }, - { multi: true } - ) - ) - ) + { multi: true }, + ), + ), + ), ) .then(() => { // eslint-disable-next-line no-console console.info('Successfully added createdAt and updatedAt to all tables'); }) - .catch((e) => { + .catch(e => { // eslint-disable-next-line no-console console.error(e); }); diff --git a/server/notifications/email.js b/server/notifications/email.js index 857c5d70..bb8a2687 100644 --- a/server/notifications/email.js +++ b/server/notifications/email.js @@ -3,11 +3,15 @@ Meteor.startup(() => { Notifications.subscribe('email', (user, title, description, params) => { // add quote to make titles easier to read in email text const quoteParams = _.clone(params); - ['card', 'list', 'oldList', 'board', 'comment'].forEach((key) => { + ['card', 'list', 'oldList', 'board', 'comment'].forEach(key => { if (quoteParams[key]) quoteParams[key] = `"${params[key]}"`; }); - const text = `${params.user} ${TAPi18n.__(description, quoteParams, user.getLanguage())}\n${params.url}`; + const text = `${params.user} ${TAPi18n.__( + description, + quoteParams, + user.getLanguage(), + )}\n${params.url}`; user.addEmailBuffer(text); // unlike setTimeout(func, delay, args), @@ -39,5 +43,3 @@ Meteor.startup(() => { }, process.env.EMAIL_NOTIFICATION_TIMEOUT || 30000); }); }); - - diff --git a/server/notifications/notifications.js b/server/notifications/notifications.js index fa8b2ee2..3f103339 100644 --- a/server/notifications/notifications.js +++ b/server/notifications/notifications.js @@ -14,14 +14,14 @@ Notifications = { notifyServices[serviceName] = callback; }, - unsubscribe: (serviceName) => { + unsubscribe: serviceName => { if (typeof notifyServices[serviceName] === 'function') delete notifyServices[serviceName]; }, - getUsers: (watchers) => { + getUsers: watchers => { const users = []; - watchers.forEach((userId) => { + watchers.forEach(userId => { const user = Users.findOne(userId); if (user) users.push(user); }); @@ -29,9 +29,10 @@ Notifications = { }, notify: (user, title, description, params) => { - for(const k in notifyServices) { + for (const k in notifyServices) { const notifyImpl = notifyServices[k]; - if (notifyImpl && typeof notifyImpl === 'function') notifyImpl(user, title, description, params); + if (notifyImpl && typeof notifyImpl === 'function') + notifyImpl(user, title, description, params); } }, }; diff --git a/server/notifications/outgoing.js b/server/notifications/outgoing.js index 655fe824..85d54968 100644 --- a/server/notifications/outgoing.js +++ b/server/notifications/outgoing.js @@ -8,7 +8,18 @@ const postCatchError = Meteor.wrapAsync((url, options, resolve) => { }); }); -const webhooksAtbts = ( (process.env.WEBHOOKS_ATTRIBUTES && process.env.WEBHOOKS_ATTRIBUTES.split(',') ) || ['cardId', 'listId', 'oldListId', 'boardId', 'comment', 'user', 'card', 'commentId', 'swimlaneId']); +const webhooksAtbts = (process.env.WEBHOOKS_ATTRIBUTES && + process.env.WEBHOOKS_ATTRIBUTES.split(',')) || [ + 'cardId', + 'listId', + 'oldListId', + 'boardId', + 'comment', + 'user', + 'card', + 'commentId', + 'swimlaneId', +]; Meteor.methods({ outgoingWebhooks(integrations, description, params) { @@ -18,13 +29,29 @@ Meteor.methods({ // label activity did not work yet, see wekan/models/activities.js const quoteParams = _.clone(params); - ['card', 'list', 'oldList', 'board', 'oldBoard', 'comment', 'checklist', 'swimlane', 'oldSwimlane', 'label', 'attachment'].forEach((key) => { + [ + 'card', + 'list', + 'oldList', + 'board', + 'oldBoard', + 'comment', + 'checklist', + 'swimlane', + 'oldSwimlane', + 'label', + 'attachment', + ].forEach(key => { if (quoteParams[key]) quoteParams[key] = `"${params[key]}"`; }); - const userId = (params.userId) ? params.userId : integrations[0].userId; + const userId = params.userId ? params.userId : integrations[0].userId; const user = Users.findOne(userId); - const text = `${params.user} ${TAPi18n.__(description, quoteParams, user.getLanguage())}\n${params.url}`; + const text = `${params.user} ${TAPi18n.__( + description, + quoteParams, + user.getLanguage(), + )}\n${params.url}`; if (text.length === 0) return; @@ -32,7 +59,7 @@ Meteor.methods({ text: `${text}`, }; - webhooksAtbts.forEach((key) => { + webhooksAtbts.forEach(key => { if (params[key]) value[key] = params[key]; }); value.description = description; @@ -45,7 +72,7 @@ Meteor.methods({ data: value, }; - integrations.forEach((integration) => { + integrations.forEach(integration => { const response = postCatchError(integration.url, options); if (response && response.statusCode && response.statusCode === 200) { diff --git a/server/notifications/watch.js b/server/notifications/watch.js index 253e15ba..8a628dad 100644 --- a/server/notifications/watch.js +++ b/server/notifications/watch.js @@ -12,22 +12,19 @@ Meteor.methods({ watchableObj = Boards.findOne(id); if (!watchableObj) throw new Meteor.Error('error-board-doesNotExist'); board = watchableObj; - } else if (watchableType === 'list') { watchableObj = Lists.findOne(id); if (!watchableObj) throw new Meteor.Error('error-list-doesNotExist'); board = watchableObj.board(); - } else if (watchableType === 'card') { watchableObj = Cards.findOne(id); if (!watchableObj) throw new Meteor.Error('error-card-doesNotExist'); board = watchableObj.board(); - } else { throw new Meteor.Error('error-json-schema'); } - if ((board.permission === 'private') && !board.hasMember(userId)) + if (board.permission === 'private' && !board.hasMember(userId)) throw new Meteor.Error('error-board-notAMember'); watchableObj.setWatcher(userId, level); diff --git a/server/policy.js b/server/policy.js index 02a42cd4..a8c33a05 100644 --- a/server/policy.js +++ b/server/policy.js @@ -1,8 +1,7 @@ import { BrowserPolicy } from 'meteor/browser-policy-common'; Meteor.startup(() => { - - if ( process.env.BROWSER_POLICY_ENABLED === 'true' ) { + if (process.env.BROWSER_POLICY_ENABLED === 'true') { // Trusted URL that can embed Wekan in iFrame. const trusted = process.env.TRUSTED_URL; BrowserPolicy.framing.disallow(); @@ -13,8 +12,7 @@ Meteor.startup(() => { //BrowserPolicy.content.allowFontDataUrl(); BrowserPolicy.framing.restrictToOrigin(trusted); //BrowserPolicy.content.allowScriptOrigin(trusted); - } - else { + } else { // Disable browser policy and allow all framing and including. // Use only at internal LAN, not at Internet. BrowserPolicy.framing.allowAll(); @@ -26,9 +24,8 @@ Meteor.startup(() => { // If Matomo URL is set, allow it. const matomoUrl = process.env.MATOMO_ADDRESS; - if (matomoUrl){ + if (matomoUrl) { //BrowserPolicy.content.allowScriptOrigin(matomoUrl); //BrowserPolicy.content.allowImageOrigin(matomoUrl); } - }); diff --git a/server/publications/activities.js b/server/publications/activities.js index 14459bf8..90be1a39 100644 --- a/server/publications/activities.js +++ b/server/publications/activities.js @@ -4,16 +4,21 @@ // We use this publication to paginate for these two publications. Meteor.publish('activities', (kind, id, limit, hideSystem) => { - check(kind, Match.Where((x) => { - return ['board', 'card'].indexOf(x) !== -1; - })); + check( + kind, + Match.Where(x => { + return ['board', 'card'].indexOf(x) !== -1; + }), + ); check(id, String); check(limit, Number); check(hideSystem, Boolean); - const selector = (hideSystem) ? {$and: [{activityType: 'addComment'}, {[`${kind}Id`]: id}]} : {[`${kind}Id`]: id}; + const selector = hideSystem + ? { $and: [{ activityType: 'addComment' }, { [`${kind}Id`]: id }] } + : { [`${kind}Id`]: id }; return Activities.find(selector, { limit, - sort: {createdAt: -1}, + sort: { createdAt: -1 }, }); }); diff --git a/server/publications/boards.js b/server/publications/boards.js index cec03858..96ef3054 100644 --- a/server/publications/boards.js +++ b/server/publications/boards.js @@ -5,58 +5,62 @@ Meteor.publish('boards', function() { // Ensure that the user is connected. If it is not, we need to return an empty // array to tell the client to remove the previously published docs. - if (!Match.test(this.userId, String)) - return []; + if (!Match.test(this.userId, String)) return []; // Defensive programming to verify that starredBoards has the expected // format -- since the field is in the `profile` a user can modify it. - const {starredBoards = []} = Users.findOne(this.userId).profile || {}; + const { starredBoards = [] } = Users.findOne(this.userId).profile || {}; check(starredBoards, [String]); - return Boards.find({ - archived: false, - $or: [ - { - _id: { $in: starredBoards }, - permission: 'public', + return Boards.find( + { + archived: false, + $or: [ + { + _id: { $in: starredBoards }, + permission: 'public', + }, + { members: { $elemMatch: { userId: this.userId, isActive: true } } }, + ], + }, + { + fields: { + _id: 1, + archived: 1, + slug: 1, + title: 1, + description: 1, + color: 1, + members: 1, + permission: 1, + type: 1, }, - { members: { $elemMatch: { userId: this.userId, isActive: true }}}, - ], - }, { - fields: { - _id: 1, - archived: 1, - slug: 1, - title: 1, - description: 1, - color: 1, - members: 1, - permission: 1, - type: 1, }, - }); + ); }); Meteor.publish('archivedBoards', function() { - if (!Match.test(this.userId, String)) - return []; + if (!Match.test(this.userId, String)) return []; - return Boards.find({ - archived: true, - members: { - $elemMatch: { - userId: this.userId, - isAdmin: true, + return Boards.find( + { + archived: true, + members: { + $elemMatch: { + userId: this.userId, + isAdmin: true, + }, }, }, - }, { - fields: { - _id: 1, - archived: 1, - slug: 1, - title: 1, + { + fields: { + _id: 1, + archived: 1, + slug: 1, + title: 1, + }, }, - }); + ); }); // If isArchived = false, this will only return board elements which are not archived. @@ -67,106 +71,130 @@ Meteor.publishRelations('board', function(boardId, isArchived) { check(isArchived, Boolean); const thisUserId = this.userId; - this.cursor(Boards.find({ - _id: boardId, - archived: false, - // If the board is not public the user has to be a member of it to see - // it. - $or: [ - { permission: 'public' }, - { members: { $elemMatch: { userId: this.userId, isActive: true }}}, - ], - // Sort required to ensure oplog usage - }, { limit: 1, sort: { _id: 1 } }), function(boardId, board) { - this.cursor(Lists.find({ boardId, archived: isArchived })); - this.cursor(Swimlanes.find({ boardId, archived: isArchived })); - this.cursor(Integrations.find({ boardId })); - this.cursor(CustomFields.find({ boardIds: {$in: [boardId]} }, { sort: { name: 1 } })); + this.cursor( + Boards.find( + { + _id: boardId, + archived: false, + // If the board is not public the user has to be a member of it to see + // it. + $or: [ + { permission: 'public' }, + { members: { $elemMatch: { userId: this.userId, isActive: true } } }, + ], + // Sort required to ensure oplog usage + }, + { limit: 1, sort: { _id: 1 } }, + ), + function(boardId, board) { + this.cursor(Lists.find({ boardId, archived: isArchived })); + this.cursor(Swimlanes.find({ boardId, archived: isArchived })); + this.cursor(Integrations.find({ boardId })); + this.cursor( + CustomFields.find( + { boardIds: { $in: [boardId] } }, + { sort: { name: 1 } }, + ), + ); - // Cards and cards comments - // XXX Originally we were publishing the card documents as a child of the - // list publication defined above using the following selector `{ listId: - // list._id }`. But it was causing a race condition in publish-composite, - // that I documented here: - // - // https://github.com/englue/meteor-publish-composite/issues/29 - // - // cottz:publish had a similar problem: - // - // https://github.com/Goluis/cottz-publish/issues/4 - // - // The current state of relational publishing in meteor is a bit sad, - // there are a lot of various packages, with various APIs, some of them - // are unmaintained. Fortunately this is something that will be fixed by - // meteor-core at some point: - // - // https://trello.com/c/BGvIwkEa/48-easy-joins-in-subscriptions - // - // And in the meantime our code below works pretty well -- it's not even a - // hack! + // Cards and cards comments + // XXX Originally we were publishing the card documents as a child of the + // list publication defined above using the following selector `{ listId: + // list._id }`. But it was causing a race condition in publish-composite, + // that I documented here: + // + // https://github.com/englue/meteor-publish-composite/issues/29 + // + // cottz:publish had a similar problem: + // + // https://github.com/Goluis/cottz-publish/issues/4 + // + // The current state of relational publishing in meteor is a bit sad, + // there are a lot of various packages, with various APIs, some of them + // are unmaintained. Fortunately this is something that will be fixed by + // meteor-core at some point: + // + // https://trello.com/c/BGvIwkEa/48-easy-joins-in-subscriptions + // + // And in the meantime our code below works pretty well -- it's not even a + // hack! - // Gather queries and send in bulk - const cardComments = this.join(CardComments); - cardComments.selector = (_ids) => ({ cardId: _ids }); - const attachments = this.join(Attachments); - attachments.selector = (_ids) => ({ cardId: _ids }); - const checklists = this.join(Checklists); - checklists.selector = (_ids) => ({ cardId: _ids }); - const checklistItems = this.join(ChecklistItems); - checklistItems.selector = (_ids) => ({ cardId: _ids }); - const parentCards = this.join(Cards); - parentCards.selector = (_ids) => ({ parentId: _ids }); - const boards = this.join(Boards); - const subCards = this.join(Cards); - subCards.selector = (_ids) => ({ archived: isArchived }); + // Gather queries and send in bulk + const cardComments = this.join(CardComments); + cardComments.selector = _ids => ({ cardId: _ids }); + const attachments = this.join(Attachments); + attachments.selector = _ids => ({ cardId: _ids }); + const checklists = this.join(Checklists); + checklists.selector = _ids => ({ cardId: _ids }); + const checklistItems = this.join(ChecklistItems); + checklistItems.selector = _ids => ({ cardId: _ids }); + const parentCards = this.join(Cards); + parentCards.selector = _ids => ({ parentId: _ids }); + const boards = this.join(Boards); + const subCards = this.join(Cards); + subCards.selector = () => ({ archived: isArchived }); - this.cursor(Cards.find({ boardId: {$in: [boardId, board.subtasksDefaultBoardId]}, archived: isArchived }), function(cardId, card) { - if (card.type === 'cardType-linkedCard') { - const impCardId = card.linkedId; - subCards.push(impCardId); - cardComments.push(impCardId); - attachments.push(impCardId); - checklists.push(impCardId); - checklistItems.push(impCardId); - } else if (card.type === 'cardType-linkedBoard') { - boards.push(card.linkedId); - } - cardComments.push(cardId); - attachments.push(cardId); - checklists.push(cardId); - checklistItems.push(cardId); - parentCards.push(cardId); - }); + this.cursor( + Cards.find({ + boardId: { $in: [boardId, board.subtasksDefaultBoardId] }, + archived: isArchived, + }), + function(cardId, card) { + if (card.type === 'cardType-linkedCard') { + const impCardId = card.linkedId; + subCards.push(impCardId); + cardComments.push(impCardId); + attachments.push(impCardId); + checklists.push(impCardId); + checklistItems.push(impCardId); + } else if (card.type === 'cardType-linkedBoard') { + boards.push(card.linkedId); + } + cardComments.push(cardId); + attachments.push(cardId); + checklists.push(cardId); + checklistItems.push(cardId); + parentCards.push(cardId); + }, + ); - // Send bulk queries for all found ids - subCards.send(); - cardComments.send(); - attachments.send(); - checklists.send(); - checklistItems.send(); - boards.send(); - parentCards.send(); + // Send bulk queries for all found ids + subCards.send(); + cardComments.send(); + attachments.send(); + checklists.send(); + checklistItems.send(); + boards.send(); + parentCards.send(); - if (board.members) { - // Board members. This publication also includes former board members that - // aren't members anymore but may have some activities attached to them in - // the history. - const memberIds = _.pluck(board.members, 'userId'); + if (board.members) { + // Board members. This publication also includes former board members that + // aren't members anymore but may have some activities attached to them in + // the history. + const memberIds = _.pluck(board.members, 'userId'); - // We omit the current user because the client should already have that data, - // and sending it triggers a subtle bug: - // https://github.com/wefork/wekan/issues/15 - this.cursor(Users.find({ - _id: { $in: _.without(memberIds, thisUserId)}, - }, { fields: { - 'username': 1, - 'profile.fullname': 1, - 'profile.avatarUrl': 1, - }})); + // We omit the current user because the client should already have that data, + // and sending it triggers a subtle bug: + // https://github.com/wefork/wekan/issues/15 + this.cursor( + Users.find( + { + _id: { $in: _.without(memberIds, thisUserId) }, + }, + { + fields: { + username: 1, + 'profile.fullname': 1, + 'profile.avatarUrl': 1, + }, + }, + ), + ); - this.cursor(presences.find({ userId: { $in: memberIds } })); - } - }); + this.cursor(presences.find({ userId: { $in: memberIds } })); + } + }, + ); return this.ready(); }); diff --git a/server/publications/cards.js b/server/publications/cards.js index c9abc421..61210ce5 100644 --- a/server/publications/cards.js +++ b/server/publications/cards.js @@ -1,4 +1,4 @@ -Meteor.publish('card', (cardId) => { +Meteor.publish('card', cardId => { check(cardId, String); return Cards.find({ _id: cardId }); }); diff --git a/server/publications/people.js b/server/publications/people.js index 56187732..cc8e3fc9 100644 --- a/server/publications/people.js +++ b/server/publications/people.js @@ -7,19 +7,22 @@ Meteor.publish('people', function(limit) { const user = Users.findOne(this.userId); if (user && user.isAdmin) { - return Users.find({}, { - limit, - sort: {createdAt: -1}, - fields: { - 'username': 1, - 'profile.fullname': 1, - 'isAdmin': 1, - 'emails': 1, - 'createdAt': 1, - 'loginDisabled': 1, - 'authenticationMethod': 1, + return Users.find( + {}, + { + limit, + sort: { createdAt: -1 }, + fields: { + username: 1, + 'profile.fullname': 1, + isAdmin: 1, + emails: 1, + createdAt: 1, + loginDisabled: 1, + authenticationMethod: 1, + }, }, - }); + ); } else { return []; } diff --git a/server/publications/rules.js b/server/publications/rules.js index d0864893..2a593067 100644 --- a/server/publications/rules.js +++ b/server/publications/rules.js @@ -1,4 +1,4 @@ -Meteor.publish('rules', (ruleId) => { +Meteor.publish('rules', ruleId => { check(ruleId, String); return Rules.find({ _id: ruleId, diff --git a/server/publications/settings.js b/server/publications/settings.js index a8f8a969..d273fe62 100644 --- a/server/publications/settings.js +++ b/server/publications/settings.js @@ -1,23 +1,25 @@ Meteor.publish('setting', () => { - return Settings.find({}, { - fields:{ - disableRegistration: 1, - productName: 1, - hideLogo: 1, - customHTMLafterBodyStart: 1, - customHTMLbeforeBodyEnd: 1, - displayAuthenticationMethod: 1, - defaultAuthenticationMethod: 1, + return Settings.find( + {}, + { + fields: { + disableRegistration: 1, + productName: 1, + hideLogo: 1, + customHTMLafterBodyStart: 1, + customHTMLbeforeBodyEnd: 1, + displayAuthenticationMethod: 1, + defaultAuthenticationMethod: 1, + }, }, - }); + ); }); -Meteor.publish('mailServer', function () { - if (!Match.test(this.userId, String)) - return []; +Meteor.publish('mailServer', function() { + if (!Match.test(this.userId, String)) return []; const user = Users.findOne(this.userId); - if(user && user.isAdmin){ - return Settings.find({}, {fields: {mailServer: 1}}); + if (user && user.isAdmin) { + return Settings.find({}, { fields: { mailServer: 1 } }); } return []; }); diff --git a/server/publications/users.js b/server/publications/users.js index f0c94153..59411ca0 100644 --- a/server/publications/users.js +++ b/server/publications/users.js @@ -3,7 +3,7 @@ Meteor.publish('user-miniprofile', function(userId) { return Users.find(userId, { fields: { - 'username': 1, + username: 1, 'profile.fullname': 1, 'profile.avatarUrl': 1, }, @@ -20,9 +20,12 @@ Meteor.publish('user-admin', function() { Meteor.publish('user-authenticationMethod', function(match) { check(match, String); - return Users.find({$or: [{_id: match}, {email: match}, {username: match}]}, { - fields: { - 'authenticationMethod': 1, + return Users.find( + { $or: [{ _id: match }, { email: match }, { username: match }] }, + { + fields: { + authenticationMethod: 1, + }, }, - }); + ); }); diff --git a/server/rulesHelper.js b/server/rulesHelper.js index 7eb65f1a..cf278c52 100644 --- a/server/rulesHelper.js +++ b/server/rulesHelper.js @@ -1,72 +1,78 @@ RulesHelper = { - executeRules(activity){ + executeRules(activity) { const matchingRules = this.findMatchingRules(activity); - for(let i = 0; i< matchingRules.length; i++){ + for (let i = 0; i < matchingRules.length; i++) { const action = matchingRules[i].getAction(); - if(action !== undefined){ + if (action !== undefined) { this.performAction(activity, action); } } }, - findMatchingRules(activity){ + findMatchingRules(activity) { const activityType = activity.activityType; - if(TriggersDef[activityType] === undefined){ + if (TriggersDef[activityType] === undefined) { return []; } const matchingFields = TriggersDef[activityType].matchingFields; const matchingMap = this.buildMatchingFieldsMap(activity, matchingFields); const matchingTriggers = Triggers.find(matchingMap); const matchingRules = []; - matchingTriggers.forEach(function(trigger){ + matchingTriggers.forEach(function(trigger) { const rule = trigger.getRule(); // Check that for some unknown reason there are some leftover triggers // not connected to any rules - if(rule !== undefined){ + if (rule !== undefined) { matchingRules.push(trigger.getRule()); } }); return matchingRules; }, - buildMatchingFieldsMap(activity, matchingFields){ - const matchingMap = {'activityType':activity.activityType}; - for(let i = 0; i< matchingFields.length; i++){ + buildMatchingFieldsMap(activity, matchingFields) { + const matchingMap = { activityType: activity.activityType }; + for (let i = 0; i < matchingFields.length; i++) { // Creating a matching map with the actual field of the activity // and with the wildcard (for example: trigger when a card is added // in any [*] board - matchingMap[matchingFields[i]] = { $in: [activity[matchingFields[i]], '*']}; + matchingMap[matchingFields[i]] = { + $in: [activity[matchingFields[i]], '*'], + }; } return matchingMap; }, - performAction(activity, action){ - const card = Cards.findOne({_id:activity.cardId}); + performAction(activity, action) { + const card = Cards.findOne({ _id: activity.cardId }); const boardId = activity.boardId; - if(action.actionType === 'moveCardToTop'){ + if (action.actionType === 'moveCardToTop') { let listId; let list; - if(action.listTitle === '*'){ + if (action.listTitle === '*') { listId = card.listId; list = card.list(); - }else{ - list = Lists.findOne({title: action.listTitle, boardId }); + } else { + list = Lists.findOne({ title: action.listTitle, boardId }); listId = list._id; } - const minOrder = _.min(list.cardsUnfiltered(card.swimlaneId).map((c) => c.sort)); + const minOrder = _.min( + list.cardsUnfiltered(card.swimlaneId).map(c => c.sort), + ); card.move(boardId, card.swimlaneId, listId, minOrder - 1); } - if(action.actionType === 'moveCardToBottom'){ + if (action.actionType === 'moveCardToBottom') { let listId; let list; - if(action.listTitle === '*'){ + if (action.listTitle === '*') { listId = card.listId; list = card.list(); - }else{ - list = Lists.findOne({title: action.listTitle, boardId}); + } else { + list = Lists.findOne({ title: action.listTitle, boardId }); listId = list._id; } - const maxOrder = _.max(list.cardsUnfiltered(card.swimlaneId).map((c) => c.sort)); + const maxOrder = _.max( + list.cardsUnfiltered(card.swimlaneId).map(c => c.sort), + ); card.move(boardId, card.swimlaneId, listId, maxOrder + 1); } - if(action.actionType === 'sendEmail'){ + if (action.actionType === 'sendEmail') { const to = action.emailTo; const text = action.emailMsg || ''; const subject = action.emailSubject || ''; @@ -84,38 +90,38 @@ RulesHelper = { } } - if(action.actionType === 'setDate') { + if (action.actionType === 'setDate') { try { const currentDateTime = new Date(); - switch (action.dateField){ - case 'startAt': { - const resStart = card.getStart(); - if (typeof resStart === 'undefined') { - card.setStart(currentDateTime); + switch (action.dateField) { + case 'startAt': { + const resStart = card.getStart(); + if (typeof resStart === 'undefined') { + card.setStart(currentDateTime); + } + break; } - break; - } - case 'endAt': { - const resEnd = card.getEnd(); - if (typeof resEnd === 'undefined') { - card.setEnd(currentDateTime); + case 'endAt': { + const resEnd = card.getEnd(); + if (typeof resEnd === 'undefined') { + card.setEnd(currentDateTime); + } + break; } - break; - } - case 'dueAt': { - const resDue = card.getDue(); - if (typeof resDue === 'undefined') { - card.setDue(currentDateTime); + case 'dueAt': { + const resDue = card.getDue(); + if (typeof resDue === 'undefined') { + card.setDue(currentDateTime); + } + break; } - break; - } - case 'receivedAt': { - const resReceived = card.getReceived(); - if (typeof resReceived === 'undefined') { - card.setReceived(currentDateTime); + case 'receivedAt': { + const resReceived = card.getReceived(); + if (typeof resReceived === 'undefined') { + card.setReceived(currentDateTime); + } + break; } - break; - } } } catch (e) { // eslint-disable-next-line no-console @@ -124,135 +130,177 @@ RulesHelper = { } } - if(action.actionType === 'updateDate'){ + if (action.actionType === 'updateDate') { const currentDateTimeUpdate = new Date(); - switch (action.dateField){ - case 'startAt': { - card.setStart(currentDateTimeUpdate); - break; - } - case 'endAt': { - card.setEnd(currentDateTimeUpdate); - break; - } - case 'dueAt': { - card.setDue(currentDateTimeUpdate); - break; - } - case 'receivedAt': { - card.setReceived(currentDateTimeUpdate); - break; - } + switch (action.dateField) { + case 'startAt': { + card.setStart(currentDateTimeUpdate); + break; + } + case 'endAt': { + card.setEnd(currentDateTimeUpdate); + break; + } + case 'dueAt': { + card.setDue(currentDateTimeUpdate); + break; + } + case 'receivedAt': { + card.setReceived(currentDateTimeUpdate); + break; + } } } - if(action.actionType === 'removeDate'){ - switch (action.dateField){ - case 'startAt': { - card.unsetStart(); - break; - } - case 'endAt': { - card.unsetEnd(); - break; - } - case 'dueAt': { - card.unsetDue(); - break; - } - case 'receivedAt': { - card.unsetReceived(); - break; - } + if (action.actionType === 'removeDate') { + switch (action.dateField) { + case 'startAt': { + card.unsetStart(); + break; + } + case 'endAt': { + card.unsetEnd(); + break; + } + case 'dueAt': { + card.unsetDue(); + break; + } + case 'receivedAt': { + card.unsetReceived(); + break; + } } } - if(action.actionType === 'archive'){ + if (action.actionType === 'archive') { card.archive(); } - if(action.actionType === 'unarchive'){ + if (action.actionType === 'unarchive') { card.restore(); } - if(action.actionType === 'setColor'){ + if (action.actionType === 'setColor') { card.setColor(action.selectedColor); } - if(action.actionType === 'addLabel'){ + if (action.actionType === 'addLabel') { card.addLabel(action.labelId); } - if(action.actionType === 'removeLabel'){ + if (action.actionType === 'removeLabel') { card.removeLabel(action.labelId); } - if(action.actionType === 'addMember'){ - const memberId = Users.findOne({username:action.username})._id; + if (action.actionType === 'addMember') { + const memberId = Users.findOne({ username: action.username })._id; card.assignMember(memberId); } - if(action.actionType === 'removeMember'){ - if(action.username === '*'){ + if (action.actionType === 'removeMember') { + if (action.username === '*') { const members = card.members; - for(let i = 0; i< members.length; i++){ + for (let i = 0; i < members.length; i++) { card.unassignMember(members[i]); } - }else{ - const memberId = Users.findOne({username:action.username})._id; + } else { + const memberId = Users.findOne({ username: action.username })._id; card.unassignMember(memberId); } } - if(action.actionType === 'checkAll'){ - const checkList = Checklists.findOne({'title':action.checklistName, 'cardId':card._id}); + if (action.actionType === 'checkAll') { + const checkList = Checklists.findOne({ + title: action.checklistName, + cardId: card._id, + }); checkList.checkAllItems(); } - if(action.actionType === 'uncheckAll'){ - const checkList = Checklists.findOne({'title':action.checklistName, 'cardId':card._id}); + if (action.actionType === 'uncheckAll') { + const checkList = Checklists.findOne({ + title: action.checklistName, + cardId: card._id, + }); checkList.uncheckAllItems(); } - if(action.actionType === 'checkItem'){ - const checkList = Checklists.findOne({'title':action.checklistName, 'cardId':card._id}); - const checkItem = ChecklistItems.findOne({'title':action.checkItemName, 'checkListId':checkList._id}); + if (action.actionType === 'checkItem') { + const checkList = Checklists.findOne({ + title: action.checklistName, + cardId: card._id, + }); + const checkItem = ChecklistItems.findOne({ + title: action.checkItemName, + checkListId: checkList._id, + }); checkItem.check(); } - if(action.actionType === 'uncheckItem'){ - const checkList = Checklists.findOne({'title':action.checklistName, 'cardId':card._id}); - const checkItem = ChecklistItems.findOne({'title':action.checkItemName, 'checkListId':checkList._id}); + if (action.actionType === 'uncheckItem') { + const checkList = Checklists.findOne({ + title: action.checklistName, + cardId: card._id, + }); + const checkItem = ChecklistItems.findOne({ + title: action.checkItemName, + checkListId: checkList._id, + }); checkItem.uncheck(); } - if(action.actionType === 'addChecklist'){ - Checklists.insert({'title':action.checklistName, 'cardId':card._id, 'sort':0}); + if (action.actionType === 'addChecklist') { + Checklists.insert({ + title: action.checklistName, + cardId: card._id, + sort: 0, + }); } - if(action.actionType === 'removeChecklist'){ - Checklists.remove({'title':action.checklistName, 'cardId':card._id, 'sort':0}); + if (action.actionType === 'removeChecklist') { + Checklists.remove({ + title: action.checklistName, + cardId: card._id, + sort: 0, + }); } - if(action.actionType === 'addSwimlane'){ + if (action.actionType === 'addSwimlane') { Swimlanes.insert({ title: action.swimlaneName, boardId, sort: 0, }); } - if(action.actionType === 'addChecklistWithItems'){ - const checkListId = Checklists.insert({'title':action.checklistName, 'cardId':card._id, 'sort':0}); + if (action.actionType === 'addChecklistWithItems') { + const checkListId = Checklists.insert({ + title: action.checklistName, + cardId: card._id, + sort: 0, + }); const itemsArray = action.checklistItems.split(','); - const checkList = Checklists.findOne({_id:checkListId}); - for(let i = 0; i