From 6b6ca25efa4bf93f61aabf5e888fad9c9ebf6d5b Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 24 Mar 2026 19:47:28 +0100 Subject: [PATCH] feat(templates): add isTemplate to frontend project model and store --- frontend/src/modelTypes/IProject.ts | 1 + frontend/src/models/project.ts | 1 + frontend/src/stores/projects.ts | 21 +++++++++++++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/frontend/src/modelTypes/IProject.ts b/frontend/src/modelTypes/IProject.ts index 555b35a97..c7623d854 100644 --- a/frontend/src/modelTypes/IProject.ts +++ b/frontend/src/modelTypes/IProject.ts @@ -12,6 +12,7 @@ export interface IProject extends IAbstract { owner: IUser tasks: ITask[] isArchived: boolean + isTemplate: boolean hexColor: string identifier: string backgroundInformation: unknown | null // FIXME: improve type diff --git a/frontend/src/models/project.ts b/frontend/src/models/project.ts index 53b75a9b8..7f0b6cad9 100644 --- a/frontend/src/models/project.ts +++ b/frontend/src/models/project.ts @@ -17,6 +17,7 @@ export default class ProjectModel extends AbstractModel implements IPr owner: IUser = UserModel tasks: ITask[] = [] isArchived = false + isTemplate = false hexColor = '' identifier = '' backgroundInformation: unknown | null = null diff --git a/frontend/src/stores/projects.ts b/frontend/src/stores/projects.ts index 37110100e..878a19549 100644 --- a/frontend/src/stores/projects.ts +++ b/frontend/src/stores/projects.ts @@ -37,14 +37,17 @@ export const useProjectStore = defineStore('project', () => { } const notArchivedRootProjects = computed(() => projectsArray.value - .filter(p => !p.isArchived && p.id > 0 && ( + .filter(p => !p.isArchived && !p.isTemplate && p.id > 0 && ( p.parentProjectId === 0 || isOrphanedSubProject(p) ))) const favoriteProjects = computed(() => projectsArray.value - .filter(p => !p.isArchived && p.isFavorite)) + .filter(p => !p.isArchived && !p.isTemplate && p.isFavorite)) const savedFilterProjects = computed(() => projectsArray.value .filter(p => !p.isArchived && p.id < -1)) const hasProjects = computed(() => projectsArray.value.length > 0) + const templateProjects = computed(() => projectsArray.value + .filter(p => !p.isArchived && p.isTemplate)) + const hasTemplates = computed(() => templateProjects.value.length > 0) const getChildProjects = computed(() => { return (id: IProject['id']) => projectsArray.value.filter(p => p.parentProjectId === id) @@ -265,11 +268,19 @@ export const useProjectStore = defineStore('project', () => { loadedProjects.push(...newProjects) page++ } while (page <= projectService.totalPages) - + + // Fetch templates separately + let templatePage = 1 + do { + const newTemplates = await projectService.getAll({}, {is_template: true, expand: 'permissions'}, templatePage) as IProject[] + loadedProjects.push(...newTemplates) + templatePage++ + } while (templatePage <= projectService.totalPages) + } finally { cancel() } - + projects.value = {} setProjects(loadedProjects) @@ -329,6 +340,8 @@ export const useProjectStore = defineStore('project', () => { favoriteProjects: readonly(favoriteProjects), hasProjects: readonly(hasProjects), savedFilterProjects: readonly(savedFilterProjects), + templateProjects: readonly(templateProjects), + hasTemplates: readonly(hasTemplates), getChildProjects, isOrphanedSubProject,