diff --git a/frontend/src/components/project/ProjectWrapper.vue b/frontend/src/components/project/ProjectWrapper.vue index 44001db9b..35c6219f5 100644 --- a/frontend/src/components/project/ProjectWrapper.vue +++ b/frontend/src/components/project/ProjectWrapper.vue @@ -73,12 +73,12 @@ const baseStore = useBaseStore() const projectStore = useProjectStore() const currentProject = computed(() => { - return typeof baseStore.currentProject === 'undefined' ? { + return baseStore.currentProject || { id: 0, title: '', isArchived: false, maxPermission: null, - } : baseStore.currentProject + } }) useTitle(() => currentProject.value?.id ? getProjectTitle(currentProject.value) : '') diff --git a/frontend/src/components/project/views/ProjectKanban.vue b/frontend/src/components/project/views/ProjectKanban.vue index de1b3dbf1..30d8c8264 100644 --- a/frontend/src/components/project/views/ProjectKanban.vue +++ b/frontend/src/components/project/views/ProjectKanban.vue @@ -429,6 +429,7 @@ const canWrite = computed(() => baseStore.currentProject?.maxPermission > Permis const canCreateTasks = computed(() => canWrite.value && projectId.value > 0) const buckets = computed(() => kanbanStore.buckets) const loading = computed(() => kanbanStore.isLoading) +const projectIdWithFallback = computed(() => project.value?.id || projectId.value) const taskLoading = computed(() => taskStore.isLoading || taskPositionService.value.loading) @@ -553,7 +554,7 @@ async function updateTaskPosition(e) { taskId: newTask.id, bucketId: newTask.bucketId, projectViewId: props.viewId, - projectId: project.value.id, + projectId: projectIdWithFallback.value, })) Object.assign(newTask, updatedTaskBucket.task) newTask.bucketId = updatedTaskBucket.bucketId @@ -602,7 +603,7 @@ async function addTaskToBucket(bucketId: IBucket['id']) { const task = await taskStore.createNewTask({ title: newTaskText.value, bucketId, - projectId: project.value.id, + projectId: projectIdWithFallback.value, }) newTaskText.value = '' kanbanStore.addTaskToBucket(task) @@ -629,7 +630,7 @@ async function createNewBucket() { await kanbanStore.createBucket(new BucketModel({ title: newBucketTitle.value, - projectId: project.value.id, + projectId: projectIdWithFallback.value, projectViewId: props.viewId, })) newBucketTitle.value = '' @@ -649,7 +650,7 @@ async function deleteBucket() { await kanbanStore.deleteBucket({ bucket: new BucketModel({ id: bucketToDelete.value, - projectId: project.value.id, + projectId: projectIdWithFallback.value, projectViewId: props.viewId, }), params: params.value, @@ -802,7 +803,7 @@ async function toggleDoneBucket(bucket: IBucket) { ...view.value, doneBucketId, })) - + const views = project.value.views.map(v => v.id === view.value?.id ? updatedView : v) const updatedProject = { ...project.value, @@ -816,7 +817,7 @@ async function toggleDoneBucket(bucket: IBucket) { function collapseBucket(bucket: IBucket) { collapsedBuckets.value[bucket.id] = true - saveCollapsedBucketState(project.value.id, collapsedBuckets.value) + saveCollapsedBucketState(projectIdWithFallback.value, collapsedBuckets.value) } function unCollapseBucket(bucket: IBucket) { @@ -825,7 +826,7 @@ function unCollapseBucket(bucket: IBucket) { } collapsedBuckets.value[bucket.id] = false - saveCollapsedBucketState(project.value.id, collapsedBuckets.value) + saveCollapsedBucketState(projectIdWithFallback.value, collapsedBuckets.value) } diff --git a/frontend/src/composables/useRouteWithModal.ts b/frontend/src/composables/useRouteWithModal.ts index c3d82d659..4cfc6a441 100644 --- a/frontend/src/composables/useRouteWithModal.ts +++ b/frontend/src/composables/useRouteWithModal.ts @@ -62,7 +62,6 @@ export function useRouteWithModal() { const historyState = computed(() => route.fullPath ? window.history.state : undefined) function closeModal() { - // If the current project was changed because the user moved the currently opened task while coming from kanban, // we need to reflect that change in the route when they close the task modal. // The last route is only available as resolved string, therefore we need to use a regex for matching here @@ -70,31 +69,50 @@ export function useRouteWithModal() { const match = historyState.value?.back ? routeMatch.exec(historyState.value.back) : null - if (match !== null && baseStore.currentProject) { + if (match !== null && baseStore.currentProject && baseStore.currentProject.id !== 0) { let viewId: string | number = match[1] if (!viewId) { - viewId = projectStore.projects[baseStore.currentProject?.id].views[0]?.id + const project = projectStore.projects[baseStore.currentProject.id] + viewId = project?.views?.[0]?.id } - const newRoute = { - name: 'project.view', - params: { - projectId: baseStore.currentProject?.id, - viewId, - }, + // Only navigate if we have a valid project and view + if (baseStore.currentProject.id && viewId) { + const newRoute = { + name: 'project.view', + params: { + projectId: baseStore.currentProject.id, + viewId, + }, + } + + router.push(newRoute) + return } - router.push(newRoute) + } + + // Try browser history first + if (historyState.value?.back) { + router.back() return } - if (historyState.value) { - router.back() + // Try backdrop view + const backdropRoute = historyState.value?.backdropView && router.resolve(historyState.value.backdropView) + if (backdropRoute && backdropRoute.params?.projectId !== '0') { + router.push(backdropRoute) + return + } + + // Fallback to current project or home + if (baseStore.currentProject && baseStore.currentProject.id !== 0) { + router.push({ + name: 'project.index', + params: { projectId: baseStore.currentProject.id }, + }) } else { - const backdropRoute = historyState.value?.backdropView && router.resolve(historyState.value.backdropView) - if (backdropRoute) { - router.push(backdropRoute) - } + router.push({ name: 'home' }) } }