system for creating plugins
This commit is contained in:
+3
-1
@@ -270,4 +270,6 @@ Temp/
|
||||
**/Assets/**/setup.*
|
||||
**/Assets/**/*.js
|
||||
deps/*.dll
|
||||
zero.Commerce/
|
||||
zero.Commerce/
|
||||
zero.Web.UI/package.json
|
||||
zero.Web.UI/package-lock.json
|
||||
@@ -19,16 +19,15 @@
|
||||
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 Router from 'zero/router.config.js'
|
||||
import AuthApi from 'zero/services/auth.js'
|
||||
import 'zero/vue.config.js'
|
||||
import 'zero/axios.config.js'
|
||||
import 'zero/zero.config.js'
|
||||
import 'zero/config/vue.config.js'
|
||||
import 'zero/config/axios.config.js'
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
|
||||
router: Router,
|
||||
// router: Router,
|
||||
|
||||
components: { AppNavigation, AppOverlays, AppLogin, AppNotifications },
|
||||
|
||||
@@ -38,6 +37,7 @@
|
||||
|
||||
created()
|
||||
{
|
||||
console.info(this.zero);
|
||||
AuthApi.$on('authenticated', isAuthenticated =>
|
||||
{
|
||||
this.isAuthenticated = isAuthenticated;
|
||||
@@ -52,7 +52,7 @@
|
||||
getClassList()
|
||||
{
|
||||
return {
|
||||
'is-preview': this.$route.name === 'preview'
|
||||
'is-preview': false //this.$route.name === 'preview'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import Localization from 'zero/services/localization';
|
||||
|
||||
|
||||
// set meta title before routing
|
||||
const beforeEach = () => (to, from, next) =>
|
||||
{
|
||||
let isGuarded = false;
|
||||
|
||||
// set document title + call next
|
||||
let callback = () =>
|
||||
{
|
||||
let title = Localization.localize('@zero.name');
|
||||
|
||||
if (to.meta.name && to.meta.alias !== zero.alias.sections.dashboard)
|
||||
{
|
||||
let name = to.meta.name;
|
||||
let nameParts = _isArray(name) ? name : [name];
|
||||
let translations = [];
|
||||
|
||||
nameParts.forEach(part =>
|
||||
{
|
||||
if (part)
|
||||
{
|
||||
translations.push(Localization.localize(part));
|
||||
}
|
||||
});
|
||||
|
||||
title += ': ' + translations.join(' - ');
|
||||
}
|
||||
|
||||
document.title = title;
|
||||
|
||||
next();
|
||||
};
|
||||
|
||||
// dirty form guard
|
||||
if (from.matched.length && from.matched[0].instances)
|
||||
{
|
||||
let instance = from.matched[0].instances.default;
|
||||
|
||||
if (instance.$refs['form'] && typeof instance.$refs.form.beforeRouteLeave === 'function')
|
||||
{
|
||||
isGuarded = true;
|
||||
instance.$refs.form.beforeRouteLeave(to, from, res =>
|
||||
{
|
||||
if (res === false)
|
||||
{
|
||||
next(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!isGuarded)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export default {
|
||||
mode: 'history',
|
||||
base: zero.path,
|
||||
linkActiveClass: 'is-active',
|
||||
linkExactActiveClass: 'is-active-exact',
|
||||
beforeEach: beforeEach,
|
||||
scrollBehavior(to, from, savedPosition)
|
||||
{
|
||||
return savedPosition ? savedPosition : { x: 0, y: 0 };
|
||||
}
|
||||
};
|
||||
@@ -1,25 +1,20 @@
|
||||
import Vue from 'vue';
|
||||
import VueRouter from 'vue-router';
|
||||
import Localization from 'zero/services/localization';
|
||||
|
||||
import { isArray as _isArray, find as _find, map as _map, filter as _filter } from 'underscore';
|
||||
import { warn } from 'zero/services/debug';
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
const routes = [];
|
||||
|
||||
let routes = [];
|
||||
|
||||
|
||||
// add defined backoffice sections (with their children) to the router
|
||||
|
||||
let addSection = (section, component, parent) =>
|
||||
const addSection = (section, component, parent) =>
|
||||
{
|
||||
let route = {
|
||||
path: section.url,
|
||||
path: section.url,
|
||||
component: component,
|
||||
name: (parent ? parent.alias + '-' : '') + section.alias,
|
||||
meta: {
|
||||
name: [ section.name, (parent ? parent.name : null) ],
|
||||
name: [section.name, (parent ? parent.name : null)],
|
||||
alias: section.alias,
|
||||
section: section,
|
||||
parent: parent
|
||||
@@ -93,7 +88,7 @@ let addRoutesPerContext = (context, isPlugin) =>
|
||||
}
|
||||
parentRoute.children.push(route);
|
||||
}
|
||||
// add routes to root
|
||||
// add routes to root
|
||||
else
|
||||
{
|
||||
routes.push(route);
|
||||
@@ -120,92 +115,9 @@ catch (exc)
|
||||
|
||||
|
||||
|
||||
|
||||
// add fallback route (this should probably by 404 page)
|
||||
|
||||
routes.push({ name: '404', path: '*', component: () => import('zero/pages/notfound') });
|
||||
|
||||
|
||||
|
||||
|
||||
// create the router with history mode
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
routes: routes,
|
||||
base: zero.path,
|
||||
linkActiveClass: 'is-active',
|
||||
linkExactActiveClass: 'is-active-exact',
|
||||
scrollBehavior(to, from, savedPosition)
|
||||
{
|
||||
return savedPosition ? savedPosition : { x: 0, y: 0 };
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// set meta title before routing
|
||||
|
||||
router.beforeEach((to, from, next) =>
|
||||
{
|
||||
let isGuarded = false;
|
||||
|
||||
|
||||
// set document title + call next
|
||||
let callback = () =>
|
||||
{
|
||||
let title = Localization.localize('@zero.name');
|
||||
|
||||
if (to.meta.name && to.meta.alias !== zero.alias.sections.dashboard)
|
||||
{
|
||||
let name = to.meta.name;
|
||||
let nameParts = _isArray(name) ? name : [name];
|
||||
let translations = [];
|
||||
|
||||
nameParts.forEach(part =>
|
||||
{
|
||||
if (part)
|
||||
{
|
||||
translations.push(Localization.localize(part));
|
||||
}
|
||||
});
|
||||
|
||||
title += ': ' + translations.join(' - ');
|
||||
}
|
||||
|
||||
document.title = title;
|
||||
|
||||
next();
|
||||
};
|
||||
|
||||
// dirty form guard
|
||||
if (from.matched.length && from.matched[0].instances)
|
||||
{
|
||||
let instance = from.matched[0].instances.default;
|
||||
|
||||
if (instance.$refs['form'] && typeof instance.$refs.form.beforeRouteLeave === 'function')
|
||||
{
|
||||
isGuarded = true;
|
||||
instance.$refs.form.beforeRouteLeave(to, from, res =>
|
||||
{
|
||||
if (res === false)
|
||||
{
|
||||
next(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!isGuarded)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default router;
|
||||
export default routes;
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
//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();
|
||||
// }
|
||||
//});
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
export default {
|
||||
version: '0.1.0',
|
||||
|
||||
apiPath: '/zero/api/',
|
||||
|
||||
path: '/zero/',
|
||||
|
||||
media: {
|
||||
defaults: {
|
||||
images: ['.jpg', '.jpeg', '.png', '.webp', '.svg'],
|
||||
images_natural: ['.jpg', '.jpeg', '.webp'],
|
||||
images_artificial: ['.png', '.webp', '.svg']
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
class Plugin
|
||||
{
|
||||
#name;
|
||||
#onInstall;
|
||||
|
||||
routes = [];
|
||||
renderers = {};
|
||||
|
||||
|
||||
constructor(name)
|
||||
{
|
||||
this.#name = name;
|
||||
}
|
||||
|
||||
|
||||
get name()
|
||||
{
|
||||
return this.#name;
|
||||
}
|
||||
|
||||
get install()
|
||||
{
|
||||
return this.#onInstall;
|
||||
}
|
||||
|
||||
set install(callback)
|
||||
{
|
||||
this.#onInstall = callback;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add a new vue form renderer to the global configuration
|
||||
*/
|
||||
addRenderer(alias, config)
|
||||
{
|
||||
this.renderers[alias] = config;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds new form renderers to the global configuration
|
||||
* Can either by an array (where a key of the child object is `alias`) or an object where the key is the renderer alias
|
||||
*/
|
||||
addRenderers(renderers)
|
||||
{
|
||||
let items = !Array.isArray(renderers) ? Object.values(renderers) : renderers;
|
||||
items.forEach(item => this.addRenderer(item.alias, item));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new route to vue-router
|
||||
*/
|
||||
addRoute(route)
|
||||
{
|
||||
this.routes.push(route);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds new routes to vue-router
|
||||
*/
|
||||
addRoutes(routes)
|
||||
{
|
||||
this.routes.forEach(route => this.addRoute(route));
|
||||
}
|
||||
};
|
||||
|
||||
export default Plugin;
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
import Plugin from './plugin.js';
|
||||
import renderers from '../renderers/all.js';
|
||||
import routes from '../config/routes.js';
|
||||
|
||||
const plugin = new Plugin('zero');
|
||||
|
||||
// add renderers
|
||||
plugin.addRenderers(renderers);
|
||||
|
||||
// add routes
|
||||
plugin.addRoutes(routes);
|
||||
|
||||
export default plugin;
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
// ref:
|
||||
// https://github.com/vuejs/vue-router/blob/dev/src/index.js
|
||||
|
||||
import ZeroPlugin from './plugin.zero.js';
|
||||
import CommercePlugin from '../../../zero.Commerce/Plugins/zero.Commerce/plugin.js'; // TODO dynPath
|
||||
import options from './options.js';
|
||||
|
||||
class Zero
|
||||
{
|
||||
static install;
|
||||
|
||||
config = { ...options };
|
||||
|
||||
#vue = null;
|
||||
#plugins = [];
|
||||
|
||||
|
||||
constructor(vue, opts)
|
||||
{
|
||||
this.config = { ...options, ...opts };
|
||||
this.#vue = vue;
|
||||
|
||||
this.use(ZeroPlugin);
|
||||
this.use(CommercePlugin);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the currently installed version of the zero frontend
|
||||
*/
|
||||
get version()
|
||||
{
|
||||
return this.config.version;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all installed zero plugins
|
||||
*/
|
||||
get plugins()
|
||||
{
|
||||
return this.#plugins;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Locates zero plugins and install them
|
||||
*/
|
||||
setup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Installs a zero plugin
|
||||
* Each plugin is a superset of a vue (client) plugin and can therefore hook into the vue system
|
||||
*/
|
||||
use(plugin)
|
||||
{
|
||||
if (typeof plugin.install === 'function')
|
||||
{
|
||||
plugin.install(this.#vue, this);
|
||||
}
|
||||
|
||||
this.#plugins.push(plugin);
|
||||
|
||||
console.log(`[zero] Installed %c${plugin.name}%cplugin`, 'font-style:italic;');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Registers zero within the vue system
|
||||
*/
|
||||
Zero.install = (vue, opts) =>
|
||||
{
|
||||
const zero = new Zero(vue, opts);
|
||||
|
||||
Object.defineProperty(vue.prototype, 'zero', {
|
||||
get: () => zero
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export default Zero;
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
import application from './application.js';
|
||||
import country from './country.js';
|
||||
import language from './language.js';
|
||||
import media from './media.js';
|
||||
import translation from './translation.js';
|
||||
import user from './user.js';
|
||||
import userRole from './userRole.js';
|
||||
|
||||
export default {
|
||||
application,
|
||||
country,
|
||||
language,
|
||||
media,
|
||||
translation,
|
||||
user,
|
||||
userRole
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
//# sourceMappingURL=test.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"test.js","sourceRoot":"","sources":["test.ts"],"names":[],"mappings":""}
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
window.zero = window.zero || {};
|
||||
window.zero.config = window.zero.config || {};
|
||||
|
||||
window.zero.config.media = {
|
||||
defaults: {
|
||||
images: ['.jpg', '.jpeg', '.png', '.webp', '.svg'],
|
||||
images_natural: ['.jpg', '.jpeg', '.webp'],
|
||||
images_artificial: ['.png', '.webp', '.svg']
|
||||
}
|
||||
};
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
+11
-5
@@ -1,16 +1,22 @@
|
||||
import Vue from 'vue';
|
||||
import VueRouter from 'vue-router';
|
||||
import Zero from 'zero/core/zero.js';
|
||||
import App from 'zero/app';
|
||||
import 'zero/components/globals';
|
||||
import 'zero/directives/globals';
|
||||
import 'zero/filters/globals';
|
||||
|
||||
zero.apps = {
|
||||
shared: true
|
||||
};
|
||||
|
||||
import 'zero/components/globals';
|
||||
import 'zero/directives/globals';
|
||||
import 'zero/filters/globals';
|
||||
import 'zero/renderers/globals';
|
||||
//import 'zero/pages/register';
|
||||
|
||||
import 'zero/zero.plugins.js';
|
||||
//import ZeroPlugin from 'zero/config/zero.plugin.js';
|
||||
|
||||
Vue.use(VueRouter);
|
||||
Vue.use(Zero);
|
||||
|
||||
import 'zero/config/zero.plugins.js';
|
||||
|
||||
new Vue(App).$mount('#app');
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
// TODO
|
||||
// create tool which installs node, npm + other global dependencies (npm-deps(1)) needed to run the application
|
||||
// (see umbraco for details)
|
||||
// maybe this can be done via the create dotnet-tool
|
||||
|
||||
"name": "zero",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"install": "",
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"build-dev": "vue-cli-service build --mode development",
|
||||
"watch": "vue-cli-service build --mode development --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.5",
|
||||
"axios": "^0.19.2",
|
||||
"dayjs": "^1.8.26",
|
||||
"flatpickr": "^4.6.3",
|
||||
"lodash": "*",
|
||||
"sortablejs": "^1.10.2",
|
||||
"underscore": "^1.10.2",
|
||||
"vue": "^2.6.11",
|
||||
"vue-router": "^3.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-router": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"sass": "^1.26.5",
|
||||
"sass-loader": "^8.0.2",
|
||||
"syncpack": "^5.6.10",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"install": "",
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"build-dev": "vue-cli-service build --mode development",
|
||||
@@ -25,6 +26,7 @@
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"sass": "^1.26.5",
|
||||
"sass-loader": "^8.0.2",
|
||||
"syncpack": "^5.6.10",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user