From 0e550e45c77e79e5a7e38d93e8a422fcaef17858 Mon Sep 17 00:00:00 2001 From: JzoNg Date: Mon, 16 Jun 2025 11:10:18 +0800 Subject: [PATCH] new mixed input --- .../tool-selector/reasoning-config-form.tsx | 20 +- .../_base/components/form-input-item.tsx | 27 +- .../nodes/tool/components/input-var-list.tsx | 247 ------------------ .../mixed-variable-text-input/index.tsx | 37 ++- .../mixed-variable-text-input/placeholder.tsx | 6 +- web/i18n/en-US/workflow.ts | 2 + web/i18n/zh-Hans/workflow.ts | 2 + 7 files changed, 44 insertions(+), 297 deletions(-) delete mode 100644 web/app/components/workflow/nodes/tool/components/input-var-list.tsx diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/reasoning-config-form.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/reasoning-config-form.tsx index c77ea74c88..130e3ec198 100644 --- a/web/app/components/plugins/plugin-detail-panel/tool-selector/reasoning-config-form.tsx +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/reasoning-config-form.tsx @@ -7,7 +7,7 @@ import { } from '@remixicon/react' import Tooltip from '@/app/components/base/tooltip' import Switch from '@/app/components/base/switch' -import MixedInput from '@/app/components/workflow/nodes/_base/components/input-support-select-var' +import MixedVariableTextInput from '@/app/components/workflow/nodes/tool/components/mixed-variable-text-input' import Input from '@/app/components/base/input' import FormInputTypeSwitch from '@/app/components/workflow/nodes/_base/components/form-input-type-switch' import FormInputBoolean from '@/app/components/workflow/nodes/_base/components/form-input-boolean' @@ -60,18 +60,6 @@ const ReasoningConfigForm: React.FC = ({ return VarKindType.mixed } - const [inputsIsFocus, setInputsIsFocus] = useState>({}) - const handleInputFocus = useCallback((variable: string) => { - return (value: boolean) => { - setInputsIsFocus((prev) => { - return { - ...prev, - [variable]: value, - } - }) - } - }, []) - const handleAutomatic = (key: string, val: any, type: FormTypeEnum) => { onChange({ ...value, @@ -259,15 +247,11 @@ const ReasoningConfigForm: React.FC = ({ )} {isString && ( - )} {isNumber && isConstant && ( diff --git a/web/app/components/workflow/nodes/_base/components/form-input-item.tsx b/web/app/components/workflow/nodes/_base/components/form-input-item.tsx index 0c98620ada..76f5c7c97a 100644 --- a/web/app/components/workflow/nodes/_base/components/form-input-item.tsx +++ b/web/app/components/workflow/nodes/_base/components/form-input-item.tsx @@ -1,7 +1,5 @@ 'use client' import type { FC } from 'react' -import React, { useCallback, useState } from 'react' -import { useTranslation } from 'react-i18next' import type { ToolVarInputs } from '@/app/components/workflow/nodes/tool/types' import type { CredentialFormSchema } from '@/app/components/header/account-setting/model-provider-page/declarations' import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' @@ -11,17 +9,17 @@ import { VarType } from '@/app/components/workflow/types' import type { ValueSelector, Var } from '@/app/components/workflow/types' import FormInputTypeSwitch from './form-input-type-switch' -import MixedInput from '@/app/components/workflow/nodes/_base/components/input-support-select-var' import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list' import Input from '@/app/components/base/input' import { SimpleSelect } from '@/app/components/base/select' +import MixedVariableTextInput from '@/app/components/workflow/nodes/tool/components/mixed-variable-text-input' import FormInputBoolean from './form-input-boolean' import AppSelector from '@/app/components/plugins/plugin-detail-panel/app-selector' import ModelParameterModal from '@/app/components/plugins/plugin-detail-panel/model-selector' import VarReferencePicker from '@/app/components/workflow/nodes/_base/components/variable/var-reference-picker' -import cn from '@/utils/classnames' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' +import cn from '@/utils/classnames' type Props = { readOnly: boolean @@ -40,7 +38,6 @@ const FormInputItem: FC = ({ onChange, inPanel, }) => { - const { t } = useTranslation() const language = useLanguage() const { @@ -178,34 +175,18 @@ const FormInputItem: FC = ({ }) } - const [inputsIsFocus, setInputsIsFocus] = useState>({}) - const handleInputFocus = useCallback((variable: string) => { - return (value: boolean) => { - setInputsIsFocus((prev) => { - return { - ...prev, - [variable]: value, - } - }) - } - }, []) - return (
{showTypeSwitch && ( )} {isString && ( - )} {isNumber && isConstant && ( diff --git a/web/app/components/workflow/nodes/tool/components/input-var-list.tsx b/web/app/components/workflow/nodes/tool/components/input-var-list.tsx deleted file mode 100644 index dc25184f5a..0000000000 --- a/web/app/components/workflow/nodes/tool/components/input-var-list.tsx +++ /dev/null @@ -1,247 +0,0 @@ -'use client' -import type { FC } from 'react' -import React, { useCallback, useState } from 'react' -import produce from 'immer' -import { useTranslation } from 'react-i18next' -import type { ToolVarInputs } from '../types' -import { VarType as VarKindType } from '../types' -import cn from '@/utils/classnames' -import type { ValueSelector, Var } from '@/app/components/workflow/types' -import type { CredentialFormSchema } from '@/app/components/header/account-setting/model-provider-page/declarations' -import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' -import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' -import VarReferencePicker from '@/app/components/workflow/nodes/_base/components/variable/var-reference-picker' -import Input from '@/app/components/workflow/nodes/_base/components/input-support-select-var' -import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list' -import { VarType } from '@/app/components/workflow/types' -import AppSelector from '@/app/components/plugins/plugin-detail-panel/app-selector' -import ModelParameterModal from '@/app/components/plugins/plugin-detail-panel/model-selector' -import { noop } from 'lodash-es' - -type Props = { - readOnly: boolean - nodeId: string - schema: CredentialFormSchema[] - value: ToolVarInputs - onChange: (value: ToolVarInputs) => void - onOpen?: (index: number) => void - isSupportConstantValue?: boolean - filterVar?: (payload: Var, valueSelector: ValueSelector) => boolean -} - -const InputVarList: FC = ({ - readOnly, - nodeId, - schema, - value, - onChange, - onOpen = noop, - isSupportConstantValue, - filterVar, -}) => { - const language = useLanguage() - const { t } = useTranslation() - const { availableVars, availableNodesWithParent } = useAvailableVarList(nodeId, { - onlyLeafNodeVar: false, - filterVar: (varPayload: Var) => { - return [VarType.string, VarType.number, VarType.secret].includes(varPayload.type) - }, - }) - const paramType = (type: string) => { - if (type === FormTypeEnum.textNumber) - return 'Number' - else if (type === FormTypeEnum.file || type === FormTypeEnum.files) - return 'Files' - else if (type === FormTypeEnum.appSelector) - return 'AppSelector' - else if (type === FormTypeEnum.modelSelector) - return 'ModelSelector' - else if (type === FormTypeEnum.toolSelector) - return 'ToolSelector' - else - return 'String' - } - - const handleNotMixedTypeChange = useCallback((variable: string) => { - return (varValue: ValueSelector | string, varKindType: VarKindType) => { - const newValue = produce(value, (draft: ToolVarInputs) => { - const target = draft[variable] - if (target) { - target.type = varKindType - target.value = varValue - } - else { - draft[variable] = { - type: varKindType, - value: varValue, - } - } - }) - onChange(newValue) - } - }, [value, onChange]) - - const handleMixedTypeChange = useCallback((variable: string) => { - return (itemValue: string) => { - const newValue = produce(value, (draft: ToolVarInputs) => { - const target = draft[variable] - if (target) { - target.value = itemValue - } - else { - draft[variable] = { - type: VarKindType.mixed, - value: itemValue, - } - } - }) - onChange(newValue) - } - }, [value, onChange]) - - const handleFileChange = useCallback((variable: string) => { - return (varValue: ValueSelector | string) => { - const newValue = produce(value, (draft: ToolVarInputs) => { - draft[variable] = { - type: VarKindType.variable, - value: varValue, - } - }) - onChange(newValue) - } - }, [value, onChange]) - - const handleAppChange = useCallback((variable: string) => { - return (app: { - app_id: string - inputs: Record - files?: any[] - }) => { - const newValue = produce(value, (draft: ToolVarInputs) => { - draft[variable] = app as any - }) - onChange(newValue) - } - }, [onChange, value]) - const handleModelChange = useCallback((variable: string) => { - return (model: any) => { - const newValue = produce(value, (draft: ToolVarInputs) => { - draft[variable] = { - ...draft[variable], - ...model, - } as any - }) - onChange(newValue) - } - }, [onChange, value]) - - const [inputsIsFocus, setInputsIsFocus] = useState>({}) - const handleInputFocus = useCallback((variable: string) => { - return (value: boolean) => { - setInputsIsFocus((prev) => { - return { - ...prev, - [variable]: value, - } - }) - } - }, []) - const handleOpen = useCallback((index: number) => { - return () => onOpen(index) - }, [onOpen]) - return ( -
- { - schema.map((schema, index) => { - const { - variable, - label, - type, - required, - tooltip, - scope, - } = schema - const varInput = value[variable] - const isNumber = type === FormTypeEnum.textNumber - const isSelect = type === FormTypeEnum.select - const isFile = type === FormTypeEnum.file || type === FormTypeEnum.files - const isAppSelector = type === FormTypeEnum.appSelector - const isModelSelector = type === FormTypeEnum.modelSelector - // const isToolSelector = type === FormTypeEnum.toolSelector - const isString = !isNumber && !isSelect && !isFile && !isAppSelector && !isModelSelector - - return ( -
-
- {label[language] || label.en_US} - {paramType(type)} - {required && Required} -
- {isString && ( - - )} - {(isNumber || isSelect) && ( - - )} - {isFile && ( - varPayload.type === VarType.file || varPayload.type === VarType.arrayFile} - /> - )} - {isAppSelector && ( - - )} - {isModelSelector && ( - - )} - {tooltip &&
{tooltip[language] || tooltip.en_US}
} -
- ) - }) - } -
- ) -} -export default React.memo(InputVarList) diff --git a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/index.tsx b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/index.tsx index 4bb562ba3a..6680c8ebb6 100644 --- a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/index.tsx +++ b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/index.tsx @@ -1,34 +1,57 @@ import { memo, } from 'react' +import { useTranslation } from 'react-i18next' import PromptEditor from '@/app/components/base/prompt-editor' -import cn from '@/utils/classnames' import Placeholder from './placeholder' +import type { + Node, + NodeOutPutVar, +} from '@/app/components/workflow/types' +import { BlockEnum } from '@/app/components/workflow/types' +import cn from '@/utils/classnames' type MixedVariableTextInputProps = { - editable?: boolean + readOnly?: boolean + nodesOutputVars?: NodeOutPutVar[] + availableNodes?: Node[] value?: string onChange?: (text: string) => void } const MixedVariableTextInput = ({ - editable = true, + readOnly = false, + nodesOutputVars, + availableNodes = [], value = '', onChange, }: MixedVariableTextInputProps) => { + const { t } = useTranslation() return ( { + acc[node.id] = { + title: node.data.title, + type: node.data.type, + } + if (node.data.type === BlockEnum.Start) { + acc.sys = { + title: t('workflow.blocks.start'), + type: BlockEnum.Start, + } + } + return acc + }, {} as any), }} placeholder={} onChange={onChange} diff --git a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/placeholder.tsx b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/placeholder.tsx index e84ffbeb28..3337d6ae66 100644 --- a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/placeholder.tsx +++ b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/placeholder.tsx @@ -1,4 +1,5 @@ import { useCallback } from 'react' +import { useTranslation } from 'react-i18next' import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' import { FOCUS_COMMAND } from 'lexical' import { $insertNodes } from 'lexical' @@ -6,6 +7,7 @@ import { CustomTextNode } from '@/app/components/base/prompt-editor/plugins/cust import Badge from '@/app/components/base/badge' const Placeholder = () => { + const { t } = useTranslation() const [editor] = useLexicalComposerContext() const handleInsert = useCallback((text: string) => { @@ -25,7 +27,7 @@ const Placeholder = () => { }} >
- Type or press + {t('workflow.nodes.tool.insertPlaceholder1')}
/
{ handleInsert('/') })} > - insert variable + {t('workflow.nodes.tool.insertPlaceholder2')}