diff --git a/zero.Debug/Controllers/HomeController.cs b/zero.Debug/Controllers/HomeController.cs index 655948d6..307e27a6 100644 --- a/zero.Debug/Controllers/HomeController.cs +++ b/zero.Debug/Controllers/HomeController.cs @@ -17,6 +17,16 @@ namespace zero.Debug.Controllers return View(); } + [HttpGet] + public async Task Test() + { + await Task.Delay(3000); + return Json(new + { + result = "okay" + }); + } + [HttpGet] public async Task SavePages([FromServices] IDocumentStore raven) { diff --git a/zero.Web.UI/App/app.vue b/zero.Web.UI/App/app.vue index 4cb0616f..7318f432 100644 --- a/zero.Web.UI/App/app.vue +++ b/zero.Web.UI/App/app.vue @@ -19,7 +19,7 @@ import AppLogin from 'zero/pages/login/login.vue' import AppOverlays from 'zero/components/overlays/overlay-holder.vue' import AppNotifications from 'zero/components/notifications/notification-holder.vue' - //import Router from 'zero/router.config.js' + import EventHub from './services/eventhub.js'; import AuthApi from 'zero/services/auth.js' import 'zero/config/vue.config.js' import 'zero/config/axios.config.js' @@ -27,8 +27,6 @@ export default { name: 'app', - // router: Router, - components: { AppNavigation, AppOverlays, AppLogin, AppNotifications }, data: () => ({ @@ -37,13 +35,12 @@ created() { - console.info(this.zero); + AuthApi.setUser(__zero.user); + AuthApi.$on('authenticated', isAuthenticated => { this.isAuthenticated = isAuthenticated; }); - - AuthApi.setUser(zero.user); }, diff --git a/zero.Web.UI/App/config/axios.config.js b/zero.Web.UI/App/config/axios.config.js index c721f021..f9d1272f 100644 --- a/zero.Web.UI/App/config/axios.config.js +++ b/zero.Web.UI/App/config/axios.config.js @@ -2,12 +2,12 @@ import Auth from 'zero/services/auth'; import Qs from 'qs'; -if (!zero || !zero.apiPath) +if (!__zero || !__zero.apiPath) { throw Exception('window.zero and zero.apiPath (= base path to the backoffice API) have to be configured'); } -Axios.defaults.baseURL = zero.apiPath; +Axios.defaults.baseURL = __zero.apiPath; Axios.defaults.withCredentials = true; Axios.defaults.paramsSerializer = (params) => diff --git a/zero.Web.UI/App/config/router.config.js b/zero.Web.UI/App/config/router.config.js index f4c00c8d..b3697ca5 100644 --- a/zero.Web.UI/App/config/router.config.js +++ b/zero.Web.UI/App/config/router.config.js @@ -11,7 +11,7 @@ const beforeEach = () => (to, from, next) => { let title = Localization.localize('@zero.name'); - if (to.meta.name && to.meta.alias !== zero.alias.sections.dashboard) + if (to.meta.name && to.meta.alias !== __zero.alias.sections.dashboard) { let name = to.meta.name; let nameParts = _isArray(name) ? name : [name]; @@ -64,7 +64,7 @@ const beforeEach = () => (to, from, next) => export default { mode: 'history', - base: zero.path, + base: __zero.path, linkActiveClass: 'is-active', linkExactActiveClass: 'is-active-exact', beforeEach: beforeEach, diff --git a/zero.Web.UI/App/config/routes.js b/zero.Web.UI/App/config/routes.js deleted file mode 100644 index 5c9a3e84..00000000 --- a/zero.Web.UI/App/config/routes.js +++ /dev/null @@ -1,123 +0,0 @@ - -import { isArray as _isArray, find as _find, map as _map, filter as _filter } from 'underscore'; -import { warn } from 'zero/services/debug'; - -let routes = []; - - -// add defined backoffice sections (with their children) to the router - -const addSection = (section, component, parent) => -{ - let route = { - path: section.url, - component: component, - name: (parent ? parent.alias + '-' : '') + section.alias, - meta: { - name: [section.name, (parent ? parent.name : null)], - alias: section.alias, - section: section, - parent: parent - } - }; - - routes.push(route); - - return route; -}; - -zero.sections.forEach(section => -{ - if (!section.isExternal) - { - addSection(section, () => import('zero/pages/' + section.alias + '/' + section.alias)); - - if (section.children.length > 0) - { - section.children.forEach(child => - { - addSection(child, () => import('zero/pages/' + section.alias + '/' + section.alias + '/' + child.alias), section); - }); - } - } -}); - - -// add additional routes - -routes.push({ - path: '/preview', - component: () => import('zero/pages/preview'), - name: 'preview', - meta: { - name: '@preview.name' - } -}); - - -// find internal route definitions per section - -let addRoutesPerContext = (context, isPlugin) => -{ - context.keys().forEach((path) => - { - const routesDefinition = context(path); - const definition = routesDefinition.default || routesDefinition; - let _routes = _isArray(definition) ? definition : definition.routes; - - _routes.forEach(route => - { - const parentAlias = route.section || definition.section; - const isChild = typeof parentAlias === 'string'; - const parentRoute = isChild ? _find(routes, r => r.meta.alias === parentAlias) : null; - - // could not append routes to a section - if (isChild && !parentRoute) - { - if (_routes.length > 0) - { - warn(`router: Could not find section "${definition.section}" in route definition file ${path}`); - } - } - // append routes to a section - else if (isChild) - { - if (!parentRoute.children) - { - parentRoute.children = []; - } - parentRoute.children.push(route); - } - // add routes to root - else - { - routes.push(route); - } - }); - }); -}; - - - -// add internal route extensions -addRoutesPerContext(require.context('zero/pages', true, /routes\.js$/)); - -// add plugin route extensions -try -{ - addRoutesPerContext(require.context('@/../zero.Commerce/Plugins/zero.Commerce', true, /routes\.js$/), true); // TODO dynPATH -} -catch (exc) -{ - // TODO error will throw when user is not logged in as "section" in routes.js is null -} -//addRoutesPerContext(require.context('@/plugins', true, /routes\.js$/), true); // TODO use zero.pluginPath, but this fails - - - -// add fallback route (this should probably by 404 page) - -routes.push({ name: '404', path: '*', component: () => import('zero/pages/notfound') }); - - -export default routes; \ No newline at end of file diff --git a/zero.Web.UI/App/config/zero.plugins.js b/zero.Web.UI/App/config/zero.plugins.js deleted file mode 100644 index 4cdeccd0..00000000 --- a/zero.Web.UI/App/config/zero.plugins.js +++ /dev/null @@ -1,36 +0,0 @@ - -//zero.plugins = zero.plugins || []; - -//// TODO correct path -//let plugins = require.context('@/../zero.Commerce/Plugins/zero.Commerce', true, /plugin\.js$/); // TODO dynPATH - -//plugins.keys().forEach(path => -//{ -// const routesDefinition = plugins(path); -// const definition = routesDefinition.default || routesDefinition; - -// definition.name = 'commerce'; // TODO -// zero.plugins.push(definition); -//}); - -////plugins = require.context('@/../zero.Debug', true, /plugin\.js$/); // TODO dynPATH - -////plugins.keys().forEach(path => -////{ -//// const routesDefinition = plugins(path); -//// const definition = routesDefinition.default || routesDefinition; - -//// definition.name = 'project'; // TODO -//// zero.plugins.push(definition); -////}); - - -//// run setup action directly - -//zero.plugins.forEach(plugin => -//{ -// if (typeof plugin.setup === 'function') -// { -// plugin.setup(); -// } -//}); \ No newline at end of file diff --git a/zero.Web.UI/App/core/plugin.js b/zero.Web.UI/App/core/plugin.js index 64b38e39..35c55247 100644 --- a/zero.Web.UI/App/core/plugin.js +++ b/zero.Web.UI/App/core/plugin.js @@ -61,7 +61,7 @@ class Plugin */ addRoutes(routes) { - this.routes.forEach(route => this.addRoute(route)); + routes.forEach(route => this.addRoute(route)); } }; diff --git a/zero.Web.UI/App/core/plugin.zero.js b/zero.Web.UI/App/core/plugin.zero.js index 77647fea..04793aab 100644 --- a/zero.Web.UI/App/core/plugin.zero.js +++ b/zero.Web.UI/App/core/plugin.zero.js @@ -1,7 +1,7 @@  import Plugin from './plugin.js'; import renderers from '../renderers/all.js'; -import routes from '../config/routes.js'; +import routes from './routes.js'; const plugin = new Plugin('zero'); diff --git a/zero.Web.UI/App/core/routes.js b/zero.Web.UI/App/core/routes.js new file mode 100644 index 00000000..a0c85d9a --- /dev/null +++ b/zero.Web.UI/App/core/routes.js @@ -0,0 +1,29 @@ + +import Preview from '../pages/preview.vue'; +import NotFound from '../pages/notfound.vue'; +import dashboardRoutes from '../pages/dashboard/routes.js'; +import pageRoutes from '../pages/pages/routes.js'; +import mediaRoutes from '../pages/media/routes.js'; +import settingsRoutes from '../pages/settings/routes.js'; +import spaceRoutes from '../pages/spaces/routes.js'; + +export default [ + { + name: 'preview', + path: '/preview', + component: Preview, + meta: { + name: '@preview.name' + } + }, + ...dashboardRoutes, + ...pageRoutes, + ...mediaRoutes, + ...settingsRoutes, + ...spaceRoutes, + { + name: '404', + path: '*', + component: NotFound + } +]; \ No newline at end of file diff --git a/zero.Web.UI/App/core/zero.js b/zero.Web.UI/App/core/zero.js index 31e63d80..9b83d36e 100644 --- a/zero.Web.UI/App/core/zero.js +++ b/zero.Web.UI/App/core/zero.js @@ -2,9 +2,14 @@ // ref: // https://github.com/vuejs/vue-router/blob/dev/src/index.js +import Axios from 'axios'; import ZeroPlugin from './plugin.zero.js'; -import CommercePlugin from '../../../zero.Commerce/Plugins/zero.Commerce/plugin.js'; // TODO dynPath +import EventHub from '../services/eventhub.js'; +import VueRouter from 'vue-router'; +import Vue from 'vue'; +//import CommercePlugin from '../../../zero.Commerce/Plugins/zero.Commerce/plugin.js'; // TODO dynPath import options from './options.js'; +import routerConfig from '../config/router.config.js' class Zero { @@ -14,6 +19,8 @@ class Zero #vue = null; #plugins = []; + #routes = []; + #router = null; constructor(vue, opts) @@ -22,7 +29,7 @@ class Zero this.#vue = vue; this.use(ZeroPlugin); - this.use(CommercePlugin); + //this.use(CommercePlugin); } @@ -43,12 +50,33 @@ class Zero } + /* + * Get all installed zero plugins + */ + get router() + { + return this.#router; + } + + /* * Locates zero plugins and install them */ setup() { - + this.#router = new VueRouter({ + ...routerConfig, + routes: this.#routes + }); + + console.info(this.#routes); + + //const result = await Axios.get('zerovue/config'); + //this.config = { ...this.config, ...result.data }; + + //console.info(this.#vue.router); + + //EventHub.$emit('zero.setup'); } @@ -65,6 +93,12 @@ class Zero this.#plugins.push(plugin); + // append routes + plugin.routes.forEach(route => + { + this.#routes.push(route); + }); + console.log(`[zero] Installed %c${plugin.name}%cplugin`, 'font-style:italic;'); } }; @@ -80,6 +114,12 @@ Zero.install = (vue, opts) => Object.defineProperty(vue.prototype, 'zero', { get: () => zero }); + + zero.setup(); + + Vue.mixin({ + router: zero.router + }); }; diff --git a/zero.Web.UI/App/pages/dashboard/routes.js b/zero.Web.UI/App/pages/dashboard/routes.js new file mode 100644 index 00000000..d6dfc0fe --- /dev/null +++ b/zero.Web.UI/App/pages/dashboard/routes.js @@ -0,0 +1,18 @@ + +import Dashboard from './dashboard.vue'; + +const alias = __zero.alias.sections.dashboard; +const section = __zero.sections.find(x => x.alias === alias); + +export default section ? [ + { + name: section.alias, + path: section.url, + component: Dashboard, + meta: { + name: section.name, + alias: section.alias, + section: section + } + } +] : []; \ No newline at end of file diff --git a/zero.Web.UI/App/pages/media/routes.js b/zero.Web.UI/App/pages/media/routes.js index 9a54e5ef..a4fdd90c 100644 --- a/zero.Web.UI/App/pages/media/routes.js +++ b/zero.Web.UI/App/pages/media/routes.js @@ -1,46 +1,36 @@ -import { find as _find } from 'underscore'; + +import Media from './detail.vue'; +import Medias from './media.vue'; -const alias = zero.alias.sections.media; -const section = _find(zero.sections, section => section.alias === alias); -let routes = []; +const alias = __zero.alias.sections.media; +const section = __zero.sections.find(x => x.alias === alias); -if (section) -{ - routes.push({ +export default section ? [ + { + name: section.alias, + path: section.url, + component: Medias, + meta: { + name: section.name, + alias: section.alias, + section: section + }, + children: [ + { + name: 'mediaitem', + path: 'edit/:id', + props: true, + component: Media + } + ] + }, + { + name: 'mediafolder', path: section.url + '/folder/:id', props: true, - name: 'mediafolder', - component: () => import('zero/pages/' + alias + '/media') - }); - - routes.push({ - section: alias, - path: 'edit/:id', - props: true, - name: 'mediaitem', - component: () => import('zero/pages/' + alias + '/detail') - }); - - routes.push({ - section: alias, - path: 'recyclebin', - name: 'mediarecyclebin', - component: () => import('zero/pages/' + alias + '/recyclebin'), + component: Medias, meta: { - name: '@recyclebin.name' + name: section.name } - }); - - //routes.push({ - // path: 'history', - // name: 'history', - // component: () => import('zero/pages/' + alias + '/history'), - // meta: { - // name: '@page.history.name' - // } - //}); -} - -export default { - routes: routes -}; \ No newline at end of file + } +] : []; \ No newline at end of file diff --git a/zero.Web.UI/App/pages/pages/routes.js b/zero.Web.UI/App/pages/pages/routes.js index af85b7e4..3224beb0 100644 --- a/zero.Web.UI/App/pages/pages/routes.js +++ b/zero.Web.UI/App/pages/pages/routes.js @@ -1,45 +1,45 @@ -import { find as _find } from 'underscore'; + +import Page from './page.vue'; +import Pages from './pages.vue'; +import RecycleBin from './recyclebin/recyclebin.vue'; -const alias = zero.alias.sections.pages; -const section = _find(zero.sections, section => section.alias === alias); -let routes = []; +const alias = __zero.alias.sections.pages; +const section = __zero.sections.find(x => x.alias === alias); -if (section) -{ - routes.push({ - path: 'edit/:id', - props: true, - name: 'page', - component: () => import('zero/pages/' + alias + '/page') - }); - - routes.push({ - path: 'create/:type/:parent?', - props: true, - name: 'page-create', - component: () => import('zero/pages/' + alias + '/page') - }); - - routes.push({ - path: 'recyclebin', - name: 'recyclebin', - component: () => import('zero/pages/' + alias + '/recyclebin/recyclebin'), +export default section ? [ + { + name: section.alias, + path: section.url, + component: Pages, meta: { - name: '@recyclebin.name' - } - }); - - routes.push({ - path: 'history', - name: 'history', - component: () => import('zero/pages/' + alias + '/history'), - meta: { - name: '@page.history.name' - } - }); -} - -export default { - section: alias, - routes: routes -}; \ No newline at end of file + name: section.name, + alias: section.alias, + section: section + }, + children: [ + { + name: 'page', + path: 'edit/:id', + section: alias, + props: true, + component: Page + }, + { + name: 'page-create', + path: 'create/:type/:parent?', + section: alias, + props: true, + component: Page + }, + { + name: 'recyclebin', + path: 'recyclebin', + section: alias, + component: RecycleBin, + meta: { + name: '@recyclebin.name' + } + } + ] + } +] : []; \ No newline at end of file diff --git a/zero.Web.UI/App/pages/settings/application.vue b/zero.Web.UI/App/pages/settings/application.vue index 8ec48068..7f945064 100644 --- a/zero.Web.UI/App/pages/settings/application.vue +++ b/zero.Web.UI/App/pages/settings/application.vue @@ -18,7 +18,7 @@ data: () => ({ meta: {}, model: { name: null, features: [], domains: [] }, - route: zero.alias.sections.settings + '-' + zero.alias.settings.applications + '-edit', + route: zero.alias.settings.applications + '-edit', disabled: false }), diff --git a/zero.Web.UI/App/pages/settings/applications-items.vue b/zero.Web.UI/App/pages/settings/applications-items.vue index c2f09f8d..f0e6a3c0 100644 --- a/zero.Web.UI/App/pages/settings/applications-items.vue +++ b/zero.Web.UI/App/pages/settings/applications-items.vue @@ -13,7 +13,7 @@ diff --git a/zero.Web/ZeroVue.cs b/zero.Web/ZeroVue.cs index befd99ec..b03a5627 100644 --- a/zero.Web/ZeroVue.cs +++ b/zero.Web/ZeroVue.cs @@ -46,7 +46,7 @@ namespace zero.Web /// - public async Task ConfigAsJson() + public async Task Config() { ZeroVueConfig config = new ZeroVueConfig(); @@ -79,7 +79,14 @@ namespace zero.Web }; } - return JsonSerializer.Serialize(config, new JsonSerializerOptions() + return config; + } + + + /// + public async Task ConfigAsJson() + { + return JsonSerializer.Serialize(await Config(), new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); @@ -270,6 +277,11 @@ namespace zero.Web public interface IZeroVue { + /// + /// Creates the zero configuration for vue + /// + Task Config(); + /// /// Creates the zero configuration for vue ///