diff --git a/common/script/index.js b/common/script/index.js index 7db322f6e7..8706290bca 100644 --- a/common/script/index.js +++ b/common/script/index.js @@ -814,10 +814,13 @@ api.wrap = function(user, main) { message: i18n.t('messageTaskNotFound', req.language) }) : void 0; } - _.merge(task, _.omit(req.body, ['checklist', 'id', 'type'])); + _.merge(task, _.omit(req.body, ['checklist', 'reminders', 'id', 'type'])); if (req.body.checklist) { task.checklist = req.body.checklist; } + if (req.body.reminders) { + task.reminders = req.body.reminders; + } if (typeof task.markModified === "function") { task.markModified('tags'); } diff --git a/test/api/v2/user/PUT-user.test.js b/test/api/v2/user/PUT-user.test.js index 033a278646..e4774528ae 100644 --- a/test/api/v2/user/PUT-user.test.js +++ b/test/api/v2/user/PUT-user.test.js @@ -175,4 +175,27 @@ describe('PUT /user', () => { }); }); }); + + context('Improvement Categories', () => { + it('sets valid categories', async () => { + await user.put('/user', { + 'preferences.improvementCategories': ['work', 'school'], + }); + + await user.sync(); + + expect(user.preferences.improvementCategories).to.eql(['work', 'school']); + }); + + it('discards invalid categories', async () => { + await expect(user.put('/user', { + 'preferences.improvementCategories': ['work', 'procrastination', 'school'], + })).to.eventually.be.rejected.and.eql({ + code: 400, + text: [ + 'Validator failed for path `preferences.improvementCategories` with value `work,procrastination,school`', + ], + }); + }); + }); }); diff --git a/website/src/controllers/api-v2/user.js b/website/src/controllers/api-v2/user.js index 201d1d034d..d06bb96288 100644 --- a/website/src/controllers/api-v2/user.js +++ b/website/src/controllers/api-v2/user.js @@ -355,7 +355,15 @@ api.update = (req, res, next) => { user.save((err) => { if (!_.isEmpty(errors)) return res.json(401, {err: errors}); - if (err) return next(err); + if (err) { + if (err.name == 'ValidationError') { + let errorMessages = _.map(_.values(err.errors), (error) => { + return error.message; + }); + return res.json(400, {err: errorMessages}); + } + return next(err); + } res.json(200, user); user = errors = null; diff --git a/website/src/models/task.js b/website/src/models/task.js index 8ae24e353a..97a0e1e7c6 100644 --- a/website/src/models/task.js +++ b/website/src/models/task.js @@ -28,7 +28,12 @@ var TaskSchema = { broken: String, // CHALLENGE_DELETED, TASK_DELETED, UNSUBSCRIBED, CHALLENGE_CLOSED winner: String // user.profile.name // group: {type: 'Strign', ref: 'Group'} // if we restore this, rename `id` above to `challenge` - } + }, + reminders: [{ + id: {type:String,'default':shared.uuid}, + startDate: Date, + time: Date + }] }; var HabitSchema = new Schema( diff --git a/website/src/models/user.js b/website/src/models/user.js index f9ac573179..9c2f11bcfd 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -390,7 +390,14 @@ var UserSchema = new Schema({ hatchPet: {type: Boolean, 'default': false}, raisePet: {type: Boolean, 'default': false}, streak: {type: Boolean, 'default': false} - } + }, + improvementCategories: { + type: Array, + validate: (categories) => { + const validCategories = ['work', 'exercise', 'healthWellness', 'school', 'teams', 'chores', 'creativity']; + let isValidCategory = categories.every(category => validCategories.indexOf(category) !== -1); + return isValidCategory; + }} }, profile: { blurb: String,