mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 06:37:23 +01:00
Change $type of date for todos (#12779)
* change $type to date for task and add new test * adjust apidocs to reflect type change * migration test for api date $type change * minor fixes to migration * unset instead of set empty string * add type filter * fix(todo date migration): make sure the update command works and limit update ops Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
This commit is contained in:
61
migrations/archive/2020/20201111_api_date.js
Normal file
61
migrations/archive/2020/20201111_api_date.js
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Fix dates in the database that were stored as $type string instead of Date
|
||||
*/
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const MIGRATION_NAME = '20201111_api_date';
|
||||
|
||||
import * as Tasks from '../../../website/server/models/task';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (todo) {
|
||||
count++;
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${todo._id}`);
|
||||
|
||||
const newDate = new Date(todo.date);
|
||||
if (isValidDate(newDate)) return;
|
||||
|
||||
return await Tasks.Task.update({_id: todo._id, type: 'todo'}, {$unset: {date: ''}}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
type: 'todo',
|
||||
date: {$exists: true}
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
type: 1,
|
||||
date: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await Tasks.Task // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.select(fields)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate tasks found and modified.');
|
||||
console.warn(`\n${count} tasks processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
|
||||
function isValidDate(d) {
|
||||
return !isNaN(d.getTime());
|
||||
}
|
||||
@@ -220,6 +220,18 @@ describe('POST /tasks/user', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('errors if todo due date supplied is an invalid date', async () => {
|
||||
await expect(user.post('/tasks/user', {
|
||||
type: 'todo',
|
||||
text: 'todo text',
|
||||
date: 'invalid date',
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'todo validation failed',
|
||||
});
|
||||
});
|
||||
|
||||
context('sending task activity webhooks', () => {
|
||||
before(async () => {
|
||||
await server.start();
|
||||
|
||||
@@ -80,7 +80,7 @@ const requiredGroupFields = '_id leader tasksOrder name';
|
||||
* "per", "con"
|
||||
* @apiParam (Body) {Boolean} [collapseChecklist=false] Determines if a checklist will be displayed
|
||||
* @apiParam (Body) {String} [notes] Extra notes
|
||||
* @apiParam (Body) {String} [date] Due date to be shown in task list. Only valid for type "todo."
|
||||
* @apiParam (Body) {Date} [date] Due date to be shown in task list. Only valid for type "todo."
|
||||
* @apiParam (Body) {Number="0.1","1","1.5","2"} [priority=1] Difficulty, options are 0.1, 1,
|
||||
* 1.5, 2; eqivalent of Trivial,
|
||||
* Easy, Medium, Hard.
|
||||
@@ -253,7 +253,7 @@ api.createUserTasks = {
|
||||
* "int", "per", "con".
|
||||
* @apiParam (Body) {Boolean} [collapseChecklist=false] Determines if a checklist will be displayed
|
||||
* @apiParam (Body) {String} [notes] Extra notes
|
||||
* @apiParam (Body) {String} [date] Due date to be shown in task list. Only valid for type "todo."
|
||||
* @apiParam (Body) {Date} [date] Due date to be shown in task list. Only valid for type "todo."
|
||||
* @apiParam (Body) {Number="0.1","1","1.5","2"} [priority=1] Difficulty, options are 0.1, 1,
|
||||
* 1.5, 2; eqivalent of Trivial,
|
||||
* Easy, Medium, Hard.
|
||||
@@ -567,7 +567,7 @@ api.getTask = {
|
||||
* "per", "con".
|
||||
* @apiParam (Body) {Boolean} [collapseChecklist=false] Determines if a checklist will be displayed
|
||||
* @apiParam (Body) {String} [notes] Extra notes
|
||||
* @apiParam (Body) {String} [date] Due date to be shown in task list. Only valid for type "todo."
|
||||
* @apiParam (Body) {Date} [date] Due date to be shown in task list. Only valid for type "todo."
|
||||
* @apiParam (Body) {Number="0.1","1","1.5","2"} [priority=1] Difficulty, options are 0.1, 1,
|
||||
* 1.5, 2; eqivalent of Trivial,
|
||||
* Easy, Medium, Hard.
|
||||
|
||||
@@ -404,8 +404,7 @@ export const daily = Task.discriminator('daily', DailySchema);
|
||||
|
||||
export const TodoSchema = new Schema(_.defaults({
|
||||
dateCompleted: Date,
|
||||
// TODO we're getting parse errors, people have stored as "today" and "3/13". Need to run a migration & put this back to $type: Date see http://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript
|
||||
date: String, // due date for todos
|
||||
date: Date, // due date for todos
|
||||
}, dailyTodoSchema()), subDiscriminatorOptions);
|
||||
export const todo = Task.discriminator('todo', TodoSchema);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user