Files
habitica/website/src/models/task.js
Matteo Pagliazzi 955b0f042b fix tests
2015-12-06 17:07:29 +01:00

119 lines
4.5 KiB
JavaScript

import mongoose from 'mongoose';
import shared from '../../../common';
import validator from 'validator';
import moment from 'moment';
import baseModel from '../libs/api-v3/baseModel';
import _ from 'lodash';
let Schema = mongoose.Schema;
let discriminatorOptions = {
discriminatorKey: 'type', // the key that distinguishes task types
};
let subDiscriminatorOptions = _.defaults(_.cloneDeep(discriminatorOptions), {_id: false});
export let tasksTypes = ['habit', 'daily', 'todo', 'reward'];
export let TaskSchema = new Schema({
type: {type: String, enum: tasksTypes, required: true, default: tasksTypes[0]},
text: {type: String, required: true},
notes: {type: String, default: ''},
tags: [{
type: String,
validate: [validator.isUUID, 'Invalid uuid.'],
}],
value: {type: Number, default: 0}, // redness or cost for rewards
priority: {type: Number, default: 1, required: true}, // TODO enum?
attribute: {type: String, default: 'str', enum: ['str', 'con', 'int', 'per']},
userId: {type: String, ref: 'User'}, // When null it belongs to a challenge
challenge: {
id: {type: String, ref: 'Challenge'},
taskId: {type: String, ref: 'Task'}, // When null but challenge.id defined it's the original task
broken: String, // CHALLENGE_DELETED, TASK_DELETED, UNSUBSCRIBED, CHALLENGE_CLOSED TODO enum
winner: String, // user.profile.name TODO necessary?
},
}, _.defaults({
minimize: true, // So empty objects are returned
strict: true,
}, discriminatorOptions));
TaskSchema.plugin(baseModel, {
// TODO checklist fields editable?
// TODO value should be settable only for rewards
noSet: ['challenge', 'userId', 'completed', 'history', 'streak', 'dateCompleted'],
private: [],
timestamps: true,
});
// A list of additional fields that cannot be set on creation (but can be set on updare)
let noCreate = ['completed'];
TaskSchema.statics.sanitizeCreate = function sanitizeCreate (createObj) {
return Task.sanitize(createObj, noCreate); // eslint-disable-line no-use-before-define
};
// A list of additional fields that cannot be updated (but can be set on creation)
let noUpdate = ['_id', 'type']; // TODO should prevent changes to checlist.*.id
TaskSchema.statics.sanitizeUpdate = function sanitizeUpdate (updateObj) {
return Task.sanitize(updateObj, noUpdate); // eslint-disable-line no-use-before-define
};
export let Task = mongoose.model('Task', TaskSchema);
// habits and dailies shared fields
let habitDailySchema = () => {
return {history: Array}; // [{date:Date, value:Number}], // this causes major performance problems TODO revisit
};
// dailys and todos shared fields
let dailyTodoSchema = () => {
return {
completed: {type: Boolean, default: false},
// Checklist fields (dailies and todos)
collapseChecklist: {type: Boolean, default: false},
checklist: [{
completed: {type: Boolean, default: false},
text: {type: String, required: true},
_id: {type: String, default: shared.uuid, validate: [validator.isUUID, 'Invalid uuid.']},
}],
};
};
export let HabitSchema = new Schema(_.defaults({
up: {type: Boolean, default: true},
down: {type: Boolean, default: true},
}, habitDailySchema()), subDiscriminatorOptions);
export let habit = Task.discriminator('habit', HabitSchema);
export let DailySchema = new Schema(_.defaults({
frequency: {type: String, default: 'weekly', enum: ['daily', 'weekly']},
everyX: {type: Number, default: 1}, // e.g. once every X weeks
startDate: {
type: Date,
default () {
return moment().startOf('day').toDate();
},
},
repeat: { // used only for 'weekly' frequency,
m: {type: Boolean, default: true},
t: {type: Boolean, default: true},
w: {type: Boolean, default: true},
th: {type: Boolean, default: true},
f: {type: Boolean, default: true},
s: {type: Boolean, default: true},
su: {type: Boolean, default: true},
},
streak: {type: Number, default: 0},
}, habitDailySchema(), dailyTodoSchema()), subDiscriminatorOptions);
export let daily = Task.discriminator('daily', DailySchema);
export let TodoSchema = new Schema(_.defaults({
dateCompleted: Date,
// FIXME we're getting parse errors, people have stored as "today" and "3/13". Need to run a migration & put this back to type: Date
// TODO change field name
date: String, // due date for todos
}, dailyTodoSchema()), subDiscriminatorOptions);
export let todo = Task.discriminator('todo', TodoSchema);
export let RewardSchema = new Schema({}, subDiscriminatorOptions);
export let reward = Task.discriminator('reward', RewardSchema);