UNPKG

@vs-form/vs-form

Version:

A schema-based form generator component for React using material-ui

1,373 lines (1,352 loc) 120 kB
import React__default, { Component, createElement, Fragment, createRef } from 'react'; import capitalize from 'lodash/capitalize'; import cloneDeep from 'lodash/cloneDeep'; import get from 'lodash/get'; import has from 'lodash/has'; import isArray from 'lodash/isArray'; import isDate from 'lodash/isDate'; import 'lodash/isBoolean'; import 'lodash/isEmpty'; import isFunction from 'lodash/isFunction'; import isInteger from 'lodash/isInteger'; import isNull from 'lodash/isNull'; import isNumber from 'lodash/isNumber'; import isObject from 'lodash/isObject'; import isPlainObject from 'lodash/isPlainObject'; import isRegExp from 'lodash/isRegExp'; import isString from 'lodash/isString'; import isUndefined from 'lodash/isUndefined'; import merge from 'lodash/merge'; import set from 'lodash/set'; import 'lodash/toInteger'; import 'lodash/toNumber'; import 'lodash/trimEnd'; import uniq from 'lodash/uniq'; import 'lodash/debounce'; import 'lodash/throttle'; import { a as VsBaseDataComponent } from './chunk-6c10537c.js'; import TextField from '@material-ui/core/TextField'; import InputAdornment from '@material-ui/core/InputAdornment'; import { a as DataType, b as Component$1, c as ValidationMethod, d as SortDirection, e as ButtonAction, f as InputVariant, g as SchemaEventType } from './chunk-68362596.js'; import Tooltip from '@material-ui/core/Tooltip'; import { withStyles, createStyles } from '@material-ui/core/styles'; import { a as BaseIcon } from './chunk-9f5de191.js'; import { a as getRegisteredComponentList, b as getRegisteredComponent } from './chunk-3774fd4c.js'; import { format } from 'date-fns'; import { EventEmitter } from 'events'; import { a as Text } from './chunk-4358fb9c.js'; import Grid from '@material-ui/core/Grid'; import IconButton from '@material-ui/core/IconButton'; import { a as chevronDown, b as chevronUp, c as alertOutline } from './chunk-dab541a3.js'; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { this.setState({ hasError: true }); console.log(this.props, error, info); } render() { if (this.state.hasError) { return (createElement(Fragment, null, createElement("p", { style: { color: 'red' } }, "Component with id: \"", this.props.comp.node, "\" has errors! "), createElement("p", { style: { color: 'red' } }, "check the console for more info."))); } return this.props.children; } } const addStyles = (component, styles) => { return withStyles(styles)(component); }; const styles = createStyles({ itemSelected: { boxSizing: 'border-box', position: 'absolute', width: '10px', height: '10px', background: 'lightgray', border: '1px solid #333', zIndex: 1, }, dragArea: { minHeight: '50px', }, itemFocused: { boxSizing: 'border-box', position: 'absolute', width: '10px', height: '10px', background: 'greenyellow', border: '1px solid #333', zIndex: 1, } }); const getSelectedClass = (props) => { if (isFocused(props)) { return props.classes.itemFocused; } else if (isSelected(props)) { return props.classes.itemSelected; } else { return ''; } }; const isFocused = (props) => { return props.schemaManager.selection.length >= 1 && props.schemaManager.selection[0] === props.comp; }; const isSelected = (props) => { return !isFocused(props) && props.schemaManager.selection.includes(props.comp); }; const SelectDiv = (props) => (createElement("div", { className: getSelectedClass(props) })); var SelectDiv$1 = addStyles(SelectDiv, styles); class VsForm extends Component { constructor(props) { super(props); this.counter = 0; this.getKey = () => { const s = this.props.schemaManager.schema; return s.name + (this.counter > 0 ? '_' + this.counter : ''); }; } render() { return (createElement(Item, Object.assign({}, this.props, { schema: this.props.schemaManager.schema, node: this.props.node, comp: this.props.schemaManager.schema.components[this.props.node], key: this.getKey() }))); } componentDidMount() { this.props.schemaManager.callSchemaEvent('onDidMount'); } componentWillUnmount() { this.props.schemaManager.clearInputRefList(); this.props.schemaManager.callSchemaEvent('onWillUnmount'); } } VsForm.defaultProps = { node: 'root', designMode: false }; var propTypes = /*#__PURE__*/Object.freeze({ }); const buttons = { btnOk: 'btnOk', btnCancel: 'btnCancel', }; const arrayKeyField = '__rec_id__'; const htmlDateFormat = 'yyyy-MM-dd'; const htmlTimeFormat = 'HH:mm'; const htmlTimeFormatWithSeconds = 'HH:mm:ss'; var constants = /*#__PURE__*/Object.freeze({ buttons: buttons, arrayKeyField: arrayKeyField, htmlDateFormat: htmlDateFormat, htmlTimeFormat: htmlTimeFormat, htmlTimeFormatWithSeconds: htmlTimeFormatWithSeconds }); const dataTypeIsArray = (dataType) => [DataType.array, DataType.arrayString, DataType.arrayNumber, DataType.arrayObject].indexOf(dataType) > -1; const dataTypeToValue = (dataType) => { if (dataType === DataType.string) { return ''; } else if (dataType === DataType.date) { return null; } else if (dataType === DataType.number || dataType === DataType.integer) { return null; } else if (dataType === DataType.boolean) { return false; } else if (dataType === DataType.object) { return {}; } else if (dataTypeIsArray(dataType)) { return []; } else { return ''; } }; const checkType = (type, value) => { if (type === DataType.any) { return true; } else if (type === DataType.string) { return isString(value) || isNull(value); } else if (type === DataType.number) { return isNumber(value) || isNull(value); } else if (type === DataType.integer) { return isInteger(value) || isNull(value); } else if (type === DataType.date) { return isDate(value) || isNull(value); } else if (type === DataType.function) { return isFunction(value); } else if (type === DataType.regex) { return isRegExp(value); } else if (type === DataType.array) { return isArray(value); } else if (type === DataType.arrayString) { return isArray(value) && value.filter(e => !isString(e)).length === 0; } else if (type === DataType.arrayNumber) { return isArray(value) && value.filter(e => !isNumber(e)).length === 0; } else if (type === DataType.arrayObject) { return isArray(value) && value.filter(e => !isObject(e)).length === 0; } if (dataTypeIsArray(type)) { return isArray(value); } if (isArray(value)) { return (dataTypeIsArray(type)); } return typeof value === type; }; const formatJSON = (obj) => { return JSON.stringify(obj, null, 2); }; const valueIsNumber = (val) => { if (typeof val === 'string') { return !isNaN(Number(val)); } return typeof val === 'number'; }; const dateToString = (date, compType, withSeconds) => { const f = withSeconds ? htmlTimeFormatWithSeconds : htmlTimeFormat; if (compType === Component$1.date) { return format(date, htmlDateFormat); } else if (compType === Component$1.datetime) { return format(date, htmlDateFormat) + 'T' + format(date, f); } else if (compType === Component$1.time) { return format(date, f); } return ''; }; const stringToDate = (compType, val) => { let dt = null; if ([Component$1.date, Component$1.datetime].indexOf(compType) > -1) { try { dt = new Date(val); } catch (error) { } } else if (compType === Component$1.time) { try { dt = new Date('1970-01-01T' + val); } catch (error) { } } return dt; }; const checkIsParentComponent = (comp) => { if (comp && has(comp, 'children')) { return comp; } else { return undefined; } }; const checkIsDataComponent = (comp) => { if (comp && has(comp, 'data.field')) { return comp; } else { return undefined; } }; const checkIsButtonComponent = (comp) => { if (comp && (comp.type === Component$1.button || comp.type === Component$1.iconbutton)) { return comp; } else { return undefined; } }; const checkIsSelectComponent = (comp) => { if (comp && (comp.type === Component$1.select || comp.type === Component$1.radiogroup || comp.type === Component$1.selectext)) { return comp; } else { return undefined; } }; var common = /*#__PURE__*/Object.freeze({ dataTypeIsArray: dataTypeIsArray, dataTypeToValue: dataTypeToValue, checkType: checkType, formatJSON: formatJSON, valueIsNumber: valueIsNumber, dateToString: dateToString, stringToDate: stringToDate, checkIsParentComponent: checkIsParentComponent, checkIsDataComponent: checkIsDataComponent, checkIsButtonComponent: checkIsButtonComponent, checkIsSelectComponent: checkIsSelectComponent }); var SchemaErrorType; (function (SchemaErrorType) { SchemaErrorType["error"] = "error"; SchemaErrorType["warning"] = "warning"; })(SchemaErrorType || (SchemaErrorType = {})); var types = /*#__PURE__*/Object.freeze({ get SchemaErrorType () { return SchemaErrorType; } }); var ErrorCode; (function (ErrorCode) { ErrorCode["rootnotContainer"] = "rootnotContainer"; ErrorCode["rootChildrenEmpty"] = "rootChildrenEmpty"; ErrorCode["errParseString"] = "errParseString"; ErrorCode["schemaNotFound"] = "schemaNotFound"; ErrorCode["subSchemaNotFound"] = "subSchemaNotFound"; ErrorCode["subSchemaKeyInvalid"] = "subSchemaKeyInvalid"; ErrorCode["componentsnotdefined"] = "componentsnotdefined"; ErrorCode["valuesnotdefined"] = "valuesnotdefined"; ErrorCode["namePropMissing"] = "namePropMissing"; ErrorCode["duplicateFields"] = "duplicateFields"; ErrorCode["duplicateFieldPaths"] = "duplicateFieldPaths"; ErrorCode["duplicateIds"] = "duplicateIds"; ErrorCode["fieldsHasNoParent"] = "fieldsHasNoParent"; ErrorCode["fieldhasDuplicatesInChildren"] = "fieldhasDuplicatesInChildren"; ErrorCode["valuesKeyHasNoField"] = "valuesKeyHasNoField"; ErrorCode["onlyFormTagForRootComp"] = "onlyFormTagForRootComp"; ErrorCode["recursiveChildren"] = "recursiveChildren"; ErrorCode["possibleRecursion"] = "possibleRecursion"; ErrorCode["hasnotype"] = "hasnotype"; ErrorCode["invalidtype"] = "invalidtype"; ErrorCode["invalidComponentType"] = "invalidComponentType"; ErrorCode["hasNoComponentType"] = "hasNoComponentType"; ErrorCode["requiredPropMissing"] = "requiredPropMissing"; ErrorCode["wrongPropertyType"] = "wrongPropertyType"; ErrorCode["wrongPropertyTypeInArray"] = "wrongPropertyTypeInArray"; ErrorCode["arrayIsEmpty"] = "arrayIsEmpty"; ErrorCode["noChildrenKeys"] = "noChildrenKeys"; ErrorCode["invalidChildrenKeys"] = "invalidChildrenKeys"; ErrorCode["invalidTabsKeys"] = "invalidTabsKeys"; ErrorCode["invalidColumns"] = "invalidColumns"; ErrorCode["notDataFieldColumns"] = "notDataFieldColumns"; ErrorCode["valueNotInEnum"] = "valueNotInEnum"; ErrorCode["valueSmallerThanMin"] = "valueSmallerThanMin"; ErrorCode["valueGreaterThanMax"] = "valueGreaterThanMax"; ErrorCode["valueNotInMinMax"] = "valueNotInMinMax"; ErrorCode["fieldNotInValues"] = "fieldNotInValues"; ErrorCode["wrongDataTypeInValues"] = "wrongDataTypeInValues"; ErrorCode["hasInvalidProp"] = "hasInvalidProp"; ErrorCode["wrongDataType"] = "wrongDataType"; ErrorCode["wrongDataTypeDefaultValue"] = "wrongDataTypeDefaultValue"; ErrorCode["selectItemsMustBeObjects"] = "selectItemsMustBeObjects"; ErrorCode["selectItemsMustHaveValueAndText"] = "selectItemsMustHaveValueAndText"; ErrorCode["selectItemsMustHaveCorrectDataType"] = "selectItemsMustHaveCorrectDataType"; ErrorCode["selectItemsUnique"] = "selectItemsUnique"; ErrorCode["selectItemsTextMusBeString"] = "selectItemsTextMusBeString"; ErrorCode["selectItemsTextOnlyOneEmpty"] = "selectItemsTextOnlyOneEmpty"; ErrorCode["selectItemsTextNotUnique"] = "selectItemsTextNotUnique"; ErrorCode["typeStringOrArray"] = "typeStringOrArray"; ErrorCode["compNotFound"] = "compNotFound"; ErrorCode["invalidPrefixType"] = "invalidPrefixType"; ErrorCode["invalidIconType"] = "invalidIconType"; ErrorCode["maskOnlyInMaskInputComponent"] = "maskOnlyInMaskInputComponent"; ErrorCode["maskNotMultilineInput"] = "maskNotMultilineInput"; ErrorCode["maskArrayOrFunction"] = "maskArrayOrFunction"; ErrorCode["maskArrayItemsStringOrRegExp"] = "maskArrayItemsStringOrRegExp"; ErrorCode["stringOrFunction"] = "stringOrFunction"; ErrorCode["styleMustBeObject"] = "styleMustBeObject"; ErrorCode["styleAttrNotObject"] = "styleAttrNotObject"; ErrorCode["speedDialActionObject"] = "speedDialActionObject"; ErrorCode["iconOrSvg"] = "iconOrSvg"; })(ErrorCode || (ErrorCode = {})); const ErrorStrings = { rootnotContainer: 'Root component type must be a container', rootChildrenEmpty: 'the children array may not be empty', errParseString: 'String parsing error', schemaNotFound: 'ISchema not found in List', subSchemaNotFound: 'Sub-Schema not found', subSchemaKeyInvalid: 'The keyField is not a valid field.', componentsnotdefined: 'components not defined!', valuesnotdefined: 'values not defined!', namePropMissing: 'schema has no name property', duplicateFields: 'duplicate fields are present', duplicateFieldPaths: 'duplicate Field Paths are present', duplicateIds: 'duplicate Ids are present', fieldsHasNoParent: 'field has no parent (not in any children)', fieldhasDuplicatesInChildren: 'field is in several parents', valuesKeyHasNoField: 'For the following value key(s) the component is missing:', onlyFormTagForRootComp: 'Form component is only allowed for the root component', recursiveChildren: 'Possible Recursion with children in containers', possibleRecursion: 'Possible Recursion : More than 100 Sub-Schemas found', hasnotype: 'has no type', invalidtype: 'has invalid type', requiredPropMissing: 'required Property missing', wrongPropertyType: 'property has wrong type', wrongPropertyTypeInArray: 'Items in the array has the wrong type', arrayIsEmpty: 'array should not be empty', noChildrenKeys: 'Container has no children', invalidChildrenKeys: 'Container contains invalid keys', invalidTabsKeys: 'Only tabs-Component are allowed', invalidColumns: 'Data Table has invalid columns', notDataFieldColumns: 'The columns of the Data Table must be data fields', valueNotInEnum: 'value is not in the list of allowed values', valueSmallerThanMin: 'value is smaller than minimum', valueGreaterThanMax: 'value is greater than maximum', valueNotInMinMax: 'value is not between min and max', fieldNotInValues: 'field not present in schema.values', wrongDataTypeInValues: 'field has wrong Value Type in schema.values', hasInvalidProp: 'invalid (unnecessary) property', wrongDataType: 'the value has a wrong data-type', wrongDataTypeDefaultValue: 'the default value has the wrong data-type', invalidComponentType: 'IComponent has an invalid type', hasNoComponentType: 'Component has no type', selectItemsMustBeObjects: 'Items in select must objects', selectItemsMustHaveValueAndText: 'All Items in select must have a text and a value property', selectItemsMustHaveCorrectDataType: 'All Item-Values must have the type defined in the datatype', selectItemsUnique: 'All Item-Values must be unique', selectItemsTextMusBeString: 'All Item-Texts must be string', selectItemsTextOnlyOneEmpty: 'Only one Item should have empty string', selectItemsTextNotUnique: 'Text in items are not unique', typeStringOrArray: 'property must be either string or array of strings', compNotFound: 'Prefix/Suffix: Component not found', invalidPrefixType: 'Prefix/Suffix-Components must be either text, button or iconbutton', invalidIconType: 'Icon-Component is not an icon', maskOnlyInMaskInputComponent: 'mask can only be defined in the input component', maskNotMultilineInput: 'masks cannot be applied to multiline inputs', maskArrayOrFunction: 'mask must be either an array or a function', maskArrayItemsStringOrRegExp: 'each item in the mask array mmust be either a string or a regexp', stringOrFunction: 'property must be either string or a function', styleMustBeObject: 'Style must be an object', styleAttrNotObject: 'Style attribute should not be an object', speedDialActionObject: 'Each Speed Dial Action must be an object', iconOrSvg: 'Icon or svg property must be provided for Icon-Component', }; var str_err = /*#__PURE__*/Object.freeze({ get ErrorCode () { return ErrorCode; }, ErrorStrings: ErrorStrings }); const required = (name) => (v) => !!v || `${name} is required`; const checkItemsInSelect = (_items, dataType) => { if (isFunction(_items)) { return ''; } const items = _items; let arr = []; let sortedArr = []; const dataTypeValue = () => dataType === DataType.arrayString ? DataType.string : (dataType === DataType.arrayNumber || dataType === DataType.integer || dataType === DataType.arrayInteger) ? DataType.number : dataType; const getLineNumbers = (orig, error) => { return error.map(el => orig.indexOf(el) + 1); }; const arrToString = (a) => { return a.map(e => e && e.value ? e.value.toString() : '' + ',' + (e ? e.text : '')).toString(); }; arr = items.filter(el => !(isObject(el))); if (arr.length > 0) { return { errcode: ErrorCode.selectItemsMustBeObjects, addOn: arrToString(arr), itemNo: getLineNumbers(items, arr).toString() }; } arr = items.filter(el => !(has(el, 'value') && has(el, 'text'))); if (arr.length > 0) { return { errcode: ErrorCode.selectItemsMustHaveValueAndText, addOn: arrToString(arr), itemNo: getLineNumbers(items, arr).toString() }; } arr = items.filter((el) => typeof el.value !== dataTypeValue()); if (arr.length > 0) { return { errcode: ErrorCode.selectItemsMustHaveCorrectDataType, addOn: arrToString(arr), itemNo: getLineNumbers(items, arr).toString() }; } sortedArr = items.map(e => e); if (dataTypeValue() === DataType.number) { sortedArr.sort((a, b) => (a.value - b.value)); } else { sortedArr.sort((a, b) => { if (a.value < b.value) { return -1; } else if (a.value > b.value) { return 1; } else { return 0; } }); } arr = []; for (let i = 0; i < sortedArr.length - 2; i++) { if (sortedArr[i + 1] && sortedArr[i + 1].value === sortedArr[i].value) { arr.push(sortedArr[i]); } } arr = uniq(arr); if (arr.length > 0) { return { errcode: ErrorCode.selectItemsUnique, addOn: arrToString(arr), itemNo: getLineNumbers(items, arr).toString() }; } arr = items.filter(el => !isString(el.text)); if (arr.length > 0) { return { errcode: ErrorCode.selectItemsTextMusBeString, addOn: arrToString(arr) }; } arr = items.filter(el => (el.text.trim() === '')); if (arr.length > 1) { return { errcode: ErrorCode.selectItemsTextOnlyOneEmpty, addOn: arrToString(arr) }; } sortedArr = items.sort((a, b) => { if (a.text < b.text) { return -1; } else if (a.text > b.text) { return 1; } else { return 0; } }); arr = []; for (let i = 0; i < sortedArr.length - 1; i++) { if (sortedArr[i + 1].text === sortedArr[i].text) { arr.push(sortedArr[i]); } } arr = uniq(arr); if (arr.length > 0) { return { errcode: ErrorCode.selectItemsTextNotUnique, type: SchemaErrorType.warning, addOn: arrToString(arr), itemNo: getLineNumbers(items, arr).toString() }; } return ''; }; var fieldValidators = /*#__PURE__*/Object.freeze({ required: required, checkItemsInSelect: checkItemsInSelect }); const rootIsWrong = sm => { const comp = sm.schema.components.root; if ([Component$1.form, Component$1.panel, Component$1.card, Component$1.expansionpanel, Component$1.tabs].indexOf(comp.type) === -1) { return { errcode: ErrorCode.rootnotContainer, schemaName: sm.schema.name }; } if (comp.children && isArray(comp.children) && comp.children.length === 0) { return { errcode: ErrorCode.rootChildrenEmpty, schemaName: sm.schema.name }; } return ''; }; const hasRecursion = sm => { const counter = { count: 0, max: 100 }; hasRecursion1(sm, sm.schema, sm.schemaList, counter); return counter.count >= counter.max ? { errcode: ErrorCode.possibleRecursion, schemaName: sm.schema.name } : ''; }; function hasRecursion1(schemaManager, schema, schemaList, counter) { if (counter.count >= counter.max) { counter.count = counter.max + 1; return; } Object.keys(schema.components).forEach(key => { const comp = schema.components[key]; if (comp.type === Component$1.subschema) { counter.count++; if (comp.schemaName && counter.count < counter.max) { const s = schemaManager.getSchemaFromList(comp.schemaName); if (s) { hasRecursion1(schemaManager, s, schemaList, counter); } } } }); } const hasUnresolvedSubschemaNames = sm => { const arr = []; const componentCallback = p => { if (p.comp && p.comp.type === Component$1.subschema && p.comp.schemaName) { const s = sm.getSchemaFromList(p.comp.schemaName); if (!s) { arr.push(p.comp.schemaName); } } }; const options = { processSubSchemas: true }; SchemaManager.processSchema({ componentCallback, schema: sm.schema, options }); return arr.length > 0 ? { errcode: ErrorCode.subSchemaNotFound, addOn: arr.toString(), schemaName: sm.schema.name } : ''; }; const onlyFormTagForRoot = sm => { const arr = []; const componentCallback = p => { if (p.comp && p.comp.type === Component$1.form && p.comp.id !== 'root') { arr.push(p.comp.id); } }; const options = { processSubSchemas: false }; SchemaManager.processSchema({ componentCallback, schema: sm.schema, options }); return arr.length > 0 ? { errcode: ErrorCode.onlyFormTagForRootComp, addOn: arr.toString(), schemaName: sm.schema.name } : ''; }; const isDuplicateInChildren = sm => { const parents = Object.keys(sm.schema.components).map(c => sm.schema.components[c]).filter(c => has(c, 'children')); const getParents = (key) => parents.filter(c => c.children.includes(key)); const dup = []; const componentCallback = p => { const pr = getParents(p.comp.node); if (pr.length > 1) { dup.push(p.comp.node); } }; const options = { processSubSchemas: true }; SchemaManager.processSchema({ componentCallback, schema: sm.schema, options }); if (dup.length > 0) { return { errcode: ErrorCode.fieldhasDuplicatesInChildren, type: SchemaErrorType.warning, addOn: dup.toString(), schemaName: sm.schema.name }; } else { return ''; } }; const childrenHasRecursion = sm => { const dup = []; const recursiveChildren = (comp, counter) => { if (counter.count >= counter.max) { counter.count = counter.max + 1; return; } const cp = checkIsParentComponent(comp); if (cp) { cp.children.forEach((child) => { counter.count++; if (has(sm.schema.components, child) && counter.count < counter.max) { recursiveChildren(sm.schema.components[child], counter); } }); } }; const componentCallback = p => { const counter = { count: 0, max: 500 }; recursiveChildren(p.comp, counter); if (counter.count >= counter.max) { const key = p.key; if (!dup.includes(key)) { dup.push(key); } } }; const options = { processSubSchemas: true }; SchemaManager.processSchema({ componentCallback, schema: sm.schema, options }); if (dup.length > 0) { return { errcode: ErrorCode.recursiveChildren, addOn: dup.toString(), schemaName: sm.schema.name }; } else { return ''; } }; const hasDuplicateFields = sm => { const arr = []; let dup = []; const componentCallback = p => { const cd = checkIsDataComponent(p.comp); if (cd) { const field = cd.data.field; if (arr.includes(field)) { dup.push(field); } arr.push(field); } }; const options = { processSubSchemas: false }; SchemaManager.processSchema({ componentCallback, schema: sm.schema, options }); dup = uniq(dup); if (dup.length > 0) { return { errcode: ErrorCode.duplicateFields, addOn: dup.toString(), type: SchemaErrorType.warning, schemaName: sm.schema.name }; } else { return ''; } }; const hasFieldsNotInChildren = sm => { const missing = sm.getComponentsWithNoParent(); return missing.length > 0 ? { errcode: ErrorCode.fieldsHasNoParent, addOn: missing.toString(), type: SchemaErrorType.warning, schemaName: sm.schema.name } : ''; }; const valuesKeyHasNoComponent = sm => { const arr = []; const getFields = (values, parent) => { Object.keys(values).forEach(key => { const comp = sm.getComponentByFieldPath(parent + key); if (!comp) { arr.push(parent + key); } else if (comp.type === Component$1.subschema) { getFields(values[key], parent + key + '.'); } }); }; if (sm.schema.values) { getFields(sm.schema.values, ''); } if (arr.length > 0) { return { errcode: ErrorCode.valuesKeyHasNoField, addOn: arr.toString(), type: SchemaErrorType.warning, schemaName: sm.schema.name }; } else { return ''; } }; const hasValidChildrenKeys = (validSchema, component, schema) => { const property = get(component, validSchema.prop); if (property.length === 0) { return { errcode: ErrorCode.noChildrenKeys, type: SchemaErrorType.warning }; } const arr = []; property.forEach((el) => { if (!has(schema.components, el)) { arr.push(el); } }); if (arr.length > 0) { return { errcode: ErrorCode.invalidChildrenKeys, addOn: arr.toString() }; } return ''; }; const hasValidTabsKeys = (validSchema, component, schema) => { const property = get(component, validSchema.prop); if (property.length === 0) { return { errcode: ErrorCode.noChildrenKeys, type: SchemaErrorType.warning }; } let arr = []; property.forEach((el) => { if (!has(schema.components, el)) { arr.push(el); } }); if (arr.length > 0) { return { errcode: ErrorCode.invalidChildrenKeys, addOn: arr.toString() }; } arr = []; property.forEach((el) => { if (schema.components[el].type !== Component$1.tab) { arr.push(el); } }); if (arr.length > 0) { return { errcode: ErrorCode.invalidTabsKeys, addOn: arr.toString() }; } return ''; }; const stylesValid = (validSchema, component, _schema) => { let err = ''; const property = get(component, validSchema.prop); if (isObject(property)) { Object.keys(property).forEach(key => { if (!isObject(property[key])) { err = { errcode: ErrorCode.styleMustBeObject, prop: 'styles.' + key }; return; } }); } return err; }; const speedDialActionsValid = (validSchema, component, _schema) => { let err = ''; const property = get(component, validSchema.prop); if (isArray(property)) { if (property.length === 0) { return { errcode: ErrorCode.arrayIsEmpty }; } property.forEach((obj, ind) => { const sInd = (ind + 1).toString(); if (isObject(obj)) { if (isUndefined(obj['icon'])) { err = { errcode: ErrorCode.requiredPropMissing, addOn: 'prop: icon', itemNo: sInd }; return; } if (!isString(obj['icon'])) { err = { errcode: ErrorCode.wrongPropertyTypeInArray, addOn: 'prop: icon', itemNo: sInd }; return; } if (isUndefined(obj['tooltip'])) { err = { errcode: ErrorCode.requiredPropMissing, addOn: 'prop: tooltip', itemNo: sInd }; return; } if (!isString(obj['tooltip'])) { err = { errcode: ErrorCode.wrongPropertyTypeInArray, addOn: 'prop: tooltip', itemNo: sInd }; return; } if (isUndefined(obj['onClick'])) { err = { errcode: ErrorCode.requiredPropMissing, addOn: 'prop: onClick', itemNo: sInd, type: SchemaErrorType.warning }; return; } if (!isFunction(obj['onClick'])) { err = { errcode: ErrorCode.wrongPropertyTypeInArray, addOn: 'prop: onClick', itemNo: sInd }; return; } } else { err = { errcode: ErrorCode.speedDialActionObject, addOn: 'Entry No.: ' + sInd, itemNo: sInd }; return; } }); } return err; }; const prefixSuffixCompValid = (validSchema, component, schema) => { const property = get(component, validSchema.prop); if (!(isArray(property) || isString(property))) { return { errcode: ErrorCode.typeStringOrArray }; } if (isArray(property)) { const arr = []; property.forEach((s) => { const c = schema.components[s]; if (!c) { arr.push(s); } }); if (arr.length > 0) { return { errcode: ErrorCode.compNotFound, addOn: arr.toString() }; } property.forEach((s) => { const c = schema.components[s]; if ([Component$1.button, Component$1.iconbutton, Component$1.icon, Component$1.text].indexOf(c.type) === -1) { arr.push(s); } }); if (arr.length > 0) { return { errcode: ErrorCode.invalidPrefixType, addOn: arr.toString() }; } } return ''; }; const iconValid = (_validSchema, component, _schema) => { if (!(component['icon'] || component['svg'] || component['component'])) { return { errcode: ErrorCode.iconOrSvg }; } return ''; }; const iconCompValid = (validSchema, component, schema) => { const property = get(component, validSchema.prop); if (!(isArray(property) || isString(property))) { return { errcode: ErrorCode.typeStringOrArray }; } if (isArray(property)) { const arr = []; property.forEach((s) => { const c = schema.components[s]; if (!c) { arr.push(s); } }); if (arr.length > 0) { return { errcode: ErrorCode.compNotFound, addOn: arr.toString() }; } property.forEach((s) => { const c = schema.components[s]; if (c.type !== Component$1.icon) { arr.push(s); } }); if (arr.length > 0) { return { errcode: ErrorCode.invalidIconType, addOn: arr.toString() }; } } return ''; }; const subschemaKeyField = (validSchema, component, schema) => { const property = get(component, validSchema.prop); const subschema = component['schema']; const options = { done: false }; let fieldFound = false; const componentCallback = p => { const cd = checkIsDataComponent(p.comp); if (cd) { if (cd.data.field === property) { options.done = true; fieldFound = true; } } }; SchemaManager.processSchema({ componentCallback, schema: subschema, options }); if (!fieldFound) { return { errcode: ErrorCode.subSchemaKeyInvalid }; } return ''; }; const maskInput = (_validSchema, component, _schema) => { if (component.type === Component$1.maskinput) { if (component.props && component.props.multiline) { return { errcode: ErrorCode.maskNotMultilineInput }; } const mask = component.maskProps.mask; if (isFunction(mask)) { return ''; } else if (isArray(mask)) { const arr = mask.filter(e => !(isString(e) || isRegExp(e))); if (arr.length > 0) { return { errcode: ErrorCode.maskArrayItemsStringOrRegExp }; } } else { return { errcode: ErrorCode.maskArrayOrFunction }; } } else { return { errcode: ErrorCode.maskOnlyInMaskInputComponent }; } return ''; }; const numberFormat = (_validSchema, component, _schema) => { const ci = component; if (!ci.numberFormatProps) { return { errcode: ErrorCode.requiredPropMissing }; } if (ci.numberFormatProps.format) { if (!(isString(ci.numberFormatProps.format) || isFunction(ci.numberFormatProps.format))) { return { errcode: ErrorCode.stringOrFunction, prop: 'numberFormatProps.format' }; } } if (ci.numberFormatProps.mask) { if (!(isString(ci.numberFormatProps.mask) || isArray(ci.numberFormatProps.mask))) { return { errcode: ErrorCode.typeStringOrArray, prop: 'numberFormatProps.mask' }; } } return ''; }; const defaultValue = (validSchema, component, _schema) => { let err = false; const cd = checkIsDataComponent(component); if (cd) { const property = get(component, validSchema.prop); if (isUndefined(property) || !cd.data.dataType) { return ''; } if (isFunction(property)) { return ''; } if (get(cd, 'data.dataType') === DataType.integer) { err = !(isInteger(property)); } else if (get(cd, 'data.dataType') === DataType.date) { err = !(isDate(property)); } else if (get(cd, 'data.dataType') === DataType.arrayNumber) { if (!isArray(property)) { err = true; } else { property.forEach(item => { if (typeof item !== DataType.number) { err = true; } }); } } else if (get(cd, 'data.dataType') === DataType.arrayInteger) { if (!isArray(property)) { err = true; } else { property.forEach(item => { if (!isInteger(item)) { err = true; } }); } } else if (get(cd, 'data.dataType') === DataType.arrayString) { if (!isArray(property)) { err = true; } else { property.forEach(item => { if (typeof item !== DataType.string) { err = true; } }); } } else if (get(cd, 'data.dataType') === DataType.arrayObject) { if (!isArray(property)) { err = true; } else { property.forEach(item => { if (!isObject(item)) { err = true; } }); } } else if (typeof property !== get(cd, 'data.dataType')) { err = true; return { errcode: ErrorCode.wrongDataTypeDefaultValue }; } } if (err) { return { errcode: ErrorCode.wrongDataTypeDefaultValue }; } else { return ''; } }; const hasValidColumns = (validSchema, component, _schema) => { const property = get(component, validSchema.prop); const arr = []; if (property) { property.forEach((el) => { const comp = get(component.schema.components, el.compId); const cd = checkIsDataComponent(comp); if (!cd) { arr.push(el.compId); } }); if (arr.length > 0) { return { errcode: ErrorCode.invalidColumns, addOn: arr.toString() }; } } return ''; }; const itemsInSelect = (_validSchema, component, _schema) => { if (has(component, 'data.items')) { return checkItemsInSelect(component.data.items, component.data.dataType); } return ''; }; const required$1 = () => ({ required: true }); const typeString = () => ({ type: DataType.string }); const typeNumber = () => ({ type: DataType.number }); const typeObject = () => ({ type: DataType.object }); const typeStringOrFunction = () => ({ type: [DataType.string, DataType.function] }); const typeStringOrStringArray = () => ({ type: [DataType.string, DataType.arrayString] }); const typeArray = () => ({ type: DataType.array }); const typeBoolean = () => ({ type: DataType.boolean }); const typeBooleanOrFunction = () => ({ type: [DataType.boolean, DataType.function] }); const typeAny = () => ({ type: DataType.any }); const typeFunction = () => ({ type: DataType.function }); const typeRegex = () => ({ type: DataType.regex }); const gridSize = () => ({ enum: [true, false, 'auto', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] }); const objectRequired = () => ({ ...required$1(), ...typeObject() }); const arrayRequired = () => ({ ...required$1(), ...typeArray() }); const arrayNotRequired = () => ({ ...typeArray() }); const labelRequired = () => ({ label: { ...required$1(), ...typeStringOrFunction() }, }); const label = () => ({ label: { ...typeStringOrFunction() }, }); const hint = () => ({ hint: { ...typeStringOrFunction() }, }); const tooltip = () => ({ tooltip: { ...typeStringOrFunction() }, tooltipProps: { ...typeObject() } }); const text = () => ({ text: { ...typeStringOrFunction() }, }); const fieldRequired = () => ({ field: { ...required$1(), ...typeString() } }); const stringRequired = () => ({ ...required$1(), ...typeString() }); const validatorsChildren = () => ({ validators: [hasValidChildrenKeys] }); const validatorsTabsChildren = () => ({ validators: [hasValidTabsKeys] }); const itemsChildren = () => ({ items: { ...typeString() } }); const validatorsColumns = () => ({ validators: [hasValidColumns] }); const validatorsDefaultValue = () => ({ validators: [defaultValue] }); const validatorsMaskInput = () => ({ validators: [maskInput] }); const validatorsNumberFormat = () => ({ validators: [numberFormat] }); const validatorsPrefixComp = () => ({ validators: [prefixSuffixCompValid] }); const validatorsIconComp = () => ({ validators: [iconCompValid] }); const validatorsSubschemaKeyField = () => ({ validators: [subschemaKeyField] }); const validatorsIcon = () => ({ validators: [iconValid] }); const validatorsStyles = () => ({ validators: [stylesValid] }); const validatorsSpeedDialActions = () => ({ validators: [speedDialActionsValid] }); const gridProps = () => ({ ...typeObject(), properties: { xl: { ...typeAny(), ...gridSize() }, lg: { ...typeAny(), ...gridSize() }, md: { ...typeAny(), ...gridSize() }, sm: { ...typeAny(), ...gridSize() }, xs: { ...typeAny(), ...gridSize() }, alignContent: { ...typeString(), enum: ['stretch', 'center', 'flex-start', 'flex-end', 'space-between', 'space-around'] }, alignItems: { ...typeString(), enum: ['flex-start', 'center', 'flex-end', 'stretch', 'baseline'] }, direction: { ...typeString(), enum: ['row', 'row-reverse', 'column', 'column-reverse'] }, justify: { ...typeString(), enum: ['flex-start', 'center', 'flex-end', 'space-between', 'space-around', 'space-evenly'] }, spacing: { ...typeNumber(), enum: [0, 8, 16, 24, 32, 40] }, wrap: { ...typeString(), enum: ['nowrap', 'wrap', 'wrap-reverse'] }, zeroMinWidth: { ...typeBoolean() }, item: { ...typeBoolean() }, container: { ...typeBoolean() }, style: { ...typeObject() }, } }); const maskProps = () => ({ ...typeObject(), properties: { mask: { ...typeAny(), ...validatorsMaskInput() }, guide: { ...typeBoolean() }, placeholder: { ...typeString() }, pipe: { ...typeFunction() }, showMask: { ...typeBoolean() }, } }); const numberFormatProps = () => ({ ...objectRequired(), properties: { thousandSeparator: { ...typeString() }, decimalSeparator: { ...typeString() }, decimalScale: { ...typeNumber() }, fixedDecimalScale: { ...typeBoolean() }, displayType: { ...typeString(), enum: ['input', 'text'] }, prefix: { ...typeString() }, suffix: { ...typeString() }, format: { ...typeStringOrFunction() }, removeFormatting: { ...typeFunction() }, mask: { ...typeStringOrStringArray() }, allowNegative: { ...typeBoolean() }, allowEmptyFormatting: { ...typeBoolean() }, isAllowed: { ...typeFunction() } } }); const modifyDataPropsText = (obj) => { obj.properties.dataType.enum = [DataType.string]; }; const modifyDataPropsSelect = (obj) => { obj.properties.dataType.enum = [DataType.string, DataType.integer, DataType.number, DataType.arrayString, DataType.arrayInteger, DataType.arrayNumber]; obj.properties.items = arrayRequired(); obj.properties.items.validators = [itemsInSelect]; }; const modifyDataPropsCheckListBox = (obj) => { obj.properties.dataType.enum = [DataType.arrayString, DataType.arrayInteger, DataType.arrayNumber]; obj.properties.items = arrayRequired(); obj.properties.items.validators = [itemsInSelect]; }; const modifyDataPropsRadio = (obj) => { obj.properties.dataType.enum = [DataType.string, DataType.integer, DataType.number]; obj.properties.items = arrayRequired(); obj.properties.items.validators = [itemsInSelect]; }; const modifyDataPropsNumber = (obj) => { obj.properties.dataType.enum = [DataType.number]; }; const modifyDataPropsSlider = (obj) => { obj.properties.dataType.enum = [DataType.number]; obj.properties.validations.properties.step = { ...typeNumber() }; }; const modifyDataPropsNumberFormat = (obj) => { obj.properties.dataType.enum = [DataType.number, DataType.integer]; }; const modifyDataPropsInteger = (obj) => { obj.properties.dataType.enum = [DataType.integer]; }; const modifyDataPropsDate = (obj) => { obj.properties.dataType.enum = [DataType.date]; }; const modifyDataPropsBoolean = (obj) => { obj.properties.dataType.enum = [DataType.boolean]; }; const modifyDataPropsSubschema = (obj) => { obj.properties.dataType.enum = [DataType.object, DataType.array]; }; const commonProps = (modifyPropsProps) => { const fn = modifyPropsProps ? modifyPropsProps : () => ({}); return { type: { ...stringRequired() }, id: { ...typeString() }, node: { ...typeString() }, ...tooltip(), gridItem: { ...gridProps() }, styles: { ...typeObject(), ...validatorsStyles() }, ...commonPropsProps(fn), disabled: { ...typeBoolean() }, hidden: { ...typeBoolean() }, }; }; const _validSchemaSchema = () => ({ ...typeObject(), preValidators: [rootIsWrong, hasRecursion, childrenHasRecursion, hasUnresolvedSubschemaNames], postValidators: [hasDuplicateFields, hasFieldsNotInChildren, isDuplicateInChildren, onlyFormTagForRoot, valuesKeyHasNoComponent], additionalProperties: true, properties: { id: { ...typeString() }, name: { ...stringRequired() }, node: { ...typeString() }, validationMethod: { ...typeNumber(), enum: [ValidationMethod.validateOnChange, ValidationMethod.validateOnSubmit] }, hideValidationErrorPanel: { ...typeBoolean() }, label: { ...typeString() }, values: { ...typeObject() }, components: { ...objectRequired(), additionalProperties: true, properties: { root: { ...objectRequired(), properties: { label: { ...typeString() }, ...commonProps(), ...label(), gridContainer: { ...gridProps() }, children: { ...arrayRequired(), ...required$1(), ...itemsChildren(), }, } }, } }, styles: { ...typeObject(), ...validatorsStyles() }, disabled: { ...typeBoolean() }, onCreated: { ...typeFunction() }, onDidMount: { ...typeFunction() }, onWillUnmount: { ...typeFunction() }, onChange: { ...typeFunction() }, onSubmit: { ...typeFunction() }, onCancelValues: { ...typeFunction() }, validate: { ...typeFunction() }, } }); const commonDataProps = (modifyProps) => { const obj = { ...objectRequired(), properties: { ...fieldRequired(), dataType: { ...stringRequired(), enum: [] }, fieldPath: { ...typeString() }, default: { ...typeAny(), ...validatorsDefaultValue() }, onBeforeChange: { ...typeFunction() }, onChange: { ...typeFunction() }, validations: { ...typeObject(), properties: { required: { ...typeBooleanOrFunction() }, allowedValues: { ...typeArray() }, min: { ...typeNumber() }, max: { ...typeNumber() }, regex: { ...typeRegex() }, validate: { ...typeFunction() } } }, modifiers: { ...typeObject(), properties: { trim: { ...typeBoolean() }, toLowerCase: { ...typeBoolean() }, toUpperCase: { ...typeBoolean() }, capitalize: { ...typeBoolean() }, } }, errors: { ...typeArray() }, } }; if (modifyProps) { modifyProps(obj); } return obj; }; const commonPropsProps = (modifyProps) => { return { props: { ...typeObject(), additionalProperties: true, properties: { className: { ...typeString() }, style: { ...typeObject() }, ...modifyProps() } } }; }; const propsPropsInputField = () => { return { variant: { ...typeString(), enum: Object.keys(InputVariant).map(key => InputVariant[key]) }, multiline: { ...typeBoolean() } }; }; const commonInputFieldProps = () => ({ ...labelRequired(), ...hint(), prefix: { ...typeStringOrStringArr