mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
"allCompletedTodos" option in API for returning all completed To-Dos for when 30 isn't enough (#7773)
* add new "allCompletedTodos" option to API for returning all completed To-Dos at once - fixes #7301 * make minor fixes to allCompletedTodos option * change allCompletedTodos option to _allCompletedTodos and add a BETA comment
This commit is contained in:
@@ -64,7 +64,7 @@ describe('GET /tasks/user', () => {
|
|||||||
expect(todos.every(task => task.completed === false));
|
expect(todos.every(task => task.completed === false));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns completed todos sorted by reverse completion date if req.query.type is "completeTodos"', async () => {
|
it('returns completed todos sorted by reverse completion date if req.query.type is "completedTodos"', async () => {
|
||||||
let todo1 = await user.post('/tasks/user', {text: 'todo to complete 1', type: 'todo'});
|
let todo1 = await user.post('/tasks/user', {text: 'todo to complete 1', type: 'todo'});
|
||||||
let todo2 = await user.post('/tasks/user', {text: 'todo to complete 2', type: 'todo'});
|
let todo2 = await user.post('/tasks/user', {text: 'todo to complete 2', type: 'todo'});
|
||||||
|
|
||||||
@@ -81,4 +81,50 @@ describe('GET /tasks/user', () => {
|
|||||||
expect(completedTodos.length).to.equal(2);
|
expect(completedTodos.length).to.equal(2);
|
||||||
expect(completedTodos[completedTodos.length - 1].text).to.equal('todo to complete 2'); // last is the todo that was completed most recently
|
expect(completedTodos[completedTodos.length - 1].text).to.equal('todo to complete 2'); // last is the todo that was completed most recently
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns completed todos sorted by reverse completion date if req.query.type is "_allCompletedTodos"', async () => {
|
||||||
|
let todo1 = await user.post('/tasks/user', {text: 'todo to complete 1', type: 'todo'});
|
||||||
|
let todo2 = await user.post('/tasks/user', {text: 'todo to complete 2', type: 'todo'});
|
||||||
|
|
||||||
|
await user.sync();
|
||||||
|
let initialTodoCount = user.tasksOrder.todos.length;
|
||||||
|
|
||||||
|
await user.post(`/tasks/${todo2._id}/score/up`);
|
||||||
|
await user.post(`/tasks/${todo1._id}/score/up`);
|
||||||
|
await user.sync();
|
||||||
|
|
||||||
|
expect(user.tasksOrder.todos.length).to.equal(initialTodoCount - 2);
|
||||||
|
|
||||||
|
let allCompletedTodos = await user.get('/tasks/user?type=_allCompletedTodos');
|
||||||
|
expect(allCompletedTodos.length).to.equal(2);
|
||||||
|
expect(allCompletedTodos[allCompletedTodos.length - 1].text).to.equal('todo to complete 2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns only some completed todos if req.query.type is "completedTodos" or "_allCompletedTodos"', async () => {
|
||||||
|
const LIMIT = 30;
|
||||||
|
let numberOfTodos = LIMIT + 1;
|
||||||
|
let todosInput = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < numberOfTodos; i++) {
|
||||||
|
todosInput[i] = {text: 'todo to complete ${i}', type: 'todo'};
|
||||||
|
}
|
||||||
|
let todos = await user.post('/tasks/user', todosInput);
|
||||||
|
await user.sync();
|
||||||
|
let initialTodoCount = user.tasksOrder.todos.length;
|
||||||
|
|
||||||
|
for (let i = 0; i < numberOfTodos; i++) {
|
||||||
|
let id = todos[i]._id;
|
||||||
|
|
||||||
|
await user.post(`/tasks/${id}/score/up`); // eslint-disable-line babel/no-await-in-loop
|
||||||
|
}
|
||||||
|
await user.sync();
|
||||||
|
|
||||||
|
expect(user.tasksOrder.todos.length).to.equal(initialTodoCount - numberOfTodos);
|
||||||
|
|
||||||
|
let completedTodos = await user.get('/tasks/user?type=completedTodos');
|
||||||
|
expect(completedTodos.length).to.equal(LIMIT);
|
||||||
|
|
||||||
|
let allCompletedTodos = await user.get('/tasks/user?type=_allCompletedTodos');
|
||||||
|
expect(allCompletedTodos.length).to.equal(numberOfTodos);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -143,12 +143,17 @@ async function _getTasks (req, res, user, challenge) {
|
|||||||
if (type === 'todos') {
|
if (type === 'todos') {
|
||||||
query.completed = false; // Exclude completed todos
|
query.completed = false; // Exclude completed todos
|
||||||
query.type = 'todo';
|
query.type = 'todo';
|
||||||
} else if (type === 'completedTodos') {
|
} else if (type === 'completedTodos' || type === '_allCompletedTodos') { // _allCompletedTodos is currently in BETA and is likely to be removed in future
|
||||||
|
let limit = 30;
|
||||||
|
|
||||||
|
if (type === '_allCompletedTodos') {
|
||||||
|
limit = 0; // no limit
|
||||||
|
}
|
||||||
query = Tasks.Task.find({
|
query = Tasks.Task.find({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
type: 'todo',
|
type: 'todo',
|
||||||
completed: true,
|
completed: true,
|
||||||
}).limit(30).sort({ // TODO add ability to pick more than 30 completed todos
|
}).limit(limit).sort({
|
||||||
dateCompleted: -1,
|
dateCompleted: -1,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -164,7 +169,7 @@ async function _getTasks (req, res, user, challenge) {
|
|||||||
let tasks = await Tasks.Task.find(query).exec();
|
let tasks = await Tasks.Task.find(query).exec();
|
||||||
|
|
||||||
// Order tasks based on tasksOrder
|
// Order tasks based on tasksOrder
|
||||||
if (type && type !== 'completedTodos') {
|
if (type && type !== 'completedTodos' && type !== '_allCompletedTodos') {
|
||||||
let order = (challenge || user).tasksOrder[type];
|
let order = (challenge || user).tasksOrder[type];
|
||||||
let orderedTasks = new Array(tasks.length);
|
let orderedTasks = new Array(tasks.length);
|
||||||
let unorderedTasks = []; // what we want to add later
|
let unorderedTasks = []; // what we want to add later
|
||||||
@@ -193,7 +198,7 @@ async function _getTasks (req, res, user, challenge) {
|
|||||||
* @apiName GetUserTasks
|
* @apiName GetUserTasks
|
||||||
* @apiGroup Task
|
* @apiGroup Task
|
||||||
*
|
*
|
||||||
* @apiParam {string="habits","dailys","todos","rewards","completedTodos"} type Optional query parameter to return just a type of tasks. By default all types will be returned except completed todos that must be requested separately.
|
* @apiParam {string="habits","dailys","todos","rewards","completedTodos"} type Optional query parameter to return just a type of tasks. By default all types will be returned except completed todos that must be requested separately. The "completedTodos" type returns only the 30 most recently completed.
|
||||||
*
|
*
|
||||||
* @apiSuccess {Array} data An array of tasks
|
* @apiSuccess {Array} data An array of tasks
|
||||||
*/
|
*/
|
||||||
@@ -203,7 +208,7 @@ api.getUserTasks = {
|
|||||||
middlewares: [authWithHeaders()],
|
middlewares: [authWithHeaders()],
|
||||||
async handler (req, res) {
|
async handler (req, res) {
|
||||||
let types = Tasks.tasksTypes.map(type => `${type}s`);
|
let types = Tasks.tasksTypes.map(type => `${type}s`);
|
||||||
types.push('completedTodos');
|
types.push('completedTodos', '_allCompletedTodos'); // _allCompletedTodos is currently in BETA and is likely to be removed in future
|
||||||
req.checkQuery('type', res.t('invalidTaskType')).optional().isIn(types);
|
req.checkQuery('type', res.t('invalidTaskType')).optional().isIn(types);
|
||||||
|
|
||||||
let validationErrors = req.validationErrors();
|
let validationErrors = req.validationErrors();
|
||||||
|
|||||||
Reference in New Issue
Block a user