diff --git a/src/fireedge/src/client/components/FormControl/AutocompleteController.js b/src/fireedge/src/client/components/FormControl/AutocompleteController.js index d743c5b091..9242477d7d 100644 --- a/src/fireedge/src/client/components/FormControl/AutocompleteController.js +++ b/src/fireedge/src/client/components/FormControl/AutocompleteController.js @@ -32,7 +32,7 @@ const AutocompleteController = memo( tooltip = '', multiple = false, values = [], - fieldProps = {} + fieldProps: { separators, ...fieldProps } = {} }) => { const { field: { value: renderValue, onBlur, onChange }, @@ -88,6 +88,15 @@ const AutocompleteController = memo( loading: true, loadingText: labelCanBeTranslated(tooltip) ? Tr(tooltip) : tooltip })} + {...(Array.isArray(separators) && { + autoSelect: true, + onInputChange: (event, newInputValue) => { + if (separators.includes(newInputValue.at(-1))) { + event.target.blur() + event.target.focus() + } + } + })} {...fieldProps} /> ) diff --git a/src/fireedge/src/client/components/Forms/Provision/CreateForm/Steps/index.js b/src/fireedge/src/client/components/Forms/Provision/CreateForm/Steps/index.js index b91ba923da..f91485e363 100644 --- a/src/fireedge/src/client/components/Forms/Provision/CreateForm/Steps/index.js +++ b/src/fireedge/src/client/components/Forms/Provision/CreateForm/Steps/index.js @@ -24,7 +24,7 @@ const Steps = createSteps( [Template, Provider, BasicConfiguration, Inputs], { transformBeforeSubmit: formData => { - const { template, provider, configuration, inputs: dirtyInputs } = formData + const { template, provider, configuration, inputs } = formData const { name, description } = configuration const providerName = provider?.[0]?.NAME @@ -40,11 +40,15 @@ const Steps = createSteps( }) } - const parseInputs = mapUserInputs(dirtyInputs) - const inputs = provisionTemplateSelected?.inputs - ?.map(input => ({ ...input, value: `${parseInputs[input?.name]}` })) + const resolvedInputs = provisionTemplateSelected?.inputs + ?.map(input => ({ ...input, value: `${inputs[input?.name]}` })) - return { ...provisionTemplateSelected, name, description, inputs } + return { + ...provisionTemplateSelected, + name, + description, + inputs: resolvedInputs + } } } ) diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js index dc82f72033..b922acf581 100644 --- a/src/fireedge/src/client/constants/translates.js +++ b/src/fireedge/src/client/constants/translates.js @@ -603,6 +603,7 @@ module.exports = { Max: 'Max', DefaultValue: 'Default value', Mandatory: 'Mandatory', + PressKeysToAddAValue: 'Press any of the following keys to add a value: %s', /* Validation */ /* Validation - mixed */ diff --git a/src/fireedge/src/client/utils/schema.js b/src/fireedge/src/client/utils/schema.js index 9d115cd52a..fb12c2d591 100644 --- a/src/fireedge/src/client/utils/schema.js +++ b/src/fireedge/src/client/utils/schema.js @@ -23,7 +23,7 @@ import { string, number, boolean, array, object, BaseSchema } from 'yup' // eslint-disable-next-line no-unused-vars import { Row } from 'react-table' -import { UserInputObject, INPUT_TYPES, USER_INPUT_TYPES } from 'client/constants' +import { UserInputObject, T, INPUT_TYPES, USER_INPUT_TYPES } from 'client/constants' // ---------------------------------------------------------- // Types @@ -176,14 +176,14 @@ import { UserInputObject, INPUT_TYPES, USER_INPUT_TYPES } from 'client/constants // Constants // ---------------------------------------------------------- -const requiredSchema = (mandatory, name, schema) => - mandatory - ? schema.required(`${name} field is required`) - : schema.notRequired().nullable() +const SEMICOLON_CHAR = ';' + +const requiredSchema = (mandatory, schema) => + mandatory ? schema.required() : schema.notRequired().nullable() const getRange = options => options?.split('..').map(option => parseFloat(option)) -const getValuesFromArray = (options, separator = ';') => options?.split(separator) +const getValuesFromArray = (options, separator = SEMICOLON_CHAR) => options?.split(separator) const getOptionsFromList = options => options ?.map(option => typeof option === 'string' @@ -225,7 +225,7 @@ export const schemaUserInput = ({ mandatory, name, type, options, default: defau htmlType: type === 'password' ? 'password' : 'text', validation: string() .trim() - .concat(requiredSchema(mandatory, name, string())) + .concat(requiredSchema(mandatory, string())) .default(defaultValue || undefined) } case USER_INPUT_TYPES.number: @@ -233,8 +233,7 @@ export const schemaUserInput = ({ mandatory, name, type, options, default: defau type: INPUT_TYPES.TEXT, htmlType: 'number', validation: number() - .typeError(`${name} must be a number`) - .concat(requiredSchema(mandatory, name, number())) + .concat(requiredSchema(mandatory, number())) .transform(value => !isNaN(value) ? value : null) .default(() => parseFloat(defaultValue) ?? undefined) } @@ -245,10 +244,9 @@ export const schemaUserInput = ({ mandatory, name, type, options, default: defau return { type: INPUT_TYPES.SLIDER, validation: number() - .typeError(`${name} must be a number`) - .concat(requiredSchema(mandatory, name, number())) - .min(min, `${name} must be greater than or equal to ${min}`) - .max(max, `${name} must be less than or equal to ${max}`) + .concat(requiredSchema(mandatory, number())) + .min(min) + .max(max) .transform(value => !isNaN(value) ? value : undefined) .default(parseFloat(defaultValue) ?? undefined), fieldProps: { min, max, step: type === 'range-float' ? 0.01 : 1 } @@ -257,8 +255,9 @@ export const schemaUserInput = ({ mandatory, name, type, options, default: defau case USER_INPUT_TYPES.boolean: return { type: INPUT_TYPES.CHECKBOX, validation: boolean() - .concat(requiredSchema(mandatory, name, boolean())) + .concat(requiredSchema(mandatory, boolean())) .default(defaultValue === 'YES' ?? false) + .yesOrNo() } case USER_INPUT_TYPES.list: { const values = getOptionsFromList(options) @@ -269,9 +268,9 @@ export const schemaUserInput = ({ mandatory, name, type, options, default: defau type: INPUT_TYPES.SELECT, validation: string() .trim() - .concat(requiredSchema(mandatory, name, string())) + .concat(requiredSchema(mandatory, string())) .oneOf(values.map(({ value }) => value)) - .default(defaultValue || firstOption) + .default(() => defaultValue || firstOption) } } case USER_INPUT_TYPES.array: { @@ -280,10 +279,12 @@ export const schemaUserInput = ({ mandatory, name, type, options, default: defau return { type: INPUT_TYPES.AUTOCOMPLETE, multiple: true, + tooltip: [T.PressKeysToAddAValue, ['ENTER, semicolon (;)']], + fieldProps: { freeSolo: true, separators: [SEMICOLON_CHAR] }, validation: array(string().trim()) - .concat(requiredSchema(mandatory, name, array())) - .default(defaultValues), - fieldProps: { freeSolo: true } + .concat(requiredSchema(mandatory, array())) + .default(() => defaultValues) + .afterSubmit(value => value?.join(SEMICOLON_CHAR)) } } case USER_INPUT_TYPES.listMultiple: { @@ -295,7 +296,7 @@ export const schemaUserInput = ({ mandatory, name, type, options, default: defau type: INPUT_TYPES.SELECT, multiple: true, validation: array(string().trim()) - .concat(requiredSchema(mandatory, name, array())) + .concat(requiredSchema(mandatory, array())) .default(defaultValues) } } @@ -303,7 +304,7 @@ export const schemaUserInput = ({ mandatory, name, type, options, default: defau type: INPUT_TYPES.TEXT, validation: string() .trim() - .concat(requiredSchema(mandatory, name, string())) + .concat(requiredSchema(mandatory, string())) .default(defaultValue || undefined) } } diff --git a/src/fireedge/src/client/utils/translation.js b/src/fireedge/src/client/utils/translation.js index 7d669996d7..8e66820a6f 100644 --- a/src/fireedge/src/client/utils/translation.js +++ b/src/fireedge/src/client/utils/translation.js @@ -22,7 +22,10 @@ import { isDivisibleBy, isBase64 } from 'client/utils/helpers' const buildMethods = () => { [number, string, boolean, object, array, date].forEach(schemaType => { addMethod(schemaType, 'afterSubmit', function (fn) { - this.submit = (...args) => typeof fn === 'function' ? fn(...args) : args[0] + this._mutate = true // allows to mutate the initial schema + this.submit = (...args) => + typeof fn === 'function' ? fn(...args) : args[0] + return this }) addMethod(schemaType, 'cast', function (value, options = {}) {