From 85acc4b703882868101ecb59ea5a57b9391a498b Mon Sep 17 00:00:00 2001 From: Sergio Betanzos Date: Fri, 9 Apr 2021 14:47:10 +0200 Subject: [PATCH] F #3951: Add support to on-premise provisions (#1085) --- .../client/components/FormStepper/index.js | 11 ++--- .../src/client/constants/provision.js | 4 ++ .../Form/Create/Steps/Template/index.js | 38 ++++++++++------ .../containers/Providers/Form/Create/index.js | 2 +- .../containers/Providers/Sections/info.js | 44 ++++++++++--------- .../Form/Create/Steps/Template/index.js | 27 +++++++----- .../src/client/models/ProviderTemplate.js | 3 +- src/fireedge/src/client/types/provision.js | 9 +++- .../server/routes/api/provision/schemas.js | 2 +- 9 files changed, 86 insertions(+), 54 deletions(-) diff --git a/src/fireedge/src/client/components/FormStepper/index.js b/src/fireedge/src/client/components/FormStepper/index.js index b2adc7e240..082f4c26b9 100644 --- a/src/fireedge/src/client/components/FormStepper/index.js +++ b/src/fireedge/src/client/components/FormStepper/index.js @@ -14,7 +14,7 @@ const FIRST_STEP = 0 const FormStepper = ({ steps, schema, onSubmit }) => { const isMobile = useMediaQuery(theme => theme.breakpoints.only('xs')) const { watch, reset, errors, setError } = useFormContext() - const { isLoading } = useGeneral() + const { isLoading, changeLoading } = useGeneral() const [formData, setFormData] = useState(() => watch()) const [activeStep, setActiveStep] = useState(FIRST_STEP) @@ -37,15 +37,16 @@ const FormStepper = ({ steps, schema, onSubmit }) => { .then(() => ({ id, data: stepData })) } - const setErrors = ({ inner: errors, ...rest }) => { + const setErrors = ({ inner: errors = [], ...rest }) => { + changeLoading(false) const errorsByPath = groupBy(errors, 'path') ?? {} const totalErrors = Object.keys(errorsByPath).length totalErrors > 0 ? setError(id, { - type: 'manual', - message: `${totalErrors} error(s) occurred` - }) + type: 'manual', + message: `${totalErrors} error(s) occurred` + }) : setError(id, rest) errors?.forEach(({ path, type, message }) => diff --git a/src/fireedge/src/client/constants/provision.js b/src/fireedge/src/client/constants/provision.js index 5f68de122f..c3dc48ee46 100644 --- a/src/fireedge/src/client/constants/provision.js +++ b/src/fireedge/src/client/constants/provision.js @@ -42,5 +42,9 @@ export const PROVIDERS_TYPES = [ { name: 'packet', color: '#364562' + }, + { + name: 'dummy', + color: '#436637' } ] diff --git a/src/fireedge/src/client/containers/Providers/Form/Create/Steps/Template/index.js b/src/fireedge/src/client/containers/Providers/Form/Create/Steps/Template/index.js index 4d16335d5f..880c9bcdc0 100644 --- a/src/fireedge/src/client/containers/Providers/Form/Create/Steps/Template/index.js +++ b/src/fireedge/src/client/containers/Providers/Form/Create/Steps/Template/index.js @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react' +import React, { useCallback, useEffect } from 'react' import { Divider, Select, Breadcrumbs } from '@material-ui/core' import ArrowIcon from '@material-ui/icons/ArrowForwardIosRounded' import Marked from 'marked' @@ -22,16 +22,25 @@ const Template = () => ({ resolver: () => STEP_FORM_SCHEMA, content: useCallback( ({ data, setFormData }) => { + const { provisionsTemplates } = useProvision() + const templateSelected = data?.[0] - const [provisionSelected, setProvision] = React.useState(() => templateSelected?.plain?.provision_type) + const [provisionSelected, setProvision] = React.useState( + () => templateSelected?.plain?.provision_type ?? Object.keys(provisionsTemplates)?.[0] + ) + const [providerSelected, setProvider] = React.useState(() => templateSelected?.provider) - const { provisionsTemplates } = useProvision() - const provisionSelectedDescription = provisionsTemplates?.[provisionSelected]?.description const providersTypes = provisionsTemplates?.[provisionSelected]?.providers ?? [] + const provisionSelectedDescription = provisionsTemplates?.[provisionSelected]?.description const templatesAvailable = providersTypes?.[providerSelected] + useEffect(() => { + // Select the first provider type + setProvider(Object.keys(providersTypes)?.[0]) + }, [provisionSelected]) + const { handleSelect, handleUnselect, @@ -52,26 +61,29 @@ const Template = () => ({ const handleClick = (template, isSelected) => { const { name, description, plain = {}, connection } = template const { location_key: locationKey = '' } = plain - const { [locationKey]: _, ...connectionEditable } = connection + const { [locationKey]: _, ...connectionEditable } = connection ?? {} // reset rest of form when change template - setFormData({ [CONFIGURATION_ID]: { name, description }, [CONNECTION_ID]: connectionEditable }) + setFormData({ + [CONFIGURATION_ID]: { name, description }, + [CONNECTION_ID]: connectionEditable + }) isSelected ? handleUnselect(name, item => item.name === name) : handleSelect(template) } - const RenderOptions = ({ options = {} }) => Object.keys(options)?.map(option => ( - - )) + const RenderOptions = ({ options = {} }) => Object.keys(options)?.map( + option => + ) ?? const RenderDescription = ({ description = '' }) => { const renderer = new Marked.Renderer() renderer.link = (href, title, text) => ( `${text}` + target="_blank" rel="nofollow" title='${title}' href='${href}'>${text}` ) const html = Marked(sanitize`${description}`, { renderer }) @@ -91,7 +103,6 @@ const Template = () => ({ value={provisionSelected} variant='outlined' > - {provisionSelected && } @@ -124,8 +134,8 @@ const Template = () => ({ !provisionSelected ? 'Please choose your provision type' : !providerSelected - ? 'Please choose your provider type' - : 'Your providers templates list is empty' + ? 'Please choose your provider type' + : 'Your providers templates list is empty' } /> } gridProps={{ 'data-cy': 'providers-templates' }} diff --git a/src/fireedge/src/client/containers/Providers/Form/Create/index.js b/src/fireedge/src/client/containers/Providers/Form/Create/index.js index 70b9ef30b1..fb8dad4ab4 100644 --- a/src/fireedge/src/client/containers/Providers/Form/Create/index.js +++ b/src/fireedge/src/client/containers/Providers/Form/Create/index.js @@ -54,7 +54,7 @@ function ProviderCreateForm () { const { inputs, plain, provider } = templateSelected const { location_key: locationKey } = plain - const { [locationKey]: connectionFixed } = templateSelected.connection + const connectionFixed = templateSelected.connection?.[locationKey] const formatData = { connection: { ...connection, [locationKey]: connectionFixed }, diff --git a/src/fireedge/src/client/containers/Providers/Sections/info.js b/src/fireedge/src/client/containers/Providers/Sections/info.js index 0e49e3a64d..408f5dcb53 100644 --- a/src/fireedge/src/client/containers/Providers/Sections/info.js +++ b/src/fireedge/src/client/containers/Providers/Sections/info.js @@ -26,6 +26,8 @@ const Info = memo(({ data }) => { registration_time: time } = TEMPLATE?.PROVISION_BODY + const hasConnection = connection && Object.keys(connection).length > 0 + const isChecked = checked => checked === '1' ? : @@ -71,26 +73,28 @@ const Info = memo(({ data }) => { - - - - {Tr(T.Credentials)} - - {!showConnection && } - - - - {Object.entries(connection)?.map(([key, value]) => - typeof value === 'string' && ( - - {key} - - {showConnection?.[key] ?? value} - - - ))} - - + {hasConnection && ( + + + + {Tr(T.Credentials)} + + {!showConnection && } + + + + {Object.entries(connection)?.map(([key, value]) => + typeof value === 'string' && ( + + {key} + + {showConnection?.[key] ?? value} + + + ))} + + + )} diff --git a/src/fireedge/src/client/containers/Provisions/Form/Create/Steps/Template/index.js b/src/fireedge/src/client/containers/Provisions/Form/Create/Steps/Template/index.js index 36fdbd8f91..2e95c5c098 100644 --- a/src/fireedge/src/client/containers/Provisions/Form/Create/Steps/Template/index.js +++ b/src/fireedge/src/client/containers/Provisions/Form/Create/Steps/Template/index.js @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react' +import React, { useCallback, useEffect } from 'react' import { Divider, Select, Breadcrumbs } from '@material-ui/core' import ArrowIcon from '@material-ui/icons/ArrowForwardIosRounded' import Marked from 'marked' @@ -22,16 +22,25 @@ const Template = () => ({ label: T.ProvisionTemplate, resolver: () => STEP_FORM_SCHEMA, content: useCallback(({ data, setFormData }) => { + const { provisionsTemplates, providers } = useProvision() + const templateSelected = data?.[0] - const [provisionSelected, setProvision] = React.useState(templateSelected?.provision_type) - const [providerSelected, setProvider] = React.useState(templateSelected?.provider) + const [provisionSelected, setProvision] = React.useState( + () => templateSelected?.provision_type ?? Object.keys(provisionsTemplates)?.[0] + ) + + const [providerSelected, setProvider] = React.useState(() => templateSelected?.provider) - const { provisionsTemplates, providers } = useProvision() - const provisionSelectedDescription = provisionsTemplates?.[provisionSelected]?.description const providersTypes = provisionsTemplates?.[provisionSelected]?.provisions ?? [] + const provisionSelectedDescription = provisionsTemplates?.[provisionSelected]?.description const templatesAvailable = providersTypes?.[providerSelected] ?? [] + useEffect(() => { + // Select the first provider type + setProvider(Object.keys(providersTypes)?.[0]) + }, [provisionSelected]) + const { handleSelect, handleUnselect, @@ -76,7 +85,7 @@ const Template = () => ({ renderer.link = (href, title, text) => ( `${text}` + target="_blank" rel="nofollow" title='${title}' href='${href}'>${text}` ) const html = Marked(sanitize`${description}`, { renderer }) @@ -96,7 +105,6 @@ const Template = () => ({ value={provisionSelected} variant='outlined' > - {provisionSelected && } @@ -129,8 +136,8 @@ const Template = () => ({ !provisionSelected ? 'Please choose your provision type' : !providerSelected - ? 'Please choose your provider type' - : 'Your provisions templates list is empty' + ? 'Please choose your provider type' + : 'Your provisions templates list is empty' } /> } gridProps={{ 'data-cy': 'provisions-templates' }} diff --git a/src/fireedge/src/client/models/ProviderTemplate.js b/src/fireedge/src/client/models/ProviderTemplate.js index f3c802eed2..2255c39408 100644 --- a/src/fireedge/src/client/models/ProviderTemplate.js +++ b/src/fireedge/src/client/models/ProviderTemplate.js @@ -1,7 +1,8 @@ export const isValidProviderTemplate = ({ name, provider, plain = {}, connection }) => { const { provision_type: provisionType, location_key: locationKey } = plain - const locationKeyConnectionNotExists = connection[locationKey] === undefined + const hasConnection = connection !== undefined + const locationKeyConnectionNotExists = !hasConnection || connection?.[locationKey] === undefined return ( !(locationKey && locationKeyConnectionNotExists) || diff --git a/src/fireedge/src/client/types/provision.js b/src/fireedge/src/client/types/provision.js index 3c1b848179..fff933ce85 100644 --- a/src/fireedge/src/client/types/provision.js +++ b/src/fireedge/src/client/types/provision.js @@ -27,11 +27,16 @@ export const UserInput = PropTypes.shape({ ]) }) -export const ProviderType = PropTypes.oneOf(['aws', 'packet']) +export const ProviderType = PropTypes.oneOf([ + 'aws', + 'packet', + 'dummy' +]) export const ProvisionType = PropTypes.oneOf([ 'metal', - 'virtual' + 'virtual', + 'onprem' ]) export const ProvisionHost = PropTypes.shape({ diff --git a/src/fireedge/src/server/routes/api/provision/schemas.js b/src/fireedge/src/server/routes/api/provision/schemas.js index ff60461f85..02db058ef9 100644 --- a/src/fireedge/src/server/routes/api/provision/schemas.js +++ b/src/fireedge/src/server/routes/api/provision/schemas.js @@ -12,7 +12,7 @@ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ -const providers = ['aws', 'packet'] +const providers = ['aws', 'packet', 'dummy'] const provider = { id: '/Provider',