release v2.0.0 #4
|
@ -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