feature/projects-all-the-way-down #3323
|
@ -12,7 +12,7 @@
|
|||
>
|
||||
<template #searchResult="{option}">
|
||||
<span class="has-text-grey">
|
||||
{{ getParentProjects(option, projectStore).filter(p => p.id !== option.id).map(p => getProjectTitle(p) ).join(' > ') }} >
|
||||
{{ projectStore.getParentProjects(option).filter(p => p.id !== option.id).map(p => getProjectTitle(p) ).join(' > ') }} >
|
||||
</span>
|
||||
{{ getProjectTitle(option) }}
|
||||
</template>
|
||||
|
@ -27,7 +27,7 @@ import {useI18n} from 'vue-i18n'
|
|||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
import {useProjectStore} from '@/stores/projects'
|
||||
import {getProjectTitle, getParentProjects} from '@/helpers/getProjectTitle'
|
||||
import {getProjectTitle} from '@/helpers/getProjectTitle'
|
||||
|
||||
import ProjectModel from '@/models/project'
|
||||
|
||||
|
|
|
@ -13,16 +13,3 @@ export function getProjectTitle(project: IProject) {
|
|||
|
||||
return project.title
|
||||
}
|
||||
|
||||
export function getParentProjects(project: IProject, projectStore): IProject[] {
|
||||
let parents = []
|
||||
if (project.parentProjectId) {
|
||||
const parentProject = projectStore.getProjectById(project.parentProjectId)
|
||||
parents = getParentProjects(parentProject, projectStore)
|
||||
}
|
||||
|
||||
return [
|
||||
...parents,
|
||||
project,
|
||||
]
|
||||
}
|
||||
|
|
|
@ -47,9 +47,9 @@ export const useProjectStore = defineStore('project', () => {
|
|||
const searchProject = computed(() => {
|
||||
return (query: string, includeArchived = false) => {
|
||||
return search(query)
|
||||
?.filter(value => value > 0)
|
||||
.map(id => projects.value[id])
|
||||
.filter(project => project.isArchived === includeArchived)
|
||||
?.filter(value => value > 0)
|
||||
.map(id => projects.value[id])
|
||||
.filter(project => project.isArchived === includeArchived)
|
||||
|| []
|
||||
}
|
||||
})
|
||||
|
@ -65,21 +65,21 @@ export const useProjectStore = defineStore('project', () => {
|
|||
if (baseStore.currentProject?.id === project.id) {
|
||||
baseStore.setCurrentProject(project)
|
||||
}
|
||||
|
||||
|
||||
if (updateChildren) {
|
||||
project.childProjects?.forEach(p => setProject(p))
|
||||
}
|
||||
|
||||
|
||||
// if the project is a child project, we need to also set it in the parent
|
||||
|
||||
if (project.parentProjectId) {
|
||||
const parent = projects.value[project.parentProjectId]
|
||||
let foundProject = false
|
||||
dpschen
commented
The three lines above should be called via a deep watcher on the current project. Not as a side effect. The three lines above should be called via a deep watcher on the current project. Not as a side effect.
konrad
commented
You mean setting the current project in the base store? You mean setting the current project in the base store?
dpschen
commented
I mean:
It might be even better to make the currentProject a computed based on the store instead and only setting it via id (unsure here how to handle projects that are not saved yet) I mean:
1) remove this sideeffect of the `setProject` function:
```
if (baseStore.currentProject?.id === project.id) {
baseStore.setCurrentProject(project)
}
```
2) Instead add a watcher on the project that has the id of the current project.
```ts
watchEffect(() => baseStore.setCurrentProject(projects.value[baseStore.currentProject.id])
)
```
It might be even better to make the currentProject a computed based on the store instead and only setting it via id (unsure here how to handle projects that are not saved yet)
konrad
commented
I've now changed it to use a watcher.
That sounds like a good idea, but let's push that to another PR. I've now changed it to use a watcher.
> It might be even better to make the currentProject a computed based on the store instead and only setting it via id (unsure here how to handle projects that are not saved yet)
That sounds like a good idea, but let's push that to another PR.
konrad
commented
I've now changed it to use a watcher.
That sounds like a good idea, but let's push that to another PR. I've now changed it to use a watcher.
> It might be even better to make the currentProject a computed based on the store instead and only setting it via id (unsure here how to handle projects that are not saved yet)
That sounds like a good idea, but let's push that to another PR.
|
||||
parent.childProjects = parent.childProjects?.map(p => {
|
||||
if(p.id === project.id) {
|
||||
if (p.id === project.id) {
|
||||
foundProject = true
|
||||
return project
|
||||
}
|
||||
|
||||
|
||||
return p
|
||||
})
|
||||
// If we hit this, the project now has a new parent project which it did not have before
|
||||
|
@ -162,7 +162,7 @@ export const useProjectStore = defineStore('project', () => {
|
|||
cancel()
|
||||
}
|
||||
}
|
||||
dpschen
commented
When I read this first I thought that this implies that one project could have several parents. If I got it correct that's wrong. So how about When I read this first I thought that this implies that one project could have several parents. If I got it correct that's wrong. So how about `getAncestors` instead?
konrad
commented
I like that. Changed it. I like that. Changed it.
|
||||
|
||||
|
||||
async function loadProjects() {
|
||||
const cancel = setModuleLoading(setIsLoading)
|
||||
|
||||
|
@ -178,6 +178,18 @@ export const useProjectStore = defineStore('project', () => {
|
|||
}
|
||||
}
|
||||
|
||||
function getParentProjects(project: IProject): IProject[] {
|
||||
if (!project?.parentProjectId) {
|
||||
return [project]
|
||||
}
|
||||
|
||||
const parentProject = projects.value[project.parentProjectId]
|
||||
return [
|
||||
...getParentProjects(parentProject),
|
||||
project,
|
||||
]
|
||||
}
|
||||
|
||||
return {
|
||||
isLoading: readonly(isLoading),
|
||||
projects: readonly(projects),
|
||||
|
@ -196,6 +208,7 @@ export const useProjectStore = defineStore('project', () => {
|
|||
createProject,
|
||||
updateProject,
|
||||
deleteProject,
|
||||
getParentProjects,
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -215,6 +228,7 @@ export function useProject(projectId: MaybeRef<IProject['id']>) {
|
|||
)
|
||||
|
||||
const projectStore = useProjectStore()
|
||||
dpschen
commented
This changes project before calling update. was that intended? What happens if This changes project before calling update. was that intended? What happens if `parentProject.value.id` is undefined?
konrad
commented
It was not intended. I've changed it now so that it checks it before and provides a proper fallback. It was not intended. I've changed it now so that it checks it before and provides a proper fallback.
|
||||
|
||||
async function save() {
|
||||
await projectStore.updateProject(project)
|
||||
success({message: t('project.edit.success')})
|
||||
|
@ -229,5 +243,5 @@ export function useProject(projectId: MaybeRef<IProject['id']>) {
|
|||
|
||||
// support hot reloading
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept(acceptHMRUpdate(useProjectStore, import.meta.hot))
|
||||
import.meta.hot.accept(acceptHMRUpdate(useProjectStore, import.meta.hot))
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
ref="heading"
|
||||
/>
|
||||
<h6 class="subtitle" v-if="project?.id">
|
||||
<template v-for="p in getParentProjects(project, projectStore)">
|
||||
dpschen
commented
Shouldn't we still show the parent here? Shouldn't we still show the parent here?
konrad
commented
I've changed it now so that is shows this: (each project is clickable individually) For a hierarchy like this: I've changed it now so that is shows this:
![Screenshot_20230328_174428.png](/attachments/35babb55-b48a-49bf-a595-3fcc28da12dc)
(each project is clickable individually)
For a hierarchy like this:
![Screenshot_20230328_174646.png](/attachments/070d677e-d199-45ee-af6b-c0a6b3196681)
dpschen
commented
Can't see these images either Can't see these images either
konrad
commented
This starts to feel like a gitea bug... This starts to feel like a gitea bug...
|
||||
<template v-for="p in projectStore.getParentProjects(project)">
|
||||
dpschen
commented
This won't update dynamically. Should we change the This won't update dynamically. Should we change the `getParentProjects` to a computed `parentProjects` that automatically updates instead?
konrad
commented
I tried to change it but it fails with I tried to change it but it fails with `getAncestors is not a function`. Any idea?
konrad
commented
Actually this does update dynamically when the project changes. I've had a task open, moved the project to another parent project and it updated instantly. Actually this does update dynamically when the project changes. I've had a task open, moved the project to another parent project and it updated instantly.
|
||||
<router-link :to="{ name: 'project.index', params: { projectId: p.id } }">
|
||||
{{ getProjectTitle(p) }}
|
||||
</router-link>
|
||||
|
@ -488,7 +488,7 @@ import TaskSubscription from '@/components/misc/subscription.vue'
|
|||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||
|
||||
import {uploadFile} from '@/helpers/attachments'
|
||||
import {getProjectTitle, getParentProjects} from '@/helpers/getProjectTitle'
|
||||
import {getProjectTitle} from '@/helpers/getProjectTitle'
|
||||
import {scrollIntoView} from '@/helpers/scrollIntoView'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
|
|
See comment about having the data as sub projects from earlier.