mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
feat: add new MainLayout to handle lock and modals with Suspense (async views)
This commit is contained in:
parent
0cf60eab98
commit
f05d5769ff
3 changed files with 138 additions and 45 deletions
|
@ -5,13 +5,13 @@ import { useStore } from 'vuex'
|
|||
import { useRequests } from '@/composables/useRequests'
|
||||
import { useSettings } from '@/composables/useSettings'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import { HistoryConsole, ViewLockOverlay } from '@/views/_partials'
|
||||
import { HistoryConsole } from '@/views/_partials'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const { connected, yunohost, routerKey, ssoLink } = useStoreGetters()
|
||||
const { connected, yunohost, ssoLink } = useStoreGetters()
|
||||
const { locked } = useRequests()
|
||||
const { spinner, dark, transitions, transitionName } = useSettings()
|
||||
const { spinner, dark } = useSettings()
|
||||
|
||||
async function logout() {
|
||||
store.dispatch('LOGOUT')
|
||||
|
@ -113,20 +113,7 @@ onMounted(() => {
|
|||
</header>
|
||||
|
||||
<!-- MAIN -->
|
||||
<ViewLockOverlay>
|
||||
<YBreadcrumb />
|
||||
|
||||
<main id="main">
|
||||
<!-- The `key` on RouterView make sure that if a link points to a page that
|
||||
use the same component as the previous one, it will be refreshed -->
|
||||
<RouterView v-slot="{ Component }" :key="routerKey">
|
||||
<Transition v-if="transitions" :name="transitionName">
|
||||
<Component :is="Component" class="animated" />
|
||||
</Transition>
|
||||
<Component v-else :is="Component" class="static" />
|
||||
</RouterView>
|
||||
</main>
|
||||
</ViewLockOverlay>
|
||||
<MainLayout />
|
||||
|
||||
<BModalOrchestrator />
|
||||
|
||||
|
@ -196,34 +183,6 @@ header {
|
|||
}
|
||||
}
|
||||
|
||||
main {
|
||||
position: relative;
|
||||
|
||||
// Routes transition
|
||||
.animated {
|
||||
transition: all 0.15s ease-in-out;
|
||||
}
|
||||
.slide-left-enter-from,
|
||||
.slide-right-leave-active {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
transform: translate(100vw, 0);
|
||||
}
|
||||
.slide-left-leave-active,
|
||||
.slide-right-enter-from {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
transform: translate(-100vw, 0);
|
||||
}
|
||||
// hack to hide last transition provoqued by the <RouterView> element change
|
||||
// while disabling the transitions in ToolWebAdmin
|
||||
.static ~ .animated {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#console {
|
||||
// Allows the console to be tabbed before the footer links while remaining visually
|
||||
// the last element of the page
|
||||
|
|
133
app/src/components/layouts/MainLayout.vue
Normal file
133
app/src/components/layouts/MainLayout.vue
Normal file
|
@ -0,0 +1,133 @@
|
|||
<script setup lang="ts">
|
||||
import { createReusableTemplate } from '@vueuse/core'
|
||||
import type { VNode } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import {
|
||||
ModalError,
|
||||
ModalReconnecting,
|
||||
ModalWaiting,
|
||||
ModalWarning,
|
||||
} from '@/components/modals'
|
||||
import { useRequests } from '@/composables/useRequests'
|
||||
import { useSettings } from '@/composables/useSettings'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import type { VueClass } from '@/types/commons'
|
||||
|
||||
const router = useRouter()
|
||||
const { routerKey } = useStoreGetters()
|
||||
const { reconnecting, currentRequest, dismissModal } = useRequests()
|
||||
const { transitions, transitionName, dark } = useSettings()
|
||||
|
||||
const RootView = createReusableTemplate<{
|
||||
Component: VNode
|
||||
classes: VueClass
|
||||
}>()
|
||||
|
||||
const skeleton = computed(
|
||||
() => router.currentRoute.value.meta.skeleton || 'CardInfoSkeleton',
|
||||
)
|
||||
|
||||
const modalComponent = computed(() => {
|
||||
if (reconnecting.value) {
|
||||
return {
|
||||
is: ModalReconnecting,
|
||||
props: {
|
||||
reconnecting: reconnecting.value,
|
||||
onDismiss: () => (reconnecting.value = undefined),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const request = currentRequest.value
|
||||
if (!request) return null
|
||||
const { status, err } = request
|
||||
|
||||
if (status === 'error' && err) {
|
||||
return {
|
||||
is: ModalError,
|
||||
props: { request, onDismiss: () => dismissModal(request.id) },
|
||||
}
|
||||
} else if (status === 'warning') {
|
||||
return {
|
||||
is: ModalWarning,
|
||||
props: { request, onDismiss: () => dismissModal(request.id) },
|
||||
}
|
||||
} else {
|
||||
return { is: ModalWaiting, props: { request } }
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RootView.define v-slot="{ Component, classes }">
|
||||
<BOverlay
|
||||
opacity="0.75"
|
||||
rounded
|
||||
:show="!!modalComponent"
|
||||
:variant="dark ? 'dark' : 'light'"
|
||||
class="main-overlay"
|
||||
>
|
||||
<Suspense>
|
||||
<Component :is="Component" :class="classes" />
|
||||
<template #fallback>
|
||||
<Component :is="skeleton" />
|
||||
</template>
|
||||
</Suspense>
|
||||
|
||||
<template v-if="modalComponent" #overlay>
|
||||
<Component :is="modalComponent.is" v-bind="modalComponent.props" />
|
||||
</template>
|
||||
</BOverlay>
|
||||
</RootView.define>
|
||||
|
||||
<YBreadcrumb />
|
||||
|
||||
<main id="main">
|
||||
<!-- The `key` on RouterView make sure that if a link points to a page that
|
||||
use the same component as the previous one, it will be refreshed -->
|
||||
<RouterView v-slot="{ Component }" :key="routerKey">
|
||||
<Transition v-if="transitions" :name="transitionName">
|
||||
<RootView.reuse v-bind="{ Component, classes: 'animated' }" />
|
||||
</Transition>
|
||||
<RootView.reuse v-else v-bind="{ Component, classes: 'static' }" />
|
||||
</RouterView>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
main {
|
||||
position: relative;
|
||||
|
||||
// Routes transition
|
||||
.animated {
|
||||
transition: all 0.15s ease-in-out;
|
||||
}
|
||||
.slide-left-enter-from,
|
||||
.slide-right-leave-active {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
transform: translate(100vw, 0);
|
||||
}
|
||||
.slide-left-leave-active,
|
||||
.slide-right-enter-from {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
transform: translate(-100vw, 0);
|
||||
}
|
||||
// hack to hide last transition provoqued by the <RouterView> element change
|
||||
// while disabling the transitions in ToolWebAdmin
|
||||
.static ~ .animated {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.main-overlay :deep(.b-overlay :first-child) {
|
||||
width: calc(100% + 20px);
|
||||
height: calc(100% + 20px);
|
||||
transform: translate(-10px, -10px);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -124,6 +124,7 @@ $h4-font-size: $font-size-base * 1.25;
|
|||
$h5-font-size: $font-size-base * 1.1;
|
||||
|
||||
$list-group-item-padding-y: $spacer * 0.75;
|
||||
$modal-md: 600px;
|
||||
|
||||
// Import default variables after the above setup to compute all other variables.
|
||||
@import '~bootstrap/scss/variables';
|
||||
|
|
Loading…
Reference in a new issue