summaryrefslogtreecommitdiffstats
path: root/client/components/sidebar
diff options
context:
space:
mode:
authorMaxime Quandalle <maxime@quandalle.com>2015-09-08 20:19:42 +0200
committerMaxime Quandalle <maxime@quandalle.com>2015-09-08 20:19:42 +0200
commit45b662a1ddb46a0f17fab7b2383c82aa1e1620ef (patch)
treecc7be215c7e7ebffd2597df70cf271b3dd435e1a /client/components/sidebar
parentc04341f1ea5efe082bf7318cf9eb0e99b9b8374a (diff)
downloadwekan-45b662a1ddb46a0f17fab7b2383c82aa1e1620ef.tar.gz
wekan-45b662a1ddb46a0f17fab7b2383c82aa1e1620ef.tar.bz2
wekan-45b662a1ddb46a0f17fab7b2383c82aa1e1620ef.zip
Centralize all mutations at the model level
This commit uses a new package that I need to document. It tries to solve the long-standing debate in the Meteor community about allow/deny rules versus methods (RPC). This approach gives us both the centralized security rules of allow/deny and the white-list of allowed mutations similarly to Meteor methods. The idea to have static mutation descriptions is also inspired by Facebook's Relay/GraphQL. This will allow the development of a REST API using the high-level methods instead of the MongoDB queries to do the mapping between the HTTP requests and our collections.
Diffstat (limited to 'client/components/sidebar')
-rw-r--r--client/components/sidebar/sidebar.js47
-rw-r--r--client/components/sidebar/sidebarArchives.js8
-rw-r--r--client/components/sidebar/sidebarFilters.js49
3 files changed, 27 insertions, 77 deletions
diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js
index eff0ef52..8c58c37e 100644
--- a/client/components/sidebar/sidebar.js
+++ b/client/components/sidebar/sidebar.js
@@ -109,14 +109,6 @@ EscapeActions.register('sidebarView',
() => { return Sidebar && Sidebar.getView() !== defaultView; }
);
-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() {
return Users.findOne(this.userId);
@@ -135,13 +127,8 @@ Template.memberPopup.events({
'click .js-change-role': Popup.open('changePermissions'),
'click .js-remove-member': Popup.afterConfirm('removeMember', function() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
- const memberIndex = getMemberIndex(currentBoard, this.userId);
-
- Boards.update(currentBoard._id, {
- $set: {
- [`members.${memberIndex}.isActive`]: false,
- },
- });
+ const memberId = this.userId;
+ currentBoard.removeMember(memberId);
Popup.close();
}),
'click .js-leave-member'() {
@@ -209,26 +196,7 @@ Template.addMemberPopup.events({
'click .js-select-member'() {
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,
- isAdmin: false,
- isActive: true,
- },
- },
- });
- } else {
- const memberIndex = getMemberIndex(currentBoard, userId);
-
- Boards.update(currentBoard._id, {
- $set: {
- [`members.${memberIndex}.isActive`]: true,
- },
- });
- }
+ currentBoard.addMember(userId);
Popup.close();
},
});
@@ -240,14 +208,9 @@ Template.addMemberPopup.onRendered(function() {
Template.changePermissionsPopup.events({
'click .js-set-admin, click .js-set-normal'(event) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
- const memberIndex = getMemberIndex(currentBoard, this.userId);
+ const memberId = this.userId;
const isAdmin = $(event.currentTarget).hasClass('js-set-admin');
-
- Boards.update(currentBoard._id, {
- $set: {
- [`members.${memberIndex}.isAdmin`]: isAdmin,
- },
- });
+ currentBoard.setMemberPermission(memberId, isAdmin);
Popup.back(1);
},
});
diff --git a/client/components/sidebar/sidebarArchives.js b/client/components/sidebar/sidebarArchives.js
index f2597c3c..52d42edb 100644
--- a/client/components/sidebar/sidebarArchives.js
+++ b/client/components/sidebar/sidebarArchives.js
@@ -29,8 +29,8 @@ BlazeComponent.extendComponent({
events() {
return [{
'click .js-restore-card'() {
- const cardId = this.currentData()._id;
- Cards.update(cardId, {$set: {archived: false}});
+ const card = this.currentData();
+ card.restore();
},
'click .js-delete-card': Popup.afterConfirm('cardDelete', function() {
const cardId = this._id;
@@ -38,8 +38,8 @@ BlazeComponent.extendComponent({
Popup.close();
}),
'click .js-restore-list'() {
- const listId = this.currentData()._id;
- Lists.update(listId, {$set: {archived: false}});
+ const list = this.currentData();
+ list.restore();
},
}];
},
diff --git a/client/components/sidebar/sidebarFilters.js b/client/components/sidebar/sidebarFilters.js
index 335cc7d6..babd2f1e 100644
--- a/client/components/sidebar/sidebarFilters.js
+++ b/client/components/sidebar/sidebarFilters.js
@@ -30,9 +30,9 @@ BlazeComponent.extendComponent({
},
}).register('filterSidebar');
-function updateSelectedCards(query) {
+function mutateSelectedCards(mutationName, ...args) {
Cards.find(MultiSelection.getMongoSelector()).forEach((card) => {
- Cards.update(card._id, query);
+ card[mutationName](...args);
});
}
@@ -67,47 +67,34 @@ BlazeComponent.extendComponent({
'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, (bool) => !bool))
- operation = '$addToSet';
- else {
+
+ if (_.every(mappedSelection)) {
+ mutateSelectedCards('addLabel', labelId);
+ } else if (_.every(mappedSelection, (bool) => !bool)) {
+ mutateSelectedCards('removeLabel', labelId);
+ } else {
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);
}
-
- updateSelectedCards({
- [operation]: {
- labelIds: labelId,
- },
- });
},
'click .js-toggle-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, (bool) => !bool))
- operation = '$addToSet';
- else {
+ if (_.every(mappedSelection)) {
+ mutateSelectedCards('assignMember', memberId);
+ } else if (_.every(mappedSelection, (bool) => !bool)) {
+ mutateSelectedCards('unassignMember', memberId);
+ } else {
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);
}
-
- updateSelectedCards({
- [operation]: {
- members: memberId,
- },
- });
},
'click .js-archive-selection'() {
- updateSelectedCards({$set: {archived: true}});
+ mutateSelectedCards('archive');
},
}];
},
@@ -115,22 +102,22 @@ BlazeComponent.extendComponent({
Template.disambiguateMultiLabelPopup.events({
'click .js-remove-label'() {
- updateSelectedCards({$pull: {labelIds: this._id}});
+ mutateSelectedCards('removeLabel', this._id);
Popup.close();
},
'click .js-add-label'() {
- updateSelectedCards({$addToSet: {labelIds: this._id}});
+ mutateSelectedCards('addLabel', this._id);
Popup.close();
},
});
Template.disambiguateMultiMemberPopup.events({
'click .js-unassign-member'() {
- updateSelectedCards({$pull: {members: this._id}});
+ mutateSelectedCards('assignMember', this._id);
Popup.close();
},
'click .js-assign-member'() {
- updateSelectedCards({$addToSet: {members: this._id}});
+ mutateSelectedCards('unassignMember', this._id);
Popup.close();
},
});