diff options
Diffstat (limited to 'models')
-rw-r--r-- | models/activities.js | 7 | ||||
-rw-r--r-- | models/cards.js | 30 | ||||
-rw-r--r-- | models/checklists.js | 164 |
3 files changed, 201 insertions, 0 deletions
diff --git a/models/activities.js b/models/activities.js index aa2ea3ec..7d262ec6 100644 --- a/models/activities.js +++ b/models/activities.js @@ -35,6 +35,9 @@ Activities.helpers({ attachment() { return Attachments.findOne(this.attachmentId); }, + checklist() { + return Checklists.findOne(this.checklistId); + }, }); Activities.before.insert((userId, doc) => { @@ -102,6 +105,10 @@ if (Meteor.isServer) { const attachment = activity.attachment(); params.attachment = attachment._id; } + if (activity.checklistId) { + const checklist = activity.checklist(); + params.checklist = checklist.title; + } if (board) { const watchingUsers = _.pluck(_.where(board.watchers, {level: 'watching'}), 'userId'); const trackingUsers = _.pluck(_.where(board.watchers, {level: 'tracking'}), 'userId'); diff --git a/models/cards.js b/models/cards.js index 9e7d58c8..f6bd0b06 100644 --- a/models/cards.js +++ b/models/cards.js @@ -141,6 +141,36 @@ Cards.helpers({ return cover && cover.url() && cover; }, + checklists() { + return Checklists.find({ cardId: this._id }, { sort: { createdAt: 1 }}); + }, + + checklistItemCount() { + const checklists = this.checklists().fetch(); + return checklists.map((checklist) => { + return checklist.itemCount(); + }).reduce((prev, next) => { + return prev + next; + }, 0); + }, + + checklistFinishedCount() { + const checklists = this.checklists().fetch(); + return checklists.map((checklist) => { + return checklist.finishedCount(); + }).reduce((prev, next) => { + return prev + next; + }, 0); + }, + + checklistFinished() { + return this.hasChecklist() && this.checklistItemCount() === this.checklistFinishedCount(); + }, + + hasChecklist() { + return this.checklistItemCount() !== 0; + }, + absoluteUrl() { const board = this.board(); return FlowRouter.url('card', { diff --git a/models/checklists.js b/models/checklists.js new file mode 100644 index 00000000..35be4dcc --- /dev/null +++ b/models/checklists.js @@ -0,0 +1,164 @@ +Checklists = new Mongo.Collection('checklists'); + +Checklists.attachSchema(new SimpleSchema({ + cardId: { + type: String, + }, + title: { + type: String, + }, + items: { + type: [Object], + defaultValue: [], + }, + 'items.$._id': { + type: String, + }, + 'items.$.title': { + type: String, + }, + 'items.$.isFinished': { + type: Boolean, + defaultValue: false, + }, + finishedAt: { + type: Date, + optional: true, + }, + createdAt: { + type: Date, + denyUpdate: false, + }, +})); + +Checklists.helpers({ + itemCount () { + return this.items.length; + }, + finishedCount () { + return this.items.filter((item) => { + return item.isFinished; + }).length; + }, + isFinished () { + return 0 !== this.itemCount() && this.itemCount() === this.finishedCount(); + }, + getItem (_id) { + return _.findWhere(this.items, { _id }); + }, + itemIndex(itemId) { + return _.pluck(this.items, '_id').indexOf(itemId); + }, +}); + +Checklists.allow({ + insert(userId, doc) { + return allowIsBoardMemberByCard(userId, Cards.findOne(doc.cardId)); + }, + update(userId, doc) { + return allowIsBoardMemberByCard(userId, Cards.findOne(doc.cardId)); + }, + remove(userId, doc) { + return allowIsBoardMemberByCard(userId, Cards.findOne(doc.cardId)); + }, + fetch: ['userId', 'cardId'], +}); + +Checklists.before.insert((userId, doc) => { + doc.createdAt = new Date(); + if (!doc.userId) { + doc.userId = userId; + } +}); + +Checklists.mutations({ + //for checklist itself + setTitle(title){ + return { $set: { title }}; + }, + //for items in checklist + addItem(title) { + const itemCount = this.itemCount(); + const _id = `${this._id}${itemCount}`; + return { $addToSet: {items: {_id, title, isFinished: false}} }; + }, + removeItem(itemId) { + return {$pull: {items: {_id : itemId}}}; + }, + editItem(itemId, title) { + if (this.getItem(itemId)) { + const itemIndex = this.itemIndex(itemId); + return { + $set: { + [`items.${itemIndex}.title`]: title, + }, + }; + } + return {}; + }, + finishItem(itemId) { + if (this.getItem(itemId)) { + const itemIndex = this.itemIndex(itemId); + return { + $set: { + [`items.${itemIndex}.isFinished`]: true, + }, + }; + } + return {}; + }, + resumeItem(itemId) { + if (this.getItem(itemId)) { + const itemIndex = this.itemIndex(itemId); + return { + $set: { + [`items.${itemIndex}.isFinished`]: false, + }, + }; + } + return {}; + }, + toggleItem(itemId) { + const item = this.getItem(itemId); + if (item) { + const itemIndex = this.itemIndex(itemId); + return { + $set: { + [`items.${itemIndex}.isFinished`]: !item.isFinished, + }, + }; + } + return {}; + }, +}); + +if (Meteor.isServer) { + Checklists.after.insert((userId, doc) => { + Activities.insert({ + userId, + activityType: 'addChecklist', + cardId: doc.cardId, + boardId: Cards.findOne(doc.cardId).boardId, + checklistId: doc._id, + }); + }); + + //TODO: so there will be no activity for adding item into checklist, maybe will be implemented in the future. + // Checklists.after.update((userId, doc) => { + // console.log('update:', doc) + // Activities.insert({ + // userId, + // activityType: 'addChecklist', + // boardId: doc.boardId, + // cardId: doc.cardId, + // checklistId: doc._id, + // }); + // }); + + Checklists.before.remove((userId, doc) => { + const activity = Activities.findOne({ checklistId: doc._id }); + if (activity) { + Activities.remove(activity._id); + } + }); +} |