summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/components/activities/activities.js75
-rw-r--r--client/components/activities/comments.js28
-rw-r--r--client/components/boards/boardArchive.js32
-rw-r--r--client/components/boards/boardBody.js92
-rw-r--r--client/components/boards/boardHeader.js120
-rw-r--r--client/components/boards/boardsList.js22
-rw-r--r--client/components/cards/attachments.js24
-rw-r--r--client/components/cards/cardDetails.js102
-rw-r--r--client/components/cards/labels.js114
-rw-r--r--client/components/cards/minicard.js4
-rw-r--r--client/components/lists/list.js83
-rw-r--r--client/components/lists/listBody.js80
-rw-r--r--client/components/lists/listHeader.js62
-rw-r--r--client/components/main/editor.js57
-rw-r--r--client/components/main/header.js10
-rw-r--r--client/components/main/helpers.js65
-rw-r--r--client/components/main/layouts.js16
-rw-r--r--client/components/main/popup.js20
-rw-r--r--client/components/mixins/infiniteScrolling.js24
-rw-r--r--client/components/mixins/perfectScrollbar.js12
-rw-r--r--client/components/sidebar/sidebar.js194
-rw-r--r--client/components/sidebar/sidebarArchives.js34
-rw-r--r--client/components/sidebar/sidebarFilters.js100
-rw-r--r--client/components/users/userAvatar.js124
-rw-r--r--client/components/users/userHeader.js43
-rw-r--r--client/config/accounts.js26
-rw-r--r--client/config/blazeHelpers.js48
-rw-r--r--client/config/reactiveTabs.js5
-rw-r--r--client/config/router.js38
-rw-r--r--client/lib/cssEvents.js28
-rw-r--r--client/lib/escapeActions.js72
-rw-r--r--client/lib/filter.js88
-rw-r--r--client/lib/i18n.js9
-rw-r--r--client/lib/inlinedform.js32
-rw-r--r--client/lib/keyboard.js18
-rw-r--r--client/lib/modal.js2
-rw-r--r--client/lib/multiSelection.js93
-rw-r--r--client/lib/popup.js123
-rw-r--r--client/lib/unsavedEdits.js20
-rw-r--r--client/lib/utils.js66
40 files changed, 1066 insertions, 1139 deletions
diff --git a/client/components/activities/activities.js b/client/components/activities/activities.js
index 400e3848..d6a0cf7f 100644
--- a/client/components/activities/activities.js
+++ b/client/components/activities/activities.js
@@ -1,99 +1,98 @@
-var activitiesPerPage = 20;
+const activitiesPerPage = 20;
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'activities';
},
- onCreated: function() {
- var self = this;
+ onCreated() {
// XXX Should we use ReactiveNumber?
- self.page = new ReactiveVar(1);
- self.loadNextPageLocked = false;
- var sidebar = self.componentParent(); // XXX for some reason not working
+ this.page = new ReactiveVar(1);
+ this.loadNextPageLocked = false;
+ const sidebar = this.componentParent(); // XXX for some reason not working
sidebar.callFirstWith(null, 'resetNextPeak');
- self.autorun(function() {
- var mode = self.data().mode;
- var capitalizedMode = Utils.capitalize(mode);
- var id = Session.get('current' + capitalizedMode);
- var limit = self.page.get() * activitiesPerPage;
+ this.autorun(() => {
+ const mode = this.data().mode;
+ const capitalizedMode = Utils.capitalize(mode);
+ const id = Session.get(`current${capitalizedMode}`);
+ const limit = this.page.get() * activitiesPerPage;
if (id === null)
return;
- self.subscribe('activities', mode, id, limit, function() {
- self.loadNextPageLocked = false;
+ this.subscribe('activities', mode, id, limit, () => {
+ this.loadNextPageLocked = false;
// If the sibear peak hasn't increased, that mean that there are no more
// activities, and we can stop calling new subscriptions.
// XXX This is hacky! We need to know excatly and reactively how many
// activities there are, we probably want to denormalize this number
// dirrectly into card and board documents.
- var a = sidebar.callFirstWith(null, 'getNextPeak');
+ const nextPeakBefore = sidebar.callFirstWith(null, 'getNextPeak');
sidebar.calculateNextPeak();
- var b = sidebar.callFirstWith(null, 'getNextPeak');
- if (a === b) {
+ const nextPeakAfter = sidebar.callFirstWith(null, 'getNextPeak');
+ if (nextPeakBefore === nextPeakAfter) {
sidebar.callFirstWith(null, 'resetNextPeak');
}
});
});
},
- loadNextPage: function() {
+ loadNextPage() {
if (this.loadNextPageLocked === false) {
this.page.set(this.page.get() + 1);
this.loadNextPageLocked = true;
}
},
- boardLabel: function() {
+ boardLabel() {
return TAPi18n.__('this-board');
},
- cardLabel: function() {
+ cardLabel() {
return TAPi18n.__('this-card');
},
- cardLink: function() {
- var card = this.currentData().card();
+ cardLink() {
+ const card = this.currentData().card();
return card && Blaze.toHTML(HTML.A({
href: card.absoluteUrl(),
- 'class': 'action-card'
+ 'class': 'action-card',
}, card.title));
},
- memberLink: function() {
+ memberLink() {
return Blaze.toHTMLWithData(Template.memberName, {
- user: this.currentData().member()
+ user: this.currentData().member(),
});
},
- attachmentLink: function() {
- var attachment = this.currentData().attachment();
+ attachmentLink() {
+ const attachment = this.currentData().attachment();
return attachment && Blaze.toHTML(HTML.A({
href: attachment.url(),
- 'class': 'js-open-attachment-viewer'
+ 'class': 'js-open-attachment-viewer',
}, attachment.name()));
},
- events: function() {
+ events() {
return [{
// XXX We should use Popup.afterConfirmation here
- 'click .js-delete-comment': function() {
- var commentId = this.currentData().commentId;
+ 'click .js-delete-comment'() {
+ const commentId = this.currentData().commentId;
CardComments.remove(commentId);
},
- 'submit .js-edit-comment': function(evt) {
+ 'submit .js-edit-comment'(evt) {
evt.preventDefault();
- var commentText = this.currentComponent().getValue();
- var commentId = Template.parentData().commentId;
+ const commentText = this.currentComponent().getValue();
+ const commentId = Template.parentData().commentId;
if ($.trim(commentText)) {
CardComments.update(commentId, {
$set: {
- text: commentText
- }
+ text: commentText,
+ },
});
}
- }
+ },
}];
- }
+ },
}).register('activities');
diff --git a/client/components/activities/comments.js b/client/components/activities/comments.js
index e3a82c4b..08401caa 100644
--- a/client/components/activities/comments.js
+++ b/client/components/activities/comments.js
@@ -1,4 +1,4 @@
-let commentFormIsOpen = new ReactiveVar(false);
+const commentFormIsOpen = new ReactiveVar(false);
BlazeComponent.extendComponent({
template() {
@@ -19,16 +19,16 @@ BlazeComponent.extendComponent({
events() {
return [{
- 'click .js-new-comment:not(.focus)': function() {
+ 'click .js-new-comment:not(.focus)'() {
commentFormIsOpen.set(true);
},
- 'submit .js-new-comment-form': function(evt) {
- let input = this.getInput();
+ 'submit .js-new-comment-form'(evt) {
+ const input = this.getInput();
if ($.trim(input.val())) {
CardComments.insert({
boardId: this.currentData().boardId,
cardId: this.currentData()._id,
- text: input.val()
+ text: input.val(),
});
resetCommentInput(input);
Tracker.flush();
@@ -37,13 +37,13 @@ BlazeComponent.extendComponent({
evt.preventDefault();
},
// Pressing Ctrl+Enter should submit the form
- 'keydown form textarea': function(evt) {
+ 'keydown form textarea'(evt) {
if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) {
this.find('button[type=submit]').click();
}
- }
+ },
}];
- }
+ },
}).register('commentForm');
// XXX This should be a static method of the `commentForm` component
@@ -63,15 +63,15 @@ Tracker.autorun(() => {
Tracker.afterFlush(() => {
autosize.update($('.js-new-comment-input'));
});
-})
+});
EscapeActions.register('inlinedForm',
- function() {
+ () => {
const draftKey = {
fieldName: 'cardComment',
- docId: Session.get('currentCard')
+ docId: Session.get('currentCard'),
};
- let commentInput = $('.js-new-comment-input');
+ const commentInput = $('.js-new-comment-input');
if ($.trim(commentInput.val())) {
UnsavedEdits.set(draftKey, commentInput.val());
} else {
@@ -79,7 +79,7 @@ EscapeActions.register('inlinedForm',
}
resetCommentInput(commentInput);
},
- function() { return commentFormIsOpen.get(); }, {
- noClickEscapeOn: '.js-new-comment'
+ () => { return commentFormIsOpen.get(); }, {
+ noClickEscapeOn: '.js-new-comment',
}
);
diff --git a/client/components/boards/boardArchive.js b/client/components/boards/boardArchive.js
index 1ce1a593..9d7ca7f2 100644
--- a/client/components/boards/boardArchive.js
+++ b/client/components/boards/boardArchive.js
@@ -1,8 +1,8 @@
Template.headerTitle.events({
- 'click .js-open-archived-board': function() {
- Modal.open('archivedBoards')
- }
-})
+ 'click .js-open-archived-board'() {
+ Modal.open('archivedBoards');
+ },
+});
BlazeComponent.extendComponent({
template() {
@@ -10,26 +10,26 @@ BlazeComponent.extendComponent({
},
onCreated() {
- this.subscribe('archivedBoards')
+ this.subscribe('archivedBoards');
},
archivedBoards() {
return Boards.find({ archived: true }, {
- sort: ['title']
- })
+ sort: ['title'],
+ });
},
events() {
return [{
- 'click .js-restore-board': function() {
- let boardId = this.currentData()._id
+ 'click .js-restore-board'() {
+ const boardId = this.currentData()._id;
Boards.update(boardId, {
$set: {
- archived: false
- }
- })
- Utils.goBoardId(boardId)
- }
- }]
+ archived: false,
+ },
+ });
+ Utils.goBoardId(boardId);
+ },
+ }];
},
-}).register('archivedBoards')
+}).register('archivedBoards');
diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js
index fd9ee6bc..980a9015 100644
--- a/client/components/boards/boardBody.js
+++ b/client/components/boards/boardBody.js
@@ -1,11 +1,11 @@
-var subManager = new SubsManager();
+const subManager = new SubsManager();
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'board';
},
- onCreated: function() {
+ onCreated() {
this.draggingActive = new ReactiveVar(false);
this.showOverlay = new ReactiveVar(false);
this.isBoardReady = new ReactiveVar(false);
@@ -15,15 +15,15 @@ BlazeComponent.extendComponent({
// XXX The boardId should be readed from some sort the component "props",
// unfortunatly, Blaze doesn't have this notion.
this.autorun(() => {
- let currentBoardId = Session.get('currentBoard');
- if (! currentBoardId)
+ const currentBoardId = Session.get('currentBoard');
+ if (!currentBoardId)
return;
- var handle = subManager.subscribe('board', currentBoardId);
+ const handle = subManager.subscribe('board', currentBoardId);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
this.isBoardReady.set(handle.ready());
- })
- })
+ });
+ });
});
this._isDragging = false;
@@ -33,52 +33,52 @@ BlazeComponent.extendComponent({
this.mouseHasEnterCardDetails = false;
},
- openNewListForm: function() {
+ openNewListForm() {
this.componentChildren('addListForm')[0].open();
},
// XXX Flow components allow us to avoid creating these two setter methods by
// exposing a public API to modify the component state. We need to investigate
// best practices here.
- setIsDragging: function(bool) {
+ setIsDragging(bool) {
this.draggingActive.set(bool);
},
- scrollLeft: function(position = 0) {
+ scrollLeft(position = 0) {
this.$('.js-lists').animate({
- scrollLeft: position
+ scrollLeft: position,
});
},
- currentCardIsInThisList: function() {
- var currentCard = Cards.findOne(Session.get('currentCard'));
- var listId = this.currentData()._id;
+ currentCardIsInThisList() {
+ const currentCard = Cards.findOne(Session.get('currentCard'));
+ const listId = this.currentData()._id;
return currentCard && currentCard.listId === listId;
},
- events: function() {
+ events() {
return [{
// XXX The board-overlay div should probably be moved to the parent
// component.
- 'mouseenter .board-overlay': function() {
+ 'mouseenter .board-overlay'() {
if (this.mouseHasEnterCardDetails) {
this.showOverlay.set(false);
}
},
// Click-and-drag action
- 'mousedown .board-canvas': function(evt) {
+ 'mousedown .board-canvas'(evt) {
if ($(evt.target).closest('a,.js-list-header').length === 0) {
this._isDragging = true;
this._lastDragPositionX = evt.clientX;
}
},
- 'mouseup': function(evt) {
+ 'mouseup'() {
if (this._isDragging) {
this._isDragging = false;
}
},
- 'mousemove': function(evt) {
+ 'mousemove'(evt) {
if (this._isDragging) {
// Update the canvas position
this.listsDom.scrollLeft -= evt.clientX - this._lastDragPositionX;
@@ -91,40 +91,40 @@ BlazeComponent.extendComponent({
EscapeActions.executeUpTo('popup-close');
EscapeActions.preventNextClick();
}
- }
+ },
}];
- }
+ },
}).register('board');
Template.boardBody.onRendered(function() {
- var self = BlazeComponent.getComponentForElement(this.firstNode);
+ const self = BlazeComponent.getComponentForElement(this.firstNode);
self.listsDom = this.find('.js-lists');
- if (! Session.get('currentCard')) {
+ if (!Session.get('currentCard')) {
self.scrollLeft();
}
// We want to animate the card details window closing. We rely on CSS
// transition for the actual animation.
self.listsDom._uihooks = {
- removeElement: function(node) {
- var removeNode = _.once(function() {
+ removeElement(node) {
+ const removeNode = _.once(() => {
node.parentNode.removeChild(node);
});
if ($(node).hasClass('js-card-details')) {
$(node).css({
flexBasis: 0,
- padding: 0
+ padding: 0,
});
$(self.listsDom).one(CSSEvents.transitionend, removeNode);
} else {
removeNode();
}
- }
+ },
};
- if (! Meteor.user() || ! Meteor.user().isBoardMember())
+ if (!Meteor.user() || !Meteor.user().isBoardMember())
return;
self.$(self.listsDom).sortable({
@@ -134,63 +134,63 @@ Template.boardBody.onRendered(function() {
items: '.js-list:not(.js-list-composer)',
placeholder: 'list placeholder',
distance: 7,
- start: function(evt, ui) {
+ start(evt, ui) {
ui.placeholder.height(ui.helper.height());
Popup.close();
},
- stop: function() {
+ stop() {
self.$('.js-lists').find('.js-list:not(.js-list-composer)').each(
- function(i, list) {
- var data = Blaze.getData(list);
+ (i, list) => {
+ const data = Blaze.getData(list);
Lists.update(data._id, {
$set: {
- sort: i
- }
+ sort: i,
+ },
});
}
);
- }
+ },
});
// Disable drag-dropping while in multi-selection mode
- self.autorun(function() {
+ self.autorun(() => {
self.$(self.listsDom).sortable('option', 'disabled',
MultiSelection.isActive());
});
// If there is no data in the board (ie, no lists) we autofocus the list
// creation form by clicking on the corresponding element.
- var currentBoard = Boards.findOne(Session.get('currentBoard'));
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (currentBoard.lists().count() === 0) {
self.openNewListForm();
}
});
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'addListForm';
},
// Proxy
- open: function() {
+ open() {
this.componentChildren('inlinedForm')[0].open();
},
- events: function() {
+ events() {
return [{
- submit: function(evt) {
+ submit(evt) {
evt.preventDefault();
- var title = this.find('.list-name-input');
+ const title = this.find('.list-name-input');
if ($.trim(title.value)) {
Lists.insert({
title: title.value,
boardId: Session.get('currentBoard'),
- sort: $('.list').length
+ sort: $('.list').length,
});
title.value = '';
}
- }
+ },
}];
- }
+ },
}).register('addListForm');
diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js
index d23dd5f2..5d13fa34 100644
--- a/client/components/boards/boardHeader.js
+++ b/client/components/boards/boardHeader.js
@@ -1,143 +1,143 @@
Template.boardMenuPopup.events({
'click .js-rename-board': Popup.open('boardChangeTitle'),
- 'click .js-open-archives': function() {
+ 'click .js-open-archives'() {
Sidebar.setView('archives');
Popup.close();
},
'click .js-change-board-color': Popup.open('boardChangeColor'),
'click .js-change-language': Popup.open('changeLanguage'),
- 'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
- var boardId = Session.get('currentBoard');
+ 'click .js-archive-board ': Popup.afterConfirm('archiveBoard', () => {
+ const boardId = Session.get('currentBoard');
Boards.update(boardId, { $set: { archived: true }});
// XXX We should have some kind of notification on top of the page to
// confirm that the board was successfully archived.
FlowRouter.go('home');
- })
+ }),
});
Template.boardChangeTitlePopup.events({
- submit: function(evt, t) {
- var title = t.$('.js-board-name').val().trim();
+ submit(evt, tpl) {
+ const title = tpl.$('.js-board-name').val().trim();
if (title) {
Boards.update(this._id, {
$set: {
- title: title
- }
+ title,
+ },
});
Popup.close();
}
evt.preventDefault();
- }
+ },
});
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'headerBoard';
},
- isStarred: function() {
- var boardId = Session.get('currentBoard');
- var user = Meteor.user();
+ isStarred() {
+ const boardId = Session.get('currentBoard');
+ const user = Meteor.user();
return user && user.hasStarred(boardId);
},
// Only show the star counter if the number of star is greater than 2
- showStarCounter: function() {
- var currentBoard = this.currentData();
+ showStarCounter() {
+ const currentBoard = this.currentData();
return currentBoard && currentBoard.stars >= 2;
},
- events: function() {
+ events() {
return [{
'click .js-edit-board-title': Popup.open('boardChangeTitle'),
- 'click .js-star-board': function() {
+ 'click .js-star-board'() {
Meteor.user().toggleBoardStar(Session.get('currentBoard'));
},
'click .js-open-board-menu': Popup.open('boardMenu'),
'click .js-change-visibility': Popup.open('boardChangeVisibility'),
- 'click .js-open-filter-view': function() {
+ 'click .js-open-filter-view'() {
Sidebar.setView('filter');
},
- 'click .js-filter-reset': function(evt) {
+ 'click .js-filter-reset'(evt) {
evt.stopPropagation();
Sidebar.setView();
Filter.reset();
},
- 'click .js-multiselection-activate': function() {
- var currentCard = Session.get('currentCard');
+ 'click .js-multiselection-activate'() {
+ const currentCard = Session.get('currentCard');
MultiSelection.activate();
if (currentCard) {
MultiSelection.add(currentCard);
}
},
- 'click .js-multiselection-reset': function(evt) {
+ 'click .js-multiselection-reset'(evt) {
evt.stopPropagation();
MultiSelection.disable();
- }
+ },
}];
- }
+ },
}).register('headerBoard');
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'boardChangeColorPopup';
},
- backgroundColors: function() {
+ backgroundColors() {
return Boards.simpleSchema()._schema.color.allowedValues;
},
- isSelected: function() {
- var currentBoard = Boards.findOne(Session.get('currentBoard'));
+ isSelected() {
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
return currentBoard.color === this.currentData().toString();
},
- events: function() {
+ events() {
return [{
- 'click .js-select-background': function(evt) {
- var currentBoardId = Session.get('currentBoard');
+ 'click .js-select-background'(evt) {
+ const currentBoardId = Session.get('currentBoard');
Boards.update(currentBoardId, {
$set: {
- color: this.currentData().toString()
- }
+ color: this.currentData().toString(),
+ },
});
evt.preventDefault();
- }
+ },
}];
- }
+ },
}).register('boardChangeColorPopup');
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'createBoardPopup';
},
- onCreated: function() {
+ onCreated() {
this.visibilityMenuIsOpen = new ReactiveVar(false);
this.visibility = new ReactiveVar('private');
},
- visibilityCheck: function() {
+ visibilityCheck() {
return this.currentData() === this.visibility.get();
},
- setVisibility: function(visibility) {
+ setVisibility(visibility) {
this.visibility.set(visibility);
this.visibilityMenuIsOpen.set(false);
},
- toogleVisibilityMenu: function() {
- this.visibilityMenuIsOpen.set(! this.visibilityMenuIsOpen.get());
+ toogleVisibilityMenu() {
+ this.visibilityMenuIsOpen.set(!this.visibilityMenuIsOpen.get());
},
- onSubmit: function(evt) {
+ onSubmit(evt) {
evt.preventDefault();
- var title = this.find('.js-new-board-title').value;
- var visibility = this.visibility.get();
+ const title = this.find('.js-new-board-title').value;
+ const visibility = this.visibility.get();
- var boardId = Boards.insert({
- title: title,
- permission: visibility
+ const boardId = Boards.insert({
+ title,
+ permission: visibility,
});
Utils.goBoardId(boardId);
@@ -146,39 +146,39 @@ BlazeComponent.extendComponent({
Meteor.user().toggleBoardStar(boardId);
},
- events: function() {
+ events() {
return [{
- 'click .js-select-visibility': function() {
+ 'click .js-select-visibility'() {
this.setVisibility(this.currentData());
},
'click .js-change-visibility': this.toogleVisibilityMenu,
- submit: this.onSubmit
+ submit: this.onSubmit,
}];
- }
+ },
}).register('createBoardPopup');
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'boardChangeVisibilityPopup';
},
- visibilityCheck: function() {
- var currentBoard = Boards.findOne(Session.get('currentBoard'));
+ visibilityCheck() {
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
return this.currentData() === currentBoard.permission;
},
- selectBoardVisibility: function() {
+ selectBoardVisibility() {
Boards.update(Session.get('currentBoard'), {
$set: {
- permission: this.currentData()
- }
+ permission: this.currentData(),
+ },
});
Popup.close();
},
- events: function() {
+ events() {
return [{
- 'click .js-select-visibility': this.selectBoardVisibility
+ 'click .js-select-visibility': this.selectBoardVisibility,
}];
- }
+ },
}).register('boardChangeVisibilityPopup');
diff --git a/client/components/boards/boardsList.js b/client/components/boards/boardsList.js
index 2311e7d0..1a2d3c9a 100644
--- a/client/components/boards/boardsList.js
+++ b/client/components/boards/boardsList.js
@@ -1,30 +1,30 @@
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'boardList';
},
- boards: function() {
+ boards() {
return Boards.find({
archived: false,
- 'members.userId': Meteor.userId()
+ 'members.userId': Meteor.userId(),
}, {
- sort: ['title']
+ sort: ['title'],
});
},
- isStarred: function() {
- var user = Meteor.user();
+ isStarred() {
+ const user = Meteor.user();
return user && user.hasStarred(this.currentData()._id);
},
- events: function() {
+ events() {
return [{
'click .js-add-board': Popup.open('createBoard'),
- 'click .js-star-board': function(evt) {
- var boardId = this.currentData()._id;
+ 'click .js-star-board'(evt) {
+ const boardId = this.currentData()._id;
Meteor.user().toggleBoardStar(boardId);
evt.preventDefault();
- }
+ },
}];
- }
+ },
}).register('boardList');
diff --git a/client/components/cards/attachments.js b/client/components/cards/attachments.js
index 9e299cc0..ba56aa1a 100644
--- a/client/components/cards/attachments.js
+++ b/client/components/cards/attachments.js
@@ -1,32 +1,32 @@
Template.attachmentsGalery.events({
'click .js-add-attachment': Popup.open('cardAttachments'),
'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete',
- function() {
+ () => {
Attachments.remove(this._id);
Popup.close();
}
),
// If we let this event bubble, FlowRouter will handle it and empty the page
// content, see #101.
- 'click .js-download': function(event) {
+ 'click .js-download'(event) {
event.stopPropagation();
},
- 'click .js-open-viewer': function() {
+ 'click .js-open-viewer'() {
// XXX Not implemented!
},
- 'click .js-add-cover': function() {
+ 'click .js-add-cover'() {
Cards.update(this.cardId, { $set: { coverId: this._id } });
},
- 'click .js-remove-cover': function() {
+ 'click .js-remove-cover'() {
Cards.update(this.cardId, { $unset: { coverId: '' } });
- }
+ },
});
Template.cardAttachmentsPopup.events({
- 'change .js-attach-file': function(evt) {
- var card = this;
- FS.Utility.eachFile(evt, function(f) {
- var file = new FS.File(f);
+ 'change .js-attach-file'(evt) {
+ const card = this;
+ FS.Utility.eachFile(evt, (f) => {
+ const file = new FS.File(f);
file.boardId = card.boardId;
file.cardId = card._id;
@@ -34,8 +34,8 @@ Template.cardAttachmentsPopup.events({
Popup.close();
});
},
- 'click .js-computer-upload': function(evt, tpl) {
+ 'click .js-computer-upload'(evt, tpl) {
tpl.find('.js-attach-file').click();
evt.preventDefault();
- }
+ },
});
diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js
index aba7254a..69e0cfdd 100644
--- a/client/components/cards/cardDetails.js
+++ b/client/components/cards/cardDetails.js
@@ -1,39 +1,39 @@
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'cardDetails';
},
- mixins: function() {
+ mixins() {
return [Mixins.InfiniteScrolling, Mixins.PerfectScrollbar];
},
- calculateNextPeak: function() {
- var altitude = this.find('.js-card-details').scrollHeight;
+ calculateNextPeak() {
+ const altitude = this.find('.js-card-details').scrollHeight;
this.callFirstWith(this, 'setNextPeak', altitude);
},
- reachNextPeak: function() {
- var activitiesComponent = this.componentChildren('activities')[0];
+ reachNextPeak() {
+ const activitiesComponent = this.componentChildren('activities')[0];
activitiesComponent.loadNextPage();
},
- onCreated: function() {
+ onCreated() {
this.isLoaded = new ReactiveVar(false);
this.componentParent().showOverlay.set(true);
this.componentParent().mouseHasEnterCardDetails = false;
},
- scrollParentContainer: function() {
+ scrollParentContainer() {
const cardPanelWidth = 510;
- let bodyBoardComponent = this.componentParent();
+ const bodyBoardComponent = this.componentParent();
- let $cardContainer = bodyBoardComponent.$('.js-lists');
- let $cardView = this.$(this.firstNode());
- let cardContainerScroll = $cardContainer.scrollLeft();
- let cardContainerWidth = $cardContainer.width();
+ const $cardContainer = bodyBoardComponent.$('.js-lists');
+ const $cardView = this.$(this.firstNode());
+ const cardContainerScroll = $cardContainer.scrollLeft();
+ const cardContainerWidth = $cardContainer.width();
- let cardViewStart = $cardView.offset().left;
- let cardViewEnd = cardViewStart + cardPanelWidth;
+ const cardViewStart = $cardView.offset().left;
+ const cardViewEnd = cardViewStart + cardPanelWidth;
let offset = false;
if (cardViewStart < 0) {
@@ -47,53 +47,53 @@ BlazeComponent.extendComponent({
}
},
- onRendered: function() {
+ onRendered() {
this.scrollParentContainer();
},
- onDestroyed: function() {
+ onDestroyed() {
this.componentParent().showOverlay.set(false);
},
- updateCard: function(modifier) {
+ updateCard(modifier) {
Cards.update(this.data()._id, {
- $set: modifier
+ $set: modifier,
});
},
- events: function() {
- var events = {
- [CSSEvents.animationend + ' .js-card-details']: function() {
+ events() {
+ const events = {
+ [`${CSSEvents.animationend} .js-card-details`]() {
this.isLoaded.set(true);
- }
+ },
};
return [_.extend(events, {
- 'click .js-close-card-details': function() {
+ 'click .js-close-card-details'() {
Utils.goBoardId(this.data().boardId);
},
'click .js-open-card-details-menu': Popup.open('cardDetailsActions'),
- 'submit .js-card-description': function(evt) {
+ 'submit .js-card-description'(evt) {
evt.preventDefault();
- var description = this.currentComponent().getValue();
- this.updateCard({ description: description });
+ const description = this.currentComponent().getValue();
+ this.updateCard({ description });
},
- 'submit .js-card-details-title': function(evt) {
+ 'submit .js-card-details-title'(evt) {
evt.preventDefault();
- var title = this.currentComponent().getValue();
+ const title = this.currentComponent().getValue();
if ($.trim(title)) {
- this.updateCard({ title: title });
+ this.updateCard({ title });
}
},
'click .js-member': Popup.open('cardMember'),
'click .js-add-members': Popup.open('cardMembers'),
'click .js-add-labels': Popup.open('cardLabels'),
- 'mouseenter .js-card-details': function() {
+ 'mouseenter .js-card-details'() {
this.componentParent().showOverlay.set(true);
this.componentParent().mouseHasEnterCardDetails = true;
- }
+ },
})];
- }
+ },
}).register('cardDetails');
// We extends the normal InlinedForm component to support UnsavedEdits draft
@@ -103,12 +103,12 @@ BlazeComponent.extendComponent({
return {
fieldName: 'cardDescription',
docId: Session.get('currentCard'),
- }
+ };
}
close(isReset = false) {
- if (this.isOpen.get() && ! isReset) {
- let draft = $.trim(this.getValue());
+ if (this.isOpen.get() && !isReset) {
+ const draft = $.trim(this.getValue());
if (draft !== Cards.findOne(Session.get('currentCard')).description) {
UnsavedEdits.set(this._getUnsavedEditKey(), this.getValue());
}
@@ -136,45 +136,45 @@ Template.cardDetailsActionsPopup.events({
'click .js-attachments': Popup.open('cardAttachments'),
'click .js-move-card': Popup.open('moveCard'),
// 'click .js-copy': Popup.open(),
- 'click .js-archive': function(evt) {
+ 'click .js-archive'(evt) {
evt.preventDefault();
Cards.update(this._id, {
$set: {
- archived: true
- }
+ archived: true,
+ },
});
Popup.close();
},
- 'click .js-more': Popup.open('cardMore')
+ 'click .js-more': Popup.open('cardMore'),
});
Template.moveCardPopup.events({
- 'click .js-select-list': function() {
+ 'click .js-select-list'() {
// XXX We should *not* get the currentCard from the global state, but
// instead from a “component” state.
- var cardId = Session.get('currentCard');
- var newListId = this._id;
+ const cardId = Session.get('currentCard');
+ const newListId = this._id;
Cards.update(cardId, {
$set: {
- listId: newListId
- }
+ listId: newListId,
+ },
});
Popup.close();
- }
+ },
});
Template.cardMorePopup.events({
- 'click .js-delete': Popup.afterConfirm('cardDelete', function() {
+ 'click .js-delete': Popup.afterConfirm('cardDelete', () => {
Popup.close();
Cards.remove(this._id);
Utils.goBoardId(this.board()._id);
- })
+ }),
});
// Close the card details pane by pressing escape
EscapeActions.register('detailsPane',
- function() { Utils.goBoardId(Session.get('currentBoard')); },
- function() { return ! Session.equals('currentCard', null); }, {
- noClickEscapeOn: '.js-card-details,.board-sidebar,#header'
+ () => { Utils.goBoardId(Session.get('currentBoard')); },
+ () => { return !Session.equals('currentCard', null); }, {
+ noClickEscapeOn: '.js-card-details,.board-sidebar,#header',
}
);
diff --git a/client/components/cards/labels.js b/client/components/cards/labels.js
index 4e6ceb3a..2da3b80b 100644
--- a/client/components/cards/labels.js
+++ b/client/components/cards/labels.js
@@ -1,136 +1,136 @@
-
-var labelColors;
-Meteor.startup(function() {
+let labelColors;
+Meteor.startup(() => {
labelColors = Boards.simpleSchema()._schema['labels.$.color'].allowedValues;
});
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'formLabel';
},
- onCreated: function() {
+ onCreated() {
this.currentColor = new ReactiveVar(this.data().color);
},
- labels: function() {
- return _.map(labelColors, function(color) {
- return { color: color, name: '' };
+ labels() {
+ return _.map(labelColors, (color) => {
+ return { color, name: '' };
});
},
- isSelected: function(color) {
+ isSelected(color) {
return this.currentColor.get() === color;
},
- events: function() {
+ events() {
return [{
- 'click .js-palette-color': function() {
+ 'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
- }
+ },
}];
- }
+ },
}).register('formLabel');
Template.createLabelPopup.helpers({
// This is the default color for a new label. We search the first color that
// is not already used in the board (although it's not a problem if two
// labels have the same color).
- defaultColor: function() {
- var labels = Boards.findOne(Session.get('currentBoard')).labels;
- var usedColors = _.pluck(labels, 'color');
- var availableColors = _.difference(labelColors, usedColors);
+ defaultColor() {
+ const labels = Boards.findOne(Session.get('currentBoard')).labels;
+ const usedColors = _.pluck(labels, 'color');
+ const availableColors = _.difference(labelColors, usedColors);
return availableColors.length > 1 ? availableColors[0] : labelColors[0];
- }
+ },
});
Template.cardLabelsPopup.events({
- 'click .js-select-label': function(evt) {
- var cardId = Template.parentData(2).data._id;
- var labelId = this._id;
- var operation;
+ 'click .js-select-label'(evt) {
+ const cardId = Template.parentData(2).data._id;
+ const labelId = this._id;
+ let operation;
if (Cards.find({ _id: cardId, labelIds: labelId}).count() === 0)
operation = '$addToSet';
else
operation = '$pull';
- var query = {};
- query[operation] = {
- labelIds: labelId
- };
- Cards.update(cardId, query);
+ Cards.update(cardId, {
+ [operation]: {
+ labelIds: labelId,
+ },
+ });
evt.preventDefault();
},
'click .js-edit-label': Popup.open('editLabel'),
- 'click .js-add-label': Popup.open('createLabel')
+ 'click .js-add-label': Popup.open('createLabel'),
});
Template.formLabel.events({
- 'click .js-palette-color': function(evt) {
- var $this = $(evt.currentTarget);
+ 'click .js-palette-color'(evt) {
+ const $this = $(evt.currentTarget);
// hide selected ll colors
$('.js-palette-select').addClass('hide');
// show select color
$this.find('.js-palette-select').removeClass('hide');
- }
+ },
});
Template.createLabelPopup.events({
// Create the new label
- 'submit .create-label': function(evt, tpl) {
- var name = tpl.$('#labelName').val().trim();
- var boardId = Session.get('currentBoard');
- var color = Blaze.getData(tpl.find('.fa-check')).color;
+ 'submit .create-label'(evt, tpl) {
+ const name = tpl.$('#labelName').val().trim();
+ const boardId = Session.get('currentBoard');
+ const color = Blaze.getData(tpl.find('.fa-check')).color;
Boards.update(boardId, {
$push: {
labels: {
+ name,
+ color,
_id: Random.id(6),
- name: name,
- color: color
- }
- }
+ },
+ },
});
Popup.back();
evt.preventDefault();
- }
+ },
});
Template.editLabelPopup.events({
'click .js-delete-label': Popup.afterConfirm('deleteLabel', function() {
- var boardId = Session.get('currentBoard');
+ const boardId = Session.get('currentBoard');
Boards.update(boardId, {
$pull: {
labels: {
- _id: this._id
- }
- }
+ _id: this._id,
+ },
+ },
});
Popup.back(2);
}),
- 'submit .edit-label': function(evt, tpl) {
+ 'submit .edit-label'(evt, tpl) {
evt.preventDefault();
- var name = tpl.$('#labelName').val().trim();
- var boardId = Session.get('currentBoard');
- var getLabel = Utils.getLabelIndex(boardId, this._id);
- var color = Blaze.getData(tpl.find('.fa-check')).color;
+ const name = tpl.$('#labelName').val().trim();
+ const boardId = Session.get('currentBoard');
+ const getLabel = Utils.getLabelIndex(boardId, this._id);
+ const color = Blaze.getData(tpl.find('.fa-check')).color;
- var $set = {};
- $set[getLabel.key('name')] = name;
- $set[getLabel.key('color')] = color;
-
- Boards.update(boardId, { $set: $set });
+ Boards.update(boardId, {
+ $set: {
+ [getLabel.key('name')]: name,
+ [getLabel.key('color')]: color,
+ },
+ });
Popup.back();
- }
+ },
});
Template.cardLabelsPopup.helpers({
- isLabelSelected: function(cardId) {
+ isLabelSelected(cardId) {
return _.contains(Cards.findOne(cardId).labelIds, this._id);
- }
+ },
});
diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js
index 70751152..a98b5730 100644
--- a/client/components/cards/minicard.js
+++ b/client/components/cards/minicard.js
@@ -3,7 +3,7 @@
// });
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'minicard';
- }
+ },
}).register('minicard');
diff --git a/client/components/lists/list.js b/client/components/lists/list.js
index 3b602f43..1b54741c 100644
--- a/client/components/lists/list.js
+++ b/client/components/lists/list.js
@@ -1,14 +1,16 @@
+const { calculateIndex } = Utils;
+
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'list';
},
- // Proxies
- openForm: function(options) {
+ // Proxy
+ openForm(options) {
this.componentChildren('listBody')[0].openForm(options);
},
- onCreated: function() {
+ onCreated() {
this.newCardFormIsVisible = new ReactiveVar(true);
},
@@ -19,28 +21,27 @@ BlazeComponent.extendComponent({
// By calling asking the sortable library to cancel its move on the `stop`
// callback, we basically solve all issues related to reactive updates. A
// comment below provides further details.
- onRendered: function() {
- var self = this;
- if (! Meteor.user() || ! Meteor.user().isBoardMember())
+ onRendered() {
+ if (!Meteor.user() || !Meteor.user().isBoardMember())
return;
- var boardComponent = self.componentParent();
- var itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
- var $cards = self.$('.js-minicards');
+ const boardComponent = this.componentParent();
+ const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
+ const $cards = this.$('.js-minicards');
$cards.sortable({
connectWith: '.js-minicards',
tolerance: 'pointer',
appendTo: 'body',
- helper: function(evt, item) {
- var helper = item.clone();
+ helper(evt, item) {
+ const helper = item.clone();
if (MultiSelection.isActive()) {
- var andNOthers = $cards.find('.js-minicard.is-checked').length - 1;
+ const andNOthers = $cards.find('.js-minicard.is-checked').length - 1;
if (andNOthers > 0) {
helper.append($(Blaze.toHTML(HTML.DIV(
// XXX Super bad class name
{'class': 'and-n-other'},
// XXX Need to translate
- 'and ' + andNOthers + ' other cards.'
+ `and ${andNOthers} other cards.`
))));
}
}
@@ -50,19 +51,19 @@ BlazeComponent.extendComponent({
items: itemsSelector,
scroll: false,
placeholder: 'minicard-wrapper placeholder',
- start: function(evt, ui) {
+ start(evt, ui) {
ui.placeholder.height(ui.helper.height());
EscapeActions.executeUpTo('popup');
boardComponent.setIsDragging(true);
},
- stop: function(evt, ui) {
+ stop(evt, ui) {
// To attribute the new index number, we need to get the DOM element
// of the previous and the following card -- if any.
- var prevCardDom = ui.item.prev('.js-minicard').get(0);
- var nextCardDom = ui.item.next('.js-minicard').get(0);
- var nCards = MultiSelection.isActive() ? MultiSelection.count() : 1;
- var sortIndex = Utils.calculateIndex(prevCardDom, nextCardDom, nCards);
- var listId = Blaze.getData(ui.item.parents('.list').get(0))._id;
+ const prevCardDom = ui.item.prev('.js-minicard').get(0);
+ const nextCardDom = ui.item.next('.js-minicard').get(0);
+ const nCards = MultiSelection.isActive() ? MultiSelection.count() : 1;
+ const sortIndex = calculateIndex(prevCardDom, nextCardDom, nCards);
+ const listId = Blaze.getData(ui.item.parents('.list').get(0))._id;
// Normally the jquery-ui sortable library moves the dragged DOM element
// to its new position, which disrupts Blaze reactive updates mechanism
@@ -74,53 +75,53 @@ BlazeComponent.extendComponent({
$cards.sortable('cancel');
if (MultiSelection.isActive()) {
- Cards.find(MultiSelection.getMongoSelector()).forEach(function(c, i) {
+ Cards.find(MultiSelection.getMongoSelector()).forEach((c, i) => {
Cards.update(c._id, {
$set: {
- listId: listId,
- sort: sortIndex.base + i * sortIndex.increment
- }
+ listId,
+ sort: sortIndex.base + i * sortIndex.increment,
+ },
});
});
} else {
- var cardDomElement = ui.item.get(0);
- var cardId = Blaze.getData(cardDomElement)._id;
+ const cardDomElement = ui.item.get(0);
+ const cardId = Blaze.getData(cardDomElement)._id;
Cards.update(cardId, {
$set: {
- listId: listId,
- sort: sortIndex.base
- }
+ listId,
+ sort: sortIndex.base,
+ },
});
}
boardComponent.setIsDragging(false);
- }
+ },
});
// We want to re-run this function any time a card is added.
- self.autorun(function() {
- var currentBoardId = Tracker.nonreactive(function() {
+ this.autorun(() => {
+ const currentBoardId = Tracker.nonreactive(() => {
return Session.get('currentBoard');
});
Cards.find({ boardId: currentBoardId }).fetch();
- Tracker.afterFlush(function() {
+ Tracker.afterFlush(() => {
$cards.find(itemsSelector).droppable({
hoverClass: 'draggable-hover-card',
accept: '.js-member,.js-label',
- drop: function(event, ui) {
- var cardId = Blaze.getData(this)._id;
- var addToSet;
+ drop(event, ui) {
+ const cardId = Blaze.getData(this)._id;
+ let addToSet;
if (ui.draggable.hasClass('js-member')) {
- var memberId = Blaze.getData(ui.draggable.get(0)).userId;
+ const memberId = Blaze.getData(ui.draggable.get(0)).userId;
addToSet = { members: memberId };
} else {
- var labelId = Blaze.getData(ui.draggable.get(0))._id;
+ const labelId = Blaze.getData(ui.draggable.get(0))._id;
addToSet = { labelIds: labelId };
}
Cards.update(cardId, { $addToSet: addToSet });
- }
+ },
});
});
});
- }
+ },
}).register('list');
diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js
index 2b561ae3..cc8c94cc 100644
--- a/client/components/lists/listBody.js
+++ b/client/components/lists/listBody.js
@@ -1,46 +1,46 @@
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'listBody';
},
- mixins: function() {
+ mixins() {
return [Mixins.PerfectScrollbar];
},
- openForm: function(options) {
+ openForm(options) {
options = options || {};
options.position = options.position || 'top';
- var forms = this.componentChildren('inlinedForm');
- var form = _.find(forms, function(component) {
+ const forms = this.componentChildren('inlinedForm');
+ let form = _.find(forms, (component) => {
return component.data().position === options.position;
});
- if (! form && forms.length > 0) {
+ if (!form && forms.length > 0) {
form = forms[0];
}
form.open();
},
- addCard: function(evt) {
+ addCard(evt) {
evt.preventDefault();
- var textarea = $(evt.currentTarget).find('textarea');
- var title = textarea.val();
- var position = Blaze.getData(evt.currentTarget).position;
- var sortIndex;
- var firstCard = this.find('.js-minicard:first');
- var lastCard = this.find('.js-minicard:last');
+ const firstCardDom = this.find('.js-minicard:first');
+ const lastCardDom = this.find('.js-minicard:last');
+ const textarea = $(evt.currentTarget).find('textarea');
+ const title = textarea.val();
+ const position = Blaze.getData(evt.currentTarget).position;
+ let sortIndex;
if (position === 'top') {
- sortIndex = Utils.calculateIndex(null, firstCard).base;
+ sortIndex = Utils.calculateIndex(null, firstCardDom).base;
} else if (position === 'bottom') {
- sortIndex = Utils.calculateIndex(lastCard, null).base;
+ sortIndex = Utils.calculateIndex(lastCardDom, null).base;
}
if ($.trim(title)) {
- var _id = Cards.insert({
- title: title,
+ const _id = Cards.insert({
+ title,
listId: this.data()._id,
boardId: this.data().board()._id,
- sort: sortIndex
+ sort: sortIndex,
});
// In case the filter is active we need to add the newly inserted card in
// the list of exceptions -- cards that are not filtered. Otherwise the
@@ -56,18 +56,18 @@ BlazeComponent.extendComponent({
}
},
- scrollToBottom: function() {
- var container = this.firstNode();
+ scrollToBottom() {
+ const container = this.firstNode();
$(container).animate({
- scrollTop: container.scrollHeight
+ scrollTop: container.scrollHeight,
});
},
- clickOnMiniCard: function(evt) {
+ clickOnMiniCard(evt) {
if (MultiSelection.isActive() || evt.shiftKey) {
evt.stopImmediatePropagation();
evt.preventDefault();
- var methodName = evt.shiftKey ? 'toogleRange' : 'toogle';
+ const methodName = evt.shiftKey ? 'toogleRange' : 'toogle';
MultiSelection[methodName](this.currentData()._id);
// If the card is already selected, we want to de-select it.
@@ -80,36 +80,36 @@ BlazeComponent.extendComponent({
}
},
- cardIsSelected: function() {
+ cardIsSelected() {
return Session.equals('currentCard', this.currentData()._id);
},
- toggleMultiSelection: function(evt) {
+ toggleMultiSelection(evt) {
evt.stopPropagation();
evt.preventDefault();
MultiSelection.toogle(this.currentData()._id);
},
- events: function() {
+ events() {
return [{
'click .js-minicard': this.clickOnMiniCard,
'click .js-toggle-multi-selection': this.toggleMultiSelection,
'click .open-minicard-composer': this.scrollToBottom,
- submit: this.addCard
+ submit: this.addCard,
}];
- }
+ },
}).register('listBody');
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'addCardForm';
},
- pressKey: function(evt) {
+ pressKey(evt) {
// Pressing Enter should submit the card
if (evt.keyCode === 13) {
evt.preventDefault();
- var $form = $(evt.currentTarget).closest('form');
+ const $form = $(evt.currentTarget).closest('form');
// XXX For some reason $form.submit() does not work (it's probably a bug
// of blaze-component related to the fact that the submit event is non-
// bubbling). This is why we click on the submit button instead -- which
@@ -120,24 +120,24 @@ BlazeComponent.extendComponent({
// in the reverse order
} else if (evt.keyCode === 9) {
evt.preventDefault();
- var isReverse = evt.shiftKey;
- var list = $('#js-list-' + this.data().listId);
- var listSelector = '.js-list:not(.js-list-composer)';
- var nextList = list[isReverse ? 'prev' : 'next'](listSelector).get(0);
+ const isReverse = evt.shiftKey;
+ const list = $(`#js-list-${this.data().listId}`);
+ const listSelector = '.js-list:not(.js-list-composer)';
+ let nextList = list[isReverse ? 'prev' : 'next'](listSelector).get(0);
// If there is no next list, loop back to the beginning.
- if (! nextList) {
+ if (!nextList) {
nextList = $(listSelector + (isReverse ? ':last' : ':first')).get(0);
}
BlazeComponent.getComponentForElement(nextList).openForm({
- position:this.data().position
+ position:this.data().position,
});
}
},
- events: function() {
+ events() {
return [{
- keydown: this.pressKey
+ keydown: this.pressKey,
}];
- }
+ },
}).register('addCardForm');
diff --git a/client/components/lists/listHeader.js b/client/components/lists/listHeader.js
index cd4df276..9431b461 100644
--- a/client/components/lists/listHeader.js
+++ b/client/components/lists/listHeader.js
@@ -1,78 +1,78 @@
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'listHeader';
},
- editTitle: function(evt) {
+ editTitle(evt) {
evt.preventDefault();
- var form = this.componentChildren('inlinedForm')[0];
- var newTitle = form.getValue();
+ const form = this.componentChildren('inlinedForm')[0];
+ const newTitle = form.getValue();
if ($.trim(newTitle)) {
Lists.update(this.currentData()._id, {
$set: {
- title: newTitle
- }
+ title: newTitle,
+ },
});
}
},
- events: function() {
+ events() {
return [{
'click .js-open-list-menu': Popup.open('listAction'),
- submit: this.editTitle
+ submit: this.editTitle,
}];
- }
+ },
}).register('listHeader');
Template.listActionPopup.events({
- 'click .js-add-card': function() {
- var listDom = document.getElementById('js-list-' + this._id);
- var listComponent = BlazeComponent.getComponentForElement(listDom);
+ 'click .js-add-card'() {
+ const listDom = document.getElementById(`js-list-${this._id}`);
+ const listComponent = BlazeComponent.getComponentForElement(listDom);
listComponent.openForm({ position: 'top' });
Popup.close();
},
- 'click .js-list-subscribe': function() {},
- 'click .js-select-cards': function() {
- var cardIds = Cards.find(
+ 'click .js-list-subscribe'() {},
+ 'click .js-select-cards'() {
+ const cardIds = Cards.find(
{listId: this._id},
{fields: { _id: 1 }}
- ).map(function(card) { return card._id; });
+ ).map((card) => card._id);
MultiSelection.add(cardIds);
Popup.close();
},
'click .js-move-cards': Popup.open('listMoveCards'),
- 'click .js-archive-cards': Popup.afterConfirm('listArchiveCards', function() {
- Cards.find({listId: this._id}).forEach(function(card) {
+ 'click .js-archive-cards': Popup.afterConfirm('listArchiveCards', () => {
+ Cards.find({listId: this._id}).forEach((card) => {
Cards.update(card._id, {
$set: {
- archived: true
- }
+ archived: true,
+ },
});
});
Popup.close();
}),
- 'click .js-close-list': function(evt) {
+ 'click .js-close-list'(evt) {
evt.preventDefault();
Lists.update(this._id, {
$set: {
- archived: true
- }
+ archived: true,
+ },
});
Popup.close();
- }
+ },
});
Template.listMoveCardsPopup.events({
- 'click .js-select-list': function() {
- var fromList = Template.parentData(2).data._id;
- var toList = this._id;
- Cards.find({listId: fromList}).forEach(function(card) {
+ 'click .js-select-list'() {
+ const fromList = Template.parentData(2).data._id;
+ const toList = this._id;
+ Cards.find({ listId: fromList }).forEach((card) => {
Cards.update(card._id, {
$set: {
- listId: toList
- }
+ listId: toList,
+ },
});
});
Popup.close();
- }
+ },
});
diff --git a/client/components/main/editor.js b/client/components/main/editor.js
index 7966ff60..c34539b3 100644
--- a/client/components/main/editor.js
+++ b/client/components/main/editor.js
@@ -1,7 +1,7 @@
-var dropdownMenuIsOpened = false;
+let dropdownMenuIsOpened = false;
-Template.editor.onRendered(function() {
- var $textarea = this.$('textarea');
+Template.editor.onRendered(() => {
+ const $textarea = this.$('textarea');
autosize($textarea);
@@ -9,39 +9,40 @@ Template.editor.onRendered(function() {
// Emojies
{
match: /\B:([\-+\w]*)$/,
- search: function(term, callback) {
- callback($.map(Emoji.values, function(emoji) {
+ search(term, callback) {
+ callback($.map(Emoji.values, (emoji) => {
return emoji.indexOf(term) === 0 ? emoji : null;
}));
},
- template: function(value) {
- var image = '<img src="' + Emoji.baseImagePath + value + '.png"></img>';
+ template(value) {
+ const imgSrc = Emoji.baseImagePath + value;
+ const image = `<img src="${imgSrc}.png" />`;
return image + value;
},
- replace: function(value) {
- return ':' + value + ':';
+ replace(value) {
+ return `:${value}:`;
},
- index: 1
+ index: 1,
},
// User mentions
{
match: /\B@(\w*)$/,
- search: function(term, callback) {
- var currentBoard = Boards.findOne(Session.get('currentBoard'));
- callback($.map(currentBoard.members, function(member) {
- var username = Users.findOne(member.userId).username;
+ search(term, callback) {
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ callback($.map(currentBoard.members, (member) => {
+ const username = Users.findOne(member.userId).username;
return username.indexOf(term) === 0 ? username : null;
}));
},
- template: function(value) {
+ template(value) {
return value;
},
- replace: function(username) {
- return '@' + username + ' ';
+ replace(username) {
+ return `@${username} `;
},
- index: 1
- }
+ index: 1,
+ },
]);
// Since commit d474017 jquery-textComplete automatically closes a potential
@@ -51,27 +52,27 @@ Template.editor.onRendered(function() {
// 'open' and 'hide' events, and create a ghost escapeAction when the dropdown
// is opened (and rely on textComplete to execute the actual action).
$textarea.on({
- 'textComplete:show': function() {
+ 'textComplete:show'() {
dropdownMenuIsOpened = true;
},
- 'textComplete:hide': function() {
- Tracker.afterFlush(function() {
+ 'textComplete:hide'() {
+ Tracker.afterFlush(() => {
dropdownMenuIsOpened = false;
});
- }
+ },
});
});
EscapeActions.register('textcomplete',
- function() {},
- function() { return dropdownMenuIsOpened; }
+ () => {},
+ () => dropdownMenuIsOpened
);
Template.viewer.events({
// Viewer sometimes have click-able wrapper around them (for instance to edit
// the corresponding text). Clicking a link shouldn't fire these actions, stop
// we stop these event at the viewer component level.
- 'click a': function(evt) {
+ 'click a'(evt) {
evt.stopPropagation();
// XXX We hijack the build-in browser action because we currently don't have
@@ -79,7 +80,7 @@ Template.viewer.events({
// handled by a third party package that we can't configure easily. Fix that
// by using directly `_blank` attribute in the rendered HTML.
evt.preventDefault();
- let href = evt.currentTarget.href;
+ const href = evt.currentTarget.href;
window.open(href, '_blank');
- }
+ },
});
diff --git a/client/components/main/header.js b/client/components/main/header.js
index 7b7e431f..30cb2d8f 100644
--- a/client/components/main/header.js
+++ b/client/components/main/header.js
@@ -1,14 +1,14 @@
Template.header.helpers({
// Reactively set the color of the page from the color of the current board.
- headerTemplate: function() {
+ headerTemplate() {
return 'headerBoard';
},
- wrappedHeader: function() {
- return ! Session.get('currentBoard');
- }
+ wrappedHeader() {
+ return !Session.get('currentBoard');
+ },
});
Template.header.events({
- 'click .js-create-board': Popup.open('createBoard')
+ 'click .js-create-board': Popup.open('createBoard'),
});
diff --git a/client/components/main/helpers.js b/client/components/main/helpers.js
deleted file mode 100644
index 91205351..00000000
--- a/client/components/main/helpers.js
+++ /dev/null
@@ -1,65 +0,0 @@
-var Helpers = {
- error: function() {
- return Session.get('error');
- },
-
- toLowerCase: function(text) {
- return text && text.toLowerCase();
- },
-
- toUpperCase: function(text) {
- return text && text.toUpperCase();
- },
-
- firstChar: function(text) {
- return text && text[0].toUpperCase();
- },
-
- session: function(prop) {
- return Session.get(prop);
- },
-
- getUser: function(userId) {
- return Users.findOne(userId);
- }
-};
-
-// Register all Helpers
-_.each(Helpers, function(fn, name) { Blaze.registerHelper(name, fn); });
-
-// XXX I believe we should compute a HTML rendered field on the server that
-// would handle markdown, emojies and user mentions. We can simply have two
-// fields, one source, and one compiled version (in HTML) and send only the
-// compiled version to most users -- who don't need to edit.
-// In the meantime, all the transformation are done on the client using the
-// Blaze API.
-var at = HTML.CharRef({html: '&commat;', str: '@'});
-Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
- var view = this;
- var content = Blaze.toHTML(view.templateContentBlock);
- var currentBoard = Session.get('currentBoard');
- var knowedUsers = _.map(currentBoard.members, function(member) {
- member.username = Users.findOne(member.userId).username;
- return member;
- });
-
- var mentionRegex = /\B@(\w*)/gi;
- var currentMention, knowedUser, href, linkClass, linkValue, link;
- while (!! (currentMention = mentionRegex.exec(content))) {
-
- knowedUser = _.findWhere(knowedUsers, { username: currentMention[1] });
- if (! knowedUser)
- continue;
-
- linkValue = [' ', at, knowedUser.username];
- href = Router.url('Profile', { username: knowedUser.username });
- linkClass = 'atMention';
- if (knowedUser.userId === Meteor.userId())
- linkClass += ' me';
- link = HTML.A({ href: href, 'class': linkClass }, linkValue);
-
- content = content.replace(currentMention[0], Blaze.toHTML(link));
- }
-
- return HTML.Raw(content);
-}));
diff --git a/client/components/main/layouts.js b/client/components/main/layouts.js
index 11a43313..ab62e76a 100644
--- a/client/components/main/layouts.js
+++ b/client/components/main/layouts.js
@@ -1,13 +1,13 @@
-Meteor.subscribe('boards')
+Meteor.subscribe('boards');
-BlazeLayout.setRoot('body')
+BlazeLayout.setRoot('body');
-Template.userFormsLayout.onRendered(function() {
- EscapeActions.executeAll()
-})
+Template.userFormsLayout.onRendered(() => {
+ EscapeActions.executeAll();
+});
Template.defaultLayout.events({
'click .js-close-modal': () => {
- Modal.close()
- }
-})
+ Modal.close();
+ },
+});
diff --git a/client/components/main/popup.js b/client/components/main/popup.js
index 5fc4e979..ba20a6d3 100644
--- a/client/components/main/popup.js
+++ b/client/components/main/popup.js
@@ -1,11 +1,11 @@
Popup.template.events({
- 'click .js-back-view': function() {
+ 'click .js-back-view'() {
Popup.back();
},
- 'click .js-close-pop-over': function() {
+ 'click .js-close-pop-over'() {
Popup.close();
},
- 'click .js-confirm': function() {
+ 'click .js-confirm'() {
this.__afterConfirmAction.call(this);
},
// This handler intends to solve a pretty tricky bug with our popup
@@ -18,22 +18,22 @@ Popup.template.events({
// in moving the whole popup container outside of the popup wrapper. To
// disable this behavior we have to manually reset the scrollLeft position
// whenever it is modified.
- 'scroll .content-wrapper': function(evt) {
+ 'scroll .content-wrapper'(evt) {
evt.currentTarget.scrollLeft = 0;
- }
+ },
});
// When a popup content is removed (ie, when the user press the "back" button),
// we need to wait for the container translation to end before removing the
// actual DOM element. For that purpose we use the undocumented `_uihooks` API.
-Popup.template.onRendered(function() {
- var container = this.find('.content-container');
+Popup.template.onRendered(() => {
+ const container = this.find('.content-container');
container._uihooks = {
- removeElement: function(node) {
+ removeElement(node) {
$(node).addClass('no-height');
- $(container).one(CSSEvents.transitionend, function() {
+ $(container).one(CSSEvents.transitionend, () => {
node.parentNode.removeChild(node);
});
- }
+ },
};
});
diff --git a/client/components/mixins/infiniteScrolling.js b/client/components/mixins/infiniteScrolling.js
index df3b8901..0afb33f9 100644
--- a/client/components/mixins/infiniteScrolling.js
+++ b/client/components/mixins/infiniteScrolling.js
@@ -1,37 +1,37 @@
-var peakAnticipation = 200;
+const peakAnticipation = 200;
Mixins.InfiniteScrolling = BlazeComponent.extendComponent({
- onCreated: function() {
+ onCreated() {
this._nextPeak = Infinity;
},
- setNextPeak: function(v) {
+ setNextPeak(v) {
this._nextPeak = v;
},
- getNextPeak: function() {
+ getNextPeak() {
return this._nextPeak;
},
- resetNextPeak: function() {
+ resetNextPeak() {
this._nextPeak = Infinity;
},
// To be overwritten by consumers of this mixin
- reachNextPeak: function() {
+ reachNextPeak() {
},
- events: function() {
+ events() {
return [{
- scroll: function(evt) {
- var domElement = evt.currentTarget;
- var altitude = domElement.scrollTop + domElement.offsetHeight;
+ scroll(evt) {
+ const domElement = evt.currentTarget;
+ let altitude = domElement.scrollTop + domElement.offsetHeight;
altitude += peakAnticipation;
if (altitude >= this.callFirstWith(null, 'getNextPeak')) {
this.callFirstWith(null, 'reachNextPeak');
}
- }
+ },
}];
- }
+ },
});
diff --git a/client/components/mixins/perfectScrollbar.js b/client/components/mixins/perfectScrollbar.js
index 510a4563..f652f043 100644
--- a/client/components/mixins/perfectScrollbar.js
+++ b/client/components/mixins/perfectScrollbar.js
@@ -1,14 +1,12 @@
Mixins.PerfectScrollbar = BlazeComponent.extendComponent({
- onRendered: function() {
- var component = this.mixinParent();
- var domElement = component.find('.js-perfect-scrollbar');
+ onRendered() {
+ const component = this.mixinParent();
+ const domElement = component.find('.js-perfect-scrollbar');
Ps.initialize(domElement);
// XXX We should create an event map to be consistent with other components
// but since BlazeComponent doesn't merge Mixins events transparently I
// prefered to use a jQuery event (which is what an event map ends up doing)
- component.$(domElement).on('mouseenter', function() {
- Ps.update(domElement);
- });
- }
+ component.$(domElement).on('mouseenter', () => Ps.update(domElement));
+ },
});
diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js
index 97b6f2de..51f3e0e4 100644
--- a/client/components/sidebar/sidebar.js
+++ b/client/components/sidebar/sidebar.js
@@ -1,76 +1,76 @@
Sidebar = null;
-var defaultView = 'home';
+const defaultView = 'home';
-var viewTitles = {
+const viewTitles = {
filter: 'filter-cards',
multiselection: 'multi-selection',
- archives: 'archives'
+ archives: 'archives',
};
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'sidebar';
},
- mixins: function() {
+ mixins() {
return [Mixins.InfiniteScrolling, Mixins.PerfectScrollbar];
},
- onCreated: function() {
- this._isOpen = new ReactiveVar(! Session.get('currentCard'));
+ onCreated() {
+ this._isOpen = new ReactiveVar(!Session.get('currentCard'));
this._view = new ReactiveVar(defaultView);
Sidebar = this;
},
- onDestroyed: function() {
+ onDestroyed() {
Sidebar = null;
},
- isOpen: function() {
+ isOpen() {
return this._isOpen.get();
},
- open: function() {
- if (! this._isOpen.get()) {
+ open() {
+ if (!this._isOpen.get()) {
this._isOpen.set(true);
EscapeActions.executeUpTo('detailsPane');
}
},
- hide: function() {
+ hide() {
if (this._isOpen.get()) {
this._isOpen.set(false);
}
},
- toogle: function() {
- this._isOpen.set(! this._isOpen.get());
+ toogle() {
+ this._isOpen.set(!this._isOpen.get());
},
- calculateNextPeak: function() {
- var altitude = this.find('.js-board-sidebar-content').scrollHeight;
+ calculateNextPeak() {
+ const altitude = this.find('.js-board-sidebar-content').scrollHeight;
this.callFirstWith(this, 'setNextPeak', altitude);
},
- reachNextPeak: function() {
- var activitiesComponent = this.componentChildren('activities')[0];
+ reachNextPeak() {
+ const activitiesComponent = this.componentChildren('activities')[0];
activitiesComponent.loadNextPage();
},
- isTongueHidden: function() {
+ isTongueHidden() {
return this.isOpen() && this.getView() !== defaultView;
},
- scrollTop: function() {
+ scrollTop() {
this.$('.js-board-sidebar-content').scrollTop(0);
},
- getView: function() {
+ getView() {
return this._view.get();
},
- setView: function(view) {
+ setView(view) {
view = _.isString(view) ? view : defaultView;
if (this._view.get() !== view) {
this._view.set(view);
@@ -80,83 +80,84 @@ BlazeComponent.extendComponent({
this.open();
},
- isDefaultView: function() {
+ isDefaultView() {
return this.getView() === defaultView;
},
- getViewTemplate: function() {
- return this.getView() + 'Sidebar';
+ getViewTemplate() {
+ return `${this.getView()}Sidebar`;
},
- getViewTitle: function() {
+ getViewTitle() {
return TAPi18n.__(viewTitles[this.getView()]);
},
- events: function() {
+ events() {
// XXX Hacky, we need some kind of `super`
- var mixinEvents = this.getMixin(Mixins.InfiniteScrolling).events();
+ const mixinEvents = this.getMixin(Mixins.InfiniteScrolling).events();
return mixinEvents.concat([{
'click .js-toogle-sidebar': this.toogle,
- 'click .js-back-home': this.setView
+ 'click .js-back-home': this.setView,
}]);
- }
+ },
}).register('sidebar');
-Blaze.registerHelper('Sidebar', function() {
- return Sidebar;
-});
+Blaze.registerHelper('Sidebar', () => Sidebar);
EscapeActions.register('sidebarView',
- function() { Sidebar.setView(defaultView); },
- function() { return Sidebar && Sidebar.getView() !== defaultView; }
+ () => { Sidebar.setView(defaultView); },
+ () => { return Sidebar && Sidebar.getView() !== defaultView; }
);
-var getMemberIndex = function(board, searchId) {
- for (var i = 0; i < board.members.length; i++) {
+function getMemberIndex(board, searchId) {
+ for (let i = 0; i < board.members.length; i++) {
if (board.members[i].userId === searchId)
return i;
}
throw new Meteor.Error('Member not found');
-};
+}
Template.memberPopup.helpers({
- user: function() {
+ user() {
return Users.findOne(this.userId);
},
- memberType: function() {
- var type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal';
+ memberType() {
+ const type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal';
return TAPi18n.__(type).toLowerCase();
- }
+ },
});
Template.memberPopup.events({
- 'click .js-filter-member': function() {
+ 'click .js-filter-member'() {
Filter.members.toogle(this.userId);
Popup.close();
},
'click .js-change-role': Popup.open('changePermissions'),
'click .js-remove-member': Popup.afterConfirm('removeMember', function() {
- var currentBoard = Boards.findOne(Session.get('currentBoard'));
- var memberIndex = getMemberIndex(currentBoard, this.userId);
- var setQuery = {};
- setQuery[['members', memberIndex, 'isActive'].join('.')] = false;
- Boards.update(currentBoard._id, { $set: setQuery });
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ const memberIndex = getMemberIndex(currentBoard, this.userId);
+
+ Boards.update(currentBoard._id, {
+ $set: {
+ [`members.${memberIndex}.isActive`]: false,
+ },
+ });
Popup.close();
}),
- 'click .js-leave-member': function() {
+ 'click .js-leave-member'() {
// XXX Not implemented
Popup.close();
- }
+ },
});
Template.membersWidget.events({
'click .js-member': Popup.open('member'),
- 'click .js-manage-board-members': Popup.open('addMember')
+ 'click .js-manage-board-members': Popup.open('addMember'),
});
Template.labelsWidget.events({
'click .js-label': Popup.open('editLabel'),
- 'click .js-add-label': Popup.open('createLabel')
+ 'click .js-add-label': Popup.open('createLabel'),
});
// Board members can assign people or labels by drag-dropping elements from the
@@ -164,99 +165,102 @@ Template.labelsWidget.events({
// plugin any time a draggable member or label is modified or removed we use a
// autorun function and register a dependency on the both members and labels
// fields of the current board document.
-var draggableMembersLabelsWidgets = function() {
- var self = this;
- if (! Meteor.user() || ! Meteor.user().isBoardMember())
+function draggableMembersLabelsWidgets() {
+ if (!Meteor.user() || !Meteor.user().isBoardMember())
return;
- self.autorun(function() {
- var currentBoardId = Tracker.nonreactive(function() {
+ this.autorun(() => {
+ const currentBoardId = Tracker.nonreactive(() => {
return Session.get('currentBoard');
});
Boards.findOne(currentBoardId, {
fields: {
members: 1,
- labels: 1
- }
+ labels: 1,
+ },
});
- Tracker.afterFlush(function() {
- self.$('.js-member,.js-label').draggable({
+ Tracker.afterFlush(() => {
+ this.$('.js-member,.js-label').draggable({
appendTo: 'body',
helper: 'clone',
revert: 'invalid',
revertDuration: 150,
snap: false,
snapMode: 'both',
- start: function() {
+ start() {
EscapeActions.executeUpTo('popup-back');
- }
+ },
});
});
});
-};
+}
Template.membersWidget.onRendered(draggableMembersLabelsWidgets);
Template.labelsWidget.onRendered(draggableMembersLabelsWidgets);
Template.addMemberPopup.helpers({
- isBoardMember: function() {
- var user = Users.findOne(this._id);
+ isBoardMember() {
+ const user = Users.findOne(this._id);
return user && user.isBoardMember();
- }
+ },
});
Template.addMemberPopup.events({
- 'click .pop-over-member-list li:not(.disabled)': function() {
- var userId = this._id;
- var currentBoard = Boards.findOne(Session.get('currentBoard'));
- var currentMembersIds = _.pluck(currentBoard.members, 'userId');
+ 'click .pop-over-member-list li:not(.disabled)'() {
+ const userId = this._id;
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ const currentMembersIds = _.pluck(currentBoard.members, 'userId');
if (currentMembersIds.indexOf(userId) === -1) {
Boards.update(currentBoard._id, {
$push: {
members: {
- userId: userId,
+ userId,
isAdmin: false,
- isActive: true
- }
- }
+ isActive: true,
+ },
+ },
});
} else {
- var memberIndex = getMemberIndex(currentBoard, userId);
- var setQuery = {};
- setQuery[['members', memberIndex, 'isActive'].join('.')] = true;
- Boards.update(currentBoard._id, { $set: setQuery });
+ const memberIndex = getMemberIndex(currentBoard, userId);
+
+ Boards.update(currentBoard._id, {
+ $set: {
+ [`members.${memberIndex}.isActive`]: true,
+ },
+ });
}
Popup.close();
- }
+ },
});
-Template.addMemberPopup.onRendered(function() {
+Template.addMemberPopup.onRendered(() => {
this.find('.js-search-member input').focus();
});
Template.changePermissionsPopup.events({
- 'click .js-set-admin, click .js-set-normal': function(event) {
- var currentBoard = Boards.findOne(Session.get('currentBoard'));
- var memberIndex = getMemberIndex(currentBoard, this.user._id);
- var isAdmin = $(event.currentTarget).hasClass('js-set-admin');
- var setQuery = {};
- setQuery[['members', memberIndex, 'isAdmin'].join('.')] = isAdmin;
+ 'click .js-set-admin, click .js-set-normal'(event) {
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ const memberIndex = getMemberIndex(currentBoard, this.user._id);
+ const isAdmin = $(event.currentTarget).hasClass('js-set-admin');
+
Boards.update(currentBoard._id, {
- $set: setQuery
+ $set: {
+ [`members.${memberIndex}.isAdmin`]: isAdmin,
+ },
});
Popup.back(1);
- }
+ },
});
Template.changePermissionsPopup.helpers({
- isAdmin: function() {
+ isAdmin() {
return this.user.isBoardAdmin();
},
- isLastAdmin: function() {
- if (! this.user.isBoardAdmin())
+ isLastAdmin() {
+ if (!this.user.isBoardAdmin())
return false;
- var currentBoard = Boards.findOne(Session.get('currentBoard'));
- var nbAdmins = _.where(currentBoard.members, { isAdmin: true }).length;
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ const nbAdmins = _.where(currentBoard.members, { isAdmin: true }).length;
return nbAdmins === 1;
- }
+ },
});
diff --git a/client/components/sidebar/sidebarArchives.js b/client/components/sidebar/sidebarArchives.js
index 4e44f3f4..f2597c3c 100644
--- a/client/components/sidebar/sidebarArchives.js
+++ b/client/components/sidebar/sidebarArchives.js
@@ -1,46 +1,46 @@
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'archivesSidebar';
},
- tabs: function() {
+ tabs() {
return [
{ name: TAPi18n.__('cards'), slug: 'cards' },
- { name: TAPi18n.__('lists'), slug: 'lists' }
- ]
+ { name: TAPi18n.__('lists'), slug: 'lists' },
+ ];
},
- archivedCards: function() {
+ archivedCards() {
return Cards.find({ archived: true });
},
- archivedLists: function() {
+ archivedLists() {
return Lists.find({ archived: true });
},
- cardIsInArchivedList: function() {
+ cardIsInArchivedList() {
return this.currentData().list().archived;
},
- onRendered: function() {
- //XXX We should support dragging a card from the sidebar to the board
+ onRendered() {
+ // XXX We should support dragging a card from the sidebar to the board
},
- events: function() {
+ events() {
return [{
- 'click .js-restore-card': function() {
- var cardId = this.currentData()._id;
+ 'click .js-restore-card'() {
+ const cardId = this.currentData()._id;
Cards.update(cardId, {$set: {archived: false}});
},
'click .js-delete-card': Popup.afterConfirm('cardDelete', function() {
- var cardId = this._id;
+ const cardId = this._id;
Cards.remove(cardId);
Popup.close();
}),
- 'click .js-restore-list': function() {
- var listId = this.currentData()._id;
+ 'click .js-restore-list'() {
+ const listId = this.currentData()._id;
Lists.update(listId, {$set: {archived: false}});
- }
+ },
}];
- }
+ },
}).register('archivesSidebar');
diff --git a/client/components/sidebar/sidebarFilters.js b/client/components/sidebar/sidebarFilters.js
index c7b28443..7fce7286 100644
--- a/client/components/sidebar/sidebarFilters.js
+++ b/client/components/sidebar/sidebarFilters.js
@@ -1,136 +1,136 @@
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'filterSidebar';
},
- events: function() {
+ events() {
return [{
- 'click .js-toggle-label-filter': function(evt) {
+ 'click .js-toggle-label-filter'(evt) {
evt.preventDefault();
Filter.labelIds.toogle(this.currentData()._id);
Filter.resetExceptions();
},
- 'click .js-toogle-member-filter': function(evt) {
+ 'click .js-toogle-member-filter'(evt) {
evt.preventDefault();
Filter.members.toogle(this.currentData()._id);
Filter.resetExceptions();
},
- 'click .js-clear-all': function(evt) {
+ 'click .js-clear-all'(evt) {
evt.preventDefault();
Filter.reset();
},
- 'click .js-filter-to-selection': function(evt) {
+ 'click .js-filter-to-selection'(evt) {
evt.preventDefault();
- var selectedCards = Cards.find(Filter.mongoSelector()).map(function(c) {
+ const selectedCards = Cards.find(Filter.mongoSelector()).map((c) => {
return c._id;
});
MultiSelection.add(selectedCards);
- }
+ },
}];
- }
+ },
}).register('filterSidebar');
-var updateSelectedCards = function(query) {
- Cards.find(MultiSelection.getMongoSelector()).forEach(function(card) {
+function updateSelectedCards(query) {
+ Cards.find(MultiSelection.getMongoSelector()).forEach((card) => {
Cards.update(card._id, query);
});
-};
+}
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'multiselectionSidebar';
},
- mapSelection: function(kind, _id) {
- return Cards.find(MultiSelection.getMongoSelector()).map(function(card) {
- var methodName = kind === 'label' ? 'hasLabel' : 'isAssigned';
+ mapSelection(kind, _id) {
+ return Cards.find(MultiSelection.getMongoSelector()).map((card) => {
+ const methodName = kind === 'label' ? 'hasLabel' : 'isAssigned';
return card[methodName](_id);
});
},
- allSelectedElementHave: function(kind, _id) {
+ allSelectedElementHave(kind, _id) {
if (MultiSelection.isEmpty())
return false;
else
return _.every(this.mapSelection(kind, _id));
},
- someSelectedElementHave: function(kind, _id) {
+ someSelectedElementHave(kind, _id) {
if (MultiSelection.isEmpty())
return false;
else
return _.some(this.mapSelection(kind, _id));
},
- events: function() {
+ events() {
return [{
- 'click .js-toggle-label-multiselection': function(evt) {
- var labelId = this.currentData()._id;
- var mappedSelection = this.mapSelection('label', labelId);
- var operation;
+ 'click .js-toggle-label-multiselection'(evt) {
+ const labelId = this.currentData()._id;
+ const mappedSelection = this.mapSelection('label', labelId);
+ let operation;
if (_.every(mappedSelection))
operation = '$pull';
- else if (_.every(mappedSelection, function(bool) { return ! bool; }))
+ else if (_.every(mappedSelection, (bool) => !bool))
operation = '$addToSet';
else {
- var popup = Popup.open('disambiguateMultiLabel');
+ const popup = Popup.open('disambiguateMultiLabel');
// XXX We need to have a better integration between the popup and the
// UI components systems.
return popup.call(this.currentData(), evt);
}
- var query = {};
- query[operation] = {
- labelIds: labelId
- };
- updateSelectedCards(query);
+ updateSelectedCards({
+ [operation]: {
+ labelIds: labelId,
+ },
+ });
},
- 'click .js-toogle-member-multiselection': function(evt) {
- var memberId = this.currentData()._id;
- var mappedSelection = this.mapSelection('member', memberId);
- var operation;
+ 'click .js-toogle-member-multiselection'(evt) {
+ const memberId = this.currentData()._id;
+ const mappedSelection = this.mapSelection('member', memberId);
+ let operation;
if (_.every(mappedSelection))
operation = '$pull';
- else if (_.every(mappedSelection, function(bool) { return ! bool; }))
+ else if (_.every(mappedSelection, (bool) => !bool))
operation = '$addToSet';
else {
- var popup = Popup.open('disambiguateMultiMember');
+ const popup = Popup.open('disambiguateMultiMember');
// XXX We need to have a better integration between the popup and the
// UI components systems.
return popup.call(this.currentData(), evt);
}
- var query = {};
- query[operation] = {
- members: memberId
- };
- updateSelectedCards(query);
+ updateSelectedCards({
+ [operation]: {
+ members: memberId,
+ },
+ });
},
- 'click .js-archive-selection': function() {
+ 'click .js-archive-selection'() {
updateSelectedCards({$set: {archived: true}});
- }
+ },
}];
- }
+ },
}).register('multiselectionSidebar');
Template.disambiguateMultiLabelPopup.events({
- 'click .js-remove-label': function() {
+ 'click .js-remove-label'() {
updateSelectedCards({$pull: {labelIds: this._id}});
Popup.close();
},
- 'click .js-add-label': function() {
+ 'click .js-add-label'() {
updateSelectedCards({$addToSet: {labelIds: this._id}});
Popup.close();
- }
+ },
});
Template.disambiguateMultiMemberPopup.events({
- 'click .js-unassign-member': function() {
+ 'click .js-unassign-member'() {
updateSelectedCards({$pull: {members: this._id}});
Popup.close();
},
- 'click .js-assign-member': function() {
+ 'click .js-assign-member'() {
updateSelectedCards({$addToSet: {members: this._id}});
Popup.close();
- }
+ },
});
diff --git a/client/components/users/userAvatar.js b/client/components/users/userAvatar.js
index a35415e2..b0702468 100644
--- a/client/components/users/userAvatar.js
+++ b/client/components/users/userAvatar.js
@@ -1,98 +1,98 @@
Meteor.subscribe('my-avatars');
Template.userAvatar.helpers({
- userData: function() {
+ userData() {
return Users.findOne(this.userId, {
fields: {
profile: 1,
- username: 1
- }
+ username: 1,
+ },
});
},
- memberType: function() {
- var user = Users.findOne(this.userId);
+ memberType() {
+ const user = Users.findOne(this.userId);
return user && user.isBoardAdmin() ? 'admin' : 'normal';
},
- presenceStatusClassName: function() {
- var userPresence = Presences.findOne({ userId: this.userId });
- if (! userPresence)
+ presenceStatusClassName() {
+ const userPresence = Presences.findOne({ userId: this.userId });
+ if (!userPresence)
return 'disconnected';
else if (Session.equals('currentBoard', userPresence.state.currentBoardId))
return 'active';
else
return 'idle';
- }
+ },
});
Template.userAvatar.events({
- 'click .js-change-avatar': Popup.open('changeAvatar')
+ 'click .js-change-avatar': Popup.open('changeAvatar'),
});
Template.userAvatarInitials.helpers({
- initials: function() {
- var user = Users.findOne(this.userId);
+ initials() {
+ const user = Users.findOne(this.userId);
return user && user.getInitials();
},
- viewPortWidth: function() {
- var user = Users.findOne(this.userId);
+ viewPortWidth() {
+ const user = Users.findOne(this.userId);
return (user && user.getInitials().length || 1) * 12;
- }
+ },
});
BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'changeAvatarPopup';
},
- onCreated: function() {
+ onCreated() {
this.error = new ReactiveVar('');
},
- avatarUrlOptions: function() {
+ avatarUrlOptions() {
return {
auth: false,
- brokenIsFine: true
+ brokenIsFine: true,
};
},
- uploadedAvatars: function() {
+ uploadedAvatars() {
return Avatars.find({userId: Meteor.userId()});
},
- isSelected: function() {
- var userProfile = Meteor.user().profile;
- var avatarUrl = userProfile && userProfile.avatarUrl;
- var currentAvatarUrl = this.currentData().url(this.avatarUrlOptions());
+ isSelected() {
+ const userProfile = Meteor.user().profile;
+ const avatarUrl = userProfile && userProfile.avatarUrl;
+ const currentAvatarUrl = this.currentData().url(this.avatarUrlOptions());
return avatarUrl === currentAvatarUrl;
},
- noAvatarUrl: function() {
- var userProfile = Meteor.user().profile;
- var avatarUrl = userProfile && userProfile.avatarUrl;
- return ! avatarUrl;
+ noAvatarUrl() {
+ const userProfile = Meteor.user().profile;
+ const avatarUrl = userProfile && userProfile.avatarUrl;
+ return !avatarUrl;
},
- setAvatar: function(avatarUrl) {
+ setAvatar(avatarUrl) {
Meteor.users.update(Meteor.userId(), {
$set: {
- 'profile.avatarUrl': avatarUrl
- }
+ 'profile.avatarUrl': avatarUrl,
+ },
});
},
- setError: function(error) {
+ setError(error) {
this.error.set(error);
},
- events: function() {
+ events() {
return [{
- 'click .js-upload-avatar': function() {
+ 'click .js-upload-avatar'() {
this.$('.js-upload-avatar-input').click();
},
- 'change .js-upload-avatar-input': function(evt) {
+ 'change .js-upload-avatar-input'(evt) {
let file, fileUrl;
FS.Utility.eachFile(evt, (f) => {
@@ -106,71 +106,71 @@ BlazeComponent.extendComponent({
if (fileUrl) {
this.setError('');
- let fetchAvatarInterval = window.setInterval(() => {
+ const fetchAvatarInterval = window.setInterval(() => {
$.ajax({
url: fileUrl,
success: () => {
this.setAvatar(file.url(this.avatarUrlOptions()));
window.clearInterval(fetchAvatarInterval);
- }
+ },
});
}, 100);
}
},
- 'click .js-select-avatar': function() {
- var avatarUrl = this.currentData().url(this.avatarUrlOptions());
+ 'click .js-select-avatar'() {
+ const avatarUrl = this.currentData().url(this.avatarUrlOptions());
this.setAvatar(avatarUrl);
},
- 'click .js-select-initials': function() {
+ 'click .js-select-initials'() {
this.setAvatar('');
},
- 'click .js-delete-avatar': function() {
+ 'click .js-delete-avatar'() {
Avatars.remove(this.currentData()._id);
- }
+ },
}];
- }
+ },
}).register('changeAvatarPopup');
Template.cardMembersPopup.helpers({
- isCardMember: function() {
- var cardId = Template.parentData()._id;
- var cardMembers = Cards.findOne(cardId).members || [];
+ isCardMember() {
+ const cardId = Template.parentData()._id;
+ const cardMembers = Cards.findOne(cardId).members || [];
return _.contains(cardMembers, this.userId);
},
- user: function() {
+ user() {
return Users.findOne(this.userId);
- }
+ },
});
Template.cardMembersPopup.events({
- 'click .js-select-member': function(evt) {
- var cardId = Template.parentData(2).data._id;
- var memberId = this.userId;
- var operation;
+ 'click .js-select-member'(evt) {
+ const cardId = Template.parentData(2).data._id;
+ const memberId = this.userId;
+ let operation;
if (Cards.find({ _id: cardId, members: memberId}).count() === 0)
operation = '$addToSet';
else
operation = '$pull';
- var query = {};
- query[operation] = {
- members: memberId
- };
- Cards.update(cardId, query);
+ Cards.update(cardId, {
+ [operation]: {
+ members: memberId,
+ },
+ });
evt.preventDefault();
- }
+ },
});
Template.cardMemberPopup.helpers({
- user: function() {
+ user() {
return Users.findOne(this.userId);
- }
+ },
});
Template.cardMemberPopup.events({
- 'click .js-remove-member': function() {
+ 'click .js-remove-member'() {
Cards.update(this.cardId, {$pull: {members: this.userId}});
Popup.close();
},
- 'click .js-edit-profile': Popup.open('editProfile')
+ 'click .js-edit-profile': Popup.open('editProfile'),
});
diff --git a/client/components/users/userHeader.js b/client/components/users/userHeader.js
index 2110faa6..d8b1ee48 100644
--- a/client/components/users/userHeader.js
+++ b/client/components/users/userHeader.js
@@ -1,6 +1,6 @@
Template.headerUserBar.events({
'click .js-open-header-member-menu': Popup.open('memberMenu'),
- 'click .js-change-avatar': Popup.open('changeAvatar')
+ 'click .js-change-avatar': Popup.open('changeAvatar'),
});
Template.memberMenuPopup.events({
@@ -8,58 +8,57 @@ Template.memberMenuPopup.events({
'click .js-change-avatar': Popup.open('changeAvatar'),
'click .js-change-password': Popup.open('changePassword'),
'click .js-change-language': Popup.open('changeLanguage'),
- 'click .js-logout': function(evt) {
+ 'click .js-logout'(evt) {
evt.preventDefault();
AccountsTemplates.logout();
- }
+ },
});
Template.editProfilePopup.events({
- submit: function(evt, tpl) {
+ submit(evt, tpl) {
evt.preventDefault();
- var fullname = $.trim(tpl.find('.js-profile-fullname').value);
- var username = $.trim(tpl.find('.js-profile-username').value);
- var initials = $.trim(tpl.find('.js-profile-initials').value);
+ const fullname = $.trim(tpl.find('.js-profile-fullname').value);
+ const username = $.trim(tpl.find('.js-profile-username').value);
+ const initials = $.trim(tpl.find('.js-profile-initials').value);
Users.update(Meteor.userId(), {$set: {
'profile.fullname': fullname,
- 'profile.initials': initials
+ 'profile.initials': initials,
}});
// XXX We should report the error to the user.
if (username !== Meteor.user().username) {
Meteor.call('setUsername', username);
}
Popup.back();
- }
+ },
});
// XXX For some reason the useraccounts autofocus isnt working in this case.
// See https://github.com/meteor-useraccounts/core/issues/384
-Template.changePasswordPopup.onRendered(function() {
+Template.changePasswordPopup.onRendered(() => {
this.find('#at-field-current_password').focus();
});
Template.changeLanguagePopup.helpers({
- languages: function() {
- return _.map(TAPi18n.getLanguages(), function(lang, tag) {
- return {
- tag: tag,
- name: lang.name
- };
+ languages() {
+ return _.map(TAPi18n.getLanguages(), (lang, tag) => {
+ const name = lang.name;
+ return { tag, name };
});
},
- isCurrentLanguage: function() {
+
+ isCurrentLanguage() {
return this.tag === TAPi18n.getLanguage();
- }
+ },
});
Template.changeLanguagePopup.events({
- 'click .js-set-language': function(evt) {
+ 'click .js-set-language'(evt) {
Users.update(Meteor.userId(), {
$set: {
- 'profile.language': this.tag
- }
+ 'profile.language': this.tag,
+ },
});
evt.preventDefault();
- }
+ },
});
diff --git a/client/config/accounts.js b/client/config/accounts.js
index a448d612..df0935f7 100644
--- a/client/config/accounts.js
+++ b/client/config/accounts.js
@@ -1,11 +1,11 @@
-var passwordField = AccountsTemplates.removeField('password');
-var emailField = AccountsTemplates.removeField('email');
+const passwordField = AccountsTemplates.removeField('password');
+const emailField = AccountsTemplates.removeField('email');
AccountsTemplates.addFields([{
_id: 'username',
type: 'text',
displayName: 'username',
required: true,
- minLength: 2
+ minLength: 2,
}, emailField, passwordField]);
AccountsTemplates.configure({
@@ -15,36 +15,34 @@ AccountsTemplates.configure({
enablePasswordChange: true,
sendVerificationEmail: true,
showForgotPasswordLink: true,
- onLogoutHook: function() {
- var homePage = 'home';
+ onLogoutHook() {
+ const homePage = 'home';
if (FlowRouter.getRouteName() === homePage) {
FlowRouter.reload();
} else {
FlowRouter.go(homePage);
}
- }
+ },
});
_.each(['signIn', 'signUp', 'resetPwd', 'forgotPwd', 'enrollAccount'],
- function(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.
AccountsTemplates.configure({
texts: {
title: {
- changePwd: ''
- }
- }
+ changePwd: '',
+ },
+ },
});
AccountsTemplates.configureRoute('changePwd', {
- redirect: function() {
+ redirect() {
// XXX We should emit a notification once we have a notification system.
// Currently the user has no indication that his modification has been
// applied.
Popup.back();
- }
+ },
});
diff --git a/client/config/blazeHelpers.js b/client/config/blazeHelpers.js
index 1be44728..2c55bc40 100644
--- a/client/config/blazeHelpers.js
+++ b/client/config/blazeHelpers.js
@@ -1,13 +1,53 @@
-Blaze.registerHelper('currentBoard', function() {
- var boardId = Session.get('currentBoard');
+Blaze.registerHelper('currentBoard', () => {
+ const boardId = Session.get('currentBoard');
if (boardId) {
return Boards.findOne(boardId);
}
});
-Blaze.registerHelper('currentCard', function() {
- var cardId = Session.get('currentCard');
+Blaze.registerHelper('currentCard', () => {
+ const cardId = Session.get('currentCard');
if (cardId) {
return Cards.findOne(cardId);
}
});
+
+Blaze.registerHelper('getUser', (userId) => Users.findOne(userId));
+
+// XXX I believe we should compute a HTML rendered field on the server that
+// would handle markdown, emojies and user mentions. We can simply have two
+// fields, one source, and one compiled version (in HTML) and send only the
+// compiled version to most users -- who don't need to edit.
+// In the meantime, all the transformation are done on the client using the
+// Blaze API.
+const at = HTML.CharRef({html: '&commat;', str: '@'});
+Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
+ const view = this;
+ const currentBoard = Session.get('currentBoard');
+ const knowedUsers = _.map(currentBoard.members, (member) => {
+ member.username = Users.findOne(member.userId).username;
+ return member;
+ });
+ const mentionRegex = /\B@(\w*)/gi;
+ let content = Blaze.toHTML(view.templateContentBlock);
+
+ let currentMention, knowedUser, href, linkClass, linkValue, link;
+ while (Boolean(currentMention = mentionRegex.exec(content))) {
+
+ knowedUser = _.findWhere(knowedUsers, { username: currentMention[1] });
+ if (!knowedUser)
+ continue;
+
+ linkValue = [' ', at, knowedUser.username];
+ // XXX We need to convert to flow router
+ href = Router.url('Profile', { username: knowedUser.username });
+ linkClass = 'atMention';
+ if (knowedUser.userId === Meteor.userId())
+ linkClass += ' me';
+ link = HTML.A({ href, 'class': linkClass }, linkValue);
+
+ content = content.replace(currentMention[0], Blaze.toHTML(link));
+ }
+
+ return HTML.Raw(content);
+}));
diff --git a/client/config/reactiveTabs.js b/client/config/reactiveTabs.js
index 937057f7..5365c6d1 100644
--- a/client/config/reactiveTabs.js
+++ b/client/config/reactiveTabs.js
@@ -1,5 +1,4 @@
// XXX Since Blaze doesn't have a clean high component API, component API are
// also tweaky to use. I guess React would be a solution.
-ReactiveTabs.createInterface({
- template: 'basicTabs'
-});
+const template = 'basicTabs';
+ReactiveTabs.createInterface({ template });
diff --git a/client/config/router.js b/client/config/router.js
index 77b17b63..5260e03f 100644
--- a/client/config/router.js
+++ b/client/config/router.js
@@ -6,7 +6,7 @@ FlowRouter.triggers.exit([({path}) => {
FlowRouter.route('/', {
name: 'home',
triggersEnter: [AccountsTemplates.ensureSignedIn],
- action: function() {
+ action() {
Session.set('currentBoard', null);
Session.set('currentCard', null);
@@ -14,14 +14,14 @@ FlowRouter.route('/', {
EscapeActions.executeAll();
BlazeLayout.render('defaultLayout', { content: 'boardList' });
- }
+ },
});
FlowRouter.route('/b/:id/:slug', {
name: 'board',
- action: function(params) {
- let currentBoard = params.id;
- let previousBoard = Session.get('currentBoard');
+ action(params) {
+ const currentBoard = params.id;
+ const previousBoard = Session.get('currentBoard');
Session.set('currentBoard', currentBoard);
Session.set('currentCard', null);
@@ -32,57 +32,57 @@ FlowRouter.route('/b/:id/:slug', {
}
BlazeLayout.render('defaultLayout', { content: 'board' });
- }
+ },
});
FlowRouter.route('/b/:boardId/:slug/:cardId', {
name: 'card',
- action: function(params) {
+ action(params) {
Session.set('currentBoard', params.boardId);
Session.set('currentCard', params.cardId);
EscapeActions.executeUpTo('inlinedForm');
BlazeLayout.render('defaultLayout', { content: 'board' });
- }
+ },
});
FlowRouter.route('/shortcuts', {
name: 'shortcuts',
- action: function(params) {
+ action() {
const shortcutsTemplate = 'keyboardShortcuts';
EscapeActions.executeUpTo('popup-close');
if (previousPath) {
Modal.open(shortcutsTemplate, {
- onCloseGoTo: previousPath
+ onCloseGoTo: previousPath,
});
} else {
// XXX There is currently no way to escape this page on Sandstorm
BlazeLayout.render('defaultLayout', { content: shortcutsTemplate });
}
- }
+ },
});
FlowRouter.notFound = {
- action: function() {
+ action() {
BlazeLayout.render('defaultLayout', { content: 'notFound' });
- }
-}
+ },
+};
// We maintain a list of redirections to ensure that we don't break old URLs
// when we change our routing scheme.
-var redirections = {
+const redirections = {
'/boards': '/',
'/boards/:id/:slug': '/b/:id/:slug',
- '/boards/:id/:slug/:cardId': '/b/:id/:slug/:cardId'
+ '/boards/:id/:slug/:cardId': '/b/:id/:slug/:cardId',
};
-_.each(redirections, function(newPath, oldPath) {
+_.each(redirections, (newPath, oldPath) => {
FlowRouter.route(oldPath, {
- triggersEnter: [function(context, redirect) {
+ triggersEnter: [(context, redirect) => {
redirect(FlowRouter.path(newPath, context.params));
- }]
+ }],
});
});
diff --git a/client/lib/cssEvents.js b/client/lib/cssEvents.js
index 487ba69b..39c3fb90 100644
--- a/client/lib/cssEvents.js
+++ b/client/lib/cssEvents.js
@@ -1,42 +1,40 @@
// XXX Should we use something like Moderniz instead of our custom detector?
-var whichTransitionEvent = function() {
- var t;
- var el = document.createElement('fakeelement');
- var transitions = {
+function whichTransitionEvent() {
+ const el = document.createElement('fakeelement');
+ const transitions = {
transition:'transitionend',
OTransition:'oTransitionEnd',
MSTransition:'msTransitionEnd',
MozTransition:'transitionend',
- WebkitTransition:'webkitTransitionEnd'
+ WebkitTransition:'webkitTransitionEnd',
};
- for (t in transitions) {
+ for (const t in transitions) {
if (el.style[t] !== undefined) {
return transitions[t];
}
}
-};
+}
-var whichAnimationEvent = function() {
- var t;
- var el = document.createElement('fakeelement');
- var transitions = {
+function whichAnimationEvent() {
+ const el = document.createElement('fakeelement');
+ const transitions = {
animation:'animationend',
OAnimation:'oAnimationEnd',
MSTransition:'msAnimationEnd',
MozAnimation:'animationend',
- WebkitAnimation:'webkitAnimationEnd'
+ WebkitAnimation:'webkitAnimationEnd',
};
- for (t in transitions) {
+ for (const t in transitions) {
if (el.style[t] !== undefined) {
return transitions[t];
}
}
-};
+}
CSSEvents = {
transitionend: whichTransitionEvent(),
- animationend: whichAnimationEvent()
+ animationend: whichAnimationEvent(),
};
diff --git a/client/lib/escapeActions.js b/client/lib/escapeActions.js
index ff793b1d..f2dc3dcb 100644
--- a/client/lib/escapeActions.js
+++ b/client/lib/escapeActions.js
@@ -31,7 +31,7 @@ EscapeActions = {
enabledOnClick = true;
}
- let noClickEscapeOn = options.noClickEscapeOn;
+ const noClickEscapeOn = options.noClickEscapeOn;
this._actions = _.sortBy([...this._actions, {
priority,
@@ -44,20 +44,20 @@ EscapeActions = {
executeLowest() {
return this._execute({
- multipleAction: false
+ multipleAction: false,
});
},
executeAll() {
return this._execute({
- multipleActions: true
+ multipleActions: true,
});
},
executeUpTo(maxLabel) {
return this._execute({
- maxLabel: maxLabel,
- multipleActions: true
+ maxLabel,
+ multipleActions: true,
});
},
@@ -66,10 +66,10 @@ EscapeActions = {
this._nextclickPrevented = false;
} else {
return this._execute({
- maxLabel: maxLabel,
+ maxLabel,
multipleActions: false,
isClick: true,
- clickTarget: target
+ clickTarget: target,
});
}
},
@@ -79,7 +79,7 @@ EscapeActions = {
},
_stopClick(action, clickTarget) {
- if (! _.isString(action.noClickEscapeOn))
+ if (!_.isString(action.noClickEscapeOn))
return false;
else
return $(clickTarget).closest(action.noClickEscapeOn).length > 0;
@@ -88,86 +88,46 @@ EscapeActions = {
_execute(options) {
const maxLabel = options.maxLabel;
const multipleActions = options.multipleActions;
- const isClick = !! options.isClick;
+ const isClick = Boolean(options.isClick);
const clickTarget = options.clickTarget;
let executedAtLeastOne = false;
let maxPriority;
- if (! maxLabel)
+ if (!maxLabel)
maxPriority = Infinity;
else
maxPriority = this.hierarchy.indexOf(maxLabel);
- for (let currentAction of this._actions) {
+ for (const currentAction of this._actions) {
if (currentAction.priority > maxPriority)
return executedAtLeastOne;
if (isClick && this._stopClick(currentAction, clickTarget))
return executedAtLeastOne;
- let isEnabled = currentAction.enabledOnClick || ! isClick;
+ const isEnabled = currentAction.enabledOnClick || !isClick;
if (isEnabled && currentAction.condition()) {
currentAction.action();
executedAtLeastOne = true;
- if (! multipleActions)
+ if (!multipleActions)
return executedAtLeastOne;
}
}
return executedAtLeastOne;
- }
-};
-
-// MouseTrap plugin bindGlobal plugin. Adds a bindGlobal method to Mousetrap
-// that allows you to bind specific keyboard shortcuts that will still work
-// inside a text input field.
-//
-// usage:
-// Mousetrap.bindGlobal('ctrl+s', _saveChanges);
-//
-// source:
-// https://github.com/ccampbell/mousetrap/tree/master/plugins/global-bind
-var _globalCallbacks = {};
-var _originalStopCallback = Mousetrap.stopCallback;
-
-Mousetrap.stopCallback = function(e, element, combo, sequence) {
- var self = this;
-
- if (self.paused) {
- return true;
- }
-
- if (_globalCallbacks[combo] || _globalCallbacks[sequence]) {
- return false;
- }
-
- return _originalStopCallback.call(self, e, element, combo);
-};
-
-Mousetrap.bindGlobal = function(keys, callback, action) {
- var self = this;
- self.bind(keys, callback, action);
-
- if (keys instanceof Array) {
- for (var i = 0; i < keys.length; i++) {
- _globalCallbacks[keys[i]] = true;
- }
- return;
- }
-
- _globalCallbacks[keys] = true;
+ },
};
// Pressing escape to execute one escape action. We use `bindGloabal` vecause
// the shortcut sould work on textarea and inputs as well.
-Mousetrap.bindGlobal('esc', function() {
+Mousetrap.bindGlobal('esc', () => {
EscapeActions.executeLowest();
});
// 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', function(evt) {
+$(document).on('click', (evt) => {
if (evt.button === 0 &&
$(evt.target).closest('a,button,.is-editable').length === 0) {
EscapeActions.clickExecute(evt.target, 'multiselection');
diff --git a/client/lib/filter.js b/client/lib/filter.js
index 359b65d3..532ef236 100644
--- a/client/lib/filter.js
+++ b/client/lib/filter.js
@@ -4,66 +4,66 @@
// goal is to filter complete documents by using the local filters for each
// fields.
-var showFilterSidebar = function() {
+function showFilterSidebar() {
Sidebar.setView('filter');
-};
+}
// Use a "set" filter for a field that is a set of documents uniquely
// identified. For instance `{ labels: ['labelA', 'labelC', 'labelD'] }`.
-var SetFilter = function() {
- this._dep = new Tracker.Dependency();
- this._selectedElements = [];
-};
+class SetFilter {
+ constructor() {
+ this._dep = new Tracker.Dependency();
+ this._selectedElements = [];
+ }
-_.extend(SetFilter.prototype, {
- isSelected: function(val) {
+ isSelected(val) {
this._dep.depend();
return this._selectedElements.indexOf(val) > -1;
- },
+ }
- add: function(val) {
+ add(val) {
if (this._indexOfVal(val) === -1) {
this._selectedElements.push(val);
this._dep.changed();
showFilterSidebar();
}
- },
+ }
- remove: function(val) {
- var indexOfVal = this._indexOfVal(val);
+ remove(val) {
+ const indexOfVal = this._indexOfVal(val);
if (this._indexOfVal(val) !== -1) {
this._selectedElements.splice(indexOfVal, 1);
this._dep.changed();
}
- },
+ }
- toogle: function(val) {
+ toogle(val) {
if (this._indexOfVal(val) === -1) {
this.add(val);
} else {
this.remove(val);
}
- },
+ }
- reset: function() {
+ reset() {
this._selectedElements = [];
this._dep.changed();
- },
+ }
- _indexOfVal: function(val) {
+ _indexOfVal(val) {
return this._selectedElements.indexOf(val);
- },
+ }
- _isActive: function() {
+ _isActive() {
this._dep.depend();
return this._selectedElements.length !== 0;
- },
+ }
- _getMongoSelector: function() {
+ _getMongoSelector() {
this._dep.depend();
return { $in: this._selectedElements };
}
-});
+}
// The global Filter object.
// XXX It would be possible to re-write this object more elegantly, and removing
@@ -84,50 +84,46 @@ Filter = {
_exceptions: [],
_exceptionsDep: new Tracker.Dependency(),
- isActive: function() {
- var self = this;
- return _.any(self._fields, function(fieldName) {
- return self[fieldName]._isActive();
+ isActive() {
+ return _.any(this._fields, (fieldName) => {
+ return this[fieldName]._isActive();
});
},
- _getMongoSelector: function() {
- var self = this;
-
- if (! self.isActive())
+ _getMongoSelector() {
+ if (!this.isActive())
return {};
- var filterSelector = {};
- _.forEach(self._fields, function(fieldName) {
- var filter = self[fieldName];
+ const filterSelector = {};
+ _.forEach(this._fields, (fieldName) => {
+ const filter = this[fieldName];
if (filter._isActive())
filterSelector[fieldName] = filter._getMongoSelector();
});
- var exceptionsSelector = {_id: {$in: this._exceptions}};
+ const exceptionsSelector = {_id: {$in: this._exceptions}};
this._exceptionsDep.depend();
return {$or: [filterSelector, exceptionsSelector]};
},
- mongoSelector: function(additionalSelector) {
- var filterSelector = this._getMongoSelector();
+ mongoSelector(additionalSelector) {
+ const filterSelector = this._getMongoSelector();
if (_.isUndefined(additionalSelector))
return filterSelector;
else
return {$and: [filterSelector, additionalSelector]};
},
- reset: function() {
- var self = this;
- _.forEach(self._fields, function(fieldName) {
- var filter = self[fieldName];
+ reset() {
+ _.forEach(this._fields, (fieldName) => {
+ const filter = this[fieldName];
filter.reset();
});
- self.resetExceptions();
+ this.resetExceptions();
},
- addException: function(_id) {
+ addException(_id) {
if (this.isActive()) {
this._exceptions.push(_id);
this._exceptionsDep.changed();
@@ -135,10 +131,10 @@ Filter = {
}
},
- resetExceptions: function() {
+ resetExceptions() {
this._exceptions = [];
this._exceptionsDep.changed();
- }
+ },
};
Blaze.registerHelper('Filter', Filter);
diff --git a/client/lib/i18n.js b/client/lib/i18n.js
index 7d7e3ebb..a03fb398 100644
--- a/client/lib/i18n.js
+++ b/client/lib/i18n.js
@@ -2,9 +2,9 @@
// the language reactively. If the user is not connected we use the language
// information provided by the browser, and default to english.
-Tracker.autorun(function() {
- var language;
- var currentUser = Meteor.user();
+Tracker.autorun(() => {
+ const currentUser = Meteor.user();
+ let language;
if (currentUser) {
language = currentUser.profile && currentUser.profile.language;
} else {
@@ -12,11 +12,10 @@ Tracker.autorun(function() {
}
if (language) {
-
TAPi18n.setLanguage(language);
// XXX
- var shortLanguage = language.split('-')[0];
+ const shortLanguage = language.split('-')[0];
T9n.setLanguage(shortLanguage);
}
});
diff --git a/client/lib/inlinedform.js b/client/lib/inlinedform.js
index 15074f40..2732a2e3 100644
--- a/client/lib/inlinedform.js
+++ b/client/lib/inlinedform.js
@@ -13,66 +13,66 @@
// // the content when the form is close (optional)
// We can only have one inlined form element opened at a time
-currentlyOpenedForm = new ReactiveVar(null);
+const currentlyOpenedForm = new ReactiveVar(null);
InlinedForm = BlazeComponent.extendComponent({
- template: function() {
+ template() {
return 'inlinedForm';
},
- onCreated: function() {
+ onCreated() {
this.isOpen = new ReactiveVar(false);
},
- onDestroyed: function() {
+ onDestroyed() {
currentlyOpenedForm.set(null);
},
- open: function() {
+ open() {
// Close currently opened form, if any
EscapeActions.executeUpTo('inlinedForm');
this.isOpen.set(true);
currentlyOpenedForm.set(this);
},
- close: function() {
+ close() {
this.isOpen.set(false);
currentlyOpenedForm.set(null);
},
- getValue: function() {
- var input = this.find('textarea,input[type=text]');
+ getValue() {
+ const input = this.find('textarea,input[type=text]');
return this.isOpen.get() && input && input.value;
},
- events: function() {
+ events() {
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': function(evt) {
+ '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: function() {
+ submit() {
if (this.currentData().autoclose !== false) {
Tracker.afterFlush(() => {
this.close();
});
}
- }
+ },
}];
- }
+ },
}).register('inlinedForm');
// Press escape to close the currently opened inlinedForm
EscapeActions.register('inlinedForm',
- function() { currentlyOpenedForm.get().close(); },
- function() { return currentlyOpenedForm.get() !== null; }, {
- noClickEscapeOn: '.js-inlined-form'
+ () => { currentlyOpenedForm.get().close(); },
+ () => { return currentlyOpenedForm.get() !== null; }, {
+ noClickEscapeOn: '.js-inlined-form',
}
);
diff --git a/client/lib/keyboard.js b/client/lib/keyboard.js
index 2b327b33..0bb9c380 100644
--- a/client/lib/keyboard.js
+++ b/client/lib/keyboard.js
@@ -24,7 +24,7 @@ Mousetrap.bind('x', () => {
});
Mousetrap.bind(['down', 'up'], (evt, key) => {
- if (! Session.get('currentCard')) {
+ if (!Session.get('currentCard')) {
return;
}
@@ -39,24 +39,24 @@ Mousetrap.bind(['down', 'up'], (evt, key) => {
Template.keyboardShortcuts.helpers({
mapping: [{
keys: ['W'],
- action: 'shortcut-toogle-sidebar'
+ action: 'shortcut-toogle-sidebar',
}, {
keys: ['Q'],
- action: 'shortcut-filter-my-cards'
+ action: 'shortcut-filter-my-cards',
}, {
keys: ['X'],
- action: 'shortcut-clear-filters'
+ action: 'shortcut-clear-filters',
}, {
keys: ['?'],
- action: 'shortcut-show-shortcuts'
+ action: 'shortcut-show-shortcuts',
}, {
keys: ['ESC'],
- action: 'shortcut-close-dialog'
+ action: 'shortcut-close-dialog',
}, {
keys: ['@'],
- action: 'shortcut-autocomplete-members'
+ action: 'shortcut-autocomplete-members',
}, {
keys: [':'],
- action: 'shortcut-autocomplete-emojies'
- }]
+ action: 'shortcut-autocomplete-emojies',
+ }],
});
diff --git a/client/lib/modal.js b/client/lib/modal.js
index 9b204bb4..5b3392b2 100644
--- a/client/lib/modal.js
+++ b/client/lib/modal.js
@@ -1,4 +1,4 @@
-const closedValue = null
+const closedValue = null;
window.Modal = new class {
constructor() {
diff --git a/client/lib/multiSelection.js b/client/lib/multiSelection.js
index e6db42cd..77f351a4 100644
--- a/client/lib/multiSelection.js
+++ b/client/lib/multiSelection.js
@@ -1,53 +1,53 @@
-var getCardsBetween = function(idA, idB) {
+function getCardsBetween(idA, idB) {
- var pluckId = function(doc) {
+ function pluckId(doc) {
return doc._id;
- };
+ }
- var getListsStrictlyBetween = function(id1, id2) {
+ function getListsStrictlyBetween(id1, id2) {
return Lists.find({
$and: [
{ sort: { $gt: Lists.findOne(id1).sort } },
- { sort: { $lt: Lists.findOne(id2).sort } }
+ { sort: { $lt: Lists.findOne(id2).sort } },
],
- archived: false
+ archived: false,
}).map(pluckId);
- };
+ }
- var cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], function(c) {
+ const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], (c) => {
return c.sort;
});
- var selector;
+ let selector;
if (cards[0].listId === cards[1].listId) {
selector = {
listId: cards[0].listId,
sort: {
$gte: cards[0].sort,
- $lte: cards[1].sort
+ $lte: cards[1].sort,
},
- archived: false
+ archived: false,
};
} else {
selector = {
$or: [{
listId: cards[0].listId,
- sort: { $lte: cards[0].sort }
+ sort: { $lte: cards[0].sort },
}, {
listId: {
- $in: getListsStrictlyBetween(cards[0].listId, cards[1].listId)
- }
+ $in: getListsStrictlyBetween(cards[0].listId, cards[1].listId),
+ },
}, {
listId: cards[1].listId,
- sort: { $gte: cards[1].sort }
+ sort: { $gte: cards[1].sort },
}],
- archived: false
+ archived: false,
};
}
return Cards.find(Filter.mongoSelector(selector)).map(pluckId);
-};
+}
MultiSelection = {
sidebarView: 'multiselection',
@@ -58,30 +58,30 @@ MultiSelection = {
startRangeCardId: null,
- reset: function() {
+ reset() {
this._selectedCards.set([]);
},
- getMongoSelector: function() {
+ getMongoSelector() {
return Filter.mongoSelector({
- _id: { $in: this._selectedCards.get() }
+ _id: { $in: this._selectedCards.get() },
});
},
- isActive: function() {
+ isActive() {
return this._isActive.get();
},
- count: function() {
+ count() {
return Cards.find(this.getMongoSelector()).count();
},
- isEmpty: function() {
+ isEmpty() {
return this.count() === 0;
},
- activate: function() {
- if (! this.isActive()) {
+ activate() {
+ if (!this.isActive()) {
EscapeActions.executeUpTo('detailsPane');
this._isActive.set(true);
Tracker.flush();
@@ -89,7 +89,7 @@ MultiSelection = {
Sidebar.setView(this.sidebarView);
},
- disable: function() {
+ disable() {
if (this.isActive()) {
this._isActive.set(false);
if (Sidebar && Sidebar.getView() === this.sidebarView) {
@@ -99,19 +99,19 @@ MultiSelection = {
}
},
- add: function(cardIds) {
+ add(cardIds) {
return this.toogle(cardIds, { add: true, remove: false });
},
- remove: function(cardIds) {
+ remove(cardIds) {
return this.toogle(cardIds, { add: false, remove: true });
},
- toogleRange: function(cardId) {
- var selectedCards = this._selectedCards.get();
- var startRange;
+ toogleRange(cardId) {
+ const selectedCards = this._selectedCards.get();
+ let startRange;
this.reset();
- if (! this.isActive() || selectedCards.length === 0) {
+ if (!this.isActive() || selectedCards.length === 0) {
this.toogle(cardId);
} else {
startRange = selectedCards[selectedCards.length - 1];
@@ -119,23 +119,22 @@ MultiSelection = {
}
},
- toogle: function(cardIds, options) {
- var self = this;
+ toogle(cardIds, options) {
cardIds = _.isString(cardIds) ? [cardIds] : cardIds;
options = _.extend({
add: true,
- remove: true
+ remove: true,
}, options || {});
- if (! self.isActive()) {
- self.reset();
- self.activate();
+ if (!this.isActive()) {
+ this.reset();
+ this.activate();
}
- var selectedCards = self._selectedCards.get();
+ const selectedCards = this._selectedCards.get();
- _.each(cardIds, function(cardId) {
- var indexOfCard = selectedCards.indexOf(cardId);
+ _.each(cardIds, (cardId) => {
+ const indexOfCard = selectedCards.indexOf(cardId);
if (options.remove && indexOfCard > -1)
selectedCards.splice(indexOfCard, 1);
@@ -144,19 +143,19 @@ MultiSelection = {
selectedCards.push(cardId);
});
- self._selectedCards.set(selectedCards);
+ this._selectedCards.set(selectedCards);
},
- isSelected: function(cardId) {
+ isSelected(cardId) {
return this._selectedCards.get().indexOf(cardId) > -1;
- }
+ },
};
Blaze.registerHelper('MultiSelection', MultiSelection);
EscapeActions.register('multiselection',
- function() { MultiSelection.disable(); },
- function() { return MultiSelection.isActive(); }, {
- noClickEscapeOn: '.js-minicard,.js-board-sidebar-content'
+ () => { MultiSelection.disable(); },
+ () => { return MultiSelection.isActive(); }, {
+ noClickEscapeOn: '.js-minicard,.js-board-sidebar-content',
}
);
diff --git a/client/lib/popup.js b/client/lib/popup.js
index b2340e04..3c39af29 100644
--- a/client/lib/popup.js
+++ b/client/lib/popup.js
@@ -1,55 +1,53 @@
// A simple tracker dependency that we invalidate every time the window is
// resized. This is used to reactively re-calculate the popup position in case
// of a window resize. This is the equivalent of a "Signal" in some other
-// programming environments.
-let windowResizeDep = new Tracker.Dependency()
-$(window).on('resize', () => windowResizeDep.changed())
+// programming environments (eg, elm).
+const windowResizeDep = new Tracker.Dependency();
+$(window).on('resize', () => windowResizeDep.changed());
window.Popup = new class {
constructor() {
// The template we use to render popups
- this.template = Template.popup
+ this.template = Template.popup;
// We only want to display one popup at a time and we keep the view object
// in this `Popup._current` variable. If there is no popup currently opened
// the value is `null`.
- this._current = null
+ this._current = null;
// It's possible to open a sub-popup B from a popup A. In that case we keep
// the data of popup A so we can return back to it. Every time we open a new
// popup the stack grows, every time we go back the stack decrease, and if
// we close the popup the stack is reseted to the empty stack [].
- this._stack = []
+ this._stack = [];
// We invalidate this internal dependency every time the top of the stack
// has changed and we want to re-render a popup with the new top-stack data.
- this._dep = new Tracker.Dependency()
+ this._dep = new Tracker.Dependency();
}
/// This function returns a callback that can be used in an event map:
- ///
/// Template.tplName.events({
- /// 'click .elementClass': Popup.open("popupName")
- /// })
- ///
+ /// 'click .elementClass': Popup.open("popupName"),
+ /// });
/// The popup inherit the data context of its parent.
open(name) {
- let self = this
- const popupName = `${name}Popup`
+ const self = this;
+ const popupName = `${name}Popup`;
function clickFromPopup(evt) {
- return $(evt.target).closest('.js-pop-over').length !== 0
+ return $(evt.target).closest('.js-pop-over').length !== 0;
}
return function(evt) {
// If a popup is already opened, clicking again on the opener element
// should close it -- and interrupt the current `open` function.
if (self.isOpen()) {
- let previousOpenerElement = self._getTopStack().openerElement
+ const previousOpenerElement = self._getTopStack().openerElement;
if (previousOpenerElement === evt.currentTarget) {
- return self.close()
+ return self.close();
} else {
- $(previousOpenerElement).removeClass('is-active')
+ $(previousOpenerElement).removeClass('is-active');
}
}
@@ -58,16 +56,16 @@ window.Popup = new class {
// if the popup has no parent, or from the parent `openerElement` if it
// has one. This allows us to position a sub-popup exactly at the same
// position than its parent.
- let openerElement
+ let openerElement;
if (clickFromPopup(evt)) {
- openerElement = self._getTopStack().openerElement
+ openerElement = self._getTopStack().openerElement;
} else {
- self._stack = []
- openerElement = evt.currentTarget
+ self._stack = [];
+ openerElement = evt.currentTarget;
}
- $(openerElement).addClass('is-active')
- evt.preventDefault()
+ $(openerElement).addClass('is-active');
+ evt.preventDefault();
// We push our popup data to the stack. The top of the stack is always
// used as the data source for our current popup.
@@ -79,7 +77,7 @@ window.Popup = new class {
depth: self._stack.length,
offset: self._getOffset(openerElement),
dataContext: this.currentData && this.currentData() || this,
- })
+ });
// If there are no popup currently opened we use the Blaze API to render
// one into the DOM. We use a reactive function as the data parameter that
@@ -90,39 +88,38 @@ window.Popup = new class {
// Otherwise if there is already a popup open we just need to invalidate
// our internal dependency, and since we just changed the top element of
// our internal stack, the popup will be updated with the new data.
- if (! self.isOpen()) {
+ if (!self.isOpen()) {
self.current = Blaze.renderWithData(self.template, () => {
- self._dep.depend()
- return _.extend(self._getTopStack(), { stack: self._stack })
- }, document.body)
+ self._dep.depend();
+ return _.extend(self._getTopStack(), { stack: self._stack });
+ }, document.body);
} else {
- self._dep.changed()
+ self._dep.changed();
}
- }
+ };
}
/// This function returns a callback that can be used in an event map:
- ///
/// Template.tplName.events({
/// 'click .elementClass': Popup.afterConfirm("popupName", function() {
/// // What to do after the user has confirmed the action
- /// })
- /// })
+ /// }),
+ /// });
afterConfirm(name, action) {
- let self = this
+ const self = this;
return function(evt, tpl) {
- let context = this.currentData && this.currentData() || this
- context.__afterConfirmAction = action
- self.open(name).call(context, evt, tpl)
- }
+ const context = this.currentData && this.currentData() || this;
+ context.__afterConfirmAction = action;
+ self.open(name).call(context, evt, tpl);
+ };
}
/// The public reactive state of the popup.
isOpen() {
- this._dep.changed()
- return !! this.current
+ this._dep.changed();
+ return Boolean(this.current);
}
/// In case the popup was opened from a parent popup we can get back to it
@@ -132,45 +129,45 @@ window.Popup = new class {
/// steps back is greater than the popup stack size, the popup will be closed.
back(n = 1) {
if (this._stack.length > n) {
- _.times(n, () => this._stack.pop())
- this._dep.changed()
+ _.times(n, () => this._stack.pop());
+ this._dep.changed();
} else {
- this.close()
+ this.close();
}
}
/// Close the current opened popup.
close() {
if (this.isOpen()) {
- Blaze.remove(this.current)
- this.current = null
+ Blaze.remove(this.current);
+ this.current = null;
- let openerElement = this._getTopStack().openerElement
- $(openerElement).removeClass('is-active')
+ const openerElement = this._getTopStack().openerElement;
+ $(openerElement).removeClass('is-active');
- this._stack = []
+ this._stack = [];
}
}
// An utility fonction that returns the top element of the internal stack
_getTopStack() {
- return this._stack[this._stack.length - 1]
+ return this._stack[this._stack.length - 1];
}
// We automatically calculate the popup offset from the reference element
// position and dimensions. We also reactively use the window dimensions to
// ensure that the popup is always visible on the screen.
_getOffset(element) {
- let $element = $(element)
+ const $element = $(element);
return () => {
- windowResizeDep.depend()
- const offset = $element.offset()
- const popupWidth = 300 + 15
+ windowResizeDep.depend();
+ const offset = $element.offset();
+ const popupWidth = 300 + 15;
return {
left: Math.min(offset.left, $(window).width() - popupWidth),
top: offset.top + $element.outerHeight(),
- }
- }
+ };
+ };
}
// We get the title from the translation files. Instead of returning the
@@ -178,22 +175,22 @@ window.Popup = new class {
// is a reactive data source, the title will be changed reactively.
_getTitle(popupName) {
return () => {
- const translationKey = `${popupName}-title`
+ const translationKey = `${popupName}-title`;
// XXX There is no public API to check if there is an available
// translation for a given key. So we try to translate the key and if the
// translation output equals the key input we deduce that no translation
// was available and returns `false`. There is a (small) risk a false
// positives.
- const title = TAPi18n.__(translationKey)
- return title !== translationKey ? title : false
- }
+ const title = TAPi18n.__(translationKey);
+ return title !== translationKey ? title : false;
+ };
}
-}
+};
// 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']
+const escapeActions = ['back', 'close'];
_.each(escapeActions, (actionName) => {
EscapeActions.register(`popup-${actionName}`,
() => Popup[actionName](),
@@ -202,6 +199,6 @@ _.each(escapeActions, (actionName) => {
noClickEscapeOn: '.js-pop-over',
enabledOnClick: actionName === 'close',
}
- )
-})
+ );
+});
diff --git a/client/lib/unsavedEdits.js b/client/lib/unsavedEdits.js
index 55ea2529..dc267bfb 100644
--- a/client/lib/unsavedEdits.js
+++ b/client/lib/unsavedEdits.js
@@ -27,9 +27,9 @@ UnsavedEdits = {
// _collection: UnsavedEditCollection,
get({ fieldName, docId }, defaultTo = '') {
- let unsavedValue = this._getCollectionDocument(fieldName, docId);
+ const unsavedValue = this._getCollectionDocument(fieldName, docId);
if (unsavedValue) {
- return unsavedValue.value
+ return unsavedValue.value;
} else {
return defaultTo;
}
@@ -40,13 +40,9 @@ UnsavedEdits = {
},
set({ fieldName, docId }, value) {
- let currentDoc = this._getCollectionDocument(fieldName, docId);
+ const currentDoc = this._getCollectionDocument(fieldName, docId);
if (currentDoc) {
- UnsavedEditCollection.update(currentDoc._id, {
- $set: {
- value: value
- }
- });
+ UnsavedEditCollection.update(currentDoc._id, { $set: { value }});
} else {
UnsavedEditCollection.insert({
fieldName,
@@ -57,7 +53,7 @@ UnsavedEdits = {
},
reset({ fieldName, docId }) {
- let currentDoc = this._getCollectionDocument(fieldName, docId);
+ const currentDoc = this._getCollectionDocument(fieldName, docId);
if (currentDoc) {
UnsavedEditCollection.remove(currentDoc._id);
}
@@ -65,13 +61,13 @@ UnsavedEdits = {
_getCollectionDocument(fieldName, docId) {
return UnsavedEditCollection.findOne({fieldName, docId});
- }
-}
+ },
+};
Blaze.registerHelper('getUnsavedValue', (fieldName, docId, defaultTo) => {
// Workaround some blaze feature that ass a list of keywords arguments as the
// last parameter (even if the caller didn't specify any).
- if (! _.isString(defaultTo)) {
+ if (!_.isString(defaultTo)) {
defaultTo = '';
}
return UnsavedEdits.get({ fieldName, docId }, defaultTo);
diff --git a/client/lib/utils.js b/client/lib/utils.js
index c6a9adc5..0cd93419 100644
--- a/client/lib/utils.js
+++ b/client/lib/utils.js
@@ -1,62 +1,70 @@
Utils = {
// XXX We should remove these two methods
- goBoardId: function(_id) {
- var board = Boards.findOne(_id);
+ goBoardId(_id) {
+ const board = Boards.findOne(_id);
return board && FlowRouter.go('board', {
id: board._id,
- slug: board.slug
+ slug: board.slug,
});
},
- goCardId: function(_id) {
- var card = Cards.findOne(_id);
- var board = Boards.findOne(card.boardId);
+ 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
+ slug: board.slug,
});
},
- capitalize: function(string) {
+ capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
},
- getLabelIndex: function(boardId, labelId) {
- var board = Boards.findOne(boardId);
- var labels = {};
- _.each(board.labels, function(a, b) {
+ getLabelIndex(boardId, labelId) {
+ const board = Boards.findOne(boardId);
+ const labels = {};
+ _.each(board.labels, (a, b) => {
labels[a._id] = b;
});
return {
index: labels[labelId],
- key: function(key) {
- return 'labels.' + labels[labelId] + '.' + key;
- }
+ key(key) {
+ return `labels.${labels[labelId]}.${key}`;
+ },
};
},
// Determine the new sort index
- calculateIndex: function(prevCardDomElement, nextCardDomElement, nCards) {
- nCards = nCards || 1;
-
+ calculateIndex(prevCardDomElement, nextCardDomElement, nCards = 1) {
+ let base, increment;
// If we drop the card to an empty column
- if (! prevCardDomElement && ! nextCardDomElement) {
- return {base: 0, increment: 1};
+ if (!prevCardDomElement && !nextCardDomElement) {
+ base = 0;
+ increment = 1;
// If we drop the card in the first position
- } else if (! prevCardDomElement) {
- return {base: Blaze.getData(nextCardDomElement).sort - 1, increment: -1};
+ } else if (!prevCardDomElement) {
+ base = Blaze.getData(nextCardDomElement).sort - 1;
+ increment = -1;
// If we drop the card in the last position
- } else if (! nextCardDomElement) {
- return {base: Blaze.getData(prevCardDomElement).sort + 1, increment: 1};
+ } else if (!nextCardDomElement) {
+ base = Blaze.getData(prevCardDomElement).sort + 1;
+ increment = 1;
}
// In the general case take the average of the previous and next element
// sort indexes.
else {
- var prevSortIndex = Blaze.getData(prevCardDomElement).sort;
- var nextSortIndex = Blaze.getData(nextCardDomElement).sort;
- var increment = (nextSortIndex - prevSortIndex) / (nCards + 1);
- return {base: prevSortIndex + increment, increment: increment};
+ const prevSortIndex = Blaze.getData(prevCardDomElement).sort;
+ const nextSortIndex = Blaze.getData(nextCardDomElement).sort;
+ increment = (nextSortIndex - prevSortIndex) / (nCards + 1);
+ base = prevSortIndex + increment;
}
- }
+ // XXX Return a generator that yield values instead of a base with a
+ // increment number.
+ return {
+ base,
+ increment,
+ };
+ },
};