diff options
Diffstat (limited to 'models/lists.js')
-rw-r--r-- | models/lists.js | 187 |
1 files changed, 184 insertions, 3 deletions
diff --git a/models/lists.js b/models/lists.js index 6f6996cb..1a0910c2 100644 --- a/models/lists.js +++ b/models/lists.js @@ -1,10 +1,19 @@ Lists = new Mongo.Collection('lists'); +/** + * A list (column) in the Wekan board. + */ Lists.attachSchema(new SimpleSchema({ title: { + /** + * the title of the list + */ type: String, }, archived: { + /** + * is the list archived + */ type: Boolean, autoValue() { // eslint-disable-line consistent-return if (this.isInsert && !this.isSet) { @@ -13,9 +22,22 @@ Lists.attachSchema(new SimpleSchema({ }, }, boardId: { + /** + * the board associated to this list + */ type: String, }, + swimlaneId: { + /** + * the swimlane associated to this list. Used for templates + */ + type: String, + defaultValue: '', + }, createdAt: { + /** + * creation date + */ type: Date, autoValue() { // eslint-disable-line consistent-return if (this.isInsert) { @@ -26,12 +48,18 @@ Lists.attachSchema(new SimpleSchema({ }, }, sort: { + /** + * is the list sorted + */ type: Number, decimal: true, // XXX We should probably provide a default optional: true, }, updatedAt: { + /** + * last update of the list + */ type: Date, optional: true, autoValue() { // eslint-disable-line consistent-return @@ -43,38 +71,102 @@ Lists.attachSchema(new SimpleSchema({ }, }, wipLimit: { + /** + * WIP object, see below + */ type: Object, optional: true, }, 'wipLimit.value': { + /** + * value of the WIP + */ type: Number, decimal: false, defaultValue: 1, }, 'wipLimit.enabled': { + /** + * is the WIP enabled + */ type: Boolean, defaultValue: false, }, 'wipLimit.soft': { + /** + * is the WIP a soft or hard requirement + */ type: Boolean, defaultValue: false, }, + color: { + /** + * the color of the list + */ + type: String, + optional: true, + // silver is the default, so it is left out + allowedValues: [ + 'white', 'green', 'yellow', 'orange', 'red', 'purple', + 'blue', 'sky', 'lime', 'pink', 'black', + 'peachpuff', 'crimson', 'plum', 'darkgreen', + 'slateblue', 'magenta', 'gold', 'navy', 'gray', + 'saddlebrown', 'paleturquoise', 'mistyrose', 'indigo', + ], + }, + type: { + /** + * The type of list + */ + type: String, + defaultValue: 'list', + }, })); Lists.allow({ insert(userId, doc) { - return allowIsBoardMemberNonComment(userId, Boards.findOne(doc.boardId)); + return allowIsBoardMemberCommentOnly(userId, Boards.findOne(doc.boardId)); }, update(userId, doc) { - return allowIsBoardMemberNonComment(userId, Boards.findOne(doc.boardId)); + return allowIsBoardMemberCommentOnly(userId, Boards.findOne(doc.boardId)); }, remove(userId, doc) { - return allowIsBoardMemberNonComment(userId, Boards.findOne(doc.boardId)); + return allowIsBoardMemberCommentOnly(userId, Boards.findOne(doc.boardId)); }, fetch: ['boardId'], }); Lists.helpers({ + copy(boardId, swimlaneId) { + const oldId = this._id; + const oldSwimlaneId = this.swimlaneId || null; + this.boardId = boardId; + this.swimlaneId = swimlaneId; + + let _id = null; + existingListWithSameName = Lists.findOne({ + boardId, + title: this.title, + archived: false, + }); + if (existingListWithSameName) { + _id = existingListWithSameName._id; + } else { + delete this._id; + delete this.swimlaneId; + _id = Lists.insert(this); + } + + // Copy all cards in list + Cards.find({ + swimlaneId: oldSwimlaneId, + listId: oldId, + archived: false, + }).forEach((card) => { + card.copy(boardId, swimlaneId, _id); + }); + }, + cards(swimlaneId) { const selector = { listId: this._id, @@ -86,6 +178,17 @@ Lists.helpers({ { sort: ['sort'] }); }, + cardsUnfiltered(swimlaneId) { + const selector = { + listId: this._id, + archived: false, + }; + if (swimlaneId) + selector.swimlaneId = swimlaneId; + return Cards.find(selector, + { sort: ['sort'] }); + }, + allCards() { return Cards.find({ listId: this._id }); }, @@ -104,6 +207,20 @@ Lists.helpers({ return list.wipLimit[option] ? list.wipLimit[option] : 0; // Necessary check to avoid exceptions for the case where the doc doesn't have the wipLimit field yet set } }, + + colorClass() { + if (this.color) + return this.color; + return ''; + }, + + isTemplateList() { + return this.type === 'template-list'; + }, + + remove() { + Lists.remove({ _id: this._id}); + }, }); Lists.mutations({ @@ -112,10 +229,20 @@ Lists.mutations({ }, archive() { + if (this.isTemplateList()) { + this.cards().forEach((card) => { + return card.archive(); + }); + } return { $set: { archived: true } }; }, restore() { + if (this.isTemplateList()) { + this.allCards().forEach((card) => { + return card.restore(); + }); + } return { $set: { archived: false } }; }, @@ -130,6 +257,17 @@ Lists.mutations({ setWipLimit(limit) { return { $set: { 'wipLimit.value': limit } }; }, + + setColor(newColor) { + if (newColor === 'silver') { + newColor = null; + } + return { + $set: { + color: newColor, + }, + }; + }, }); Meteor.methods({ @@ -176,6 +314,12 @@ if (Meteor.isServer) { }); Lists.before.remove((userId, doc) => { + const cards = Cards.find({ listId: doc._id }); + if (cards) { + cards.forEach((card) => { + Cards.remove(card._id); + }); + } Activities.insert({ userId, type: 'list', @@ -201,6 +345,14 @@ if (Meteor.isServer) { //LISTS REST API if (Meteor.isServer) { + /** + * @operation get_all_lists + * @summary Get the list of Lists attached to a board + * + * @param {string} boardId the board ID + * @return_type [{_id: string, + * title: string}] + */ JsonRoutes.add('GET', '/api/boards/:boardId/lists', function (req, res) { try { const paramBoardId = req.params.boardId; @@ -224,6 +376,14 @@ if (Meteor.isServer) { } }); + /** + * @operation get_list + * @summary Get a List attached to a board + * + * @param {string} boardId the board ID + * @param {string} listId the List ID + * @return_type Lists + */ JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId', function (req, res) { try { const paramBoardId = req.params.boardId; @@ -242,13 +402,23 @@ if (Meteor.isServer) { } }); + /** + * @operation new_list + * @summary Add a List to a board + * + * @param {string} boardId the board ID + * @param {string} title the title of the List + * @return_type {_id: string} + */ JsonRoutes.add('POST', '/api/boards/:boardId/lists', function (req, res) { try { Authentication.checkUserId( req.userId); const paramBoardId = req.params.boardId; + const board = Boards.findOne(paramBoardId); const id = Lists.insert({ title: req.body.title, boardId: paramBoardId, + sort: board.lists().count(), }); JsonRoutes.sendResult(res, { code: 200, @@ -265,6 +435,17 @@ if (Meteor.isServer) { } }); + /** + * @operation delete_list + * @summary Delete a List + * + * @description This **deletes** a list from a board. + * The list is not put in the recycle bin. + * + * @param {string} boardId the board ID + * @param {string} listId the ID of the list to remove + * @return_type {_id: string} + */ JsonRoutes.add('DELETE', '/api/boards/:boardId/lists/:listId', function (req, res) { try { Authentication.checkUserId( req.userId); |