From b75cddc191797a0e92900d904667a5b45833c0f8 Mon Sep 17 00:00:00 2001 From: Po-Chun Chiu <57251712+EiffelFly@users.noreply.github.com> Date: Wed, 11 Oct 2023 15:43:06 +0800 Subject: [PATCH] fix(toolkit): fix start operator wrongly delete input when you edit without saving then creating a new field (#949) Because - operator wrongly delete input when you edit without saving then create a new field This commit - fix start operator wrongly delete input when you edit without saving then create a new field --- packages/toolkit/package.json | 2 +- .../pipeline-builder/components/StartNode.tsx | 667 ------------------ .../ConnectorNode.tsx | 0 .../ConnectorNodeControlPanel.tsx | 0 .../InputPropertyItem.tsx | 0 .../index.ts | 0 .../view/pipeline-builder/components/index.ts | 4 +- .../components/start-node/StartNode.tsx | 183 +++++ .../start-node/StartNodeInputForm.tsx | 505 +++++++++++++ .../components/start-node/index.ts | 1 + 10 files changed, 692 insertions(+), 670 deletions(-) delete mode 100644 packages/toolkit/src/view/pipeline-builder/components/StartNode.tsx rename packages/toolkit/src/view/pipeline-builder/components/{ConnectorNode => connector-node}/ConnectorNode.tsx (100%) rename packages/toolkit/src/view/pipeline-builder/components/{ConnectorNode => connector-node}/ConnectorNodeControlPanel.tsx (100%) rename packages/toolkit/src/view/pipeline-builder/components/{ConnectorNode => connector-node}/InputPropertyItem.tsx (100%) rename packages/toolkit/src/view/pipeline-builder/components/{ConnectorNode => connector-node}/index.ts (100%) create mode 100644 packages/toolkit/src/view/pipeline-builder/components/start-node/StartNode.tsx create mode 100644 packages/toolkit/src/view/pipeline-builder/components/start-node/StartNodeInputForm.tsx create mode 100644 packages/toolkit/src/view/pipeline-builder/components/start-node/index.ts diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json index 35bc7d68..bd2c339f 100644 --- a/packages/toolkit/package.json +++ b/packages/toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@instill-ai/toolkit", - "version": "0.68.3-rc.15", + "version": "0.68.3-rc.20", "description": "Instill AI's frontend toolkit", "repository": "https://github.com/instill-ai/design-system.git", "bugs": "https://github.com/instill-ai/design-system/issues", diff --git a/packages/toolkit/src/view/pipeline-builder/components/StartNode.tsx b/packages/toolkit/src/view/pipeline-builder/components/StartNode.tsx deleted file mode 100644 index e1f0c4d9..00000000 --- a/packages/toolkit/src/view/pipeline-builder/components/StartNode.tsx +++ /dev/null @@ -1,667 +0,0 @@ -import * as React from "react"; -import * as z from "zod"; -import { useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import cn from "clsx"; -import { isAxiosError } from "axios"; -import { NodeProps, Position } from "reactflow"; -import { shallow } from "zustand/shallow"; -import { PipelineComponentReference, StartNodeData } from "../type"; -import { - Button, - Checkbox, - ComplicateIcons, - Form, - Icons, - Input, - Tag, - useToast, -} from "@instill-ai/design-system"; - -import { - PipelineBuilderStore, - usePipelineBuilderStore, -} from "../usePipelineBuilderStore"; -import { - extractReferencesFromConfiguration, - composeEdgesFromReferences, - recursiveParseToNum, - recursiveRemoveUndefinedAndNullFromArray, - recursiveReplaceNullAndEmptyStringWithUndefined, -} from "../lib"; -import { CustomHandle } from "./CustomHandle"; -import { useStartOperatorTestModeInputForm } from "../use-node-input-fields"; -import { StartNodeInputType } from "./StartNodeInputType"; -import { - Nullable, - StartOperatorInputSingularType, - StartOperatorInputType, - getInstillApiErrorMessage, - useTriggerUserPipeline, -} from "../../../lib"; - -export const CreateStartOperatorInputSchema = z.object({ - title: z.string().min(1, { message: "Title is required" }), - key: z.string().min(1, { message: "Key is required" }), -}); - -const pipelineBuilderSelector = (state: PipelineBuilderStore) => ({ - pipelineIsNew: state.pipelineIsNew, - pipelineName: state.pipelineName, - nodes: state.nodes, - edges: state.edges, - updateNodes: state.updateNodes, - updateEdges: state.updateEdges, - testModeEnabled: state.testModeEnabled, - updateTestModeTriggerResponse: state.updateTestModeTriggerResponse, - accessToken: state.accessToken, - updatePipelineRecipeIsDirty: state.updatePipelineRecipeIsDirty, - isLatestVersion: state.isLatestVersion, - isOwner: state.isOwner, -}); - -export const StartNode = ({ data, id }: NodeProps) => { - const [enableEdit, setEnableEdit] = React.useState(false); - const [selectedType, setSelectedType] = - React.useState>(null); - const [prevFieldKey, setPrevFieldKey] = - React.useState>(null); - const [isTriggering, setIsTriggering] = React.useState(false); - const [inputTypeIsArray, setInputTypeIsArray] = React.useState(false); - - const { - pipelineName, - nodes, - edges, - updateNodes, - updateEdges, - testModeEnabled, - updateTestModeTriggerResponse, - accessToken, - updatePipelineRecipeIsDirty, - isLatestVersion, - isOwner, - } = usePipelineBuilderStore(pipelineBuilderSelector, shallow); - - const { toast } = useToast(); - - const createStartOperatorInputform = useForm< - z.infer - >({ - resolver: zodResolver(CreateStartOperatorInputSchema), - }); - - const { - Schema: StartOperatorTestModeInputSchema, - fields: startOperatorTestModeInputfields, - form: startOperatorTestModeInputForm, - } = useStartOperatorTestModeInputForm({ nodes }); - - const useTriggerPipeline = useTriggerUserPipeline(); - - const onTriggerPipeline = ( - data: z.infer - ) => { - if (!pipelineName) return; - - const input = recursiveRemoveUndefinedAndNullFromArray( - recursiveReplaceNullAndEmptyStringWithUndefined(recursiveParseToNum(data)) - ); - - setIsTriggering(true); - - useTriggerPipeline.mutate( - { - pipelineName, - accessToken, - payload: { - inputs: [input], - }, - returnTraces: true, - }, - { - onSuccess: (data) => { - setIsTriggering(false); - updateTestModeTriggerResponse(() => data); - }, - onError: (error) => { - setIsTriggering(false); - if (isAxiosError(error)) { - toast({ - title: "Something went wrong when trigger the pipeline", - variant: "alert-error", - size: "large", - description: getInstillApiErrorMessage(error), - }); - } else { - toast({ - title: "Something went wrong when trigger the pipeline", - variant: "alert-error", - size: "large", - description: "Please try again later", - }); - } - }, - } - ); - }; - - const onSubmit = ( - formData: z.infer - ) => { - if (!selectedType) return; - - let finalType: StartOperatorInputType = selectedType; - - if (inputTypeIsArray) { - switch (selectedType) { - case "text": { - finalType = "text_array"; - break; - } - case "audio": { - finalType = "audio_array"; - break; - } - case "boolean": { - finalType = "boolean_array"; - break; - } - case "image": { - finalType = "image_array"; - break; - } - case "number": { - finalType = "number_array"; - break; - } - } - } - - const newNodes = nodes.map((node) => { - if (node.data.nodeType === "start") { - if (prevFieldKey) { - delete node.data.component.configuration.metadata[prevFieldKey]; - } - - node.data = { - ...node.data, - component: { - ...node.data.component, - configuration: { - ...node.data.component.configuration, - metadata: { - ...node.data.component.configuration.metadata, - [formData.key]: { - type: finalType, - title: formData.title, - }, - }, - }, - }, - }; - } - return node; - }); - - updateNodes(() => newNodes); - - const allReferences: PipelineComponentReference[] = []; - - newNodes.forEach((node) => { - if (node.data.component?.configuration) { - allReferences.push( - ...extractReferencesFromConfiguration( - node.data.component?.configuration, - node.id - ) - ); - } - }); - - const newEdges = composeEdgesFromReferences(allReferences, newNodes); - updateEdges(() => newEdges); - - setEnableEdit(false); - setSelectedType(null); - setPrevFieldKey(null); - setInputTypeIsArray(false); - updatePipelineRecipeIsDirty(() => true); - createStartOperatorInputform.reset({ - title: "", - key: "", - }); - }; - - const onDeleteField = (key: string) => { - const newNodes = nodes.map((node) => { - if (node.data.nodeType === "start") { - delete node.data.component.configuration.metadata[key]; - - node.data = { - ...node.data, - }; - } - return node; - }); - - updateNodes(() => newNodes); - - const allReferences: PipelineComponentReference[] = []; - - newNodes.forEach((node) => { - if (node.data.component?.configuration) { - allReferences.push( - ...extractReferencesFromConfiguration( - node.data.component?.configuration, - node.id - ) - ); - } - }); - - const newEdges = composeEdgesFromReferences(allReferences, newNodes); - updateEdges(() => newEdges); - updatePipelineRecipeIsDirty(() => true); - }; - - const onEditField = (key: string) => { - createStartOperatorInputform.reset({ - title: data.component.configuration.metadata[key].title, - key: key, - }); - setEnableEdit(true); - setSelectedType(() => { - let finalType = data.component.configuration.metadata[key].type; - - switch (finalType) { - case "text_array": { - finalType = "text"; - setInputTypeIsArray(true); - break; - } - case "audio_array": { - finalType = "audio"; - setInputTypeIsArray(true); - break; - } - case "boolean_array": { - finalType = "boolean"; - setInputTypeIsArray(true); - break; - } - case "image_array": { - finalType = "image"; - setInputTypeIsArray(true); - break; - } - case "number_array": { - finalType = "number"; - setInputTypeIsArray(true); - break; - } - } - - return finalType; - }); - }; - - const hasSourceEdges = React.useMemo(() => { - return edges.some((edge) => edge.source === id); - }, [edges]); - - return ( - <> -
-
-

- start -

-
- - {enableEdit ? ( - -
-
- -
- -
-
-
- { - if (selectedType === "text") { - setSelectedType(null); - } else { - setSelectedType("text"); - } - setInputTypeIsArray(false); - }} - /> - { - if (selectedType === "number") { - setSelectedType(null); - } else { - setSelectedType("number"); - } - setInputTypeIsArray(false); - }} - /> - { - if (selectedType === "image") { - setSelectedType(null); - } else { - setSelectedType("image"); - } - setInputTypeIsArray(false); - }} - /> - { - if (selectedType === "audio") { - setSelectedType(null); - } else { - setSelectedType("audio"); - } - setInputTypeIsArray(false); - }} - /> - { - if (selectedType === "boolean") { - setSelectedType(null); - } else { - setSelectedType("boolean"); - } - setInputTypeIsArray(false); - }} - /> -
- {["number", "image", "text", "audio"].includes( - selectedType ?? "" - ) ? ( -
- { - if (typeof e === "boolean") { - setInputTypeIsArray(e); - } - }} - id="is_array" - className="my-auto h-4 w-4" - /> -
- -
-
- ) : null} -
- { - return ( - - - Title - - - - - - - - - ); - }} - /> - { - return ( - - - Key - - - - - - - - - ); - }} - /> -
-
-
- ) : ( -
- {testModeEnabled ? ( - -
-
- {...startOperatorTestModeInputfields} -
-
- -
-
-
- ) : ( -
- {Object.entries(data.component.configuration.metadata).map( - ([key, value]) => { - let icon: Nullable = null; - - switch (value.type) { - case "text": - case "text_array": { - icon = ( - - ); - break; - } - case "audio": - case "audio_array": { - icon = ( - - ); - break; - } - case "boolean": - case "boolean_array": { - icon = ( - - ); - break; - } - case "image": - case "image_array": { - icon = ( - - ); - break; - } - case "number": - case "number_array": { - icon = ( - - ); - break; - } - default: - break; - } - - return ( -
-
-
- {key} -
- {isLatestVersion && isOwner ? ( -
- - -
- ) : null} -
-
- - {icon} - {value.type} - -
-
- ); - } - )} - -
- )} -
- )} -
- - - ); -}; diff --git a/packages/toolkit/src/view/pipeline-builder/components/ConnectorNode/ConnectorNode.tsx b/packages/toolkit/src/view/pipeline-builder/components/connector-node/ConnectorNode.tsx similarity index 100% rename from packages/toolkit/src/view/pipeline-builder/components/ConnectorNode/ConnectorNode.tsx rename to packages/toolkit/src/view/pipeline-builder/components/connector-node/ConnectorNode.tsx diff --git a/packages/toolkit/src/view/pipeline-builder/components/ConnectorNode/ConnectorNodeControlPanel.tsx b/packages/toolkit/src/view/pipeline-builder/components/connector-node/ConnectorNodeControlPanel.tsx similarity index 100% rename from packages/toolkit/src/view/pipeline-builder/components/ConnectorNode/ConnectorNodeControlPanel.tsx rename to packages/toolkit/src/view/pipeline-builder/components/connector-node/ConnectorNodeControlPanel.tsx diff --git a/packages/toolkit/src/view/pipeline-builder/components/ConnectorNode/InputPropertyItem.tsx b/packages/toolkit/src/view/pipeline-builder/components/connector-node/InputPropertyItem.tsx similarity index 100% rename from packages/toolkit/src/view/pipeline-builder/components/ConnectorNode/InputPropertyItem.tsx rename to packages/toolkit/src/view/pipeline-builder/components/connector-node/InputPropertyItem.tsx diff --git a/packages/toolkit/src/view/pipeline-builder/components/ConnectorNode/index.ts b/packages/toolkit/src/view/pipeline-builder/components/connector-node/index.ts similarity index 100% rename from packages/toolkit/src/view/pipeline-builder/components/ConnectorNode/index.ts rename to packages/toolkit/src/view/pipeline-builder/components/connector-node/index.ts diff --git a/packages/toolkit/src/view/pipeline-builder/components/index.ts b/packages/toolkit/src/view/pipeline-builder/components/index.ts index eaf37650..a41dadd8 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/index.ts +++ b/packages/toolkit/src/view/pipeline-builder/components/index.ts @@ -1,7 +1,7 @@ export * from "./BackToLatestVersionTopBar"; export * from "./BottomBar"; export * from "./CreateResourceDialog"; -export * from "./ConnectorNode"; +export * from "./connector-node"; export * from "./CustomEdge"; export * from "./CustomHandle"; export * from "./EmptyNode"; @@ -9,5 +9,5 @@ export * from "./EndNode"; export * from "./PipelineNameForm"; export * from "./ReleasePipelineModal"; export * from "./SelectConnectorResourceDialog"; -export * from "./StartNode"; +export * from "./start-node"; export * from "./PipelineToolkitModal"; diff --git a/packages/toolkit/src/view/pipeline-builder/components/start-node/StartNode.tsx b/packages/toolkit/src/view/pipeline-builder/components/start-node/StartNode.tsx new file mode 100644 index 00000000..bd17bc54 --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/components/start-node/StartNode.tsx @@ -0,0 +1,183 @@ +import * as React from "react"; +import * as z from "zod"; +import { isAxiosError } from "axios"; +import { NodeProps, Position } from "reactflow"; +import { shallow } from "zustand/shallow"; +import { StartNodeData } from "../../type"; +import { Button, Form, Icons, useToast } from "@instill-ai/design-system"; + +import { + PipelineBuilderStore, + usePipelineBuilderStore, +} from "../../usePipelineBuilderStore"; +import { + recursiveParseToNum, + recursiveRemoveUndefinedAndNullFromArray, + recursiveReplaceNullAndEmptyStringWithUndefined, +} from "../../lib"; +import { CustomHandle } from "../CustomHandle"; +import { useStartOperatorTestModeInputForm } from "../../use-node-input-fields"; +import { + getInstillApiErrorMessage, + useTriggerUserPipeline, +} from "../../../../lib"; +import { StartNodeInputForm } from "./StartNodeInputForm"; + +export const CreateStartOperatorInputSchema = z.object({ + title: z.string().min(1, { message: "Title is required" }), + key: z.string().min(1, { message: "Key is required" }), +}); + +const pipelineBuilderSelector = (state: PipelineBuilderStore) => ({ + pipelineIsNew: state.pipelineIsNew, + pipelineName: state.pipelineName, + nodes: state.nodes, + edges: state.edges, + testModeEnabled: state.testModeEnabled, + updateTestModeTriggerResponse: state.updateTestModeTriggerResponse, + accessToken: state.accessToken, +}); + +export const StartNode = ({ data, id }: NodeProps) => { + const [isTriggering, setIsTriggering] = React.useState(false); + + const { + pipelineName, + nodes, + edges, + testModeEnabled, + updateTestModeTriggerResponse, + accessToken, + } = usePipelineBuilderStore(pipelineBuilderSelector, shallow); + + const { toast } = useToast(); + + const { + Schema: StartOperatorTestModeInputSchema, + fields: startOperatorTestModeInputfields, + form: startOperatorTestModeInputForm, + } = useStartOperatorTestModeInputForm({ nodes }); + + const useTriggerPipeline = useTriggerUserPipeline(); + + const onTriggerPipeline = ( + data: z.infer + ) => { + if (!pipelineName) return; + + const input = recursiveRemoveUndefinedAndNullFromArray( + recursiveReplaceNullAndEmptyStringWithUndefined(recursiveParseToNum(data)) + ); + + setIsTriggering(true); + + useTriggerPipeline.mutate( + { + pipelineName, + accessToken, + payload: { + inputs: [input], + }, + returnTraces: true, + }, + { + onSuccess: (data) => { + setIsTriggering(false); + updateTestModeTriggerResponse(() => data); + }, + onError: (error) => { + setIsTriggering(false); + if (isAxiosError(error)) { + toast({ + title: "Something went wrong when trigger the pipeline", + variant: "alert-error", + size: "large", + description: getInstillApiErrorMessage(error), + }); + } else { + toast({ + title: "Something went wrong when trigger the pipeline", + variant: "alert-error", + size: "large", + description: "Please try again later", + }); + } + }, + } + ); + }; + + const hasSourceEdges = React.useMemo(() => { + return edges.some((edge) => edge.source === id); + }, [edges]); + + return ( + +
+
+

+ start +

+
+
+ {testModeEnabled ? ( + +
+
+ {...startOperatorTestModeInputfields} +
+
+ +
+
+
+ ) : ( + + )} +
+
+ +
+ ); +}; diff --git a/packages/toolkit/src/view/pipeline-builder/components/start-node/StartNodeInputForm.tsx b/packages/toolkit/src/view/pipeline-builder/components/start-node/StartNodeInputForm.tsx new file mode 100644 index 00000000..a61aeb18 --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/components/start-node/StartNodeInputForm.tsx @@ -0,0 +1,505 @@ +import cn from "clsx"; +import * as React from "react"; +import * as z from "zod"; +import { + Button, + Checkbox, + ComplicateIcons, + Form, + Icons, + Input, + Tag, +} from "@instill-ai/design-system"; +import { StartNodeInputType } from "../StartNodeInputType"; +import { + Nullable, + StartOperatorInputSingularType, + StartOperatorInputType, +} from "../../../../lib"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { + PipelineBuilderStore, + usePipelineBuilderStore, +} from "../../usePipelineBuilderStore"; +import { shallow } from "zustand/shallow"; +import { PipelineComponentReference, StartNodeData } from "../../type"; +import { + composeEdgesFromReferences, + extractReferencesFromConfiguration, +} from "../../lib"; + +export const Schema = z.object({ + title: z.string().min(1, { message: "Title is required" }), + key: z.string().min(1, { message: "Key is required" }), +}); + +const selector = (store: PipelineBuilderStore) => ({ + nodes: store.nodes, + updateNodes: store.updateNodes, + updateEdges: store.updateEdges, + updatePipelineRecipeIsDirty: store.updatePipelineRecipeIsDirty, + isLatestVersion: store.isLatestVersion, + isOwner: store.isOwner, +}); + +export const StartNodeInputForm = ({ data }: { data: StartNodeData }) => { + const { + nodes, + updateNodes, + updateEdges, + updatePipelineRecipeIsDirty, + isLatestVersion, + isOwner, + } = usePipelineBuilderStore(selector, shallow); + + const [enableEdit, setEnableEdit] = React.useState(false); + const [selectedType, setSelectedType] = + React.useState>(null); + const [prevFieldKey, setPrevFieldKey] = + React.useState>(null); + const [inputTypeIsArray, setInputTypeIsArray] = React.useState(false); + + const form = useForm>({ + resolver: zodResolver(Schema), + }); + + const onCreateInput = (formData: z.infer) => { + if (!selectedType) return; + + let finalType: StartOperatorInputType = selectedType; + + if (inputTypeIsArray) { + switch (selectedType) { + case "text": { + finalType = "text_array"; + break; + } + case "audio": { + finalType = "audio_array"; + break; + } + case "boolean": { + finalType = "boolean_array"; + break; + } + case "image": { + finalType = "image_array"; + break; + } + case "number": { + finalType = "number_array"; + break; + } + } + } + + const newNodes = nodes.map((node) => { + if (node.data.nodeType === "start") { + if (prevFieldKey) { + delete node.data.component.configuration.metadata[prevFieldKey]; + } + + node.data = { + ...node.data, + component: { + ...node.data.component, + configuration: { + ...node.data.component.configuration, + metadata: { + ...node.data.component.configuration.metadata, + [formData.key]: { + type: finalType, + title: formData.title, + }, + }, + }, + }, + }; + } + return node; + }); + + updateNodes(() => newNodes); + + const allReferences: PipelineComponentReference[] = []; + + newNodes.forEach((node) => { + if (node.data.component?.configuration) { + allReferences.push( + ...extractReferencesFromConfiguration( + node.data.component?.configuration, + node.id + ) + ); + } + }); + + const newEdges = composeEdgesFromReferences(allReferences, newNodes); + updateEdges(() => newEdges); + + setEnableEdit(false); + setSelectedType(null); + setPrevFieldKey(null); + setInputTypeIsArray(false); + updatePipelineRecipeIsDirty(() => true); + form.reset({ + title: "", + key: "", + }); + }; + + const onDeleteInput = (key: string) => { + const newNodes = nodes.map((node) => { + if (node.data.nodeType === "start") { + delete node.data.component.configuration.metadata[key]; + + node.data = { + ...node.data, + }; + } + return node; + }); + + updateNodes(() => newNodes); + + const allReferences: PipelineComponentReference[] = []; + + newNodes.forEach((node) => { + if (node.data.component?.configuration) { + allReferences.push( + ...extractReferencesFromConfiguration( + node.data.component?.configuration, + node.id + ) + ); + } + }); + + const newEdges = composeEdgesFromReferences(allReferences, newNodes); + updateEdges(() => newEdges); + updatePipelineRecipeIsDirty(() => true); + }; + + const onEditInput = (key: string) => { + form.reset({ + title: data.component.configuration.metadata[key].title, + key: key, + }); + setEnableEdit(true); + setSelectedType(() => { + let finalType = data.component.configuration.metadata[key].type; + + switch (finalType) { + case "text_array": { + finalType = "text"; + setInputTypeIsArray(true); + break; + } + case "audio_array": { + finalType = "audio"; + setInputTypeIsArray(true); + break; + } + case "boolean_array": { + finalType = "boolean"; + setInputTypeIsArray(true); + break; + } + case "image_array": { + finalType = "image"; + setInputTypeIsArray(true); + break; + } + case "number_array": { + finalType = "number"; + setInputTypeIsArray(true); + break; + } + } + + return finalType; + }); + }; + + return enableEdit ? ( + +
+
+ +
+ +
+
+
+ { + if (selectedType === "text") { + setSelectedType(null); + } else { + setSelectedType("text"); + } + setInputTypeIsArray(false); + }} + /> + { + if (selectedType === "number") { + setSelectedType(null); + } else { + setSelectedType("number"); + } + setInputTypeIsArray(false); + }} + /> + { + if (selectedType === "image") { + setSelectedType(null); + } else { + setSelectedType("image"); + } + setInputTypeIsArray(false); + }} + /> + { + if (selectedType === "audio") { + setSelectedType(null); + } else { + setSelectedType("audio"); + } + setInputTypeIsArray(false); + }} + /> + { + if (selectedType === "boolean") { + setSelectedType(null); + } else { + setSelectedType("boolean"); + } + setInputTypeIsArray(false); + }} + /> +
+ {["number", "image", "text", "audio"].includes(selectedType ?? "") ? ( +
+ { + if (typeof e === "boolean") { + setInputTypeIsArray(e); + } + }} + id="is_array" + className="my-auto h-4 w-4" + /> +
+ +
+
+ ) : null} +
+ { + return ( + + + Title + + + + + + + + + ); + }} + /> + { + return ( + + + Key + + + + + + + + + ); + }} + /> +
+
+
+ ) : ( +
+ {Object.entries(data.component.configuration.metadata).map( + ([key, value]) => { + let icon: Nullable = null; + + switch (value.type) { + case "text": + case "text_array": { + icon = ( + + ); + break; + } + case "audio": + case "audio_array": { + icon = ( + + ); + break; + } + case "boolean": + case "boolean_array": { + icon = ( + + ); + break; + } + case "image": + case "image_array": { + icon = ( + + ); + break; + } + case "number": + case "number_array": { + icon = ( + + ); + break; + } + default: + break; + } + + return ( +
+
+
+ {key} +
+ {isLatestVersion && isOwner ? ( +
+ + +
+ ) : null} +
+
+ + {icon} + {value.type} + +
+
+ ); + } + )} + +
+ ); +}; diff --git a/packages/toolkit/src/view/pipeline-builder/components/start-node/index.ts b/packages/toolkit/src/view/pipeline-builder/components/start-node/index.ts new file mode 100644 index 00000000..d46ae4e1 --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/components/start-node/index.ts @@ -0,0 +1 @@ +export * from "./StartNode";