602 lines
17 KiB
TypeScript
602 lines
17 KiB
TypeScript
|
|
class EditorField
|
|
{
|
|
path = null;
|
|
|
|
options = {
|
|
label: null,
|
|
hideLabel: false,
|
|
description: null,
|
|
helpText: null,
|
|
condition: null,
|
|
disabled: false,
|
|
tab: null,
|
|
allTabs: false,
|
|
vertical: true,
|
|
coreDatabase: false,
|
|
fieldset: null,
|
|
fieldsetColumns: null,
|
|
class: '',
|
|
onChange: null
|
|
};
|
|
|
|
_preview = {
|
|
icon: 'fth-filter',
|
|
preview: x => x,
|
|
hasValue: x => !!x
|
|
};
|
|
|
|
_component = null;
|
|
_componentOptions = {};
|
|
_required = false;
|
|
_isReadOnly = false;
|
|
|
|
constructor(path, options)
|
|
{
|
|
this.path = path;
|
|
this.options = { ...this.options, ...options };
|
|
}
|
|
|
|
|
|
get component()
|
|
{
|
|
return this._component;
|
|
}
|
|
|
|
get componentOptions()
|
|
{
|
|
return this._componentOptions;
|
|
}
|
|
|
|
get isRequired()
|
|
{
|
|
return this._required;
|
|
}
|
|
|
|
get previewOptions()
|
|
{
|
|
return this._preview;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set another editor field as the base for this editor (copies properties)
|
|
* @param {EditorField} field - Base editor field
|
|
* @returns {EditorField}
|
|
*/
|
|
setBase(field)
|
|
{
|
|
this.path = field.path;
|
|
this.options = { ...field.options };
|
|
this._preview = { ...field.previewOptions };
|
|
this._component = field.component;
|
|
this._componentOptions = field.componentOptions;
|
|
this._required = field.isRequired;
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
_setComponent(component, options?)
|
|
{
|
|
this._component = component;
|
|
this._componentOptions = options || {};
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets the column count for this field, only available within a an editor fieldset
|
|
* @param {number} columnCount - Column count between 1 and 12
|
|
* @returns {EditorField}
|
|
*/
|
|
cols(columnCount)
|
|
{
|
|
this.options.fieldsetColumns = columnCount < 1 ? 1 : (columnCount > 12 ? 12 : columnCount);
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Whether the input is below the headline or next to it
|
|
* @param {boolean} isVertical
|
|
* @returns {EditorField}
|
|
*/
|
|
vertical(isVertical)
|
|
{
|
|
this.options.vertical = isVertical;
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set this field to disabled
|
|
*/
|
|
disabled()
|
|
{
|
|
this.options.disabled = true;
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
required(condition)
|
|
{
|
|
if (typeof condition === 'function')
|
|
{
|
|
this._required = condition;
|
|
}
|
|
else if (typeof condition === 'boolean')
|
|
{
|
|
this._required = condition;
|
|
}
|
|
else
|
|
{
|
|
this._required = true;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Conditionally render this field (this is an alternative method to the field options 'condition')
|
|
* @param {function} condition - function which returns a boolean and gets passed the current model
|
|
*/
|
|
when(condition)
|
|
{
|
|
this.options.condition = condition;
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* The expression argument is called when the value of the field changes
|
|
* @param {function} expression - function which is called
|
|
*/
|
|
onChange(expression)
|
|
{
|
|
this.options.onChange = expression;
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a custom component
|
|
* @param {object} component - The custom vue component
|
|
* @param {object} [options] - Custom options
|
|
* @returns {EditorField}
|
|
*/
|
|
custom(component, options)
|
|
{
|
|
return this._setComponent(component, { ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a text input field
|
|
* @param {number} [maxLength] - Maximum length of the input
|
|
* @param {string|function} [placeholder] - Placeholder text (can be a translation) or function
|
|
* @returns {EditorField}
|
|
*/
|
|
text(maxLength, placeholder)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/text.vue'), { maxLength, placeholder });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a password input field
|
|
* @param {number} [maxLength] - Maximum length of the input
|
|
* @param {string|function} [placeholder] - Placeholder text (can be a translation) or function
|
|
* @returns {EditorField}
|
|
*/
|
|
password(maxLength, placeholder)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/password.vue'), { maxLength, placeholder });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a password hash field
|
|
* @param {number} [maxLength] - Maximum length of the password
|
|
* @returns {EditorField}
|
|
*/
|
|
passwordHash(maxLength)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/password-hash.vue'), { maxLength });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a currency input field
|
|
* @param {string|function} [placeholder] - Placeholder text (can be a translation) or function
|
|
* @returns {EditorField}
|
|
*/
|
|
currency(placeholder)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/currency.vue'), { placeholder });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a number input field
|
|
* @param {number} [maxLength] - Maximum length of the input
|
|
* @param {string|function} [placeholder] - Placeholder text (can be a translation) or function
|
|
* @returns {EditorField}
|
|
*/
|
|
number(maxLength, placeholder)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/number.vue'), { maxLength, placeholder });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a rich-text editor field
|
|
* @param {object} [options] - Custom options
|
|
* @param {number} [options.maxLength=null] - Maximum characters
|
|
* @param {string} [options.placeholder=null] - Placeholder text (can be a translation) or function
|
|
* @param {function} [options.setup=value] - Called on RTE setup
|
|
* @returns {EditorField}
|
|
*/
|
|
rte(options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/rte.vue'), { ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* @typedef {object} EditorSelectItem
|
|
* @param {object} key - Key/Id of the item
|
|
* @param {string} value - Label/Value of the item (can be a translation)
|
|
*/
|
|
|
|
/**
|
|
* Render a select dropdown with the specified items
|
|
* @param {EditorSelectItem[]|function} items - Set items to pick from
|
|
* @param {object} [options] - Custom options
|
|
* @param {number} [options.emptyOption=false] - Adds an empty option so the field can be blank
|
|
* @returns {EditorField}
|
|
*/
|
|
select(items, options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/select.vue'), { items, ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a text area
|
|
* @param {number} [maxLength] - Maximum length of the input
|
|
* @returns {EditorField}
|
|
*/
|
|
textarea(maxLength)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/textarea.vue'), { maxLength });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a toggle
|
|
* @param {boolean} [negative] - Toggle with a negative color / red background
|
|
* @param {object} [options] - Custom options
|
|
* @param {number} [options.negative=false] - Display the toggle in red when set to TRUE
|
|
* @param {number} [options.onContent=null] - Text next to toggle when it is set to TRUE
|
|
* @param {number} [options.offContent=null] - Text next to toggle when it is set to FALSE
|
|
* @returns {EditorField}
|
|
*/
|
|
toggle(options)
|
|
{
|
|
this.options.vertical = false;
|
|
return this._setComponent(() => import('../editor/fields/toggle.vue'), { ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders the field value
|
|
* @param {function} [render] - Render the output based on the given function
|
|
* @returns {EditorField}
|
|
*/
|
|
output(render)
|
|
{
|
|
this._isReadOnly = true;
|
|
return this._setComponent(() => import('../editor/fields/output.vue'), { render });
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders an input which generates an alias for a given name or an alternative custom alias
|
|
* @param {string} [namePath] - Optional path to the name value which is used to auto-generate the alias
|
|
* @returns {EditorField}
|
|
*/
|
|
alias(namePath)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/alias.vue'), { namePath });
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders an input which generates an alias for a given name or an alternative custom alias
|
|
* @param {EditorSelectItem[]|function} items - Set items to choose from, either via an array or a promise which returns such array
|
|
* @param {object} [options] - Custom options
|
|
* @param {number} [options.limit=100] - Maximum items to be checked
|
|
* @param {boolean} [options.reverse=false] - Reverse the checklist behaviour, so all items are checked by default and unchecking them adds them to the result list
|
|
* @param {string} [options.labelKey=value] - Object key to get the label
|
|
* @param {string} [options.idKey=key] - Object key to get the id
|
|
* @returns {EditorField}
|
|
*/
|
|
checkList(items, options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/checklist.vue'), { items, ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders a HEX color picker
|
|
* @returns {EditorField}
|
|
*/
|
|
colorPicker()
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/colorpicker.vue'));
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders a country picker
|
|
* @param {number} [limit=1] - Maximum items to be selected
|
|
* @returns {EditorField}
|
|
*/
|
|
countryPicker(limit)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/countrypicker.vue'), { limit });
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders a space picker
|
|
* @param {number} [limit=1] - Maximum items to be selected
|
|
* @returns {EditorField}
|
|
*/
|
|
spacePicker(limit)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/spacepicker.vue'), { limit });
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders a culture picker
|
|
* @returns {EditorField}
|
|
*/
|
|
culturePicker()
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/culturepicker.vue'));
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders a mail template picker
|
|
* @param {number} [limit=1] - Maximum items to be selected
|
|
* @returns {EditorField}
|
|
*/
|
|
mailTemplatePicker(limit)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/mailtemplatepicker.vue'), { limit });
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders a date picker
|
|
* @param {object} [options] - Custom options
|
|
* @param {string} [options.format] - Format the date output
|
|
* @param {boolean} [options.time=false] - Allow time input
|
|
* @param {string|Date} [options.maxDate] - Maximum selectable date
|
|
* @param {string|Date} [options.minDate] - Minimum selectable date
|
|
* @param {string} [options.amPm] - Render time as AM/PM
|
|
* @returns {EditorField}
|
|
*/
|
|
datePicker(options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/datepicker.vue'), { ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders a date range picker
|
|
* @param {object} [options] - Custom options
|
|
* @param {string} [options.format] - Format the date output
|
|
* @param {boolean} [options.time=false] - Allow time input
|
|
* @param {string|Date} [options.maxDate] - Maximum selectable date
|
|
* @param {string|Date} [options.minDate] - Minimum selectable date
|
|
* @param {string} [options.fromLabel] - Label next to the "from" date input
|
|
* @param {string} [options.toLabel] - Label next to the "to" date input
|
|
* @param {string} [options.amPm] - Render time as AM/PM
|
|
* @param {string} [options.inline] - Don't render the range picker on an overlay
|
|
* @returns {EditorField}
|
|
*/
|
|
dateRangePicker(options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/daterangepicker.vue'), { ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Pick an icon from the specified icon collection
|
|
* @param {string} [iconSetAlias] - Custom icon set alias (defined in ZeroOptions.Icons)
|
|
* @returns {EditorField}
|
|
*/
|
|
iconPicker(iconSetAlias)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/iconPicker.vue'), { set: iconSetAlias });
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders a page picker
|
|
* @param {object} [options] - Custom options
|
|
* @param {number} [options.limit=1] - Limit of selection
|
|
* @returns {EditorField}
|
|
*/
|
|
pagePicker(options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/pagepicker.vue'), { ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a link picker
|
|
* @param {object} [options] - Custom options
|
|
* @param {number} [options.limit=1] - Limit of selection
|
|
* @param {boolean} [options.title=true] - Allow input of custom link title
|
|
* @param {boolean} [options.target=true] - Allow selection of the link target
|
|
* @param {boolean} [options.label=false] - Allow input of a custom label for button generation
|
|
* @param {boolean} [options.suffix=false] - Allow input of custom link URL suffix (query or hash)
|
|
* @param {string[]} [options.areas] - Limit link areas to the specified values (built-in are zero.pages, zero.media and zero.url)
|
|
* @returns {EditorField}
|
|
*/
|
|
linkPicker(options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/linkpicker.vue'), { ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Create a list of strings
|
|
* @param {number} [limit=10] - Limit the inputs
|
|
* @param {number} [maxItemLength=200] - Maximum length for an item input
|
|
* @param {string} [addLabel] - Label for the add button
|
|
* @returns {EditorField}
|
|
*/
|
|
inputList(limit, maxItemLength, addLabel)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/inputlist.vue'), { limit, maxItemLength, addLabel });
|
|
}
|
|
|
|
|
|
/**
|
|
* Append tags to an entity
|
|
* @param {number} [limit=10] - Limit the tags
|
|
* @param {number} [maxItemLength=200] - Maximum length for a tag
|
|
* @returns {EditorField}
|
|
*/
|
|
tags(limit, maxItemLength)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/tags.vue'), { limit, maxItemLength });
|
|
}
|
|
|
|
|
|
/**
|
|
* Pick a language
|
|
* @returns {EditorField}
|
|
*/
|
|
languagePicker()
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/language.vue'));
|
|
}
|
|
|
|
|
|
/**
|
|
* Display a module renderer which allows you to select from defined modules
|
|
* @param {string[]} [tags] - Only allow selection of modules which match defined tags
|
|
* @returns {EditorField}
|
|
*/
|
|
modules(tags)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/modules.vue'), { tags });
|
|
}
|
|
|
|
|
|
/**
|
|
* Display a module renderer which allows you to select from defined modules
|
|
* @param {Editor} [editor] - Use the specified editor for each item
|
|
* @param {object} [options] - Custom options
|
|
* @param {number} [options.limit=100] - Limit the creation of items
|
|
* @param {string} [options.title] - Headline in the editor overlay
|
|
* @param {string} [options.addLabel] - Label for the add button
|
|
* @param {function} [options.itemLabel] - Function which generates the label for the current item
|
|
* @param {function} [options.itemDescription] - Function which generates the description for the current item
|
|
* @param {string|function} [options.itemIcon] - Static icon or function which generates the icon for the current item
|
|
* @param {object} [options.template] - Template which is used when adding an item
|
|
* @param {object} [options.width=820] - Width of the overlay panel
|
|
* @returns {EditorField}
|
|
*/
|
|
nested(editor, options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/nested.vue'), { editor, ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a select as a button group
|
|
* @param {EditorSelectItem[]} items - Set items to choose from
|
|
* @returns {EditorField}
|
|
*/
|
|
state(items)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/state.vue'), { items });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a media upload + picker
|
|
* @param {object} [options] - Custom options
|
|
* @param {number} [options.limit=1] - Limit the media select count
|
|
* @param {boolean} [options.disallowSelect=false] - Disallow the selection (only upload) of media items
|
|
* @param {boolean} [options.disallowUpload=false] - Disallow upload (only selection) of media items
|
|
* @param {string[]} [options.fileExtensions] - Allow upload + selection only for the specified file extensions
|
|
* @param {number} [options.maxFileSize=10] - Maximum allowed file size for uploads in Mibibytes
|
|
* @returns {EditorField}
|
|
*/
|
|
media(options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/media.vue'), { ...options });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a media upload + picker
|
|
* @param {object} [options] - Custom options
|
|
* @param {number} [options.limit=1] - Limit the media select count
|
|
* @param {boolean} [options.disallowSelect=false] - Disallow the selection (only upload) of media items
|
|
* @param {boolean} [options.disallowUpload=false] - Disallow upload (only selection) of media items
|
|
* @param {string[]} [options.fileExtensions] - Allow upload + selection only for the specified file extensions
|
|
* @param {number} [options.maxFileSize=10] - Maximum allowed file size for uploads in Mibibytes
|
|
* @returns {EditorField}
|
|
*/
|
|
image(options)
|
|
{
|
|
return this._setComponent(() => import('../editor/fields/media.vue'), { ...options, fileExtensions: ['.jpg', '.jpeg', '.png', '.webp', '.svg'] });
|
|
}
|
|
|
|
|
|
/**
|
|
* Render a video (YouTube/vimeo) picker
|
|
* @param {number} [limit=1] - Limit the videos
|
|
* @returns {EditorField}
|
|
*/
|
|
video(limit)
|
|
{
|
|
return this._setComponent(() => import('../editor/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;
|
|
}
|
|
}
|
|
|
|
|
|
export default EditorField; |