diff --git a/zero.Web.UI/App/components/tabs/tabs.vue b/zero.Web.UI/App/components/tabs/tabs.vue
index 0c08b508..0ac20a4c 100644
--- a/zero.Web.UI/App/components/tabs/tabs.vue
+++ b/zero.Web.UI/App/components/tabs/tabs.vue
@@ -34,14 +34,11 @@
tabs: []
}),
- created()
+ mounted()
{
this.cacheKey = this.cache ? `zero.ui-tabs.cache.${this.cache}` : null;
this.tabs = this.$children;
- },
- mounted()
- {
if (this.cache)
{
const cachedActiveTab = localStorage.getItem(this.cacheKey);
diff --git a/zero.Web.UI/App/core/editor-field.js b/zero.Web.UI/App/core/editor-field.js
index c9dd0bb7..51b3ad4d 100644
--- a/zero.Web.UI/App/core/editor-field.js
+++ b/zero.Web.UI/App/core/editor-field.js
@@ -6,21 +6,21 @@ import Rte from '../editor/fields/rte.vue';
import Select from '../editor/fields/select.vue';
import Textarea from '../editor/fields/textarea.vue';
import Toggle from '../editor/fields/toggle.vue';
-import Alias from '../editor/fields/toggle.vue';
-import Output from '../editor/fields/toggle.vue';
-import Checklist from '../editor/fields/toggle.vue';
-import ColorPicker from '../editor/fields/toggle.vue';
-import CountryPicker from '../editor/fields/toggle.vue';
-import CulturePicker from '../editor/fields/toggle.vue';
-import DateRangePicker from '../editor/fields/toggle.vue';
-import IconPicker from '../editor/fields/toggle.vue';
-import LanguagePicker from '../editor/fields/toggle.vue';
-import InputList from '../editor/fields/toggle.vue';
-import Media from '../editor/fields/toggle.vue';
-import Modules from '../editor/fields/toggle.vue';
-import Nested from '../editor/fields/toggle.vue';
-import State from '../editor/fields/toggle.vue';
-import Tags from '../editor/fields/toggle.vue';
+import Alias from '../editor/fields/alias.vue';
+import Output from '../editor/fields/output.vue';
+import Checklist from '../editor/fields/checklist.vue';
+import ColorPicker from '../editor/fields/colorpicker.vue';
+import CountryPicker from '../editor/fields/countrypicker.vue';
+import CulturePicker from '../editor/fields/culturepicker.vue';
+import DateRangePicker from '../editor/fields/daterangepicker.vue';
+import IconPicker from '../editor/fields/iconPicker.vue';
+import LanguagePicker from '../editor/fields/language.vue';
+import InputList from '../editor/fields/inputlist.vue';
+import Media from '../editor/fields/media.vue';
+import Modules from '../editor/fields/modules.vue';
+import Nested from '../editor/fields/nested.vue';
+import State from '../editor/fields/state.vue';
+import Tags from '../editor/fields/tags.vue';
class EditorField
@@ -28,6 +28,7 @@ class EditorField
path = null;
options = {
label: null,
+ hideLabel: false,
description: null,
helpText: null,
condition: null,
@@ -48,6 +49,22 @@ class EditorField
}
+ get component()
+ {
+ return this.#component;
+ }
+
+ get componentOptions()
+ {
+ return this.#componentOptions;
+ }
+
+ get isRequired()
+ {
+ return this.#required;
+ }
+
+
/**
*
*/
@@ -87,7 +104,7 @@ class EditorField
* @param {object} [options] - Custom options
* @returns {EditorField}
*/
- component(component, options)
+ custom(component, options)
{
return this._setComponent(component, { ...options });
}
@@ -281,7 +298,7 @@ class EditorField
* @param {string} [addLabel] - Label for the add button
* @returns {EditorField}
*/
- inputList(limit, maxItemLength)
+ inputList(limit, maxItemLength, addLabel)
{
return this._setComponent(InputList, { limit, maxItemLength, addLabel });
}
diff --git a/zero.Web.UI/App/core/editor.js b/zero.Web.UI/App/core/editor.js
index 5ee126a2..d82761da 100644
--- a/zero.Web.UI/App/core/editor.js
+++ b/zero.Web.UI/App/core/editor.js
@@ -4,8 +4,15 @@ import EditorField from './editor-field.js';
class Editor
{
#alias;
- #templateLabel = field => field;
- #templateDescription = field => field;
+
+ /**
+ * Overrides the string generation for the label
+ */
+ templateLabel = field => field;
+ /**
+ * Overrides the string generation for the description
+ */
+ templateDescription = field => field;
tabs = [];
fields = [];
@@ -22,34 +29,6 @@ class Editor
return this.#alias;
}
- /**
- * Overrides the string generation for the label
- * @param {function} callback - Called when a label is constructed
- */
- set onLabelCreate(callback)
- {
- if (typeof callback !== 'function')
- {
- console.warn(`[zero] onLabelCreate excepts a function as the first parameter`);
- return;
- }
- this.#templateLabel = callback;
- }
-
- /**
- * Overrides the string generation for the label description
- * @param {function} callback - Called when a description is constructed
- */
- set onDescriptionCreate(callback)
- {
- if (typeof callback !== 'function')
- {
- console.warn(`[zero] onDescriptionCreate excepts a function as the first parameter`);
- return;
- }
- this.#templateDescription = callback;
- }
-
/**
* A tab within an editor
@@ -100,6 +79,7 @@ class Editor
* @param {string} path - Model path
* @param {object} [options] - Custom options
* @param {string} [options.label] - A custom label for this field (otherwise it's generated via `onLabelCreate`)
+ * @param {string} [options.hideLabel] - Hide the field label and make the content full-width
* @param {string} [options.description] - A custom description for this field (otherwise it's generated via `onDescriptionCreate`)
* @param {string} [options.helpText] - Display a help text below the field
* @param {boolean|function} [options.condition] - Conditionally hide the field
@@ -111,10 +91,23 @@ class Editor
field(path, options)
{
const field = new EditorField(path, options);
+ this.fields.push(field);
return field;
}
+ /**
+ * Get fields for the specified tab
+ * @param {string|EditorTab} [tab] - Pass the tab or its alias
+ * @returns {EditorField[]}
+ */
+ getFields(tab)
+ {
+ const alias = typeof tab === 'undefined' ? null : (typeof tab === 'string' ? tab : tab.alias);
+ return this.fields.filter(x => !alias ? true : x.options.tab === alias);
+ }
+
+
/**
* Create a new tab instance
* @returns {EditorTab}
diff --git a/zero.Web.UI/App/core/plugin.js b/zero.Web.UI/App/core/plugin.js
index 82a4c168..cecca522 100644
--- a/zero.Web.UI/App/core/plugin.js
+++ b/zero.Web.UI/App/core/plugin.js
@@ -5,7 +5,7 @@ class Plugin
#onInstall;
routes = [];
- renderers = [];
+ editors = [];
constructor(name)
@@ -33,20 +33,19 @@ class Plugin
/*
* Add a new vue form renderer to the global configuration
*/
- addRenderer(alias, config)
+ addEditor(config)
{
- config.alias = alias;
- this.renderers.push(config);
+ this.editors.push(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)
+ addEditors(editors)
{
- let items = !Array.isArray(renderers) ? Object.values(renderers) : renderers;
- items.forEach(item => this.addRenderer(item.alias, item));
+ let items = !Array.isArray(editors) ? Object.values(editors) : editors;
+ items.forEach(item => this.addEditor(item));
}
/*
diff --git a/zero.Web.UI/App/core/plugin.zero.js b/zero.Web.UI/App/core/plugin.zero.js
index 04793aab..561fcc60 100644
--- a/zero.Web.UI/App/core/plugin.zero.js
+++ b/zero.Web.UI/App/core/plugin.zero.js
@@ -1,12 +1,12 @@
import Plugin from './plugin.js';
-import renderers from '../renderers/all.js';
+import editors from '../editors/all.js';
import routes from './routes.js';
const plugin = new Plugin('zero');
// add renderers
-plugin.addRenderers(renderers);
+plugin.addEditors(editors);
// add routes
plugin.addRoutes(routes);
diff --git a/zero.Web.UI/App/core/zero.js b/zero.Web.UI/App/core/zero.js
index 222b614e..73ff3f26 100644
--- a/zero.Web.UI/App/core/zero.js
+++ b/zero.Web.UI/App/core/zero.js
@@ -19,7 +19,7 @@ class Zero
#vue = null;
#plugins = [];
- #renderers = [];
+ #editors = [];
#routes = [];
#router = null;
@@ -95,8 +95,8 @@ class Zero
// append routes
plugin.routes.forEach(x => this.#routes.push(x));
- // append renderers
- plugin.renderers.forEach(x => this.#renderers.push(x));
+ // append editors
+ plugin.editors.forEach(x => this.#editors.push(x));
console.log(`[zero] Installed %c${plugin.name}%cplugin`, 'font-style:italic;');
}
@@ -105,9 +105,9 @@ class Zero
/*
* Returns a renderer
*/
- getRenderer(alias)
+ getEditor(alias)
{
- const renderer = this.#renderers.find(x => x.alias === alias);
+ const renderer = this.#editors.find(x => x.alias === alias);
if (!renderer)
{
diff --git a/zero.Web.UI/App/directives/localize.js b/zero.Web.UI/App/directives/localize.js
index d1c85c36..cd1fa6c5 100644
--- a/zero.Web.UI/App/directives/localize.js
+++ b/zero.Web.UI/App/directives/localize.js
@@ -8,11 +8,12 @@ Vue.directive('localize', (el, binding) =>
{
if (binding.value !== binding.oldValue || !el.innerText)
{
+ const hasValue = !!binding.value;
const isObject = typeof binding.value === 'object';
- let key = isObject ? binding.value.key : binding.value;
- let options = isObject ? binding.value : null;
+ let key = hasValue ? (isObject ? binding.value.key : binding.value) : null;
+ let options = hasValue && isObject ? binding.value : null;
- const result = Localization.localize(key, options);
+ const result = hasValue ? Localization.localize(key, options) : '';
// set content as html
if (binding.arg === 'html')
diff --git a/zero.Web.UI/App/editor/editor-component-old.vue b/zero.Web.UI/App/editor/editor-component-old.vue
new file mode 100644
index 00000000..9e3c94e7
--- /dev/null
+++ b/zero.Web.UI/App/editor/editor-component-old.vue
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zero.Web.UI/App/editor/editor-component.vue b/zero.Web.UI/App/editor/editor-component.vue
index 9e3c94e7..115c5cba 100644
--- a/zero.Web.UI/App/editor/editor-component.vue
+++ b/zero.Web.UI/App/editor/editor-component.vue
@@ -1,7 +1,8 @@
-
-
-
+
+
+
@@ -9,46 +10,31 @@
+
+
\ No newline at end of file
diff --git a/zero.Web.UI/App/editor/editor.vue b/zero.Web.UI/App/editor/editor.vue
index 08a8c7e7..df141709 100644
--- a/zero.Web.UI/App/editor/editor.vue
+++ b/zero.Web.UI/App/editor/editor.vue
@@ -1,71 +1,35 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
- Not found
- The renderer [{{config}}] could not be found
-
\ No newline at end of file
diff --git a/zero.Web.UI/App/editor/fields/text.vue b/zero.Web.UI/App/editor/fields/text.vue
index 9e186990..0e5e4e43 100644
--- a/zero.Web.UI/App/editor/fields/text.vue
+++ b/zero.Web.UI/App/editor/fields/text.vue
@@ -1,7 +1,5 @@
-
-
-
+
@@ -12,17 +10,13 @@
type: String,
default: null
},
- config: Object,
- disabled: {
- type: Boolean,
- default: false
- }
- },
-
- computed: {
- maxLength()
- {
- return this.config.maxLength > 0 ? this.config.maxLength : null;
+ maxLength: {
+ type: Number,
+ default: null
+ },
+ placeholder: {
+ type: String,
+ default: null
}
}
}
diff --git a/zero.Web.UI/App/editor/fields/toggle.vue b/zero.Web.UI/App/editor/fields/toggle.vue
index d9322a05..e01d4796 100644
--- a/zero.Web.UI/App/editor/fields/toggle.vue
+++ b/zero.Web.UI/App/editor/fields/toggle.vue
@@ -1,5 +1,5 @@
-
+
@@ -14,7 +14,10 @@
type: Boolean,
default: false
},
- config: Object
+ negative: {
+ type: Boolean,
+ default: false
+ }
}
}
\ No newline at end of file
diff --git a/zero.Web.UI/App/editors/all.js b/zero.Web.UI/App/editors/all.js
new file mode 100644
index 00000000..a46add92
--- /dev/null
+++ b/zero.Web.UI/App/editors/all.js
@@ -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
+};
\ No newline at end of file
diff --git a/zero.Web.UI/App/editors/application.js b/zero.Web.UI/App/editors/application.js
new file mode 100644
index 00000000..cfbbfce9
--- /dev/null
+++ b/zero.Web.UI/App/editors/application.js
@@ -0,0 +1,23 @@
+
+import Editor from '../core/editor.js';
+import ApplicationFeatures from '../pages/settings/application-features.vue';
+
+const editor = new Editor('application');
+const prefix = '@application.fields.';
+
+editor.templateLabel = x => prefix + x;
+editor.templateDescription = x => prefix + x + '_text';
+
+const general = editor.tab('general', '@ui.tab_general');
+const domains = editor.tab('domains', '@application.tab_domains', x => x.domains.length);
+const features = editor.tab('features', '@application.tab_features', x => x.features.length);
+
+general.field('name', { label: '@ui.name' }).text(50).required();
+general.field('fullName').text(120);
+general.field('email').text(120).required();
+general.field('imageId').image();
+general.field('iconId').image();
+domains.field('domains', { helpText: prefix + 'domains_help' }).inputList(10, null, prefix + 'domains_add').required();
+features.field('features').custom(ApplicationFeatures);
+
+export default editor;
\ No newline at end of file
diff --git a/zero.Web.UI/App/renderers/country.js b/zero.Web.UI/App/editors/country.js
similarity index 100%
rename from zero.Web.UI/App/renderers/country.js
rename to zero.Web.UI/App/editors/country.js
diff --git a/zero.Web.UI/App/renderers/language.js b/zero.Web.UI/App/editors/language.js
similarity index 100%
rename from zero.Web.UI/App/renderers/language.js
rename to zero.Web.UI/App/editors/language.js
diff --git a/zero.Web.UI/App/renderers/media.js b/zero.Web.UI/App/editors/media.js
similarity index 100%
rename from zero.Web.UI/App/renderers/media.js
rename to zero.Web.UI/App/editors/media.js
diff --git a/zero.Web.UI/App/renderers/translation.js b/zero.Web.UI/App/editors/translation.js
similarity index 100%
rename from zero.Web.UI/App/renderers/translation.js
rename to zero.Web.UI/App/editors/translation.js
diff --git a/zero.Web.UI/App/renderers/user.js b/zero.Web.UI/App/editors/user.js
similarity index 100%
rename from zero.Web.UI/App/renderers/user.js
rename to zero.Web.UI/App/editors/user.js
diff --git a/zero.Web.UI/App/renderers/userRole.js b/zero.Web.UI/App/editors/userRole.js
similarity index 100%
rename from zero.Web.UI/App/renderers/userRole.js
rename to zero.Web.UI/App/editors/userRole.js
diff --git a/zero.Web.UI/App/pages/settings/application.vue b/zero.Web.UI/App/pages/settings/application.vue
index 7f945064..9f83fe9d 100644
--- a/zero.Web.UI/App/pages/settings/application.vue
+++ b/zero.Web.UI/App/pages/settings/application.vue
@@ -1,7 +1,7 @@
-
+
@@ -26,7 +26,8 @@
onLoad(form)
{
- form.load(!this.id ? ApplicationsApi.getEmpty() : ApplicationsApi.getById(this.id)).then(response =>
+ const id = this.$route.params.id;
+ form.load(!id ? ApplicationsApi.getEmpty() : ApplicationsApi.getById(id)).then(response =>
{
this.disabled = !response.meta.canEdit;
this.meta = response.meta;
diff --git a/zero.Web.UI/App/renderers/all.js b/zero.Web.UI/App/renderers/all.js
deleted file mode 100644
index c364b0ae..00000000
--- a/zero.Web.UI/App/renderers/all.js
+++ /dev/null
@@ -1,18 +0,0 @@
-
-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
-};
\ No newline at end of file
diff --git a/zero.Web.UI/App/renderers/application-new.js b/zero.Web.UI/App/renderers/application-new.js
deleted file mode 100644
index 1bdb386f..00000000
--- a/zero.Web.UI/App/renderers/application-new.js
+++ /dev/null
@@ -1,23 +0,0 @@
-
-import Editor from '../core/editor.js';
-import ApplicationFeatures from '../pages/settings/application-features.vue';
-
-const editor = new Editor('application');
-const prefix = '@application.fields.';
-
-editor.onLabelCreate = x => prefix + x;
-editor.onDescriptionCreate = x => prefix + x + '_text';
-
-editor.tab('general', '@ui.tab_general');
-const domains = editor.tab('domains', '@application.tab_domains', x => x.domains.length);
-const features = editor.tab('features', '@application.tab_features', x => x.features.length);
-
-editor.field('name', { label: '@ui.name' }).text(50);
-editor.field('fullName').text(120);
-editor.field('email').text(120);
-editor.field('imageId').image();
-editor.field('iconId').image();
-domains.field('domains', { helpText: prefix + 'domains_help' }).inputList(10, null, prefix + 'domains_add');
-features.field('features').component(ApplicationFeatures);
-
-export default editor;
\ No newline at end of file
diff --git a/zero.Web.UI/App/renderers/application.js b/zero.Web.UI/App/renderers/application.js
deleted file mode 100644
index f4a61661..00000000
--- a/zero.Web.UI/App/renderers/application.js
+++ /dev/null
@@ -1,77 +0,0 @@
-export default {
- alias: 'application',
-
- tabs: [
- {
- name: 'general',
- label: '@ui.tab_general'
- },
- {
- name: 'domains',
- label: '@application.tab_domains',
- count: x => x.domains.length
- },
- {
- name: 'features',
- label: '@application.tab_features',
- count: x => x.features.length
- }
- ],
-
- labelTemplate(field)
- {
- return "@application.fields." + field;
- },
-
- descriptionTemplate(field)
- {
- return "@application.fields." + field + "_text";
- },
-
- fields: [
- {
- field: 'name',
- display: 'text',
- label: '@ui.name',
- required: true,
- maxLength: 50
- },
- {
- field: 'fullName',
- display: 'text',
- maxLength: 120
- },
- {
- field: 'email',
- display: 'text',
- required: true,
- maxLength: 120
- },
- {
- field: 'imageId',
- display: 'media',
- type: 'image',
- class: 'my-image'
- },
- {
- field: 'iconId',
- display: 'media',
- type: 'image'
- },
- {
- tab: 'domains',
- field: 'domains',
- display: 'inputList',
- required: true,
- limit: 10,
- addLabel: '@application.fields.domains_add',
- helpText: '@application.fields.domains_help'
- },
- {
- tab: 'features',
- field: 'features',
- display: 'custom',
- path: '@zero/pages/settings/application-features.vue'
- }
- ]
-};
\ No newline at end of file