diff --git a/src/boot/plugins.ts b/src/boot/plugins.ts index f4eeede..9a9dd7c 100644 --- a/src/boot/plugins.ts +++ b/src/boot/plugins.ts @@ -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[]; 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,105 @@ 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.concat(plugin.shortCuts); + 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); }); diff --git a/src/components/CompositionComponent.vue b/src/components/CompositionComponent.vue deleted file mode 100644 index 22b4bd7..0000000 --- a/src/components/CompositionComponent.vue +++ /dev/null @@ -1,59 +0,0 @@ - - - diff --git a/src/components/navigation/PluginChildrenLinks.vue b/src/components/navigation/PluginChildrenLinks.vue deleted file mode 100644 index 1f81695..0000000 --- a/src/components/navigation/PluginChildrenLinks.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/src/components/navigation/ShortCutLink.vue b/src/components/navigation/ShortCutLink.vue new file mode 100644 index 0000000..6a0a446 --- /dev/null +++ b/src/components/navigation/ShortCutLink.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index e5d2370..203aa4f 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -23,8 +23,12 @@
- - +
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 = [ @@ -114,15 +119,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); @@ -142,7 +162,7 @@ export default defineComponent({ const pluginChildLinks = computed(() => { const test: | 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; @@ -170,7 +190,8 @@ export default defineComponent({ leftDrawerClicker, links, pluginChildLinks, - showRoute + showRoute, + shortcuts }; } }); diff --git a/src/pages/Index.vue b/src/pages/Index.vue deleted file mode 100644 index 1d56395..0000000 --- a/src/pages/Index.vue +++ /dev/null @@ -1,49 +0,0 @@ - - - diff --git a/src/pages/about/About.vue b/src/pages/about/About.vue index 7781ae1..e6e5c63 100644 --- a/src/pages/about/About.vue +++ b/src/pages/about/About.vue @@ -36,12 +36,12 @@ {{ plugin.name }} - Version + {{ plugin.version }} diff --git a/src/plugins/plugin-example/pages/Plugin.vue b/src/plugins/plugin-example/pages/Plugin.vue index 0beeb75..c0fd5a6 100644 --- a/src/plugins/plugin-example/pages/Plugin.vue +++ b/src/plugins/plugin-example/pages/Plugin.vue @@ -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 }; } }); diff --git a/src/plugins/plugin-example/plugin.ts b/src/plugins/plugin-example/plugin.ts index 8708048..ce84cc2 100644 --- a/src/plugins/plugin-example/plugin.ts +++ b/src/plugins/plugin-example/plugin.ts @@ -26,7 +26,10 @@ const plugin: Plugin = { routes, mainLink, name: mainLink.name, - requiredModules: [] + requiredModules: [], + shortCuts: [], + shortCutsOut: [], + version: '1.0.2' }; export { mainLink }; diff --git a/src/plugins/user-plugin/pages/Plugin.vue b/src/plugins/user-plugin/pages/Plugin.vue index 0beeb75..c0fd5a6 100644 --- a/src/plugins/user-plugin/pages/Plugin.vue +++ b/src/plugins/user-plugin/pages/Plugin.vue @@ -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 }; } }); diff --git a/src/plugins/user-plugin/plugin.ts b/src/plugins/user-plugin/plugin.ts index e850196..beeb0a9 100644 --- a/src/plugins/user-plugin/plugin.ts +++ b/src/plugins/user-plugin/plugin.ts @@ -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 }; diff --git a/src/plugins/user/pages/User.vue b/src/plugins/user/pages/User.vue index 7ac07fd..5acf604 100644 --- a/src/plugins/user/pages/User.vue +++ b/src/plugins/user/pages/User.vue @@ -21,7 +21,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 }; } }); diff --git a/src/plugins/user/plugin.ts b/src/plugins/user/plugin.ts index 7a04344..d977e55 100644 --- a/src/plugins/user/plugin.ts +++ b/src/plugins/user/plugin.ts @@ -13,7 +13,10 @@ const plugin: Plugin = { routes, mainLink, name: mainLink.name, - requiredModules: [] + requiredModules: [], + shortCutsOut: [], + shortCuts: [], + version: '0.0.1' }; export { mainLink };