From 592cc2abcd8b891a19865f945c32970ed54a2e5a Mon Sep 17 00:00:00 2001 From: BennyKok Date: Fri, 22 Dec 2023 16:09:36 +0800 Subject: [PATCH] feat(web): add run inputs options on dashboard --- web/bun.lockb | Bin 337014 -> 341617 bytes web/package.json | 7 + web/src/components/RunInputs.tsx | 27 ++- web/src/components/VersionSelect.tsx | 125 +++++++++++--- web/src/components/customInputNodes.tsx | 1 + web/src/components/ui/accordion.tsx | 27 ++- web/src/components/ui/auto-form/config.ts | 33 ++++ .../components/ui/auto-form/fields/array.tsx | 67 ++++++++ .../ui/auto-form/fields/checkbox.tsx | 32 ++++ .../components/ui/auto-form/fields/date.tsx | 37 ++++ .../components/ui/auto-form/fields/enum.tsx | 71 ++++++++ .../components/ui/auto-form/fields/input.tsx | 36 ++++ .../components/ui/auto-form/fields/number.tsx | 17 ++ .../components/ui/auto-form/fields/object.tsx | 130 ++++++++++++++ .../ui/auto-form/fields/radio-group.tsx | 44 +++++ .../components/ui/auto-form/fields/switch.tsx | 32 ++++ .../ui/auto-form/fields/textarea.tsx | 36 ++++ web/src/components/ui/auto-form/index.tsx | 87 ++++++++++ web/src/components/ui/auto-form/types.ts | 37 ++++ web/src/components/ui/auto-form/utils.ts | 159 ++++++++++++++++++ web/src/components/ui/calendar.tsx | 66 ++++++++ web/src/components/ui/date-picker.tsx | 46 +++++ web/src/components/ui/form.tsx | 102 ++++++----- web/src/components/ui/popover.tsx | 31 ++++ web/src/components/ui/radio-group.tsx | 44 +++++ web/src/components/ui/separator.tsx | 31 ++++ web/src/components/ui/switch.tsx | 29 ++++ web/src/components/ui/textarea.tsx | 24 +++ web/src/components/ui/toggle.tsx | 45 +++++ 29 files changed, 1321 insertions(+), 102 deletions(-) create mode 100644 web/src/components/ui/auto-form/config.ts create mode 100644 web/src/components/ui/auto-form/fields/array.tsx create mode 100644 web/src/components/ui/auto-form/fields/checkbox.tsx create mode 100644 web/src/components/ui/auto-form/fields/date.tsx create mode 100644 web/src/components/ui/auto-form/fields/enum.tsx create mode 100644 web/src/components/ui/auto-form/fields/input.tsx create mode 100644 web/src/components/ui/auto-form/fields/number.tsx create mode 100644 web/src/components/ui/auto-form/fields/object.tsx create mode 100644 web/src/components/ui/auto-form/fields/radio-group.tsx create mode 100644 web/src/components/ui/auto-form/fields/switch.tsx create mode 100644 web/src/components/ui/auto-form/fields/textarea.tsx create mode 100644 web/src/components/ui/auto-form/index.tsx create mode 100644 web/src/components/ui/auto-form/types.ts create mode 100644 web/src/components/ui/auto-form/utils.ts create mode 100644 web/src/components/ui/calendar.tsx create mode 100644 web/src/components/ui/date-picker.tsx create mode 100644 web/src/components/ui/popover.tsx create mode 100644 web/src/components/ui/radio-group.tsx create mode 100644 web/src/components/ui/separator.tsx create mode 100644 web/src/components/ui/switch.tsx create mode 100644 web/src/components/ui/textarea.tsx create mode 100644 web/src/components/ui/toggle.tsx diff --git a/web/bun.lockb b/web/bun.lockb index 88b5cc274ec740aa96c17d8e0e2bebd791fd459d..a80378225b2c6b2f77d903004a30dd0eb6032a7b 100755 GIT binary patch delta 68076 zcmeFadz_7B-~PYW8mndzr4mMisf2{aZiZnYWM3)7NDPJ?+k1#YmY-NGhbLs*?ovz5=jS+gpL2Vi*IKi# z`DyFLN58%J!FsjR%ARxHxK($LNW8B1!lY#nRQaaPw})aMxIK1Z$8G6f9ZQNYZXERK zRcrPw)jG#ki*XI_*Lgl)-h`a&v1ua*`Ql6Yd=;_Bq^AuWOLP&o;+v2=q;y$>+)Oz+ znQmam?2Q#8h3EQw7ZW)ub4=RU^laaV30}d^#`=6^(8p$^kIWoA-Z$UckHTfqUngIA zc*yXq0m{*_w9j_|cGk#&>9WU-NgFk4ywBGPU6r?_u=C+ZVWhmda5Vb56sR^&mQQD_~MC>Fe)p1ETZoi36$aBIbMMy(?({g&q|Z-BJ}ZT zBZjMyFB30^edwzAc_NkX7`n>qL(fVdr5@zf9$THgmv}Y!eK%dim$!+45`IpzRN#Oy zX#*JyU(ZWCeG#kzzk?MYt$1kW*i03inO)Z%h`n@=%2{nISPm=wi1aZ-(i`}EQT?e( z-e?U@%N{$r5e1A%&&igP!|89eux^|;cgDjSwuLsspy9WxKHtMm<(O)bXBZW^HTqI- zGNg?hKO$}Hz>KspL)=vNQ@tj|W~Qvtt&8_Krm9y0^Apg~ZFv9q8ihjLcz~ zLokb~7Js#mgB1Wd?j#bTLF7x^DIIlOX8PpP{ zC3!WiegUkR^izVT?}e3a8>|6(9;U1Fo`mJl_8Q)Ry#}ixOVLX+aq`TSUPN@}%ppP^ z56HHti!y1aKEyr7Z=s2%{S#`bqL&v4L^j(3Qi=g_-m%AT0SUk{7|_T9pZt*vvcLyH8`SrYsAq1%5WiqCdcW3 zw<~ zVd#u@-p-~zUv;=ylZfX@K{KC^;mo^&1ed_&ESIMywfIzum#*0ITNEhA-o@57_5!SY zAGEMT6!s=_6<7}aMtV)|J+SJzwWZH@89X+$whp2urowWMWhZww!| z>DpcE#gE5U{6MQe+QuudRaiPXQW|NpKZ7 z4OZ86gH=EWDw3WEEB&Rg3OwWY`Pdrrb}&Zj@dU$q_ zmTD}cEgjv{D|iSjM+aq%tvfI+JAGu9OTK=$c>0CJt6?FVeqdJCu*`IyFOgo1$kU&w zKn|4c?Nv|;md9z?BNMfNN8O$?HgkBk@B3a}R~K2n2#3_dfefL>{*69fm#=~~B*Sm@ z%5BltbKpE!b73E>xpPHd`d^dcluft~mfgOeH%VTE-AQQ+tdFe%Hj_>}T6b9XB;u>U zl?Hg}&w=IG8?e$HO!N7;F6F%oUkdLZ=+(0(js8~w=@cNo1y&a~hA)Gkp_??D&l~Jz z$c5FF(aE|6TdU$aE|#ijF6qUWWq1{phE;AidPokXj_~GC_Si8aa|pMO@Jn6a7*>Ki zM*4hLz}2uXfqif_`1vev@>aoM`4Y{b?O6u_EfGhkI5Jt$^iCt#<- zYG5l^jz((PgcV`6>~|{A5L`djtDqsQuHA>OF1#nl=erzUhg}<<2dm&=uzKoxSdP?# zD_I*P>Z9|{I=fN++HQ=Gyb#+WSW>ETooFQb4BSIZAE+cbb26kq4dM@?&-ks+;w8VHF zGb(LtM%`iQ<2e)$XEyr=&i6W$dy~2}Vn{D+l~ZSdmwv(mXF|EEkx;%@@At@>SHIou z&HQ3m6MoM^Z;vR%R`>Lx=<0ATtO4(`*qfK%!IiMjdDxqWW3km6ue?vuH85{ui@6S^kG$QPcm9Qu?;iJxcn((7i_1Ox)fHYFN}$ERjZcI%TPnk9X(?FS)(P^-0d5oB z9po!)Rg{^XHfBuPc;6@3YS?yI+s9J)5_Yt_2MJsN-wvM-4~LbYC#;sWgyqOJ@cHnH z4W5HlvE}d)dQQ`ICoG4ew=vN>_eU5~mFK=?!3H%KTaHYJBMRJ3Km}#MYIz@4j*fv%oNk$($xa{Z-bi!S^Z8D`&gnv3 zS4>8=@B>&~=1{O~yCI}kr$V(X1WRAUWL3{p-{iF<3s!suSVI|r<=~HRc@7UsADxrN z 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 ICXGt`AA@$2IRF3v delta 65793 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 { let imageUrl; try { - const url = new URL(data); - if (url.pathname.endsWith('.png')) { + if (data.startsWith("data:image/")) { imageUrl = data; + } else { + const url = new URL(data); + if (url.pathname.endsWith(".png")) { + imageUrl = data; + } } - } catch (_) { - } + } catch (_) {} return ( {key} - {imageUrl ? : {data}} + {imageUrl ? ( + + + + ) : ( + {data} + )} ); })} diff --git a/web/src/components/VersionSelect.tsx b/web/src/components/VersionSelect.tsx index ccf117e..b51e696 100644 --- a/web/src/components/VersionSelect.tsx +++ b/web/src/components/VersionSelect.tsx @@ -2,7 +2,16 @@ import { callServerPromise } from "./callServerPromise"; import { LoadingIcon } from "@/components/LoadingIcon"; +import AutoForm, { AutoFormSubmit } from "@/components/ui/auto-form"; import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; import { DropdownMenu, DropdownMenuContent, @@ -18,14 +27,16 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; +import { getInputsFromWorkflow } from "@/lib/getInputsFromWorkflow"; import { createRun } from "@/server/createRun"; import { createDeployments } from "@/server/curdDeploments"; import type { getMachines } from "@/server/curdMachine"; import type { findFirstTableWithVersion } from "@/server/findFirstTableWithVersion"; import { Copy, MoreVertical, Play } from "lucide-react"; import { parseAsInteger, useQueryState } from "next-usequerystate"; -import { useState } from "react"; +import { useMemo, useState } from "react"; import { toast } from "sonner"; +import { z } from "zod"; export function VersionSelect({ workflow, @@ -106,31 +117,95 @@ export function RunWorkflowButton({ defaultValue: machines[0].id ?? "", }); const [isLoading, setIsLoading] = useState(false); - return ( - + const [values, setValues] = useState>({}); + const [open, setOpen] = useState(false); + + const schema = useMemo(() => { + const workflow_version = getWorkflowVersionFromVersionIndex( + workflow, + version + ); + const inputs = getInputsFromWorkflow(workflow_version); + + if (!inputs) return null; + + return z.object({ + ...Object.fromEntries( + inputs?.map((x) => { + return [x?.input_id, z.string().optional()]; + }) + ), + }); + }, [version]); + + const runWorkflow = async () => { + console.log(values); + + const val = Object.keys(values).length > 0 ? values : undefined; + + const workflow_version_id = workflow?.versions.find( + (x) => x.version === version + )?.id; + console.log(workflow_version_id); + if (!workflow_version_id) return; + + setIsLoading(true); + try { + const origin = window.location.origin; + await callServerPromise( + createRun(origin, workflow_version_id, machine, val, true) + ); + // console.log(res.json()); + setIsLoading(false); + } catch (error) { + setIsLoading(false); + } + + setOpen(false); + }; + + return ( + + + + + + + Run outputs + + You can view your run's outputs here + + + {/*
*/} + {schema && ( + +
+ + Run + + {isLoading ? : } + + +
+
+ )} + {!schema && ( + + )} + {/*
*/} + {/*
{view}
*/} +
+
); } diff --git a/web/src/components/customInputNodes.tsx b/web/src/components/customInputNodes.tsx index 95af87f..4adfc5e 100644 --- a/web/src/components/customInputNodes.tsx +++ b/web/src/components/customInputNodes.tsx @@ -1,4 +1,5 @@ export const customInputNodes: Record = { ComfyUIDeployExternalText: "string", ComfyUIDeployExternalImage: "string - (public image url)", + ComfyUIDeployExternalImageAlpha: "string - (public image url)", }; diff --git a/web/src/components/ui/accordion.tsx b/web/src/components/ui/accordion.tsx index 24c788c..740b4bc 100644 --- a/web/src/components/ui/accordion.tsx +++ b/web/src/components/ui/accordion.tsx @@ -1,12 +1,11 @@ -"use client" +"use client"; -import * as React from "react" -import * as AccordionPrimitive from "@radix-ui/react-accordion" -import { ChevronDown } from "lucide-react" +import { cn } from "@/lib/utils"; +import * as AccordionPrimitive from "@radix-ui/react-accordion"; +import { ChevronDown } from "lucide-react"; +import * as React from "react"; -import { cn } from "@/lib/utils" - -const Accordion = AccordionPrimitive.Root +const Accordion = AccordionPrimitive.Root; const AccordionItem = React.forwardRef< React.ElementRef, @@ -17,8 +16,8 @@ const AccordionItem = React.forwardRef< className={cn("border-b", className)} {...props} /> -)) -AccordionItem.displayName = "AccordionItem" +)); +AccordionItem.displayName = "AccordionItem"; const AccordionTrigger = React.forwardRef< React.ElementRef, @@ -37,8 +36,8 @@ const AccordionTrigger = React.forwardRef< -)) -AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName +)); +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; const AccordionContent = React.forwardRef< React.ElementRef, @@ -51,8 +50,8 @@ const AccordionContent = React.forwardRef< >
{children}
-)) +)); -AccordionContent.displayName = AccordionPrimitive.Content.displayName +AccordionContent.displayName = AccordionPrimitive.Content.displayName; -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/web/src/components/ui/auto-form/config.ts b/web/src/components/ui/auto-form/config.ts new file mode 100644 index 0000000..b94b9b0 --- /dev/null +++ b/web/src/components/ui/auto-form/config.ts @@ -0,0 +1,33 @@ +import AutoFormCheckbox from "./fields/checkbox"; +import AutoFormDate from "./fields/date"; +import AutoFormEnum from "./fields/enum"; +import AutoFormInput from "./fields/input"; +import AutoFormNumber from "./fields/number"; +import AutoFormRadioGroup from "./fields/radio-group"; +import AutoFormSwitch from "./fields/switch"; +import AutoFormTextarea from "./fields/textarea"; + +export const INPUT_COMPONENTS = { + checkbox: AutoFormCheckbox, + date: AutoFormDate, + select: AutoFormEnum, + radio: AutoFormRadioGroup, + switch: AutoFormSwitch, + textarea: AutoFormTextarea, + number: AutoFormNumber, + fallback: AutoFormInput, +}; + +/** + * Define handlers for specific Zod types. + * You can expand this object to support more types. + */ +export const DEFAULT_ZOD_HANDLERS: { + [key: string]: keyof typeof INPUT_COMPONENTS; +} = { + ZodBoolean: "checkbox", + ZodDate: "date", + ZodEnum: "select", + ZodNativeEnum: "select", + ZodNumber: "number", +}; diff --git a/web/src/components/ui/auto-form/fields/array.tsx b/web/src/components/ui/auto-form/fields/array.tsx new file mode 100644 index 0000000..1e787e5 --- /dev/null +++ b/web/src/components/ui/auto-form/fields/array.tsx @@ -0,0 +1,67 @@ +import type { useForm , useForm } from "react-hook-form"; +import { useFieldArray } from "react-hook-form"; +import { Button } from "../../button"; +import { Separator } from "../../separator"; +import { beautifyObjectName } from "../utils"; +import AutoFormObject from "./object"; +import { Plus, Trash } from "lucide-react"; +import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"; +import type { z } from "zod"; + +export default function AutoFormArray({ + name, + item, + form, + path = [], + fieldConfig, +}: { + name: string; + item: z.ZodArray; + form: ReturnType; + path?: string[]; + fieldConfig?: any; +}) { + const { fields, append, remove } = useFieldArray({ + control: form.control, + name, + }); + const title = item._def.description ?? beautifyObjectName(name); + + return ( + + {title} + + {fields.map((_field, index) => { + const key = [...path, index.toString()].join("."); + return ( +
+ } + form={form} + fieldConfig={fieldConfig} + path={[...path, index.toString()]} + /> + + +
+ ); + })} + +
+
+ ); +} diff --git a/web/src/components/ui/auto-form/fields/checkbox.tsx b/web/src/components/ui/auto-form/fields/checkbox.tsx new file mode 100644 index 0000000..7087a1e --- /dev/null +++ b/web/src/components/ui/auto-form/fields/checkbox.tsx @@ -0,0 +1,32 @@ +import { Checkbox } from "../../checkbox"; +import { FormControl, FormDescription, FormItem, FormLabel } from "../../form"; +import { AutoFormInputComponentProps } from "../types"; + +export default function AutoFormCheckbox({ + label, + isRequired, + field, + fieldConfigItem, + fieldProps, +}: AutoFormInputComponentProps) { + return ( + + + + +
+ + {label} + {isRequired && *} + + {fieldConfigItem.description && ( + {fieldConfigItem.description} + )} +
+
+ ); +} diff --git a/web/src/components/ui/auto-form/fields/date.tsx b/web/src/components/ui/auto-form/fields/date.tsx new file mode 100644 index 0000000..93197f4 --- /dev/null +++ b/web/src/components/ui/auto-form/fields/date.tsx @@ -0,0 +1,37 @@ +import { DatePicker } from "../../date-picker"; +import { + FormControl, + FormDescription, + FormItem, + FormLabel, + FormMessage, +} from "../../form"; +import type { AutoFormInputComponentProps } from "../types"; + +export default function AutoFormDate({ + label, + isRequired, + field, + fieldConfigItem, + fieldProps, +}: AutoFormInputComponentProps) { + return ( + + + {label} + {isRequired && *} + + + + + {fieldConfigItem.description && ( + {fieldConfigItem.description} + )} + + + ); +} diff --git a/web/src/components/ui/auto-form/fields/enum.tsx b/web/src/components/ui/auto-form/fields/enum.tsx new file mode 100644 index 0000000..c529f6e --- /dev/null +++ b/web/src/components/ui/auto-form/fields/enum.tsx @@ -0,0 +1,71 @@ +import { + FormControl, + FormDescription, + FormItem, + FormLabel, + FormMessage, +} from "../../form"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "../../select"; +import { AutoFormInputComponentProps } from "../types"; +import { getBaseSchema } from "../utils"; +import * as z from "zod"; + +export default function AutoFormEnum({ + label, + isRequired, + field, + fieldConfigItem, + zodItem, +}: AutoFormInputComponentProps) { + const baseValues = (getBaseSchema(zodItem) as unknown as z.ZodEnum)._def + .values; + + let values: [string, string][] = []; + if (!Array.isArray(baseValues)) { + values = Object.entries(baseValues); + } else { + values = baseValues.map((value) => [value, value]); + } + + function findItem(value: any) { + return values.find((item) => item[0] === value); + } + + return ( + + + {label} + {isRequired && *} + + + + + {fieldConfigItem.description && ( + {fieldConfigItem.description} + )} + + + ); +} diff --git a/web/src/components/ui/auto-form/fields/input.tsx b/web/src/components/ui/auto-form/fields/input.tsx new file mode 100644 index 0000000..242556b --- /dev/null +++ b/web/src/components/ui/auto-form/fields/input.tsx @@ -0,0 +1,36 @@ +import { + FormControl, + FormDescription, + FormItem, + FormLabel, + FormMessage, +} from "../../form"; +import { Input } from "../../input"; +import { AutoFormInputComponentProps } from "../types"; + +export default function AutoFormInput({ + label, + isRequired, + fieldConfigItem, + fieldProps, +}: AutoFormInputComponentProps) { + const { showLabel: _showLabel, ...fieldPropsWithoutShowLabel } = fieldProps; + const showLabel = _showLabel === undefined ? true : _showLabel; + return ( + + {showLabel && ( + + {label} + {isRequired && *} + + )} + + + + {fieldConfigItem.description && ( + {fieldConfigItem.description} + )} + + + ); +} diff --git a/web/src/components/ui/auto-form/fields/number.tsx b/web/src/components/ui/auto-form/fields/number.tsx new file mode 100644 index 0000000..b1f8236 --- /dev/null +++ b/web/src/components/ui/auto-form/fields/number.tsx @@ -0,0 +1,17 @@ +import { AutoFormInputComponentProps } from "../types"; +import AutoFormInput from "./input"; + +export default function AutoFormNumber({ + fieldProps, + ...props +}: AutoFormInputComponentProps) { + return ( + + ); +} diff --git a/web/src/components/ui/auto-form/fields/object.tsx b/web/src/components/ui/auto-form/fields/object.tsx new file mode 100644 index 0000000..9e00789 --- /dev/null +++ b/web/src/components/ui/auto-form/fields/object.tsx @@ -0,0 +1,130 @@ +import * as z from "zod"; +import { useForm } from "react-hook-form"; +import { FieldConfig, FieldConfigItem } from "../types"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "../../accordion"; +import { + beautifyObjectName, + getBaseSchema, + getBaseType, + zodToHtmlInputProps, +} from "../utils"; +import { FormField } from "../../form"; +import { DEFAULT_ZOD_HANDLERS, INPUT_COMPONENTS } from "../config"; +import AutoFormArray from "./array"; + +function DefaultParent({ children }: { children: React.ReactNode }) { + return <>{children}; +} + +export default function AutoFormObject< + SchemaType extends z.ZodObject, +>({ + schema, + form, + fieldConfig, + path = [], +}: { + schema: SchemaType | z.ZodEffects; + form: ReturnType; + fieldConfig?: FieldConfig>; + path?: string[]; +}) { + const { shape } = getBaseSchema(schema); + + return ( + + {Object.keys(shape).map((name) => { + const item = shape[name] as z.ZodAny; + const zodBaseType = getBaseType(item); + const itemName = item._def.description ?? beautifyObjectName(name); + const key = [...path, name].join("."); + + if (zodBaseType === "ZodObject") { + return ( + + {itemName} + + } + form={form} + fieldConfig={ + (fieldConfig?.[name] ?? {}) as FieldConfig< + z.infer + > + } + path={[...path, name]} + /> + + + ); + } + if (zodBaseType === "ZodArray") { + return ( + } + form={form} + fieldConfig={fieldConfig?.[name] ?? {}} + path={[...path, name]} + /> + ); + } + + const fieldConfigItem: FieldConfigItem = fieldConfig?.[name] ?? {}; + const zodInputProps = zodToHtmlInputProps(item); + const isRequired = + zodInputProps.required || + fieldConfigItem.inputProps?.required || + false; + + return ( + { + const inputType = + fieldConfigItem.fieldType ?? + DEFAULT_ZOD_HANDLERS[zodBaseType] ?? + "fallback"; + + const InputComponent = + typeof inputType === "function" + ? inputType + : INPUT_COMPONENTS[inputType]; + const ParentElement = + fieldConfigItem.renderParent ?? DefaultParent; + + return ( + + + + ); + }} + /> + ); + })} + + ); +} diff --git a/web/src/components/ui/auto-form/fields/radio-group.tsx b/web/src/components/ui/auto-form/fields/radio-group.tsx new file mode 100644 index 0000000..7ea7840 --- /dev/null +++ b/web/src/components/ui/auto-form/fields/radio-group.tsx @@ -0,0 +1,44 @@ +import * as z from "zod"; +import { AutoFormInputComponentProps } from "../types"; +import { FormControl, FormItem, FormLabel, FormMessage } from "../../form"; +import { RadioGroup, RadioGroupItem } from "../../radio-group"; + +export default function AutoFormRadioGroup({ + label, + isRequired, + field, + zodItem, + fieldProps, +}: AutoFormInputComponentProps) { + const values = (zodItem as unknown as z.ZodEnum)._def.values; + + return ( + + + {label} + {isRequired && *} + + + + {values.map((value: any) => ( + + + + + {value} + + ))} + + + + + ); +} diff --git a/web/src/components/ui/auto-form/fields/switch.tsx b/web/src/components/ui/auto-form/fields/switch.tsx new file mode 100644 index 0000000..43df3f6 --- /dev/null +++ b/web/src/components/ui/auto-form/fields/switch.tsx @@ -0,0 +1,32 @@ +import { FormControl, FormDescription, FormItem, FormLabel } from "../../form"; +import { Switch } from "../../switch"; +import { AutoFormInputComponentProps } from "../types"; + +export default function AutoFormSwitch({ + label, + isRequired, + field, + fieldConfigItem, + fieldProps, +}: AutoFormInputComponentProps) { + return ( + + + + +
+ + {label} + {isRequired && *} + + {fieldConfigItem.description && ( + {fieldConfigItem.description} + )} +
+
+ ); +} diff --git a/web/src/components/ui/auto-form/fields/textarea.tsx b/web/src/components/ui/auto-form/fields/textarea.tsx new file mode 100644 index 0000000..92dece7 --- /dev/null +++ b/web/src/components/ui/auto-form/fields/textarea.tsx @@ -0,0 +1,36 @@ +import { + FormControl, + FormDescription, + FormItem, + FormLabel, + FormMessage, +} from "../../form"; +import { Textarea } from "../../textarea"; +import { AutoFormInputComponentProps } from "../types"; + +export default function AutoFormTextarea({ + label, + isRequired, + fieldConfigItem, + fieldProps, +}: AutoFormInputComponentProps) { + const { showLabel: _showLabel, ...fieldPropsWithoutShowLabel } = fieldProps; + const showLabel = _showLabel === undefined ? true : _showLabel; + return ( + + {showLabel && ( + + {label} + {isRequired && *} + + )} + +