From e6652586a5ce786b16f4e741054ebf48bc7b52d5 Mon Sep 17 00:00:00 2001 From: Sergio Betanzos Date: Thu, 18 Nov 2021 12:41:00 +0100 Subject: [PATCH] F #5422: Add form to create & update VM Templates (#1583) --- .../components/FormStepper/MobileStepper.js | 6 +- .../client/components/FormStepper/index.js | 2 +- .../Steps/AdvancedOptions/schema.js | 74 ++++++++--------- .../Steps/NetworksTable/index.js | 2 +- .../Steps/NetworksTable/schema.js | 12 +-- .../Forms/Vm/AttachNicForm/Steps/index.js | 4 +- .../ExtraConfiguration/booting/bootSchema.js | 10 +-- .../ExtraConfiguration/booting/rawSchema.js | 8 +- .../context/configurationSchema.js | 8 +- .../context/userInputsSchema.js | 12 ++- .../inputOutput/graphicsSchema.js | 16 ++-- .../ExtraConfiguration/inputOutput/index.js | 4 +- .../inputOutput/inputsSchema.js | 8 +- .../inputOutput/pciDevicesSchema.js | 8 +- .../ExtraConfiguration/inputOutput/schema.js | 20 ++--- .../Steps/General/capacitySchema.js | 16 +--- .../CreateForm/Steps/General/index.js | 33 +++++--- .../Steps/General/informationSchema.js | 21 +++-- .../CreateForm/Steps/General/schema.js | 5 +- .../VmTemplate/CreateForm/Steps/index.js | 59 +++++++------ .../src/client/components/HOC/Translate.js | 5 +- .../src/client/constants/translates.js | 7 ++ .../containers/Dashboard/Provision/index.js | 21 ++--- .../containers/Dashboard/Provision/styles.js | 24 ------ .../containers/Dashboard/Sunstone/index.js | 22 ++--- .../containers/Dashboard/Sunstone/styles.js | 24 ------ .../src/client/containers/Settings/index.js | 82 ++++++------------- .../src/client/containers/Settings/schema.js | 31 +++---- .../client/containers/VmTemplates/Create.js | 41 ++++++---- .../src/client/features/Auth/slice.js | 2 +- src/fireedge/src/client/utils/translation.js | 33 +++++++- 31 files changed, 279 insertions(+), 341 deletions(-) delete mode 100644 src/fireedge/src/client/containers/Dashboard/Provision/styles.js delete mode 100644 src/fireedge/src/client/containers/Dashboard/Sunstone/styles.js diff --git a/src/fireedge/src/client/components/FormStepper/MobileStepper.js b/src/fireedge/src/client/components/FormStepper/MobileStepper.js index 0918238277..202847b674 100644 --- a/src/fireedge/src/client/components/FormStepper/MobileStepper.js +++ b/src/fireedge/src/client/components/FormStepper/MobileStepper.js @@ -20,7 +20,7 @@ import { Button, MobileStepper, Typography, Box, alpha } from '@mui/material' import makeStyles from '@mui/styles/makeStyles' import { NavArrowLeft as PreviousIcon, NavArrowRight as NextIcon } from 'iconoir-react' -import { Tr, Translate, labelCanBeTranslated } from 'client/components/HOC' +import { Translate, labelCanBeTranslated } from 'client/components/HOC' import { T } from 'client/constants' const useStyles = makeStyles(theme => ({ @@ -61,8 +61,8 @@ const CustomMobileStepper = ({ {Boolean(errors[id]) && ( - {labelCanBeTranslated(errors[id]?.message) - ? Tr(errors[id]?.message) : errors[id]?.message} + {labelCanBeTranslated(label) + ? : errors[id]?.message} )} diff --git a/src/fireedge/src/client/components/FormStepper/index.js b/src/fireedge/src/client/components/FormStepper/index.js index b098622873..d02b39eaae 100644 --- a/src/fireedge/src/client/components/FormStepper/index.js +++ b/src/fireedge/src/client/components/FormStepper/index.js @@ -114,7 +114,7 @@ const FormStepper = ({ steps = [], schema, onSubmit }) => { if (activeStep === lastStep) { const submitData = { ...formData, [id]: data } - const schemaData = schema().cast(submitData, { context: submitData }) + const schemaData = schema().cast(submitData, { context: submitData, isSubmit: true }) onSubmit(schemaData) } else { setFormData(prev => ({ ...prev, [id]: data })) diff --git a/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/AdvancedOptions/schema.js b/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/AdvancedOptions/schema.js index adfdedbc37..5a389b8b18 100644 --- a/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/AdvancedOptions/schema.js +++ b/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/AdvancedOptions/schema.js @@ -13,45 +13,37 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -/* eslint-disable jsdoc/require-jsdoc */ -import * as yup from 'yup' +import { boolean, string, object, ObjectSchema } from 'yup' -import { getValidationFromFields } from 'client/utils' -import { INPUT_TYPES } from 'client/constants' +import { Field, getValidationFromFields } from 'client/utils' +import { T, INPUT_TYPES } from 'client/constants' +/** @type {Field} RDP connection field */ const RDP_FIELD = { name: 'RDP', - label: 'RDP connection', + label: T.RdpConnection, type: INPUT_TYPES.SWITCH, - validation: yup - .boolean() - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }) - .default(false), + validation: boolean().yesOrNo(), grid: { md: 12 } } +/** @type {Field} SSH connection field */ const SSH_FIELD = { name: 'SSH', - label: 'SSH connection', + label: T.SshConnection, type: INPUT_TYPES.SWITCH, - validation: yup - .boolean() - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }) - .default(false), + validation: boolean().yesOrNo(), grid: { md: 12 } } -const ALIAS_FIELD = ({ nics = [] } = {}) => ({ +/** + * @param {object} currentFormData - Current form data + * @param {object[]} currentFormData.nics - Nics + * @returns {Field} Alias field + */ +const ALIAS_FIELD = ({ nics = [] }) => ({ name: 'PARENT', - label: 'Attach as an alias', + label: T.AsAnAlias, dependOf: 'NAME', type: name => { const hasAlias = nics?.some(nic => nic.PARENT === name) @@ -70,35 +62,33 @@ const ALIAS_FIELD = ({ nics = [] } = {}) => ({ return { text, value: NAME } }) ], - validation: yup - .string() + validation: string() .trim() .notRequired() - .default(undefined) + .default(() => undefined) }) +/** @type {Field} External field */ const EXTERNAL_FIELD = { name: 'EXTERNAL', - label: 'External', + label: T.External, + tooltip: T.ExternalConcept, type: INPUT_TYPES.SWITCH, - tooltip: 'The NIC will be attached as an external alias of the VM', - dependOf: ALIAS_FIELD().name, - htmlType: type => !type?.length ? INPUT_TYPES.HIDDEN : undefined, - validation: yup - .boolean() - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }) - .default(false) + dependOf: 'PARENT', + htmlType: parent => !parent?.length && INPUT_TYPES.HIDDEN, + validation: boolean().yesOrNo() } -export const FIELDS = props => [ +/** + * @param {object} [currentFormData] - Current form data + * @returns {Field[]} List of Graphics fields + */ +export const FIELDS = (currentFormData = {}) => [ RDP_FIELD, SSH_FIELD, - ALIAS_FIELD(props), + ALIAS_FIELD(currentFormData), EXTERNAL_FIELD ] -export const SCHEMA = yup.object(getValidationFromFields(FIELDS())) +/** @type {ObjectSchema} Advanced options schema */ +export const SCHEMA = object(getValidationFromFields(FIELDS())) diff --git a/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/NetworksTable/index.js b/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/NetworksTable/index.js index 364c0b02ce..c57568e634 100644 --- a/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/NetworksTable/index.js +++ b/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/NetworksTable/index.js @@ -52,7 +52,7 @@ const Content = ({ data, setFormData }) => { const NetworkStep = () => ({ id: STEP_ID, - label: T.Network, + label: T.SelectNetwork, resolver: SCHEMA, content: Content }) diff --git a/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/NetworksTable/schema.js b/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/NetworksTable/schema.js index d1e3006421..6635419924 100644 --- a/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/NetworksTable/schema.js +++ b/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/NetworksTable/schema.js @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import * as yup from 'yup' +import { array, object, ArraySchema } from 'yup' -export const SCHEMA = yup - .array(yup.object()) - .min(1, 'Select network') - .max(1, 'Max. one network selected') - .required('Network field is required') +/** @type {ArraySchema} Virtual Network table schema */ +export const SCHEMA = array(object()) + .min(1) + .max(1) + .required() .ensure() .default(() => []) diff --git a/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/index.js b/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/index.js index 4622c823bf..e96b341a62 100644 --- a/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/index.js +++ b/src/fireedge/src/client/components/Forms/Vm/AttachNicForm/Steps/index.js @@ -15,7 +15,7 @@ * ------------------------------------------------------------------------- */ import NetworksTable, { STEP_ID as NETWORK_ID } from 'client/components/Forms/Vm/AttachNicForm/Steps/NetworksTable' import AdvancedOptions, { STEP_ID as ADVANCED_ID } from 'client/components/Forms/Vm/AttachNicForm/Steps/AdvancedOptions' -import { mapUserInputs, createSteps } from 'client/utils' +import { createSteps } from 'client/utils' const Steps = createSteps( [NetworksTable, AdvancedOptions], @@ -52,7 +52,7 @@ const Steps = createSteps( NETWORK_UID: UID, NETWORK_UNAME: UNAME, SECURITY_GROUPS, - ...mapUserInputs(advanced) + ...advanced } } } diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/booting/bootSchema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/booting/bootSchema.js index 0815e0280a..43aa082ce7 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/booting/bootSchema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/booting/bootSchema.js @@ -178,7 +178,7 @@ export const FIRMWARE = { grid: { md: 12 } } -/** @type {Field} Feature secure field */ +/** @type {Field} Firmware secure field */ export const FIRMWARE_SECURE = { name: 'OS.FIRMWARE_SECURE', label: T.FirmwareSecure, @@ -186,13 +186,7 @@ export const FIRMWARE_SECURE = { type: INPUT_TYPES.CHECKBOX, dependOf: FEATURE_CUSTOM_ENABLED.name, htmlType: custom => !custom && INPUT_TYPES.HIDDEN, - validation: boolean() - .default(() => false) - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }), + validation: boolean().yesOrNo(), grid: { md: 12 } } diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/booting/rawSchema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/booting/rawSchema.js index 5a48f0074e..de4a5a4f4a 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/booting/rawSchema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/booting/rawSchema.js @@ -54,13 +54,7 @@ const VALIDATE = { tooltip: T.RawValidateConcept, type: INPUT_TYPES.CHECKBOX, notOnHypervisors: [lxc, vcenter, firecracker], - validation: boolean() - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }) - .default(() => false), + validation: boolean().yesOrNo(), grid: { md: 12 } } diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/context/configurationSchema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/context/configurationSchema.js index a16c4215a1..fda6d05fda 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/context/configurationSchema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/context/configurationSchema.js @@ -20,13 +20,7 @@ import { Field, getObjectSchemaFromFields } from 'client/utils' const switchField = { type: INPUT_TYPES.SWITCH, - validation: boolean() - .notRequired() - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }), + validation: boolean().yesOrNo(), grid: { md: 12 } } diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/context/userInputsSchema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/context/userInputsSchema.js index 620feaf2f7..9b06354aa3 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/context/userInputsSchema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/context/userInputsSchema.js @@ -15,6 +15,7 @@ * ------------------------------------------------------------------------- */ import { object, array, string, boolean, number, ref, ObjectSchema } from 'yup' +import { userInputsToObject } from 'client/models/Helper' import { UserInputType, T, INPUT_TYPES, USER_INPUT_TYPES } from 'client/constants' import { Field, arrayToOptions, sentenceCase, getObjectSchemaFromFields } from 'client/utils' @@ -183,6 +184,13 @@ export const USER_INPUT_SCHEMA = getObjectSchemaFromFields(USER_INPUT_FIELDS) /** @type {ObjectSchema} User Inputs schema */ export const USER_INPUTS_SCHEMA = object({ - USER_INPUTS: array(USER_INPUT_SCHEMA).ensure(), - INPUTS_ORDER: string().trim().strip() + USER_INPUTS: array(USER_INPUT_SCHEMA) + .ensure() + .afterSubmit(userInputs => userInputsToObject(userInputs)), + INPUTS_ORDER: string() + .trim() + .afterSubmit((_, { context }) => { + const userInputs = context?.extra?.USER_INPUTS + return userInputs?.map(({ name }) => name).join(',') + }) }) diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/graphicsSchema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/graphicsSchema.js index a542f89127..166bbab5a1 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/graphicsSchema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/graphicsSchema.js @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { string, boolean } from 'yup' +import { string, boolean, ObjectSchema } from 'yup' -import { Field, arrayToOptions, filterFieldsByHypervisor } from 'client/utils' +import { Field, arrayToOptions, filterFieldsByHypervisor, getObjectSchemaFromFields } from 'client/utils' import { T, INPUT_TYPES, HYPERVISORS } from 'client/constants' const { vcenter, lxc, kvm } = HYPERVISORS @@ -90,13 +90,7 @@ const RANDOM_PASSWD = { type: INPUT_TYPES.CHECKBOX, dependOf: TYPE.name, htmlType: noneType => !noneType && INPUT_TYPES.HIDDEN, - validation: boolean() - .default(() => false) - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }), + validation: boolean().yesOrNo(), grid: { md: 12 } } @@ -139,3 +133,7 @@ export const GRAPHICS_FIELDS = hypervisor => [TYPE, LISTEN, PORT, KEYMAP, PASSWD, RANDOM_PASSWD, COMMAND], hypervisor ) + +/** @type {ObjectSchema} Context Files schema */ +export const GRAPHICS_SCHEMA = hypervisor => + getObjectSchemaFromFields(GRAPHICS_FIELDS(hypervisor)) diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/index.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/index.js index 1b8a28d6fc..ce23c8d923 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/index.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/index.js @@ -23,7 +23,7 @@ import { FormWithSchema } from 'client/components/Forms' import { STEP_ID as EXTRA_ID, TabType } from 'client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration' import InputsSection, { SECTION_ID as INPUT_ID } from './inputsSection' import PciDevicesSection, { SECTION_ID as PCI_ID } from './pciDevicesSection' -import { INPUT_OUTPUT_FIELDS, INPUTS_FIELDS, PCI_FIELDS } from './schema' +import { GRAPHICS_FIELDS, INPUTS_FIELDS, PCI_FIELDS } from './schema' import { T } from 'client/constants' export const TAB_ID = ['GRAPHICS', INPUT_ID, PCI_ID] @@ -40,7 +40,7 @@ const InputOutput = ({ hypervisor }) => { > diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/inputsSchema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/inputsSchema.js index 678e478e14..3e43efe27d 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/inputsSchema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/inputsSchema.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { string, array, object, ObjectSchema, ArraySchema } from 'yup' +import { string, array, object, ObjectSchema } from 'yup' import { PcMouse, PenTablet, Usb, PlugTypeG } from 'iconoir-react' import { Field, arrayToOptions, filterFieldsByHypervisor, getValidationFromFields } from 'client/utils' @@ -69,5 +69,7 @@ export const INPUTS_FIELDS = (hypervisor) => /** @type {ObjectSchema} Graphic input object schema */ export const INPUT_SCHEMA = object(getValidationFromFields([TYPE, BUS])) -/** @type {ArraySchema} Graphic inputs schema */ -export const INPUTS_SCHEMA = array(INPUT_SCHEMA).ensure() +/** @type {ObjectSchema} Graphic inputs schema */ +export const INPUTS_SCHEMA = object({ + INPUT: array(INPUT_SCHEMA).ensure() +}) diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/pciDevicesSchema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/pciDevicesSchema.js index 76b55cdb1e..51c4bcf5ec 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/pciDevicesSchema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/pciDevicesSchema.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { string, array, ObjectSchema, ArraySchema } from 'yup' +import { object, string, array, ObjectSchema } from 'yup' import { useHost } from 'client/features/One' import { getPciDevices } from 'client/models/Host' @@ -88,5 +88,7 @@ export const PCI_FIELDS = (hypervisor) => /** @type {ObjectSchema} PCI devices object schema */ export const PCI_SCHEMA = getObjectSchemaFromFields([DEVICE, VENDOR, CLASS]) -/** @type {ArraySchema} PCI devices schema */ -export const PCI_DEVICES_SCHEMA = array(PCI_SCHEMA).ensure() +/** @type {ObjectSchema} PCI devices schema */ +export const PCI_DEVICES_SCHEMA = object({ + PCI: array(PCI_SCHEMA).ensure() +}) diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/schema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/schema.js index 0098e85c09..48cefcb0ec 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/schema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration/inputOutput/schema.js @@ -15,28 +15,18 @@ * ------------------------------------------------------------------------- */ import { object, ObjectSchema } from 'yup' -import { GRAPHICS_FIELDS } from './graphicsSchema' +import { GRAPHICS_SCHEMA } from './graphicsSchema' import { INPUTS_SCHEMA } from './inputsSchema' import { PCI_DEVICES_SCHEMA } from './pciDevicesSchema' -import { Field, getObjectSchemaFromFields } from 'client/utils' - -/** - * @param {string} [hypervisor] - VM hypervisor - * @returns {Field[]} List of I/O fields - */ -export const INPUT_OUTPUT_FIELDS = hypervisor => - [...GRAPHICS_FIELDS(hypervisor)] /** * @param {string} [hypervisor] - VM hypervisor * @returns {ObjectSchema} I/O schema */ -export const SCHEMA = hypervisor => object({ - INPUT: INPUTS_SCHEMA, - PCI: PCI_DEVICES_SCHEMA -}).concat(getObjectSchemaFromFields([ - ...GRAPHICS_FIELDS(hypervisor) -])) +export const SCHEMA = hypervisor => object() + .concat(INPUTS_SCHEMA) + .concat(PCI_DEVICES_SCHEMA) + .concat(GRAPHICS_SCHEMA(hypervisor)) export * from './graphicsSchema' export * from './inputsSchema' diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/capacitySchema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/capacitySchema.js index 014b479631..5a0fd9bb2a 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/capacitySchema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/capacitySchema.js @@ -43,13 +43,7 @@ export const ENABLE_HR_MEMORY = { name: 'HOT_RESIZE.MEMORY_HOT_ADD_ENABLED', label: T.EnableHotResize, type: INPUT_TYPES.SWITCH, - validation: boolean() - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }) - .default(() => false), + validation: boolean().yesOrNo(), grid: { xs: 4, md: 6 } } @@ -94,13 +88,7 @@ export const ENABLE_HR_VCPU = { name: 'HOT_RESIZE.CPU_HOT_ADD_ENABLED', label: T.EnableHotResize, type: INPUT_TYPES.SWITCH, - validation: boolean() - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }) - .default(() => false), + validation: boolean().yesOrNo(), grid: { xs: 4, md: 6 } } diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/index.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/index.js index 854a22d056..86aa231678 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/index.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/index.js @@ -15,6 +15,7 @@ * ------------------------------------------------------------------------- */ /* eslint-disable jsdoc/require-jsdoc */ import { useMemo } from 'react' +import PropTypes from 'prop-types' import { useWatch } from 'react-hook-form' import { useAuth } from 'client/features/Auth' @@ -28,7 +29,7 @@ import { T } from 'client/constants' export const STEP_ID = 'general' -const Content = () => { +const Content = ({ isUpdate }) => { const classes = useStyles() const { view, getResourceView } = useAuth() const hypervisor = useWatch({ name: `${STEP_ID}.HYPERVISOR` }) @@ -37,7 +38,7 @@ const Content = () => { const dialog = getResourceView('VM-TEMPLATE')?.dialogs?.create_dialog const sectionsAvailable = getSectionsAvailable(dialog, hypervisor) - return SECTIONS(hypervisor) + return SECTIONS(hypervisor, isUpdate) .filter(({ id, required }) => required || sectionsAvailable.includes(id)) }, [view, hypervisor]) @@ -62,15 +63,23 @@ const Content = () => { ) } -const General = () => ({ - id: STEP_ID, - label: T.General, - resolver: formData => { - const hypervisor = formData?.[STEP_ID]?.HYPERVISOR - return SCHEMA(hypervisor) - }, - optionsValidate: { abortEarly: false }, - content: Content -}) +const General = initialValues => { + const isUpdate = initialValues?.NAME + + return { + id: STEP_ID, + label: T.General, + resolver: formData => { + const hypervisor = formData?.[STEP_ID]?.HYPERVISOR + return SCHEMA(hypervisor, isUpdate) + }, + optionsValidate: { abortEarly: false }, + content: () => Content({ isUpdate }) + } +} + +Content.propTypes = { + isUpdate: PropTypes.bool +} export default General diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/informationSchema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/informationSchema.js index 5684c1d7d5..33467c6e29 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/informationSchema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/informationSchema.js @@ -19,8 +19,11 @@ import Image from 'client/components/Image' import { T, LOGO_IMAGES_URL, INPUT_TYPES, HYPERVISORS } from 'client/constants' import { Field, arrayToOptions } from 'client/utils' -/** @type {Field} Name field */ -export const NAME = { +/** + * @param {boolean} isUpdate - If `true`, the form is being updated + * @returns {Field} Name field + */ +export const NAME = isUpdate => ({ name: 'NAME', label: T.Name, type: INPUT_TYPES.TEXT, @@ -28,8 +31,9 @@ export const NAME = { .trim() .required() .default(() => undefined), - grid: { sm: 6 } -} + grid: { sm: 6 }, + ...(isUpdate && { fieldProps: { disabled: true } }) +}) /** @type {Field} Description field */ export const DESCRIPTION = { @@ -100,9 +104,12 @@ export const LOGO = { .default(() => undefined) } -/** @type {Field[]} List of information fields */ -export const FIELDS = [ - NAME, +/** + * @param {boolean} isUpdate - If `true`, the form is being updated + * @returns {Field[]} List of information fields + */ +export const FIELDS = isUpdate => [ + NAME(isUpdate), DESCRIPTION, LOGO ] diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/schema.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/schema.js index 7580215973..b810c73db4 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/schema.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/General/schema.js @@ -26,14 +26,15 @@ import { T, HYPERVISORS } from 'client/constants' /** * @param {HYPERVISORS} [hypervisor] - Template hypervisor + * @param {boolean} [isUpdate] - If `true`, the form is being updated * @returns {Section[]} Fields */ -const SECTIONS = hypervisor => [ +const SECTIONS = (hypervisor, isUpdate) => [ { id: 'information', legend: T.Information, required: true, - fields: filterFieldsByHypervisor(INFORMATION_FIELDS, hypervisor) + fields: filterFieldsByHypervisor(INFORMATION_FIELDS(isUpdate), hypervisor) }, { id: 'capacity', diff --git a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/index.js b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/index.js index e63aea4590..c4dc093376 100644 --- a/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/index.js +++ b/src/fireedge/src/client/components/Forms/VmTemplate/CreateForm/Steps/index.js @@ -15,37 +15,43 @@ * ------------------------------------------------------------------------- */ import General, { STEP_ID as GENERAL_ID } from 'client/components/Forms/VmTemplate/CreateForm/Steps/General' import ExtraConfiguration, { STEP_ID as EXTRA_ID } from 'client/components/Forms/VmTemplate/CreateForm/Steps/ExtraConfiguration' -// import { jsonToXml } from 'client/models/Helper' -import { userInputsToArray, userInputsToObject } from 'client/models/Helper' +import { jsonToXml, userInputsToArray } from 'client/models/Helper' import { createSteps, isBase64 } from 'client/utils' const Steps = createSteps( [General, ExtraConfiguration], { - transformInitialValue: (vmTemplate, schema) => ({ - ...schema.pick([GENERAL_ID]).cast({ - [GENERAL_ID]: { ...vmTemplate, ...vmTemplate?.TEMPLATE } - }, { stripUnknown: true }), - ...schema.pick([EXTRA_ID]).cast({ - [EXTRA_ID]: { - ...vmTemplate?.TEMPLATE, - USER_INPUTS: userInputsToArray(vmTemplate?.TEMPLATE?.USER_INPUTS) - } - }, { stripUnknown: true, context: { [EXTRA_ID]: vmTemplate.TEMPLATE } }) - }), + transformInitialValue: (vmTemplate, schema) => { + const generalStep = schema + .pick([GENERAL_ID]) + .cast( + { [GENERAL_ID]: { ...vmTemplate, ...vmTemplate?.TEMPLATE } }, + { stripUnknown: true } + ) + + const inputsOrder = vmTemplate?.TEMPLATE?.INPUTS_ORDER?.split(',') ?? [] + const userInputs = userInputsToArray(vmTemplate?.TEMPLATE?.USER_INPUTS) + .sort((a, b) => inputsOrder.indexOf(a.name) - inputsOrder.indexOf(b.name)) + + const configurationStep = schema + .pick([EXTRA_ID]) + .cast( + { [EXTRA_ID]: { ...vmTemplate?.TEMPLATE, USER_INPUTS: userInputs } }, + { stripUnknown: true, context: { [EXTRA_ID]: vmTemplate.TEMPLATE } } + ) + + return { ...generalStep, ...configurationStep } + }, transformBeforeSubmit: formData => { const { [GENERAL_ID]: general = {}, - [EXTRA_ID]: { USER_INPUTS, CONTEXT, ...extraTemplate } = {} + [EXTRA_ID]: { + USER_INPUTS, + CONTEXT: { START_SCRIPT, ENCODE_START_SCRIPT, ...restOfContext }, + ...extraTemplate + } = {} } = formData ?? {} - // const templateXML = jsonToXml({ ...general, ...extraTemplate }) - // return { template: templateXML } - - const userInputs = userInputsToObject(USER_INPUTS) - const inputsOrder = USER_INPUTS.map(({ name }) => name).join(',') - const { START_SCRIPT, ENCODE_START_SCRIPT, ...restOfContext } = CONTEXT - const context = { ...restOfContext, // transform start script to base64 if needed @@ -56,18 +62,17 @@ const Steps = createSteps( } // add user inputs to context - for (const { name } of USER_INPUTS) { + const userInputsNames = Object.keys(USER_INPUTS).forEach(name => { const upperName = String(name).toUpperCase() context[upperName] = `$${upperName}` - } + }) - return { + return jsonToXml({ ...extraTemplate, ...general, CONTEXT: context, - USER_INPUTS: userInputs, - INPUTS_ORDER: inputsOrder - } + USER_INPUTS: USER_INPUTS + }) } } ) diff --git a/src/fireedge/src/client/components/HOC/Translate.js b/src/fireedge/src/client/components/HOC/Translate.js index 725c83d7d3..2b04292696 100644 --- a/src/fireedge/src/client/components/HOC/Translate.js +++ b/src/fireedge/src/client/components/HOC/Translate.js @@ -126,7 +126,10 @@ TranslateProvider.propTypes = { } Translate.propTypes = { - word: PropTypes.string, + word: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.array + ]), values: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js index 8fc1b5f34e..676009572f 100644 --- a/src/fireedge/src/client/constants/translates.js +++ b/src/fireedge/src/client/constants/translates.js @@ -102,6 +102,7 @@ module.exports = { Select: 'Select', SelectGroup: 'Select a group', SelectHost: 'Select a host', + SelectNetwork: 'Select a network', SelectRequest: 'Select request', SelectVmTemplate: 'Select a VM Template', Share: 'Share', @@ -212,6 +213,7 @@ module.exports = { System: 'System', Language: 'Language', DisableDashboardAnimations: 'Disable dashboard animations', + ConfigurationUI: 'Configuration UI', /* sections - system */ User: 'User', @@ -346,6 +348,11 @@ module.exports = { /* VM schema - network */ NIC: 'NIC', Alias: 'Alias', + AsAnAlias: 'Attach as an alias', + RdpConnection: 'RDP connection', + SshConnection: 'SSH connection', + External: 'External', + ExternalConcept: 'The NIC will be attached as an external alias of the VM', /* VM Template schema */ /* VM schema - general */ diff --git a/src/fireedge/src/client/containers/Dashboard/Provision/index.js b/src/fireedge/src/client/containers/Dashboard/Provision/index.js index bba82d101e..bfced84e58 100644 --- a/src/fireedge/src/client/containers/Dashboard/Provision/index.js +++ b/src/fireedge/src/client/containers/Dashboard/Provision/index.js @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -/* eslint-disable jsdoc/require-jsdoc */ -import { useEffect } from 'react' +import { useEffect, JSXElementConstructor } from 'react' import { Container, Box, Grid } from '@mui/material' import { useAuth } from 'client/features/Auth' import { useFetchAll } from 'client/hooks' import { useProvisionApi, useProviderApi } from 'client/features/One' import * as Widgets from 'client/components/Widgets' -import dashboardStyles from 'client/containers/Dashboard/Provision/styles' +import { stringToBoolean } from 'client/models/Helper' -function Dashboard () { +/** @returns {JSXElementConstructor} Provision dashboard container */ +function ProvisionDashboard () { const { status, fetchRequestAll, STATUS } = useFetchAll() const { INIT, PENDING } = STATUS @@ -31,9 +31,6 @@ function Dashboard () { const { getProviders } = useProviderApi() const { settings: { disableanimations } = {} } = useAuth() - const classes = dashboardStyles({ disableanimations }) - - const withoutAnimations = String(disableanimations).toUpperCase() === 'YES' useEffect(() => { fetchRequestAll([ @@ -45,8 +42,12 @@ function Dashboard () { return ( @@ -72,4 +73,4 @@ function Dashboard () { ) } -export default Dashboard +export default ProvisionDashboard diff --git a/src/fireedge/src/client/containers/Dashboard/Provision/styles.js b/src/fireedge/src/client/containers/Dashboard/Provision/styles.js deleted file mode 100644 index 2eebec104a..0000000000 --- a/src/fireedge/src/client/containers/Dashboard/Provision/styles.js +++ /dev/null @@ -1,24 +0,0 @@ -/* ------------------------------------------------------------------------- * - * Copyright 2002-2021, OpenNebula Project, OpenNebula Systems * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); you may * - * not use this file except in compliance with the License. You may obtain * - * a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - * ------------------------------------------------------------------------- */ -import makeStyles from '@mui/styles/makeStyles' - -export default makeStyles({ - withoutAnimations: { - '& *, & *::before, & *::after': { - animation: 'none !important' - } - } -}) diff --git a/src/fireedge/src/client/containers/Dashboard/Sunstone/index.js b/src/fireedge/src/client/containers/Dashboard/Sunstone/index.js index 84784b3711..d9eadb94c0 100644 --- a/src/fireedge/src/client/containers/Dashboard/Sunstone/index.js +++ b/src/fireedge/src/client/containers/Dashboard/Sunstone/index.js @@ -13,18 +13,17 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -/* eslint-disable jsdoc/require-jsdoc */ -import { useEffect } from 'react' +import { useEffect, JSXElementConstructor } from 'react' import { Container, Box, Grid } from '@mui/material' import { useAuth } from 'client/features/Auth' import { useFetchAll } from 'client/hooks' import { useUserApi, useImageApi, useVNetworkApi, useDatastoreApi } from 'client/features/One' - import * as Widgets from 'client/components/Widgets' -import dashboardStyles from 'client/containers/Dashboard/Provision/styles' +import { stringToBoolean } from 'client/models/Helper' -function Dashboard () { +/** @returns {JSXElementConstructor} Sunstone dashboard container */ +function SunstoneDashboard () { const { status, fetchRequestAll, STATUS } = useFetchAll() const { INIT, PENDING } = STATUS @@ -34,9 +33,6 @@ function Dashboard () { const { getDatastores } = useDatastoreApi() const { settings: { disableanimations } = {} } = useAuth() - const classes = dashboardStyles({ disableanimations }) - - const withoutAnimations = String(disableanimations).toUpperCase() === 'YES' useEffect(() => { fetchRequestAll([ @@ -50,8 +46,12 @@ function Dashboard () { return ( @@ -67,4 +67,4 @@ function Dashboard () { ) } -export default Dashboard +export default SunstoneDashboard diff --git a/src/fireedge/src/client/containers/Dashboard/Sunstone/styles.js b/src/fireedge/src/client/containers/Dashboard/Sunstone/styles.js deleted file mode 100644 index 2eebec104a..0000000000 --- a/src/fireedge/src/client/containers/Dashboard/Sunstone/styles.js +++ /dev/null @@ -1,24 +0,0 @@ -/* ------------------------------------------------------------------------- * - * Copyright 2002-2021, OpenNebula Project, OpenNebula Systems * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); you may * - * not use this file except in compliance with the License. You may obtain * - * a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - * ------------------------------------------------------------------------- */ -import makeStyles from '@mui/styles/makeStyles' - -export default makeStyles({ - withoutAnimations: { - '& *, & *::before, & *::after': { - animation: 'none !important' - } - } -}) diff --git a/src/fireedge/src/client/containers/Settings/index.js b/src/fireedge/src/client/containers/Settings/index.js index 80d7294928..fdf34f0f42 100644 --- a/src/fireedge/src/client/containers/Settings/index.js +++ b/src/fireedge/src/client/containers/Settings/index.js @@ -13,12 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -/* eslint-disable jsdoc/require-jsdoc */ -import { useEffect } from 'react' - -import { Container, Paper, Box, Typography } from '@mui/material' -import makeStyles from '@mui/styles/makeStyles' - +import { JSXElementConstructor } from 'react' +import { Container, Paper, Box, Typography, Divider } from '@mui/material' import { useForm, FormProvider } from 'react-hook-form' import { yupResolver } from '@hookform/resolvers/yup' @@ -28,38 +24,14 @@ import SubmitButton from 'client/components/FormControl/SubmitButton' import { useAuth, useAuthApi } from 'client/features/Auth' import { useUserApi } from 'client/features/One' import { useGeneralApi } from 'client/features/General' -import { Tr } from 'client/components/HOC' +import { Translate, Tr } from 'client/components/HOC' import { T } from 'client/constants' import { FORM_FIELDS, FORM_SCHEMA } from 'client/containers/Settings/schema' -import { mapUserInputs } from 'client/utils' import * as Helper from 'client/models/Helper' -const useStyles = makeStyles(theme => ({ - header: { - paddingTop: '1rem' - }, - title: { - flexGrow: 1, - letterSpacing: 0.1, - fontWeight: 500 - }, - wrapper: { - backgroundColor: theme.palette.background.default, - maxWidth: 550, - padding: '1rem' - }, - subheader: { - marginBottom: '1rem' - }, - actions: { - padding: '1rem 0', - textAlign: 'end' - } -})) - +/** @returns {JSXElementConstructor} Settings container */ const Settings = () => { - const classes = useStyles() const { user, settings } = useAuth() const { getAuthUser } = useAuthApi() const { updateUser } = useUserApi() @@ -67,47 +39,43 @@ const Settings = () => { const { handleSubmit, setError, reset, formState, ...methods } = useForm({ reValidateMode: 'onSubmit', - defaultValues: settings, + defaultValues: FORM_SCHEMA.cast(settings), resolver: yupResolver(FORM_SCHEMA) }) - useEffect(() => { - reset( - FORM_SCHEMA.cast(settings), - { keepIsSubmitted: false, keepErrors: false } - ) - }, [settings]) - const onSubmit = async dataForm => { try { - const inputs = mapUserInputs(dataForm) - const template = Helper.jsonToXml({ FIREEDGE: inputs }) - + const template = Helper.jsonToXml({ FIREEDGE: dataForm }) await updateUser(user.ID, { template }).then(getAuthUser) } catch { - enqueueError(Tr(T.SomethingWrong)) + enqueueError(T.SomethingWrong) } } return ( -
- - {Tr(T.Settings)} - -
+ + + -
+ - - - {`${Tr(T.Configuration)} UI`} - + - + -
+ { disabled={!formState.isDirty} isSubmitting={formState.isSubmitting} /> -
+
diff --git a/src/fireedge/src/client/containers/Settings/schema.js b/src/fireedge/src/client/containers/Settings/schema.js index a32fbc8c72..19a5af83fd 100644 --- a/src/fireedge/src/client/containers/Settings/schema.js +++ b/src/fireedge/src/client/containers/Settings/schema.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import * as yup from 'yup' +import { object, boolean, string } from 'yup' import { T, INPUT_TYPES, SCHEMES, DEFAULT_SCHEME, DEFAULT_LANGUAGE } from 'client/constants' import { getValidationFromFields } from 'client/utils' @@ -26,11 +26,10 @@ const SCHEME = { { text: T.Dark, value: SCHEMES.DARK }, { text: T.Light, value: SCHEMES.LIGHT } ], - validation: yup - .string() + validation: string() .trim() - .required('Scheme field is required') - .default(DEFAULT_SCHEME), + .required() + .default(() => DEFAULT_SCHEME), grid: { md: 12 } } @@ -40,11 +39,10 @@ const LANGUAGES = { type: INPUT_TYPES.SELECT, values: () => window?.langs?.map(({ key, value }) => ({ text: value, value: key })) ?? [], - validation: yup - .string() + validation: string() .trim() - .required('Language field is required') - .default(DEFAULT_LANGUAGE), + .required() + .default(() => DEFAULT_LANGUAGE), grid: { md: 12 } } @@ -52,19 +50,12 @@ const DISABLE_ANIMATIONS = { name: 'disableanimations', label: T.DisableDashboardAnimations, type: INPUT_TYPES.CHECKBOX, - validation: yup - .boolean() - .transform(value => { - if (typeof value === 'boolean') return value - - return String(value).toUpperCase() === 'YES' - }) - .default(false), + validation: boolean() + .yesOrNo() + .default(() => false), grid: { md: 12 } } export const FORM_FIELDS = [SCHEME, LANGUAGES, DISABLE_ANIMATIONS] -export const FORM_SCHEMA = yup.object( - getValidationFromFields(FORM_FIELDS) -) +export const FORM_SCHEMA = object(getValidationFromFields(FORM_FIELDS)) diff --git a/src/fireedge/src/client/containers/VmTemplates/Create.js b/src/fireedge/src/client/containers/VmTemplates/Create.js index a8779887a2..c8028a5d2a 100644 --- a/src/fireedge/src/client/containers/VmTemplates/Create.js +++ b/src/fireedge/src/client/containers/VmTemplates/Create.js @@ -13,32 +13,39 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -/* eslint-disable jsdoc/require-jsdoc */ -import { /* useHistory, */ useLocation } from 'react-router' +import { JSXElementConstructor } from 'react' +import { useHistory, useLocation } from 'react-router' import { Container } from '@mui/material' -// import { useGeneralApi } from 'client/features/General' -// import { useVmTemplateApi } from 'client/features/One' +import { useGeneralApi } from 'client/features/General' +import { useVmTemplateApi } from 'client/features/One' import { CreateForm } from 'client/components/Forms/VmTemplate' -// import { PATH } from 'client/apps/sunstone/routesOne' +import { PATH } from 'client/apps/sunstone/routesOne' import { isDevelopment } from 'client/utils' +/** + * Displays the creation or modification form to a VM Template. + * + * @returns {JSXElementConstructor} VM Template form + */ function CreateVmTemplate () { - // const history = useHistory() - const { state: { ID: templateId } = {} } = useLocation() + const history = useHistory() + const { state: { ID: templateId, NAME } = {} } = useLocation() - // const { enqueueInfo } = useGeneralApi() - // const { instantiate } = useVmTemplateApi() + const { enqueueSuccess } = useGeneralApi() + const { update, allocate } = useVmTemplateApi() - const onSubmit = async formData => { + const onSubmit = async template => { try { - console.log({ formData }) - /* const { ID, NAME } = templateSelected - - await Promise.all(templates.map(template => instantiate(ID, template))) - - history.push(templateId ? PATH.TEMPLATE.VMS.LIST : PATH.INSTANCE.VMS.LIST) - enqueueInfo(`VM Template instantiated x${templates.length} - #${ID} ${NAME}`) */ + if (templateId === undefined) { + await allocate(template) + history.push(PATH.TEMPLATE.VMS.LIST) + enqueueSuccess(`VM Template created - #${templateId}`) + } else { + await update(templateId, template) + history.push(PATH.TEMPLATE.VMS.LIST) + enqueueSuccess(`VM Template updated - #${templateId} ${NAME}`) + } } catch (err) { isDevelopment() && console.error(err) } diff --git a/src/fireedge/src/client/features/Auth/slice.js b/src/fireedge/src/client/features/Auth/slice.js index 51a0c95cab..00fc1b14f1 100644 --- a/src/fireedge/src/client/features/Auth/slice.js +++ b/src/fireedge/src/client/features/Auth/slice.js @@ -33,7 +33,7 @@ const initial = () => ({ settings: { scheme: DEFAULT_SCHEME, lang: DEFAULT_LANGUAGE, - disableAnimations: 'NO' + disableanimations: 'NO' }, isLoginInProgress: false, isLoading: false diff --git a/src/fireedge/src/client/utils/translation.js b/src/fireedge/src/client/utils/translation.js index d02bf7944a..7d669996d7 100644 --- a/src/fireedge/src/client/utils/translation.js +++ b/src/fireedge/src/client/utils/translation.js @@ -14,14 +14,41 @@ * limitations under the License. * * ------------------------------------------------------------------------- */ -/* eslint-disable react/display-name */ -/* eslint-disable react/prop-types */ -import { setLocale, addMethod, number, string } from 'yup' +import { setLocale, addMethod, number, string, boolean, object, array, date } from 'yup' import { T } from 'client/constants' 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] + return this + }) + addMethod(schemaType, 'cast', function (value, options = {}) { + const resolvedSchema = this.resolve({ value, ...options }) + let result = resolvedSchema._cast(value, options) + + if (options.isSubmit) { + result = this.submit?.(result, options) ?? result + } + + return result + }) + }) + addMethod(boolean, 'yesOrNo', function (addAfterSubmit = true) { + const schema = this.transform(function (value) { + return !this.isType(value) + ? String(value).toUpperCase() === 'YES' + : value + }) + + if (addAfterSubmit) { + schema.afterSubmit(value => value ? 'YES' : 'NO') + } + + return schema + }) addMethod(number, 'isDivisibleBy', function (divisor) { return this.test( 'is-divisible',