From bfc0462060031cda7bed54d40f2c4b83faf6cdb8 Mon Sep 17 00:00:00 2001 From: Hazim Arafa Date: Sun, 24 Nov 2024 16:42:28 -0800 Subject: [PATCH 1/4] refactor(dashboard): optimize execute `WfRun` components --- .../(diagram)/components/Forms/WfRunForm.tsx | 32 +++++---- .../Forms/components/BaseFormField.tsx | 63 ++++++++++++++++ .../Forms/components/FormFields.tsx | 20 ++---- .../components/Forms/components/FormInput.tsx | 72 +++++-------------- .../Forms/components/FormSelect.tsx | 47 +++--------- .../Forms/components/FormTextarea.tsx | 43 +++-------- .../components/Forms/components/validation.ts | 6 +- .../components/Modals/ExecuteWorkflowRun.tsx | 27 ++++--- dashboard/src/types/index.ts | 5 +- 9 files changed, 144 insertions(+), 171 deletions(-) create mode 100644 dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/BaseFormField.tsx diff --git a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/WfRunForm.tsx b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/WfRunForm.tsx index b4663c731..cac0bdfc3 100644 --- a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/WfRunForm.tsx +++ b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/WfRunForm.tsx @@ -14,33 +14,35 @@ type Prop = { onSubmit: (data: FormValues) => void } -// eslint-disable-next-line react/display-name export const WfRunForm = forwardRef(({ wfSpecVariables, onSubmit }, ref) => { const methods = useForm() const { register, handleSubmit, formState } = methods - const onSubmitForm = (data: FormValues) => { - onSubmit(data) - } - return ( -
+
- - +
+ +
+
+ {!!wfSpecVariables?.length && wfSpecVariables.map((variable: ThreadVarDef) => ( - + ))}
) }) + +WfRunForm.displayName = 'WfRunForm' diff --git a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/BaseFormField.tsx b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/BaseFormField.tsx new file mode 100644 index 000000000..85b270f3c --- /dev/null +++ b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/BaseFormField.tsx @@ -0,0 +1,63 @@ +import { getVariableValue } from '@/app/utils' +import { Label } from '@/components/ui/label' +import { FormFieldProp } from '@/types' +import { WfRunVariableAccessLevel } from 'littlehorse-client/proto' +import { CircleAlert } from 'lucide-react' +import { useFormContext } from 'react-hook-form' + +export const accessLevels: { [key in WfRunVariableAccessLevel]: string } = { + PUBLIC_VAR: 'Public', + INHERITED_VAR: 'Inherited', + PRIVATE_VAR: 'Private', + UNRECOGNIZED: '', +} + +type FormFieldWrapperProps = { + variables: FormFieldProp['variable'] + children: React.ReactNode +} + +export const BaseFormField = ({ variables, children }: FormFieldWrapperProps) => { + const { + formState: { errors }, + } = useFormContext() + + if (!variables?.varDef?.name) return null + + const { + varDef: { name, defaultValue }, + required, + accessLevel, + } = variables + + const hasDefaultValue = !!defaultValue + + return ( +
+
+ +
+ +
{children}
+ {errors[name] && ( +

+ + {errors[name]?.message?.toString()} +

+ )} +
+ ) +} diff --git a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormFields.tsx b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormFields.tsx index 75aa5d072..9d492fc8f 100644 --- a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormFields.tsx +++ b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormFields.tsx @@ -1,16 +1,10 @@ -import React, { FC } from 'react' +import { FormFieldProp } from '@/types' +import { FC } from 'react' import { FormComponent } from './formType' -import { VariableType, ThreadVarDef } from 'littlehorse-client/proto' -import { FieldValues, UseFormRegister, FormState } from 'react-hook-form' -type Prop = { - variables: ThreadVarDef - register: UseFormRegister - formState: FormState -} -export const FormFields: FC = props => { - const type = props.variables?.varDef?.type as VariableType - if (!type) return - const Component = FormComponent[type] - return +export const FormFields: FC = ({ variable: variables, register, formState }) => { + if (!variables?.varDef?.type) return null + + const Component = FormComponent[variables.varDef.type] + return } diff --git a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormInput.tsx b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormInput.tsx index e2ba9a178..5c5c4b367 100644 --- a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormInput.tsx +++ b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormInput.tsx @@ -1,77 +1,43 @@ import { VARIABLE_TYPES } from '@/app/constants' import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' import { FormFieldProp } from '@/types' import { VariableType } from 'littlehorse-client/proto' -import { CircleAlert } from 'lucide-react' -import { FC, useState } from 'react' -import { accessLevels } from '../../../wfSpec/[...props]/components/Variables' +import { FC } from 'react' +import { useFormContext } from 'react-hook-form' +import { BaseFormField } from './BaseFormField' export const FormInput: FC = props => { - const [isDisabled, setIsDisabled] = useState(false) - if (!props.variables?.varDef?.name) return null + const { register } = useFormContext() + + if (!props.variable?.varDef?.name) return null const { - variables: { + variable: { varDef: { type, name }, required, - accessLevel, }, - register, - formState: { errors }, } = props - const variableToType = (variable: VariableType) => { - switch (variable) { - case VariableType.INT: - return 'number' - case VariableType.DOUBLE: - return 'number' - case VariableType.BYTES: - return 'number' - case VariableType.STR: - return 'text' - default: - return 'text' - } - } - - const setValue = (value: number | string) => { - if (value === null) return value - return variableToType(type) === 'number' ? parseFloat(value?.toString()) || undefined : value || undefined - } - return ( -
-
- -
+ { + if (value === '') return undefined + + if ((type === VariableType.DOUBLE || type === VariableType.INT) && value) { + return parseFloat(value) + } + + return value + }, })} /> - {errors[name] && ( -

- - {errors[name]?.message} -

- )} -
+ ) } diff --git a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormSelect.tsx b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormSelect.tsx index c3ba897fa..6b0351e51 100644 --- a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormSelect.tsx +++ b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormSelect.tsx @@ -1,33 +1,25 @@ -import { Label } from '@/components/ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { FormFieldProp } from '@/types' -import { CircleAlert } from 'lucide-react' import { FC, useState } from 'react' import { useFormContext } from 'react-hook-form' -import { accessLevels } from '../../../wfSpec/[...props]/components/Variables' +import { BaseFormField } from './BaseFormField' export const FormSelect: FC = props => { - const { - register, - setValue, - formState: { errors }, - getValues, - trigger, - } = useFormContext() - const [isDisabled, setIsDisabled] = useState(false) + const { register, setValue, getValues, trigger } = useFormContext() + const [isDisabled] = useState(false) - if (!props.variables?.varDef?.name) return null + if (!props.variable?.varDef?.name) return null const { - variables: { + variable: { varDef: { name }, required, - accessLevel, }, } = props - const handleChange = (value: string) => { - if (value === 'none') setValue(name, undefined) + const handleChange = (value: string | null) => { + if (value === null) setValue(name, null) + else if (value === 'none') setValue(name, undefined) else { const booleanValue = value === 'true' setValue(name, booleanValue) @@ -38,25 +30,14 @@ export const FormSelect: FC = props => { const value = getValues(name) return ( -
-
- -
+ - {errors[name]?.message && ( -

- - {String(errors[name]?.message)} -

- )} -
+ ) } diff --git a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormTextarea.tsx b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormTextarea.tsx index adebb0dce..a610d3f90 100644 --- a/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormTextarea.tsx +++ b/dashboard/src/app/(authenticated)/(diagram)/components/Forms/components/FormTextarea.tsx @@ -1,46 +1,27 @@ -import { Label } from '@/components/ui/label' +import { VARIABLE_TYPES } from '@/app/constants' import { Textarea } from '@/components/ui/textarea' import { FormFieldProp } from '@/types' -import { FC, useState } from 'react' - -import { VARIABLE_TYPES } from '@/app/constants' -import { CircleAlert } from 'lucide-react' +import { FC } from 'react' import { useFormContext } from 'react-hook-form' -import { accessLevels } from '../../../wfSpec/[...props]/components/Variables' +import { BaseFormField } from './BaseFormField' import { getValidation } from './validation' export const FormTextarea: FC = props => { - const [isDisabled, setIsDisabled] = useState(false) - const { setValue, trigger } = useFormContext() + const { setValue, trigger, register } = useFormContext() + + if (!props.variable?.varDef?.name) return null - if (!props.variables?.varDef?.name) return const { - variables: { + variable: { varDef: { type, name }, - accessLevel, required, }, - register, - formState: { errors }, } = props return ( -
-
- -
+