flaschengeist-frontend/src/layouts/MainLayout.vue

226 lines
6.8 KiB
Vue
Raw Normal View History

2020-10-02 07:13:14 +00:00
<template>
2021-04-03 11:24:19 +00:00
<q-layout view="hHh Lpr lff">
<q-header elevated class="bg-primary text-white">
2020-10-02 07:13:14 +00:00
<q-toolbar>
2021-04-03 11:24:19 +00:00
<q-btn dense flat round icon="mdi-menu" @click="openMenu" />
2020-10-02 07:13:14 +00:00
<q-toolbar-title>
<router-link :to="{ name: 'dashboard' }" style="text-decoration: none; color: inherit">
2021-01-29 15:24:43 +00:00
<q-avatar rounded>
<img src="flaschengeist-logo-white.svg" />
</q-avatar>
<span class="gt-xs"> Flaschengeist </span>
</router-link>
2020-10-02 07:13:14 +00:00
</q-toolbar-title>
<!-- Hier kommen die Shortlinks hin -->
2021-04-18 21:43:16 +00:00
<q-btn icon="mdi-message-bulleted" flat dense round>
<q-badge color="negative" floating>
{{ notifications.length }}
</q-badge>
<q-menu max-height="400px" style="min-width: 290px" class="q-pa-xs">
<q-btn
v-if="useNative && noPermission"
label="Benachrichtigungen erlauben"
@click="requestPermission"
/>
2021-03-29 05:35:23 +00:00
<template v-if="notifications.length > 0">
<Notification
v-for="(notification, index) in notifications"
:key="index"
:model-value="notification"
@remove="remove"
/>
</template>
<div v-else class="q-pa-sm">Keine neuen Benachrichtigungen</div>
</q-menu>
</q-btn>
2021-04-18 21:43:16 +00:00
<drag v-model="shortCuts" item-key="link" ghost-class="ghost">
<template #item="{ element }">
<shortcut-link :shortcut="element" context @delete-shortcut="deleteShortcut" />
</template>
</drag>
2021-11-27 21:36:24 +00:00
<q-btn v-if="!platform.is.capacitor" flat round dense icon="mdi-exit-to-app" @click="logout()" />
2020-10-02 07:13:14 +00:00
</q-toolbar>
</q-header>
<q-drawer
v-model="leftDrawer"
side="left"
bordered
:mini="leftDrawerMini"
@click.capture="openMenu"
>
<!-- Plugins -->
2021-05-25 19:55:22 +00:00
<essential-expansion-link
v-for="(entry, index) in mainLinks"
:key="'plugin' + index"
:entry="entry"
@add-short-cut="addShortcut"
/>
<q-separator />
<essential-link
v-for="(entry, index) in essentials"
:key="'essential' + index"
:entry="entry"
/>
2021-11-27 21:36:24 +00:00
<div v-if="platform.is.capacitor">
<q-separator />
<q-item clickable tag="a" target="self" @click="logout">
<q-item-section avatar>
<q-icon name="mdi-exit-to-app" />
</q-item-section>
<q-item-section>
<q-item-label>Logout</q-item-label>
</q-item-section>
</q-item>
</div>
2020-10-02 07:13:14 +00:00
</q-drawer>
<q-page-container>
<router-view />
2020-10-02 07:13:14 +00:00
</q-page-container>
</q-layout>
</template>
<script lang="ts">
2021-05-25 19:55:22 +00:00
import EssentialExpansionLink from 'components/navigation/EssentialExpansionLink.vue';
import EssentialLink from 'src/components/navigation/EssentialLink.vue';
import ShortcutLink from 'src/components/navigation/ShortcutLink.vue';
2021-03-29 05:35:23 +00:00
import Notification from 'src/components/Notification.vue';
import { defineComponent, ref, inject, computed, onBeforeMount, onBeforeUnmount } from 'vue';
2021-11-19 22:10:56 +00:00
import { Screen, Platform } from 'quasar';
import config from 'src/config';
import { useRouter } from 'vue-router';
import { useMainStore } from '@flaschengeist/api';
import { FG_Plugin } from '@flaschengeist/types';
import drag from 'vuedraggable';
const essentials: FG_Plugin.MenuLink[] = [
2020-10-13 09:27:27 +00:00
{
2020-10-13 21:13:42 +00:00
title: 'Über Flaschengeist',
2020-10-13 09:27:27 +00:00
link: 'about',
icon: 'mdi-information',
},
2020-10-09 16:04:32 +00:00
];
2020-10-02 07:13:14 +00:00
export default defineComponent({
name: 'MainLayout',
components: {
EssentialExpansionLink,
EssentialLink,
ShortcutLink,
Notification,
drag,
},
setup() {
const router = useRouter();
const mainStore = useMainStore();
2021-02-04 01:42:49 +00:00
const flaschengeist = inject<FG_Plugin.Flaschengeist>('flaschengeist');
const leftDrawer = ref(!Platform.is.mobile);
const leftDrawerMini = ref(false);
const mainLinks = flaschengeist?.menuLinks || [];
2021-03-29 05:35:23 +00:00
const notifications = computed(() => mainStore.notifications.slice().reverse());
const polling = ref(NaN);
const useNative = 'Notification' in window && window.Notification !== undefined;
const noPermission = ref(!useNative || window.Notification.permission !== 'granted');
2021-03-29 05:35:23 +00:00
onBeforeMount(() => {
polling.value = window.setInterval(() => pollNotification(), config.pollingInterval);
pollNotification();
2021-04-18 21:26:54 +00:00
void mainStore.getShortcuts();
});
onBeforeUnmount(() => window.clearInterval(polling.value));
2021-04-03 11:24:19 +00:00
function openMenu(event: { target: HTMLInputElement }) {
if (event.target.nodeName === 'DIV') leftDrawerMini.value = false;
else {
if (!leftDrawer.value || leftDrawerMini.value) {
leftDrawer.value = true;
leftDrawerMini.value = false;
} else {
leftDrawerMini.value = Screen.gt.sm && !leftDrawerMini.value;
leftDrawer.value = leftDrawerMini.value;
}
}
}
2020-10-02 07:13:14 +00:00
function logout() {
void router.push({ name: 'login', params: { logout: 'logout' } });
void mainStore.logout();
}
2021-03-29 05:35:23 +00:00
async function remove(id: number) {
await mainStore.removeNotification(id);
}
function requestPermission() {
void window.Notification.requestPermission().then(
(p) => (noPermission.value = p !== 'granted')
);
}
function pollNotification() {
void mainStore
.loadNotifications(<FG_Plugin.Flaschengeist>flaschengeist)
.then((notifications) => {
if (useNative && !noPermission.value)
notifications.forEach(
(notif) =>
new window.Notification(notif.text, {
timestamp: notif.time.getTime(),
})
);
});
}
2021-04-18 21:26:54 +00:00
const shortCuts = computed({
get: () => mainStore.shortcuts,
set: (val: Array<FG_Plugin.MenuLink>) => {
mainStore.shortcuts = val;
2021-04-18 21:43:16 +00:00
void mainStore.setShortcuts();
2021-04-18 21:26:54 +00:00
},
});
function addShortcut(val: FG_Plugin.MenuLink) {
const idx = shortCuts.value.findIndex((a: FG_Plugin.MenuLink) => a.link === val.link);
if (idx < 0) {
shortCuts.value.push(val);
void mainStore.setShortcuts();
}
}
function deleteShortcut(val: FG_Plugin.MenuLink) {
const idx = shortCuts.value.findIndex((a: FG_Plugin.MenuLink) => a.link === val.link);
if (idx > -1) {
shortCuts.value.splice(idx, 1);
void mainStore.setShortcuts();
}
}
2020-10-13 09:27:27 +00:00
return {
essentials,
2021-04-03 11:24:19 +00:00
leftDrawer,
2020-10-13 09:27:27 +00:00
leftDrawerMini,
logout,
mainLinks,
2021-03-29 05:35:23 +00:00
notifications,
noPermission,
2021-04-03 11:24:19 +00:00
openMenu,
2021-03-29 05:35:23 +00:00
remove,
requestPermission,
useNative,
2021-04-18 21:26:54 +00:00
shortCuts,
addShortcut,
deleteShortcut,
2021-11-27 21:36:24 +00:00
platform: Platform,
2020-10-13 09:27:27 +00:00
};
},
2020-10-02 07:13:14 +00:00
});
</script>
2021-04-18 21:43:16 +00:00
<style scoped lang="sass">
.ghost
opacity: 0.5
background: $accent
</style>