fix(kanban): opening a task from the kanban board and then reloading the page should not crash everything when then navigating back
continuous-integration/drone/push Build is passing Details

Before this fix, the following would not work:

1. Open the kanban view of a project
2. Click on a task to open it in a modal
3. Reload the page
4. Using your browser's back button, navigate back

Instead of showing the kanban board with the task modal closed, it would
navigate to `/projects/0/kanban` and crash.
This commit is contained in:
kolaente 2023-11-15 23:43:31 +01:00
parent 7e623d919e
commit 75262b716f
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
4 changed files with 32 additions and 19 deletions

View File

@ -39,7 +39,7 @@
</router-view> </router-view>
<modal <modal
:enabled="Boolean(currentModal)" :enabled="typeof currentModal !== 'undefined'"
@close="closeModal()" @close="closeModal()"
variant="scrolling" variant="scrolling"
class="task-detail-view-modal" class="task-detail-view-modal"

View File

@ -24,13 +24,18 @@ export function useRouteWithModal() {
// this is adapted from vue-router // this is adapted from vue-router
// https://github.com/vuejs/vue-router-next/blob/798cab0d1e21f9b4d45a2bd12b840d2c7415f38a/src/RouterView.ts#L125 // https://github.com/vuejs/vue-router-next/blob/798cab0d1e21f9b4d45a2bd12b840d2c7415f38a/src/RouterView.ts#L125
const routePropsOption = route.matched[0]?.props.default const routePropsOption = route.matched[0]?.props.default
const routeProps = routePropsOption let routeProps = undefined
? routePropsOption === true if (routePropsOption) {
? route.params if (routePropsOption === true) {
: typeof routePropsOption === 'function' routeProps = route.params
? routePropsOption(route) } else {
: routePropsOption if(typeof routePropsOption === 'function') {
: {} routeProps = routePropsOption(route)
} else {
routeProps = routePropsOption
}
}
}
if (typeof routeProps === 'undefined') { if (typeof routeProps === 'undefined') {
currentModal.value = undefined currentModal.value = undefined

View File

@ -37,7 +37,11 @@ const MigrationHandlerComponent = () => import('@/views/migrate/MigrationHandler
const ProjectList = () => import('@/views/project/ProjectList.vue') const ProjectList = () => import('@/views/project/ProjectList.vue')
const ProjectGantt = () => import('@/views/project/ProjectGantt.vue') const ProjectGantt = () => import('@/views/project/ProjectGantt.vue')
const ProjectTable = () => import('@/views/project/ProjectTable.vue') const ProjectTable = () => import('@/views/project/ProjectTable.vue')
const ProjectKanban = () => import('@/views/project/ProjectKanban.vue') // If we load the component async, using it as a backdrop view will not work. Instead, everything explodes
// with an error from the core saying "Cannot read properties of undefined (reading 'parentNode')"
// Of course, with no clear indicator of where the problem comes from.
// const ProjectKanban = () => import('@/views/project/ProjectKanban.vue')
import ProjectKanban from '@/views/project/ProjectKanban.vue'
const ProjectInfo = () => import('@/views/project/ProjectInfo.vue') const ProjectInfo = () => import('@/views/project/ProjectInfo.vue')
// Project Settings // Project Settings

View File

@ -1,7 +1,7 @@
<template> <template>
<ProjectWrapper <ProjectWrapper
class="project-kanban" class="project-kanban"
:project-id="project.id" :project-id="projectId"
viewName="kanban" viewName="kanban"
> >
<template #header> <template #header>
@ -330,9 +330,14 @@ const bucketDraggableComponentData = computed(() => ({
{'dragging-disabled': !canWrite.value}, {'dragging-disabled': !canWrite.value},
], ],
})) }))
const {
projectId = undefined,
} = defineProps<{
projectId: number,
}>()
const canWrite = computed(() => baseStore.currentProject?.maxRight > Rights.READ) const canWrite = computed(() => baseStore.currentProject?.maxRight > Rights.READ)
const project = computed(() => baseStore.currentProject) const project = computed(() => projectId ? projectStore.projects[projectId]: null)
const buckets = computed(() => kanbanStore.buckets) const buckets = computed(() => kanbanStore.buckets)
const loading = computed(() => kanbanStore.isLoading) const loading = computed(() => kanbanStore.isLoading)
@ -342,10 +347,9 @@ const taskLoading = computed(() => taskStore.isLoading)
watch( watch(
() => ({ () => ({
params: params.value, params: params.value,
project: project.value, projectId,
}), }),
({params, project}) => { ({params}) => {
const projectId = project.id
if (projectId === undefined || Number(projectId) === 0) { if (projectId === undefined || Number(projectId) === 0) {
return return
} }
@ -396,7 +400,7 @@ function updateTasks(bucketId: IBucket['id'], tasks: IBucket['tasks']) {
async function updateTaskPosition(e) { async function updateTaskPosition(e) {
drag.value = false drag.value = false
// While we could just pass the bucket index in through the function call, this would not give us the // While we could just pass the bucket index in through the function call, this would not give us the
// new bucket id when a task has been moved between buckets, only the new bucket. Using the data-bucket-id // new bucket id when a task has been moved between buckets, only the new bucket. Using the data-bucket-id
// of the drop target works all the time. // of the drop target works all the time.
const bucketIndex = parseInt(e.to.dataset.bucketIndex) const bucketIndex = parseInt(e.to.dataset.bucketIndex)
@ -450,7 +454,7 @@ async function updateTaskPosition(e) {
try { try {
await taskStore.update(newTask) await taskStore.update(newTask)
// Make sure the first and second task don't both get position 0 assigned // Make sure the first and second task don't both get position 0 assigned
if(newTaskIndex === 0 && taskAfter !== null && taskAfter.kanbanPosition === 0) { if(newTaskIndex === 0 && taskAfter !== null && taskAfter.kanbanPosition === 0) {
const taskAfterAfter = newBucket.tasks[newTaskIndex + 2] ?? null const taskAfterAfter = newBucket.tasks[newTaskIndex + 2] ?? null
@ -480,7 +484,7 @@ async function addTaskToBucket(bucketId: IBucket['id']) {
return return
} }
newTaskError.value[bucketId] = false newTaskError.value[bucketId] = false
const task = await taskStore.createNewTask({ const task = await taskStore.createNewTask({
title: newTaskText.value, title: newTaskText.value,
bucketId, bucketId,
@ -619,7 +623,7 @@ async function toggleDoneBucket(bucket: IBucket) {
const doneBucketId = project.value.doneBucketId === bucket.id const doneBucketId = project.value.doneBucketId === bucket.id
? 0 ? 0
: bucket.id : bucket.id
await projectStore.updateProject({ await projectStore.updateProject({
...project.value, ...project.value,
doneBucketId, doneBucketId,
@ -722,7 +726,7 @@ $filter-container-height: '1rem - #{$switch-view-height}';
} }
&:last-of-type { &:last-of-type {
padding-bottom: .5rem; padding-bottom: .5rem;
} }
} }
.no-move { .no-move {