Skip to content

Commit

Permalink
#417 rework command elements (#419)
Browse files Browse the repository at this point in the history
  • Loading branch information
west270 authored Jun 22, 2023
1 parent 2f9a308 commit a6c5915
Show file tree
Hide file tree
Showing 11 changed files with 293 additions and 270 deletions.
60 changes: 60 additions & 0 deletions src/components/FormComponents/FormAnyOrDict.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { TextField, TextFieldProps } from '@mui/material'
import { defaultTextFieldProps } from 'components/FormComponents'
import { ChangeEvent } from 'react'
import { RegisterOptions, useFormContext } from 'react-hook-form'

export type FormAnyOrDictProps = {
registerKey: string
registerOptions?: RegisterOptions
} & TextFieldProps

const FormAnyOrDict = ({ registerKey, registerOptions, ...textFieldProps }: FormAnyOrDictProps) => {
const { getFieldState, watch, setValue, register, setError, clearErrors } = useFormContext()

register(registerKey, {...registerOptions})

const currentValue = watch(registerKey)

const { error, invalid } = getFieldState(registerKey)

if(error){
textFieldProps.error = true
if(error.message) textFieldProps.helperText = error.message
}

return (
<TextField
{...defaultTextFieldProps}
{...textFieldProps}
value={ invalid ? currentValue : JSON.stringify(currentValue)}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
if(event.target.value === '') {
clearErrors(registerKey)
setValue(registerKey, undefined)
}
else try {
const value = JSON.parse(event.target.value)
if( textFieldProps.type === 'any' || typeof value === 'object' ) {
setValue(registerKey, value)
clearErrors(registerKey)
} else throw new Error('value is not valid')
} catch(e) {
if(event.target.value !== ''){
setError(registerKey, {
type: 'parseError',
message: textFieldProps.type === 'object' ?
'Invalid object'
:
'Unknown Type. Remember, variant fields must be enclosed with {} (object), [] (array), or "" (string).'
})
} else {
clearErrors(registerKey)
}
setValue(registerKey, event.target.value)
}
}}
/>
)
}

export { FormAnyOrDict }
6 changes: 2 additions & 4 deletions src/components/FormComponents/FormArray.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ const FormArray = ({ registerKey, disabled, helperText, label, minimum, maximum,
const addItem = () => {
const tempData = getValues(registerKey) || []
if(!maximum || tempData.length < maximum)
setValue(`${registerKey}.${tempData.length}`, addValue ? addValue : null)
setValue(`${registerKey}.${tempData.length}`, addValue)
}

watch(registerKey)

const currentValue = getValues(registerKey) || []
const currentValue = watch(registerKey) || []

const error = getFieldState(registerKey).error

Expand Down
43 changes: 43 additions & 0 deletions src/components/FormComponents/FormFile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { TextField, TextFieldProps } from '@mui/material'
import { defaultTextFieldProps } from 'components/FormComponents'
import { ChangeEvent } from 'react'
import { RegisterOptions, useFormContext } from 'react-hook-form'

export type FormFileProps = {
registerKey: string
registerOptions?: RegisterOptions
} & TextFieldProps

const FormFile = ({ registerKey, registerOptions, ...textFieldProps }: FormFileProps) => {
const { getFieldState, watch, setValue, register, trigger } = useFormContext()

const currentValue = watch(registerKey)

register(registerKey, {...registerOptions})

const { error } = getFieldState(registerKey)
if(error){
textFieldProps.error = true
if(error.message) textFieldProps.helperText = error.message
}

return (
<TextField
{...defaultTextFieldProps}
{...textFieldProps}
type="file"
value={currentValue !== '' && currentValue !== undefined ? currentValue.fileName : ''}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
if(event.target.files) {
setValue(registerKey, event.target.files[0])
}
else {
setValue(registerKey, '')
}
trigger(registerKey)
}}
/>
)
}

export { FormFile }
30 changes: 19 additions & 11 deletions src/components/FormComponents/FormTextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ export type FormTextFieldProps = {
menuOptions?: (string | number)[]
} & TextFieldProps

const defaultTextFieldProps: TextFieldProps = {
FormHelperTextProps: {
sx: {ml: 0}
},
size:'small',
fullWidth: true,
InputLabelProps: {shrink: true}
}

const FormTextField = ({ registerKey, registerOptions, menuOptions, ...textFieldProps }: FormTextFieldProps) => {
const { register, getFieldState, watch, } = useFormContext()
const [showPassword, setShowPassword] = useMountedState(false)
const defaultTextFieldProps: TextFieldProps = {
FormHelperTextProps: {
sx: {ml: 0}
},
size:'small',
fullWidth: true,
InputLabelProps: {shrink: true}
}

const currentValue = watch(registerKey)

Expand All @@ -46,8 +47,10 @@ const FormTextField = ({ registerKey, registerOptions, menuOptions, ...textField
}
}

if(textFieldProps.type === 'datetime-local' || textFieldProps.type === 'date-local'){
if(textFieldProps.type === 'datetime-local'){
textFieldProps.value = currentValue ? DateTime.fromISO(new Date(currentValue).toISOString()).toISO().slice(0,-8) : ''
} else if(textFieldProps.type === 'date'){
textFieldProps.value = currentValue ? DateTime.fromISO(new Date(currentValue).toISOString()).toISO().slice(0,-14) : ''
}

return menuOptions ? (
Expand All @@ -61,8 +64,13 @@ const FormTextField = ({ registerKey, registerOptions, menuOptions, ...textField
{menuOptions.map((value) => <MenuItem key={value} value={value}>{value}</MenuItem>)}
</TextField>
) : (
<TextField {...defaultTextFieldProps} value={(currentValue === 0 || currentValue) ? currentValue : ''} {...textFieldProps} {...register(registerKey, registerOptions)} />
<TextField
{...defaultTextFieldProps}
value={(currentValue === 0 || currentValue) ? currentValue : ''}
{...textFieldProps}
{...register(registerKey, registerOptions)}
/>
)
}

export { FormTextField }
export { defaultTextFieldProps, FormTextField }
3 changes: 2 additions & 1 deletion src/components/FormComponents/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './FormAnyOrDict'
export * from './FormArray'
export * from './FormCheckbox'
export * from './FormFile'
export * from './FormTextField'

60 changes: 26 additions & 34 deletions src/pages/CommandView/CommandFormFields.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TabContext, TabList } from '@mui/lab'
import { Alert, Box, Grid, MenuItem, Tab, TextField, TextFieldProps } from '@mui/material'
import { Alert, Box, Grid, Tab, TextFieldProps } from '@mui/material'
import { Divider } from 'components/Divider'
import { FormTextField } from 'components/FormComponents'
import { useMountedState } from 'hooks/useMountedState'
import { ParameterElement } from 'pages/CommandView'
import { useFormContext } from 'react-hook-form'
Expand All @@ -16,11 +17,15 @@ const CommandFormFields = ({ parameters, instances, parentKey }: { parameters: P
fullWidth: true,
}

const { register, formState: { errors } } = useFormContext()
const { formState: { errors } } = useFormContext()
const getKey = (key: string) => (
parentKey ? [parentKey, key].join('.') : key
)


const instancesNames: (string | number)[] | undefined = instances.length === 1 ? undefined : []
if(instancesNames) instances.sort((a, b) =>
(a.name < b.name ? -1 : 1)
).forEach(instance => instancesNames.push(instance.name))

const requiredParams = parameters.filter((param: Parameter) => (!param.optional)) || []
const optionalParams = parameters.filter((param: Parameter) => (param.optional)) || []
Expand Down Expand Up @@ -52,52 +57,39 @@ const CommandFormFields = ({ parameters, instances, parentKey }: { parameters: P
rowSpacing={2}
>
<Grid key="systemName" minWidth="150px" xs={1} item>
<TextField label="System Name" {...textFieldProps} {...register(getKey('system'))} />
<FormTextField label="System Name" {...textFieldProps} registerKey={getKey('system')} />
</Grid>
<Grid key="systemVersion" minWidth="150px" xs={1} item>
<TextField label="System Version" {...textFieldProps} {...register(getKey('system_version'))} />
<FormTextField label="System Version" {...textFieldProps} registerKey={getKey('system_version')} />
</Grid>
<Grid key="commandName" minWidth="150px" xs={1} item>
<TextField label="Command Name" {...textFieldProps} {...register(getKey('command'))} />
<FormTextField label="Command Name" {...textFieldProps} registerKey={getKey('command')} />
</Grid>
<Grid key="instanceName" minWidth="150px" xs={1} item>
{
instances.length === 1 ?
<TextField label="Instance Name" {...textFieldProps} {...register(getKey('instance_name'))} />
:
<TextField
label="Instance Name"
type="string"
size="small"
error={!!errors['instance_name']}
helperText={errors['instance_name']?.message || ''}
select
defaultValue={''}
fullWidth
{...register(getKey('instance_name'), {required: 'Instance is required'})}
>
{(instances.sort((a, b) =>
(a.name < b.name ? -1 : 1)
).map((instance, index) => (
<MenuItem key={`${instance.name}MenuItem${index}`} value={instance.name} >
{instance.name}
</MenuItem>)
))}
</TextField>
}
<FormTextField
label="Instance Name"
{...textFieldProps}
disabled={instances.length <= 1}
registerKey={getKey('instance_name')}
registerOptions={{required: {value: true, message: 'Instance Name is required'}}}
menuOptions={instancesNames}
/>
</Grid>
</Grid>
<TextField
<FormTextField
{...textFieldProps}
disabled={false}
multiline
label="Comment"
error={!!errors['comment']}
helperText={errors['comment']?.message || ''}
maxRows={3}
{...register(getKey('comment'), {
maxLength: {value: 140, message: 'Maximum comment length is 140 characters'}
})}
registerKey={getKey('comment')}
registerOptions={
{
maxLength: {value: 140, message: 'Maximum comment length is 140 characters'}
}
}
/>
</>
)
Expand Down
15 changes: 8 additions & 7 deletions src/pages/CommandView/CommandView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,15 @@ const CommandView = ({isJob} : {isJob?: boolean}) => {
job,
isJob
])

const getCommandFromSystem = (sys: System) => {
let tempCommand: Command | undefined = undefined
tempCommand = sys.commands.find((cmd: Command) => (cmd.name===commandName))
setCommand && setCommand(tempCommand as AugmentedCommand | undefined)
}

if(system && Object.hasOwn(system, 'commands') && !command) getCommandFromSystem(system as System)
useEffect(() => {
const getCommandFromSystem = (sys: System) => {
let tempCommand: Command | undefined = undefined
tempCommand = sys.commands.find((cmd: Command) => (cmd.name===commandName))
setCommand && setCommand(tempCommand as AugmentedCommand | undefined)
}
if(system && Object.hasOwn(system, 'commands') && !command) getCommandFromSystem(system as System)
}, [command, commandName, setCommand, system])


if (!system || !command || error) {
Expand Down
Loading

0 comments on commit a6c5915

Please sign in to comment.