diff options
Diffstat (limited to 'models')
-rw-r--r-- | models/boards.js | 12 | ||||
-rw-r--r-- | models/cards.js | 6 | ||||
-rw-r--r-- | models/lists.js | 10 | ||||
-rw-r--r-- | models/swimlanes.js | 219 |
4 files changed, 243 insertions, 4 deletions
diff --git a/models/boards.js b/models/boards.js index 594bb7b9..84a715fb 100644 --- a/models/boards.js +++ b/models/boards.js @@ -31,6 +31,14 @@ Boards.attachSchema(new SimpleSchema({ } }, }, + view: { + type: String, + autoValue() { // eslint-disable-line consistent-return + if (this.isInsert) { + return 'board-view-swimlanes'; + } + }, + }, createdAt: { type: Date, autoValue() { // eslint-disable-line consistent-return @@ -187,6 +195,10 @@ Boards.helpers({ return Lists.find({ boardId: this._id, archived: false }, { sort: { sort: 1 } }); }, + swimlanes() { + return Swimlanes.find({ boardId: this._id, archived: false }, { sort: { sort: 1 } }); + }, + hasOvertimeCards(){ const card = Cards.findOne({isOvertime: true, boardId: this._id, archived: false} ); return card !== undefined; diff --git a/models/cards.js b/models/cards.js index 8676dfdc..d175a430 100644 --- a/models/cards.js +++ b/models/cards.js @@ -18,6 +18,9 @@ Cards.attachSchema(new SimpleSchema({ listId: { type: String, }, + swimlaneId: { + type: String, + }, // The system could work without this `boardId` information (we could deduce // the board identifier from the card), but it would make the system more // difficult to manage and less efficient. @@ -216,9 +219,10 @@ Cards.mutations({ return {$set: {description}}; }, - move(listId, sortIndex) { + move(swimlaneId, listId, sortIndex) { const list = Lists.findOne(listId); const mutatedFields = { + swimlaneId, listId, boardId: list.boardId, }; diff --git a/models/lists.js b/models/lists.js index a5f4791b..7ed27361 100644 --- a/models/lists.js +++ b/models/lists.js @@ -75,11 +75,15 @@ Lists.allow({ }); Lists.helpers({ - cards() { - return Cards.find(Filter.mongoSelector({ + cards(swimlaneId) { + const selector = { listId: this._id, archived: false, - }), { sort: ['sort'] }); + }; + if (swimlaneId) + selector.swimlaneId = swimlaneId; + return Cards.find(Filter.mongoSelector(selector, + { sort: ['sort'] })); }, allCards() { diff --git a/models/swimlanes.js b/models/swimlanes.js new file mode 100644 index 00000000..68cd77da --- /dev/null +++ b/models/swimlanes.js @@ -0,0 +1,219 @@ +Swimlanes = new Mongo.Collection('swimlanes'); + +Swimlanes.attachSchema(new SimpleSchema({ + title: { + type: String, + }, + archived: { + type: Boolean, + autoValue() { // eslint-disable-line consistent-return + if (this.isInsert && !this.isSet) { + return false; + } + }, + }, + boardId: { + type: String, + }, + createdAt: { + type: Date, + autoValue() { // eslint-disable-line consistent-return + if (this.isInsert) { + return new Date(); + } else { + this.unset(); + } + }, + }, + sort: { + type: Number, + decimal: true, + // XXX We should probably provide a default + optional: true, + }, + updatedAt: { + type: Date, + optional: true, + autoValue() { // eslint-disable-line consistent-return + if (this.isUpdate) { + return new Date(); + } else { + this.unset(); + } + }, + }, +})); + +Swimlanes.allow({ + insert(userId, doc) { + return allowIsBoardMemberNonComment(userId, Boards.findOne(doc.boardId)); + }, + update(userId, doc) { + return allowIsBoardMemberNonComment(userId, Boards.findOne(doc.boardId)); + }, + remove(userId, doc) { + return allowIsBoardMemberNonComment(userId, Boards.findOne(doc.boardId)); + }, + fetch: ['boardId'], +}); + +Swimlanes.helpers({ + cards() { + return Cards.find(Filter.mongoSelector({ + swimlaneId: this._id, + archived: false, + }), { sort: ['sort'] }); + }, + + allCards() { + return Cards.find({ swimlaneId: this._id }); + }, + + board() { + return Boards.findOne(this.boardId); + }, +}); + +Swimlanes.mutations({ + rename(title) { + return { $set: { title } }; + }, + + archive() { + return { $set: { archived: true } }; + }, + + restore() { + return { $set: { archived: false } }; + }, +}); + +Swimlanes.hookOptions.after.update = { fetchPrevious: false }; + +if (Meteor.isServer) { + Meteor.startup(() => { + Swimlanes._collection._ensureIndex({ boardId: 1 }); + }); + + Swimlanes.after.insert((userId, doc) => { + Activities.insert({ + userId, + type: 'swimlane', + activityType: 'createSwimlane', + boardId: doc.boardId, + swimlaneId: doc._id, + }); + }); + + Swimlanes.before.remove((userId, doc) => { + Activities.insert({ + userId, + type: 'swimlane', + activityType: 'removeSwimlane', + boardId: doc.boardId, + swimlaneId: doc._id, + title: doc.title, + }); + }); + + Swimlanes.after.update((userId, doc) => { + if (doc.archived) { + Activities.insert({ + userId, + type: 'swimlane', + activityType: 'archivedSwimlane', + swimlaneId: doc._id, + boardId: doc.boardId, + }); + } + }); +} + +//SWIMLANE REST API +if (Meteor.isServer) { + JsonRoutes.add('GET', '/api/boards/:boardId/swimlanes', function (req, res, next) { + try { + const paramBoardId = req.params.boardId; + Authentication.checkBoardAccess( req.userId, paramBoardId); + + JsonRoutes.sendResult(res, { + code: 200, + data: Swimlanes.find({ boardId: paramBoardId, archived: false }).map(function (doc) { + return { + _id: doc._id, + title: doc.title, + }; + }), + }); + } + catch (error) { + JsonRoutes.sendResult(res, { + code: 200, + data: error, + }); + } + }); + + JsonRoutes.add('GET', '/api/boards/:boardId/swimlanes/:swimlaneId', function (req, res, next) { + try { + const paramBoardId = req.params.boardId; + const paramSwimlaneId = req.params.swimlaneId; + Authentication.checkBoardAccess( req.userId, paramBoardId); + JsonRoutes.sendResult(res, { + code: 200, + data: Swimlanes.findOne({ _id: paramSwimlaneId, boardId: paramBoardId, archived: false }), + }); + } + catch (error) { + JsonRoutes.sendResult(res, { + code: 200, + data: error, + }); + } + }); + + JsonRoutes.add('POST', '/api/boards/:boardId/swimlanes', function (req, res, next) { + try { + Authentication.checkUserId( req.userId); + const paramBoardId = req.params.boardId; + const id = Swimlanes.insert({ + title: req.body.title, + boardId: paramBoardId, + }); + JsonRoutes.sendResult(res, { + code: 200, + data: { + _id: id, + }, + }); + } + catch (error) { + JsonRoutes.sendResult(res, { + code: 200, + data: error, + }); + } + }); + + JsonRoutes.add('DELETE', '/api/boards/:boardId/swimlanes/:swimlaneId', function (req, res, next) { + try { + Authentication.checkUserId( req.userId); + const paramBoardId = req.params.boardId; + const paramSwimlaneId = req.params.swimlaneId; + Swimlanes.remove({ _id: paramSwimlaneId, boardId: paramBoardId }); + JsonRoutes.sendResult(res, { + code: 200, + data: { + _id: paramSwimlaneId, + }, + }); + } + catch (error) { + JsonRoutes.sendResult(res, { + code: 200, + data: error, + }); + } + }); + +} |