feat: implement modals with vue router 4 #816
|
@ -1,8 +1,12 @@
|
|||
<template>
|
||||
<div>
|
||||
<a @click="$store.commit('menuActive', false)" class="menu-hide-button" v-if="menuActive">
|
||||
<BaseButton
|
||||
v-if="menuActive"
|
||||
@click="$store.commit('menuActive', false)"
|
||||
class="menu-hide-button"
|
||||
>
|
||||
<icon icon="times" />
|
||||
</a>
|
||||
</BaseButton>
|
||||
<div
|
||||
:class="{'has-background': background}"
|
||||
:style="{'background-image': background && `url(${background})`}"
|
||||
|
@ -16,7 +20,11 @@
|
|||
]"
|
||||
class="app-content"
|
||||
>
|
||||
<a @click="$store.commit('menuActive', false)" class="mobile-overlay" v-if="menuActive"></a>
|
||||
<BaseButton
|
||||
v-if="menuActive"
|
||||
@click="$store.commit('menuActive', false)"
|
||||
dpschen marked this conversation as resolved
Outdated
|
||||
class="mobile-overlay"
|
||||
/>
|
||||
|
||||
<quick-actions/>
|
||||
|
||||
|
@ -28,7 +36,9 @@
|
|||
</router-view>
|
||||
|
||||
<transition name="modal">
|
||||
<component v-if="currentModal" :is="currentModal" />
|
||||
<TaskDetailViewModal v-if="currentModal" >
|
||||
dpschen marked this conversation as resolved
Outdated
konrad
commented
I suppose this is used because we don't have a modal wrapper? Using "TaskDetailView" in the general content with component feels a little out of place IMHO 😅 I suppose this is used because we don't have a modal wrapper? Using "TaskDetailView" in the general content with component feels a little out of place IMHO 😅
dpschen
commented
See it like the router-view conponent of vue router: it's also not a view itself. regardless I just wanted to make the most simple change. I guess it should be renamed to something like modal-view and maybe even merged with modal 🤔 - but that can also happen later. See it like the router-view conponent of vue router: it's also not a view itself. regardless I just wanted to make the most simple change. I guess it should be renamed to something like modal-view and maybe even merged with modal 🤔 - but that can also happen later.
dpschen
commented
I removed the component As a result this is obsolete now =) I removed the component `task-detail-view-modal` in https://kolaente.dev/vikunja/frontend/commit/6827390b77ae6e186e7b0163651c19ca9a247d2f and was able to merge it with the modal itself.
As a result this is obsolete now =)
|
||||
<component :is="currentModal" />
|
||||
</TaskDetailViewModal>
|
||||
</transition>
|
||||
|
||||
<a
|
||||
|
@ -52,25 +62,23 @@ import {useEventListener} from '@vueuse/core'
|
|||
import {CURRENT_LIST, KEYBOARD_SHORTCUTS_ACTIVE, MENU_ACTIVE} from '@/store/mutation-types'
|
||||
import Navigation from '@/components/home/navigation.vue'
|
||||
import QuickActions from '@/components/quick-actions/quick-actions.vue'
|
||||
import TaskDetailViewModal from '@/views/tasks/TaskDetailViewModal.vue'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
|
||||
function useRouteWithModal() {
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const historyState = computed(() => route.fullPath && window.history.state)
|
||||
const backdropView = computed(() => route.fullPath && window.history.state.backdropView)
|
||||
|
||||
const routeWithModal = computed(() => {
|
||||
if (historyState.value.backdropView) {
|
||||
return router.resolve(historyState.value.backdropView)
|
||||
} else {
|
||||
return route
|
||||
}
|
||||
return backdropView.value
|
||||
? router.resolve(backdropView.value)
|
||||
: route
|
||||
})
|
||||
|
||||
const currentModal = shallowRef<VNode>()
|
||||
watchEffect(() => {
|
||||
const hasBackdropView = historyState.value.backdropView
|
||||
|
||||
if (!hasBackdropView) {
|
||||
if (!backdropView.value) {
|
||||
currentModal.value = undefined
|
||||
return
|
||||
}
|
||||
|
|
|
@ -170,7 +170,8 @@ export default {
|
|||
return {
|
||||
name: 'task.detail',
|
||||
params: { id: this.task.id },
|
||||
state: { backdropView: this.$router.currentRoute.value.fullPath },
|
||||
// TODO: re-enable opening task detail in modal
|
||||
// state: { backdropView: this.$router.currentRoute.value.fullPath },
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ import DataExportDownload from '../views/user/DataExportDownload.vue'
|
|||
import ShowTasksInRangeComponent from '../views/tasks/ShowTasksInRange.vue'
|
||||
import LinkShareAuthComponent from '../views/sharing/LinkSharingAuth.vue'
|
||||
import ListNamespaces from '../views/namespaces/ListNamespaces.vue'
|
||||
import TaskDetailViewModal from '../views/tasks/TaskDetailViewModal.vue'
|
||||
import TaskDetailView from '../views/tasks/TaskDetailView.vue'
|
||||
// Team Handling
|
||||
import ListTeamsComponent from '../views/teams/ListTeams.vue'
|
||||
// Label Handling
|
||||
|
@ -242,7 +242,7 @@ const router = createRouter({
|
|||
{
|
||||
path: '/tasks/:id',
|
||||
name: 'task.detail',
|
||||
component: TaskDetailViewModal,
|
||||
component: TaskDetailView,
|
||||
props: route => ({ taskId: parseInt(route.params.id as string) }),
|
||||
},
|
||||
{
|
||||
|
|
|
@ -181,7 +181,6 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { toRef, computed, Ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import { useStorage } from '@vueuse/core'
|
||||
|
||||
|
@ -273,14 +272,15 @@ function sort(property : keyof SortBy) {
|
|||
}
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
// TODO: re-enable opening task detail in modal
|
||||
// const router = useRouter()
|
||||
const taskDetailRoutes = computed(() => Object.fromEntries(
|
||||
tasks.value.map(({id}) => ([
|
||||
id,
|
||||
{
|
||||
name: 'task.detail',
|
||||
params: { id },
|
||||
state: { backdropView: router.currentRoute.value.fullPath },
|
||||
// state: { backdropView: router.currentRoute.value.fullPath },
|
||||
},
|
||||
])),
|
||||
))
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
variant="scrolling"
|
||||
class="task-detail-view-modal"
|
||||
>
|
||||
<a @click="close()" class="close">
|
||||
<BaseButton @click="close()" class="close">
|
||||
<icon icon="times"/>
|
||||
</a>
|
||||
<task-detail-view :task-id="props.taskId"/>
|
||||
</BaseButton>
|
||||
<slot />
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
|
@ -15,14 +15,7 @@
|
|||
import {computed} from 'vue'
|
||||
import {useRouter, useRoute} from 'vue-router'
|
||||
|
||||
import TaskDetailView from './TaskDetailView.vue'
|
||||
|
||||
const props = defineProps({
|
||||
taskId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const historyState = computed(() => route.fullPath && window.history.state)
|
||||
|
|
Reference in New Issue
I don't think it is, we should make sure the modal views keep their transition though. Might make sense to include that in the modal component itself?
Either that or put the transition inside something like a provider component. In that we could use the new teleport component. I was always using portal-vue in vue 2 for this kind of stuff.
I think using the teleport component allows for a cleaner solution since there are situations where you want a transition handled by the route and others where you want to have it handled by the outer component (like delete modals).