2021-12-23 13:47:34 +01:00
|
|
|
import { Component } from "vue";
|
|
|
|
|
import { ZeroEditorField } from "zero/schemas";
|
2021-12-21 13:58:48 +01:00
|
|
|
import { extendObject } from '../utils/objects';
|
2021-12-21 00:53:17 +01:00
|
|
|
|
|
|
|
|
export declare type BooleanExpression = (model: any, value: any) => boolean;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const createFieldProxy = (field: ZeroEditorFieldImpl) => new Proxy(field, {
|
|
|
|
|
get: function (target: ZeroEditorFieldImpl, prop: string | symbol, receiver: any): any
|
|
|
|
|
{
|
|
|
|
|
// handle internals
|
|
|
|
|
if (prop in target)
|
2021-12-23 13:47:34 +01:00
|
|
|
{
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
return target[prop];
|
2021-12-21 00:53:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// handle dynamic fields + extensions
|
2021-12-23 13:47:34 +01:00
|
|
|
return (args: any) =>
|
2021-12-21 00:53:17 +01:00
|
|
|
{
|
2021-12-23 13:47:34 +01:00
|
|
|
target.fieldType = prop;
|
|
|
|
|
target.options = args;
|
2021-12-21 00:53:17 +01:00
|
|
|
return target;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
})// as EditorField;
|
|
|
|
|
|
|
|
|
|
|
2021-12-21 13:58:48 +01:00
|
|
|
// @ts-ignore
|
2021-12-21 00:53:17 +01:00
|
|
|
export class ZeroEditorFieldImpl implements ZeroEditorField
|
|
|
|
|
{
|
|
|
|
|
path: string;
|
|
|
|
|
configuration: ZeroEditorFieldConfiguration;
|
2021-12-23 13:47:34 +01:00
|
|
|
fieldType: string | symbol;
|
2021-12-21 00:53:17 +01:00
|
|
|
options?: any;
|
2021-12-23 13:47:34 +01:00
|
|
|
customComponent?: Component;
|
2021-12-21 00:53:17 +01:00
|
|
|
|
|
|
|
|
constructor(path: string, config?: ZeroEditorFieldConfiguration)
|
|
|
|
|
{
|
|
|
|
|
this.path = path;
|
2021-12-21 13:58:48 +01:00
|
|
|
this.configuration = extendObject(createDefaultFieldConfiguration(), config || {}) as ZeroEditorFieldConfiguration;
|
2021-12-21 00:53:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set this field as optional
|
|
|
|
|
* @param {function|boolean} [condition] - Optionally only require this field when a condition is fulfilled or reset the required state with true/false
|
|
|
|
|
*/
|
|
|
|
|
setOptional(condition: Function | boolean): ZeroEditorField
|
|
|
|
|
{
|
|
|
|
|
this.configuration.optional = condition;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Whether the input next to the headline or below
|
|
|
|
|
* @param {boolean} isHorizontal
|
|
|
|
|
* @returns {EditorField}
|
|
|
|
|
*/
|
|
|
|
|
setHorizontal(isHorizontal: boolean): ZeroEditorField
|
|
|
|
|
{
|
|
|
|
|
this.configuration.horizontal = !isHorizontal;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set this field to disabled
|
|
|
|
|
*/
|
|
|
|
|
setReadonly(condition: Function | boolean): ZeroEditorField
|
|
|
|
|
{
|
|
|
|
|
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): ZeroEditorField
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
*/
|
2021-12-23 13:47:34 +01:00
|
|
|
component(component: Component, options?: any): ZeroEditorField
|
2021-12-21 00:53:17 +01:00
|
|
|
{
|
2021-12-23 13:47:34 +01:00
|
|
|
this.customComponent = component;
|
2021-12-21 00:53:17 +01:00
|
|
|
this.options = options;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
2022-01-10 16:13:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The expression argument is called when the value of the field changes
|
|
|
|
|
* @param {function} callback - function which is called
|
|
|
|
|
*/
|
|
|
|
|
onChange(callback: Function): ZeroEditorField
|
|
|
|
|
{
|
|
|
|
|
this.configuration.changeHandlers.push(callback);
|
|
|
|
|
return this;
|
|
|
|
|
}
|
2021-12-21 00:53:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function createDefaultFieldConfiguration(): ZeroEditorFieldConfiguration
|
|
|
|
|
{
|
|
|
|
|
return {
|
|
|
|
|
optional: false,
|
|
|
|
|
readonly: false,
|
|
|
|
|
hidden: false,
|
|
|
|
|
label: null,
|
|
|
|
|
hideLabel: false,
|
|
|
|
|
description: null,
|
|
|
|
|
helpText: null,
|
|
|
|
|
classes: null,
|
2021-12-21 13:58:48 +01:00
|
|
|
horizontal: false,
|
2021-12-30 17:09:25 +01:00
|
|
|
sort: 0,
|
2022-01-10 16:13:59 +01:00
|
|
|
preview: undefined,
|
|
|
|
|
changeHandlers: []
|
2021-12-21 00:53:17 +01:00
|
|
|
} as ZeroEditorFieldConfiguration;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export interface ZeroEditorFieldConfiguration
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* Whether this field is optional or required (additional validation is done on the server)
|
|
|
|
|
*/
|
|
|
|
|
optional?: 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
|
|
|
|
|
**/
|
2021-12-21 13:58:48 +01:00
|
|
|
horizontal?: boolean,
|
|
|
|
|
/**
|
|
|
|
|
* Sort order for fields within the editor canvas
|
|
|
|
|
**/
|
2021-12-30 17:09:25 +01:00
|
|
|
sort?: number,
|
|
|
|
|
/**
|
|
|
|
|
* Sort order for fields within the editor canvas
|
|
|
|
|
**/
|
2022-01-10 16:13:59 +01:00
|
|
|
preview?: ZeroEditorFieldFilterPreview,
|
|
|
|
|
/**
|
|
|
|
|
* Handlers which get called on value change
|
|
|
|
|
**/
|
|
|
|
|
changeHandlers?: Array<Function>
|
2021-12-30 17:09:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export interface ZeroEditorFieldFilterPreview
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* Icon which is displayed next to the filter option
|
|
|
|
|
*/
|
|
|
|
|
icon?: string;
|
|
|
|
|
/**
|
|
|
|
|
* Checks whether the selected value for the filter option is valid and if it should be marked as selected
|
|
|
|
|
*/
|
|
|
|
|
selected?: (value: any, model: any) => boolean;
|
|
|
|
|
/**
|
|
|
|
|
* Renders the filter value which is previewed
|
|
|
|
|
*/
|
|
|
|
|
value?: (value: any, model: any) => string;
|
2021-12-21 00:53:17 +01:00
|
|
|
}
|