release v2.0.0 #4
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 33 KiB |
|
@ -2,22 +2,29 @@ import { boot } from 'quasar/wrappers';
|
|||
import { RouteConfig } from 'vue-router';
|
||||
import { Module } from 'vuex';
|
||||
|
||||
interface PluginRouteConfig extends RouteConfig {
|
||||
example?: unknown;
|
||||
}
|
||||
const config = {
|
||||
// Do not change required Modules !!
|
||||
requiredModules: ['user'],
|
||||
// here you can import plugins.
|
||||
loadModules: ['plugin1', 'user-plugin']
|
||||
};
|
||||
|
||||
interface EssentialLink {
|
||||
title: string;
|
||||
// do not change anything here !!
|
||||
|
||||
interface ShortCutLink {
|
||||
link: string;
|
||||
icon?: string;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
interface Plugin {
|
||||
name: string;
|
||||
routes: PluginRouteConfig[] | RouteConfig[];
|
||||
routes: RouteConfig[];
|
||||
store?: Module<never, never>[];
|
||||
mainLink: PluginMainLink;
|
||||
requiredModules: string[];
|
||||
shortcuts: ShortCutLink[];
|
||||
shortcutsOut: ShortCutLink[];
|
||||
version: string;
|
||||
}
|
||||
|
||||
interface PluginMainLink extends PluginChildLink {
|
||||
|
@ -31,15 +38,29 @@ interface PluginChildLink {
|
|||
icon: string;
|
||||
}
|
||||
|
||||
const config = {
|
||||
// Do not change required Modules !!
|
||||
requiredModules: ['user'],
|
||||
// here you can import plugins.
|
||||
loadModules: ['plugin1', 'user-plugin']
|
||||
interface LoadedPlugin {
|
||||
name: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
interface LoadedPlugins {
|
||||
plugins: LoadedPlugin[];
|
||||
routes: RouteConfig[];
|
||||
mainLinks: PluginMainLink[];
|
||||
shortcuts: ShortCutLink[];
|
||||
shortcutsOut: ShortCutLink[];
|
||||
}
|
||||
|
||||
export {
|
||||
Plugin,
|
||||
PluginChildLink,
|
||||
PluginMainLink,
|
||||
ShortCutLink,
|
||||
LoadedPlugins,
|
||||
LoadedPlugin
|
||||
};
|
||||
|
||||
export { PluginRouteConfig, Plugin, PluginChildLink, PluginMainLink };
|
||||
|
||||
// combine routes from source to target
|
||||
function combineRoutes(
|
||||
target: RouteConfig[],
|
||||
source: RouteConfig[]
|
||||
|
@ -52,6 +73,7 @@ function combineRoutes(
|
|||
}
|
||||
);
|
||||
if (targetRouteConfig) {
|
||||
// if exists first layer in target exist iterate through 2nd layer e.g. /main/user, /main/about
|
||||
sourceRouteConfig.children?.forEach(
|
||||
(sourcePluginChildRouteConfig: RouteConfig) => {
|
||||
const targetPluginRouteConfig:
|
||||
|
@ -62,16 +84,20 @@ function combineRoutes(
|
|||
}
|
||||
);
|
||||
if (targetPluginRouteConfig) {
|
||||
// if 2nd layer in target exist check if target has children path.
|
||||
if (targetPluginRouteConfig.children) {
|
||||
// if target has children path, add children from source.
|
||||
targetPluginRouteConfig.children = Object.assign(
|
||||
targetPluginRouteConfig.children,
|
||||
sourcePluginChildRouteConfig.children
|
||||
);
|
||||
} else {
|
||||
// if not set children of targen from children of source
|
||||
targetPluginRouteConfig.children =
|
||||
sourcePluginChildRouteConfig.children;
|
||||
}
|
||||
} else {
|
||||
// if target not exists in 2nd layer, add source to children of first targen
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
targetRouteConfig.children.push(sourcePluginChildRouteConfig);
|
||||
|
@ -79,90 +105,110 @@ function combineRoutes(
|
|||
}
|
||||
);
|
||||
} else {
|
||||
// if target not exists in first layer, add source
|
||||
target.push(sourceRouteConfig);
|
||||
}
|
||||
});
|
||||
return target;
|
||||
}
|
||||
|
||||
// combine Links of Plugins from source to target
|
||||
function combineMainLinks(
|
||||
target: PluginMainLink[],
|
||||
source: PluginMainLink
|
||||
): PluginMainLink[] {
|
||||
console.log('target', target);
|
||||
console.log('source', source);
|
||||
const targetPluginMainLink: PluginMainLink | undefined = target.find(
|
||||
(targetPluginMainLink: PluginMainLink) => {
|
||||
console.log(targetPluginMainLink.title, source.title);
|
||||
return targetPluginMainLink.title == source.title;
|
||||
}
|
||||
);
|
||||
console.log('targetPluginMainLink', targetPluginMainLink);
|
||||
if (targetPluginMainLink) {
|
||||
source.children.forEach((sourcePluginChildLink: PluginChildLink) => {
|
||||
targetPluginMainLink.children.push(sourcePluginChildLink);
|
||||
});
|
||||
} else {
|
||||
console.log('push source', source);
|
||||
target.push(source);
|
||||
}
|
||||
console.log('merged', target);
|
||||
return target;
|
||||
}
|
||||
|
||||
// loade plugins
|
||||
function loadPlugin(
|
||||
loadedPlugins: LoadedPlugins,
|
||||
modules: string[],
|
||||
plugins: Plugin[],
|
||||
store: any
|
||||
): LoadedPlugins {
|
||||
modules.forEach(requiredModule => {
|
||||
const plugin = plugins.find(plugin => {
|
||||
return plugin.name == requiredModule;
|
||||
});
|
||||
if (plugin) {
|
||||
loadedPlugins.routes = combineRoutes(loadedPlugins.routes, plugin.routes);
|
||||
if (plugin.store) {
|
||||
plugin.store.forEach(store_module => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
store.registerModule(store_module);
|
||||
});
|
||||
}
|
||||
loadedPlugins.mainLinks = combineMainLinks(
|
||||
loadedPlugins.mainLinks,
|
||||
plugin.mainLink
|
||||
);
|
||||
loadedPlugins.shortcuts = loadedPlugins.shortcuts.concat(
|
||||
plugin.shortcuts
|
||||
);
|
||||
loadedPlugins.shortcutsOut = loadedPlugins.shortcutsOut.concat(
|
||||
plugin.shortcutsOut
|
||||
);
|
||||
loadedPlugins.plugins.push({
|
||||
name: plugin.name,
|
||||
version: plugin.version
|
||||
});
|
||||
} else {
|
||||
console.exception(`Don't find required Plugin ${requiredModule}`);
|
||||
}
|
||||
});
|
||||
return loadedPlugins;
|
||||
}
|
||||
|
||||
// "async" is optional;
|
||||
// more info on params: https://quasar.dev/quasar-cli/cli-documentation/boot-files#Anatomy-of-a-boot-file
|
||||
export default boot(({ Vue, router, store }) => {
|
||||
const pluginsContext = require.context('src/plugins', true, /.+\/plugin.ts$/);
|
||||
let pluginMainLinks: PluginMainLink[] = [];
|
||||
const plugins: Plugin[] = [];
|
||||
let loadedPlugins: LoadedPlugins = {
|
||||
routes: [],
|
||||
plugins: [],
|
||||
mainLinks: [],
|
||||
shortcuts: [],
|
||||
shortcutsOut: []
|
||||
};
|
||||
|
||||
// get all plugins
|
||||
const pluginsContext = require.context('src/plugins', true, /.+\/plugin.ts$/);
|
||||
pluginsContext.keys().forEach((fileName: string) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
plugins.push(pluginsContext(fileName).default);
|
||||
});
|
||||
|
||||
let routes: RouteConfig[] = [];
|
||||
// load plugins
|
||||
loadedPlugins = loadPlugin(
|
||||
loadedPlugins,
|
||||
config.requiredModules,
|
||||
plugins,
|
||||
store
|
||||
);
|
||||
loadedPlugins = loadPlugin(loadedPlugins, config.loadModules, plugins, store);
|
||||
|
||||
config.requiredModules.forEach(requiredModule => {
|
||||
const plugin = plugins.find(plugin => {
|
||||
return plugin.name == requiredModule;
|
||||
});
|
||||
if (plugin) {
|
||||
routes = combineRoutes(routes, plugin.routes);
|
||||
if (plugin.store) {
|
||||
plugin.store.forEach(store_module => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
store.registerModule(store_module);
|
||||
});
|
||||
}
|
||||
pluginMainLinks = combineMainLinks(pluginMainLinks, plugin.mainLink);
|
||||
} else {
|
||||
console.exception(`Don't find required Plugin ${requiredModule}`);
|
||||
}
|
||||
});
|
||||
console.log(loadedPlugins.routes);
|
||||
|
||||
config.loadModules.forEach(loadModule => {
|
||||
const plugin = plugins.find(plugin => {
|
||||
return plugin.name == loadModule;
|
||||
});
|
||||
if (plugin) {
|
||||
routes = combineRoutes(routes, plugin.routes);
|
||||
if (plugin.store) {
|
||||
plugin.store.forEach(store_module => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
store.registerModule(store_module);
|
||||
});
|
||||
}
|
||||
pluginMainLinks = combineMainLinks(pluginMainLinks, plugin.mainLink);
|
||||
} else {
|
||||
console.exception(`Don't find Plugin ${loadModule}`);
|
||||
}
|
||||
});
|
||||
console.log(routes);
|
||||
router.addRoutes(routes);
|
||||
// add new routes for plugins
|
||||
router.addRoutes(loadedPlugins.routes);
|
||||
|
||||
// save plugins in VM-variable
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
Vue.prototype.$flaschengeistPluginsMainLinks = pluginMainLinks;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
Vue.prototype.$flaschengeistPlugins = plugins;
|
||||
console.log(pluginMainLinks);
|
||||
Vue.prototype.$flaschengeistPlugins = loadedPlugins;
|
||||
console.log(loadedPlugins);
|
||||
console.log(Vue.prototype.$flaschengeistPlugins);
|
||||
});
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<essential-link
|
||||
v-for="(link, index) in links"
|
||||
:key="index"
|
||||
:title="link.title"
|
||||
:link="link.link"
|
||||
:icon="link.icon"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
const links = [
|
||||
{ title: 'Neues Home', link: 'newHome', icon: 'mdi-google-home' },
|
||||
{ title: 'Altes Home', link: 'oldHome', icon: 'mdi-home-modern' }
|
||||
];
|
||||
import { defineComponent } from '@vue/composition-api';
|
||||
import EssentialLink from 'components/navigation/EssentialLink.vue';
|
||||
export default defineComponent({
|
||||
// name: 'ComponentName'
|
||||
components: { EssentialLink },
|
||||
setup() {
|
||||
return { links };
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,20 @@
|
|||
<template>
|
||||
<q-btn flat dense :icon="icon" :to="{ name: link }" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from '@vue/composition-api';
|
||||
export default defineComponent({
|
||||
name: 'ShortCutLink',
|
||||
props: {
|
||||
link: {
|
||||
required: true,
|
||||
type: String
|
||||
},
|
||||
icon: {
|
||||
required: true,
|
||||
type: String
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -26,17 +26,11 @@
|
|||
|
||||
<!-- Hier kommen die Shortlinks hin -->
|
||||
<div>
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
dense
|
||||
icon="sim_card"
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
dense
|
||||
icon="gamepad"
|
||||
<short-cut-link
|
||||
v-for="(shortcut, index) in $flaschengeistPlugins.shortcuts"
|
||||
:key="'shortcut' + index"
|
||||
:link="shortcut.link"
|
||||
:icon="shortcut.icon"
|
||||
/>
|
||||
</div>
|
||||
<q-btn
|
||||
|
@ -60,7 +54,7 @@
|
|||
<!-- Plugins -->
|
||||
<q-list>
|
||||
<essential-link
|
||||
v-for="(link, index) in $flaschengeistPluginsMainLinks"
|
||||
v-for="(link, index) in $flaschengeistPlugins.mainLinks"
|
||||
:key="'plugin' + index"
|
||||
:title="link.title"
|
||||
:link="link.link"
|
||||
|
@ -115,8 +109,9 @@
|
|||
|
||||
<script lang="ts">
|
||||
import EssentialLink from 'components/navigation/EssentialLink.vue';
|
||||
import ShortCutLink from 'components/navigation/ShortCutLink.vue';
|
||||
import { Screen } from 'quasar';
|
||||
import { PluginMainLink } from 'boot/plugins';
|
||||
import { LoadedPlugins, PluginMainLink } from 'boot/plugins';
|
||||
import { defineComponent, ref, computed } from '@vue/composition-api';
|
||||
|
||||
const links = [
|
||||
|
@ -128,15 +123,30 @@ const links = [
|
|||
},
|
||||
];
|
||||
|
||||
const shortcuts = [
|
||||
{
|
||||
link: 'about',
|
||||
icon: 'mdi-information',
|
||||
},
|
||||
{
|
||||
link: 'user',
|
||||
icon: 'mdi-account',
|
||||
},
|
||||
{
|
||||
link: 'user-plugin1',
|
||||
icon: 'mdi-account-plus',
|
||||
},
|
||||
];
|
||||
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
$flaschengeistPluginsMainLinks: PluginMainLink[];
|
||||
$flaschengeistPlugins: LoadedPlugins;
|
||||
}
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MainLayout',
|
||||
components: { EssentialLink },
|
||||
components: { EssentialLink, ShortCutLink },
|
||||
setup(_, ctx) {
|
||||
const leftDrawer = ref(false);
|
||||
|
||||
|
@ -156,7 +166,7 @@ export default defineComponent({
|
|||
const pluginChildLinks = computed(() => {
|
||||
const link:
|
||||
| PluginMainLink
|
||||
| undefined = ctx.root.$flaschengeistPluginsMainLinks.find(
|
||||
| undefined = ctx.root.$flaschengeistPlugins.mainLinks.find(
|
||||
(plugin: PluginMainLink) => {
|
||||
if (ctx.root.$route.matched.length > 1) {
|
||||
return plugin.name == ctx.root.$route.matched[1].name;
|
||||
|
@ -177,6 +187,7 @@ export default defineComponent({
|
|||
leftDrawerClicker,
|
||||
links,
|
||||
pluginChildLinks,
|
||||
shortcuts,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -13,6 +13,14 @@
|
|||
Flaschengeist
|
||||
</span>
|
||||
</q-toolbar-title>
|
||||
<div>
|
||||
<short-cut-link
|
||||
v-for="(shortcut, index) in $flaschengeistPlugins.shortcutsOut"
|
||||
:key="'shortcut' + index"
|
||||
:link="shortcut.link"
|
||||
:icon="shortcut.icon"
|
||||
/>
|
||||
</div>
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
|
@ -45,7 +53,9 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from '@vue/composition-api';
|
||||
import ShortCutLink from 'components/navigation/ShortCutLink.vue';
|
||||
export default defineComponent({
|
||||
name: 'OutLayout'
|
||||
name: 'OutLayout',
|
||||
components: { ShortCutLink }
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
class="fit row justify-center content-center items-center"
|
||||
v-if="$route.name == 'about' || $route.name == 'about_out'"
|
||||
>
|
||||
<q-card flat class="col-6">
|
||||
<q-card flat class="col-xs-12 col-sm-10 col-md-6">
|
||||
<q-card-section
|
||||
class="row fit justify-center items-center content-center"
|
||||
>
|
||||
|
@ -36,12 +36,12 @@
|
|||
</q-card-section>
|
||||
<q-card-section v-if="$route.name == 'about'">
|
||||
<q-chip
|
||||
v-for="(plugin, index) in $flaschengeistPlugins"
|
||||
v-for="(plugin, index) in $flaschengeistPlugins.plugins"
|
||||
:key="'plugin' + index"
|
||||
>
|
||||
{{ plugin.name }}
|
||||
<q-separator vertical color="black" class="q-ma-xs" />
|
||||
Version
|
||||
{{ plugin.version }}
|
||||
</q-chip>
|
||||
</q-card-section>
|
||||
<q-separator />
|
||||
|
@ -54,8 +54,8 @@
|
|||
class="fit row inline wrap justify-around items-start content-start q-gutter-sm"
|
||||
>
|
||||
<developer
|
||||
v-for="developer in developers"
|
||||
:key="i"
|
||||
v-for="(developer, index) in developers"
|
||||
:key="'dev' + index"
|
||||
class="col-xs-12 col-md-5 col-lg-3"
|
||||
:firstname="developer.firstname"
|
||||
:lastname="developer.lastname"
|
||||
|
|
|
@ -15,7 +15,7 @@ import { mainLink } from '../plugin';
|
|||
export default defineComponent({
|
||||
// name: 'PageName'
|
||||
setup(_, ctx) {
|
||||
const a = ctx.root.$flaschengeistPluginsMainLinks;
|
||||
const a = ctx.root.$flaschengeistPlugins.mainLinks;
|
||||
return { a, mainLink };
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Plugin, PluginMainLink } from 'boot/plugins';
|
||||
import { Plugin, PluginMainLink, ShortCutLink } from 'boot/plugins';
|
||||
import routes from 'src/plugins/plugin-example/routes';
|
||||
|
||||
const mainLink: PluginMainLink = {
|
||||
|
@ -26,7 +26,10 @@ const plugin: Plugin = {
|
|||
routes,
|
||||
mainLink,
|
||||
name: mainLink.name,
|
||||
requiredModules: []
|
||||
requiredModules: [],
|
||||
shortcuts: [],
|
||||
shortcutsOut: [],
|
||||
version: '1.0.2'
|
||||
};
|
||||
|
||||
export { mainLink };
|
||||
|
|
|
@ -15,7 +15,7 @@ import { mainLink } from '../plugin';
|
|||
export default defineComponent({
|
||||
// name: 'PageName'
|
||||
setup(_, ctx) {
|
||||
const a = ctx.root.$flaschengeistPluginsMainLinks;
|
||||
const a = ctx.root.$flaschengeistPlugins.mainLinks;
|
||||
return { a, mainLink };
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Plugin, PluginMainLink } from 'boot/plugins';
|
||||
import { Plugin, PluginMainLink, ShortCutLink } from 'boot/plugins';
|
||||
import routes from './routes';
|
||||
|
||||
const mainLink: PluginMainLink = {
|
||||
|
@ -22,11 +22,21 @@ const mainLink: PluginMainLink = {
|
|||
]
|
||||
};
|
||||
|
||||
const shortcuts: ShortCutLink[] = [
|
||||
{
|
||||
link: 'user-plugin2',
|
||||
icon: 'mdi-account-minus'
|
||||
}
|
||||
];
|
||||
|
||||
const plugin: Plugin = {
|
||||
routes,
|
||||
mainLink,
|
||||
name: mainLink.name,
|
||||
requiredModules: ['user']
|
||||
requiredModules: ['user'],
|
||||
shortcuts,
|
||||
shortcutsOut: [],
|
||||
version: '0.1.0'
|
||||
};
|
||||
|
||||
export { mainLink };
|
||||
|
|
|
@ -36,7 +36,7 @@ export default defineComponent({
|
|||
const userState = computed(
|
||||
() => <UserStateInterface>root.$store.state.user
|
||||
);
|
||||
const a = root.$flaschengeistPluginsMainLinks;
|
||||
const a = ctx.root.$flaschengeistPlugins.mainLinks;
|
||||
return { a, userState };
|
||||
},
|
||||
});
|
||||
|
|
|
@ -13,7 +13,10 @@ const plugin: Plugin = {
|
|||
routes,
|
||||
mainLink,
|
||||
name: mainLink.name,
|
||||
requiredModules: []
|
||||
requiredModules: [],
|
||||
shortcutsOut: [],
|
||||
shortcuts: [],
|
||||
version: '0.0.1'
|
||||
};
|
||||
|
||||
export { mainLink };
|
||||
|
|
Loading…
Reference in New Issue