mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
starts fixing default tasks and use discriminator
This commit is contained in:
@@ -10,10 +10,10 @@ var ChallengeSchema = new Schema({
|
|||||||
shortName: String,
|
shortName: String,
|
||||||
description: String,
|
description: String,
|
||||||
official: {type: Boolean,'default':false},
|
official: {type: Boolean,'default':false},
|
||||||
habits: [TaskSchemas.HabitSchema],
|
//habits: [TaskSchemas.HabitSchema],
|
||||||
dailys: [TaskSchemas.DailySchema],
|
//dailys: [TaskSchemas.DailySchema],
|
||||||
todos: [TaskSchemas.TodoSchema],
|
//todos: [TaskSchemas.TodoSchema],
|
||||||
rewards: [TaskSchemas.RewardSchema],
|
//rewards: [TaskSchemas.RewardSchema],
|
||||||
leader: {type: String, ref: 'User'},
|
leader: {type: String, ref: 'User'},
|
||||||
group: {type: String, ref: 'Group'},
|
group: {type: String, ref: 'Group'},
|
||||||
timestamp: {type: Date, 'default': Date.now},
|
timestamp: {type: Date, 'default': Date.now},
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import baseModel from '../libs/api-v3/baseModel';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
let Schema = mongoose.Schema;
|
let Schema = mongoose.Schema;
|
||||||
let discriminatorOptions = () => {
|
let discriminatorOptions = {
|
||||||
return {discriminatorKey: 'type'}; // the key that distinguishes task types
|
discriminatorKey: 'type', // the key that distinguishes task types
|
||||||
};
|
};
|
||||||
|
let subDiscriminatorOptions = _.defaults(_.cloneDeep(discriminatorOptions), {_id: false});
|
||||||
|
|
||||||
// TODO make sure a task can only update the fields belonging to its type
|
// TODO make sure a task can only update the fields belonging to its type
|
||||||
// We could use discriminators but it looks like when loading from the parent
|
// We could use discriminators but it looks like when loading from the parent
|
||||||
@@ -29,10 +30,10 @@ export let TaskSchema = new Schema({
|
|||||||
broken: String, // CHALLENGE_DELETED, TASK_DELETED, UNSUBSCRIBED, CHALLENGE_CLOSED TODO enum
|
broken: String, // CHALLENGE_DELETED, TASK_DELETED, UNSUBSCRIBED, CHALLENGE_CLOSED TODO enum
|
||||||
winner: String, // user.profile.name TODO necessary?
|
winner: String, // user.profile.name TODO necessary?
|
||||||
},
|
},
|
||||||
}, _.default({
|
}, _.defaults({
|
||||||
minimize: true, // So empty objects are returned
|
minimize: true, // So empty objects are returned
|
||||||
strict: true,
|
strict: true,
|
||||||
}, discriminatorOptions()));
|
}, discriminatorOptions));
|
||||||
|
|
||||||
TaskSchema.plugin(baseModel, {
|
TaskSchema.plugin(baseModel, {
|
||||||
noSet: [],
|
noSet: [],
|
||||||
@@ -66,7 +67,7 @@ let dailyTodoSchema = () => {
|
|||||||
export let Habit = Task.discriminator('Habit', new Schema(_.defaults({
|
export let Habit = Task.discriminator('Habit', new Schema(_.defaults({
|
||||||
up: {type: Boolean, default: true},
|
up: {type: Boolean, default: true},
|
||||||
down: {type: Boolean, default: true},
|
down: {type: Boolean, default: true},
|
||||||
}, habitDailySchema())), discriminatorOptions());
|
}, habitDailySchema()), subDiscriminatorOptions));
|
||||||
|
|
||||||
export let Daily = Task.discriminator('Daily', new Schema(_.defaults({
|
export let Daily = Task.discriminator('Daily', new Schema(_.defaults({
|
||||||
frequency: {type: String, default: 'weekly', enum: ['daily', 'weekly']},
|
frequency: {type: String, default: 'weekly', enum: ['daily', 'weekly']},
|
||||||
@@ -87,13 +88,13 @@ export let Daily = Task.discriminator('Daily', new Schema(_.defaults({
|
|||||||
su: {type: Boolean, default: true},
|
su: {type: Boolean, default: true},
|
||||||
},
|
},
|
||||||
streak: {type: Number, default: 0},
|
streak: {type: Number, default: 0},
|
||||||
}, habitDailySchema(), dailyTodoSchema())), discriminatorOptions());
|
}, habitDailySchema(), dailyTodoSchema()), subDiscriminatorOptions));
|
||||||
|
|
||||||
export let Todo = Task.discriminator('Todo', new Schema(_.defaults({
|
export let Todo = Task.discriminator('Todo', new Schema(_.defaults({
|
||||||
dateCompleted: Date,
|
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
|
// 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
|
// TODO change field name
|
||||||
date: String, // due date for todos
|
date: String, // due date for todos
|
||||||
}, dailyTodoSchema())), discriminatorOptions());
|
}, dailyTodoSchema()), subDiscriminatorOptions));
|
||||||
|
|
||||||
export let Reward = Task.discriminator('Reward', new Schema({}), discriminatorOptions());
|
export let Reward = Task.discriminator('Reward', new Schema({}, subDiscriminatorOptions));
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import shared from '../../../common';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import validator from 'validator';
|
import validator from 'validator';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import Q from 'q';
|
||||||
import { model as Task } from './task';
|
import { model as Task } from './task';
|
||||||
import baseModel from '../libs/api-v3/baseModel';
|
import baseModel from '../libs/api-v3/baseModel';
|
||||||
// import {model as Challenge} from './challenge';
|
// import {model as Challenge} from './challenge';
|
||||||
@@ -491,36 +492,37 @@ schema.post('init', function postInitUser (doc) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function _populateDefaultTasks (user, taskTypes) {
|
function _populateDefaultTasks (user, taskTypes) {
|
||||||
_.each(taskTypes, (taskType) => {
|
if ('tags' in taskTypes) {
|
||||||
// TODO save in own documents
|
user.tags = _.map(shared.content.userDefaults.tags, function(tag){
|
||||||
user[taskType] = _.map(shared.content.userDefaults[taskType], (taskDefaults) => {
|
let newTag = _.cloneDeep(tag);
|
||||||
let newTask;
|
|
||||||
|
|
||||||
// Render task's text and notes in user's language
|
// tasks automatically get _id=helpers.uuid() from TaskSchema id.default, but tags are Schema.Types.Mixed - so we need to manually invoke here
|
||||||
if (taskType === 'tags') {
|
newTag.id = shared.uuid();
|
||||||
newTask = _.cloneDeep(taskDefaults);
|
// Render tag's name in user's language
|
||||||
// tasks automatically get id=helpers.uuid() from TaskSchema id.default, but tags are Schema.Types.Mixed - so we need to manually invoke here
|
newTag.name = newTag.name(user.preferences.language);
|
||||||
newTask.id = shared.uuid();
|
return newTag;
|
||||||
newTask.name = newTask.name(user.preferences.language);
|
});
|
||||||
} else {
|
|
||||||
newTask = new Task(taskDefaults);
|
|
||||||
newTask.userId = user._id;
|
|
||||||
newTask.text = newTask.text(user.preferences.language);
|
|
||||||
if (newTask.notes) {
|
|
||||||
newTask.notes = newTask.notes(user.preferences.language);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let tasksToCreate = [];
|
||||||
|
_.each(taskTypes, (taskType) => {
|
||||||
|
let tasksOfType = _.map(shared.content.userDefaults[taskType], (taskDefaults) => {
|
||||||
|
let newTask = new Task(taskDefaults);
|
||||||
|
newTask.userId = user._id;
|
||||||
|
newTask.text = newTask.text(user.preferences.language);
|
||||||
|
if (newTask.notes) newTask.notes = newTask.notes(user.preferences.language);
|
||||||
if (newTask.checklist) {
|
if (newTask.checklist) {
|
||||||
newTask.checklist = _.map(newTask.checklist, (checklistItem) => {
|
newTask.checklist = _.map(newTask.checklist, (checklistItem) => {
|
||||||
checklistItem.text = checklistItem.text(user.preferences.language);
|
checklistItem.text = checklistItem.text(user.preferences.language);
|
||||||
return checklistItem;
|
return checklistItem;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return newTask;
|
tasksToCreate.push(...tasksOfType);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return Task.create(tasksToCreate);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _populateDefaultsForNewUser (user) {
|
function _populateDefaultsForNewUser (user) {
|
||||||
@@ -543,7 +545,7 @@ function _populateDefaultsForNewUser (user) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_populateDefaultTasks(user, taskTypes);
|
return _populateDefaultTasks(user, taskTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _setProfileName (user) {
|
function _setProfileName (user) {
|
||||||
@@ -556,13 +558,10 @@ function _setProfileName (user) {
|
|||||||
return localUsername || facebookUsername || anonymous;
|
return localUsername || facebookUsername || anonymous;
|
||||||
}
|
}
|
||||||
|
|
||||||
schema.pre('save', function postSaveUser (next) {
|
schema.pre('save', function postSaveUser (next, done) {
|
||||||
// Populate new users with default content
|
next();
|
||||||
if (this.isNew) {
|
|
||||||
_populateDefaultsForNewUser(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this.markModified('tasks');
|
// TODO remove all unnecessary checks
|
||||||
if (_.isNaN(this.preferences.dayStart) || this.preferences.dayStart < 0 || this.preferences.dayStart > 23) {
|
if (_.isNaN(this.preferences.dayStart) || this.preferences.dayStart < 0 || this.preferences.dayStart > 23) {
|
||||||
this.preferences.dayStart = 0;
|
this.preferences.dayStart = 0;
|
||||||
}
|
}
|
||||||
@@ -611,7 +610,12 @@ schema.pre('save', function postSaveUser (next) {
|
|||||||
if (_.isNaN(this._v) || !_.isNumber(this._v)) this._v = 0;
|
if (_.isNaN(this._v) || !_.isNumber(this._v)) this._v = 0;
|
||||||
this._v++;
|
this._v++;
|
||||||
|
|
||||||
next();
|
// Populate new users with default content
|
||||||
|
if (this.isNew) {
|
||||||
|
_populateDefaultsForNewUser(this)
|
||||||
|
.then((tasks) => done())
|
||||||
|
.catch(done);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
schema.methods.unlink = function unlink (options, cb) {
|
schema.methods.unlink = function unlink (options, cb) {
|
||||||
|
|||||||
Reference in New Issue
Block a user