feat: don't handle child projects and instead only save the ids

This commit is contained in:
kolaente 2023-03-29 16:09:18 +02:00
parent 26bec05174
commit 760efa854d
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
5 changed files with 36 additions and 20 deletions

View File

@ -26,7 +26,7 @@
> >
<section> <section>
<BaseButton <BaseButton
v-if="p.childProjects.length > 0" v-if="childProjects[p.id]?.length > 0"
@click="collapsedProjects[p.id] = !collapsedProjects[p.id]" @click="collapsedProjects[p.id] = !collapsedProjects[p.id]"
class="collapse-project-button" class="collapse-project-button"
> >
@ -67,7 +67,7 @@
</section> </section>
<ProjectsNavigation <ProjectsNavigation
v-if="!collapsedProjects[p.id]" v-if="!collapsedProjects[p.id]"
v-model="p.childProjects" v-model="childProjects[p.id]"
:can-edit-order="true" :can-edit-order="true"
/> />
</li> </li>
@ -93,7 +93,7 @@ import {useBaseStore} from '@/stores/base'
import {useProjectStore} from '@/stores/projects' import {useProjectStore} from '@/stores/projects'
const props = defineProps<{ const props = defineProps<{
modelValue: IProject[], modelValue?: IProject[],
canEditOrder: boolean, canEditOrder: boolean,
}>() }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
@ -114,11 +114,16 @@ const currentProject = computed(() => baseStore.currentProject)
// TODO: child projects // TODO: child projects
const collapsedProjects = ref<{ [id: IProject['id']]: boolean }>({}) const collapsedProjects = ref<{ [id: IProject['id']]: boolean }>({})
const availableProjects = ref<IProject[]>([]) const availableProjects = ref<IProject[]>([])
const childProjects = ref<{ [id: IProject['id']]: boolean }>({})
watch( watch(
() => props.modelValue, () => props.modelValue,
projects => { projects => {
availableProjects.value = projects availableProjects.value = projects || []
projects.forEach(p => collapsedProjects.value[p.id] = false) projects?.forEach(p => {
collapsedProjects.value[p.id] = false
childProjects.value[p.id] = projectStore.getChildProjects(p.id)
.sort((a, b) => a.position - b.position)
})
}, },
{immediate: true}, {immediate: true},
) )
@ -149,8 +154,8 @@ async function saveProjectPosition(e: SortableEvent) {
if (project.parentProjectId !== parentProjectId && project.parentProjectId > 0) { if (project.parentProjectId !== parentProjectId && project.parentProjectId > 0) {
const parentProject = projectStore.getProjectById(project.parentProjectId) const parentProject = projectStore.getProjectById(project.parentProjectId)
const childProjectIndex = parentProject.childProjects.findIndex(p => p.id === project.id) const childProjectIndex = parentProject.childProjectIds.findIndex(pId => pId === project.id)
parentProject.childProjects.splice(childProjectIndex, 1) parentProject.childProjectIds.splice(childProjectIndex, 1)
} }
try { try {

View File

@ -17,14 +17,18 @@ const projectStore = useProjectStore()
await projectStore.loadProjects() await projectStore.loadProjects()
const projects = computed(() => projectStore.projectsArray const projects = computed({
.filter(p => p.parentProjectId === 0 && !p.isArchived) get() {
.sort((a, b) => a.position - b.position)) return projectStore.projectsArray
.filter(p => p.parentProjectId === 0 && !p.isArchived)
.sort((a, b) => a.position - b.position)
},
set() { }, // Vue will complain about the component not being writable - but we never need to write here. The setter is only here to silence the warning.
})
const favoriteProjects = computed(() => projectStore.projectsArray const favoriteProjects = computed(() => projectStore.projectsArray
.filter(p => !p.isArchived && p.isFavorite) .filter(p => !p.isArchived && p.isFavorite)
.map(p => ({ .map(p => ({
...p, ...p,
childProjects: [],
})) }))
.sort((a, b) => a.position - b.position)) .sort((a, b) => a.position - b.position))
</script> </script>

View File

@ -18,7 +18,7 @@ export interface IProject extends IAbstract {
subscription: ISubscription subscription: ISubscription
position: number position: number
backgroundBlurHash: string backgroundBlurHash: string
childProjects: IProject[] | null childProjectIds: number[]
parentProjectId: number parentProjectId: number
created: Date created: Date

View File

@ -22,7 +22,7 @@ export default class ProjectModel extends AbstractModel<IProject> implements IPr
subscription: ISubscription = null subscription: ISubscription = null
position = 0 position = 0
backgroundBlurHash = '' backgroundBlurHash = ''
childProjects = [] childProjectIds = []
parentProjectId = 0 parentProjectId = 0
created: Date = null created: Date = null
@ -47,7 +47,7 @@ export default class ProjectModel extends AbstractModel<IProject> implements IPr
this.subscription = new SubscriptionModel(this.subscription) this.subscription = new SubscriptionModel(this.subscription)
} }
this.childProjects = this.childProjects.map(p => new ProjectModel(p)) this.childProjectIds = this.childProjects?.map(p => p.id) || []
this.created = new Date(this.created) this.created = new Date(this.created)
this.updated = new Date(this.updated) this.updated = new Date(this.updated)

View File

@ -34,6 +34,9 @@ export const useProjectStore = defineStore('project', () => {
const getProjectById = computed(() => { const getProjectById = computed(() => {
return (id: IProject['id']) => typeof projects.value[id] !== 'undefined' ? projects.value[id] : null return (id: IProject['id']) => typeof projects.value[id] !== 'undefined' ? projects.value[id] : null
}) })
const getChildProjects = computed(() => {
return (id: IProject['id']) => projectsArray.value.filter(p => p.parentProjectId === id) || []
})
const findProjectByExactname = computed(() => { const findProjectByExactname = computed(() => {
return (name: string) => { return (name: string) => {
@ -67,24 +70,27 @@ export const useProjectStore = defineStore('project', () => {
} }
if (updateChildren) { if (updateChildren) {
project.childProjects?.forEach(p => setProject(p)) // When projects are loaded from the api, they will include child projects
// in the `childProjects` property. We flatten them out into the project store here.
project.childProjects?.forEach(p => setProject(new ProjectModel(p)))
delete project.childProjects
} }
// if the project is a child project, we need to also set it in the parent // if the project is a child project, we need to also set it in the parent
if (project.parentProjectId) { if (project.parentProjectId) {
const parent = projects.value[project.parentProjectId] const parent = projects.value[project.parentProjectId]
let foundProject = false let foundProject = false
parent.childProjects = parent.childProjects?.map(p => { parent.childProjectIds = parent.childProjectIds?.forEach(p => {
if (p.id === project.id) { if (p.id === project.id) {
foundProject = true foundProject = true
return project
} }
return p
}) })
// If we hit this, the project now has a new parent project which it did not have before // If we hit this, the project now has a new parent project which it did not have before
if (!foundProject) { if (!foundProject) {
parent.childProjects.push(project) if (!parent.childProjectIds) {
parent.childProjectIds = []
}
parent.childProjectIds.push(project.id)
} }
setProject(parent, false) setProject(parent, false)
} }
@ -197,6 +203,7 @@ export const useProjectStore = defineStore('project', () => {
hasProjects: readonly(hasProjects), hasProjects: readonly(hasProjects),
getProjectById, getProjectById,
getChildProjects,
findProjectByExactname, findProjectByExactname,
searchProject, searchProject,