mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
234 lines
7.2 KiB
JavaScript
234 lines
7.2 KiB
JavaScript
import { loadAsyncResource } from 'client/libs/asyncResource';
|
|
import axios from 'axios';
|
|
import compact from 'lodash/compact';
|
|
import omit from 'lodash/omit';
|
|
|
|
export function fetchUserTasks (store, options = {}) {
|
|
return loadAsyncResource({
|
|
store,
|
|
path: 'tasks',
|
|
url: '/api/v3/tasks/user',
|
|
deserialize (response) {
|
|
// Wait for the user to be loaded before deserializing
|
|
// because user.tasksOrder is necessary
|
|
return store.dispatch('user:fetch').then((userResource) => {
|
|
return store.dispatch('tasks:order', [response.data.data, userResource.data.tasksOrder]);
|
|
});
|
|
},
|
|
forceLoad: options.forceLoad,
|
|
});
|
|
}
|
|
|
|
export async function fetchCompletedTodos (store, forceLoad = false) {
|
|
// Wait for the user to be loaded before deserializing
|
|
// because user.tasksOrder is necessary
|
|
await store.dispatch('tasks:fetchUserTasks');
|
|
|
|
const loadStatus = store.state.completedTodosStatus;
|
|
if (loadStatus === 'NOT_LOADED' || forceLoad) {
|
|
store.state.completedTodosStatus = 'LOADING';
|
|
|
|
const response = await axios.get('/api/v3/tasks/user?type=completedTodos');
|
|
const completedTodos = response.data.data;
|
|
const tasks = store.state.tasks.data;
|
|
// Remove existing completed todos
|
|
tasks.todos = tasks.todos.filter(t => !t.completed);
|
|
tasks.todos.push(...completedTodos);
|
|
|
|
store.state.completedTodosStatus = 'LOADED';
|
|
} else if (status === 'LOADED') {
|
|
return;
|
|
} else if (loadStatus === 'LOADING') {
|
|
const watcher = store.watch(state => state.completedTodosStatus, (newLoadingStatus) => {
|
|
watcher(); // remove the watcher
|
|
if (newLoadingStatus === 'LOADED') {
|
|
return;
|
|
} else {
|
|
throw new Error(); // TODO add reason?
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
export async function clearCompletedTodos (store) {
|
|
await axios.post('/api/v3/tasks/clearCompletedTodos');
|
|
store.state.tasks.data.todos = store.state.tasks.data.todos.filter(task => {
|
|
return !task.completed;
|
|
});
|
|
}
|
|
|
|
|
|
export function order (store, [rawTasks, tasksOrder]) {
|
|
const tasks = {
|
|
habits: [],
|
|
dailys: [],
|
|
todos: [],
|
|
rewards: [],
|
|
};
|
|
|
|
rawTasks.forEach(task => {
|
|
tasks[`${task.type}s`].push(task);
|
|
});
|
|
|
|
Object.keys(tasks).forEach((type) => {
|
|
let tasksOfType = tasks[type];
|
|
|
|
const orderOfType = tasksOrder[type];
|
|
const orderedTasks = new Array(tasksOfType.length);
|
|
const unorderedTasks = []; // what we want to add later
|
|
|
|
tasksOfType.forEach((task, index) => {
|
|
const taskId = task._id;
|
|
const i = orderOfType[index] === taskId ? index : orderOfType.indexOf(taskId);
|
|
if (i === -1) {
|
|
unorderedTasks.push(task);
|
|
} else {
|
|
orderedTasks[i] = task;
|
|
}
|
|
});
|
|
|
|
tasks[type] = compact(orderedTasks).concat(unorderedTasks);
|
|
});
|
|
|
|
return tasks;
|
|
}
|
|
|
|
function sanitizeChecklist (task) {
|
|
if (task.checklist) {
|
|
task.checklist = task.checklist.filter((i) => {
|
|
return Boolean(i.text);
|
|
});
|
|
}
|
|
}
|
|
|
|
// Supply an array to create multiple tasks
|
|
export async function create (store, createdTask) {
|
|
// Treat all create actions as if we are adding multiple tasks
|
|
const payload = Array.isArray(createdTask) ? createdTask : [createdTask];
|
|
|
|
payload.forEach(t => {
|
|
const type = `${t.type}s`;
|
|
const list = store.state.tasks.data[type];
|
|
|
|
sanitizeChecklist(t);
|
|
|
|
list.unshift(t);
|
|
store.state.user.data.tasksOrder[type].unshift(t._id);
|
|
});
|
|
|
|
const response = await axios.post('/api/v3/tasks/user', payload);
|
|
const data = Array.isArray(response.data.data) ? response.data.data : [response.data.data];
|
|
|
|
data.forEach(taskRes => {
|
|
const taskData = store.state.tasks.data[`${taskRes.type}s`].find(t => t._id === taskRes._id);
|
|
Object.assign(taskData, taskRes);
|
|
});
|
|
}
|
|
|
|
export async function save (store, editedTask) {
|
|
const taskId = editedTask._id;
|
|
const type = editedTask.type;
|
|
const originalTask = store.state.tasks.data[`${type}s`].find(t => t._id === taskId);
|
|
|
|
sanitizeChecklist(editedTask);
|
|
|
|
if (originalTask) Object.assign(originalTask, editedTask);
|
|
|
|
const taskDataToSend = omit(editedTask, ['history']);
|
|
const response = await axios.put(`/api/v3/tasks/${taskId}`, taskDataToSend);
|
|
if (originalTask) Object.assign(originalTask, response.data.data);
|
|
}
|
|
|
|
export async function scoreChecklistItem (store, {taskId, itemId}) {
|
|
await axios.post(`/api/v3/tasks/${taskId}/checklist/${itemId}/score`);
|
|
}
|
|
|
|
export async function collapseChecklist (store, task) {
|
|
task.collapseChecklist = !task.collapseChecklist;
|
|
await axios.put(`/api/v3/tasks/${task._id}`, {
|
|
collapseChecklist: task.collapseChecklist,
|
|
});
|
|
}
|
|
|
|
export async function destroy (store, task) {
|
|
const list = store.state.tasks.data[`${task.type}s`];
|
|
const taskIndex = list.findIndex(t => t._id === task._id);
|
|
|
|
if (taskIndex > -1) {
|
|
list.splice(taskIndex, 1);
|
|
}
|
|
|
|
await axios.delete(`/api/v3/tasks/${task._id}`);
|
|
}
|
|
|
|
export async function getChallengeTasks (store, payload) {
|
|
let response = await axios.get(`/api/v3/tasks/challenge/${payload.challengeId}`);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function createChallengeTasks (store, payload) {
|
|
let response = await axios.post(`/api/v3/tasks/challenge/${payload.challengeId}`, payload.tasks);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function getGroupTasks (store, payload) {
|
|
let response = await axios.get(`/api/v3/tasks/group/${payload.groupId}`);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function createGroupTasks (store, payload) {
|
|
let response = await axios.post(`/api/v3/tasks/group/${payload.groupId}`, payload.tasks);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function assignTask (store, payload) {
|
|
let response = await axios.post(`/api/v3/tasks/${payload.taskId}/assign/${payload.userId}`);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function unassignTask (store, payload) {
|
|
let response = await axios.post(`/api/v3/tasks/${payload.taskId}/unassign/${payload.userId}`);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function getGroupApprovals (store, payload) {
|
|
let response = await axios.get(`/api/v3/approvals/group/${payload.groupId}`);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function approve (store, payload) {
|
|
let response = await axios.post(`/api/v3/tasks/${payload.taskId}/approve/${payload.userId}`);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function unlinkOneTask (store, payload) {
|
|
if (!payload.keep) payload.keep = 'keep';
|
|
|
|
let task = payload.task;
|
|
const list = store.state.tasks.data[`${task.type}s`];
|
|
const taskIndex = list.findIndex(t => t._id === task._id);
|
|
|
|
if (taskIndex > -1) {
|
|
list.splice(taskIndex, 1);
|
|
}
|
|
|
|
let response = await axios.post(`/api/v3/tasks/unlink-one/${payload.task._id}?keep=${payload.keep}`);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function unlinkAllTasks (store, payload) {
|
|
if (!payload.keep) payload.keep = 'keep-all';
|
|
let response = await axios.post(`/api/v3/tasks/unlink-all/${payload.challengeId}?keep=${payload.keep}`);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function move (store, payload) {
|
|
let response = await axios.post(`/api/v3/tasks/${payload.taskId}/move/to/${payload.position}`);
|
|
return response.data.data;
|
|
}
|
|
|
|
export async function moveGroupTask (store, payload) {
|
|
let response = await axios.post(`/api/v3/group-tasks/${payload.taskId}/move/to/${payload.position}`);
|
|
return response.data.data;
|
|
}
|