summaryrefslogtreecommitdiffstats
path: root/models
diff options
context:
space:
mode:
Diffstat (limited to 'models')
-rw-r--r--models/activities.js8
-rw-r--r--models/boards.js4
-rw-r--r--models/cards.js66
-rw-r--r--models/customFields.js132
4 files changed, 210 insertions, 0 deletions
diff --git a/models/activities.js b/models/activities.js
index 3f1d28ae..f64b53f8 100644
--- a/models/activities.js
+++ b/models/activities.js
@@ -44,6 +44,9 @@ Activities.helpers({
checklistItem() {
return ChecklistItems.findOne(this.checklistItemId);
},
+ customField() {
+ return CustomFields.findOne(this.customFieldId);
+ },
});
Activities.before.insert((userId, doc) => {
@@ -60,6 +63,7 @@ if (Meteor.isServer) {
Activities._collection._ensureIndex({ boardId: 1, createdAt: -1 });
Activities._collection._ensureIndex({ commentId: 1 }, { partialFilterExpression: { commentId: { $exists: true } } });
Activities._collection._ensureIndex({ attachmentId: 1 }, { partialFilterExpression: { attachmentId: { $exists: true } } });
+ Activities._collection._ensureIndex({ customFieldId: 1 }, { partialFilterExpression: { customFieldId: { $exists: true } } });
});
Activities.after.insert((userId, doc) => {
@@ -127,6 +131,10 @@ if (Meteor.isServer) {
const checklistItem = activity.checklistItem();
params.checklistItem = checklistItem.title;
}
+ if (activity.customFieldId) {
+ const customField = activity.customField();
+ params.customField = customField.name;
+ }
if (board) {
const watchingUsers = _.pluck(_.where(board.watchers, {level: 'watching'}), 'userId');
const trackingUsers = _.pluck(_.where(board.watchers, {level: 'tracking'}), 'userId');
diff --git a/models/boards.js b/models/boards.js
index c863c5ce..44ce0b62 100644
--- a/models/boards.js
+++ b/models/boards.js
@@ -249,6 +249,10 @@ Boards.helpers({
return `board-color-${this.color}`;
},
+ customFields() {
+ return CustomFields.find({ boardId: this._id }, { sort: { name: 1 } });
+ },
+
// XXX currently mutations return no value so we have an issue when using addLabel in import
// XXX waiting on https://github.com/mquandalle/meteor-collection-mutations/issues/1 to remove...
pushLabel(name, color) {
diff --git a/models/cards.js b/models/cards.js
index 01f79847..8b917ee3 100644
--- a/models/cards.js
+++ b/models/cards.js
@@ -41,6 +41,21 @@ Cards.attachSchema(new SimpleSchema({
}
},
},
+ customFields: {
+ type: [Object],
+ optional: true,
+ },
+ 'customFields.$': {
+ type: new SimpleSchema({
+ _id: {
+ type: String,
+ },
+ value: {
+ type: Match.OneOf(String,Number,Boolean,Date),
+ optional: true,
+ },
+ })
+ },
dateLastActivity: {
type: Date,
autoValue() {
@@ -192,6 +207,31 @@ Cards.helpers({
return this.checklistItemCount() !== 0;
},
+ customFieldIndex(customFieldId) {
+ return _.pluck(this.customFields, '_id').indexOf(customFieldId);
+ },
+
+ // customFields with definitions
+ customFieldsWD() {
+
+ // get all definitions
+ const definitions = CustomFields.find({
+ boardId: this.boardId,
+ }).fetch();
+
+ // match right definition to each field
+ return this.customFields.map((customField) => {
+ return {
+ _id: customField._id,
+ value: customField.value,
+ definition: definitions.find((definition) => {
+ return definition._id == customField._id;
+ })
+ }
+ });
+
+ },
+
absoluteUrl() {
const board = this.board();
return FlowRouter.url('card', {
@@ -271,6 +311,32 @@ Cards.mutations({
}
},
+ assignCustomField(customFieldId) {
+ return {$addToSet: {customFields: {_id: customFieldId, value: null}}};
+ },
+
+ unassignCustomField(customFieldId) {
+ return {$pull: {customFields: {_id: customFieldId}}};
+ },
+
+ toggleCustomField(customFieldId) {
+ if (this.customFields && this.customFieldIndex(customFieldId) > -1) {
+ return this.unassignCustomField(customFieldId);
+ } else {
+ return this.assignCustomField(customFieldId);
+ }
+ },
+
+ setCustomField(customFieldId, value) {
+ // todo
+ const index = this.customFieldIndex(customFieldId);
+ if (index > -1) {
+ var update = {$set: {}};
+ update.$set["customFields." + index + ".value"] = value;
+ return update;
+ }
+ },
+
setCover(coverId) {
return {$set: {coverId}};
},
diff --git a/models/customFields.js b/models/customFields.js
new file mode 100644
index 00000000..8b0abef4
--- /dev/null
+++ b/models/customFields.js
@@ -0,0 +1,132 @@
+CustomFields = new Mongo.Collection('customFields');
+
+CustomFields.attachSchema(new SimpleSchema({
+ boardId: {
+ type: String,
+ },
+ name: {
+ type: String,
+ },
+ type: {
+ type: String,
+ allowedValues: ['text', 'number', 'checkbox', 'date', 'dropdown']
+ },
+ settings: {
+ type: Object,
+ },
+ 'settings.dropdownItems': {
+ type: [Object],
+ optional: true
+ },
+ 'settings.dropdownItems.$': {
+ type: new SimpleSchema({
+ _id: {
+ type: String,
+ },
+ name: {
+ type: String,
+ },
+ })
+ },
+ showOnCard: {
+ type: Boolean,
+ }
+}));
+
+CustomFields.allow({
+ insert(userId, doc) {
+ return allowIsBoardMember(userId, Boards.findOne(doc.boardId));
+ },
+ update(userId, doc) {
+ return allowIsBoardMember(userId, Boards.findOne(doc.boardId));
+ },
+ remove(userId, doc) {
+ return allowIsBoardMember(userId, Boards.findOne(doc.boardId));
+ },
+ fetch: ['userId', 'boardId'],
+});
+
+// not sure if we need this?
+//CustomFields.hookOptions.after.update = { fetchPrevious: false };
+
+function customFieldCreation(userId, doc){
+ Activities.insert({
+ userId,
+ activityType: 'createCustomField',
+ boardId: doc.boardId,
+ customFieldId: doc._id,
+ });
+}
+
+if (Meteor.isServer) {
+ /*Meteor.startup(() => {
+ CustomFields._collection._ensureIndex({ boardId: 1});
+ });*/
+
+ CustomFields.after.insert((userId, doc) => {
+ customFieldCreation(userId, doc);
+ });
+
+ CustomFields.after.remove((userId, doc) => {
+ Activities.remove({
+ customFieldId: doc._id,
+ });
+ });
+}
+
+//CUSTOM FIELD REST API
+if (Meteor.isServer) {
+ JsonRoutes.add('GET', '/api/boards/:boardId/custom-fields', function (req, res, next) {
+ Authentication.checkUserId( req.userId);
+ const paramBoardId = req.params.boardId;
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: CustomFields.find({ boardId: paramBoardId })
+ });
+ });
+
+ JsonRoutes.add('GET', '/api/boards/:boardId/custom-fields/:customFieldId', function (req, res, next) {
+ Authentication.checkUserId( req.userId);
+ const paramBoardId = req.params.boardId;
+ const paramCustomFieldId = req.params.customFieldId;
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: CustomFields.findOne({ _id: paramCustomFieldId, boardId: paramBoardId }),
+ });
+ });
+
+ JsonRoutes.add('POST', '/api/boards/:boardId/custom-fields', function (req, res, next) {
+ Authentication.checkUserId( req.userId);
+ const paramBoardId = req.params.boardId;
+ const id = CustomFields.direct.insert({
+ name: req.body.name,
+ type: req.body.type,
+ settings: req.body.settings,
+ showOnCard: req.body.showOnCard,
+ boardId: paramBoardId,
+ });
+
+ const customField = CustomFields.findOne({_id: id, boardId: paramBoardId });
+ customFieldCreation(req.body.authorId, customField);
+
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: {
+ _id: id,
+ },
+ });
+ });
+
+ JsonRoutes.add('DELETE', '/api/boards/:boardId/custom-fields/:customFieldId', function (req, res, next) {
+ Authentication.checkUserId( req.userId);
+ const paramBoardId = req.params.boardId;
+ const id = req.params.customFieldId;
+ CustomFields.remove({ _id: id, boardId: paramBoardId });
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: {
+ _id: id,
+ },
+ });
+ });
+}