From 5a0c0eff9f0bb822a597164c2b87da7480ce4498 Mon Sep 17 00:00:00 2001 From: Dominik Pschenitschni Date: Sun, 3 Oct 2021 15:54:24 +0200 Subject: [PATCH] feat: implement modals with vue router 4 This is an implementation of the modals with the new possibilities of vue router 3. See: https://github.com/vuejs/vue-router/issues/703#issuecomment-865066913 for a better explanation and the linked example implementation: https://github.com/vuejs/vue-router-next/blob/master/e2e/modal/index.ts --- src/components/home/contentAuth.vue | 21 +- src/components/list/partials/filter-popup.vue | 3 +- .../misc/keyboard-shortcuts/index.vue | 38 ++-- .../misc/keyboard-shortcuts/shortcuts.js | 9 +- src/components/tasks/edit-task.vue | 11 +- src/components/tasks/partials/kanban-card.vue | 9 +- .../tasks/partials/singleTaskInList.vue | 13 +- src/router/index.ts | 184 ------------------ src/views/Home.vue | 7 + src/views/list/ShowList.vue | 23 ++- src/views/list/views/Gantt.vue | 18 +- src/views/list/views/Kanban.vue | 19 +- src/views/list/views/List.vue | 23 ++- src/views/list/views/Table.vue | 25 ++- src/views/tasks/TaskDetailViewModal.vue | 33 +--- 15 files changed, 152 insertions(+), 284 deletions(-) diff --git a/src/components/home/contentAuth.vue b/src/components/home/contentAuth.vue index d3f0dc8a..3dac25ff 100644 --- a/src/components/home/contentAuth.vue +++ b/src/components/home/contentAuth.vue @@ -20,8 +20,9 @@ - + + @@ -50,6 +51,24 @@ import {CURRENT_LIST, KEYBOARD_SHORTCUTS_ACTIVE, MENU_ACTIVE} from '@/store/muta import Navigation from '@/components/home/navigation.vue' import QuickActions from '@/components/quick-actions/quick-actions.vue' +function useRouteWithModal() { + const router = useRouter() + const route = useRoute() + const historyState = computed(() => route.fullPath && window.history.state) + + const routeWithModal = computed(() => { + if (historyState.value.backgroundView) { + return router.resolve(historyState.value.backgroundView) + } else { + return route + } + }) + + return { routeWithModal } +} + +useRouteWithModal() + const store = useStore() const background = computed(() => store.state.background) diff --git a/src/components/list/partials/filter-popup.vue b/src/components/list/partials/filter-popup.vue index efbfcbe3..d4caf9b4 100644 --- a/src/components/list/partials/filter-popup.vue +++ b/src/components/list/partials/filter-popup.vue @@ -29,9 +29,10 @@ diff --git a/src/components/misc/keyboard-shortcuts/shortcuts.js b/src/components/misc/keyboard-shortcuts/shortcuts.js index bcc5014b..06a3426c 100644 --- a/src/components/misc/keyboard-shortcuts/shortcuts.js +++ b/src/components/misc/keyboard-shortcuts/shortcuts.js @@ -5,7 +5,6 @@ const ctrl = isAppleDevice() ? '⌘' : 'ctrl' export const KEYBOARD_SHORTCUTS = [ { title: 'keyboardShortcuts.general', - available: () => null, shortcuts: [ { title: 'keyboardShortcuts.toggleMenu', @@ -55,13 +54,7 @@ export const KEYBOARD_SHORTCUTS = [ }, { title: 'keyboardShortcuts.task.title', - available: (route) => [ - 'task.detail', - 'task.list.detail', - 'task.gantt.detail', - 'task.kanban.detail', - 'task.detail', - ].includes(route.name), + available: (route) => route.name === 'task.detail', shortcuts: [ { title: 'keyboardShortcuts.task.assign', diff --git a/src/components/tasks/edit-task.vue b/src/components/tasks/edit-task.vue index 90f6adb7..6ebe4110 100644 --- a/src/components/tasks/edit-task.vue +++ b/src/components/tasks/edit-task.vue @@ -67,7 +67,7 @@ {{ $t('task.openDetail') }} @@ -102,6 +102,15 @@ export default { taskEditTask: TaskModel, } }, + computed: { + taskDetailRoute() { + return { + name: 'task.detail', + params: { id: this.taskEditTask.id }, + state: { backgroundView: this.$router.currentRoute.value.fullPath }, + } + }, + }, components: { ColorPicker, Reminders, diff --git a/src/components/tasks/partials/kanban-card.vue b/src/components/tasks/partials/kanban-card.vue index 96e73a99..d0edae3e 100644 --- a/src/components/tasks/partials/kanban-card.vue +++ b/src/components/tasks/partials/kanban-card.vue @@ -7,8 +7,8 @@ 'has-light-text': !colorIsDark(task.hexColor) && task.hexColor !== `#${task.defaultColor}` && task.hexColor !== task.defaultColor, }" :style="{'background-color': task.hexColor !== '#' && task.hexColor !== `#${task.defaultColor}` ? task.hexColor : false}" - @click.ctrl="() => toggleTaskDone(task)" @click.exact="() => $router.push({ name: 'task.kanban.detail', params: { id: task.id } })" + @click.ctrl="() => toggleTaskDone(task)" @click.meta="() => toggleTaskDone(task)" > @@ -112,6 +112,13 @@ export default { this.loadingInternal = false } }, + openTaskDetail() { + this.$router.push({ + name: 'task.detail', + params: { id: this.task.id }, + state: { backgroundView: this.$router.currentRoute.value.fullPath }, + }) + }, }, } diff --git a/src/components/tasks/partials/singleTaskInList.vue b/src/components/tasks/partials/singleTaskInList.vue index 9e955d5c..168386e6 100644 --- a/src/components/tasks/partials/singleTaskInList.vue +++ b/src/components/tasks/partials/singleTaskInList.vue @@ -8,7 +8,7 @@ > @@ -126,10 +126,6 @@ export default { type: Boolean, default: false, }, - taskDetailRoute: { - type: String, - default: 'task.list.detail', - }, showList: { type: Boolean, default: false, @@ -167,6 +163,13 @@ export default { title: '', } : this.$store.state.currentList }, + taskDetailRoute() { + return { + name: 'task.detail', + params: { id: this.task.id }, + state: { backgroundView: this.$router.currentRoute.value.fullPath }, + } + }, }, methods: { async markAsDone(checked) { diff --git a/src/router/index.ts b/src/router/index.ts index 21e4a96a..43340e7b 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -13,7 +13,6 @@ import DataExportDownload from '../views/user/DataExportDownload' // Tasks import ShowTasksInRangeComponent from '../views/tasks/ShowTasksInRange' import LinkShareAuthComponent from '../views/sharing/LinkSharingAuth' -import TaskDetailViewModal from '../views/tasks/TaskDetailViewModal' import TaskDetailView from '../views/tasks/TaskDetailView' import ListNamespaces from '../views/namespaces/ListNamespaces' // Team Handling @@ -315,204 +314,21 @@ const router = createRouter({ path: '/lists/:listId/list', name: 'list.list', component: List, - children: [ - { - path: '/tasks/:id', - name: 'task.list.detail', - component: TaskDetailViewModal, - }, - { - path: '/lists/:listId/settings/edit', - name: 'list.list.settings.edit', - component: ListSettingEdit, - }, - { - path: '/lists/:listId/settings/background', - name: 'list.list.settings.background', - component: ListSettingBackground, - }, - { - path: '/lists/:listId/settings/duplicate', - name: 'list.list.settings.duplicate', - component: ListSettingDuplicate, - }, - { - path: '/lists/:listId/settings/share', - name: 'list.list.settings.share', - component: ListSettingShare, - }, - { - path: '/lists/:listId/settings/delete', - name: 'list.list.settings.delete', - component: ListSettingDelete, - }, - { - path: '/lists/:listId/settings/archive', - name: 'list.list.settings.archive', - component: ListSettingArchive, - }, - { - path: '/lists/:listId/settings/edit', - name: 'filter.list.settings.edit', - component: FilterEdit, - }, - { - path: '/lists/:listId/settings/delete', - name: 'filter.list.settings.delete', - component: FilterDelete, - }, - ], }, { path: '/lists/:listId/gantt', name: 'list.gantt', component: Gantt, - children: [ - { - path: '/tasks/:id', - name: 'task.gantt.detail', - component: TaskDetailViewModal, - }, - { - path: '/lists/:listId/settings/edit', - name: 'list.gantt.settings.edit', - component: ListSettingEdit, - }, - { - path: '/lists/:listId/settings/background', - name: 'list.gantt.settings.background', - component: ListSettingBackground, - }, - { - path: '/lists/:listId/settings/duplicate', - name: 'list.gantt.settings.duplicate', - component: ListSettingDuplicate, - }, - { - path: '/lists/:listId/settings/share', - name: 'list.gantt.settings.share', - component: ListSettingShare, - }, - { - path: '/lists/:listId/settings/delete', - name: 'list.gantt.settings.delete', - component: ListSettingDelete, - }, - { - path: '/lists/:listId/settings/archive', - name: 'list.gantt.settings.archive', - component: ListSettingArchive, - }, - { - path: '/lists/:listId/settings/edit', - name: 'filter.gantt.settings.edit', - component: FilterEdit, - }, - { - path: '/lists/:listId/settings/delete', - name: 'filter.gantt.settings.delete', - component: FilterDelete, - }, - ], }, { path: '/lists/:listId/table', name: 'list.table', component: Table, - children: [ - { - path: '/lists/:listId/settings/edit', - name: 'list.table.settings.edit', - component: ListSettingEdit, - }, - { - path: '/lists/:listId/settings/background', - name: 'list.table.settings.background', - component: ListSettingBackground, - }, - { - path: '/lists/:listId/settings/duplicate', - name: 'list.table.settings.duplicate', - component: ListSettingDuplicate, - }, - { - path: '/lists/:listId/settings/share', - name: 'list.table.settings.share', - component: ListSettingShare, - }, - { - path: '/lists/:listId/settings/delete', - name: 'list.table.settings.delete', - component: ListSettingDelete, - }, - { - path: '/lists/:listId/settings/archive', - name: 'list.table.settings.archive', - component: ListSettingArchive, - }, - { - path: '/lists/:listId/settings/edit', - name: 'filter.table.settings.edit', - component: FilterEdit, - }, - { - path: '/lists/:listId/settings/delete', - name: 'filter.table.settings.delete', - component: FilterDelete, - }, - ], }, { path: '/lists/:listId/kanban', name: 'list.kanban', component: Kanban, - children: [ - { - path: '/tasks/:id', - name: 'task.kanban.detail', - component: TaskDetailViewModal, - }, - { - path: '/lists/:listId/settings/edit', - name: 'list.kanban.settings.edit', - component: ListSettingEdit, - }, - { - path: '/lists/:listId/settings/background', - name: 'list.kanban.settings.background', - component: ListSettingBackground, - }, - { - path: '/lists/:listId/settings/duplicate', - name: 'list.kanban.settings.duplicate', - component: ListSettingDuplicate, - }, - { - path: '/lists/:listId/settings/share', - name: 'list.kanban.settings.share', - component: ListSettingShare, - }, - { - path: '/lists/:listId/settings/delete', - name: 'list.kanban.settings.delete', - component: ListSettingDelete, - }, - { - path: '/lists/:listId/settings/archive', - name: 'list.kanban.settings.archive', - component: ListSettingArchive, - }, - { - path: '/lists/:listId/settings/edit', - name: 'filter.kanban.settings.edit', - component: FilterEdit, - }, - { - path: '/lists/:listId/settings/delete', - name: 'filter.kanban.settings.delete', - component: FilterDelete, - }, - ], }, ], }, diff --git a/src/views/Home.vue b/src/views/Home.vue index f3d2b3ec..d6a63f83 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -51,6 +51,10 @@ + + + + @@ -67,6 +71,9 @@ import {getHistory} from '@/modules/listHistory' import {parseDateOrNull} from '@/helpers/parseDateOrNull' import {formatDateShort, formatDateSince} from '@/helpers/time/formatDate' import {useDateTimeSalutation} from '@/composables/useDateTimeSalutation' +import TaskDetailViewModal, { useShowModal } from '@/views/tasks/TaskDetailViewModal.vue' + +const showTaskDetail = useShowModal() const welcome = useDateTimeSalutation() diff --git a/src/views/list/ShowList.vue b/src/views/list/ShowList.vue index d0c1d20f..c5e41ff9 100644 --- a/src/views/list/ShowList.vue +++ b/src/views/list/ShowList.vue @@ -8,28 +8,28 @@ {{ $t('list.list.title') }} {{ $t('list.gantt.title') }} {{ $t('list.table.title') }} {{ $t('list.kanban.title') }} @@ -69,6 +69,11 @@ export default { }, }, computed: { + currentListType() { + // default: 'list', + return '' + }, + // Computed property to let "listId" always have a value listId() { return typeof this.$route.params.listId === 'undefined' ? 0 : this.$route.params.listId @@ -113,11 +118,11 @@ export default { this.$store.commit('kanban/setListId', 0) } - // When clicking again on a list in the menu, there would be no list view selected which means no list - // at all. Users will then have to click on the list view menu again which is quite confusing. - if (this.$route.name === 'list.index') { - return this.replaceListView() - } + // // When clicking again on a list in the menu, there would be no list view selected which means no list + // // at all. Users will then have to click on the list view menu again which is quite confusing. + // if (this.$route.name === 'list.index') { + // return this.replaceListView() + // } // Don't load the list if we either already loaded it or aren't dealing with a list at all currently and // the currently loaded list has the right set. diff --git a/src/views/list/views/Gantt.vue b/src/views/list/views/Gantt.vue index b3628238..4f89fbf7 100644 --- a/src/views/list/views/Gantt.vue +++ b/src/views/list/views/Gantt.vue @@ -52,13 +52,9 @@ :show-taskswithout-dates="showTaskswithoutDates" /> - - - - - - - + + + @@ -69,12 +65,20 @@ import flatPickr from 'vue-flatpickr-component' import Fancycheckbox from '../../../components/input/fancycheckbox' import {saveListView} from '@/helpers/saveListView' +import TaskDetailViewModal, { useShowModal } from '@/views/tasks/TaskDetailViewModal.vue' + export default { name: 'Gantt', components: { Fancycheckbox, flatPickr, GanttChart, + TaskDetailViewModal, + }, + setup() { + return { + showTaskDetail: useShowModal(), + } }, created() { // Save the current list view to local storage diff --git a/src/views/list/views/Kanban.vue b/src/views/list/views/Kanban.vue index 298ff48b..bdb570fe 100644 --- a/src/views/list/views/Kanban.vue +++ b/src/views/list/views/Kanban.vue @@ -204,18 +204,12 @@ - - - - - - - + @@ -242,6 +236,7 @@ import Dropdown from '@/components/misc/dropdown.vue' import {getCollapsedBucketState, saveCollapsedBucketState} from '@/helpers/saveCollapsedBucketState' import {calculateItemPosition} from '../../../helpers/calculateItemPosition' import KanbanCard from '@/components/tasks/partials/kanban-card' +import TaskDetailViewModal, { useShowModal } from '@/views/tasks/TaskDetailViewModal.vue' const DRAG_OPTIONS = { // sortable options @@ -261,6 +256,7 @@ export default { Dropdown, FilterPopup, draggable, + TaskDetailViewModal, }, data() { return { @@ -296,6 +292,13 @@ export default { }, } }, + + setup() { + return { + showTaskDetail: useShowModal(), + } + }, + created() { // Save the current list view to local storage // We use local storage and not vuex here to make it persistent across reloads. diff --git a/src/views/list/views/List.vue b/src/views/list/views/List.vue index d61a39e8..ff59e46e 100644 --- a/src/views/list/views/List.vue +++ b/src/views/list/views/List.vue @@ -90,7 +90,6 @@ :disabled="!canWrite" :the-task="t" @taskUpdated="updateTasks" - task-detail-route="task.detail" > @@ -147,8 +143,8 @@ import FilterPopup from '@/components/list/partials/filter-popup.vue' import {HAS_TASKS} from '@/store/mutation-types' import Nothing from '@/components/misc/nothing.vue' import Pagination from '@/components/misc/pagination.vue' -import Popup from '@/components/misc/popup' -import { ALPHABETICAL_SORT } from '@/components/list/partials/filters' +import {ALPHABETICAL_SORT} from '@/components/list/partials/filters.vue' +import TaskDetailViewModal, { useShowModal } from '@/views/tasks/TaskDetailViewModal.vue' import draggable from 'vuedraggable' import {calculateItemPosition} from '../../../helpers/calculateItemPosition' @@ -192,7 +188,6 @@ export default { taskList, ], components: { - Popup, Nothing, FilterPopup, SingleTaskInList, @@ -200,7 +195,15 @@ export default { AddTask, draggable, Pagination, + TaskDetailViewModal, }, + + setup() { + return { + showTaskDetail: useShowModal(), + } + }, + created() { // Save the current list view to local storage // We use local storage and not vuex here to make it persistent across reloads. diff --git a/src/views/list/views/Table.vue b/src/views/list/views/Table.vue index b15b0a1b..943dd773 100644 --- a/src/views/list/views/Table.vue +++ b/src/views/list/views/Table.vue @@ -120,7 +120,7 @@ - + @@ -133,7 +133,7 @@ - {{ t.title }} + {{ t.title }} @@ -185,6 +185,8 @@