diff --git a/web/app/components/app/configuration/config-var/config-modal/__tests__/type-select.spec.tsx b/web/app/components/app/configuration/config-var/config-modal/__tests__/type-select.spec.tsx index c4f0b5b6d6..1d50350229 100644 --- a/web/app/components/app/configuration/config-var/config-modal/__tests__/type-select.spec.tsx +++ b/web/app/components/app/configuration/config-var/config-modal/__tests__/type-select.spec.tsx @@ -24,7 +24,7 @@ describe('TypeSelector', () => { ) await user.click(screen.getByRole('combobox')) - const numberOption = await screen.findByRole('option', { name: 'Number' }) + const [, numberOption] = await screen.findAllByRole('option') await user.click(numberOption) expect(onSelect).toHaveBeenCalledWith({ value: 'number', name: 'Number' }) @@ -46,10 +46,8 @@ describe('TypeSelector', () => { await user.click(screen.getByRole('combobox')) - const numberOption = await screen.findByRole('option', { name: 'Number' }) + const [, numberOption] = await screen.findAllByRole('option') const popup = numberOption.closest('[data-side]') - if (!popup) - throw new Error('Expected popup container to exist') expect(popup).toHaveClass('w-(--anchor-width)') }) diff --git a/web/app/components/workflow-app/__tests__/utils.spec.ts b/web/app/components/workflow-app/__tests__/utils.spec.ts index 1b47ec9f3c..c8a9fffeec 100644 --- a/web/app/components/workflow-app/__tests__/utils.spec.ts +++ b/web/app/components/workflow-app/__tests__/utils.spec.ts @@ -1,23 +1,11 @@ -import type { Node } from '@/app/components/workflow/types' -import { BlockEnum, SupportUploadFileTypes } from '@/app/components/workflow/types' +import { SupportUploadFileTypes } from '@/app/components/workflow/types' import { TransferMethod } from '@/types/app' import { buildInitialFeatures, buildTriggerStatusMap, coerceReplayUserInputs, - normalizeWorkflowNodesForBackend, - normalizeWorkflowNodesForFrontend, } from '../utils' -type HumanInputTestField = { - type: string - output_variable_name: string -} - -type HumanInputTestNode = Node<{ - inputs: HumanInputTestField[] -}> - describe('workflow-app utils', () => { it('should map trigger statuses to enabled and disabled states', () => { expect(buildTriggerStatusMap([ @@ -50,51 +38,6 @@ describe('workflow-app utils', () => { expect(coerceReplayUserInputs(null)).toBeNull() }) - it('should normalize human-input multi-file types between frontend and backend payloads', () => { - const nodes: HumanInputTestNode[] = [ - { - id: 'node-1', - type: 'custom', - position: { x: 0, y: 0 }, - data: { - title: 'Human Input', - desc: '', - type: BlockEnum.HumanInput, - inputs: [ - { type: 'paragraph', output_variable_name: 'summary' }, - { type: 'file-list', output_variable_name: 'attachments' }, - ], - }, - }, - ] - - const backendNodes = normalizeWorkflowNodesForBackend(nodes) as HumanInputTestNode[] - expect(backendNodes[0]!.data.inputs).toEqual([ - { type: 'paragraph', output_variable_name: 'summary' }, - { type: 'file_list', output_variable_name: 'attachments' }, - ]) - - const frontendPayloadNodes: HumanInputTestNode[] = [ - { - ...nodes[0]!, - data: { - ...nodes[0]!.data, - inputs: [ - { type: 'paragraph', output_variable_name: 'summary' }, - { type: 'file_list', output_variable_name: 'attachments' }, - ], - }, - }, - ] - - const frontendNodes = normalizeWorkflowNodesForFrontend(frontendPayloadNodes) as HumanInputTestNode[] - - expect(frontendNodes[0]!.data.inputs).toEqual([ - { type: 'paragraph', output_variable_name: 'summary' }, - { type: 'file-list', output_variable_name: 'attachments' }, - ]) - }) - it('should build initial features with file-upload and feature fallbacks', () => { const result = buildInitialFeatures({ file_upload: { diff --git a/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts b/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts index 76bceb37bb..0ac528c303 100644 --- a/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts +++ b/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts @@ -14,7 +14,6 @@ import { postWithKeepalive } from '@/service/fetch' import { systemFeaturesQueryOptions } from '@/service/system-features' import { syncWorkflowDraft } from '@/service/workflow' import { useWorkflowRefreshDraft } from '.' -import { normalizeWorkflowNodesForBackend } from '../utils' export const useNodesSyncDraft = () => { const store = useStoreApi() @@ -47,14 +46,14 @@ export const useNodesSyncDraft = () => { return null const features = featuresStore!.getState().features - const producedNodes = normalizeWorkflowNodesForBackend(produce(nodes, (draft) => { + const producedNodes = produce(nodes, (draft) => { draft.forEach((node) => { Object.keys(node.data).forEach((key) => { if (key.startsWith('_')) delete node.data[key] }) }) - })) + }) const producedEdges = produce(edges.filter(edge => !edge.data?._isTemp), (draft) => { draft.forEach((edge) => { Object.keys(edge.data).forEach((key) => { diff --git a/web/app/components/workflow-app/hooks/use-workflow-init.ts b/web/app/components/workflow-app/hooks/use-workflow-init.ts index a4018dccce..00bff2919f 100644 --- a/web/app/components/workflow-app/hooks/use-workflow-init.ts +++ b/web/app/components/workflow-app/hooks/use-workflow-init.ts @@ -20,7 +20,6 @@ import { syncWorkflowDraft, } from '@/service/workflow' import { AppModeEnum } from '@/types/app' -import { normalizeWorkflowNodesForFrontend } from '../utils' import { useWorkflowTemplate } from './use-workflow-template' const hasConnectedUserInput = (nodes: Node[] = [], edges: Edge[] = []): boolean => { @@ -59,13 +58,7 @@ export const useWorkflowInit = () => { const handleGetInitialWorkflowData = useCallback(async () => { try { const res = await fetchWorkflowDraft(`/apps/${appDetail.id}/workflows/draft`) - setData({ - ...res, - graph: { - ...res.graph, - nodes: normalizeWorkflowNodesForFrontend(res.graph.nodes), - }, - }) + setData(res) workflowStore.setState({ envSecrets: (res.environment_variables || []).filter(env => env.value_type === 'secret').reduce((acc, env) => { acc[env.id] = env.value diff --git a/web/app/components/workflow-app/utils.ts b/web/app/components/workflow-app/utils.ts index 64f0b5fc17..df344e333b 100644 --- a/web/app/components/workflow-app/utils.ts +++ b/web/app/components/workflow-app/utils.ts @@ -1,8 +1,7 @@ import type { Features as FeaturesData } from '@/app/components/base/features/types' -import type { Node } from '@/app/components/workflow/types' import type { FileUploadConfigResponse } from '@/models/common' import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' -import { BlockEnum, SupportUploadFileTypes } from '@/app/components/workflow/types' +import { SupportUploadFileTypes } from '@/app/components/workflow/types' import { TransferMethod } from '@/types/app' type TriggerStatusLike = { @@ -34,15 +33,6 @@ type WorkflowFeaturesLike = { sensitive_word_avoidance?: { enabled?: boolean } } -type HumanInputFieldLike = { - type: unknown - [key: string]: unknown -} - -type HumanInputNodeExtra = { - inputs: HumanInputFieldLike[] -} - export const buildTriggerStatusMap = (triggers: TriggerStatusLike[]) => { return triggers.reduce>((acc, trigger) => { acc[trigger.node_id] = trigger.status === 'enabled' ? 'enabled' : 'disabled' @@ -81,49 +71,6 @@ export const coerceReplayUserInputs = (rawInputs: unknown): Record { - if (direction === 'frontend') - return type === 'file_list' ? 'file-list' : type - - return type === 'file-list' ? 'file_list' : type -} - -const isHumanInputNode = (node: Node): node is Node => { - return node.data.type === BlockEnum.HumanInput && Array.isArray((node.data as Partial).inputs) -} - -const normalizeHumanInputNode = ( - node: Node, - direction: 'frontend' | 'backend', -): Node => { - if (!isHumanInputNode(node)) - return node - - const normalizedNode: Node = { - ...node, - data: { - ...node.data, - inputs: node.data.inputs.map(input => ({ - ...input, - type: normalizeHumanInputFieldType(input.type, direction), - })), - }, - } - - return normalizedNode -} - -export const normalizeWorkflowNodesForFrontend = (nodes: Node[]) => { - return nodes.map(node => normalizeHumanInputNode(node, 'frontend')) -} - -export const normalizeWorkflowNodesForBackend = (nodes: Node[]) => { - return nodes.map(node => normalizeHumanInputNode(node, 'backend')) -} - export const buildInitialFeatures = ( featuresSource: WorkflowFeaturesLike | null | undefined, fileUploadConfigResponse: FileUploadConfigResponse | undefined,