Skip to content

Commit

Permalink
merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
eduwercamacaro committed Nov 25, 2024
2 parents a97906e + f4abe43 commit 83eb73c
Show file tree
Hide file tree
Showing 78 changed files with 4,142 additions and 772 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,24 @@ export const WfRunForm = forwardRef<HTMLFormElement, Prop>(({ wfSpecVariables, o
onSubmit(data)
}

// Sort variables so required fields come first
const sortedVariables = wfSpecVariables.sort((a, b) => {
if (a.required === b.required) return 0
return a.required ? -1 : 1
})

return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmitForm)} ref={ref}>
<form onSubmit={handleSubmit(onSubmitForm)} ref={ref} className="space-y-4">
<div>
<Label htmlFor="custom-id">Custom WfRun Id</Label>
<Input
type="text"
className="mb-4 mt-1"
id="custom-id"
{...register('custom-id-wfRun-flow')}
placeholder="Enter string value"
/>
<Label htmlFor="customWfRunId" className="mb-2 flex items-center gap-2">
Custom WfRun Id
<span className="rounded bg-gray-300 p-1 text-xs">Optional</span>
</Label>
<Input type="text" id="customWfRunId" {...register('customWfRunId')} placeholder="Enter string value" />
</div>
{!!wfSpecVariables?.length &&
wfSpecVariables.map((variable: ThreadVarDef) => (
{!!sortedVariables.length &&
sortedVariables.map((variable: ThreadVarDef) => (
<FormFields key={variable.varDef?.name} variables={variable} register={register} formState={formState} />
))}
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Label } from '@/components/ui/label'
import { FormFieldProp } from '@/types'
import { CircleAlert } from 'lucide-react'
import { FC, ReactNode } from 'react'
import { useFormContext } from 'react-hook-form'
import { accessLevels } from '../../../wfSpec/[...props]/components/Variables'
import { Button } from '@/components/ui/button'

type BaseFormFieldProps = FormFieldProp & {
children: ReactNode
isDisabled: boolean
setIsDisabled: (disabled: boolean) => void
}

export const BaseFormField: FC<BaseFormFieldProps> = ({
variables,
formState: { errors },
children,
isDisabled,
setIsDisabled,
}) => {
const { setValue, trigger } = useFormContext()

if (!variables?.varDef?.name) return null

const {
varDef: { name },
required,
accessLevel,
} = variables

const handleSetNull = () => {
setValue(name, null)
trigger(name)
setIsDisabled(true)
}

const handleEnable = () => {
setIsDisabled(false)
}

return (
<div>
<div className="mb-2 flex justify-between">
<Label htmlFor={name} className="flex items-center gap-2">
{name}
<span className="rounded bg-green-300 p-1 text-xs">{accessLevels[accessLevel]}</span>
{required ? (
<span className="rounded bg-red-300 p-1 text-xs">Required</span>
) : (
<span className="rounded bg-gray-300 p-1 text-xs">Optional</span>
)}
</Label>
{!required && (
<Button
type="button"
variant="outline"
size="sm"
onClick={isDisabled ? handleEnable : handleSetNull}
className="h-8"
>
{isDisabled ? 'Enter Value' : 'Set Null'}
</Button>
)}
</div>
{children}
{errors[name] && (
<p className="mt-2 flex items-center gap-1 text-sm text-destructive">
<CircleAlert size={16} />
{errors[name]?.message}
</p>
)}
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,77 +1,49 @@
import { VARIABLE_TYPES } from '@/app/constants'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { cn } from '@/components/utils'
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, useEffect, useState } from 'react'
import { useFormContext } from 'react-hook-form'
import { BaseFormField } from './BaseFormField'

export const FormInput: FC<FormFieldProp> = props => {
const [isDisabled, setIsDisabled] = useState(false)
const [isDisabled, setIsDisabled] = useState(!props.variables?.required)
const { setValue } = useFormContext()

useEffect(() => {
if (!props.variables?.required && props.variables?.varDef?.name) {
setValue(props.variables.varDef.name, null)
}
}, [props.variables, setValue])

if (!props.variables?.varDef?.name) return null

const {
variables: {
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 (
<div>
<div className="mb-2 flex justify-between">
<Label htmlFor={name} className="flex items-center gap-2">
{name}
<span className="rounded bg-green-300 p-1 text-xs">{accessLevels[accessLevel]}</span>
{required ? (
<span className="rounded bg-red-300 p-1 text-xs">Required</span>
) : (
<span className="rounded bg-gray-300 p-1 text-xs">Optional</span>
)}
</Label>
</div>
<BaseFormField {...props} isDisabled={isDisabled} setIsDisabled={setIsDisabled}>
<Input
type={variableToType(type)}
className={errors[name] ? 'mb-1 mt-2 border-red-700' : 'mb-4 mt-1'}
type={type === VariableType.INT || type === VariableType.DOUBLE ? 'number' : 'text'}
className={cn(errors[name] && 'border-destructive')}
id={name}
step={type === VariableType.DOUBLE ? '0.01' : undefined}
disabled={isDisabled}
placeholder={`Enter ${VARIABLE_TYPES[type]?.toLowerCase()} value`}
{...register(name, {
required: required ? `${name} is required` : false,
setValueAs: setValue,
setValueAs: (value: string) => {
return type === VariableType.INT || type === VariableType.DOUBLE ? parseFloat(value) || undefined : value
},
})}
/>
{errors[name] && (
<p className="mb-3 flex items-center gap-1 text-sm text-red-700">
<CircleAlert size={16} />
{errors[name]?.message}
</p>
)}
</div>
</BaseFormField>
)
}
Original file line number Diff line number Diff line change
@@ -1,76 +1,53 @@
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 { FC, useEffect, useState } from 'react'
import { useFormContext } from 'react-hook-form'
import { accessLevels } from '../../../wfSpec/[...props]/components/Variables'
import { BaseFormField } from './BaseFormField'
import { cn } from '@/components/utils'

export const FormSelect: FC<FormFieldProp> = props => {
const {
register,
setValue,
formState: { errors },
getValues,
trigger,
} = useFormContext()
const [isDisabled, setIsDisabled] = useState(false)
const [isDisabled, setIsDisabled] = useState(!props.variables?.required)
const { register, setValue, getValues, trigger } = useFormContext()

useEffect(() => {
if (!props.variables?.required && props.variables?.varDef?.name) {
setValue(props.variables.varDef.name, null)
}
}, [props.variables, setValue])

if (!props.variables?.varDef?.name) return null

const {
variables: {
varDef: { name },
required,
accessLevel,
},
} = props

const handleChange = (value: string) => {
if (value === 'none') setValue(name, undefined)
else {
const booleanValue = value === 'true'
setValue(name, booleanValue)
}
const booleanValue = value === 'true'
setValue(name, booleanValue)
trigger(name)
}

const value = getValues(name)

return (
<div>
<div className="mb-2 flex justify-between">
<Label htmlFor={name} className="center flex items-center gap-2">
{name}
<span className="rounded bg-green-300 p-1 text-xs">{accessLevels[accessLevel]}</span>
{required ? (
<span className="rounded bg-red-300 p-1 text-xs">Required</span>
) : (
<span className="rounded bg-gray-300 p-1 text-xs">Optional</span>
)}
</Label>
</div>
<BaseFormField {...props} isDisabled={isDisabled} setIsDisabled={setIsDisabled}>
<Select
value={value?.toString() || ''}
onValueChange={handleChange}
disabled={isDisabled}
{...register(name, { required: required ? `${name} is required` : false })}
>
<SelectTrigger id={name} className={errors[name] ? 'mb-1 mt-1 border-red-700' : 'mb-4 mt-1'}>
<SelectTrigger id={name} className={cn(props.formState.errors[name] && 'border-destructive')}>
<SelectValue placeholder="Select True or False" />
</SelectTrigger>
<SelectContent>
<SelectItem value="true">True</SelectItem>
<SelectItem value="false">False</SelectItem>
<SelectItem value="none">None</SelectItem>
</SelectContent>
</Select>
{errors[name]?.message && (
<p className="mb-3 flex items-center gap-1 text-sm text-red-700">
<CircleAlert size={16} />
{String(errors[name]?.message)}
</p>
)}
</div>
</BaseFormField>
)
}
Original file line number Diff line number Diff line change
@@ -1,63 +1,49 @@
import { Label } from '@/components/ui/label'
import { VARIABLE_TYPES } from '@/app/constants'
import { Textarea } from '@/components/ui/textarea'
import { cn } from '@/components/utils'
import { FormFieldProp } from '@/types'
import { FC, useState } from 'react'

import { VARIABLE_TYPES } from '@/app/constants'
import { CircleAlert } from 'lucide-react'
import { FC, useEffect, useState } 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<FormFieldProp> = props => {
const [isDisabled, setIsDisabled] = useState(false)
const [isDisabled, setIsDisabled] = useState(!props.variables?.required)
const { setValue, trigger } = useFormContext()

if (!props.variables?.varDef?.name) return
useEffect(() => {
if (!props.variables?.required && props.variables?.varDef?.name) {
setValue(props.variables.varDef.name, null)
}
}, [props.variables, setValue])

if (!props.variables?.varDef?.name) return null
const {
variables: {
varDef: { type, name },
accessLevel,
required,
},
register,
formState: { errors },
} = props

return (
<div>
<div className="flex justify-between">
<Label htmlFor={name} className="flex items-center gap-2">
{name}
<span className="rounded bg-green-300 p-1 text-xs">{accessLevels[accessLevel]}</span>
{required ? (
<span className="rounded bg-red-300 p-1 text-xs">Required</span>
) : (
<span className="rounded bg-gray-300 p-1 text-xs">Optional</span>
)}
</Label>
</div>
<BaseFormField {...props} isDisabled={isDisabled} setIsDisabled={setIsDisabled}>
<Textarea
className={errors[name] ? 'mb-1 mt-1 min-h-[120px] border-red-700' : 'mb-4 mt-1 rounded-xl'}
className={cn(errors[name] && 'border-destructive')}
id={name}
disabled={isDisabled}
placeholder={`Enter ${VARIABLE_TYPES[type]?.toLowerCase()} value`}
{...register(name, {
required: required ? `${name} is required` : false,
validate: getValidation(type),
onChange: e => {
setValue(name, e.target.value || undefined)
setValue(name, e.target.value)
trigger(name)
},
})}
defaultValue=""
/>
{errors[name] && (
<p className="mb-3 flex items-center gap-1 text-sm text-red-700">
<CircleAlert size={16} />
{errors[name]?.message}
</p>
)}
</div>
</BaseFormField>
)
}
Loading

0 comments on commit 83eb73c

Please sign in to comment.