new editor; we need it :-/ forgot why
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
import { RouteRecordRaw } from 'vue-router';
|
||||
import { App } from 'vue';
|
||||
import { App, Component } from 'vue';
|
||||
import { ZeroSchemaProp } from '../zero';
|
||||
|
||||
export interface ZeroPluginOptions
|
||||
@@ -10,6 +10,8 @@ export interface ZeroPluginOptions
|
||||
route: (route: RouteRecordRaw) => void;
|
||||
schemas: Record<string, ZeroSchemaProp>;
|
||||
schema: (alias: string, schema: ZeroSchemaProp) => void;
|
||||
fieldTypes: Record<string, Component>;
|
||||
fieldType: (alias: string, component: Component) => void;
|
||||
}
|
||||
|
||||
//export class Zero
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import { App } from 'vue';
|
||||
import { App, Component } from 'vue';
|
||||
import { ZeroInstallOptions } from './types/zeroInstallOptions';
|
||||
import { ZeroPluginOptions } from './types/zeroPluginOptions';
|
||||
import { Zero, ZeroOptions } from './types/zero';
|
||||
@@ -10,6 +10,7 @@ import registerFormComponents from '../forms/register';
|
||||
import registerEditorComponents from '../editor/register';
|
||||
import { getRouterConfig, appendRouterGuards } from './router/routerConfig';
|
||||
import { countryPlugin, applicationPlugin, settingsPlugin, languagePlugin, mediaPlugin, spacePlugin, pagePlugin } from '../modules';
|
||||
import editorPlugin from '../editor/new/plugin';
|
||||
import { ZeroSchema } from 'zero/schemas';
|
||||
import { ZeroSchemaProp } from './zero';
|
||||
import * as zeroOptions from '../options';
|
||||
@@ -20,6 +21,7 @@ export class ZeroRuntime implements Zero
|
||||
_installOptions: ZeroInstallOptions;
|
||||
_routerConfig: RouterOptions;
|
||||
_schemas: Record<string, ZeroSchemaProp> = {};
|
||||
_fieldTypes: Record<string, Component> = {};
|
||||
|
||||
/**
|
||||
* version of zero backoffice
|
||||
@@ -71,17 +73,24 @@ export class ZeroRuntime implements Zero
|
||||
vue: this._app,
|
||||
routes: this._routerConfig.routes,
|
||||
schemas: this._schemas,
|
||||
fieldTypes: this._fieldTypes,
|
||||
route(route: RouteRecordRaw)
|
||||
{
|
||||
this.routes.push(route);
|
||||
},
|
||||
schema(alias: 'string', schema: ZeroSchemaProp)
|
||||
schema(alias: string, schema: ZeroSchemaProp)
|
||||
{
|
||||
this.schemas[alias] = schema;
|
||||
},
|
||||
fieldType(alias: string, component: Component)
|
||||
{
|
||||
this.fieldTypes[alias] = component;
|
||||
}
|
||||
} as ZeroPluginOptions;
|
||||
|
||||
|
||||
// install all plugins
|
||||
editorPlugin.install(pluginOptions);
|
||||
countryPlugin.install(pluginOptions);
|
||||
applicationPlugin.install(pluginOptions);
|
||||
settingsPlugin.install(pluginOptions);
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
declare module 'zero/editor'
|
||||
declare module 'zerox/editor'
|
||||
{
|
||||
export interface FieldSupportsMaxLength
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
<!--<template>
|
||||
<template>
|
||||
<div class="blueprint" v-if="value && (isParent || isChild)">
|
||||
<div class="blueprint-box">
|
||||
<template v-if="isChild">
|
||||
@@ -28,9 +28,7 @@
|
||||
|
||||
|
||||
<script>
|
||||
import Overlay from 'zero/helpers/overlay.js';
|
||||
import SettingsOverlay from './settings.vue';
|
||||
import Localization from 'zero/helpers/localization.js';
|
||||
import * as overlays from '../../services/overlay';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -89,25 +87,28 @@
|
||||
|
||||
methods: {
|
||||
|
||||
openSettings()
|
||||
async openSettings()
|
||||
{
|
||||
const editor = typeof this.editor === 'string' ? this.zero.getEditor(this.editor) : this.editor;
|
||||
const editor = typeof this.editor === 'string' ? this.zero.getSchema(this.editor) : this.editor;
|
||||
|
||||
return Overlay.open({
|
||||
component: SettingsOverlay,
|
||||
const result = await overlays.open({
|
||||
component: () => import('./settings.vue'),
|
||||
display: 'editor',
|
||||
model: this.value,
|
||||
blueprintConfig: this.config
|
||||
}).then(res =>
|
||||
{
|
||||
this.value.blueprint = res.blueprint;
|
||||
this.$emit('input', res.blueprint);
|
||||
if (typeof res.update === 'function')
|
||||
{
|
||||
res.update(this.value);
|
||||
model: {
|
||||
value: this.value,
|
||||
blueprintConfig: this.config
|
||||
}
|
||||
//EventHub.$emit('page.update');
|
||||
});
|
||||
|
||||
console.info(result);
|
||||
return;
|
||||
this.value.blueprint = res.blueprint;
|
||||
this.$emit('input', res.blueprint);
|
||||
if (typeof res.update === 'function')
|
||||
{
|
||||
res.update(this.value);
|
||||
}
|
||||
//EventHub.$emit('page.update');
|
||||
},
|
||||
|
||||
bind()
|
||||
@@ -294,11 +295,11 @@
|
||||
margin-top: -2px;
|
||||
}
|
||||
}
|
||||
</style>-->
|
||||
</style>
|
||||
|
||||
<!--
|
||||
|
||||
<button type="button" class="ui-property-lock" v-if="locked" > <i class="fth-lock" > </i > </button >
|
||||
|
||||
<!--<button type="button" class="ui-property-lock" v-if="locked" > <i class="fth-lock" > </i > </button >
|
||||
/*.ui-property.is-locked
|
||||
{
|
||||
|
||||
@@ -317,6 +318,6 @@
|
||||
position: relative;
|
||||
top: -1px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}-->
|
||||
|
||||
|
||||
-->
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<!--<template>
|
||||
<ui-overlay-editor class="blueprint-settings">
|
||||
<template>
|
||||
<ui-trinity class="blueprint-settings">
|
||||
<template v-slot:header>
|
||||
<ui-header-bar title="Synchronisation" :back-button="false" :close-button="true" />
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<ui-button type="light onbg" label="@ui.close" @click="config.hide" />
|
||||
<ui-button type="light onbg" label="@ui.close" @click="config.close" />
|
||||
<ui-button type="primary" label="@ui.confirm" @click="onSave" :state="state" />
|
||||
</template>
|
||||
|
||||
@@ -14,25 +14,26 @@
|
||||
<ui-property class="blueprint-settings-tableheader" :key="-1" label="Property" :vertical="false">
|
||||
<b>Synchronized</b>
|
||||
</ui-property>
|
||||
<ui-property v-for="(field, index) in items" v-if="!field.disabled" :key="index" :label="field.label" :description="field.description" :vertical="false" :class="{'not-synced': !field.synced}">
|
||||
<ui-toggle v-model="field.synced" />
|
||||
</ui-property>
|
||||
<template v-for="(field, index) in items">
|
||||
<ui-property v-if="!field.disabled" :key="index" :label="field.label" :description="field.description" :vertical="false" :class="{'not-synced': !field.synced}">
|
||||
<ui-toggle v-model:on="field.synced" />
|
||||
</ui-property>
|
||||
</template>
|
||||
</div>
|
||||
</ui-overlay-editor>
|
||||
</ui-trinity>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import Arrays from 'zero/helpers/arrays.js';
|
||||
import Localization from 'zero/helpers/localization.js';
|
||||
import BlueprintApi from 'zero/api/blueprint.js';
|
||||
import { arrayRemove } from '../../utils/arrays';
|
||||
//import Localization from 'zero/helpers/localization.js';
|
||||
//import BlueprintApi from 'zero/api/blueprint.js';
|
||||
|
||||
export default {
|
||||
|
||||
props: {
|
||||
model: Object,
|
||||
config: Object,
|
||||
blueprintConfig: Object
|
||||
config: Object
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
@@ -45,10 +46,10 @@
|
||||
|
||||
mounted()
|
||||
{
|
||||
this.blueprintConfig.fields.forEach(field =>
|
||||
this.model.blueprintConfig.fields.forEach(field =>
|
||||
{
|
||||
let item = JSON.parse(JSON.stringify(field));
|
||||
item.synced = field.synced(this.model);
|
||||
item.synced = field.synced(this.model.value);
|
||||
this.items.push(item);
|
||||
});
|
||||
this.loaded = true;
|
||||
@@ -61,16 +62,16 @@
|
||||
{
|
||||
this.state = 'loading';
|
||||
|
||||
let desync = JSON.parse(JSON.stringify(this.model.blueprint.desync));
|
||||
let desync = JSON.parse(JSON.stringify(this.model.value.blueprint.desync));
|
||||
let resync = [];
|
||||
|
||||
this.items.forEach(field =>
|
||||
{
|
||||
let desynced = this.model.blueprint.desync.indexOf(field.path) > -1;
|
||||
let desynced = this.model.value.blueprint.desync.indexOf(field.path) > -1;
|
||||
|
||||
if (field.synced && desynced)
|
||||
{
|
||||
Arrays.remove(desync, field.path);
|
||||
arrayRemove(desync, field.path);
|
||||
resync.push(field.path);
|
||||
}
|
||||
else if (!field.synced && !desynced)
|
||||
@@ -79,17 +80,17 @@
|
||||
}
|
||||
});
|
||||
|
||||
this.model.blueprint.desync = desync;
|
||||
this.model.value.blueprint.desync = desync;
|
||||
|
||||
// we need to revert changed values which were switch backed to synchronised state
|
||||
// to do this we load the blueprint entity and its copy properties
|
||||
|
||||
if (resync.length > 0)
|
||||
{
|
||||
BlueprintApi.getById(this.model.blueprint.id).then(blueprint =>
|
||||
BlueprintApi.getById(this.model.value.blueprint.id).then(blueprint =>
|
||||
{
|
||||
this.config.confirm({
|
||||
blueprint: this.model.blueprint,
|
||||
blueprint: this.model.value.blueprint,
|
||||
update: entity =>
|
||||
{
|
||||
resync.forEach(path =>
|
||||
@@ -104,7 +105,7 @@
|
||||
{
|
||||
//this.state = 'success';
|
||||
this.config.confirm({
|
||||
blueprint: this.model.blueprint
|
||||
blueprint: this.model.value.blueprint
|
||||
});
|
||||
}
|
||||
|
||||
@@ -220,4 +221,4 @@
|
||||
color: var(--color-primary);
|
||||
font-weight: 400;
|
||||
}*/
|
||||
</style>-->
|
||||
</style>
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import { localize } from '../services/localization';
|
||||
import { arrayRemove } from '../utils/arrays';
|
||||
import { useUiStore } from '../ui/store';
|
||||
|
||||
function unlocked(config, model, field)
|
||||
{
|
||||
@@ -78,10 +79,11 @@ function unlock(config, model, field)
|
||||
*/
|
||||
export function createBlueprintConfig(zero, editor, model)
|
||||
{
|
||||
const store = useUiStore();
|
||||
let blueprintAlias = editor.blueprintAlias;
|
||||
let config = zero.config.blueprints.find(x => x.alias == blueprintAlias);
|
||||
let canBeBlueprinted = store.blueprints.indexOf(blueprintAlias) > -1;
|
||||
|
||||
if (!blueprintAlias || !config)
|
||||
if (!blueprintAlias || !canBeBlueprinted)
|
||||
{
|
||||
return {
|
||||
alias: blueprintAlias,
|
||||
@@ -89,13 +91,15 @@ export function createBlueprintConfig(zero, editor, model)
|
||||
canUnlock: () => false,
|
||||
isBlueprintParent: () => false,
|
||||
isBlueprintChild: () => false,
|
||||
lock: () => {},
|
||||
unlock: () => {},
|
||||
lock: () => { },
|
||||
unlock: () => { },
|
||||
fields: []
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
let config = {
|
||||
unlocked: []
|
||||
}
|
||||
|
||||
// check for blueprint availability
|
||||
//config.isParent = this.value && this.$route.query.scope === 'shared';
|
||||
@@ -112,15 +116,15 @@ export function createBlueprintConfig(zero, editor, model)
|
||||
{
|
||||
processed.push(alias);
|
||||
|
||||
if (config.unlocked.indexOf(alias) > -1)
|
||||
{
|
||||
//if (config.unlocked.indexOf(alias) > -1)
|
||||
//{
|
||||
fields.push({
|
||||
path: alias,
|
||||
label: localize("@ui.entityfields." + alias),
|
||||
description: localize("@ui.entityfields." + alias + "_text", { hideEmpty: true }),
|
||||
synced: model => !model.blueprint || model.blueprint.desync.indexOf(alias) < 0
|
||||
});
|
||||
}
|
||||
//}
|
||||
});
|
||||
|
||||
// add blueprint setting for custom fields
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
export interface EditorFieldMeta
|
||||
{
|
||||
canEdit: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface EditorFieldProps<T>
|
||||
{
|
||||
value: T;
|
||||
model: any;
|
||||
meta: EditorFieldMeta;
|
||||
disabled: boolean;
|
||||
system: boolean;
|
||||
}
|
||||
@@ -165,6 +165,31 @@ class EditorField
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a preview for this field
|
||||
* This is only used in list filters, ...
|
||||
* @param {object} options - Custom options
|
||||
* @param {string} options.icon - Custom icon
|
||||
* @param {string|function} options.preview - Render the preview when this filter has been filled out
|
||||
* @param {boolean} options.hasValue - Determine if the filter has a value or not
|
||||
* @returns {EditorField}
|
||||
*/
|
||||
preview(options)
|
||||
{
|
||||
this._preview = { ...this.preview, ...options };
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render a custom component
|
||||
* @param {object} component - The custom vue component
|
||||
@@ -580,22 +605,6 @@ class EditorField
|
||||
{
|
||||
return this._setComponent(() => import('./fields/video.vue'), { limit });
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a preview for this field
|
||||
* This is only used in list filters, ...
|
||||
* @param {object} options - Custom options
|
||||
* @param {string} options.icon - Custom icon
|
||||
* @param {string|function} options.preview - Render the preview when this filter has been filled out
|
||||
* @param {boolean} options.hasValue - Determine if the filter has a value or not
|
||||
* @returns {EditorField}
|
||||
*/
|
||||
preview(options)
|
||||
{
|
||||
this._preview = { ...this.preview, ...options };
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ class Editor
|
||||
};
|
||||
|
||||
|
||||
constructor(alias, prefix)
|
||||
constructor(prefix)
|
||||
{
|
||||
this._alias = alias;
|
||||
this._alias = null;
|
||||
this._prefix = prefix || '';
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<ui-tab v-for="(tab, index) in tabs" class="ui-box" :class="tab.class" :data-alias="tab.alias" :label="tab.name" :count="tab.count(value)" :hidden="tab.disabled(value)" :key="index">
|
||||
<h3 v-if="display == 'boxes' && tab.name" class="ui-headline editor-tab-headline" v-localize="tab.name"></h3>
|
||||
<slot name="blueprint">
|
||||
<!--<blueprint-property v-if="value && editorConfig.blueprint" :model-value="value" :meta="meta" :config="editorConfig.blueprint" />-->
|
||||
<blueprint-property v-if="value && editorConfig.blueprint" :value="value" :meta="meta" :config="editorConfig.blueprint" />
|
||||
</slot>
|
||||
<div class="ui-property ui-property-parent" v-for="fieldset in tab.fieldsets">
|
||||
<editor-component v-for="(field, fieldIndex) in fieldset.fields" :disabled="disabled" :key="fieldIndex" :config="field" @input="onChange" :editor="editorConfig" :value="value"
|
||||
@@ -97,7 +97,7 @@
|
||||
async created()
|
||||
{
|
||||
this.editorConfig = typeof this.config === 'string' ? await this.zero.getSchema(this.config) : this.config;
|
||||
this.editorConfig.blueprint = null; //createBlueprintConfig(this.zero, this.editorConfig, this.value);
|
||||
this.editorConfig.blueprint = createBlueprintConfig(this.zero, this.editorConfig, this.value);
|
||||
|
||||
this.tabs = this.editorConfig.tabs.map(tab =>
|
||||
{
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import { Component } from "vue";
|
||||
|
||||
declare module 'zero/editor'
|
||||
{
|
||||
export interface EditorFieldConfiguration
|
||||
{
|
||||
/**
|
||||
* Whether this field is required (additional validation is done on the server)
|
||||
*/
|
||||
required?: Function | boolean;
|
||||
/**
|
||||
* Whether this field is readonly and can't be changed
|
||||
*/
|
||||
readonly?: Function | boolean;
|
||||
/**
|
||||
* Conditionally hide the field
|
||||
*/
|
||||
hidden?: Function | boolean;
|
||||
/**
|
||||
* A custom label for this field (otherwise it's generated via `onLabelCreate`)
|
||||
**/
|
||||
label?: string | null,
|
||||
/**
|
||||
* Hide the field label
|
||||
**/
|
||||
hideLabel?: boolean,
|
||||
/**
|
||||
* A custom description for this field (otherwise it's generated via `onDescriptionCreate`)
|
||||
**/
|
||||
description?: string | null,
|
||||
/**
|
||||
* Display a help text below the field
|
||||
**/
|
||||
helpText?: string | null,
|
||||
/**
|
||||
* Append HTML class to the generated property
|
||||
**/
|
||||
classes?: string | null,
|
||||
/**
|
||||
* Whether to render the label next to the input
|
||||
**/
|
||||
horizontal?: boolean
|
||||
}
|
||||
|
||||
|
||||
export interface EditorFieldDefinition<T>
|
||||
{
|
||||
component: Component;
|
||||
options?: T;
|
||||
// return this._setComponent(() => import('./fields/text.vue'), { maxLength, placeholder });
|
||||
//this._component = component;
|
||||
//this._componentOptions = options || {};
|
||||
}
|
||||
|
||||
|
||||
export interface EditorField
|
||||
{
|
||||
/**
|
||||
* Set this field as required
|
||||
* @param {function|boolean} [condition] - Optionally only require this field when a condition is fulfilled or reset the required state with true/false
|
||||
*/
|
||||
setRequired(condition: Function | boolean): EditorField;
|
||||
|
||||
/**
|
||||
* Whether the input next to the headline or below
|
||||
* @param {boolean} isHorizontal
|
||||
* @returns {EditorField}
|
||||
*/
|
||||
setHorizontal(isHorizontal: boolean): EditorField;
|
||||
|
||||
/**
|
||||
* Set this field to disabled
|
||||
*/
|
||||
setReadonly(condition: Function | boolean): EditorField;
|
||||
|
||||
/**
|
||||
* Conditionally hide this field
|
||||
* @param {function} condition - function which returns a boolean and gets passed the current model
|
||||
*/
|
||||
setHidden(condition: Function | boolean): EditorField;
|
||||
|
||||
/**
|
||||
* Set a custom component for a field
|
||||
* @param {Component} component - The component to render (can be an async component too)
|
||||
* @param {T} [options] = Custom options to pass to this editor
|
||||
*/
|
||||
custom<T>(component: Component, options?: T): EditorField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { EditorField, EditorFieldConfiguration } from "zero/editor";
|
||||
import { EditorFieldBase, createFieldProxy } from "./editorField";
|
||||
|
||||
|
||||
export class Editor
|
||||
{
|
||||
fields: EditorField[];
|
||||
|
||||
constructor()
|
||||
{
|
||||
this.fields = [];
|
||||
}
|
||||
|
||||
field(alias: string, config?: EditorFieldConfiguration): EditorField
|
||||
{
|
||||
const field = new EditorFieldBase(alias, config);
|
||||
const proxy = createFieldProxy(field);
|
||||
this.fields.push(proxy);
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
|
||||
import { Component, defineAsyncComponent } from 'vue';
|
||||
import { EditorField, EditorFieldConfiguration, TextFieldOptions, EditorFieldDefinition } from 'zero/editor';
|
||||
|
||||
export const fieldTypes: Record<string, Function> = {};
|
||||
|
||||
|
||||
fieldTypes.text = function (options?: TextFieldOptions)
|
||||
{
|
||||
return field.custom(defineAsyncComponent(() => import('./fields/text.vue')), options);
|
||||
};
|
||||
|
||||
|
||||
export const createFieldProxy = (field: EditorFieldBase) => new Proxy(field, {
|
||||
get: function (target: EditorFieldBase, prop: string | symbol, receiver: any): any
|
||||
{
|
||||
// handle internals
|
||||
if (prop in target)
|
||||
{
|
||||
return target[prop];
|
||||
}
|
||||
|
||||
// handle dynamic fields + extensions
|
||||
if (fieldTypes[prop])
|
||||
{
|
||||
const fieldDefinition = fieldTypes[prop];
|
||||
console.info({ target, prop, receiver });
|
||||
//return fieldDefinition()
|
||||
return
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
})// as EditorField;
|
||||
|
||||
|
||||
export function createFieldConfiguration(): EditorFieldConfiguration
|
||||
{
|
||||
return {
|
||||
required: false,
|
||||
readonly: false,
|
||||
hidden: false,
|
||||
label: null,
|
||||
hideLabel: false,
|
||||
description: null,
|
||||
helpText: null,
|
||||
classes: null,
|
||||
horizontal: false
|
||||
} as EditorFieldConfiguration;
|
||||
}
|
||||
|
||||
|
||||
export class EditorFieldBase
|
||||
{
|
||||
alias: string;
|
||||
configuration: EditorFieldConfiguration;
|
||||
component?: Component;
|
||||
options?: any;
|
||||
|
||||
constructor(alias: string, config?: EditorFieldConfiguration)
|
||||
{
|
||||
this.alias = alias;
|
||||
this.configuration = config || createFieldConfiguration();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set this field as required
|
||||
* @param {function|boolean} [condition] - Optionally only require this field when a condition is fulfilled or reset the required state with true/false
|
||||
*/
|
||||
setRequired(condition: Function | boolean): EditorField
|
||||
{
|
||||
this.configuration.required = condition;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the input next to the headline or below
|
||||
* @param {boolean} isHorizontal
|
||||
* @returns {EditorField}
|
||||
*/
|
||||
setHorizontal(isHorizontal: boolean): EditorField
|
||||
{
|
||||
this.configuration.horizontal = !isHorizontal;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set this field to disabled
|
||||
*/
|
||||
setReadonly(condition: Function | boolean): EditorField
|
||||
{
|
||||
this.configuration.readonly = condition;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Conditionally hide this field
|
||||
* @param {function} condition - function which returns a boolean and gets passed the current model
|
||||
*/
|
||||
setHidden(condition: Function | boolean): EditorField
|
||||
{
|
||||
this.configuration.hidden = condition;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a custom component for a field
|
||||
* @param {Component} component - The component to render (can be an async component too)
|
||||
* @param {T} [options] = Custom options to pass to this editor
|
||||
*/
|
||||
custom<T>(component: Component, options?: T): EditorField
|
||||
{
|
||||
this.component = component;
|
||||
this.options = options;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
|
||||
declare module 'zero/editor'
|
||||
{
|
||||
export interface FieldSupportsMaxLength
|
||||
{
|
||||
maxLength?: number;
|
||||
}
|
||||
|
||||
|
||||
export interface FieldSupportsPlaceholder
|
||||
{
|
||||
placeholder?: string | null;
|
||||
}
|
||||
|
||||
|
||||
export type TextFieldOptions = FieldSupportsMaxLength | FieldSupportsPlaceholder;
|
||||
export type NumberFieldOptions = FieldSupportsMaxLength | FieldSupportsPlaceholder;
|
||||
|
||||
|
||||
export interface EditorField
|
||||
{
|
||||
/**
|
||||
* Set this field as required
|
||||
* @param {function|boolean} [condition] - Optionally only require this field when a condition is fulfilled or reset the required state with true/false
|
||||
*/
|
||||
text(options?: TextFieldOptions): EditorField;
|
||||
|
||||
/**
|
||||
* Set this field as required
|
||||
* @param {function|boolean} [condition] - Optionally only require this field when a condition is fulfilled or reset the required state with true/false
|
||||
*/
|
||||
number(options?: NumberFieldOptions): EditorField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<input :value="value" @input="$emit('input', $event.target.value)" type="text" class="ui-input" v-placeholder="{ placeholder: options.placeholder, model: entity }" :maxlength="options.maxLength" :disabled="disabled" />
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import { TextFieldOptions } from 'zero/editor';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
maxLength: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
placeholder: {
|
||||
type: [String, Function],
|
||||
default: null
|
||||
},
|
||||
entity: Object,
|
||||
options: Object as PropType<TextFieldOptions>
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,11 @@
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import { ZeroPlugin, ZeroPluginOptions } from '../../core';
|
||||
|
||||
export default {
|
||||
name: "zero.editor",
|
||||
|
||||
install(app: ZeroPluginOptions)
|
||||
{
|
||||
app.fieldType('text', defineAsyncComponent(() => import('./fields/text.vue')));
|
||||
}
|
||||
} as ZeroPlugin;
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
import { defineStore } from 'pinia';
|
||||
import { Component } from 'vue';
|
||||
|
||||
export type EditorState = {
|
||||
fieldTypes: Record<string, Component>
|
||||
};
|
||||
|
||||
export const useEditorStore = defineStore('zero.editor', {
|
||||
state: () => ({
|
||||
fieldTypes: {}
|
||||
} as EditorState),
|
||||
|
||||
actions: {
|
||||
|
||||
}
|
||||
});
|
||||
@@ -1,12 +1,20 @@
|
||||
|
||||
import Editor from '../../../editor/editor';
|
||||
import { Editor } from '../../../editor/new/editor';
|
||||
|
||||
const editor = new Editor('countries:edit', '@country.fields.');
|
||||
editor.blueprintAlias = 'country';
|
||||
const editor = new Editor(); //'@country.fields.');
|
||||
|
||||
editor.field('name', { label: '@ui.name' }).text(120).required();
|
||||
//editor.field('alias', { label: '@ui.alias' }).text().required();
|
||||
editor.field('code').text(2).required();
|
||||
editor.field('isPreferred').toggle();
|
||||
editor.field('name').setRequired(true).text({ maxLength: 80 });
|
||||
|
||||
export default editor;
|
||||
export default editor;
|
||||
|
||||
//import Editor from '../../../editor/editor';
|
||||
|
||||
//const editor = new Editor('@country.fields.');
|
||||
//editor.blueprintAlias = 'countries';
|
||||
|
||||
//editor.field('name', { label: '@ui.name' }).text(120).required();
|
||||
////editor.field('alias', { label: '@ui.alias' }).text().required();
|
||||
//editor.field('code').text(2).required();
|
||||
//editor.field('isPreferred').toggle();
|
||||
|
||||
//export default editor;
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ZeroPlugin, ZeroPluginOptions } from '../../core';
|
||||
import { TextFieldOptions } from 'zero/editor';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
import Editor from '../../../editor/editor';
|
||||
|
||||
const editor = new Editor('languages:edit', '@language.fields.');
|
||||
editor.blueprintAlias = 'language';
|
||||
const editor = new Editor('@language.fields.');
|
||||
editor.blueprintAlias = 'languages';
|
||||
editor.field('name', { label: '@ui.name' }).text(60).required();
|
||||
editor.field('code').text(10).required();
|
||||
editor.field('inheritedLanguageId').languagePicker();
|
||||
|
||||
@@ -37,6 +37,7 @@ builder.Services.Configure<FlavorOptions>(opts =>
|
||||
builder.Services.Configure<BlueprintOptions>(opts =>
|
||||
{
|
||||
opts.Add<Country>();
|
||||
opts.Add<Language>();
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
Reference in New Issue
Block a user