mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-19 06:50:07 +03:00
parent
02736a1d85
commit
85acc4b703
@ -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 }) =>
|
||||
|
@ -42,5 +42,9 @@ export const PROVIDERS_TYPES = [
|
||||
{
|
||||
name: 'packet',
|
||||
color: '#364562'
|
||||
},
|
||||
{
|
||||
name: 'dummy',
|
||||
color: '#436637'
|
||||
}
|
||||
]
|
||||
|
@ -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 => (
|
||||
<option key={option} value={option}>{option}</option>
|
||||
))
|
||||
const RenderOptions = ({ options = {} }) => Object.keys(options)?.map(
|
||||
option => <option key={option} value={option}>{option}</option>
|
||||
) ?? <option value=''>{T.None}</option>
|
||||
|
||||
const RenderDescription = ({ description = '' }) => {
|
||||
const renderer = new Marked.Renderer()
|
||||
|
||||
renderer.link = (href, title, text) => (
|
||||
`<a class="MuiTypography-root MuiLink-root MuiLink-underlineHover MuiTypography-colorSecondary"
|
||||
target="_blank" rel="nofollow" title='${title}' href='${href}' >${text}</a>`
|
||||
target="_blank" rel="nofollow" title='${title}' href='${href}'>${text}</a>`
|
||||
)
|
||||
|
||||
const html = Marked(sanitize`${description}`, { renderer })
|
||||
@ -91,7 +103,6 @@ const Template = () => ({
|
||||
value={provisionSelected}
|
||||
variant='outlined'
|
||||
>
|
||||
<option value="">{T.None}</option>
|
||||
<RenderOptions options={provisionsTemplates} />
|
||||
</Select>
|
||||
{provisionSelected && <Select
|
||||
@ -103,7 +114,6 @@ const Template = () => ({
|
||||
value={providerSelected}
|
||||
variant='outlined'
|
||||
>
|
||||
<option value="">{T.None}</option>
|
||||
<RenderOptions options={providersTypes} />
|
||||
</Select>}
|
||||
</Breadcrumbs>
|
||||
@ -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' }}
|
||||
|
@ -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 },
|
||||
|
@ -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' ? <CheckBox /> : <CheckBoxOutlineBlank />
|
||||
|
||||
@ -71,26 +73,28 @@ const Info = memo(({ data }) => {
|
||||
</ListItem>
|
||||
</List>
|
||||
</Paper>
|
||||
<Paper variant="outlined">
|
||||
<List className={clsx(classes.list, 'w-50')}>
|
||||
<ListItem className={classes.title}>
|
||||
<Typography>{Tr(T.Credentials)}</Typography>
|
||||
<span className={classes.alignToRight}>
|
||||
{!showConnection && <ConnectionButton />}
|
||||
</span>
|
||||
</ListItem>
|
||||
<Divider />
|
||||
{Object.entries(connection)?.map(([key, value]) =>
|
||||
typeof value === 'string' && (
|
||||
<ListItem key={key}>
|
||||
<Typography>{key}</Typography>
|
||||
<Typography data-cy={`provider-${key}`}>
|
||||
{showConnection?.[key] ?? value}
|
||||
</Typography>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
</Paper>
|
||||
{hasConnection && (
|
||||
<Paper variant="outlined">
|
||||
<List className={clsx(classes.list, 'w-50')}>
|
||||
<ListItem className={classes.title}>
|
||||
<Typography>{Tr(T.Credentials)}</Typography>
|
||||
<span className={classes.alignToRight}>
|
||||
{!showConnection && <ConnectionButton />}
|
||||
</span>
|
||||
</ListItem>
|
||||
<Divider />
|
||||
{Object.entries(connection)?.map(([key, value]) =>
|
||||
typeof value === 'string' && (
|
||||
<ListItem key={key}>
|
||||
<Typography>{key}</Typography>
|
||||
<Typography data-cy={`provider-${key}`}>
|
||||
{showConnection?.[key] ?? value}
|
||||
</Typography>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
</Paper>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Paper variant="outlined" className={classes.marginBottom}>
|
||||
|
@ -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) => (
|
||||
`<a class="MuiTypography-root MuiLink-root MuiLink-underlineHover MuiTypography-colorSecondary"
|
||||
target="_blank" rel="nofollow" title='${title}' href='${href}' >${text}</a>`
|
||||
target="_blank" rel="nofollow" title='${title}' href='${href}'>${text}</a>`
|
||||
)
|
||||
|
||||
const html = Marked(sanitize`${description}`, { renderer })
|
||||
@ -96,7 +105,6 @@ const Template = () => ({
|
||||
value={provisionSelected}
|
||||
variant='outlined'
|
||||
>
|
||||
<option value="">{T.None}</option>
|
||||
<RenderOptions options={provisionsTemplates} />
|
||||
</Select>
|
||||
{provisionSelected && <Select
|
||||
@ -108,7 +116,6 @@ const Template = () => ({
|
||||
value={providerSelected}
|
||||
variant='outlined'
|
||||
>
|
||||
<option value="">{T.None}</option>
|
||||
<RenderOptions options={providersTypes} />
|
||||
</Select>}
|
||||
</Breadcrumbs>
|
||||
@ -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' }}
|
||||
|
@ -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) ||
|
||||
|
@ -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({
|
||||
|
@ -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',
|
||||
|
Loading…
x
Reference in New Issue
Block a user