Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

417 rework command elements #419

Merged
merged 6 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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