All checks were successful
Build and Push App Image / build-and-push (push) Successful in 1m20s
421 lines
14 KiB
JavaScript
421 lines
14 KiB
JavaScript
import { defineStore } from "pinia";
|
|
import { ref } from "vue";
|
|
import apiClient from "../services/apiClient";
|
|
|
|
export const useSpaceStore = defineStore("space", () => {
|
|
const spaces = ref([]);
|
|
const currentSpace = ref(null);
|
|
const notes = ref([]);
|
|
const searchResults = ref([]);
|
|
const notesSkip = ref(0);
|
|
const notesLimit = ref(20);
|
|
const notesHasMore = ref(true);
|
|
const notesLoading = ref(false);
|
|
const categories = ref([]);
|
|
const categoryTree = ref([]);
|
|
const taskLists = ref([]);
|
|
const tasks = ref([]);
|
|
const taskStatuses = ref([]);
|
|
const noteLinkedTasks = ref([]);
|
|
|
|
const refreshSpaceData = async (spaceId) => {
|
|
await Promise.all([fetchCategories(spaceId), fetchNotes(spaceId), fetchTaskLists(spaceId), fetchTaskStatuses(spaceId), fetchTasks(spaceId)]);
|
|
};
|
|
|
|
const fetchSpaces = async () => {
|
|
try {
|
|
const response = await apiClient.get("/api/v1/spaces");
|
|
spaces.value = response.data || [];
|
|
} catch (error) {
|
|
console.error("Error fetching spaces:", error);
|
|
}
|
|
};
|
|
|
|
const selectSpace = async (spaceId) => {
|
|
try {
|
|
const response = await apiClient.get(`/api/v1/spaces/${spaceId}`);
|
|
currentSpace.value = response.data;
|
|
await refreshSpaceData(spaceId);
|
|
} catch (error) {
|
|
console.error("Error selecting space:", error);
|
|
}
|
|
};
|
|
|
|
const fetchCategories = async (spaceId) => {
|
|
try {
|
|
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/categories`);
|
|
categoryTree.value = response.data || [];
|
|
categories.value = categoryTree.value;
|
|
} catch (error) {
|
|
console.error("Error fetching categories:", error);
|
|
categoryTree.value = [];
|
|
categories.value = [];
|
|
}
|
|
};
|
|
|
|
const fetchNotes = async (spaceId, options = {}) => {
|
|
const { reset = true, limit = notesLimit.value } = options;
|
|
if (!spaceId) {
|
|
return;
|
|
}
|
|
if (notesLoading.value) {
|
|
return;
|
|
}
|
|
if (!reset && !notesHasMore.value) {
|
|
return;
|
|
}
|
|
|
|
if (reset) {
|
|
notesSkip.value = 0;
|
|
notesHasMore.value = true;
|
|
notesLimit.value = limit;
|
|
}
|
|
|
|
try {
|
|
notesLoading.value = true;
|
|
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/notes`, {
|
|
params: {
|
|
skip: notesSkip.value,
|
|
limit,
|
|
},
|
|
});
|
|
const fetchedNotes = response.data || [];
|
|
|
|
if (reset) {
|
|
notes.value = fetchedNotes;
|
|
} else {
|
|
notes.value = [...notes.value, ...fetchedNotes];
|
|
}
|
|
|
|
notesSkip.value += fetchedNotes.length;
|
|
notesHasMore.value = fetchedNotes.length === limit;
|
|
} catch (error) {
|
|
console.error("Error fetching notes:", error);
|
|
} finally {
|
|
notesLoading.value = false;
|
|
}
|
|
};
|
|
|
|
const loadMoreNotes = async (spaceId) => {
|
|
await fetchNotes(spaceId, { reset: false, limit: notesLimit.value });
|
|
};
|
|
|
|
const createSpace = async (spaceData) => {
|
|
try {
|
|
const response = await apiClient.post("/api/v1/spaces", spaceData);
|
|
spaces.value.push(response.data);
|
|
currentSpace.value = response.data;
|
|
localStorage.setItem("currentSpaceId", response.data.id);
|
|
await refreshSpaceData(response.data.id);
|
|
return response.data;
|
|
} catch (error) {
|
|
throw error.response?.data?.message || error.message;
|
|
}
|
|
};
|
|
|
|
const updateSpace = async (spaceId, spaceData) => {
|
|
try {
|
|
const response = await apiClient.put(`/api/v1/spaces/${spaceId}`, spaceData);
|
|
const index = spaces.value.findIndex((s) => s.id === spaceId);
|
|
if (index !== -1) {
|
|
spaces.value[index] = response.data;
|
|
}
|
|
if (currentSpace.value?.id === spaceId) {
|
|
currentSpace.value = response.data;
|
|
}
|
|
return response.data;
|
|
} catch (error) {
|
|
throw error.response?.data?.message || error.message;
|
|
}
|
|
};
|
|
|
|
const createCategory = async (spaceId, categoryData) => {
|
|
try {
|
|
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/categories`, categoryData);
|
|
await fetchCategories(spaceId);
|
|
return response.data;
|
|
} catch (error) {
|
|
throw error.response?.data?.message || error.message;
|
|
}
|
|
};
|
|
|
|
const updateCategory = async (spaceId, categoryId, categoryData) => {
|
|
try {
|
|
const response = await apiClient.put(`/api/v1/spaces/${spaceId}/categories/${categoryId}`, categoryData);
|
|
await fetchCategories(spaceId);
|
|
return response.data;
|
|
} catch (error) {
|
|
throw error.response?.data?.message || error.message;
|
|
}
|
|
};
|
|
|
|
const deleteCategory = async (spaceId, categoryId) => {
|
|
try {
|
|
await apiClient.delete(`/api/v1/spaces/${spaceId}/categories/${categoryId}`);
|
|
await refreshSpaceData(spaceId);
|
|
} catch (error) {
|
|
throw error.response?.data?.message || error.message;
|
|
}
|
|
};
|
|
|
|
const createNote = async (spaceId, noteData) => {
|
|
try {
|
|
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/notes`, noteData);
|
|
await refreshSpaceData(spaceId);
|
|
return response.data;
|
|
} catch (error) {
|
|
throw error.response?.data?.message || error.message;
|
|
}
|
|
};
|
|
|
|
const updateNote = async (spaceId, noteData) => {
|
|
try {
|
|
const response = await apiClient.put(`/api/v1/spaces/${spaceId}/notes/${noteData.id}`, noteData);
|
|
const index = notes.value.findIndex((n) => n.id === noteData.id);
|
|
if (index !== -1) {
|
|
notes.value[index] = response.data;
|
|
}
|
|
await fetchCategories(spaceId);
|
|
return response.data;
|
|
} catch (error) {
|
|
throw error.response?.data?.message || error.message;
|
|
}
|
|
};
|
|
|
|
const deleteNote = async (spaceId, noteId) => {
|
|
try {
|
|
await apiClient.delete(`/api/v1/spaces/${spaceId}/notes/${noteId}`);
|
|
notes.value = notes.value.filter((n) => n.id !== noteId);
|
|
await fetchCategories(spaceId);
|
|
} catch (error) {
|
|
throw error.response?.data?.message || error.message;
|
|
}
|
|
};
|
|
|
|
const searchNotes = async (query) => {
|
|
if (!currentSpace.value?.id) {
|
|
searchResults.value = [];
|
|
return [];
|
|
}
|
|
try {
|
|
const response = await apiClient.get(`/api/v1/spaces/${currentSpace.value.id}/notes/search`, { params: { q: query } });
|
|
searchResults.value = response.data || [];
|
|
return searchResults.value;
|
|
} catch (error) {
|
|
console.error("Error searching notes:", error);
|
|
searchResults.value = [];
|
|
return [];
|
|
}
|
|
};
|
|
|
|
const clearSearchResults = () => {
|
|
searchResults.value = [];
|
|
};
|
|
|
|
const fetchTaskStatuses = async (spaceId) => {
|
|
if (!spaceId) {
|
|
taskStatuses.value = [];
|
|
return [];
|
|
}
|
|
try {
|
|
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/task-statuses`);
|
|
taskStatuses.value = response.data || [];
|
|
return taskStatuses.value;
|
|
} catch (error) {
|
|
console.error("Error fetching task statuses:", error);
|
|
taskStatuses.value = [];
|
|
return [];
|
|
}
|
|
};
|
|
|
|
const fetchTaskLists = async (spaceId) => {
|
|
if (!spaceId) {
|
|
taskLists.value = [];
|
|
return [];
|
|
}
|
|
try {
|
|
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/task-lists`);
|
|
taskLists.value = response.data || [];
|
|
return taskLists.value;
|
|
} catch (error) {
|
|
console.error("Error fetching task lists:", error);
|
|
taskLists.value = [];
|
|
return [];
|
|
}
|
|
};
|
|
|
|
const createTaskList = async (spaceId, payload) => {
|
|
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/task-lists`, payload);
|
|
await fetchTaskLists(spaceId);
|
|
return response.data;
|
|
};
|
|
|
|
const updateTaskList = async (spaceId, taskListId, payload) => {
|
|
const response = await apiClient.put(`/api/v1/spaces/${spaceId}/task-lists/${taskListId}`, payload);
|
|
await fetchTaskLists(spaceId);
|
|
return response.data;
|
|
};
|
|
|
|
const deleteTaskList = async (spaceId, taskListId) => {
|
|
await apiClient.delete(`/api/v1/spaces/${spaceId}/task-lists/${taskListId}`);
|
|
await fetchTaskLists(spaceId);
|
|
};
|
|
|
|
const createTaskStatus = async (spaceId, payload) => {
|
|
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/task-statuses`, payload);
|
|
await fetchTaskStatuses(spaceId);
|
|
return response.data;
|
|
};
|
|
|
|
const updateTaskStatus = async (spaceId, statusId, payload) => {
|
|
const response = await apiClient.put(`/api/v1/spaces/${spaceId}/task-statuses/${statusId}`, payload);
|
|
await fetchTaskStatuses(spaceId);
|
|
return response.data;
|
|
};
|
|
|
|
const deleteTaskStatus = async (spaceId, statusId) => {
|
|
await apiClient.delete(`/api/v1/spaces/${spaceId}/task-statuses/${statusId}`);
|
|
await fetchTaskStatuses(spaceId);
|
|
};
|
|
|
|
const reorderTaskStatuses = async (spaceId, orderedStatusIds) => {
|
|
const response = await apiClient.put(`/api/v1/spaces/${spaceId}/task-statuses/reorder`, {
|
|
ordered_status_ids: orderedStatusIds,
|
|
});
|
|
taskStatuses.value = response.data || [];
|
|
return taskStatuses.value;
|
|
};
|
|
|
|
const fetchTasks = async (spaceId, filters = {}) => {
|
|
if (!spaceId) {
|
|
tasks.value = [];
|
|
return [];
|
|
}
|
|
const params = {};
|
|
if (filters.taskListId) {
|
|
params.taskListId = filters.taskListId;
|
|
}
|
|
if (filters.statusId) {
|
|
params.statusId = filters.statusId;
|
|
}
|
|
if (typeof filters.parentTaskId === "string") {
|
|
params.parentTaskId = filters.parentTaskId;
|
|
}
|
|
|
|
try {
|
|
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/tasks`, { params });
|
|
tasks.value = response.data || [];
|
|
return tasks.value;
|
|
} catch (error) {
|
|
console.error("Error fetching tasks:", error);
|
|
tasks.value = [];
|
|
return [];
|
|
}
|
|
};
|
|
|
|
const searchTasks = async (spaceId, query) => {
|
|
if (!spaceId || !query?.trim()) {
|
|
return [];
|
|
}
|
|
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/tasks/search`, { params: { q: query } });
|
|
return response.data || [];
|
|
};
|
|
|
|
const getTask = async (spaceId, taskId) => {
|
|
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/tasks/${taskId}`);
|
|
return response.data;
|
|
};
|
|
|
|
const createTask = async (spaceId, payload) => {
|
|
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/tasks`, payload);
|
|
await fetchTasks(spaceId);
|
|
return response.data;
|
|
};
|
|
|
|
const updateTask = async (spaceId, taskId, payload) => {
|
|
const response = await apiClient.put(`/api/v1/spaces/${spaceId}/tasks/${taskId}`, payload);
|
|
await fetchTasks(spaceId);
|
|
return response.data;
|
|
};
|
|
|
|
const deleteTask = async (spaceId, taskId) => {
|
|
await apiClient.delete(`/api/v1/spaces/${spaceId}/tasks/${taskId}`);
|
|
await fetchTasks(spaceId);
|
|
};
|
|
|
|
const transitionTask = async (spaceId, taskId, direction) => {
|
|
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/tasks/${taskId}/transition`, { direction });
|
|
await fetchTasks(spaceId);
|
|
return response.data;
|
|
};
|
|
|
|
const fetchTasksForNote = async (spaceId, noteId) => {
|
|
if (!spaceId || !noteId) {
|
|
noteLinkedTasks.value = [];
|
|
return [];
|
|
}
|
|
const response = await apiClient.get(`/api/v1/spaces/${spaceId}/notes/${noteId}/tasks`);
|
|
noteLinkedTasks.value = response.data || [];
|
|
return noteLinkedTasks.value;
|
|
};
|
|
|
|
const linkTaskToNote = async (spaceId, taskId, noteId) => {
|
|
const response = await apiClient.post(`/api/v1/spaces/${spaceId}/tasks/${taskId}/notes`, { note_id: noteId });
|
|
return response.data;
|
|
};
|
|
|
|
const unlinkTaskFromNote = async (spaceId, taskId, noteId) => {
|
|
const response = await apiClient.delete(`/api/v1/spaces/${spaceId}/tasks/${taskId}/notes/${noteId}`);
|
|
return response.data;
|
|
};
|
|
|
|
return {
|
|
spaces,
|
|
currentSpace,
|
|
notes,
|
|
searchResults,
|
|
notesHasMore,
|
|
notesLoading,
|
|
categories,
|
|
categoryTree,
|
|
taskLists,
|
|
tasks,
|
|
taskStatuses,
|
|
noteLinkedTasks,
|
|
fetchSpaces,
|
|
selectSpace,
|
|
fetchNotes,
|
|
loadMoreNotes,
|
|
fetchCategories,
|
|
createSpace,
|
|
updateSpace,
|
|
createCategory,
|
|
updateCategory,
|
|
deleteCategory,
|
|
createNote,
|
|
updateNote,
|
|
deleteNote,
|
|
searchNotes,
|
|
clearSearchResults,
|
|
fetchTaskStatuses,
|
|
fetchTaskLists,
|
|
createTaskList,
|
|
updateTaskList,
|
|
deleteTaskList,
|
|
createTaskStatus,
|
|
updateTaskStatus,
|
|
deleteTaskStatus,
|
|
reorderTaskStatuses,
|
|
fetchTasks,
|
|
searchTasks,
|
|
getTask,
|
|
createTask,
|
|
updateTask,
|
|
deleteTask,
|
|
transitionTask,
|
|
fetchTasksForNote,
|
|
linkTaskToNote,
|
|
unlinkTaskFromNote,
|
|
};
|
|
});
|