mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
118 lines
2.7 KiB
Vue
118 lines
2.7 KiB
Vue
<template>
|
|
<div id="app" :style="brandStyle">
|
|
<transition name="fade">
|
|
<div class="hydrating" v-if="hydrating">
|
|
<v-progress-circular indeterminate />
|
|
</div>
|
|
</transition>
|
|
|
|
<router-view v-if="!hydrating && appAccess" />
|
|
|
|
<v-info v-else-if="appAccess === false" center :title="$t('no_app_access')" type="danger" icon="block">
|
|
{{ $t('no_app_access_copy') }}
|
|
|
|
<template #append>
|
|
<v-button to="/logout">Switch User</v-button>
|
|
</template>
|
|
</v-info>
|
|
|
|
<portal-target name="outlet" multiple />
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, toRefs, watch, computed } from '@vue/composition-api';
|
|
import { useAppStore } from '@/stores/app';
|
|
import { useUserStore } from '@/stores/user';
|
|
import { useSettingsStore } from '@/stores/settings';
|
|
|
|
import useWindowSize from '@/composables/use-window-size';
|
|
import setFavicon from '@/utils/set-favicon';
|
|
|
|
export default defineComponent({
|
|
setup() {
|
|
const appStore = useAppStore();
|
|
const userStore = useUserStore();
|
|
const settingsStore = useSettingsStore();
|
|
|
|
const { hydrating, drawerOpen } = toRefs(appStore.state);
|
|
|
|
const brandStyle = computed(() => {
|
|
return {
|
|
'--brand': settingsStore.state.settings?.project_color || 'var(--primary)',
|
|
};
|
|
});
|
|
|
|
watch(() => settingsStore.state.settings?.project_color, setFavicon);
|
|
|
|
const { width } = useWindowSize();
|
|
|
|
watch(
|
|
width,
|
|
(newWidth, oldWidth) => {
|
|
if (newWidth === null || newWidth === 0) return;
|
|
if (newWidth === oldWidth) return;
|
|
|
|
if (newWidth >= 1424) {
|
|
if (drawerOpen.value === false) drawerOpen.value = true;
|
|
} else {
|
|
if (drawerOpen.value === true) drawerOpen.value = false;
|
|
}
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
|
|
watch(
|
|
() => userStore.state.currentUser,
|
|
(newUser) => {
|
|
document.body.classList.remove('dark');
|
|
document.body.classList.remove('light');
|
|
document.body.classList.remove('auto');
|
|
|
|
if (newUser !== undefined && newUser !== null) {
|
|
document.body.classList.add(newUser.theme);
|
|
} else {
|
|
// Default to light mode
|
|
document.body.classList.add('light');
|
|
}
|
|
}
|
|
);
|
|
|
|
const appAccess = computed(() => {
|
|
if (!userStore.state.currentUser) return true;
|
|
return userStore.state.currentUser?.role?.app_access;
|
|
});
|
|
|
|
return { hydrating, brandStyle, appAccess };
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
#app {
|
|
height: 100%;
|
|
}
|
|
|
|
.hydrating {
|
|
position: fixed;
|
|
z-index: 1000;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(255, 255, 255, 0.5);
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
|
|
.fade-enter-active,
|
|
.fade-leave-active {
|
|
transition: opacity var(--medium) var(--transition);
|
|
}
|
|
|
|
.fade-enter,
|
|
.fade-leave-to {
|
|
opacity: 0;
|
|
}
|
|
</style>
|