Allow multiple widgets and minor improvements

* Allow mulitple widgets for plugins, allow setting required permissions
* Split datetime formatter code for reuse
This commit is contained in:
Ferdinand Thiessen 2020-11-13 04:01:53 +01:00
parent 7b1a1c3656
commit 19f91d2abf
9 changed files with 67 additions and 52 deletions

View File

@ -1,5 +1,4 @@
{ {
"editor.formatOnPaste": true,
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll": true "source.fixAll": true

View File

@ -1,25 +1,7 @@
import { boot } from 'quasar/wrappers'; import { boot } from 'quasar/wrappers';
import { formatDateTime } from 'src/utils/datetime';
export default boot(({ Vue }) => { export default boot(({ Vue }) => {
function formatDateTime(
date: Date,
useDate = true,
useTime = false,
useSeconds = false,
useWeekday = false
) {
const dateTimeFormat = new Intl.DateTimeFormat([], {
year: useDate ? 'numeric' : undefined,
month: useDate ? '2-digit' : undefined,
day: useDate ? '2-digit' : undefined,
weekday: useWeekday ? 'long' : undefined,
hour: useTime ? '2-digit' : undefined,
minute: useTime ? '2-digit' : undefined,
second: useTime && useSeconds ? '2-digit' : undefined
});
return dateTimeFormat.format(date);
}
Vue.filter('date', formatDateTime); Vue.filter('date', formatDateTime);
Vue.filter('time', (date: Date, seconds = false) => Vue.filter('time', (date: Date, seconds = false) =>
formatDateTime(date, false, true, seconds) formatDateTime(date, false, true, seconds)

View File

@ -23,9 +23,7 @@ function combineRoutes(
): RouteConfig[] { ): RouteConfig[] {
target.forEach(target => { target.forEach(target => {
if (target.path === mainPath) { if (target.path === mainPath) {
console.log('target', target.path);
source.forEach((sourceMainConfig: FG_Plugin.PluginRouteConfig) => { source.forEach((sourceMainConfig: FG_Plugin.PluginRouteConfig) => {
console.log('sourceMainconfig', sourceMainConfig);
const targetMainConfig = target.children?.find( const targetMainConfig = target.children?.find(
(targetMainConfig: RouteConfig) => { (targetMainConfig: RouteConfig) => {
return sourceMainConfig.path === targetMainConfig.path; return sourceMainConfig.path === targetMainConfig.path;
@ -164,12 +162,13 @@ function loadPlugin(
plugin.outRoutes plugin.outRoutes
); );
} }
if (plugin.widget) { if (plugin.widgets.length > 0) {
loadedPlugins.widgets.push(plugin.widget); plugin.widgets.forEach(
widget => (widget.name = plugin.name + '_' + widget.name)
);
Array.prototype.push.apply(loadedPlugins.widgets, plugin.widgets);
} }
if (plugin.store) { if (plugin.store) {
console.log(plugin.store);
console.log(plugin.store.keys());
plugin.store.forEach((store_plugin, store_namespace) => { plugin.store.forEach((store_plugin, store_namespace) => {
store.registerModule(store_namespace, store_plugin); store.registerModule(store_namespace, store_plugin);
}); });

View File

@ -16,21 +16,24 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, onMounted, ref } from '@vue/composition-api'; import { defineComponent, onMounted, ref } from '@vue/composition-api';
import { hasPermissions } from 'src/components/permission';
import { AsyncComponentPromise } from 'vue/types/options'; import { AsyncComponentPromise } from 'vue/types/options';
export default defineComponent({ export default defineComponent({
name: 'Dashboard', name: 'Dashboard',
setup(_, { root }) { setup(_, { root }) {
const widgets = ref<Array<AsyncComponentPromise>>([]); const widgets = ref<Array<AsyncComponentPromise>>([]);
onMounted(() => { onMounted(() => {
console.log('mounted!'); root.$flaschengeistPlugins.widgets.forEach((widget) => {
root.$flaschengeistPlugins.widgets.forEach(widget => if (hasPermissions(widget.permissions, root.$store))
widgets.value.push(widget.widget) widgets.value.push(widget.widget);
); });
}); });
return { return {
widgets widgets,
}; };
} },
}); });
</script> </script>

18
src/plugins.d.ts vendored
View File

@ -18,14 +18,21 @@ declare namespace FG_Plugin {
meta?: { permissions?: string[] }; meta?: { permissions?: string[] };
} }
interface Widget {
name: string;
priority: number;
permissions: FG.Permission[];
widget: AsyncComponentPromise;
}
interface Plugin { interface Plugin {
name: string; name: string;
version: string;
widgets: Widget[];
requiredModules: string[];
mainRoutes?: PluginRouteConfig[]; mainRoutes?: PluginRouteConfig[];
outRoutes?: PluginRouteConfig[]; outRoutes?: PluginRouteConfig[];
store?: Map<string, Module<any, StateInterface>>; store?: Map<string, Module<any, StateInterface>>;
widget?: Widget;
requiredModules: string[];
version: string;
} }
interface PluginMainLink extends PluginChildLink { interface PluginMainLink extends PluginChildLink {
@ -45,11 +52,6 @@ declare namespace FG_Plugin {
version: string; version: string;
} }
interface Widget {
widget: AsyncComponentPromise;
priority: number;
}
interface LoadedPlugins { interface LoadedPlugins {
plugins: LoadedPlugin[]; plugins: LoadedPlugin[];
routes: RouteConfig[]; routes: RouteConfig[];

View File

@ -12,10 +12,14 @@ const plugin: FG_Plugin.Plugin = {
store: new Map<string, Module<BalanceInterface, StateInterface>>([ store: new Map<string, Module<BalanceInterface, StateInterface>>([
['balance', balance] ['balance', balance]
]), ]),
widget: { widgets: [
widget: () => import('./components/Widget.vue'), {
priority: 0 priority: 0,
} name: 'current',
permissions: ['balance_show'],
widget: () => import('./components/Widget.vue')
}
]
}; };
export default plugin; export default plugin;

View File

@ -4,10 +4,14 @@ const plugin: FG_Plugin.Plugin = {
name: 'Schedule', name: 'Schedule',
requiredModules: [], requiredModules: [],
version: '0.0.1', version: '0.0.1',
widget: { widgets: [
widget: () => import('./components/Widget.vue'), {
priority: 0 priority: 0,
} name: 'stats',
permissions: [],
widget: () => import('./components/Widget.vue')
}
]
}; };
export default plugin; export default plugin;

View File

@ -14,10 +14,14 @@ const plugin: FG_Plugin.Plugin = {
['user', userStore], ['user', userStore],
['session', sessionsStore] ['session', sessionsStore]
]), ]),
widget: { widgets: [
priority: 1, {
widget: () => import('./components/Widget.vue') priority: 1,
} name: 'greeting',
permissions: [],
widget: () => import('./components/Widget.vue')
}
]
}; };
export default plugin; export default plugin;

18
src/utils/datetime.ts Normal file
View File

@ -0,0 +1,18 @@
export function formatDateTime(
date: Date,
useDate = true,
useTime = false,
useSeconds = false,
useWeekday = false
) {
const dateTimeFormat = new Intl.DateTimeFormat([], {
year: useDate ? 'numeric' : undefined,
month: useDate ? '2-digit' : undefined,
day: useDate ? '2-digit' : undefined,
weekday: useWeekday ? 'long' : undefined,
hour: useTime ? '2-digit' : undefined,
minute: useTime ? '2-digit' : undefined,
second: useTime && useSeconds ? '2-digit' : undefined
});
return dateTimeFormat.format(date);
}