Tasks is due (#8711)

* Added isDue field and isDue set on create

* Added isDue update on update task

* Add isdue calc to score task

* Added isdue calc to cron

* Fixed lint issue

* Added isDue to no set and updated grammar
This commit is contained in:
Keith Holliday
2017-05-10 07:40:45 -06:00
committed by GitHub
parent 638c9dee89
commit 727cdc9402
8 changed files with 34 additions and 1 deletions

View File

@@ -208,6 +208,13 @@ describe('POST /tasks/:id/score/:direction', () => {
expect(task.completed).to.equal(false); expect(task.completed).to.equal(false);
}); });
it('computes isDue', async () => {
await user.post(`/tasks/${daily._id}/score/up`);
let task = await user.get(`/tasks/${daily._id}`);
expect(task.isDue).to.equal(true);
});
it('scores up daily even if it is already completed'); // Yes? it('scores up daily even if it is already completed'); // Yes?
it('scores down daily even if it is already uncompleted'); // Yes? it('scores down daily even if it is already uncompleted'); // Yes?

View File

@@ -509,6 +509,7 @@ describe('POST /tasks/user', () => {
expect(task.daysOfMonth).to.eql([15]); expect(task.daysOfMonth).to.eql([15]);
expect(task.weeksOfMonth).to.eql([3]); expect(task.weeksOfMonth).to.eql([3]);
expect(new Date(task.startDate)).to.eql(now); expect(new Date(task.startDate)).to.eql(now);
expect(task.isDue).to.be.true;
}); });
it('creates multiple dailys', async () => { it('creates multiple dailys', async () => {

View File

@@ -1,3 +1,4 @@
import moment from 'moment';
import { import {
generateUser, generateUser,
generateGroup, generateGroup,
@@ -395,12 +396,14 @@ describe('PUT /tasks/:id', () => {
notes: 'some new notes', notes: 'some new notes',
frequency: 'daily', frequency: 'daily',
everyX: 5, everyX: 5,
startDate: moment().add(1, 'days').toDate(),
}); });
expect(savedDaily.text).to.eql('some new text'); expect(savedDaily.text).to.eql('some new text');
expect(savedDaily.notes).to.eql('some new notes'); expect(savedDaily.notes).to.eql('some new notes');
expect(savedDaily.frequency).to.eql('daily'); expect(savedDaily.frequency).to.eql('daily');
expect(savedDaily.everyX).to.eql(5); expect(savedDaily.everyX).to.eql(5);
expect(savedDaily.isDue).to.be.false;
}); });
it('can update checklists (replace it)', async () => { it('can update checklists (replace it)', async () => {

View File

@@ -358,6 +358,14 @@ describe('cron', () => {
}; };
}); });
it('computes isDue', () => {
tasksByType.dailys[0].frequency = 'daily';
tasksByType.dailys[0].everyX = 5;
tasksByType.dailys[0].startDate = moment().add(1, 'days').toDate();
cron({user, tasksByType, daysMissed, analytics});
expect(tasksByType.dailys[0].isDue).to.be.false;
});
it('should add history', () => { it('should add history', () => {
cron({user, tasksByType, daysMissed, analytics}); cron({user, tasksByType, daysMissed, analytics});
expect(tasksByType.dailys[0].history).to.be.lengthOf(1); expect(tasksByType.dailys[0].history).to.be.lengthOf(1);

View File

@@ -431,6 +431,7 @@ api.updateTask = {
} else if (task.userId !== user._id) { // If the task is owned by a user make it's the current one } else if (task.userId !== user._id) { // If the task is owned by a user make it's the current one
throw new NotFound(res.t('taskNotFound')); throw new NotFound(res.t('taskNotFound'));
} }
let oldCheckList = task.checklist; let oldCheckList = task.checklist;
// we have to convert task to an object because otherwise things don't get merged correctly. Bad for performances? // we have to convert task to an object because otherwise things don't get merged correctly. Bad for performances?
let [updatedTaskObj] = common.ops.updateTask(task.toObject(), req); let [updatedTaskObj] = common.ops.updateTask(task.toObject(), req);
@@ -455,6 +456,10 @@ api.updateTask = {
task.group.approval.required = true; task.group.approval.required = true;
} }
if (sanitizedObj.type === 'daily') {
task.isDue = common.shouldDo(Date.now(), sanitizedObj, user.preferences);
}
let savedTask = await task.save(); let savedTask = await task.save();
if (group && task.group.id && task.group.assignedUsers.length > 0) { if (group && task.group.id && task.group.assignedUsers.length > 0) {
@@ -584,6 +589,10 @@ api.scoreTask = {
} }
} }
if (task.type === 'daily') {
task.isDue = common.shouldDo(Date.now(), task, user.preferences);
}
let results = await Bluebird.all([ let results = await Bluebird.all([
user.save(), user.save(),
task.save(), task.save(),

View File

@@ -314,6 +314,7 @@ export function cron (options = {}) {
value: task.value, value: task.value,
}); });
task.completed = false; task.completed = false;
task.isDue = common.shouldDo(Date.now(), task, user.preferences);
if (completed || scheduleMisses > 0) { if (completed || scheduleMisses > 0) {
if (task.checklist) { if (task.checklist) {

View File

@@ -4,6 +4,7 @@ import {
} from './errors'; } from './errors';
import Bluebird from 'bluebird'; import Bluebird from 'bluebird';
import _ from 'lodash'; import _ from 'lodash';
import shared from '../../common';
async function _validateTaskAlias (tasks, res) { async function _validateTaskAlias (tasks, res) {
let tasksWithAliases = tasks.filter(task => task.alias); let tasksWithAliases = tasks.filter(task => task.alias);
@@ -63,6 +64,8 @@ export async function createTasks (req, res, options = {}) {
newTask.userId = user._id; newTask.userId = user._id;
} }
if (newTask.type === 'daily') newTask.isDue = shared.shouldDo(Date.now(), newTask, user.preferences);
// Validate that the task is valid and throw if it isn't // Validate that the task is valid and throw if it isn't
// otherwise since we're saving user/challenge/group and task in parallel it could save the user/challenge/group with a tasksOrder that doens't match reality // otherwise since we're saving user/challenge/group and task in parallel it could save the user/challenge/group with a tasksOrder that doens't match reality
let validationErrors = newTask.validateSync(); let validationErrors = newTask.validateSync();

View File

@@ -92,7 +92,7 @@ export let TaskSchema = new Schema({
}, discriminatorOptions)); }, discriminatorOptions));
TaskSchema.plugin(baseModel, { TaskSchema.plugin(baseModel, {
noSet: ['challenge', 'userId', 'completed', 'history', 'dateCompleted', '_legacyId', 'group'], noSet: ['challenge', 'userId', 'completed', 'history', 'dateCompleted', '_legacyId', 'group', 'isDue'],
sanitizeTransform (taskObj) { sanitizeTransform (taskObj) {
if (taskObj.type && taskObj.type !== 'reward') { // value should be settable directly only for rewards if (taskObj.type && taskObj.type !== 'reward') { // value should be settable directly only for rewards
delete taskObj.value; delete taskObj.value;
@@ -242,6 +242,7 @@ export let DailySchema = new Schema(_.defaults({
streak: {type: Number, default: 0}, streak: {type: Number, default: 0},
daysOfMonth: {type: [Number], default: []}, // Days of the month that the daily should repeat on daysOfMonth: {type: [Number], default: []}, // Days of the month that the daily should repeat on
weeksOfMonth: {type: [Number], default: []}, // Weeks of the month that the daily should repeat on weeksOfMonth: {type: [Number], default: []}, // Weeks of the month that the daily should repeat on
isDue: {type: Boolean},
}, habitDailySchema(), dailyTodoSchema()), subDiscriminatorOptions); }, habitDailySchema(), dailyTodoSchema()), subDiscriminatorOptions);
export let daily = Task.discriminator('daily', DailySchema); export let daily = Task.discriminator('daily', DailySchema);