release v2.0.0 #4
|
@ -2,7 +2,7 @@ import config from 'src/config';
|
|||
import { boot } from 'quasar/wrappers';
|
||||
import { LocalStorage, Notify } from 'quasar';
|
||||
import axios, { AxiosError } from 'axios';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
const api = axios.create();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { boot } from 'quasar/wrappers';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { hasPermissions } from 'src/utils/permission';
|
||||
import { RouteRecord } from 'vue-router';
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import { api } from 'boot/axios';
|
|||
import { AxiosResponse } from 'axios';
|
||||
import { RouteRecordRaw } from 'vue-router';
|
||||
import { Notify } from 'quasar';
|
||||
import { notEmpty } from 'src/utils/validators';
|
||||
|
||||
const config: { [key: string]: Array<string> } = {
|
||||
// Do not change required Modules !!
|
||||
|
@ -56,6 +57,9 @@ interface Backend {
|
|||
}
|
||||
export { Backend };
|
||||
|
||||
// Handle Notifications
|
||||
export const translateNotification = (note: FG.Notification): FG_Plugin.Notification => note;
|
||||
|
||||
// Combine routes, shortcuts and widgets from plugins
|
||||
|
||||
/**
|
||||
|
@ -288,6 +292,7 @@ function loadPlugin(
|
|||
loadedPlugins.plugins.push({
|
||||
name: plugin.name,
|
||||
version: plugin.version,
|
||||
notification: plugin.notification?.bind({}) || translateNotification,
|
||||
});
|
||||
|
||||
return plugin;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { createPinia } from 'pinia';
|
||||
import { boot } from 'quasar/wrappers';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export default boot(({ app }) => {
|
||||
app.use(createPinia());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<q-card bordered class="row q-ma-xs q-pa-xs" style="position: relative">
|
||||
<div class="col-12 text-weight-light">{{ dateString }}</div>
|
||||
<div class="col-12">{{ modelValue.text }}</div>
|
||||
<div :id="`ntfctn-${modelValue.id}`" class="col-12" @click="click">{{ modelValue.text }}</div>
|
||||
<q-btn
|
||||
round
|
||||
dense
|
||||
|
@ -12,32 +12,58 @@
|
|||
style="position: absolute; top: 0; right: 0"
|
||||
@click="remove"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="modelValue.accept !== undefined"
|
||||
round
|
||||
dense
|
||||
icon="close"
|
||||
size="sm"
|
||||
color="positive"
|
||||
class="q-ma-xs"
|
||||
style="position: absolute; top: 50px; right: 0"
|
||||
@click="accept"
|
||||
/>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed } from 'vue';
|
||||
import { formatDateTime } from 'src/utils/datetime';
|
||||
import { FG_Plugin } from 'src/plugins';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Notification',
|
||||
props: {
|
||||
modelValue: {
|
||||
required: true,
|
||||
type: Object as PropType<FG.Notification>,
|
||||
type: Object as PropType<FG_Plugin.Notification>,
|
||||
},
|
||||
},
|
||||
emits: {
|
||||
remove: (id: number) => !!id,
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const router = useRouter();
|
||||
const dateString = computed(() => formatDateTime(props.modelValue.time, true, true));
|
||||
|
||||
async function click() {
|
||||
if (props.modelValue.link) await router.push(props.modelValue.link);
|
||||
}
|
||||
|
||||
function accept() {
|
||||
if (props.modelValue.accept)
|
||||
void props.modelValue.accept().then(() => emit('remove', props.modelValue.id));
|
||||
else emit('remove', props.modelValue.id);
|
||||
}
|
||||
|
||||
function remove() {
|
||||
if (props.modelValue.reject)
|
||||
void props.modelValue.reject().then(() => emit('remove', props.modelValue.id));
|
||||
emit('remove', props.modelValue.id);
|
||||
}
|
||||
|
||||
return { dateString, remove };
|
||||
return { accept, click, dateString, remove };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -106,7 +106,7 @@ import ShortcutLink from 'src/components/navigation/ShortcutLink.vue';
|
|||
import Notification from 'src/components/Notification.vue';
|
||||
import { Screen } from 'quasar';
|
||||
import { defineComponent, ref, inject, computed, onBeforeMount } from 'vue';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { FG_Plugin } from 'src/plugins';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Loading, Notify } from 'quasar';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
import { useRouter } from 'vue-router';
|
||||
import { Loading, Notify } from 'quasar';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export default defineComponent({
|
||||
// name: 'PageName'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { RouteRecordRaw, RouteRecordName } from 'vue-router';
|
||||
import { RouteLocationRaw, RouteRecordRaw, RouteRecordName } from 'vue-router';
|
||||
import { Component, ComputedRef } from 'vue';
|
||||
|
||||
declare namespace FG_Plugin {
|
||||
|
@ -19,6 +19,8 @@ declare namespace FG_Plugin {
|
|||
outerRoutes?: MenuRoute[];
|
||||
/** Routes without menu links, for internal usage */
|
||||
internalRoutes?: NamedRouteRecordRaw[];
|
||||
/** Handle notifications, defaults to boot/plugins.ts:translateNotification() */
|
||||
notification?(msg: FG.Notification): FG_Plugin.Notification;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,12 +41,27 @@ declare namespace FG_Plugin {
|
|||
widgets: Widget[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for a frontend notification
|
||||
*/
|
||||
interface Notification extends FG.Notification {
|
||||
/** If set a button for accepting will be shown, this function will get called before deleting the notification */
|
||||
accept?(): Promise<void>;
|
||||
/** If set this function is called before the notification gets deleted */
|
||||
reject?(): Promise<void>;
|
||||
/** If set the notification text is interpreted as a link to this location */
|
||||
link?: RouteLocationRaw;
|
||||
/** If set this icon is used */
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loaded Flaschengeist plugin
|
||||
*/
|
||||
interface LoadedPlugin {
|
||||
name: string;
|
||||
version: string;
|
||||
notification(msg: FG.Notification): FG_Plugin.Notification;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -62,7 +62,7 @@ import { hasPermission } from 'src/utils/permission';
|
|||
import BalanceHeader from '../components/BalanceHeader.vue';
|
||||
import PERMISSIONS from '../permissions';
|
||||
import { useBalanceStore } from '../store';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BalanceAdd',
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import { computed, defineComponent, onBeforeMount, PropType } from 'vue';
|
||||
import UserSelector from 'src/plugins/user/components/UserSelector.vue';
|
||||
import { useBalanceStore } from '../store';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BalanceHeader',
|
||||
|
|
|
@ -29,7 +29,7 @@ import UserSelector from 'src/plugins/user/components/UserSelector.vue';
|
|||
import BalanceHeader from '../components/BalanceHeader.vue';
|
||||
import PERMISSIONS from '../permissions';
|
||||
import { useBalanceStore } from '../store';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BalanceTransfer',
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
import { ref, computed, defineComponent, onUnmounted, onMounted, PropType } from 'vue';
|
||||
import { hasPermission } from 'src/utils/permission';
|
||||
import { formatDateTime } from 'src/utils/datetime';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { useUserStore } from 'src/plugins/user/store';
|
||||
import { useBalanceStore } from '../store';
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { useBalanceStore } from '../store';
|
||||
import { computed, defineComponent, onBeforeMount } from 'vue';
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ import BalanceAdd from '../components/BalanceAdd.vue';
|
|||
import BalanceTransfer from '../components/BalanceTransfer.vue';
|
||||
import Transaction from '../components/Transaction.vue';
|
||||
import { useBalanceStore } from '../store';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BalanceManage',
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
import { computed, defineComponent, onMounted, ref } from 'vue';
|
||||
import { formatDateTime } from 'src/utils/datetime';
|
||||
import { useBalanceStore } from '../store';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { useUserStore } from 'src/plugins/user/store';
|
||||
|
||||
export default defineComponent({
|
||||
|
|
|
@ -17,7 +17,7 @@ export interface TransactionsResponse {
|
|||
}
|
||||
|
||||
import { defineStore } from 'pinia';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { Notify } from 'quasar';
|
||||
|
||||
|
|
|
@ -326,7 +326,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent, onBeforeMount, ComputedRef, computed, ref } from 'vue';
|
||||
import DrinkPriceVolumesTable from 'src/plugins/pricelist/components/CalculationTable/DrinkPriceVolumesTable.vue';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { Drink, usePricelistStore } from 'src/plugins/pricelist/store';
|
||||
import MinPriceSetting from 'src/plugins/pricelist/components/MinPriceSetting.vue';
|
||||
import NewDrink from 'src/plugins/pricelist/components/CalculationTable/NewDrink.vue';
|
||||
|
|
|
@ -39,7 +39,7 @@ import { defineComponent, onBeforeMount, computed, PropType } from 'vue';
|
|||
import { Notify } from 'quasar';
|
||||
import { asHour } from 'src/utils/datetime';
|
||||
import { useUserStore } from 'src/plugins/user/store';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { useScheduleStore } from 'src/plugins/schedule/store';
|
||||
|
||||
export default defineComponent({
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
import { defineComponent, ref } from 'vue';
|
||||
import UserSelector from '../components/UserSelector.vue';
|
||||
import MainUserSettings from '../components/settings/MainUserSettings.vue';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { useUserStore } from '../store';
|
||||
|
||||
export default defineComponent({
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { computed, defineComponent, onMounted, ref } from 'vue';
|
||||
import { useUserStore } from '../store';
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ import { hasPermission } from 'src/utils/permission';
|
|||
import IsoDateInput from 'src/components/utils/IsoDateInput.vue';
|
||||
import { defineComponent, computed, ref, onBeforeMount, PropType } from 'vue';
|
||||
import { useUserStore } from '../../store';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MainUserSettings',
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent, ref, computed, PropType } from 'vue';
|
||||
import { formatDateTime } from 'src/utils/datetime';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { useSessionStore } from '../../store';
|
||||
|
||||
export default defineComponent({
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
import { defineComponent, onBeforeMount, ref } from 'vue';
|
||||
import Session from '../components/settings/Session.vue';
|
||||
import MainUserSettings from '../components/settings/MainUserSettings.vue';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { useSessionStore } from '../store';
|
||||
import { useUserStore } from '../store';
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { FG_Plugin } from 'src/plugins';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const mainRoutes: FG_Plugin.MenuRoute[] = [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { defineStore } from 'pinia';
|
||||
import { api } from 'src/boot/axios';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export const useUserStore = defineStore({
|
||||
id: 'users',
|
||||
|
|
|
@ -1,27 +1,11 @@
|
|||
import { store } from 'quasar/wrappers';
|
||||
import { createStore } from 'vuex';
|
||||
|
||||
export interface StateInterface {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export default store(function (/* { ssrContext } */) {
|
||||
const Store = createStore({
|
||||
modules: {},
|
||||
|
||||
// enable strict mode (adds overhead!)
|
||||
// for dev mode and --debug builds only
|
||||
strict: !!process.env.DEBUGGING,
|
||||
});
|
||||
|
||||
return Store;
|
||||
});
|
||||
|
||||
import { defineStore } from 'pinia';
|
||||
import { api } from 'src/boot/axios';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { LocalStorage, SessionStorage } from 'quasar';
|
||||
import { useUserStore, useSessionStore } from 'src/plugins/user/store';
|
||||
import { translateNotification } from 'src/boot/plugins';
|
||||
import { LocalStorage, SessionStorage } from 'quasar';
|
||||
import { FG_Plugin } from 'src/plugins';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { api } from 'src/boot/axios';
|
||||
import { defineStore } from 'pinia';
|
||||
import { inject } from 'vue';
|
||||
|
||||
function loadCurrentSession() {
|
||||
const session = LocalStorage.getItem<FG.Session>('session');
|
||||
|
@ -41,7 +25,7 @@ export const useMainStore = defineStore({
|
|||
state: () => ({
|
||||
session: loadCurrentSession(),
|
||||
user: loadUser(),
|
||||
notifications: [] as Array<FG.Notification>,
|
||||
notifications: [] as Array<FG_Plugin.Notification>,
|
||||
}),
|
||||
|
||||
getters: {
|
||||
|
@ -126,6 +110,7 @@ export const useMainStore = defineStore({
|
|||
},
|
||||
|
||||
async loadNotifications() {
|
||||
const flaschengeist = inject<FG_Plugin.Flaschengeist>('flaschengeist');
|
||||
const params =
|
||||
this.notifications.length > 0
|
||||
? { from: this.notifications[this.notifications.length - 1].time }
|
||||
|
@ -133,12 +118,17 @@ export const useMainStore = defineStore({
|
|||
const { data } = await api.get<FG.Notification[]>('/notifications', { params: params });
|
||||
data.forEach((n) => {
|
||||
n.time = new Date(n.time);
|
||||
const notif = (
|
||||
flaschengeist?.plugins.filter((p) => p.name === n.plugin)[0]?.notification ||
|
||||
translateNotification
|
||||
)(n);
|
||||
this.notifications.push(notif);
|
||||
|
||||
if (window.Notification.permission === 'granted')
|
||||
new window.Notification(n.text, {
|
||||
timestamp: n.time.getTime(),
|
||||
new window.Notification(notif.text, {
|
||||
timestamp: notif.time.getTime(),
|
||||
});
|
||||
});
|
||||
this.notifications.push(...data);
|
||||
},
|
||||
|
||||
async removeNotification(id: number) {
|
||||
|
@ -154,3 +144,5 @@ export const useMainStore = defineStore({
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default () => useMainStore;
|
|
@ -1,4 +1,4 @@
|
|||
import { useMainStore } from 'src/store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export function hasPermission(permission: string) {
|
||||
const store = useMainStore();
|
||||
|
|
Loading…
Reference in New Issue