From 935bd7cebd0427b4bcb0c095e0bc852f5b8fe8ad Mon Sep 17 00:00:00 2001 From: Po Chun Chiu <57251712+EiffelFly@users.noreply.github.com> Date: Sat, 1 Jun 2024 09:30:33 +0800 Subject: [PATCH] feat: adapt the new run on version pipeline recipe in console (#1191) Because - adapt the new run on version pipeline recipe in console This commit - adapt the new run on version pipeline recipe in console --- .../src/components/ClonePipelineDialog.tsx | 7 +- .../components/regular/SingleSelectField.tsx | 2 +- .../components/smart-hint/SmartHintList.tsx | 4 +- .../components/smart-hint/TextArea.tsx | 4 +- .../components/smart-hint/TextField.tsx | 4 +- .../components/smart-hint/onInputChange.tsx | 2 +- .../smart-hint/useFilteredHints.tsx | 4 +- .../pickPipelineTriggerRequestFormFields.tsx | 68 +++---- ...eTriggerRequestFieldsToSuperRefineRules.ts | 6 +- ...nsformPipelineTriggerRequestFieldsToZod.ts | 6 +- .../pickOutputReferenceHintsFromComponent.tsx | 115 +++++------ .../useOutputReferenceHintsFields.tsx | 3 + .../use-smart-hint/pickSmartHintsFromNodes.ts | 165 +++++----------- ...neTriggerRequestFieldsToSmartHints.test.ts | 16 +- ...ipelineTriggerRequestFieldsToSmartHints.ts | 6 +- .../lib/vdp-sdk/helper/checkIsDefinition.ts | 20 ++ .../toolkit/src/lib/vdp-sdk/helper/index.ts | 1 + packages/toolkit/src/lib/vdp-sdk/index.ts | 2 + .../toolkit/src/lib/vdp-sdk/pipeline/types.ts | 92 +++------ .../components/BackToLatestVersionTopBar.tsx | 2 +- .../pipeline-builder/components/BottomBar.tsx | 4 +- .../ComponentOutputReferenceHints.tsx | 7 +- .../components/PipelineBuilderCanvas.tsx | 6 +- .../components/PipelineToolkitDialog.tsx | 8 +- .../components/ReadOnlyPipelineBuilder.tsx | 8 +- .../iterator-editor/IteratorEditor.tsx | 22 +-- .../iterator-input/IterateElementHint.tsx | 4 +- .../iterator-input/IteratorInput.tsx | 18 +- .../iterator-output/AddOutputButton.tsx | 13 +- .../iterator-output/DeleteOutputButton.tsx | 11 +- .../iterator-output/IteratorOutput.tsx | 22 +-- .../iterator-output/OutputKeyField.tsx | 13 +- .../iterator-output/OutputValueInput.tsx | 15 +- .../iterator-output/OutputValueSelect.tsx | 19 +- .../components/nodes/common/NodeIDEditor.tsx | 9 +- .../components/nodes/common/NodeWrapper.tsx | 28 +-- .../ResourceNotCreatedWarning.tsx | 33 ---- .../components/nodes/connector-node/index.ts | 1 - ...rControlPanel.tsx => NodeControlPanel.tsx} | 59 ++---- .../components/nodes/control-panel/index.ts | 2 +- .../DataConnectorFreeForm.tsx | 149 +++++++-------- .../GeneralNode.tsx} | 65 ++++--- .../components/nodes/general-node/index.ts | 1 + .../components/nodes/index.ts | 3 +- .../iterator-node/IteratorComponentLable.tsx | 23 +-- .../nodes/iterator-node/IteratorNode.tsx | 51 ++--- .../nodes/operator-node/OperatorNode.tsx | 180 ------------------ .../components/nodes/operator-node/index.ts | 1 - .../nodes/response-node/ResponseNode.tsx | 24 +-- .../nodes/trigger-node/TriggerNode.tsx | 11 +- .../nodes/trigger-node/triggerNodeFields.tsx | 64 +++---- .../components/release-menu/ReleaseMenu.tsx | 4 +- ...elineGeneralComponentFormOnRightPanel.tsx} | 25 +-- .../components/right-panel/RightPanel.tsx | 27 +-- .../components/top-control-menu/Toolkit.tsx | 2 +- .../top-control-menu/TopControlMenu.tsx | 6 +- .../lib/checkComponentType.tsx | 19 +- .../lib/checkIsValidComponentMetadata.ts | 16 ++ .../lib/checkIsValidPosition.test.ts | 158 +++++++-------- .../lib/checkIsValidPosition.ts | 65 ++++--- .../pipeline-builder/lib/checkNodeType.tsx | 55 ++---- ...eCompleteNodesUnderEditingIteratorMode.tsx | 16 +- .../lib/composeEdgesFromNodes.test.ts | 30 +-- .../lib/composeEdgesFromNodes.ts | 39 ++-- .../composePipelineComponentMapFromNodes.ts | 66 +++++++ .../lib/composePipelineMetadataFromNodes.ts | 19 -- ...mposePipelineMetadataMapFromNodes.test.ts} | 43 +++-- .../composePipelineMetadataMapFromNodes.ts | 18 ++ .../lib/composePipelineRecipeFromNodes.tsx | 106 +++++++++++ .../lib/constructPipelineRecipeFromNodes.tsx | 137 ------------- .../lib/createGraphLayout.tsx | 10 +- .../lib/createNodesFromPipelineComponents.tsx | 72 ++----- .../lib/createNodesFromPipelineRecipe.tsx | 46 ++--- .../lib/extractComponentFromNodes.ts | 20 -- .../lib/getAllComponentID.tsx | 20 -- .../pipeline-builder/lib/getAllNodeID.tsx | 19 ++ .../lib/getConnectorInputOutputSchema.ts | 67 ------- ...ConnectorOperatorComponentConfiguration.ts | 23 --- .../lib/getGeneralComponentConfiguration.ts | 12 ++ .../lib/getGeneralComponentInOutputSchema.ts | 59 ++++++ .../lib/getOperatorInputOutputSchema.ts | 67 ------- .../view/pipeline-builder/lib/hooks/index.ts | 2 +- ...ition.tsx => useAddNodeWithDefinition.tsx} | 74 ++++--- .../lib/hooks/usePipelineBuilderGraph.tsx | 3 +- .../lib/hooks/useRenamePipeline.tsx | 12 +- .../lib/hooks/useSavePipeline.tsx | 13 +- .../lib/hooks/useUpdaterOnNode.tsx | 54 ++---- .../lib/hooks/useUpdaterOnRightPanel.tsx | 48 ++--- .../src/view/pipeline-builder/lib/index.ts | 12 +- .../lib/isTriggerByRequest.ts | 7 - .../toolkit/src/view/pipeline-builder/type.ts | 32 ++-- .../view/pipeline/view-pipeline/InOutPut.tsx | 65 ++----- .../view-pipelines/CreatePipelineDialog.tsx | 22 +-- 93 files changed, 1182 insertions(+), 1831 deletions(-) create mode 100644 packages/toolkit/src/lib/vdp-sdk/helper/checkIsDefinition.ts delete mode 100644 packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/ResourceNotCreatedWarning.tsx delete mode 100644 packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/index.ts rename packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/{ConnectorOperatorControlPanel.tsx => NodeControlPanel.tsx} (82%) rename packages/toolkit/src/view/pipeline-builder/components/nodes/{connector-node => general-node}/DataConnectorFreeForm.tsx (63%) rename packages/toolkit/src/view/pipeline-builder/components/nodes/{connector-node/ConnectorNode.tsx => general-node/GeneralNode.tsx} (78%) create mode 100644 packages/toolkit/src/view/pipeline-builder/components/nodes/general-node/index.ts delete mode 100644 packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/OperatorNode.tsx delete mode 100644 packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/index.ts rename packages/toolkit/src/view/pipeline-builder/components/right-panel/{ComponentFormOnRightPanel.tsx => PipelineGeneralComponentFormOnRightPanel.tsx} (62%) create mode 100644 packages/toolkit/src/view/pipeline-builder/lib/checkIsValidComponentMetadata.ts create mode 100644 packages/toolkit/src/view/pipeline-builder/lib/composePipelineComponentMapFromNodes.ts delete mode 100644 packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataFromNodes.ts rename packages/toolkit/src/view/pipeline-builder/lib/{composePipelineMetadataFromNodes.test.ts => composePipelineMetadataMapFromNodes.test.ts} (52%) create mode 100644 packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataMapFromNodes.ts create mode 100644 packages/toolkit/src/view/pipeline-builder/lib/composePipelineRecipeFromNodes.tsx delete mode 100644 packages/toolkit/src/view/pipeline-builder/lib/constructPipelineRecipeFromNodes.tsx delete mode 100644 packages/toolkit/src/view/pipeline-builder/lib/extractComponentFromNodes.ts delete mode 100644 packages/toolkit/src/view/pipeline-builder/lib/getAllComponentID.tsx create mode 100644 packages/toolkit/src/view/pipeline-builder/lib/getAllNodeID.tsx delete mode 100644 packages/toolkit/src/view/pipeline-builder/lib/getConnectorInputOutputSchema.ts delete mode 100644 packages/toolkit/src/view/pipeline-builder/lib/getConnectorOperatorComponentConfiguration.ts create mode 100644 packages/toolkit/src/view/pipeline-builder/lib/getGeneralComponentConfiguration.ts create mode 100644 packages/toolkit/src/view/pipeline-builder/lib/getGeneralComponentInOutputSchema.ts delete mode 100644 packages/toolkit/src/view/pipeline-builder/lib/getOperatorInputOutputSchema.ts rename packages/toolkit/src/view/pipeline-builder/lib/hooks/{useConstructNodeFromDefinition.tsx => useAddNodeWithDefinition.tsx} (76%) delete mode 100644 packages/toolkit/src/view/pipeline-builder/lib/isTriggerByRequest.ts diff --git a/packages/toolkit/src/components/ClonePipelineDialog.tsx b/packages/toolkit/src/components/ClonePipelineDialog.tsx index eaf8b97c3..cdad6c9a5 100644 --- a/packages/toolkit/src/components/ClonePipelineDialog.tsx +++ b/packages/toolkit/src/components/ClonePipelineDialog.tsx @@ -141,12 +141,7 @@ export const ClonePipelineDialog = ({ const payload: CreateUserPipelinePayload = { id: data.id, - recipe: { - version: pipeline.recipe.version, - trigger: pipeline.recipe.trigger, - components: pipeline.recipe.components, - }, - + recipe: pipeline.recipe, metadata: pipeline.metadata, readme: pipeline.readme, description: data.brief ? data.brief : pipeline.description, diff --git a/packages/toolkit/src/lib/use-instill-form/components/regular/SingleSelectField.tsx b/packages/toolkit/src/lib/use-instill-form/components/regular/SingleSelectField.tsx index c44e81a75..408d60ec3 100644 --- a/packages/toolkit/src/lib/use-instill-form/components/regular/SingleSelectField.tsx +++ b/packages/toolkit/src/lib/use-instill-form/components/regular/SingleSelectField.tsx @@ -91,7 +91,7 @@ export const SingleSelectField = ({ ) { form.setValue( currentCredentialFieldPath, - "${secrets." + `${InstillCredit.key}` + "}" + "${secret." + `${InstillCredit.key}` + "}" ); if (updateForceCloseCollapsibleFormGroups) { diff --git a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/SmartHintList.tsx b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/SmartHintList.tsx index b4bf39a37..fc60f9b94 100644 --- a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/SmartHintList.tsx +++ b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/SmartHintList.tsx @@ -103,7 +103,7 @@ export const SmartHintList = ({ > {hint.isInstillCreditHint ? (
-

{`secrets.${InstillCredit.key}`}

+

{`secret.${InstillCredit.key}`}

@@ -151,7 +151,7 @@ export const SmartHintList = ({

{instillCredential ? supportInstillCredit - ? "This configuration supports Instill Credit, You can use Instill Credit by input ${secrets." + + ? "This configuration supports Instill Credit, You can use Instill Credit by input ${secret." + InstillCredit.key + "}." : "This configuration didn't support Instill Credit, please reference your own secret" diff --git a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/TextArea.tsx b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/TextArea.tsx index a3bd93f76..a8f18d9e7 100644 --- a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/TextArea.tsx +++ b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/TextArea.tsx @@ -240,8 +240,8 @@ export const TextArea = ({ supportInstillCredit && instillCredential ? `${title} supports Instill Credit. You can use Instill Credit by input ` + "${" + - `secrets.${InstillCredit.key}` + - "}. You can still bring your own key by input ${secrets.your_secret}" + `secret.${InstillCredit.key}` + + "}. You can still bring your own key by input ${secret.your_secret}" : shortDescription ?? null } /> diff --git a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/TextField.tsx b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/TextField.tsx index d93bca708..7ec523102 100644 --- a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/TextField.tsx +++ b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/TextField.tsx @@ -252,8 +252,8 @@ export const TextField = ({ supportInstillCredit && instillCredential ? `${title} supports Instill Credit. You can use Instill Credit by input ` + "${" + - `secrets.${InstillCredit.key}` + - "}. You can still bring your own key by input ${secrets.your_secret}" + `secret.${InstillCredit.key}` + + "}. You can still bring your own key by input ${secret.your_secret}" : shortDescription ?? null } /> diff --git a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/onInputChange.tsx b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/onInputChange.tsx index dfce3fdbd..908e00693 100644 --- a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/onInputChange.tsx +++ b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/onInputChange.tsx @@ -83,7 +83,7 @@ export function onInputChange({ if (supportInstillCredit && updateIsUsingInstillCredit) { if ( event.target.value.trim().replace("${", "").replace("}", "") !== - `secrets.${InstillCredit.key}` + `secret.${InstillCredit.key}` ) { updateIsUsingInstillCredit(false); } else { diff --git a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/useFilteredHints.tsx b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/useFilteredHints.tsx index 6ae911905..0a870a01b 100644 --- a/packages/toolkit/src/lib/use-instill-form/components/smart-hint/useFilteredHints.tsx +++ b/packages/toolkit/src/lib/use-instill-form/components/smart-hint/useFilteredHints.tsx @@ -44,7 +44,7 @@ export function useFilteredHints({ if (instillSecret && secrets) { allHints = secrets.map((secret) => ({ key: secret.id, - path: `secrets.${secret.id}`, + path: `secret.${secret.id}`, instillFormat: "string", type: "string", properties: [], @@ -56,7 +56,7 @@ export function useFilteredHints({ ...allHints, { key: "instillCredit", - path: `secrets.${InstillCredit.key}`, + path: `secret.${InstillCredit.key}`, instillFormat: "string", type: "string", isInstillCreditHint: true, diff --git a/packages/toolkit/src/lib/use-instill-form/pick/pickPipelineTriggerRequestFormFields.tsx b/packages/toolkit/src/lib/use-instill-form/pick/pickPipelineTriggerRequestFormFields.tsx index bdb3d6b8c..3d391d2d2 100644 --- a/packages/toolkit/src/lib/use-instill-form/pick/pickPipelineTriggerRequestFormFields.tsx +++ b/packages/toolkit/src/lib/use-instill-form/pick/pickPipelineTriggerRequestFormFields.tsx @@ -2,7 +2,7 @@ import { UseFormReturn } from "react-hook-form"; import { Nullable } from "../../type"; import { TriggerRequestFormFields } from "../components"; import { FieldMode, StartOperatorFreeFormFieldItem } from "../types"; -import { PipelineTriggerRequestFields } from "../../vdp-sdk"; +import { PipelineVariableFieldMap } from "../../vdp-sdk"; export type PickPipelineTriggerRequestFormFieldsProps = { mode: FieldMode; @@ -15,7 +15,7 @@ export type PickPipelineTriggerRequestFormFieldsProps = { disabledFields?: boolean; disabledFieldControls?: boolean; disabledReferenceHint?: boolean; - fields: Nullable; + fields: Nullable; }; export function pickPipelineTriggerRequestFormFields({ @@ -37,12 +37,12 @@ export function pickPipelineTriggerRequestFormFields({ // is we want to sort the fields by the order of `instillUIOrder` property. for (const [key, value] of Object.entries(fields)) { - switch (value.instill_format) { + switch (value.instillFormat) { case "string": - if (value.instill_ui_multiline) { + if (value.instillUiMultiline) { items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); } else { items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -88,7 +88,7 @@ export function pickPipelineTriggerRequestFormFields({ case "array:string": { items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -112,7 +112,7 @@ export function pickPipelineTriggerRequestFormFields({ case "boolean": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -135,7 +135,7 @@ export function pickPipelineTriggerRequestFormFields({ case "number": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -158,7 +158,7 @@ export function pickPipelineTriggerRequestFormFields({ case "array:number": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -181,7 +181,7 @@ export function pickPipelineTriggerRequestFormFields({ case "audio/*": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -204,7 +204,7 @@ export function pickPipelineTriggerRequestFormFields({ case "array:audio/*": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -227,7 +227,7 @@ export function pickPipelineTriggerRequestFormFields({ case "image/*": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -250,7 +250,7 @@ export function pickPipelineTriggerRequestFormFields({ case "array:image/*": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -274,7 +274,7 @@ export function pickPipelineTriggerRequestFormFields({ case "video/*": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -297,7 +297,7 @@ export function pickPipelineTriggerRequestFormFields({ case "array:video/*": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -320,7 +320,7 @@ export function pickPipelineTriggerRequestFormFields({ case "*/*": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -343,7 +343,7 @@ export function pickPipelineTriggerRequestFormFields({ case "array:*/*": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); @@ -366,7 +366,7 @@ export function pickPipelineTriggerRequestFormFields({ case "semi-structured/json": items.push({ key, - instillUIOrder: value.instill_ui_order, + instillUIOrder: value.instillUiOrder, component: ( ), }); diff --git a/packages/toolkit/src/lib/use-instill-form/transform/transformPipelineTriggerRequestFieldsToSuperRefineRules.ts b/packages/toolkit/src/lib/use-instill-form/transform/transformPipelineTriggerRequestFieldsToSuperRefineRules.ts index 2f889eb6f..3abbe1b83 100644 --- a/packages/toolkit/src/lib/use-instill-form/transform/transformPipelineTriggerRequestFieldsToSuperRefineRules.ts +++ b/packages/toolkit/src/lib/use-instill-form/transform/transformPipelineTriggerRequestFieldsToSuperRefineRules.ts @@ -1,15 +1,15 @@ import { Nullable, SuperRefineRule } from "../../type"; -import { PipelineTriggerRequestFields } from "../../vdp-sdk"; +import { PipelineVariableFieldMap } from "../../vdp-sdk"; export function transformPipelineTriggerRequestFieldsToSuperRefineRules( - fields: Nullable + fields: Nullable ) { const rules: SuperRefineRule[] = []; if (!fields) return rules; for (const [key, value] of Object.entries(fields)) { - switch (value.instill_format) { + switch (value.instillFormat) { case "string": rules.push({ key, diff --git a/packages/toolkit/src/lib/use-instill-form/transform/transformPipelineTriggerRequestFieldsToZod.ts b/packages/toolkit/src/lib/use-instill-form/transform/transformPipelineTriggerRequestFieldsToZod.ts index 3550ad3aa..5da11f880 100644 --- a/packages/toolkit/src/lib/use-instill-form/transform/transformPipelineTriggerRequestFieldsToZod.ts +++ b/packages/toolkit/src/lib/use-instill-form/transform/transformPipelineTriggerRequestFieldsToZod.ts @@ -2,17 +2,17 @@ import * as z from "zod"; import { Nullable } from "../../type"; -import { PipelineTriggerRequestFields } from "../../vdp-sdk"; +import { PipelineVariableFieldMap } from "../../vdp-sdk"; export function transformPipelineTriggerRequestFieldsToZod( - fields: Nullable + fields: Nullable ) { let zodSchema: z.ZodObject = z.object({}); if (!fields) return zodSchema; for (const [key, value] of Object.entries(fields)) { - switch (value.instill_format) { + switch (value.instillFormat) { case "string": zodSchema = zodSchema.setKey(key, z.string().nullable().optional()); break; diff --git a/packages/toolkit/src/lib/use-smart-hint/output-reference-hint/pickOutputReferenceHintsFromComponent.tsx b/packages/toolkit/src/lib/use-smart-hint/output-reference-hint/pickOutputReferenceHintsFromComponent.tsx index 29cfe7999..cbe3211ac 100644 --- a/packages/toolkit/src/lib/use-smart-hint/output-reference-hint/pickOutputReferenceHintsFromComponent.tsx +++ b/packages/toolkit/src/lib/use-smart-hint/output-reference-hint/pickOutputReferenceHintsFromComponent.tsx @@ -1,94 +1,68 @@ -import { getConnectorInputOutputSchema } from "../../../view"; +import { getGeneralComponentInOutputSchema } from "../../../view"; import { - isConnectorComponent, - isIteratorComponent, - isOperatorComponent, + isPipelineGeneralComponent, + isPipelineIteratorComponent, } from "../../../view/pipeline-builder/lib/checkComponentType"; -import { getOperatorInputOutputSchema } from "../../../view/pipeline-builder/lib/getOperatorInputOutputSchema"; import { transformInstillJSONSchemaToFormTree } from "../../use-instill-form/transform"; import { PipelineComponent } from "../../vdp-sdk"; import { transformFormTreeToSmartHints } from "../transformFormTreeToSmartHints"; import { SmartHint } from "../types"; export function pickOutputReferenceHintsFromComponent({ + componentID, component, task, consoleComposedIteratorSchema, }: { + componentID: string; component: PipelineComponent; task?: string; consoleComposedIteratorSchema?: boolean; }) { let outputReferenceHints: SmartHint[] = []; - if (isConnectorComponent(component)) { - const { outputSchema } = getConnectorInputOutputSchema(component, task); - - if (outputSchema) { - const outputFormTree = transformInstillJSONSchemaToFormTree(outputSchema); - const hints = transformFormTreeToSmartHints(outputFormTree, component.id); - - outputReferenceHints = [...outputReferenceHints, ...hints]; - } - } - - if (isOperatorComponent(component)) { - const { outputSchema } = getOperatorInputOutputSchema(component, task); - - if (outputSchema) { - const outputFormTree = transformInstillJSONSchemaToFormTree(outputSchema); - const hints = transformFormTreeToSmartHints(outputFormTree, component.id); - - outputReferenceHints = [...outputReferenceHints, ...hints]; - } - } - - if (isIteratorComponent(component)) { + if (isPipelineIteratorComponent(component)) { let iteratorHints: SmartHint[] = []; if (consoleComposedIteratorSchema) { - Object.entries(component.iterator_component.output_elements).forEach( - ([key, value]) => { - const referencePathArray = value - .replace("${", "") - .replace("}", "") - .split("."); - - const componentKey = referencePathArray[0]; - const targetComponent = component.iterator_component.components.find( - (e) => e.id === componentKey + Object.entries(component.outputElements).forEach(([key, value]) => { + const referencePathArray = value + .replace("${", "") + .replace("}", "") + .split("."); + + const componentKey = referencePathArray[0]; + const targetComponent = component.component[componentKey]; + + if (targetComponent) { + const componentHints = pickOutputReferenceHintsFromComponent({ + component: targetComponent, + componentID: componentKey, + }); + + const targetHint = componentHints.find( + (hint) => hint.path === value.replace("${", "").replace("}", "") ); - if (targetComponent) { - const componentHints = pickOutputReferenceHintsFromComponent({ - component: targetComponent, - }); - - const targetHint = componentHints.find( - (hint) => hint.path === value.replace("${", "").replace("}", "") - ); - - if (targetHint) { - iteratorHints.push(targetHint); - } + if (targetHint) { + iteratorHints.push(targetHint); + } - // Deal with user directly reference the whole output of specific component in - // the iterator - if (value === "${" + targetComponent.id + ".output" + "}") { - iteratorHints.push({ - path: `${component.id}.output.${key}`, - key, - instillFormat: "null", - type: "array", - properties: componentHints, - }); - } + // Deal with user directly reference the whole output of specific component in + // the iterator + if (value === "${" + componentKey + ".output" + "}") { + iteratorHints.push({ + path: `${componentKey}.output.${key}`, + key, + instillFormat: "null", + type: "array", + properties: componentHints, + }); } } - ); + }); } else { - const outputSchema = - component.iterator_component.data_specification?.output; + const outputSchema = component.data_specification?.output; if (outputSchema) { const outputFormTree = @@ -96,7 +70,7 @@ export function pickOutputReferenceHintsFromComponent({ iteratorHints = transformFormTreeToSmartHints( outputFormTree, - component.id + componentID ); } } @@ -104,5 +78,16 @@ export function pickOutputReferenceHintsFromComponent({ outputReferenceHints = [...outputReferenceHints, ...iteratorHints]; } + if (isPipelineGeneralComponent(component)) { + const { outputSchema } = getGeneralComponentInOutputSchema(component, task); + + if (outputSchema) { + const outputFormTree = transformInstillJSONSchemaToFormTree(outputSchema); + const hints = transformFormTreeToSmartHints(outputFormTree, componentID); + + outputReferenceHints = [...outputReferenceHints, ...hints]; + } + } + return outputReferenceHints; } diff --git a/packages/toolkit/src/lib/use-smart-hint/output-reference-hint/useOutputReferenceHintsFields.tsx b/packages/toolkit/src/lib/use-smart-hint/output-reference-hint/useOutputReferenceHintsFields.tsx index 5a13ab42b..581c8d2a5 100644 --- a/packages/toolkit/src/lib/use-smart-hint/output-reference-hint/useOutputReferenceHintsFields.tsx +++ b/packages/toolkit/src/lib/use-smart-hint/output-reference-hint/useOutputReferenceHintsFields.tsx @@ -7,9 +7,11 @@ import { pickOutputReferenceHintsFromComponent } from "./pickOutputReferenceHint import { pickFieldsFromOutputReferenceHints } from "./pickFieldsFromOutputReferenceHints"; export function useOutputReferenceHintFields({ + componentID, component, task, }: { + componentID: string; component: Nullable; task?: string; }) { @@ -19,6 +21,7 @@ export function useOutputReferenceHintFields({ } const hints = pickOutputReferenceHintsFromComponent({ + componentID, component, task, }); diff --git a/packages/toolkit/src/lib/use-smart-hint/pickSmartHintsFromNodes.ts b/packages/toolkit/src/lib/use-smart-hint/pickSmartHintsFromNodes.ts index ad11fd9f0..8b664a94a 100644 --- a/packages/toolkit/src/lib/use-smart-hint/pickSmartHintsFromNodes.ts +++ b/packages/toolkit/src/lib/use-smart-hint/pickSmartHintsFromNodes.ts @@ -2,22 +2,20 @@ import { Node } from "reactflow"; import { IteratorNodeData, NodeData, - getConnectorInputOutputSchema, - isConnectorNode, - isIteratorNode, - isOperatorNode, - isTriggerNode, + getGeneralComponentInOutputSchema, } from "../../view"; -import { - isConnectorComponent, - isOperatorComponent, -} from "../../view/pipeline-builder/lib/checkComponentType"; + import { SmartHint } from "./types"; import { transformInstillJSONSchemaToFormTree } from "../use-instill-form/transform"; import { transformFormTreeToSmartHints } from "./transformFormTreeToSmartHints"; import { transformPipelineTriggerRequestFieldsToSmartHints } from "./transformPipelineTriggerRequestFieldsToSmartHints"; -import { getOperatorInputOutputSchema } from "../../view/pipeline-builder/lib/getOperatorInputOutputSchema"; import { PipelineIteratorComponent } from "../vdp-sdk"; +import { + isGeneralNode, + isIteratorNode, + isTriggerNode, +} from "../../view/pipeline-builder/lib/checkNodeType"; +import { isPipelineGeneralComponent } from "../../view/pipeline-builder/lib/checkComponentType"; export function pickSmartHintsFromNodes({ nodes, @@ -50,36 +48,8 @@ export function pickSmartHintsFromNodes({ continue; } - if (isConnectorNode(node)) { - const { outputSchema } = getConnectorInputOutputSchema(node.data); - - if (outputSchema) { - const outputFormTree = - transformInstillJSONSchemaToFormTree(outputSchema); - - const hints = transformFormTreeToSmartHints(outputFormTree, node.id); - - smartHints = [...smartHints, ...hints]; - } - - if (!isEditingIterator) { - smartHints = [ - ...smartHints, - { - path: `${node.id}.output`, - key: "output", - instillFormat: "semi-structured/json", - type: "object", - properties: [], - }, - ]; - } - - continue; - } - - if (isOperatorNode(node)) { - const { outputSchema } = getOperatorInputOutputSchema(node.data); + if (isGeneralNode(node)) { + const { outputSchema } = getGeneralComponentInOutputSchema(node.data); if (outputSchema) { const outputFormTree = @@ -112,90 +82,59 @@ export function pickSmartHintsFromNodes({ // The data_specification.output may not be ready due to user haven't // save the changes. - // The current solution is treating the iterator.output_elements as + // The current solution is treating the iterator.outputElements as // the source of truth instead of its data_specification.output /* - * output_elements = { + * outputElements = { * result_0: "${connector_1.output.result}", * } */ const consoleGeneratedHints: SmartHint[] = []; - Object.entries(node.data.iterator_component.output_elements).forEach( - ([key, value]) => { - const componentKey = value - .replace("${", "") - .replace("}", "") - .split(".")[0]; - - // Get target component's type - const component = ( - node.data as PipelineIteratorComponent - ).iterator_component.components.find( - (component) => component.id === componentKey - ); - - if (component) { - if (isConnectorComponent(component)) { - const { outputSchema } = getConnectorInputOutputSchema(component); - if (outputSchema) { - const outputFormTree = - transformInstillJSONSchemaToFormTree(outputSchema); - const hints = transformFormTreeToSmartHints( - outputFormTree, - component.id - ); - - const targetHint = hints.find( - (hint) => - hint.path === value.replace("${", "").replace("}", "") - ); - - if (targetHint) { - // Iterator exposed output format will be similar to - // iterator_0.output.result_0 - consoleGeneratedHints.push({ - key, - path: `${node.id}.output.${key}`, - instillFormat: targetHint.instillFormat, - type: targetHint.type, - description: targetHint.description, - }); - } - } - } + Object.entries(node.data.outputElements).forEach(([key, value]) => { + const componentKey = value + .replace("${", "") + .replace("}", "") + .split(".")[0]; + + // Get target component's type + const component = (node.data as PipelineIteratorComponent).component[ + componentKey + ]; - if (isOperatorComponent(component)) { - const { outputSchema } = getOperatorInputOutputSchema(component); - if (outputSchema) { - const outputFormTree = - transformInstillJSONSchemaToFormTree(outputSchema); - const hints = transformFormTreeToSmartHints( - outputFormTree, - component.id - ); - - const targetHint = hints.find( - (hint) => - hint.path === value.replace("${", "").replace("}", "") - ); - - if (targetHint) { - consoleGeneratedHints.push({ - key, - path: `${node.id}.output.${key}`, - instillFormat: targetHint.instillFormat, - type: targetHint.type, - description: targetHint.description, - }); - } + if (component) { + if (isPipelineGeneralComponent(component)) { + const { outputSchema } = + getGeneralComponentInOutputSchema(component); + if (outputSchema) { + const outputFormTree = + transformInstillJSONSchemaToFormTree(outputSchema); + const hints = transformFormTreeToSmartHints( + outputFormTree, + componentKey + ); + + const targetHint = hints.find( + (hint) => hint.path === value.replace("${", "").replace("}", "") + ); + + if (targetHint) { + // Iterator exposed output format will be similar to + // iterator_0.output.result_0 + consoleGeneratedHints.push({ + key, + path: `${node.id}.output.${key}`, + instillFormat: targetHint.instillFormat, + type: targetHint.type, + description: targetHint.description, + }); } } } } - ); + }); smartHints = [...smartHints, ...consoleGeneratedHints]; @@ -217,16 +156,14 @@ export function pickSmartHintsFromNodes({ // Add the iterator element into the hints if (isEditingIterator && includeEditorElement && editingIteratorID) { const targetIteratorNode = tempSavedNodesForEditingIteratorFlow?.find( - (node) => node.data.id === editingIteratorID && isIteratorNode(node) + (node) => node.id === editingIteratorID && isIteratorNode(node) ) as Node | undefined; if (targetIteratorNode) { const targetHints = smartHints.find( (hint) => hint.path === - targetIteratorNode.data.iterator_component.input - .replace("${", "") - .replace("}", "") + targetIteratorNode.data.input.replace("${", "").replace("}", "") ); if (targetHints) { diff --git a/packages/toolkit/src/lib/use-smart-hint/transformPipelineTriggerRequestFieldsToSmartHints.test.ts b/packages/toolkit/src/lib/use-smart-hint/transformPipelineTriggerRequestFieldsToSmartHints.test.ts index e40a6eef1..ed9678259 100644 --- a/packages/toolkit/src/lib/use-smart-hint/transformPipelineTriggerRequestFieldsToSmartHints.test.ts +++ b/packages/toolkit/src/lib/use-smart-hint/transformPipelineTriggerRequestFieldsToSmartHints.test.ts @@ -1,15 +1,15 @@ import { test, expect } from "vitest"; -import { PipelineTriggerRequestFields } from "../vdp-sdk"; import { transformPipelineTriggerRequestFieldsToSmartHints } from "./transformPipelineTriggerRequestFieldsToSmartHints"; +import { PipelineVariableFieldMap } from "../vdp-sdk"; -test("should transform pipeline trigger request fields to smart hints", () => { - const fields: PipelineTriggerRequestFields = { +test("should transform pipeline variables to smart hints", () => { + const fields: PipelineVariableFieldMap = { text: { - instill_format: "string", + instillFormat: "string", title: "Foo", }, audio: { - instill_format: "audio/*", + instillFormat: "audio/*", title: "Audio", }, }; @@ -38,13 +38,13 @@ test("should transform start operator metadata to smart hints with empty metadat }); test("should transform array metadata to smart hints", () => { - const fields: PipelineTriggerRequestFields = { + const fields: PipelineVariableFieldMap = { text: { - instill_format: "array:string", + instillFormat: "array:string", title: "Text", }, images: { - instill_format: "array:image/*", + instillFormat: "array:image/*", title: "Images", }, }; diff --git a/packages/toolkit/src/lib/use-smart-hint/transformPipelineTriggerRequestFieldsToSmartHints.ts b/packages/toolkit/src/lib/use-smart-hint/transformPipelineTriggerRequestFieldsToSmartHints.ts index aab181b03..f1c79f6a0 100644 --- a/packages/toolkit/src/lib/use-smart-hint/transformPipelineTriggerRequestFieldsToSmartHints.ts +++ b/packages/toolkit/src/lib/use-smart-hint/transformPipelineTriggerRequestFieldsToSmartHints.ts @@ -1,15 +1,15 @@ -import { PipelineTriggerRequestFields } from "../vdp-sdk"; +import { PipelineVariableFieldMap } from "../vdp-sdk"; import { SmartHint } from "./types"; export function transformPipelineTriggerRequestFieldsToSmartHints( - fields: PipelineTriggerRequestFields + fields: PipelineVariableFieldMap ): SmartHint[] { const hints: SmartHint[] = []; for (const [key, value] of Object.entries(fields)) { hints.push({ path: `trigger.${key}`, key: key, - instillFormat: value.instill_format ?? "null", + instillFormat: value.instillFormat ?? "null", type: "null", }); } diff --git a/packages/toolkit/src/lib/vdp-sdk/helper/checkIsDefinition.ts b/packages/toolkit/src/lib/vdp-sdk/helper/checkIsDefinition.ts new file mode 100644 index 000000000..d74557b07 --- /dev/null +++ b/packages/toolkit/src/lib/vdp-sdk/helper/checkIsDefinition.ts @@ -0,0 +1,20 @@ +import { ConnectorDefinition } from "../connector"; +import { IteratorDefinition, OperatorDefinition } from "../pipeline"; + +export function isConnectorDefinition( + definition: IteratorDefinition | ConnectorDefinition | OperatorDefinition +): definition is ConnectorDefinition { + return "type" in definition; +} + +export function isIteratorDefinition( + definition: IteratorDefinition | ConnectorDefinition | OperatorDefinition +): definition is IteratorDefinition { + return definition.id === "iterator"; +} + +export function isOperatorDefinition( + definition: IteratorDefinition | ConnectorDefinition | OperatorDefinition +): definition is OperatorDefinition { + return definition.name.startsWith("operator-definitions"); +} diff --git a/packages/toolkit/src/lib/vdp-sdk/helper/index.ts b/packages/toolkit/src/lib/vdp-sdk/helper/index.ts index cea67abff..2e503a210 100644 --- a/packages/toolkit/src/lib/vdp-sdk/helper/index.ts +++ b/packages/toolkit/src/lib/vdp-sdk/helper/index.ts @@ -1,3 +1,4 @@ +export * from "./checkIsDefinition"; export { createInstillAxiosClient } from "./createInstillAxiosClient"; export { getQueryString } from "./getQueryString"; export { getInstillApiErrorMessage } from "./getInstillApiErrorMessage"; diff --git a/packages/toolkit/src/lib/vdp-sdk/index.ts b/packages/toolkit/src/lib/vdp-sdk/index.ts index 804cb203f..c79a54701 100644 --- a/packages/toolkit/src/lib/vdp-sdk/index.ts +++ b/packages/toolkit/src/lib/vdp-sdk/index.ts @@ -8,3 +8,5 @@ export * from "./operation"; export * from "./organization"; export * from "./pipeline"; export * from "./types"; + +export * from "./helper"; diff --git a/packages/toolkit/src/lib/vdp-sdk/pipeline/types.ts b/packages/toolkit/src/lib/vdp-sdk/pipeline/types.ts index 26a8fbc5f..ffc4a0a66 100644 --- a/packages/toolkit/src/lib/vdp-sdk/pipeline/types.ts +++ b/packages/toolkit/src/lib/vdp-sdk/pipeline/types.ts @@ -21,48 +21,31 @@ export type PipelineReleaseState = | "STATE_ERROR" | "STATE_DELETED"; -export type PipelineTrigger = - | TriggerByRequest - | GeneralRecord - | Record; - export type PipelineRecipe = { version: string; - components: PipelineComponent[]; - trigger: PipelineTrigger; + component?: PipelineComponentMap; + variable?: PipelineVariableFieldMap; + output?: PipelineOutputFieldMap; }; -export type PipelineTriggerRequestField = { +export type PipelineVariableField = { title: string; description?: string; - instill_format: string; - instill_ui_order?: number; - instill_ui_multiline?: boolean; + instillFormat: string; + instillUiOrder?: number; + instillUiMultiline?: boolean; }; -export type PipelineTriggerRequestFields = Record< - string, - PipelineTriggerRequestField ->; +export type PipelineVariableFieldMap = Record; -export type PipelineTriggerResponseField = { +export type PipelineOutputField = { title: string; description?: string; value: string; - instill_ui_order?: number; + instillUiOrder?: number; }; -export type PipelineTriggerResponseFields = Record< - string, - PipelineTriggerResponseField ->; - -export type TriggerByRequest = { - trigger_by_request: { - request_fields?: PipelineTriggerRequestFields; - response_fields?: PipelineTriggerResponseFields; - }; -}; +export type PipelineOutputFieldMap = Record; export type PipelineReleaseWatchState = { state: PipelineReleaseState; @@ -167,47 +150,32 @@ export type PipelineTriggerMetadata = { traces: Record; }; -export type PipelineConnectorComponent = { - id: string; +export type ComponentBasicFields = { metadata?: GeneralRecord; - connector_component: { - definition_name: string; - definition?: Nullable; - task: string; - input: GeneralRecord; - condition: Nullable; - connection: GeneralRecord; - }; + type: string; }; -export type PipelineOperatorComponent = { - id: string; - metadata?: GeneralRecord; - operator_component: { - definition_name: string; - definition?: Nullable; - task: string; - input: GeneralRecord; - condition: Nullable; - }; -}; +export type PipelineGeneralComponent = { + definition?: Nullable; + task: string; + input: GeneralRecord; + condition: Nullable; + connection: Nullable; +} & ComponentBasicFields; export type PipelineIteratorComponent = { - id: string; - metadata?: GeneralRecord; - iterator_component: { - input: string; - output_elements: Record; - components: PipelineComponent[]; - condition: Nullable; - data_specification: Nullable; - }; -}; + input: string; + outputElements: Record; + component: PipelineComponentMap; + condition: Nullable; + data_specification: Nullable; +} & ComponentBasicFields; + +export type PipelineComponentMap = Record; export type PipelineComponent = - | PipelineConnectorComponent - | PipelineOperatorComponent - | PipelineIteratorComponent; + | PipelineIteratorComponent + | PipelineGeneralComponent; export type StartOperatorInputType = | "audio/*" diff --git a/packages/toolkit/src/view/pipeline-builder/components/BackToLatestVersionTopBar.tsx b/packages/toolkit/src/view/pipeline-builder/components/BackToLatestVersionTopBar.tsx index f0c7fa365..963999610 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/BackToLatestVersionTopBar.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/BackToLatestVersionTopBar.tsx @@ -71,7 +71,7 @@ export const BackToLatestVersionTopBar = () => { if ( checkIsValidPosition({ - components: pipeline.data.recipe.components, + component: pipeline.data.recipe.component ?? null, metadata: pipeline.data.metadata ?? null, }) ) { diff --git a/packages/toolkit/src/view/pipeline-builder/components/BottomBar.tsx b/packages/toolkit/src/view/pipeline-builder/components/BottomBar.tsx index b644d4d2e..c4f876124 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/BottomBar.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/BottomBar.tsx @@ -108,7 +108,7 @@ export const BottomBar = () => { if ( checkIsValidPosition({ - components: pipeline.data.recipe.components, + component: pipeline.data.recipe.component ?? null, metadata: pipeline.data.metadata ?? null, }) ) { @@ -156,7 +156,7 @@ export const BottomBar = () => { if ( checkIsValidPosition({ - components: release.recipe.components, + component: release.recipe.component ?? null, metadata: release.metadata ?? null, }) ) { diff --git a/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputReferenceHints.tsx b/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputReferenceHints.tsx index 2ea17c20e..671eb9a7b 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputReferenceHints.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputReferenceHints.tsx @@ -4,16 +4,15 @@ import { Icons, ScrollArea } from "@instill-ai/design-system"; import { PipelineComponent, useOutputReferenceHintFields } from "../../../lib"; export const ComponentOutputReferenceHints = ({ + componentID, component, task, }: { + componentID: string; component: PipelineComponent; task?: string; }) => { - const fields = useOutputReferenceHintFields({ - component, - task, - }); + const fields = useOutputReferenceHintFields({ componentID, component, task }); return (

diff --git a/packages/toolkit/src/view/pipeline-builder/components/PipelineBuilderCanvas.tsx b/packages/toolkit/src/view/pipeline-builder/components/PipelineBuilderCanvas.tsx index 2e0196969..883fcbc8f 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/PipelineBuilderCanvas.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/PipelineBuilderCanvas.tsx @@ -15,12 +15,11 @@ import { useShallow, } from "../../../lib"; import { - ConnectorNode, EmptyNode, IteratorNode, - OperatorNode, ResponseNode, TriggerNode, + GeneralNode, } from "./nodes"; import { CustomEdge } from "./CustomEdge"; import { isResponseNode, isTriggerNode } from "../lib"; @@ -42,11 +41,10 @@ const selector = (store: InstillStore) => ({ const nodeTypes = { triggerNode: TriggerNode, - connectorNode: ConnectorNode, emptyNode: EmptyNode, responseNode: ResponseNode, - operatorNode: OperatorNode, iteratorNode: IteratorNode, + generalNode: GeneralNode, }; const edgeTypes = { diff --git a/packages/toolkit/src/view/pipeline-builder/components/PipelineToolkitDialog.tsx b/packages/toolkit/src/view/pipeline-builder/components/PipelineToolkitDialog.tsx index 25814546f..b1279a43a 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/PipelineToolkitDialog.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/PipelineToolkitDialog.tsx @@ -5,7 +5,7 @@ import { Dialog, Icons, ScrollArea, Tabs } from "@instill-ai/design-system"; import { CodeBlock } from "../../../components"; import { InstillStore, useInstillStore, useShallow } from "../../../lib"; import { composeCompleteNodesUnderEditingIteratorMode } from "../lib/composeCompleteNodesUnderEditingIteratorMode"; -import { constructPipelineRecipeFromNodes } from "../lib"; +import { composePipelineRecipeFromNodes } from "../lib"; export type PipelineToolkitDialogProps = { snippet: string; @@ -47,11 +47,7 @@ export const PipelineToolkitDialog = (props: PipelineToolkitDialogProps) => { }); } - return JSON.stringify( - constructPipelineRecipeFromNodes(targetNodes), - null, - 2 - ); + return JSON.stringify(composePipelineRecipeFromNodes(targetNodes), null, 2); }, [ nodes, isEditingIterator, diff --git a/packages/toolkit/src/view/pipeline-builder/components/ReadOnlyPipelineBuilder.tsx b/packages/toolkit/src/view/pipeline-builder/components/ReadOnlyPipelineBuilder.tsx index d011dc973..ceb042259 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/ReadOnlyPipelineBuilder.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/ReadOnlyPipelineBuilder.tsx @@ -22,10 +22,9 @@ import { } from "../../../lib"; import { composeEdgesFromNodes, createGraphLayout } from "../lib"; import { - ConnectorNode, EmptyNode, + GeneralNode, IteratorNode, - OperatorNode, ResponseNode, TriggerNode, } from "./nodes"; @@ -42,11 +41,10 @@ const selector = (store: InstillStore) => ({ const nodeTypes = { triggerNode: TriggerNode, - connectorNode: ConnectorNode, emptyNode: EmptyNode, responseNode: ResponseNode, - operatorNode: OperatorNode, iteratorNode: IteratorNode, + generalNode: GeneralNode, }; const edgeTypes = { @@ -79,7 +77,7 @@ export const ReadOnlyPipelineBuilder = ({ React.useEffect(() => { if (!recipe || !metadata) return; - const nodes = createNodesFromPipelineRecipe(recipe); + const nodes = createNodesFromPipelineRecipe(recipe, { metadata }); const edges = composeEdgesFromNodes(nodes); createGraphLayout(nodes, edges) diff --git a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/IteratorEditor.tsx b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/IteratorEditor.tsx index 7d0960440..fe82c028f 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/IteratorEditor.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/IteratorEditor.tsx @@ -13,11 +13,11 @@ import { import { SelectComponentDialog } from ".."; import { composeEdgesFromNodes, - composePipelineMetadataFromNodes, + composePipelineMetadataMapFromNodes, isIteratorNode, isResponseNode, isTriggerNode, - useConstructNodeFromDefinition, + useAddNodeWithDefinition, } from "../../lib"; import { ReactFlowInstance } from "reactflow"; import { PipelineBuilderCanvas } from "../PipelineBuilderCanvas"; @@ -39,7 +39,7 @@ const selector = (store: InstillStore) => ({ export type InOutputOption = { path: string; - instill_format: string; + instillFormat: string; description?: string; }; @@ -65,7 +65,7 @@ export const IteratorEditor = ({ updateTempSavedNodesForEditingIteratorFlow, } = useInstillStore(useShallow(selector)); - const constructNode = useConstructNodeFromDefinition({ reactFlowInstance }); + const addNode = useAddNodeWithDefinition({ reactFlowInstance }); return (
@@ -74,10 +74,7 @@ export const IteratorEditor = ({ onClick={() => { const newNodes = tempSavedNodesForEditingIteratorFlow.map( (node) => { - if ( - node.data.id === editingIteratorID && - isIteratorNode(node) - ) { + if (node.id === editingIteratorID && isIteratorNode(node)) { const components = nodes .filter( (node) => !isTriggerNode(node) || !isResponseNode(node) @@ -88,11 +85,8 @@ export const IteratorEditor = ({ ...node, data: { ...node.data, - iterator_component: { - ...node.data.iterator_component, - components, - }, - metadata: composePipelineMetadataFromNodes(nodes), + components, + metadata: composePipelineMetadataMapFromNodes(nodes), }, }; } @@ -148,7 +142,7 @@ export const IteratorEditor = ({ open={selectDefinitionDialogIsOpen} onOpenChange={setSelectDefinitionDialogIsOpen} onSelect={(definition) => { - constructNode(definition); + addNode(definition); setSelectDefinitionDialogIsOpen(false); }} disabledTrigger={true} diff --git a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-input/IterateElementHint.tsx b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-input/IterateElementHint.tsx index 81ca1c719..fc1c23ff2 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-input/IterateElementHint.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-input/IterateElementHint.tsx @@ -13,11 +13,11 @@ export const IterateElmentHint = ({ selectedInputOption: Nullable; }) => { const humanReadableInstillFormat = React.useMemo(() => { - if (!selectedInputOption || !selectedInputOption?.instill_format) { + if (!selectedInputOption || !selectedInputOption?.instillFormat) { return null; } return transformInstillFormatToHumanReadableFormat( - selectedInputOption.instill_format + selectedInputOption.instillFormat ); }, [selectedInputOption]); diff --git a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-input/IteratorInput.tsx b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-input/IteratorInput.tsx index fa19d530f..7df869cd1 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-input/IteratorInput.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-input/IteratorInput.tsx @@ -53,7 +53,7 @@ export const IteratorInput = ({ className }: { className?: string }) => { ) .map((hint) => ({ path: hint.path, - instill_format: hint.instillFormat, + instillFormat: hint.instillFormat, description: hint.description, })); }, [tempSavedNodesForEditingIteratorFlow]); @@ -61,15 +61,13 @@ export const IteratorInput = ({ className }: { className?: string }) => { React.useEffect(() => { if (editingIteratorID && tempSavedNodesForEditingIteratorFlow) { const targetIteratorNode = tempSavedNodesForEditingIteratorFlow.find( - (node) => node.data.id === editingIteratorID && isIteratorNode(node) + (node) => node.id === editingIteratorID && isIteratorNode(node) ) as Node | undefined; const inputOption = availableInputOptions.find( (option) => option.path === - targetIteratorNode?.data.iterator_component.input - .replace("${", "") - .replace("}", "") + targetIteratorNode?.data.input.replace("${", "").replace("}", "") ); if (inputOption) { @@ -102,18 +100,12 @@ export const IteratorInput = ({ className }: { className?: string }) => { updatePipelineRecipeIsDirty(() => true); updateTempSavedNodesForEditingIteratorFlow((nodes) => nodes.map((node) => { - if ( - node.data.id === editingIteratorID && - isIteratorNode(node) - ) { + if (node.id === editingIteratorID && isIteratorNode(node)) { return { ...node, data: { ...node.data, - iterator_component: { - ...node.data.iterator_component, - input: "${" + option.path + "}", - }, + input: "${" + option.path + "}", }, }; } diff --git a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/AddOutputButton.tsx b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/AddOutputButton.tsx index 892314613..b80830a32 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/AddOutputButton.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/AddOutputButton.tsx @@ -31,31 +31,28 @@ export const AddOutputButton = ({ onClick={() => { let newOutputElements = {}; - if (targetIteratorNode?.data.iterator_component.output_elements) { + if (targetIteratorNode?.data.outputElements) { const currentIndexArray = Object.keys( - targetIteratorNode?.data.iterator_component.output_elements + targetIteratorNode?.data.outputElements ) .map((key) => key.replace("result_", "")) .map(Number) .sort((a, b) => b - a); newOutputElements = { - ...targetIteratorNode?.data.iterator_component.output_elements, + ...targetIteratorNode?.data.outputElements, [`result_${currentIndexArray[0] === 0 ? 1 : currentIndexArray[0] + 1}`]: "", }; } updateTempSavedNodesForEditingIteratorFlow((nodes) => nodes.map((node) => { - if (node.data.id === editingIteratorID && isIteratorNode(node)) { + if (node.id === editingIteratorID && isIteratorNode(node)) { return { ...node, data: { ...node.data, - iterator_component: { - ...node.data.iterator_component, - output_elements: newOutputElements, - }, + outputElements: newOutputElements, }, }; } diff --git a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/DeleteOutputButton.tsx b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/DeleteOutputButton.tsx index a714c1974..da12aa8a9 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/DeleteOutputButton.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/DeleteOutputButton.tsx @@ -25,18 +25,15 @@ export const DeleteOutputButton = ({ outputKey }: { outputKey: string }) => { onClick={() => { updateTempSavedNodesForEditingIteratorFlow((nodes) => nodes.map((node) => { - if (node.data.id === editingIteratorID && isIteratorNode(node)) { - delete node.data.iterator_component.output_elements[outputKey]; + if (node.id === editingIteratorID && isIteratorNode(node)) { + delete node.data.outputElements[outputKey]; return { ...node, data: { ...node.data, - iterator_component: { - ...node.data.iterator_component, - output_elements: { - ...node.data.iterator_component.output_elements, - }, + outputElements: { + ...node.data.outputElements, }, }, }; diff --git a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/IteratorOutput.tsx b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/IteratorOutput.tsx index e00cb669f..bcbd00616 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/IteratorOutput.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/IteratorOutput.tsx @@ -21,7 +21,7 @@ export const IteratorOutput = () => { const targetIteratorNode = React.useMemo(() => { return tempSavedNodesForEditingIteratorFlow.find( - (node) => node.data.id === editingIteratorID && isIteratorNode(node) + (node) => node.id === editingIteratorID && isIteratorNode(node) ) as Node | undefined; }, [editingIteratorID, tempSavedNodesForEditingIteratorFlow]); @@ -33,16 +33,16 @@ export const IteratorOutput = () => {

- {targetIteratorNode?.data.iterator_component.output_elements - ? Object.entries( - targetIteratorNode?.data.iterator_component.output_elements - ).map(([key]) => ( - - )) + {targetIteratorNode?.data.outputElements + ? Object.entries(targetIteratorNode?.data.outputElements).map( + ([key]) => ( + + ) + ) : null}
diff --git a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputKeyField.tsx b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputKeyField.tsx index 376d43a39..6a4a67a26 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputKeyField.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputKeyField.tsx @@ -36,19 +36,16 @@ export const OutputKeyField = ({ timer.current = window.setTimeout(() => { updateTempSavedNodesForEditingIteratorFlow((nodes) => nodes.map((node) => { - if (node.data.id === editingIteratorID && isIteratorNode(node)) { - delete node.data.iterator_component.output_elements[outputKey]; + if (node.id === editingIteratorID && isIteratorNode(node)) { + delete node.data.outputElements[outputKey]; return { ...node, data: { ...node.data, - iterator_component: { - ...node.data.iterator_component, - output_elements: { - ...node.data.iterator_component.output_elements, - [keyInput]: outputValue, - }, + outputElements: { + ...node.data.outputElements, + [keyInput]: outputValue, }, }, }; diff --git a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputValueInput.tsx b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputValueInput.tsx index 961ba0f0c..a1a2dccaf 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputValueInput.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputValueInput.tsx @@ -26,11 +26,11 @@ export const OutputValueInput = ({ outputKey }: { outputKey: string }) => { const outputValue = React.useMemo(() => { const iteratorNode = tempSavedNodesForEditingIteratorFlow.find( - (node) => node.data.id === editingIteratorID && isIteratorNode(node) + (node) => node.id === editingIteratorID && isIteratorNode(node) ) as Node | undefined; if (iteratorNode) { - return iteratorNode.data.iterator_component.output_elements[outputKey]; + return iteratorNode.data.outputElements[outputKey]; } }, [tempSavedNodesForEditingIteratorFlow, editingIteratorID, outputKey]); @@ -42,17 +42,14 @@ export const OutputValueInput = ({ outputKey }: { outputKey: string }) => { onChange={(e) => { updateTempSavedNodesForEditingIteratorFlow((nodes) => nodes.map((node) => { - if (node.data.id === editingIteratorID && isIteratorNode(node)) { + if (node.id === editingIteratorID && isIteratorNode(node)) { return { ...node, data: { ...node.data, - iterator_component: { - ...node.data.iterator_component, - output_elements: { - ...node.data.iterator_component.output_elements, - [outputKey]: e.target.value, - }, + outputElements: { + ...node.data.outputElements, + [outputKey]: e.target.value, }, }, }; diff --git a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputValueSelect.tsx b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputValueSelect.tsx index 888789d08..79a19f1cf 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputValueSelect.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/iterator-editor/iterator-output/OutputValueSelect.tsx @@ -44,22 +44,22 @@ export const OutputValueSelect = ({ outputKey }: { outputKey: string }) => { return hints.map((hint) => ({ path: hint.path, - instill_format: hint.instillFormat, + instillFormat: hint.instillFormat, description: hint.description, })); }, [nodes]); React.useEffect(() => { const targetNodes = tempSavedNodesForEditingIteratorFlow.find( - (node) => node.data.id === editingIteratorID && isIteratorNode(node) + (node) => node.id === editingIteratorID && isIteratorNode(node) ) as Node | undefined; if (targetNodes) { const outputOption = availableOutputOptions.find((option) => { if ( - targetNodes?.data.iterator_component.output_elements[outputKey] && + targetNodes?.data.outputElements[outputKey] && option.path === - targetNodes?.data.iterator_component.output_elements[outputKey] + targetNodes?.data.outputElements[outputKey] .replace("${", "") .replace("}", "") ) { @@ -92,17 +92,14 @@ export const OutputValueSelect = ({ outputKey }: { outputKey: string }) => { updatePipelineRecipeIsDirty(() => true); updateTempSavedNodesForEditingIteratorFlow((nodes) => nodes.map((node) => { - if (node.data.id === editingIteratorID && isIteratorNode(node)) { + if (node.id === editingIteratorID && isIteratorNode(node)) { return { ...node, data: { ...node.data, - iterator_component: { - ...node.data.iterator_component, - output_elements: { - ...node.data.iterator_component.output_elements, - [outputKey]: "${" + `${option.path}` + "}", - }, + outputElements: { + ...node.data.outputElements, + [outputKey]: "${" + `${option.path}` + "}", }, }, }; diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/common/NodeIDEditor.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/common/NodeIDEditor.tsx index c1880e02f..9c2077eb2 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/common/NodeIDEditor.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/common/NodeIDEditor.tsx @@ -13,9 +13,8 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { InstillErrors } from "../../../../../constant"; import { composeEdgesFromNodes, - isConnectorNode, + isGeneralNode, isIteratorNode, - isOperatorNode, } from "../../../lib"; import { validateInstillID } from "../../../../../server"; @@ -107,11 +106,7 @@ export const NodeIDEditor = ({ currentNodeID }: { currentNodeID: string }) => { const newNodes = nodes.map((node) => { if (node.id === currentNodeID) { - if ( - isConnectorNode(node) || - isOperatorNode(node) || - isIteratorNode(node) - ) { + if (isGeneralNode(node) || isIteratorNode(node)) { return { ...node, id: newID, diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/common/NodeWrapper.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/common/NodeWrapper.tsx index 136dd78f8..b447c383c 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/common/NodeWrapper.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/common/NodeWrapper.tsx @@ -20,6 +20,7 @@ const selector = (store: InstillStore) => ({ }); export const NodeWrapper = ({ + nodeID, nodeData, children, noteIsOpen, @@ -28,6 +29,7 @@ export const NodeWrapper = ({ disabledSourceHandler, disabledTargetHandler, }: { + nodeID: string; nodeData: NodeData; children: React.ReactNode; noteIsOpen: boolean; @@ -53,25 +55,25 @@ export const NodeWrapper = ({ const reactflowEdges = useEdges(); const hasTargetEdges = React.useMemo(() => { if (edges.length === 0 && reactflowEdges.length !== 0) { - return reactflowEdges.some((edge) => edge.target === nodeData.id); + return reactflowEdges.some((edge) => edge.target === nodeID); } - return edges.some((edge) => edge.target === nodeData.id); - }, [edges, reactflowEdges, nodeData.id]); + return edges.some((edge) => edge.target === nodeID); + }, [edges, reactflowEdges, nodeID]); const hasSourceEdges = React.useMemo(() => { if (edges.length === 0 && reactflowEdges.length !== 0) { - return reactflowEdges.some((edge) => edge.source === nodeData.id); + return reactflowEdges.some((edge) => edge.source === nodeID); } - return edges.some((edge) => edge.source === nodeData.id); - }, [edges, nodeData.id, reactflowEdges]); + return edges.some((edge) => edge.source === nodeID); + }, [edges, nodeID, reactflowEdges]); return (
{ - updateSelectedConnectorNodeId(() => nodeData.id); + updateSelectedConnectorNodeId(() => nodeID); // We reorder the edges so that the selected edge is on top of the unselected edges updateEdges((edges) => { @@ -79,7 +81,7 @@ export const NodeWrapper = ({ const unSelectedEdges: Edge[] = []; edges.forEach((edge) => { - if (edge.source === nodeData.id || edge.target === nodeData.id) { + if (edge.source === nodeID || edge.target === nodeID) { selectedEdges.push(edge); } else { unSelectedEdges.push(edge); @@ -108,7 +110,7 @@ export const NodeWrapper = ({ timer.current = window.setTimeout(() => { updateNodes((nodes) => nodes.map((node) => { - if (node.id === nodeData.id) { + if (node.id === nodeID) { node.data = { ...node.data, note: e.target.value, @@ -133,7 +135,7 @@ export const NodeWrapper = ({ "flex w-[var(--pipeline-builder-node-available-width)] flex-col rounded-sm border-2 border-semantic-bg-primary bg-semantic-bg-base-bg shadow-md hover:shadow-lg", { "outline outline-2 outline-offset-1 outline-semantic-accent-default": - nodeData.id === selectedConnectorNodeId, + nodeID === selectedConnectorNodeId, } )} > @@ -142,7 +144,7 @@ export const NodeWrapper = ({
{renderBottomBarInformation ? (
{renderBottomBarInformation()} @@ -153,7 +155,7 @@ export const NodeWrapper = ({ className={hasTargetEdges ? "" : "!opacity-0"} type="target" position={Position.Left} - id={nodeData.id} + id={nodeID} /> )} {disabledSourceHandler ? null : ( @@ -161,7 +163,7 @@ export const NodeWrapper = ({ className={hasSourceEdges ? "" : "!opacity-0"} type="source" position={Position.Right} - id={nodeData.id} + id={nodeID} /> )} diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/ResourceNotCreatedWarning.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/ResourceNotCreatedWarning.tsx deleted file mode 100644 index 45a199c2a..000000000 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/ResourceNotCreatedWarning.tsx +++ /dev/null @@ -1,33 +0,0 @@ -"use client"; - -import { LinkButton } from "@instill-ai/design-system"; -import { Nullable } from "../../../../../lib"; - -export const ResourceNotCreatedWarning = ({ - connectorTitle, - onCreate, - disabled, -}: { - connectorTitle: Nullable; - onCreate: () => void; - disabled?: boolean; -}) => { - return ( -
-

- {`Please create or use a configured ${ - connectorTitle ? connectorTitle : "" - } connector`} -

- - Create connector - -
- ); -}; diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/index.ts b/packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/index.ts deleted file mode 100644 index ca614f657..000000000 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./ConnectorNode"; diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/ConnectorOperatorControlPanel.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/NodeControlPanel.tsx similarity index 82% rename from packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/ConnectorOperatorControlPanel.tsx rename to packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/NodeControlPanel.tsx index 25e3d6e61..cb8cf8d28 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/ConnectorOperatorControlPanel.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/NodeControlPanel.tsx @@ -11,21 +11,15 @@ import { NodeDropdownMenu } from "../common"; import { composeEdgesFromNodes, generateUniqueIndex, - getAllComponentID, + getAllNodeID, transformConnectorDefinitionIDToComponentIDPrefix, } from "../../../lib"; +import { GeneralNodeData, IteratorNodeData, NodeData } from "../../../type"; + import { - ConnectorNodeData, - IteratorNodeData, - NodeData, - OperatorNodeData, -} from "../../../type"; -import { - isConnectorComponent, - isIteratorComponent, - isOperatorComponent, + isPipelineGeneralComponent, + isPipelineIteratorComponent, } from "../../../lib/checkComponentType"; -import { extractComponentFromNodes } from "../../../lib/extractComponentFromNodes"; const selector = (store: InstillStore) => ({ isOwner: store.isOwner, @@ -43,7 +37,7 @@ const selector = (store: InstillStore) => ({ store.tempSavedNodesForEditingIteratorFlow, }); -export const ConnectorOperatorControlPanel = ({ +export const NodeControlPanel = ({ nodeID, nodeIsCollapsed, setNodeIsCollapsed, @@ -56,7 +50,7 @@ export const ConnectorOperatorControlPanel = ({ setNodeIsCollapsed: React.Dispatch>; handleToggleNote: () => void; noteIsOpen: boolean; - nodeData: ConnectorNodeData | OperatorNodeData | IteratorNodeData; + nodeData: GeneralNodeData | IteratorNodeData; }) => { const { isOwner, @@ -75,15 +69,11 @@ export const ConnectorOperatorControlPanel = ({ const [moreOptionsIsOpen, setMoreOptionsIsOpen] = React.useState(false); const nodeTypeName = React.useMemo(() => { - if (isOperatorComponent(nodeData)) { - return "Operator Component"; - } - - if (isConnectorComponent(nodeData)) { - return "Connector Component"; + if (isPipelineGeneralComponent(nodeData)) { + return "Component"; } - if (isIteratorComponent(nodeData)) { + if (isPipelineIteratorComponent(nodeData)) { return "Iterator Component"; } @@ -114,31 +104,18 @@ export const ConnectorOperatorControlPanel = ({ let nodePrefix: Nullable = null; let nodeType: Nullable = null; - if (isOperatorComponent(nodeData)) { - if (!nodeData.operator_component.definition) { - return; - } - - nodePrefix = transformConnectorDefinitionIDToComponentIDPrefix( - nodeData.operator_component.definition.id - ); - - nodeType = "operatorNode"; - } - - if (isConnectorComponent(nodeData)) { - if (!nodeData.connector_component.definition) { + if (isPipelineGeneralComponent(nodeData)) { + if (!nodeData.definition) { return; } nodePrefix = transformConnectorDefinitionIDToComponentIDPrefix( - nodeData.connector_component.definition.id + nodeData.definition.id ); - nodeType = "connectorNode"; + nodeType = "generalNode"; } - - if (isIteratorComponent(nodeData)) { + if (isPipelineIteratorComponent(nodeData)) { nodePrefix = transformConnectorDefinitionIDToComponentIDPrefix("iterator"); nodeType = "iteratorNode"; @@ -148,13 +125,10 @@ export const ConnectorOperatorControlPanel = ({ return; } - // Generate a new component index - const components = extractComponentFromNodes(nodes); - const nodeIndex = generateUniqueIndex( isEditingIterator ? [...nodes, ...tempSavedNodesForEditingIteratorFlow].map((e) => e.id) - : getAllComponentID(components), + : getAllNodeID(nodes), nodePrefix ); @@ -171,7 +145,6 @@ export const ConnectorOperatorControlPanel = ({ zIndex: 30, data: { ...nodeData, - id: nodeID, }, }, ]; diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/index.ts b/packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/index.ts index e90803835..4c2febf7b 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/index.ts +++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/control-panel/index.ts @@ -1,2 +1,2 @@ -export * from "./ConnectorOperatorControlPanel"; +export * from "./NodeControlPanel"; export * from "./TriggerResponseNodeControlPanel"; diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/DataConnectorFreeForm.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/general-node/DataConnectorFreeForm.tsx similarity index 63% rename from packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/DataConnectorFreeForm.tsx rename to packages/toolkit/src/view/pipeline-builder/components/nodes/general-node/DataConnectorFreeForm.tsx index 8bbc8a220..47822733f 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/connector-node/DataConnectorFreeForm.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/general-node/DataConnectorFreeForm.tsx @@ -17,10 +17,11 @@ import { GeneralRecord, InstillStore, Nullable, - PipelineConnectorComponent, + PipelineGeneralComponent, useInstillStore, } from "../../../../../lib"; -import { composeEdgesFromNodes, isConnectorNode } from "../../../lib"; +import { composeEdgesFromNodes } from "../../../lib"; +import { isGeneralNode } from "../../../lib/checkNodeType"; export const Schema = z.object({ key: z.string().min(1, { message: "Key is required" }), @@ -44,7 +45,7 @@ export const DataConnectorFreeForm = ({ enableEdit: boolean; setEnableEdit: React.Dispatch>; nodeID: string; - component: PipelineConnectorComponent; + component: PipelineGeneralComponent; }) => { const [prevFieldKey, setPrevFieldKey] = React.useState>(null); @@ -63,26 +64,23 @@ export const DataConnectorFreeForm = ({ function onSubmitDataConnectorInput(formData: z.infer) { const newNodes = nodes.map((node) => { - if (isConnectorNode(node) && node.id === nodeID) { + if (isGeneralNode(node) && node.id === nodeID) { if (prevFieldKey) { - delete node.data.connector_component.input.data[prevFieldKey]; + delete node.data.input.data[prevFieldKey]; } node.data = { ...node.data, - connector_component: { - ...node.data.connector_component, - input: { - ...node.data.connector_component.input, - data: node.data.connector_component.input.data - ? { - ...node.data.connector_component.input.data, - [formData.key]: formData.value, - } - : { - [formData.key]: formData.value, - }, - }, + input: { + ...node.data.input, + data: node.data.input.data + ? { + ...node.data.input.data, + [formData.key]: formData.value, + } + : { + [formData.key]: formData.value, + }, }, }; } @@ -102,7 +100,7 @@ export const DataConnectorFreeForm = ({ function onEditDataConnectorInput(key: string) { form.reset({ - value: component.connector_component.input.data[key], + value: component.input.data[key], key: key, }); setEnableEdit(true); @@ -110,17 +108,14 @@ export const DataConnectorFreeForm = ({ function onDeleteDataConnectorInput(key: string) { const newNodes = nodes.map((node) => { - if (isConnectorNode(node) && node.id === nodeID) { - delete node.data.connector_component.input.data[key]; + if (isGeneralNode(node) && node.id === nodeID) { + delete node.data.input.data[key]; // update the value deep clone node.data = { ...node.data, - connector_component: { - ...node.data.connector_component, - input: { - ...node.data.connector_component.input, - data: { ...node.data.connector_component.input.data }, - }, + input: { + ...node.data.input, + data: { ...node.data.input.data }, }, }; } @@ -135,24 +130,24 @@ export const DataConnectorFreeForm = ({ if (pipelineIsReadOnly) { return (
- {component.connector_component.input?.data - ? Object.entries( - component.connector_component.input.data as Record - ).map(([key, value]) => { - return ( -
-

- {key} -

-
- {value} + {component.input?.data + ? Object.entries(component.input.data as Record).map( + ([key, value]) => { + return ( +
+

+ {key} +

+
+ {value} +
-
- ); - }) + ); + } + ) : null}
); @@ -243,41 +238,41 @@ export const DataConnectorFreeForm = ({ return (
- {component.connector_component.input?.data - ? Object.entries( - component.connector_component.input.data as GeneralRecord - ).map(([key]) => { - return ( -
-
-
-

- {key} -

-
-
- - + {component.input?.data + ? Object.entries(component.input.data as GeneralRecord).map( + ([key]) => { + return ( +
+
+
+

+ {key} +

+
+
+ + +
-
- ); - }) + ); + } + ) : null}
- +
)} diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/OperatorNode.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/OperatorNode.tsx deleted file mode 100644 index b0fa5137b..000000000 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/OperatorNode.tsx +++ /dev/null @@ -1,180 +0,0 @@ -"use client"; - -import * as React from "react"; -import { NodeProps } from "reactflow"; -import { Form, Icons } from "@instill-ai/design-system"; - -import { OperatorNodeData } from "../../../type"; -import { - GeneralRecord, - InstillStore, - useInstillForm, - useInstillStore, -} from "../../../../../lib"; -import { ImageWithFallback } from "../../../../../components"; -import { useShallow } from "zustand/react/shallow"; -import { ConnectorOperatorControlPanel } from "../control-panel"; -import { OpenAdvancedConfigurationButton } from "../../OpenAdvancedConfigurationButton"; -import { getOperatorInputOutputSchema } from "../../../lib/getOperatorInputOutputSchema"; -import { - getConnectorOperatorComponentConfiguration, - useCheckIsHidden, - useUpdaterOnNode, -} from "../../../lib"; -import { - NodeBottomBarContent, - NodeBottomBarMenu, - NodeHead, - NodeIDEditor, - NodeWrapper, -} from "../common"; -import { ComponentOutputReferenceHints } from "../../ComponentOutputReferenceHints"; - -const selector = (store: InstillStore) => ({ - updateCurrentAdvancedConfigurationNodeID: - store.updateCurrentAdvancedConfigurationNodeID, - pipelineIsReadOnly: store.pipelineIsReadOnly, - collapseAllNodes: store.collapseAllNodes, - entitySecrets: store.entitySecrets, - currentVersion: store.currentVersion, -}); - -export const OperatorNode = ({ data, id }: NodeProps) => { - const { - updateCurrentAdvancedConfigurationNodeID, - pipelineIsReadOnly, - collapseAllNodes, - entitySecrets, - currentVersion, - } = useInstillStore(useShallow(selector)); - - const [nodeIsCollapsed, setNodeIsCollapsed] = React.useState(false); - const [noteIsOpen, setNoteIsOpen] = React.useState(false); - const [forceCloseCollapsibleFormGroups, setForceCloseCollapsibleFormGroups] = - React.useState([]); - - React.useEffect(() => { - setNodeIsCollapsed(collapseAllNodes); - }, [collapseAllNodes]); - - const checkIsHidden = useCheckIsHidden("onNode"); - - const componentConfiguration = React.useMemo(() => { - return getConnectorOperatorComponentConfiguration(data); - }, [data]); - - const { fields, form, ValidatorSchema, selectedConditionMap } = - useInstillForm( - data.operator_component.definition?.spec.component_specification ?? null, - componentConfiguration, - { - size: "sm", - enableSmartHint: true, - checkIsHidden, - componentID: data.id, - disabledAll: currentVersion !== "latest" || pipelineIsReadOnly, - secrets: entitySecrets, - collapsibleDefaultOpen: true, - enabledCollapsibleFormGroup: true, - forceCloseCollapsibleFormGroups, - updateForceCloseCollapsibleFormGroups: - setForceCloseCollapsibleFormGroups, - } - ); - - const { outputSchema } = React.useMemo(() => { - // The configuration stored in the node will only change when the user - // click on the "Save" button. Therefore, we need to use the - // selectedConditionMap to get the latest selected task. Due to the - // output schema depends on the selected task - - return getOperatorInputOutputSchema( - data, - selectedConditionMap ? selectedConditionMap["task"] : undefined - ); - }, [data, selectedConditionMap]); - - const { getValues, trigger } = form; - - useUpdaterOnNode({ - currentNodeData: data, - form, - ValidatorSchema, - }); - - return ( - } - renderBottomBarInformation={() => ( - - )} - > - {/* The header of node */} - - -
- - } - /> - -
- setNoteIsOpen((prev) => !prev)} - noteIsOpen={noteIsOpen} - /> -
- - {nodeIsCollapsed ? null : ( - <> -
- -
{fields}
-
-
-
- { - const values = getValues(); - - const parsedResult = ValidatorSchema.safeParse(values); - - if (parsedResult.success) { - updateCurrentAdvancedConfigurationNodeID(() => id); - } else { - for (const error of parsedResult.error.errors) { - trigger(error.path.join(".")); - } - } - }} - /> -
- - - - )} -
- ); -}; diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/index.ts b/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/index.ts deleted file mode 100644 index de550b999..000000000 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./OperatorNode"; diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/response-node/ResponseNode.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/response-node/ResponseNode.tsx index 074feaf00..d304c99a6 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/response-node/ResponseNode.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/response-node/ResponseNode.tsx @@ -11,7 +11,7 @@ import { arrayMove } from "@dnd-kit/sortable"; import { InstillStore, Nullable, - PipelineTriggerResponseField, + PipelineOutputField, useInstillStore, } from "../../../../../lib"; import { UserDefinedFieldItem } from "./UserDefinedFieldItem"; @@ -48,12 +48,11 @@ export type EndOperatorNodeFieldItem = { title: string; }; -export type PipelineResponseNodeFieldSortedItem = - PipelineTriggerResponseField & { - key: string; - }; +export type PipelineResponseNodeFieldSortedItem = PipelineOutputField & { + key: string; +}; -export const ResponseNode = ({ data }: NodeProps) => { +export const ResponseNode = ({ data, id }: NodeProps) => { const [isEditing, setIsEditing] = React.useState(false); const [isCreating, setIsCreating] = React.useState(false); const [currentEditingFieldKey, setCurrentEditingFieldKey] = @@ -113,7 +112,7 @@ export const ResponseNode = ({ data }: NodeProps) => { } // We need to put on the initial order, for example, if we have - // 3 response fields, the instill_ui_order for new fields will be 3 + // 3 response fields, the instillUiOrder for new fields will be 3 const currentFieldsCount = Object.keys(node.data.fields).length; node.data = { @@ -123,7 +122,7 @@ export const ResponseNode = ({ data }: NodeProps) => { [formData.key]: { title: formData.title, value: formData.value, - instill_ui_order: currentFieldsCount, + instillUiOrder: currentFieldsCount, }, }, }; @@ -195,8 +194,8 @@ export const ResponseNode = ({ data }: NodeProps) => { }; }) .sort((a, b) => { - const aOrder = a.instill_ui_order; - const bOrder = b.instill_ui_order; + const aOrder = a.instillUiOrder; + const bOrder = b.instillUiOrder; if (typeof aOrder === "undefined") { return 1; @@ -237,6 +236,7 @@ export const ResponseNode = ({ data }: NodeProps) => { return ( ) => { /> ) : isViewResultMode ? ( ) => { { title: item.title, value: item.value, - instill_ui_order: index, + instillUiOrder: index, }, ]) ); diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/trigger-node/TriggerNode.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/trigger-node/TriggerNode.tsx index e88182156..ef650c8d0 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/trigger-node/TriggerNode.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/trigger-node/TriggerNode.tsx @@ -61,7 +61,7 @@ const selector = (store: InstillStore) => ({ store.updateRecentlyUsedStartComponentFieldTypes, }); -export const TriggerNode = ({ data }: NodeProps) => { +export const TriggerNode = ({ data, id }: NodeProps) => { const { amplitudeIsInit } = useAmplitudeCtx(); const [noteIsOpen, setNoteIsOpen] = React.useState(false); const [nodeIsCollapsed, setNodeIsCollapsed] = React.useState(false); @@ -111,9 +111,9 @@ export const TriggerNode = ({ data }: NodeProps) => { }); setIsEditing(true); - let newSelectedType = data.fields[key].instill_format; + let newSelectedType = data.fields[key].instillFormat; - if (newSelectedType === "string" && data.fields[key].instill_ui_multiline) { + if (newSelectedType === "string" && data.fields[key].instillUiMultiline) { newSelectedType = "long_string"; } @@ -262,7 +262,7 @@ export const TriggerNode = ({ data }: NodeProps) => { const semiStructuredObjectKeys: string[] = []; Object.entries(data.fields).forEach(([key, value]) => { - if (value.instill_format === "semi-structured/json") { + if (value.instillFormat === "semi-structured/json") { semiStructuredObjectKeys.push(key); } }); @@ -357,6 +357,7 @@ export const TriggerNode = ({ data }: NodeProps) => { return ( ) => { key, { ...value, - instill_ui_order: newFieldIndex, + instillUiOrder: newFieldIndex, }, ]; } diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/trigger-node/triggerNodeFields.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/trigger-node/triggerNodeFields.tsx index cb7f1e2dc..c9ff4e284 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/nodes/trigger-node/triggerNodeFields.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/trigger-node/triggerNodeFields.tsx @@ -2,26 +2,26 @@ import * as React from "react"; import { ComplicateIcons, Icons } from "@instill-ai/design-system"; -import { PipelineTriggerRequestField } from "../../../../../lib"; +import { PipelineVariableField } from "../../../../../lib"; export type TriggerNodeInputField = { title: string; - instill_format: string; + instillFormat: string; icon: React.ReactNode; order: number; getFieldConfiguration: ( title: string, description?: string - ) => PipelineTriggerRequestField; + ) => PipelineVariableField; }; export const triggerNodeFields: Record = { string: { title: "Short Text", - instill_format: "string", + instillFormat: "string", order: 0, getFieldConfiguration: (title, description) => ({ - instill_format: "string", + instillFormat: "string", title, description, }), @@ -31,10 +31,10 @@ export const triggerNodeFields: Record = { }, "array:string": { title: "Multiple Texts", - instill_format: "array:string", + instillFormat: "array:string", order: 1, getFieldConfiguration: (title, description) => ({ - instill_format: "array:string", + instillFormat: "array:string", title, description, }), @@ -44,13 +44,13 @@ export const triggerNodeFields: Record = { }, long_string: { title: "Long Text", - instill_format: "string", + instillFormat: "string", order: 2, getFieldConfiguration: (title, description) => ({ - instill_format: "string", + instillFormat: "string", title, description, - instill_ui_multiline: true, + instillUiMultiline: true, }), icon: ( @@ -58,10 +58,10 @@ export const triggerNodeFields: Record = { }, number: { title: "Number", - instill_format: "number", + instillFormat: "number", order: 3, getFieldConfiguration: (title, description) => ({ - instill_format: "number", + instillFormat: "number", title, description, }), @@ -74,10 +74,10 @@ export const triggerNodeFields: Record = { }, "image/*": { title: "Image", - instill_format: "image/*", + instillFormat: "image/*", order: 4, getFieldConfiguration: (title, description) => ({ - instill_format: "image/*", + instillFormat: "image/*", title, description, }), @@ -87,10 +87,10 @@ export const triggerNodeFields: Record = { }, "array:image/*": { title: "Multiple Images", - instill_format: "array:image/*", + instillFormat: "array:image/*", order: 5, getFieldConfiguration: (title, description) => ({ - instill_format: "array:image/*", + instillFormat: "array:image/*", title, description, }), @@ -100,10 +100,10 @@ export const triggerNodeFields: Record = { }, "audio/*": { title: "Audio", - instill_format: "audio/*", + instillFormat: "audio/*", order: 6, getFieldConfiguration: (title, description) => ({ - instill_format: "audio/*", + instillFormat: "audio/*", title, description, }), @@ -113,10 +113,10 @@ export const triggerNodeFields: Record = { }, "array:audio/*": { title: "Multiple Audios", - instill_format: "array:audio/*", + instillFormat: "array:audio/*", order: 7, getFieldConfiguration: (title, description) => ({ - instill_format: "array:audio/*", + instillFormat: "array:audio/*", title, description, }), @@ -126,10 +126,10 @@ export const triggerNodeFields: Record = { }, "*/*": { title: "File", - instill_format: "*/*", + instillFormat: "*/*", order: 8, getFieldConfiguration: (title, description) => ({ - instill_format: "*/*", + instillFormat: "*/*", title, description, }), @@ -139,10 +139,10 @@ export const triggerNodeFields: Record = { }, "array:*/*": { title: "Multiple Files", - instill_format: "array:*/*", + instillFormat: "array:*/*", order: 9, getFieldConfiguration: (title, description) => ({ - instill_format: "array:*/*", + instillFormat: "array:*/*", title, description, }), @@ -152,10 +152,10 @@ export const triggerNodeFields: Record = { }, "video/*": { title: "Video", - instill_format: "video/*", + instillFormat: "video/*", order: 10, getFieldConfiguration: (title, description) => ({ - instill_format: "video/*", + instillFormat: "video/*", title, description, }), @@ -163,10 +163,10 @@ export const triggerNodeFields: Record = { }, "array:video/*": { title: "Multiple Videos", - instill_format: "array:video/*", + instillFormat: "array:video/*", order: 11, getFieldConfiguration: (title, description) => ({ - instill_format: "array:video/*", + instillFormat: "array:video/*", title, description, }), @@ -176,10 +176,10 @@ export const triggerNodeFields: Record = { }, boolean: { title: "Boolean", - instill_format: "boolean", + instillFormat: "boolean", order: 12, getFieldConfiguration: (title, description) => ({ - instill_format: "boolean", + instillFormat: "boolean", title, description, }), @@ -195,10 +195,10 @@ export const triggerNodeFields: Record = { // By protocol, it don't have a type "semi-structured/json": { title: "JSON", - instill_format: "semi-structured/json", + instillFormat: "semi-structured/json", order: 13, getFieldConfiguration: (title, description) => ({ - instill_format: "semi-structured/json", + instillFormat: "semi-structured/json", title, description, }), diff --git a/packages/toolkit/src/view/pipeline-builder/components/release-menu/ReleaseMenu.tsx b/packages/toolkit/src/view/pipeline-builder/components/release-menu/ReleaseMenu.tsx index 9d56f173f..b017f83ae 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/release-menu/ReleaseMenu.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/release-menu/ReleaseMenu.tsx @@ -18,7 +18,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { Button, Form, useToast } from "@instill-ai/design-system"; import { Description } from "./Description"; import { LoadingSpin } from "../../../../components"; -import { constructPipelineRecipeFromNodes } from "../../lib"; +import { composePipelineRecipeFromNodes } from "../../lib"; export const ReleasePipelineFormSchema = z.object({ id: z.string(), @@ -58,7 +58,7 @@ export const ReleaseMenu = ({ onRelease }: { onRelease?: () => void }) => { const payload: CreateUserPipelineReleasePayload = { id: data.id, description: data.description ?? undefined, - recipe: constructPipelineRecipeFromNodes(nodes), + recipe: composePipelineRecipeFromNodes(nodes), }; try { diff --git a/packages/toolkit/src/view/pipeline-builder/components/right-panel/ComponentFormOnRightPanel.tsx b/packages/toolkit/src/view/pipeline-builder/components/right-panel/PipelineGeneralComponentFormOnRightPanel.tsx similarity index 62% rename from packages/toolkit/src/view/pipeline-builder/components/right-panel/ComponentFormOnRightPanel.tsx rename to packages/toolkit/src/view/pipeline-builder/components/right-panel/PipelineGeneralComponentFormOnRightPanel.tsx index d97d61096..2e14d1f6c 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/right-panel/ComponentFormOnRightPanel.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/right-panel/PipelineGeneralComponentFormOnRightPanel.tsx @@ -5,41 +5,35 @@ import { Form } from "@instill-ai/design-system"; import { useInstillForm } from "../../../../lib/use-instill-form"; import { useCheckIsHidden, useUpdaterOnRightPanel } from "../../lib"; -import { ConnectorNodeData, OperatorNodeData } from "../../type"; -import { isConnectorComponent } from "../../lib/checkComponentType"; -import { getConnectorOperatorComponentConfiguration } from "../../lib"; +import { getGeneralComponentConfiguration } from "../../lib"; import { useInstillStore } from "../../../../lib"; +import { GeneralNodeData } from "../../type"; -export const ComponentFormOnRightPanel = ({ +export const PipelineGeneralComponentFormOnRightPanel = ({ + nodeID, nodeData, disabledAll, }: { - nodeData: ConnectorNodeData | OperatorNodeData; + nodeID: string; + nodeData: GeneralNodeData; disabledAll?: boolean; }) => { const checkIsHidden = useCheckIsHidden("onRightPanel"); const entitySecrets = useInstillStore((store) => store.entitySecrets); - const definition = React.useMemo(() => { - if (isConnectorComponent(nodeData)) { - return nodeData.connector_component.definition; - } - return nodeData.operator_component.definition; - }, [nodeData]); - const configuration = React.useMemo(() => { - return getConnectorOperatorComponentConfiguration(nodeData); + return getGeneralComponentConfiguration(nodeData); }, [nodeData]); const { form, fields, ValidatorSchema } = useInstillForm( - definition?.spec.component_specification ?? null, + nodeData.definition?.spec.component_specification ?? null, configuration, { disabledAll, chooseTitleFrom: "title", checkIsHidden, enableSmartHint: true, - componentID: nodeData.id, + componentID: nodeID, secrets: entitySecrets, enabledCollapsibleFormGroup: true, collapsibleDefaultOpen: true, @@ -50,6 +44,7 @@ export const ComponentFormOnRightPanel = ({ form, ValidatorSchema, currentNodeData: nodeData, + nodeID, }); return ( diff --git a/packages/toolkit/src/view/pipeline-builder/components/right-panel/RightPanel.tsx b/packages/toolkit/src/view/pipeline-builder/components/right-panel/RightPanel.tsx index b6b05925a..c23488e3d 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/right-panel/RightPanel.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/right-panel/RightPanel.tsx @@ -4,8 +4,10 @@ import * as React from "react"; import { useShallow } from "zustand/react/shallow"; import { Button, Icons, Separator } from "@instill-ai/design-system"; import { InstillStore, useInstillStore } from "../../../../lib"; -import { ComponentFormOnRightPanel } from "./ComponentFormOnRightPanel"; -import { isConnectorNode, isOperatorNode } from "../../lib"; +import { isGeneralNode } from "../../lib"; +import { GeneralNodeData } from "../../type"; +import { Node } from "reactflow"; +import { PipelineGeneralComponentFormOnRightPanel } from "./PipelineGeneralComponentFormOnRightPanel"; const selector = (store: InstillStore) => ({ nodes: store.nodes, @@ -21,8 +23,11 @@ export const RightPanel = () => { updateCurrentAdvancedConfigurationNodeID, } = useInstillStore(useShallow(selector)); - const selectedConnectorNode = React.useMemo(() => { - return nodes.find((node) => node.id === currentAdvancedConfigurationNodeID); + const selectedGeneralNode = React.useMemo(() => { + return nodes.find( + (node) => + node.id === currentAdvancedConfigurationNodeID && isGeneralNode(node) + ) as Node | undefined; }, [nodes, currentAdvancedConfigurationNodeID]); return ( @@ -58,15 +63,11 @@ export const RightPanel = () => { */}
- {selectedConnectorNode && - isConnectorNode(selectedConnectorNode) && - selectedConnectorNode.data.connector_component.definition ? ( - - ) : null} - {selectedConnectorNode && - isOperatorNode(selectedConnectorNode) && - selectedConnectorNode.data.operator_component.definition ? ( - + {selectedGeneralNode && selectedGeneralNode.data.definition ? ( + ) : null}
diff --git a/packages/toolkit/src/view/pipeline-builder/components/top-control-menu/Toolkit.tsx b/packages/toolkit/src/view/pipeline-builder/components/top-control-menu/Toolkit.tsx index 06c070ada..5ade70e12 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/top-control-menu/Toolkit.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/top-control-menu/Toolkit.tsx @@ -66,7 +66,7 @@ export const Toolkit = () => { } for (const [key, value] of Object.entries(triggerNode.data.fields)) { - switch (value.instill_format) { + switch (value.instillFormat) { case "string": { input[key] = "Please put your value here"; break; diff --git a/packages/toolkit/src/view/pipeline-builder/components/top-control-menu/TopControlMenu.tsx b/packages/toolkit/src/view/pipeline-builder/components/top-control-menu/TopControlMenu.tsx index 1b24ef561..5c52cd3be 100644 --- a/packages/toolkit/src/view/pipeline-builder/components/top-control-menu/TopControlMenu.tsx +++ b/packages/toolkit/src/view/pipeline-builder/components/top-control-menu/TopControlMenu.tsx @@ -16,7 +16,7 @@ import { useShallow, } from "../../../../lib"; import { ReactFlowInstance } from "reactflow"; -import { useConstructNodeFromDefinition } from "../../lib"; +import { useAddNodeWithDefinition } from "../../lib"; import { Button, Icons } from "@instill-ai/design-system"; import { PipelineName } from "./PipelineName"; @@ -32,7 +32,7 @@ export const TopControlMenu = ({ }) => { const [open, setOpen] = React.useState(false); const [isSaving, setIsSaving] = React.useState(false); - const constructNode = useConstructNodeFromDefinition({ reactFlowInstance }); + const addNode = useAddNodeWithDefinition({ reactFlowInstance }); const { pipelineIsNew, isEditingIterator } = useInstillStore( useShallow(selector) ); @@ -62,7 +62,7 @@ export const TopControlMenu = ({ open={open} onOpenChange={setOpen} onSelect={(definition) => { - constructNode(definition); + addNode(definition); setOpen(false); }} /> diff --git a/packages/toolkit/src/view/pipeline-builder/lib/checkComponentType.tsx b/packages/toolkit/src/view/pipeline-builder/lib/checkComponentType.tsx index 4bb63c48f..b950bfd4b 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/checkComponentType.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/checkComponentType.tsx @@ -1,24 +1,17 @@ import { PipelineComponent, - PipelineConnectorComponent, + PipelineGeneralComponent, PipelineIteratorComponent, - PipelineOperatorComponent, } from "../../../lib"; -export function isConnectorComponent( +export function isPipelineGeneralComponent( component: PipelineComponent -): component is PipelineConnectorComponent { - return "connector_component" in component; +): component is PipelineGeneralComponent { + return component.type !== "iterator"; } -export function isOperatorComponent( - component: PipelineComponent -): component is PipelineOperatorComponent { - return "operator_component" in component; -} - -export function isIteratorComponent( +export function isPipelineIteratorComponent( component: PipelineComponent ): component is PipelineIteratorComponent { - return "iterator_component" in component; + return component.type === "iterator"; } diff --git a/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidComponentMetadata.ts b/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidComponentMetadata.ts new file mode 100644 index 000000000..dca8bb3c7 --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidComponentMetadata.ts @@ -0,0 +1,16 @@ +import { GeneralRecord, Nullable } from "../../../lib"; +import { PipelineMetadata } from "../type"; + +export function checkIsValidComponentMetadata( + metadata?: Nullable +): metadata is PipelineMetadata { + if ( + metadata && + "component" in metadata && + Object.keys(metadata.component).length > 0 + ) { + return true; + } + + return false; +} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidPosition.test.ts b/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidPosition.test.ts index 3340ceed9..b737903e1 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidPosition.test.ts +++ b/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidPosition.test.ts @@ -3,35 +3,32 @@ import { PipelineRecipe } from "../../../lib"; import { checkIsValidPosition } from "./checkIsValidPosition"; test("should check position is not valid", () => { - const recipe: PipelineRecipe = { - trigger: {}, - components: [ - { - id: "ai_0", - connector_component: { - definition_name: "connector-definitions/stability-ai", - definition: null, - task: "", - input: {}, - condition: null, - connection: {}, - }, + const recipe = { + variable: {}, + component: { + ai_0: { + type: "stability-ai", + definition: null, + task: "", + input: {}, + condition: null, + connection: {}, }, - ], + }, + output: {}, version: "v1beta", - }; + } satisfies PipelineRecipe; const isValid = checkIsValidPosition({ - components: recipe.components, + component: recipe.component, metadata: { - components: [ - { - id: "ai_1", + component: { + ai_0: { x: 0, y: 0, note: null, }, - ], + }, }, }); @@ -39,52 +36,42 @@ test("should check position is not valid", () => { }); test("should check position is valid", () => { - const recipe: PipelineRecipe = { - trigger: { - trigger_by_request: { - request_fields: {}, - response_fields: {}, + const recipe = { + variable: {}, + output: {}, + component: { + ai_0: { + type: "stability-ai", + definition: null, + task: "", + input: {}, + condition: null, + connection: {}, }, }, - components: [ - { - id: "ai_0", - connector_component: { - definition_name: "connector-definitions/stability-ai", - definition: null, - task: "", - input: {}, - condition: null, - connection: {}, - }, - }, - ], version: "v1beta", - }; + } satisfies PipelineRecipe; const isValid = checkIsValidPosition({ - components: recipe.components, + component: recipe.component, metadata: { - components: [ - { - id: "ai_0", + component: { + ai_0: { x: 0, y: 0, note: null, }, - { - id: "trigger", + trigger: { x: 0, y: 0, note: null, }, - { - id: "response", + response: { x: 0, y: 0, note: null, }, - ], + }, }, }); @@ -92,63 +79,54 @@ test("should check position is valid", () => { }); test("should check position is not valid even there is one missing data", () => { - const recipe: PipelineRecipe = { - trigger: {}, - components: [ - { - id: "ai_0", - connector_component: { - definition_name: "connector-definitions/stability-ai", - definition: null, - task: "", - input: {}, - condition: null, - connection: {}, - }, + const recipe = { + variable: {}, + output: {}, + component: { + ai_0: { + type: "stability-ai", + definition: null, + task: "", + input: {}, + condition: null, + connection: {}, }, - { - id: "ai_1", - connector_component: { - definition_name: "connector-definitions/stability-ai", - definition: null, - task: "", - input: {}, - condition: null, - connection: {}, - }, + ai_1: { + type: "stability-ai", + definition: null, + task: "", + input: {}, + condition: null, + connection: {}, }, - { - id: "ai_2", - connector_component: { - definition_name: "connector-definitions/stability-ai", - definition: null, - task: "", - input: {}, - condition: null, - connection: {}, - }, + ai_2: { + type: "stability-ai", + definition: null, + task: "", + input: {}, + condition: null, + connection: {}, }, - ], + }, + version: "v1beta", - }; + } satisfies PipelineRecipe; const isValid = checkIsValidPosition({ - components: recipe.components, + component: recipe.component, metadata: { - components: [ - { - id: "ai_1", + component: { + ai_1: { x: 0, y: 0, note: null, }, - { - id: "ai_2", + ai_2: { x: 0, y: 0, note: null, }, - ], + }, }, }); diff --git a/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidPosition.ts b/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidPosition.ts index 4fb72f401..dbacd2ca7 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidPosition.ts +++ b/packages/toolkit/src/view/pipeline-builder/lib/checkIsValidPosition.ts @@ -1,50 +1,49 @@ -import { GeneralRecord, Nullable, PipelineComponent } from "../../../lib"; -import { PipelineComponentMetadata } from "../type"; +import { GeneralRecord, Nullable, PipelineComponentMap } from "../../../lib"; +import { PipelineComponentMetadataMap } from "../type"; export function checkIsValidPosition({ - components, + component, metadata, isIteratorNode, }: { - components: PipelineComponent[]; + component: Nullable; metadata: Nullable; isIteratorNode?: boolean; }): boolean { - if (metadata && "components" in metadata) { - if (Array.isArray(metadata.components) && metadata.components.length > 0) { - // Check whether we have metadata for trigger - if ( - metadata.components.findIndex((e) => e.id === "trigger") === -1 && - !isIteratorNode - ) { - return false; - } - - // check whether we have metadata for response - if ( - metadata.components.findIndex((e) => e.id === "response") === -1 && - !isIteratorNode - ) { - return false; - } + if ( + component && + metadata && + "component" in metadata && + Object.keys(metadata.component).length > 0 + ) { + // Check whether we have metadata for trigger + if (!metadata.component["trigger"] && !isIteratorNode) { + return false; + } - // Check whether we have metadata for other components in the builder - const componentMetadatas = - metadata.components as PipelineComponentMetadata[]; + // check whether we have metadata for response + if (!metadata.component["response"] && !isIteratorNode) { + return false; + } - const componentIDs = componentMetadatas.map((e) => e.id); + // Check whether we have metadata for other components in the builder + const componentMetadatas = + metadata.component satisfies PipelineComponentMetadataMap; - let isValid = true; + let isValid = true; - for (const component of components) { - if (!componentIDs.includes(component.id)) { - isValid = false; - break; - } + for (const componentID in componentMetadatas) { + if ( + componentID !== "trigger" && + componentID !== "response" && + !component[componentID] + ) { + isValid = false; + break; } - - return isValid; } + + return isValid; } return false; diff --git a/packages/toolkit/src/view/pipeline-builder/lib/checkNodeType.tsx b/packages/toolkit/src/view/pipeline-builder/lib/checkNodeType.tsx index 8f460a0ee..0217a8033 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/checkNodeType.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/checkNodeType.tsx @@ -1,63 +1,32 @@ import { Node } from "reactflow"; import { - ConnectorNodeData, + GeneralNodeData, IteratorNodeData, NodeData, - OperatorNodeData, ResponseNodeData, TriggerNodeData, } from "../type"; +export function isIteratorNode( + node: Node +): node is Node { + return node.type === "iteratorNode"; +} + export function isTriggerNode( node: Node ): node is Node { - return node.id === "trigger"; + return node.type === "triggerNode"; } export function isResponseNode( node: Node ): node is Node { - return node.id === "response"; -} - -export function isConnectorNode( - node: Node -): node is Node { - if ( - node.id !== "trigger" && - node.id !== "response" && - "connector_component" in node.data - ) { - return true; - } - - return false; -} - -export function isOperatorNode( - node: Node -): node is Node { - if ( - node.id !== "trigger" && - node.id !== "response" && - "operator_component" in node.data - ) { - return true; - } - - return false; + return node.type === "responseNode"; } -export function isIteratorNode( +export function isGeneralNode( node: Node -): node is Node { - if ( - node.id !== "trigger" && - node.id !== "response" && - "iterator_component" in node.data - ) { - return true; - } - - return false; +): node is Node { + return node.type === "generalNode"; } diff --git a/packages/toolkit/src/view/pipeline-builder/lib/composeCompleteNodesUnderEditingIteratorMode.tsx b/packages/toolkit/src/view/pipeline-builder/lib/composeCompleteNodesUnderEditingIteratorMode.tsx index edcd4b0bb..6441ee457 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/composeCompleteNodesUnderEditingIteratorMode.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/composeCompleteNodesUnderEditingIteratorMode.tsx @@ -1,8 +1,7 @@ import { Node } from "reactflow"; import { NodeData } from "../type"; -import { isIteratorNode } from "./checkNodeType"; -import { extractComponentFromNodes } from "./extractComponentFromNodes"; -import { composePipelineMetadataFromNodes } from "./composePipelineMetadataFromNodes"; +import { composePipelineMetadataMapFromNodes } from "./composePipelineMetadataMapFromNodes"; +import { composePipelineComponentMapFromNodes } from "./composePipelineComponentMapFromNodes"; export function composeCompleteNodesUnderEditingIteratorMode({ editingIteratorID, @@ -14,18 +13,15 @@ export function composeCompleteNodesUnderEditingIteratorMode({ nodesOutsideIterator: Node[]; }): Node[] { return nodesOutsideIterator?.map((node) => { - if (node.id === editingIteratorID && isIteratorNode(node)) { - const components = extractComponentFromNodes(nodesInIterator); - const metadata = composePipelineMetadataFromNodes(nodesInIterator); + if (node.id === editingIteratorID && node.type === "iteratorNode") { + const component = composePipelineComponentMapFromNodes(nodesInIterator); + const metadata = composePipelineMetadataMapFromNodes(nodesInIterator); return { ...node, data: { ...node.data, - iterator_component: { - ...node.data.iterator_component, - components, - }, + component, metadata, }, }; diff --git a/packages/toolkit/src/view/pipeline-builder/lib/composeEdgesFromNodes.test.ts b/packages/toolkit/src/view/pipeline-builder/lib/composeEdgesFromNodes.test.ts index b6e23bed8..6ee8d45c5 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/composeEdgesFromNodes.test.ts +++ b/packages/toolkit/src/view/pipeline-builder/lib/composeEdgesFromNodes.test.ts @@ -7,11 +7,11 @@ test("should get edges from basic components", () => { const nodes: Node[] = [ { id: "trigger", + type: "triggerNode", data: { - id: "trigger", fields: { texts: { - instill_format: "array:string", + instillFormat: "array:string", title: "texts", description: "", }, @@ -22,8 +22,8 @@ test("should get edges from basic components", () => { }, { id: "response", + type: "responseNode", data: { - id: "response", fields: { result: { title: "result", @@ -45,11 +45,11 @@ test("should get edges from basic components", () => { const wrongNodes: Node[] = [ { id: "trigger", + type: "triggerNode", data: { - id: "trigger", fields: { texts: { - instill_format: "array:string", + instillFormat: "array:string", title: "texts", description: "", }, @@ -60,8 +60,8 @@ test("should get edges from basic components", () => { }, { id: "response", + type: "responseNode", data: { - id: "response", fields: { result: { title: "result", @@ -84,11 +84,11 @@ test("should strictly check the reference field exist", () => { const nodes: Node[] = [ { id: "trigger", + type: "triggerNode", data: { - id: "trigger", fields: { texts: { - instill_format: "array:string", + instillFormat: "array:string", title: "texts", description: "", }, @@ -99,8 +99,8 @@ test("should strictly check the reference field exist", () => { }, { id: "response", + type: "responseNode", data: { - id: "response", fields: { result: { title: "result", @@ -123,11 +123,11 @@ test("should loosely check the reference field exist when reference has square b const nodes: Node[] = [ { id: "trigger", + type: "triggerNode", data: { - id: "trigger", fields: { texts: { - instill_format: "array:string", + instillFormat: "array:string", title: "texts", description: "", }, @@ -138,8 +138,8 @@ test("should loosely check the reference field exist when reference has square b }, { id: "response", + type: "responseNode", data: { - id: "response", fields: { result: { title: "result", @@ -161,11 +161,11 @@ test("should loosely check the reference field exist when reference has square b const wrongNodes: Node[] = [ { id: "trigger", + type: "triggerNode", data: { - id: "trigger", fields: { texts: { - instill_format: "array:string", + instillFormat: "array:string", title: "texts", description: "", }, @@ -176,8 +176,8 @@ test("should loosely check the reference field exist when reference has square b }, { id: "response", + type: "responseNode", data: { - id: "response", fields: { result: { title: "result", diff --git a/packages/toolkit/src/view/pipeline-builder/lib/composeEdgesFromNodes.ts b/packages/toolkit/src/view/pipeline-builder/lib/composeEdgesFromNodes.ts index 68eae72d3..770597c3a 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/composeEdgesFromNodes.ts +++ b/packages/toolkit/src/view/pipeline-builder/lib/composeEdgesFromNodes.ts @@ -4,22 +4,20 @@ import { Edge, Node } from "reactflow"; import type { InstillReference, NodeData } from "../type"; import type { InstillJSONSchema, Nullable } from "../../../lib"; import { getReferencesFromAny } from "./getReferencesFromAny"; -import { getOperatorInputOutputSchema } from "./getOperatorInputOutputSchema"; -import { getConnectorInputOutputSchema } from "./getConnectorInputOutputSchema"; import { InstillAIOpenAPIProperty, getPropertiesFromOpenAPISchema, } from "./getPropertiesFromOpenAPISchema"; -import { getConnectorOperatorComponentConfiguration } from "./getConnectorOperatorComponentConfiguration"; +import { getGeneralComponentConfiguration } from "./getGeneralComponentConfiguration"; +import { createNodesFromPipelineComponents } from "./createNodesFromPipelineComponents"; import { - isConnectorNode, + isGeneralNode, isIteratorNode, - isOperatorNode, isResponseNode, isTriggerNode, } from "./checkNodeType"; -import { createNodesFromPipelineComponents } from "./createNodesFromPipelineComponents"; +import { getGeneralComponentInOutputSchema } from "./getGeneralComponentInOutputSchema"; type ReferenceWithNodeInfo = { nodeID: string; @@ -80,12 +78,10 @@ function getConnectedReferencesFromNodes( } if (isIteratorNode(node)) { - const inputReference = getReferencesFromAny( - node.data.iterator_component.input - ); + const inputReference = getReferencesFromAny(node.data.input); const nodesInInterator = createNodesFromPipelineComponents( - node.data.iterator_component.components + node.data.component ); // All the components inside the iterator will belong to the iterator itself @@ -106,10 +102,8 @@ function getConnectedReferencesFromNodes( continue; } - if (isConnectorNode(node) || isOperatorNode(node)) { - const configuration = getConnectorOperatorComponentConfiguration( - node.data - ); + if (isGeneralNode(node)) { + const configuration = getGeneralComponentConfiguration(node.data); const referencesOfThisNode = getReferencesFromAny(configuration); @@ -148,20 +142,13 @@ function getAvailableReferencesFromNodes(nodes: Node[]) { let outputSchema: Nullable = null; if (isIteratorNode(node)) { - outputSchema = - node.data.iterator_component.data_specification?.output ?? null; - } - - if (isOperatorNode(node)) { - const { outputSchema: operatorOutputSchema } = - getOperatorInputOutputSchema(node.data); - outputSchema = operatorOutputSchema; + outputSchema = node.data.data_specification?.output ?? null; } - if (isConnectorNode(node)) { - const { outputSchema: connectorOutputSchema } = - getConnectorInputOutputSchema(node.data); - outputSchema = connectorOutputSchema; + if (isGeneralNode(node)) { + const { outputSchema: GeneralNodeOutputSchema } = + getGeneralComponentInOutputSchema(node.data); + outputSchema = GeneralNodeOutputSchema; } let outputProperties: InstillAIOpenAPIProperty[] = []; diff --git a/packages/toolkit/src/view/pipeline-builder/lib/composePipelineComponentMapFromNodes.ts b/packages/toolkit/src/view/pipeline-builder/lib/composePipelineComponentMapFromNodes.ts new file mode 100644 index 000000000..0da01d6e2 --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/lib/composePipelineComponentMapFromNodes.ts @@ -0,0 +1,66 @@ +import { Node } from "reactflow"; +import { NodeData } from "../type"; +import { PipelineComponentMap } from "../../../lib"; +import { isGeneralNode, isIteratorNode } from "./checkNodeType"; +import { isPipelineGeneralComponent } from "./checkComponentType"; +import { recursiveHelpers } from "./recursive-helpers"; + +export function composePipelineComponentMapFromNodes(nodes: Node[]) { + const componentMap: PipelineComponentMap = {}; + + for (const node of nodes) { + if (isIteratorNode(node)) { + componentMap[node.id] = { + ...node.data, + component: Object.fromEntries( + Object.entries(node.data.component).map(([key, e]) => { + if (isPipelineGeneralComponent(e)) { + return [ + key, + { + ...e, + definition: undefined, + input: + recursiveHelpers.replaceNullAndEmptyStringWithUndefined( + recursiveHelpers.parseToNum(structuredClone(e.input)) + ), + connection: e.connection + ? recursiveHelpers.replaceNullAndEmptyStringWithUndefined( + recursiveHelpers.parseToNum( + structuredClone(e.connection) + ) + ) + : undefined, + }, + ]; + } + + return [key, e]; + }) + ), + }; + + continue; + } + + if (isGeneralNode(node)) { + componentMap[node.id] = { + ...node.data, + input: recursiveHelpers.replaceNullAndEmptyStringWithUndefined( + recursiveHelpers.parseToNum(structuredClone(node.data.input)) + ), + connection: node.data.connection + ? recursiveHelpers.replaceNullAndEmptyStringWithUndefined( + recursiveHelpers.parseToNum(structuredClone(node.data.connection)) + ) + : undefined, + definition: undefined, + metadata: node.data.metadata ?? undefined, + }; + + continue; + } + } + + return componentMap; +} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataFromNodes.ts b/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataFromNodes.ts deleted file mode 100644 index d8ef60207..000000000 --- a/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataFromNodes.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Node } from "reactflow"; -import { NodeData, PipelineComponentMetadata } from "../type"; - -export function composePipelineMetadataFromNodes(nodes: Node[]) { - const componentMetadatas: PipelineComponentMetadata[] = []; - - for (const node of nodes) { - componentMetadatas.push({ - id: node.id, - note: node.data.note, - x: node.position.x, - y: node.position.y, - }); - } - - return { - components: componentMetadatas, - }; -} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataFromNodes.test.ts b/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataMapFromNodes.test.ts similarity index 52% rename from packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataFromNodes.test.ts rename to packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataMapFromNodes.test.ts index f262a92bf..345172bbb 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataFromNodes.test.ts +++ b/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataMapFromNodes.test.ts @@ -1,7 +1,7 @@ import { Node } from "reactflow"; import { test, expect } from "vitest"; import { NodeData } from "../type"; -import { composePipelineMetadataFromNodes } from "./composePipelineMetadataFromNodes"; +import { composePipelineMetadataMapFromNodes } from "./composePipelineMetadataMapFromNodes"; test("should compose initial pipeline metadata", () => { const nodes: Node[] = [ @@ -12,15 +12,12 @@ test("should compose initial pipeline metadata", () => { y: 0, }, data: { - id: "ai_0", - connector_component: { - definition_name: "connector-definitions/stability-ai", - definition: null, - task: "", - input: {}, - condition: null, - connection: {}, - }, + type: "stability-ai", + definition: null, + task: "", + input: {}, + condition: null, + connection: {}, note: null, }, }, @@ -31,7 +28,6 @@ test("should compose initial pipeline metadata", () => { y: 100, }, data: { - id: "trigger", fields: {}, note: "hello-world", }, @@ -43,20 +39,31 @@ test("should compose initial pipeline metadata", () => { y: 300, }, data: { - id: "response", fields: {}, note: null, }, }, ]; - const metadata = composePipelineMetadataFromNodes(nodes); + const metadata = composePipelineMetadataMapFromNodes(nodes); expect(metadata).toStrictEqual({ - components: [ - { id: "ai_0", note: null, x: 0, y: 0 }, - { id: "trigger", note: "hello-world", x: 100, y: 100 }, - { id: "response", note: null, x: 300, y: 300 }, - ], + component: { + ai_0: { + note: null, + x: 0, + y: 0, + }, + trigger: { + note: "hello-world", + x: 100, + y: 100, + }, + response: { + note: null, + x: 300, + y: 300, + }, + }, }); }); diff --git a/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataMapFromNodes.ts b/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataMapFromNodes.ts new file mode 100644 index 000000000..27caee90e --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/lib/composePipelineMetadataMapFromNodes.ts @@ -0,0 +1,18 @@ +import { Node } from "reactflow"; +import { NodeData, PipelineComponentMetadataMap } from "../type"; + +export function composePipelineMetadataMapFromNodes(nodes: Node[]) { + const componentMetadatas: PipelineComponentMetadataMap = {}; + + for (const node of nodes) { + componentMetadatas[node.id] = { + note: node.data.note, + x: node.position.x, + y: node.position.y, + }; + } + + return { + component: componentMetadatas, + }; +} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/composePipelineRecipeFromNodes.tsx b/packages/toolkit/src/view/pipeline-builder/lib/composePipelineRecipeFromNodes.tsx new file mode 100644 index 000000000..e8aee0352 --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/lib/composePipelineRecipeFromNodes.tsx @@ -0,0 +1,106 @@ +import { recursiveHelpers } from "./recursive-helpers"; +import { PipelineComponentMap, PipelineRecipe } from "../../../lib"; +import { Node } from "reactflow"; +import { NodeData, ResponseNodeData, TriggerNodeData } from "../type"; +import { + isGeneralNode, + isIteratorNode, + isResponseNode, + isTriggerNode, +} from "./checkNodeType"; +import { isPipelineGeneralComponent } from "./checkComponentType"; + +export function composePipelineRecipeFromNodes( + nodes: Node[] +): PipelineRecipe { + const recipeComponent: PipelineComponentMap = {}; + + for (const node of nodes) { + if (isIteratorNode(node)) { + recipeComponent[node.id] = { + definition: undefined, + metadata: node.data.metadata, + input: node.data.input, + condition: node.data.condition, + outputElements: node.data.outputElements, + data_specification: null, + type: node.data.type, + component: Object.fromEntries( + Object.entries(node.data.component).map(([key, e]) => { + if (isPipelineGeneralComponent(e)) { + return [ + key, + { + definition: undefined, + input: e.input + ? recursiveHelpers.replaceNullAndEmptyStringWithUndefined( + recursiveHelpers.parseToNum(structuredClone(e.input)) + ) + : undefined, + connection: e.connection + ? recursiveHelpers.replaceNullAndEmptyStringWithUndefined( + recursiveHelpers.parseToNum( + structuredClone(e.connection) + ) + ) + : undefined, + condition: e.condition, + type: e.type, + task: e.task, + metadata: e.metadata ?? undefined, + }, + ]; + } + + return [key, e]; + }) + ), + }; + + continue; + } + + if (isGeneralNode(node)) { + recipeComponent[node.id] = { + condition: node.data.condition, + task: node.data.task, + type: node.data.type, + input: recursiveHelpers.replaceNullAndEmptyStringWithUndefined( + recursiveHelpers.parseToNum(structuredClone(node.data.input)) + ), + connection: node.data.connection + ? recursiveHelpers.replaceNullAndEmptyStringWithUndefined( + recursiveHelpers.parseToNum(structuredClone(node.data.connection)) + ) + : undefined, + definition: undefined, + metadata: node.data.metadata ?? undefined, + }; + + continue; + } + } + + const triggerNode = nodes.find( + (node) => node.id === "trigger" && isTriggerNode(node) + ) as Node | undefined; + + const responseNode = nodes.find( + (node) => node.id === "response" && isResponseNode(node) + ) as Node | undefined; + + return { + version: "v1beta", + component: recipeComponent, + variable: triggerNode + ? Object.keys(triggerNode.data.fields).length > 0 + ? triggerNode.data.fields + : undefined + : undefined, + output: responseNode + ? Object.keys(responseNode.data.fields).length > 0 + ? responseNode.data.fields + : undefined + : undefined, + }; +} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/constructPipelineRecipeFromNodes.tsx b/packages/toolkit/src/view/pipeline-builder/lib/constructPipelineRecipeFromNodes.tsx deleted file mode 100644 index d6ba5573c..000000000 --- a/packages/toolkit/src/view/pipeline-builder/lib/constructPipelineRecipeFromNodes.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import { recursiveHelpers } from "./recursive-helpers"; -import { PipelineComponent, PipelineRecipe } from "../../../lib"; -import { Node } from "reactflow"; -import { NodeData, ResponseNodeData, TriggerNodeData } from "../type"; -import { - isConnectorNode, - isIteratorNode, - isOperatorNode, - isResponseNode, - isTriggerNode, -} from "./checkNodeType"; -import { - isConnectorComponent, - isOperatorComponent, -} from "./checkComponentType"; - -export function constructPipelineRecipeFromNodes( - nodes: Node[] -): PipelineRecipe { - const recipeComponents: PipelineComponent[] = []; - - for (const node of nodes) { - if (isIteratorNode(node)) { - recipeComponents.push({ - id: node.id, - iterator_component: { - ...node.data.iterator_component, - components: node.data.iterator_component.components.map( - (component) => { - if (isConnectorComponent(component)) { - return { - ...component, - connector_component: { - ...component.connector_component, - definition: undefined, - input: - recursiveHelpers.replaceNullAndEmptyStringWithUndefined( - recursiveHelpers.parseToNum( - structuredClone(component.connector_component.input) - ) - ), - connection: - recursiveHelpers.replaceNullAndEmptyStringWithUndefined( - recursiveHelpers.parseToNum( - structuredClone( - component.connector_component.connection - ) - ) - ), - }, - }; - } - - if (isOperatorComponent(component)) { - return { - ...component, - operator_component: { - ...component.operator_component, - definition: undefined, - input: - recursiveHelpers.replaceNullAndEmptyStringWithUndefined( - recursiveHelpers.parseToNum( - structuredClone(component.operator_component.input) - ) - ), - }, - }; - } - - return component; - } - ), - }, - metadata: node.data.metadata ?? undefined, - }); - continue; - } - - if (isConnectorNode(node)) { - recipeComponents.push({ - id: node.id, - connector_component: { - ...node.data.connector_component, - input: recursiveHelpers.replaceNullAndEmptyStringWithUndefined( - recursiveHelpers.parseToNum( - structuredClone(node.data.connector_component.input) - ) - ), - connection: recursiveHelpers.replaceNullAndEmptyStringWithUndefined( - recursiveHelpers.parseToNum( - structuredClone(node.data.connector_component.connection) - ) - ), - definition: undefined, - }, - metadata: node.data.metadata ?? undefined, - }); - - continue; - } - - if (isOperatorNode(node)) { - recipeComponents.push({ - id: node.id, - operator_component: { - ...node.data.operator_component, - input: recursiveHelpers.replaceNullAndEmptyStringWithUndefined( - recursiveHelpers.parseToNum( - structuredClone(node.data.operator_component.input) - ) - ), - definition: undefined, - }, - metadata: node.data.metadata ?? undefined, - }); - } - } - - const triggerNode = nodes.find( - (node) => node.id === "trigger" && isTriggerNode(node) - ) as Node | undefined; - - const responseNode = nodes.find( - (node) => node.id === "response" && isResponseNode(node) - ) as Node | undefined; - - return { - version: "v1beta", - components: recipeComponents, - trigger: { - trigger_by_request: { - request_fields: triggerNode ? triggerNode.data.fields : {}, - response_fields: responseNode ? responseNode.data.fields : {}, - }, - }, - }; -} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/createGraphLayout.tsx b/packages/toolkit/src/view/pipeline-builder/lib/createGraphLayout.tsx index 204ae9f2a..35c1d3672 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/createGraphLayout.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/createGraphLayout.tsx @@ -74,12 +74,12 @@ export async function createGraphLayout( // return fixed layout if ( nodes.length === 2 && - nodes.findIndex((node) => node.data.id === "trigger") !== -1 && - nodes.findIndex((node) => node.data.id === "response") !== -1 + nodes.findIndex((node) => node.id === "trigger") !== -1 && + nodes.findIndex((node) => node.id === "response") !== -1 ) { return { nodes: nodes.map((node) => { - if (node.data.id === "trigger") { + if (node.id === "trigger") { node.position = { x: 0, y: 0 }; } else { node.position = { x: 350, y: 0 }; @@ -91,7 +91,7 @@ export async function createGraphLayout( } nodes.forEach((node) => { - if (node.data.id === "trigger" || node.data.id === "response") { + if (node.id === "trigger" || node.id === "response") { elkNodes.push({ id: node.id, width: TRIGGER_RESPONSE_NODE.width, @@ -137,7 +137,7 @@ export async function createGraphLayout( // We are shifting the dagre node position (anchor=center center) to the top left // so it matches the React Flow node anchor point (top left). - if (node.data.id === "trigger" || node.data.id === "response") { + if (node.id === "trigger" || node.id === "response") { node.position = { x: elkNode.x - TRIGGER_RESPONSE_NODE.width / 2, y: elkNode.y - TRIGGER_RESPONSE_NODE.height / 2, diff --git a/packages/toolkit/src/view/pipeline-builder/lib/createNodesFromPipelineComponents.tsx b/packages/toolkit/src/view/pipeline-builder/lib/createNodesFromPipelineComponents.tsx index 4923f207b..b5924318d 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/createNodesFromPipelineComponents.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/createNodesFromPipelineComponents.tsx @@ -2,50 +2,44 @@ import { Node } from "reactflow"; import { NodeData, PipelineComponentMetadata } from "../type"; import { recursiveHelpers } from "."; -import { GeneralRecord, Nullable, PipelineComponent } from "../../../lib"; +import { GeneralRecord, Nullable, PipelineComponentMap } from "../../../lib"; import { - isConnectorComponent, - isIteratorComponent, - isOperatorComponent, + isPipelineGeneralComponent, + isPipelineIteratorComponent, } from "./checkComponentType"; +import { checkIsValidComponentMetadata } from "./checkIsValidComponentMetadata"; export type CreateNodesFromPipelineComponentsOptions = { metadata?: GeneralRecord; }; export function createNodesFromPipelineComponents( - components: PipelineComponent[], + component: PipelineComponentMap, options?: CreateNodesFromPipelineComponentsOptions ) { const nodes: Node[] = []; const metadata = options ? options.metadata : null; - for (const component of components) { + for (const [id, e] of Object.entries(component)) { let componentMetadata: Nullable = null; - if ( - metadata && - "components" in metadata && - Array.isArray(metadata.components) - ) { - componentMetadata = - metadata.components.find((c) => c.id === component.id) ?? null; + if (checkIsValidComponentMetadata(metadata)) { + componentMetadata = metadata.component[id]; } // The reason we need to transform all the value back to string is due to some // constraint of the auto-form, most of the auto-form field value is string // for example, number field. (But boolean field is using boolean) - if (isIteratorComponent(component)) { + if (isPipelineIteratorComponent(e)) { nodes.push({ - id: component.id, + id, type: "iteratorNode", data: { - id: component.id, - iterator_component: component.iterator_component, + ...e, note: componentMetadata ? componentMetadata.note : null, - metadata: component.metadata, + metadata: e.metadata, }, position: componentMetadata ? { x: componentMetadata.x, y: componentMetadata.y } @@ -59,41 +53,17 @@ export function createNodesFromPipelineComponents( // Especially the original configuration connect back to the react-query object // It will pollute other components - if (isOperatorComponent(component)) { + if (isPipelineGeneralComponent(e)) { nodes.push({ - id: component.id, - type: "operatorNode", + id, + type: "generalNode", data: { - id: component.id, - operator_component: { - ...component.operator_component, - input: recursiveHelpers.parseNumberToString( - component.operator_component.input - ), - }, - metadata: component.metadata, - note: componentMetadata ? componentMetadata.note : null, - }, - position: componentMetadata - ? { x: componentMetadata.x, y: componentMetadata.y } - : { x: 0, y: 0 }, - }); - continue; - } - - if (isConnectorComponent(component)) { - nodes.push({ - id: component.id, - type: "connectorNode", - data: { - id: component.id, - connector_component: { - ...component.connector_component, - input: recursiveHelpers.parseNumberToString( - component.connector_component.input - ), - }, - metadata: component.metadata, + ...e, + connection: e.connection + ? recursiveHelpers.parseNumberToString(e.input) + : null, + input: recursiveHelpers.parseNumberToString(e.input), + metadata: e.metadata, note: componentMetadata ? componentMetadata.note : null, }, position: componentMetadata diff --git a/packages/toolkit/src/view/pipeline-builder/lib/createNodesFromPipelineRecipe.tsx b/packages/toolkit/src/view/pipeline-builder/lib/createNodesFromPipelineRecipe.tsx index ccc1ddeef..e2a96187a 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/createNodesFromPipelineRecipe.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/createNodesFromPipelineRecipe.tsx @@ -1,13 +1,7 @@ import { Node } from "reactflow"; -import { - GeneralRecord, - Nullable, - PipelineRecipe, - TriggerByRequest, -} from "../../../lib"; +import { GeneralRecord, Nullable, PipelineRecipe } from "../../../lib"; import { NodeData, PipelineComponentMetadata } from "../type"; import { createNodesFromPipelineComponents } from "./createNodesFromPipelineComponents"; -import { isTriggerByRequest } from "./isTriggerByRequest"; export type CreateNodesFromPipelineRecipeOptions = { metadata?: GeneralRecord; @@ -20,35 +14,26 @@ export function createNodesFromPipelineRecipe( const metadata = options?.metadata; const nodes: Node[] = []; - const componentNodes = createNodesFromPipelineComponents(recipe.components, { - metadata, - }); - nodes.push(...componentNodes); + if (recipe.component) { + const componentNodes = createNodesFromPipelineComponents(recipe.component, { + metadata, + }); + nodes.push(...componentNodes); + } // create trigger node let triggerMetadata: Nullable = null; - if ( - metadata && - "components" in metadata && - Array.isArray(metadata.components) - ) { - triggerMetadata = metadata.components.find((c) => c.id === "trigger"); - } - - let triggerByRequest: Nullable = null; - - if (isTriggerByRequest(recipe.trigger)) { - triggerByRequest = recipe.trigger; + if (metadata && "component" in metadata) { + triggerMetadata = metadata.component["trigger"]; } nodes.push({ id: "trigger", type: "triggerNode", data: { - id: "trigger", - fields: triggerByRequest?.trigger_by_request.request_fields ?? {}, + fields: recipe.variable ?? {}, note: triggerMetadata ? triggerMetadata.note : null, }, position: triggerMetadata @@ -60,20 +45,15 @@ export function createNodesFromPipelineRecipe( let responseMetadata: Nullable = null; - if ( - metadata && - "components" in metadata && - Array.isArray(metadata.components) - ) { - responseMetadata = metadata.components.find((c) => c.id === "response"); + if (metadata && "component" in metadata) { + responseMetadata = metadata.component["response"]; } nodes.push({ id: "response", type: "responseNode", data: { - id: "response", - fields: triggerByRequest?.trigger_by_request.response_fields ?? {}, + fields: recipe.output ?? {}, note: responseMetadata ? responseMetadata.note : null, }, position: responseMetadata diff --git a/packages/toolkit/src/view/pipeline-builder/lib/extractComponentFromNodes.ts b/packages/toolkit/src/view/pipeline-builder/lib/extractComponentFromNodes.ts deleted file mode 100644 index 4b3b6bb44..000000000 --- a/packages/toolkit/src/view/pipeline-builder/lib/extractComponentFromNodes.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Node } from "reactflow"; -import { NodeData } from "../type"; -import { PipelineComponent } from "../../../lib"; -import { - isConnectorNode, - isIteratorNode, - isOperatorNode, -} from "./checkNodeType"; - -export function extractComponentFromNodes(nodes: Node[]) { - const components: PipelineComponent[] = []; - - for (const node of nodes) { - if (isIteratorNode(node) || isConnectorNode(node) || isOperatorNode(node)) { - components.push(node.data); - } - } - - return components; -} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/getAllComponentID.tsx b/packages/toolkit/src/view/pipeline-builder/lib/getAllComponentID.tsx deleted file mode 100644 index 6c92df8e9..000000000 --- a/packages/toolkit/src/view/pipeline-builder/lib/getAllComponentID.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { isIteratorComponent } from "./checkComponentType"; -import { PipelineComponent } from "../../../lib"; - -export function getAllComponentID(components: PipelineComponent[]): string[] { - const nodeIDs: string[] = []; - - for (const component of components) { - if (isIteratorComponent(component)) { - nodeIDs.push(component.id); - nodeIDs.push( - ...getAllComponentID(component.iterator_component.components) - ); - continue; - } - - nodeIDs.push(component.id); - } - - return nodeIDs; -} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/getAllNodeID.tsx b/packages/toolkit/src/view/pipeline-builder/lib/getAllNodeID.tsx new file mode 100644 index 000000000..0238993b4 --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/lib/getAllNodeID.tsx @@ -0,0 +1,19 @@ +import { Node } from "reactflow"; +import { NodeData } from "../type"; +import { isIteratorNode } from "./checkNodeType"; + +export function getAllNodeID(nodes: Node[]): string[] { + const nodeIDs: string[] = []; + + for (const node of nodes) { + if (isIteratorNode(node)) { + nodeIDs.push(node.id); + nodeIDs.push(...Object.keys(node.data.component)); + continue; + } + + nodeIDs.push(node.id); + } + + return nodeIDs; +} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/getConnectorInputOutputSchema.ts b/packages/toolkit/src/view/pipeline-builder/lib/getConnectorInputOutputSchema.ts deleted file mode 100644 index 43143f07b..000000000 --- a/packages/toolkit/src/view/pipeline-builder/lib/getConnectorInputOutputSchema.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { - InstillJSONSchema, - Nullable, - PipelineConnectorComponent, -} from "../../../lib"; -import { JSONSchema7 } from "json-schema"; - -export function getConnectorInputOutputSchema( - component: PipelineConnectorComponent, - task?: string -) { - let inputSchema: Nullable = null; - let outputSchema: Nullable = null; - - // Sometime the component don't have complete data (Like the response of mutating the pipeline) - if (!component.connector_component) { - return { outputSchema, inputSchema }; - } - - // Additional guard - if (!component.connector_component.input) { - return { outputSchema, inputSchema }; - } - - const targetTask = task ?? component.connector_component.task; - - // We need to support the breaking changes that maybe the previous selected task's - // definition is not support anymore. Console need to check this. - if ( - targetTask && - component?.connector_component.definition?.spec.data_specifications && - component?.connector_component.definition?.spec.data_specifications[ - targetTask - ] - ) { - inputSchema = component?.connector_component.definition?.spec - .data_specifications[targetTask].input as InstillJSONSchema; - outputSchema = component?.connector_component.definition?.spec - .data_specifications[targetTask].output as InstillJSONSchema; - } else if ( - component.connector_component.definition?.spec.component_specification - .oneOf && - component.connector_component.definition.spec.component_specification.oneOf - .length > 0 - ) { - const defaultTask = - (( - ( - component?.connector_component.definition?.spec - .component_specification.oneOf[0] as JSONSchema7 - )?.properties?.task as JSONSchema7 - )?.const as string) ?? null; - - if (!defaultTask) { - return { outputSchema, inputSchema }; - } - - if (component?.connector_component.definition?.spec.data_specifications) { - inputSchema = component?.connector_component.definition?.spec - .data_specifications[defaultTask].input as InstillJSONSchema; - outputSchema = component?.connector_component.definition?.spec - .data_specifications[defaultTask].output as InstillJSONSchema; - } - } - - return { outputSchema, inputSchema }; -} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/getConnectorOperatorComponentConfiguration.ts b/packages/toolkit/src/view/pipeline-builder/lib/getConnectorOperatorComponentConfiguration.ts deleted file mode 100644 index be0d12105..000000000 --- a/packages/toolkit/src/view/pipeline-builder/lib/getConnectorOperatorComponentConfiguration.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { - PipelineConnectorComponent, - PipelineOperatorComponent, -} from "../../../lib"; - -export const getConnectorOperatorComponentConfiguration = ( - component: PipelineConnectorComponent | PipelineOperatorComponent -) => { - if ("connector_component" in component) { - return { - input: component.connector_component.input, - task: component.connector_component.task, - condition: component.connector_component.condition, - connection: component.connector_component.connection, - }; - } else { - return { - input: component.operator_component.input, - task: component.operator_component.task, - condition: component.operator_component.condition, - }; - } -}; diff --git a/packages/toolkit/src/view/pipeline-builder/lib/getGeneralComponentConfiguration.ts b/packages/toolkit/src/view/pipeline-builder/lib/getGeneralComponentConfiguration.ts new file mode 100644 index 000000000..bc91e71cb --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/lib/getGeneralComponentConfiguration.ts @@ -0,0 +1,12 @@ +import { PipelineGeneralComponent } from "../../../lib"; + +export const getGeneralComponentConfiguration = ( + component: PipelineGeneralComponent +) => { + return { + input: component.input, + task: component.task, + condition: component.condition, + connection: component.connection ? component.connection : undefined, + }; +}; diff --git a/packages/toolkit/src/view/pipeline-builder/lib/getGeneralComponentInOutputSchema.ts b/packages/toolkit/src/view/pipeline-builder/lib/getGeneralComponentInOutputSchema.ts new file mode 100644 index 000000000..bec2c78d2 --- /dev/null +++ b/packages/toolkit/src/view/pipeline-builder/lib/getGeneralComponentInOutputSchema.ts @@ -0,0 +1,59 @@ +import { + InstillJSONSchema, + Nullable, + PipelineGeneralComponent, +} from "../../../lib"; +import { JSONSchema7 } from "json-schema"; + +export function getGeneralComponentInOutputSchema( + component: PipelineGeneralComponent, + task?: string +) { + let inputSchema: Nullable = null; + let outputSchema: Nullable = null; + + // Additional guard + if (!component.input) { + return { outputSchema, inputSchema }; + } + + const targetTask = task ?? component.task; + + // We need to support the breaking changes that maybe the previous selected task's + // definition is not support anymore. Console need to check this. + if ( + targetTask && + component?.definition?.spec.data_specifications && + component?.definition?.spec.data_specifications[targetTask] + ) { + inputSchema = component?.definition?.spec.data_specifications[targetTask] + .input as InstillJSONSchema; + outputSchema = component?.definition?.spec.data_specifications[targetTask] + .output as InstillJSONSchema; + } else if ( + component.definition?.spec.component_specification.oneOf && + component.definition?.spec.component_specification.oneOf.length > 0 + ) { + const defaultTask = + (( + ( + component.definition?.spec.component_specification + .oneOf[0] as JSONSchema7 + )?.properties?.task as JSONSchema7 + )?.const as string) ?? null; + + if (!defaultTask) { + return { outputSchema, inputSchema }; + } + + if (component?.definition?.spec.data_specifications) { + inputSchema = component?.definition?.spec.data_specifications[defaultTask] + .input as InstillJSONSchema; + outputSchema = component?.definition?.spec.data_specifications[ + defaultTask + ].output as InstillJSONSchema; + } + } + + return { outputSchema, inputSchema }; +} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/getOperatorInputOutputSchema.ts b/packages/toolkit/src/view/pipeline-builder/lib/getOperatorInputOutputSchema.ts deleted file mode 100644 index fff046569..000000000 --- a/packages/toolkit/src/view/pipeline-builder/lib/getOperatorInputOutputSchema.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { - InstillJSONSchema, - Nullable, - PipelineOperatorComponent, -} from "../../../lib"; -import { JSONSchema7 } from "json-schema"; - -export function getOperatorInputOutputSchema( - component: PipelineOperatorComponent, - task?: string -) { - let inputSchema: Nullable = null; - let outputSchema: Nullable = null; - - // Sometime the component don't have complete data (Like the response of mutating the pipeline) - if (!component.operator_component) { - return { outputSchema, inputSchema }; - } - - // Additional guard - if (!component.operator_component.input) { - return { outputSchema, inputSchema }; - } - - const targetTask = task ?? component.operator_component.task; - - // We need to support the breaking changes that maybe the previous selected task's - // definition is not support anymore. Console need to check this. - if ( - targetTask && - component?.operator_component.definition?.spec.data_specifications && - component?.operator_component.definition?.spec.data_specifications[ - targetTask - ] - ) { - inputSchema = component?.operator_component.definition?.spec - .data_specifications[targetTask].input as InstillJSONSchema; - outputSchema = component?.operator_component.definition?.spec - .data_specifications[targetTask].output as InstillJSONSchema; - } else if ( - component.operator_component.definition?.spec.component_specification - .oneOf && - component.operator_component.definition?.spec.component_specification.oneOf - .length > 0 - ) { - const defaultTask = - (( - ( - component.operator_component.definition?.spec.component_specification - .oneOf[0] as JSONSchema7 - )?.properties?.task as JSONSchema7 - )?.const as string) ?? null; - - if (!defaultTask) { - return { outputSchema, inputSchema }; - } - - if (component?.operator_component.definition?.spec.data_specifications) { - inputSchema = component?.operator_component.definition?.spec - .data_specifications[defaultTask].input as InstillJSONSchema; - outputSchema = component?.operator_component.definition?.spec - .data_specifications[defaultTask].output as InstillJSONSchema; - } - } - - return { outputSchema, inputSchema }; -} diff --git a/packages/toolkit/src/view/pipeline-builder/lib/hooks/index.ts b/packages/toolkit/src/view/pipeline-builder/lib/hooks/index.ts index 8308f786b..2a38041ba 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/hooks/index.ts +++ b/packages/toolkit/src/view/pipeline-builder/lib/hooks/index.ts @@ -5,4 +5,4 @@ export * from "./useSavePipeline"; export * from "./useSortedReleases"; export * from "./useUpdaterOnNode"; export * from "./useUpdaterOnRightPanel"; -export * from "./useConstructNodeFromDefinition"; +export * from "./useAddNodeWithDefinition"; diff --git a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useConstructNodeFromDefinition.tsx b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useAddNodeWithDefinition.tsx similarity index 76% rename from packages/toolkit/src/view/pipeline-builder/lib/hooks/useConstructNodeFromDefinition.tsx rename to packages/toolkit/src/view/pipeline-builder/lib/hooks/useAddNodeWithDefinition.tsx index 35e948ace..c0a6a17d3 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useConstructNodeFromDefinition.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useAddNodeWithDefinition.tsx @@ -11,8 +11,11 @@ import { } from "../../../../lib"; import { transformConnectorDefinitionIDToComponentIDPrefix } from "../transformConnectorDefinitionIDToComponentIDPrefix"; import { generateUniqueIndex } from "../generateUniqueIndex"; -import { getAllComponentID } from "../getAllComponentID"; -import { extractComponentFromNodes } from "../extractComponentFromNodes"; +import { getAllNodeID } from "../getAllNodeID"; +import { + isConnectorDefinition, + isIteratorDefinition, +} from "../../../../lib/vdp-sdk/helper"; const selector = (store: InstillStore) => ({ nodes: store.nodes, @@ -23,7 +26,7 @@ const selector = (store: InstillStore) => ({ isEditingIterator: store.isEditingIterator, }); -export function useConstructNodeFromDefinition({ +export function useAddNodeWithDefinition({ reactFlowInstance, }: { reactFlowInstance: Nullable; @@ -92,11 +95,10 @@ export function useConstructNodeFromDefinition({ // iterator, so we need to group the two set of nodes together. Under the // editing iterator mode, nodes will be the nodes in the iterator, and // tempSavedNodesForEditingIteratorFlow will be the nodes outside the iterator - const components = extractComponentFromNodes(nodes); const nodeIndex = generateUniqueIndex( isEditingIterator ? [...nodes, ...tempSavedNodesForEditingIteratorFlow].map((e) => e.id) - : getAllComponentID(components), + : getAllNodeID(nodes), nodePrefix ); @@ -104,8 +106,7 @@ export function useConstructNodeFromDefinition({ let newNodes = nodes; - if (definition.id === "iterator") { - // Process the iterators + if (isIteratorDefinition(definition)) { newNodes = [ ...newNodes, { @@ -114,19 +115,17 @@ export function useConstructNodeFromDefinition({ sourcePosition: Position.Left, targetPosition: Position.Right, data: { - id: nodeID, - iterator_component: { - input: "", - output_elements: { - // This is the default output element - result_0: "", - }, - components: [], - condition: null, - data_specification: { - input: null, - output: null, - }, + input: "", + type: "iterator", + outputElements: { + // This is the default output element + result_0: "", + }, + component: {}, + condition: null, + data_specification: { + input: null, + output: null, }, note: null, }, @@ -134,24 +133,21 @@ export function useConstructNodeFromDefinition({ zIndex: 20, }, ]; - } else if ("type" in definition) { + } else if (isConnectorDefinition(definition)) { newNodes = [ ...newNodes, { id: nodeID, - type: "connectorNode", + type: "generalNode", sourcePosition: Position.Left, targetPosition: Position.Right, data: { - id: nodeID, - connector_component: { - definition_name: definition.name, - definition, - input: {}, - task: "", - condition: null, - connection: {}, - }, + type: definition.id, + definition, + input: {}, + task: "", + condition: null, + connection: {}, note: null, }, position: newNodeXY, @@ -163,19 +159,17 @@ export function useConstructNodeFromDefinition({ ...newNodes, { id: nodeID, - type: "operatorNode", + type: "generalNode", sourcePosition: Position.Left, targetPosition: Position.Right, data: { - id: nodeID, - operator_component: { - definition_name: definition.name, - definition: definition as OperatorDefinition, - input: {}, - task: "", - condition: null, - }, + type: definition.id, + definition: definition, + input: {}, + task: "", + condition: null, note: null, + connection: {}, }, position: newNodeXY, zIndex: 20, diff --git a/packages/toolkit/src/view/pipeline-builder/lib/hooks/usePipelineBuilderGraph.tsx b/packages/toolkit/src/view/pipeline-builder/lib/hooks/usePipelineBuilderGraph.tsx index ce16712d4..2a0de6e58 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/hooks/usePipelineBuilderGraph.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/hooks/usePipelineBuilderGraph.tsx @@ -95,13 +95,14 @@ export function usePipelineBuilderGraph() { if ( checkIsValidPosition({ - components: pipeline.data.recipe.components, + component: pipeline.data.recipe.component ?? null, metadata: pipeline.data.metadata, }) ) { const nodes = createNodesFromPipelineRecipe(pipeline.data.recipe, { metadata: pipeline.data.metadata, }); + const edges = composeEdgesFromNodes(nodes); updateNodes(() => nodes); diff --git a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useRenamePipeline.tsx b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useRenamePipeline.tsx index 206405dcc..a6348ad8e 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useRenamePipeline.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useRenamePipeline.tsx @@ -14,8 +14,8 @@ import { useShallow, useUpdateUserPipeline, } from "../../../../lib"; -import { constructPipelineRecipeFromNodes } from "../constructPipelineRecipeFromNodes"; -import { composePipelineMetadataFromNodes } from "../composePipelineMetadataFromNodes"; +import { composePipelineRecipeFromNodes } from "../composePipelineRecipeFromNodes"; +import { composePipelineMetadataMapFromNodes } from "../composePipelineMetadataMapFromNodes"; import { useToast } from "@instill-ai/design-system"; import { isAxiosError } from "axios"; import { useRouter } from "next/navigation"; @@ -67,8 +67,8 @@ export function useRenamePipeline() { if (pipelineIsNew) { const payload: CreateUserPipelinePayload = { id: newId, - recipe: constructPipelineRecipeFromNodes(nodes), - metadata: composePipelineMetadataFromNodes(nodes), + recipe: composePipelineRecipeFromNodes(nodes), + metadata: composePipelineMetadataMapFromNodes(nodes), }; try { @@ -124,8 +124,8 @@ export function useRenamePipeline() { if (pipelineRecipeIsDirty) { const payload: UpdateUserPipelinePayload = { name: entity.data.pipelineName, - recipe: constructPipelineRecipeFromNodes(nodes), - metadata: composePipelineMetadataFromNodes(nodes), + recipe: composePipelineRecipeFromNodes(nodes), + metadata: composePipelineMetadataMapFromNodes(nodes), }; try { diff --git a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useSavePipeline.tsx b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useSavePipeline.tsx index 65d0127df..31f17e3ec 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useSavePipeline.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useSavePipeline.tsx @@ -14,8 +14,8 @@ import { } from "../../../../lib"; import { composeEdgesFromNodes, - composePipelineMetadataFromNodes, - constructPipelineRecipeFromNodes, + composePipelineMetadataMapFromNodes, + composePipelineRecipeFromNodes, } from ".."; import { useToast } from "@instill-ai/design-system"; import { isAxiosError } from "axios"; @@ -98,8 +98,8 @@ export function useSavePipeline(props: UseSavePipelineProps = {}) { if (!pipelineIsNew && pipelineRecipeIsDirty) { const payload: UpdateUserPipelinePayload = { name: entity.data.pipelineName, - recipe: constructPipelineRecipeFromNodes(targetNodes), - metadata: composePipelineMetadataFromNodes(targetNodes), + recipe: composePipelineRecipeFromNodes(targetNodes), + metadata: composePipelineMetadataMapFromNodes(targetNodes), }; try { @@ -116,6 +116,7 @@ export function useSavePipeline(props: UseSavePipelineProps = {}) { const newNodes = createNodesFromPipelineRecipe(newPipeline.recipe, { metadata: newPipeline.metadata, }); + const newEdges = composeEdgesFromNodes(newNodes); if (isEditingIterator) { @@ -160,8 +161,8 @@ export function useSavePipeline(props: UseSavePipelineProps = {}) { const payload: CreateUserPipelinePayload = { id: pipelineId, - recipe: constructPipelineRecipeFromNodes(targetNodes), - metadata: composePipelineMetadataFromNodes(targetNodes), + recipe: composePipelineRecipeFromNodes(targetNodes), + metadata: composePipelineMetadataMapFromNodes(targetNodes), }; try { diff --git a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useUpdaterOnNode.tsx b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useUpdaterOnNode.tsx index 37930384d..a2b5d8c57 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useUpdaterOnNode.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useUpdaterOnNode.tsx @@ -8,15 +8,13 @@ import { useInstillStore, } from "../../../../lib"; import { useShallow } from "zustand/react/shallow"; -import { composeEdgesFromNodes, isConnectorNode, isOperatorNode } from ".."; -import { ConnectorNodeData, NodeData, OperatorNodeData } from "../../type"; -import { - isConnectorComponent, - isOperatorComponent, -} from "../checkComponentType"; +import { composeEdgesFromNodes, isGeneralNode } from ".."; +import { GeneralNodeData, NodeData } from "../../type"; + import debounce from "lodash.debounce"; import isEqual from "lodash.isequal"; import { Node } from "reactflow"; +import { isPipelineGeneralComponent } from "../checkComponentType"; const selector = (store: InstillStore) => ({ nodes: store.nodes, @@ -30,11 +28,13 @@ const selector = (store: InstillStore) => ({ }); export function useUpdaterOnNode({ + nodeID, currentNodeData, form, ValidatorSchema, }: { - currentNodeData: OperatorNodeData | ConnectorNodeData; + nodeID: string; + currentNodeData: GeneralNodeData; form: GeneralUseFormReturn; ValidatorSchema: ZodAnyValidatorSchema; }) { @@ -53,41 +53,24 @@ export function useUpdaterOnNode({ const debounceUpdater = React.useCallback( debounce( ({ - nodeID, + id, updateData, nodes, }: { - nodeID: string; + id: string; updateData: GeneralRecord; nodes: Node[]; }) => { const newNodes = nodes.map((node) => { - if (isConnectorNode(node) && node.id === nodeID) { - return { - ...node, - data: { - ...node.data, - connector_component: { - ...node.data.connector_component, - task: updateData.task, - condition: updateData.condition, - input: updateData.input, - connection: updateData.connection, - }, - }, - }; - } - - if (isOperatorNode(node) && node.id === nodeID) { + if (isGeneralNode(node) && node.id === id) { return { ...node, data: { ...node.data, - operator_component: { - ...node.data.operator_component, - input: updateData.input, - task: updateData.task, - }, + task: updateData.task, + condition: updateData.condition, + input: updateData.input, + connection: updateData.connection, }, }; } @@ -117,10 +100,8 @@ export function useUpdaterOnNode({ const parsed = ValidatorSchema.safeParse(values); if ( - (isConnectorComponent(currentNodeData) && - values.task !== currentNodeData.connector_component.task) || - (isOperatorComponent(currentNodeData) && - values.task !== currentNodeData.operator_component.task) + isPipelineGeneralComponent(currentNodeData) && + values.task !== currentNodeData.task ) { updateCurrentAdvancedConfigurationNodeID(() => null); } @@ -141,7 +122,7 @@ export function useUpdaterOnNode({ debounceUpdater({ updateData: parsed.data, nodes, - nodeID: currentNodeData.id, + id: nodeID, }); })(); }); @@ -159,5 +140,6 @@ export function useUpdaterOnNode({ pipelineIsReadOnly, debounceUpdater, form, + nodeID, ]); } diff --git a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useUpdaterOnRightPanel.tsx b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useUpdaterOnRightPanel.tsx index a064e8611..b76369d6a 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/hooks/useUpdaterOnRightPanel.tsx +++ b/packages/toolkit/src/view/pipeline-builder/lib/hooks/useUpdaterOnRightPanel.tsx @@ -8,13 +8,8 @@ import { useInstillStore, } from "../../../../lib"; import { useShallow } from "zustand/react/shallow"; -import { - composeEdgesFromNodes, - isConnectorNode, - isIteratorNode, - isOperatorNode, -} from ".."; -import { ConnectorNodeData, NodeData, OperatorNodeData } from "../../type"; +import { composeEdgesFromNodes, isIteratorNode } from ".."; +import { GeneralNodeData, NodeData } from "../../type"; import { Node } from "reactflow"; import debounce from "lodash.debounce"; @@ -29,13 +24,15 @@ const selector = (store: InstillStore) => ({ }); export function useUpdaterOnRightPanel({ + nodeID, form, ValidatorSchema, currentNodeData, }: { + nodeID: string; form: GeneralUseFormReturn; ValidatorSchema: ZodAnyValidatorSchema; - currentNodeData: ConnectorNodeData | OperatorNodeData; + currentNodeData: GeneralNodeData; }) { const { nodes, @@ -55,42 +52,24 @@ export function useUpdaterOnRightPanel({ const debounceUpdater = React.useCallback( debounce( ({ - nodeID, + id, updateData, nodes, }: { - nodeID: string; + id: string; updateData: GeneralRecord; nodes: Node[]; }) => { const newNodes: Node[] = nodes.map((node) => { - if (isConnectorNode(node) && node.id === nodeID) { - return { - ...node, - data: { - ...node.data, - connector_component: { - ...node.data.connector_component, - task: updateData.task, - condition: updateData.condition, - input: updateData.input, - connection: updateData.connection, - }, - }, - }; - } - - if (isOperatorNode(node) && node.id === nodeID) { + if (node.id === id) { return { ...node, data: { ...node.data, - operator_component: { - ...node.data.operator_component, - task: updateData.task, - condition: updateData.condition, - input: updateData.input, - }, + task: updateData.task, + condition: updateData.condition, + input: updateData.input, + connection: updateData.connection, }, }; } @@ -130,7 +109,7 @@ export function useUpdaterOnRightPanel({ form.handleSubmit(() => { debounceUpdater({ updateData: parsed.data, - nodeID: currentNodeData.id, + id: nodeID, nodes, }); })(); @@ -148,5 +127,6 @@ export function useUpdaterOnRightPanel({ debounceUpdater, nodes, form, + nodeID, ]); } diff --git a/packages/toolkit/src/view/pipeline-builder/lib/index.ts b/packages/toolkit/src/view/pipeline-builder/lib/index.ts index af8265e32..c1bd1ca8a 100644 --- a/packages/toolkit/src/view/pipeline-builder/lib/index.ts +++ b/packages/toolkit/src/view/pipeline-builder/lib/index.ts @@ -1,16 +1,17 @@ export * from "./checkIsValidPosition"; -export * from "./composePipelineMetadataFromNodes"; +export * from "./checkNodeType"; +export * from "./composePipelineMetadataMapFromNodes"; export * from "./composeEdgesFromNodes"; -export * from "./constructPipelineRecipeFromNodes"; +export * from "./composePipelineRecipeFromNodes"; export * from "./createGraphLayout"; export * from "./createNodesFromPipelineComponents"; export * from "./extractPipelineComponentReferenceFromString"; export * from "./extractReferencesFromConfiguration"; export * from "./getReferencesFromString"; export * from "./generateUniqueIndex"; -export * from "./getAllComponentID"; -export * from "./getConnectorInputOutputSchema"; -export * from "./getConnectorOperatorComponentConfiguration"; +export * from "./getAllNodeID"; +export * from "./getGeneralComponentInOutputSchema"; +export * from "./getGeneralComponentConfiguration"; export * from "./getPropertiesFromOpenAPISchema"; export * from "./readFileToBinary"; export * from "./recursive-helpers/recursiveParseNumberToString"; @@ -19,4 +20,3 @@ export * from "./transformConnectorDefinitionIDToComponentIDPrefix"; export * from "./recursive-helpers"; export * from "./hooks"; -export * from "./checkNodeType"; diff --git a/packages/toolkit/src/view/pipeline-builder/lib/isTriggerByRequest.ts b/packages/toolkit/src/view/pipeline-builder/lib/isTriggerByRequest.ts deleted file mode 100644 index 7fffc3271..000000000 --- a/packages/toolkit/src/view/pipeline-builder/lib/isTriggerByRequest.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { PipelineTrigger, TriggerByRequest } from "../../../lib"; - -export function isTriggerByRequest( - trigger: PipelineTrigger -): trigger is TriggerByRequest { - return "trigger_by_request" in trigger; -} diff --git a/packages/toolkit/src/view/pipeline-builder/type.ts b/packages/toolkit/src/view/pipeline-builder/type.ts index 4f5890fc6..6b4b80812 100644 --- a/packages/toolkit/src/view/pipeline-builder/type.ts +++ b/packages/toolkit/src/view/pipeline-builder/type.ts @@ -2,46 +2,38 @@ import { Nullable, - PipelineConnectorComponent, PipelineRecipe, - PipelineOperatorComponent, PipelineIteratorComponent, GeneralRecord, - PipelineTriggerRequestFields, - PipelineTriggerResponseFields, + PipelineVariableFieldMap, + PipelineOutputFieldMap, + PipelineGeneralComponent, } from "../../lib"; -export type ConnectorNodeData = { - note: Nullable; -} & PipelineConnectorComponent; - export type TriggerNodeData = { - id: "trigger"; note: Nullable; metadata?: GeneralRecord; - fields: PipelineTriggerRequestFields; + fields: PipelineVariableFieldMap; }; export type ResponseNodeData = { - id: "response"; note: Nullable; metadata?: GeneralRecord; - fields: PipelineTriggerResponseFields; + fields: PipelineOutputFieldMap; }; -export type OperatorNodeData = { +export type GeneralNodeData = { note: Nullable; -} & PipelineOperatorComponent; +} & PipelineGeneralComponent; export type IteratorNodeData = { note: Nullable; } & PipelineIteratorComponent; export type NodeData = - | ConnectorNodeData | TriggerNodeData | ResponseNodeData - | OperatorNodeData + | GeneralNodeData | IteratorNodeData; export type PipelineComponentReference = @@ -80,11 +72,15 @@ export type PipelineTemplate = { export type PipelineTemplatesByCategory = Record; export type PipelineMetadata = { - components: PipelineComponentMetadata[]; + component: PipelineComponentMetadataMap; }; +export type PipelineComponentMetadataMap = Record< + string, + PipelineComponentMetadata +>; + export type PipelineComponentMetadata = { - id: string; x: number; y: number; note: Nullable; diff --git a/packages/toolkit/src/view/pipeline/view-pipeline/InOutPut.tsx b/packages/toolkit/src/view/pipeline/view-pipeline/InOutPut.tsx index 15105bbc1..66161957a 100644 --- a/packages/toolkit/src/view/pipeline/view-pipeline/InOutPut.tsx +++ b/packages/toolkit/src/view/pipeline/view-pipeline/InOutPut.tsx @@ -22,7 +22,6 @@ import { Button, Form, useToast } from "@instill-ai/design-system"; import { recursiveHelpers, useSortedReleases } from "../../pipeline-builder"; import { ComponentOutputs } from "../../pipeline-builder/components/ComponentOutputs"; import { RunButton } from "./RunButton"; -import { isTriggerByRequest } from "../../pipeline-builder/lib/isTriggerByRequest"; const selector = (store: InstillStore) => ({ accessToken: store.accessToken, @@ -62,15 +61,10 @@ export const InOutPut = ({ currentVersion }: InOutPutProps) => { accessToken, }); - const triggerFields = React.useMemo(() => { - if ( - pipeline.isSuccess && - isTriggerByRequest(pipeline.data.recipe.trigger) - ) { + const variables = React.useMemo(() => { + if (pipeline.isSuccess) { if (!currentVersion || releases.length === 0) { - return ( - pipeline.data.recipe.trigger.trigger_by_request.request_fields ?? null - ); + return pipeline.data.recipe.variable ?? null; } const pipelineVersion = releases.find( @@ -78,30 +72,18 @@ export const InOutPut = ({ currentVersion }: InOutPutProps) => { release.id === currentVersion || release.alias === currentVersion ); - if ( - pipelineVersion && - isTriggerByRequest(pipelineVersion.recipe.trigger) - ) { - return ( - pipelineVersion?.recipe.trigger.trigger_by_request.request_fields ?? - null - ); + if (pipelineVersion) { + return pipelineVersion?.recipe.variable ?? null; } } return null; }, [releases, currentVersion, pipeline.isSuccess, pipeline.data]); - const responseFields = React.useMemo(() => { - if ( - pipeline.isSuccess && - isTriggerByRequest(pipeline.data.recipe.trigger) - ) { + const outputs = React.useMemo(() => { + if (pipeline.isSuccess) { if (!currentVersion || releases.length === 0) { - return ( - pipeline.data.recipe.trigger.trigger_by_request.response_fields ?? - null - ); + return pipeline.data.recipe.output ?? null; } const pipelineVersion = releases.find( @@ -109,14 +91,8 @@ export const InOutPut = ({ currentVersion }: InOutPutProps) => { release.id === currentVersion || release.alias === currentVersion ); - if ( - pipelineVersion && - isTriggerByRequest(pipelineVersion.recipe.trigger) - ) { - return ( - pipelineVersion?.recipe.trigger.trigger_by_request.response_fields ?? - null - ); + if (pipelineVersion) { + return pipelineVersion?.recipe.output ?? null; } } @@ -125,7 +101,7 @@ export const InOutPut = ({ currentVersion }: InOutPutProps) => { const { fieldItems, form, Schema } = usePipelineTriggerRequestForm({ mode: "demo", - fields: triggerFields, + fields: variables, keyPrefix: "pipeline-details-page-trigger-pipeline-form", disabledFields: false, disabledFieldControls: true, @@ -146,9 +122,9 @@ export const InOutPut = ({ currentVersion }: InOutPutProps) => { const semiStructuredObjectKeys: string[] = []; - if (triggerFields) { - Object.entries(triggerFields).forEach(([key, value]) => { - if (value.instill_format === "semi-structured/json") { + if (variables) { + Object.entries(variables).forEach(([key, value]) => { + if (value.instillFormat === "semi-structured/json") { semiStructuredObjectKeys.push(key); } }); @@ -200,25 +176,24 @@ export const InOutPut = ({ currentVersion }: InOutPutProps) => { } const inputIsNotDefined = React.useMemo(() => { - if (!triggerFields) return false; + if (!variables) return false; - if (triggerFields && Object.keys(triggerFields).length > 0) { + if (variables && Object.keys(variables).length > 0) { return false; } return true; - }, [triggerFields]); + }, [variables]); const outputIsNotDefined = React.useMemo(() => { - if (!responseFields) return true; + if (!outputs) return true; - if (responseFields && Object.keys(responseFields).length > 0) { + if (outputs && Object.keys(outputs).length > 0) { return false; } return true; - }, [responseFields]); - + }, [outputs]); return (
diff --git a/packages/toolkit/src/view/pipeline/view-pipelines/CreatePipelineDialog.tsx b/packages/toolkit/src/view/pipeline/view-pipelines/CreatePipelineDialog.tsx index b74783559..5cbfc9771 100644 --- a/packages/toolkit/src/view/pipeline/view-pipelines/CreatePipelineDialog.tsx +++ b/packages/toolkit/src/view/pipeline/view-pipelines/CreatePipelineDialog.tsx @@ -163,27 +163,21 @@ export const CreatePipelineDialog = ({ className }: { className?: string }) => { description: data.description ?? undefined, recipe: { version: "v1beta", - trigger: { - trigger_by_request: { - request_fields: {}, - response_fields: {}, - }, - }, - components: [], + variable: undefined, + output: undefined, + component: undefined, }, metadata: { - nodes: [ - { - id: "trigger", + component: { + trigger: { x: 0, y: 0, }, - { - id: "response", - x: 350, + response: { + x: 0, y: 0, }, - ], + }, }, sharing, };