Plugins für Plugins möglich.
Man kann nun Plugins für Plugins schreiben. Dabei können die Routes vom ursprünglichen Plugin überschrieben werden. Außerdem wird unterschieden zwischen required und optional (loadPlugins) Plugins. routes werden nun kombiniert und die MainLinks ebenfalls.
This commit is contained in:
parent
dddafef3a1
commit
c5799967af
|
@ -13,13 +13,15 @@ interface EssentialLink {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Plugin {
|
interface Plugin {
|
||||||
router: PluginRouteConfig[];
|
name: string;
|
||||||
store?: Module<never, never>;
|
routes: PluginRouteConfig[] | RouteConfig[];
|
||||||
|
store?: Module<never, never>[];
|
||||||
mainLink: PluginMainLink;
|
mainLink: PluginMainLink;
|
||||||
|
requiredModules: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PluginMainLink extends PluginChildLink {
|
interface PluginMainLink extends PluginChildLink {
|
||||||
children: PluginChildLink[] | [];
|
children: PluginChildLink[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PluginChildLink {
|
interface PluginChildLink {
|
||||||
|
@ -29,20 +31,136 @@ interface PluginChildLink {
|
||||||
icon: string;
|
icon: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
// Do not change required Modules !!
|
||||||
|
requiredModules: ['user'],
|
||||||
|
// here you can import plugins.
|
||||||
|
loadModules: ['plugin1', 'user-plugin']
|
||||||
|
};
|
||||||
|
|
||||||
export { PluginRouteConfig, Plugin, PluginChildLink, PluginMainLink };
|
export { PluginRouteConfig, Plugin, PluginChildLink, PluginMainLink };
|
||||||
|
|
||||||
|
function combineRoutes(
|
||||||
|
target: RouteConfig[],
|
||||||
|
source: RouteConfig[]
|
||||||
|
): RouteConfig[] {
|
||||||
|
// iterate first layer e.g. /main, /login etc.
|
||||||
|
source.forEach((sourceRouteConfig: RouteConfig) => {
|
||||||
|
const targetRouteConfig: RouteConfig | undefined = target.find(
|
||||||
|
(routeConfig: RouteConfig) => {
|
||||||
|
return sourceRouteConfig.path == routeConfig.path;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (targetRouteConfig) {
|
||||||
|
sourceRouteConfig.children?.forEach(
|
||||||
|
(sourcePluginChildRouteConfig: RouteConfig) => {
|
||||||
|
const targetPluginRouteConfig:
|
||||||
|
| RouteConfig
|
||||||
|
| undefined = targetRouteConfig.children?.find(
|
||||||
|
(routeConfig: RouteConfig) => {
|
||||||
|
return sourcePluginChildRouteConfig.path == routeConfig.path;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (targetPluginRouteConfig) {
|
||||||
|
if (targetPluginRouteConfig.children) {
|
||||||
|
targetPluginRouteConfig.children = Object.assign(
|
||||||
|
targetPluginRouteConfig.children,
|
||||||
|
sourcePluginChildRouteConfig.children
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
targetPluginRouteConfig.children =
|
||||||
|
sourcePluginChildRouteConfig.children;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
targetRouteConfig.children.push(sourcePluginChildRouteConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
target.push(sourceRouteConfig);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return 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;
|
||||||
|
}
|
||||||
|
|
||||||
// "async" is optional;
|
// "async" is optional;
|
||||||
// more info on params: https://quasar.dev/quasar-cli/cli-documentation/boot-files#Anatomy-of-a-boot-file
|
// more info on params: https://quasar.dev/quasar-cli/cli-documentation/boot-files#Anatomy-of-a-boot-file
|
||||||
export default boot(({ Vue, router }) => {
|
export default boot(({ Vue, router, store }) => {
|
||||||
const plugins = require.context('src/plugins', true, /.+\/plugin.ts$/);
|
const pluginsContext = require.context('src/plugins', true, /.+\/plugin.ts$/);
|
||||||
const pluginMainLinks: PluginMainLink[] = [];
|
let pluginMainLinks: PluginMainLink[] = [];
|
||||||
plugins.keys().forEach((fileName: string) => {
|
const plugins: Plugin[] = [];
|
||||||
|
pluginsContext.keys().forEach((fileName: string) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||||
router.addRoutes(plugins(fileName).default.router);
|
plugins.push(pluginsContext(fileName).default);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
||||||
pluginMainLinks.push(plugins(fileName).default.mainLink);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let routes: RouteConfig[] = [];
|
||||||
|
|
||||||
|
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}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||||
Vue.prototype.$flaschengeist_plugins = pluginMainLinks;
|
Vue.prototype.$flaschengeist_plugins = pluginMainLinks;
|
||||||
console.log(plugins);
|
console.log(pluginMainLinks);
|
||||||
});
|
});
|
||||||
|
|
|
@ -103,15 +103,6 @@ import { PluginMainLink } from 'boot/plugins';
|
||||||
import { defineComponent, ref, computed } from '@vue/composition-api';
|
import { defineComponent, ref, computed } from '@vue/composition-api';
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
{
|
|
||||||
name: 'home',
|
|
||||||
title: 'home',
|
|
||||||
icon: 'mdi-home',
|
|
||||||
children: [
|
|
||||||
{ title: 'Neues Home', link: 'newHome', icon: 'mdi-google-home' },
|
|
||||||
{ title: 'Altes Home', link: 'oldHome', icon: 'mdi-home-modern' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'about',
|
name: 'about',
|
||||||
title: 'about',
|
title: 'about',
|
||||||
|
@ -162,11 +153,14 @@ export default defineComponent({
|
||||||
| PluginMainLink
|
| PluginMainLink
|
||||||
| undefined = ctx.root.$flaschengeist_plugins.find(
|
| undefined = ctx.root.$flaschengeist_plugins.find(
|
||||||
(plugin: PluginMainLink) => {
|
(plugin: PluginMainLink) => {
|
||||||
|
if (ctx.root.$route.matched.length > 1) {
|
||||||
return plugin.name == ctx.root.$route.matched[1].name;
|
return plugin.name == ctx.root.$route.matched[1].name;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
console.log(test);
|
console.log(test);
|
||||||
if (typeof test == undefined) {
|
console.log(typeof test);
|
||||||
|
if (test == undefined) {
|
||||||
return [];
|
return [];
|
||||||
} else {
|
} else {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
|
|
@ -47,7 +47,7 @@ export default defineComponent({
|
||||||
|
|
||||||
function doLogin() {
|
function doLogin() {
|
||||||
console.log(username.value, password.value);
|
console.log(username.value, password.value);
|
||||||
void ctx.root.$router.push({ name: 'home' });
|
void ctx.root.$router.push({ name: 'main' });
|
||||||
}
|
}
|
||||||
|
|
||||||
return { username, password, doLogin, rules };
|
return { username, password, doLogin, rules };
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<template>
|
|
||||||
<q-page padding class="fit row justify-center content-center items-center">
|
|
||||||
<q-card class="col-4" height="" v-if="$route.name == 'home'">
|
|
||||||
<q-card-section>
|
|
||||||
Home
|
|
||||||
</q-card-section>
|
|
||||||
<q-card-section>
|
|
||||||
{{ a }}
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
<router-view />
|
|
||||||
</q-page>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from '@vue/composition-api';
|
|
||||||
export default defineComponent({
|
|
||||||
// name: 'PageName'
|
|
||||||
setup(_, ctx) {
|
|
||||||
const a = ctx.root.$flaschengeist_plugins;
|
|
||||||
return { a };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,14 +0,0 @@
|
||||||
<template>
|
|
||||||
<q-card class="col-4" height="">
|
|
||||||
<q-card-section>
|
|
||||||
Neues Zuhause
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from '@vue/composition-api';
|
|
||||||
export default defineComponent({
|
|
||||||
// name: 'PageName'
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,14 +0,0 @@
|
||||||
<template>
|
|
||||||
<q-card class="col-4" height="">
|
|
||||||
<q-card-section>
|
|
||||||
Altes Zuhause
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from '@vue/composition-api';
|
|
||||||
export default defineComponent({
|
|
||||||
// name: 'PageName'
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { Plugin } from 'boot/plugins';
|
|
||||||
import routes from 'src/plugins/plugin-example-2/routes';
|
|
||||||
|
|
||||||
const plugin: Plugin = {
|
|
||||||
router: routes,
|
|
||||||
mainLink: {
|
|
||||||
name: 'plugin2',
|
|
||||||
title: 'Plugin2',
|
|
||||||
link: 'plugin2',
|
|
||||||
icon: 'mdi-toy-brick-plus',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'plugin2',
|
|
||||||
title: 'Neues Plugin2',
|
|
||||||
link: 'plugin2_1',
|
|
||||||
icon: 'mdi-information-outline'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'plugin2',
|
|
||||||
title: 'Altes Plugin2',
|
|
||||||
link: 'plugin2_2',
|
|
||||||
icon: 'mdi-information-variant'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const mainLink = plugin.mainLink;
|
|
||||||
export { mainLink };
|
|
||||||
export default plugin;
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { Plugin } from 'boot/plugins';
|
import { Plugin, PluginMainLink } from 'boot/plugins';
|
||||||
import routes from 'src/plugins/plugin-example/routes';
|
import routes from 'src/plugins/plugin-example/routes';
|
||||||
|
|
||||||
const plugin: Plugin = {
|
const mainLink: PluginMainLink = {
|
||||||
router: routes,
|
|
||||||
mainLink: {
|
|
||||||
name: 'plugin1',
|
name: 'plugin1',
|
||||||
title: 'Plugin1',
|
title: 'Plugin1',
|
||||||
link: 'plugin1',
|
link: 'plugin1',
|
||||||
|
@ -22,10 +20,14 @@ const plugin: Plugin = {
|
||||||
icon: 'mdi-information-variant'
|
icon: 'mdi-information-variant'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mainLink = plugin.mainLink;
|
const plugin: Plugin = {
|
||||||
|
routes,
|
||||||
|
mainLink,
|
||||||
|
name: mainLink.name,
|
||||||
|
requiredModules: []
|
||||||
|
};
|
||||||
|
|
||||||
export { mainLink };
|
export { mainLink };
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { Plugin, PluginMainLink } from 'boot/plugins';
|
||||||
|
import routes from './routes';
|
||||||
|
|
||||||
|
const mainLink: PluginMainLink = {
|
||||||
|
name: 'user-plugin',
|
||||||
|
title: 'User',
|
||||||
|
link: 'user',
|
||||||
|
icon: 'mdi-account',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'user-plugin',
|
||||||
|
title: 'Erstes Plugin für User',
|
||||||
|
link: 'user-plugin1',
|
||||||
|
icon: 'mdi-account-plus'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'user-plugin',
|
||||||
|
title: 'Zweites Plugin für User',
|
||||||
|
link: 'user-plugin2',
|
||||||
|
icon: 'mdi-account-minus'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugin: Plugin = {
|
||||||
|
routes,
|
||||||
|
mainLink,
|
||||||
|
name: mainLink.name,
|
||||||
|
requiredModules: ['user']
|
||||||
|
};
|
||||||
|
|
||||||
|
export { mainLink };
|
||||||
|
export default plugin;
|
|
@ -8,21 +8,18 @@ const routes: RouteConfig[] = [
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'plugin2',
|
path: 'user',
|
||||||
name: 'plugin2',
|
name: 'user',
|
||||||
components: {
|
component: () => import('src/plugins/user/pages/User.vue'),
|
||||||
default: () => import('../pages/Plugin.vue'),
|
|
||||||
'plugin-nav': () => import('../components/navigation/PluginLinks.vue')
|
|
||||||
},
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'plugin2_1',
|
path: 'user-plugin',
|
||||||
name: 'plugin2_1',
|
name: 'user-plugin1',
|
||||||
component: () => import('../pages/NewPlugin.vue')
|
component: () => import('../pages/NewPlugin.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'plugin2_2',
|
path: 'user-plugin2',
|
||||||
name: 'plugin2_2',
|
name: 'user-plugin2',
|
||||||
component: () => import('../pages/OldPlugin.vue')
|
component: () => import('../pages/OldPlugin.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<q-page
|
||||||
|
padding
|
||||||
|
class="fit row justify-center content-center items-center"
|
||||||
|
v-if="$route.name == mainLink.link"
|
||||||
|
>
|
||||||
|
<q-card class="col-4" height="">
|
||||||
|
<q-card-section>
|
||||||
|
{{ mainLink.title }}
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</q-page>
|
||||||
|
<router-view />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from '@vue/composition-api';
|
||||||
|
import { mainLink } from '../plugin';
|
||||||
|
export default defineComponent({
|
||||||
|
// name: 'PageName'
|
||||||
|
setup(_, ctx) {
|
||||||
|
const a = ctx.root.$flaschengeist_plugins;
|
||||||
|
return { a, mainLink };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { Plugin, PluginMainLink } from 'boot/plugins';
|
||||||
|
import routes from './routes';
|
||||||
|
|
||||||
|
const mainLink: PluginMainLink = {
|
||||||
|
name: 'user',
|
||||||
|
title: 'User',
|
||||||
|
link: 'user',
|
||||||
|
icon: 'mdi-account',
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugin: Plugin = {
|
||||||
|
routes,
|
||||||
|
mainLink,
|
||||||
|
name: mainLink.name,
|
||||||
|
requiredModules: []
|
||||||
|
};
|
||||||
|
|
||||||
|
export { mainLink };
|
||||||
|
|
||||||
|
export default plugin;
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { RouteConfig } from 'vue-router';
|
||||||
|
|
||||||
|
const routes: RouteConfig[] = [
|
||||||
|
{
|
||||||
|
path: '/main',
|
||||||
|
component: () => import('layouts/MainLayout.vue'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'user',
|
||||||
|
name: 'user',
|
||||||
|
component: () => import('../pages/User.vue')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export default routes;
|
|
@ -15,25 +15,9 @@ const routes: RouteConfig[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/main',
|
path: '/main',
|
||||||
|
name: 'main',
|
||||||
component: () => import('layouts/MainLayout.vue'),
|
component: () => import('layouts/MainLayout.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
|
||||||
name: 'home',
|
|
||||||
path: 'home',
|
|
||||||
component: () => import('pages/home/Home.vue'),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'newHome',
|
|
||||||
path: 'newHome',
|
|
||||||
component: () => import('pages/home/NewHome.vue')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'oldHome',
|
|
||||||
path: 'oldHome',
|
|
||||||
component: () => import('pages/home/OldHome.vue')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'about',
|
name: 'about',
|
||||||
path: 'about',
|
path: 'about',
|
||||||
|
|
Loading…
Reference in New Issue