fix: close modal
This commit is contained in:
parent
b264065d7e
commit
345542cbbd
|
@ -5,12 +5,7 @@ export default { inheritAttrs: false }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useAttrs } from 'vue'
|
|
||||||
|
|
||||||
defineProps<{ is: any }>()
|
defineProps<{ is: any }>()
|
||||||
|
|
||||||
const attrs = useAttrs()
|
|
||||||
console.log(JSON.parse(JSON.stringify(attrs)))
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -32,16 +32,14 @@
|
||||||
|
|
||||||
<quick-actions/>
|
<quick-actions/>
|
||||||
|
|
||||||
<router-view :route="routeWithModal" v-slot="{ Component }">
|
<router-view v-if="routeWithModal" :route="routeWithModal" v-slot="{ Component }">
|
||||||
<keep-alive :include="['list.list', 'list.gantt', 'list.table', 'list.kanban']">
|
<!-- <keep-alive :include="['list.list', 'list.gantt', 'list.table', 'list.kanban']"> -->
|
||||||
<component :is="Component"/>
|
<component :is="Component"/>
|
||||||
</keep-alive>
|
<!-- test -->
|
||||||
|
<!-- </keep-alive> -->
|
||||||
</router-view>
|
</router-view>
|
||||||
|
|
||||||
<component
|
<component :is="currentModal" />
|
||||||
:is="currentModal"
|
|
||||||
@close="closeModal()"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="keyboard-shortcuts-button d-print-none"
|
class="keyboard-shortcuts-button d-print-none"
|
||||||
|
@ -69,7 +67,7 @@ import {useLabelStore} from '@/stores/labels'
|
||||||
import {useRouteWithModal} from '@/composables/useRouteWithModal'
|
import {useRouteWithModal} from '@/composables/useRouteWithModal'
|
||||||
import {useRenewTokenOnFocus} from '@/composables/useRenewTokenOnFocus'
|
import {useRenewTokenOnFocus} from '@/composables/useRenewTokenOnFocus'
|
||||||
|
|
||||||
const {routeWithModal, currentModal, closeModal} = useRouteWithModal()
|
const {routeWithModal, currentModal} = useRouteWithModal()
|
||||||
|
|
||||||
const baseStore = useBaseStore()
|
const baseStore = useBaseStore()
|
||||||
const background = computed(() => baseStore.background)
|
const background = computed(() => baseStore.background)
|
||||||
|
|
|
@ -1,56 +1,112 @@
|
||||||
import { computed, shallowRef, watchEffect, h, type VNode } from 'vue'
|
import { computed, shallowRef, watch, h, type VNode, ref } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter, loadRouteLocation, type RouteLocationNormalizedLoaded, type RouteLocationRaw } from 'vue-router'
|
||||||
|
import router from '@/router'
|
||||||
|
|
||||||
|
// this is adapted from vue-router
|
||||||
|
// https://github.com/vuejs/vue-router-next/blob/798cab0d1e21f9b4d45a2bd12b840d2c7415f38a/src/RouterView.ts#L125
|
||||||
|
function getRouteProps(route: RouteLocationNormalizedLoaded) {
|
||||||
|
const routePropsOption = route.matched[0]?.props.default
|
||||||
|
return routePropsOption
|
||||||
|
? routePropsOption === true
|
||||||
|
? route.params
|
||||||
|
: typeof routePropsOption === 'function'
|
||||||
|
? routePropsOption(route)
|
||||||
|
: routePropsOption
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveAndLoadRoute(route: RouteLocationRaw) {
|
||||||
|
return loadRouteLocation(router.resolve(route))
|
||||||
|
}
|
||||||
|
|
||||||
export function useRouteWithModal() {
|
export function useRouteWithModal() {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const backdropView = computed(() => route.fullPath && window.history.state.backdropView)
|
|
||||||
|
const backdropView = computed<RouteLocationRaw | undefined>(() => {
|
||||||
const routeWithModal = computed(() => {
|
// every time the fullPath changes we check the history state
|
||||||
return backdropView.value
|
// this happens also initially
|
||||||
? router.resolve(backdropView.value)
|
return route.fullPath
|
||||||
: route
|
? window.history.state?.backdropView
|
||||||
|
: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const routerIsReady = ref(false)
|
||||||
|
router.isReady().then(() => {
|
||||||
|
routerIsReady.value = true
|
||||||
|
})
|
||||||
|
|
||||||
|
const baseRoute = shallowRef<RouteLocationNormalizedLoaded>()
|
||||||
|
watch(
|
||||||
|
[backdropView, routerIsReady],
|
||||||
|
async () => {
|
||||||
|
if (routerIsReady.value === false || !route.fullPath) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backdropView.value === undefined) {
|
||||||
|
if (route.meta?.showAsModal !== true) {
|
||||||
|
baseRoute.value = route
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO: maybe load parent route here in the future,
|
||||||
|
// via: route.matched[route.matched.length - 2]
|
||||||
|
// see: https://router.vuejs.org/guide/migration/#removal-of-parent-from-route-locations
|
||||||
|
baseRoute.value = await resolveAndLoadRoute({ name: 'home' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// we get the resolved route from the fullpath
|
||||||
|
// and wait for the route component to be loaded before we assign it
|
||||||
|
baseRoute.value = await resolveAndLoadRoute(backdropView.value)
|
||||||
|
},
|
||||||
|
{immediate: true},
|
||||||
|
)
|
||||||
|
|
||||||
|
const backdropRoute = computed(() => route.fullPath !== baseRoute.value?.fullPath ? baseRoute.value : undefined)
|
||||||
|
|
||||||
const currentModal = shallowRef<VNode>()
|
const currentModal = shallowRef<VNode>()
|
||||||
watchEffect(() => {
|
watch(
|
||||||
if (!backdropView.value) {
|
[backdropRoute, baseRoute, route],
|
||||||
currentModal.value = undefined
|
() => {
|
||||||
return
|
if (routerIsReady.value === false || !route.fullPath || !backdropRoute.value) {
|
||||||
|
currentModal.value = undefined
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = getRouteProps(route)
|
||||||
|
|
||||||
|
props.backdropView = backdropRoute.value
|
||||||
|
props.onClose = closeModal
|
||||||
|
|
||||||
|
const component = route.matched[0]?.components?.default
|
||||||
|
|
||||||
|
if (!component) {
|
||||||
|
currentModal.value = undefined
|
||||||
|
return
|
||||||
|
}
|
||||||
|
currentModal.value = h(component, props)
|
||||||
|
},
|
||||||
|
{immediate: true},
|
||||||
|
)
|
||||||
|
|
||||||
|
async function closeModal() {
|
||||||
|
await router.isReady()
|
||||||
|
if (backdropRoute.value !== undefined) {
|
||||||
|
// TODO: Dialog modals might want to replace the route here via router.replace()
|
||||||
|
return router.push(backdropRoute.value)
|
||||||
}
|
}
|
||||||
|
if (window.history.state === undefined) {
|
||||||
// this is adapted from vue-router
|
return router.push({ name: 'home' })
|
||||||
// https://github.com/vuejs/vue-router-next/blob/798cab0d1e21f9b4d45a2bd12b840d2c7415f38a/src/RouterView.ts#L125
|
|
||||||
const routePropsOption = route.matched[0]?.props.default
|
|
||||||
const routeProps = routePropsOption
|
|
||||||
? routePropsOption === true
|
|
||||||
? route.params
|
|
||||||
: typeof routePropsOption === 'function'
|
|
||||||
? routePropsOption(route)
|
|
||||||
: routePropsOption
|
|
||||||
: {}
|
|
||||||
|
|
||||||
routeProps.backdropView = backdropView.value
|
|
||||||
|
|
||||||
const component = route.matched[0]?.components?.default
|
|
||||||
|
|
||||||
if (!component) {
|
|
||||||
currentModal.value = undefined
|
|
||||||
return
|
|
||||||
}
|
|
||||||
currentModal.value = h(component, routeProps)
|
|
||||||
})
|
|
||||||
|
|
||||||
function closeModal() {
|
|
||||||
const historyState = computed(() => route.fullPath && window.history.state)
|
|
||||||
|
|
||||||
if (historyState.value === undefined) {
|
|
||||||
router.back()
|
|
||||||
} else {
|
} else {
|
||||||
const backdropRoute = historyState.value.backdropView && router.resolve(historyState.value.backdropView)
|
router.back()
|
||||||
router.push(backdropRoute)
|
throw new Error('')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {routeWithModal, currentModal, closeModal}
|
return {
|
||||||
|
routeWithModal: baseRoute,
|
||||||
|
currentModal,
|
||||||
|
closeModal,
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -240,7 +240,7 @@ const router = createRouter({
|
||||||
meta: {
|
meta: {
|
||||||
showAsModal: true,
|
showAsModal: true,
|
||||||
},
|
},
|
||||||
props: route => ({ namespaceId: parseInt(route.params.id as string) }),
|
props: route => ({ namespaceId: Number(route.params.id as string) }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/namespaces/:id/settings/delete',
|
path: '/namespaces/:id/settings/delete',
|
||||||
|
@ -468,6 +468,9 @@ const router = createRouter({
|
||||||
path: '/about',
|
path: '/about',
|
||||||
name: 'about',
|
name: 'about',
|
||||||
component: About,
|
component: About,
|
||||||
|
meta: {
|
||||||
|
showAsModal: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
|
@ -512,9 +512,6 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
defineEmits(['close'])
|
|
||||||
const attrs = useAttrs()
|
|
||||||
console.log(JSON.parse(JSON.stringify(attrs)))
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
|
|
||||||
|
|
Reference in New Issue