diff --git a/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx b/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx new file mode 100644 index 0000000000..e987cecdc9 --- /dev/null +++ b/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx @@ -0,0 +1,16 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { InputVar } from '../../../../types' + +export type Props = { + inputs: InputVar[] +} + +const Form: FC = () => { + return ( +
+
+ ) +} +export default React.memo(Form) diff --git a/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx b/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx new file mode 100644 index 0000000000..5c52789a65 --- /dev/null +++ b/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx @@ -0,0 +1,76 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { useTranslation } from 'react-i18next' +import type { Props } from './form' +import Form from './form' +import Button from '@/app/components/base/button' +import { StopCircle } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices' +import { Loading02, XClose } from '@/app/components/base/icons/src/vender/line/general' + +const i18nPrefix = 'workflow.singleRun' + +type BeforeRunFormProps = Props & { + nodeName: string + onHide: () => void + onRun: () => void + onStop: () => void + runningStatus: string // todo: wait for enum + result?: JSX.Element +} +const BeforeRunForm: FC = ({ + nodeName, + onHide, + onRun, + onStop, + runningStatus, + result, + ...formProps +}) => { + const { t } = useTranslation() + + const isFinished = runningStatus === 'finished' + const isRunning = runningStatus === 'running' + return ( +
+
+
+
+ {t(`${i18nPrefix}.testRun`)} {nodeName} +
+
+ +
+
+ +
+
+
+ +
+ {isRunning && ( +
+ +
+ )} + +
+ + {isFinished && ( +
+ {result} +
+ )} +
+
+ ) +} +export default React.memo(BeforeRunForm) diff --git a/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts new file mode 100644 index 0000000000..5526a69428 --- /dev/null +++ b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts @@ -0,0 +1,52 @@ +import { useState } from 'react' +import { useWorkflow } from '@/app/components/workflow/hooks' +import type { CommonNodeType, InputVar, Variable } from '@/app/components/workflow/types' +import { InputVarType } from '@/app/components/workflow/types' + +type Params = { + id: string + data: CommonNodeType +} + +const useOneStepRun = ({ id, data }: Params) => { + const { handleNodeDataUpdate } = useWorkflow() + const isShowSingleRun = data._isSingleRun + const hideSingleRun = () => { + handleNodeDataUpdate({ + id, + data: { + ...data, + _isSingleRun: false, + }, + }) + } + + const [runningStatus, setRunningStatus] = useState('un started') + + const toVarInputs = (variables: Variable[]): InputVar[] => { + if (!variables) + return [] + + const varInputs = variables.map((item) => { + return { + label: item.variable, + variable: item.variable, + type: InputVarType.textInput, // TODO: dynamic get var type + required: true, // TODO + options: [], // TODO + } + }) + + return varInputs + } + + return { + isShowSingleRun, + hideSingleRun, + toVarInputs, + runningStatus, + setRunningStatus, + } +} + +export default useOneStepRun diff --git a/web/app/components/workflow/nodes/llm/panel.tsx b/web/app/components/workflow/nodes/llm/panel.tsx index fe9e06e050..6eb9669941 100644 --- a/web/app/components/workflow/nodes/llm/panel.tsx +++ b/web/app/components/workflow/nodes/llm/panel.tsx @@ -15,6 +15,7 @@ import ModelParameterModal from '@/app/components/header/account-setting/model-p import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars' import { Resolution } from '@/types/app' import type { NodePanelProps } from '@/app/components/workflow/types' +import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' const i18nPrefix = 'workflow.nodes.llm' @@ -38,6 +39,12 @@ const Panel: FC> = ({ handlePromptChange, handleMemoryChange, handleVisionResolutionChange, + isShowSingleRun, + hideSingleRun, + runningStatus, + handleRun, + handleStop, + varInputs, } = useConfig(id, data) const isChatApp = true // TODO: get from app context @@ -148,6 +155,17 @@ const Panel: FC> = ({ + {isShowSingleRun && ( + + )} + ) } diff --git a/web/app/components/workflow/nodes/llm/use-config.ts b/web/app/components/workflow/nodes/llm/use-config.ts index 2c15c4d5b4..75c7ac9b54 100644 --- a/web/app/components/workflow/nodes/llm/use-config.ts +++ b/web/app/components/workflow/nodes/llm/use-config.ts @@ -7,6 +7,7 @@ import { Resolution } from '@/types/app' import { useTextGenerationCurrentProviderAndModelAndModelList } from '@/app/components/header/account-setting/model-provider-page/hooks' import { ModelFeatureEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud' +import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run' import type { PromptItem } from '@/models/debug' const useConfig = (id: string, payload: LLMNodeType) => { @@ -87,6 +88,26 @@ const useConfig = (id: string, payload: LLMNodeType) => { setInputs(newInputs) }, [inputs, setInputs]) + // single run + const { + isShowSingleRun, + hideSingleRun, + toVarInputs, + runningStatus, + setRunningStatus, + } = useOneStepRun({ + id, + data: inputs, + }) + const varInputs = toVarInputs(inputs.variables) + const handleRun = () => { + setRunningStatus('running') + } + + const handleStop = () => { + setRunningStatus('not started') + } + return { inputs, isChatModel, @@ -100,6 +121,12 @@ const useConfig = (id: string, payload: LLMNodeType) => { handlePromptChange, handleMemoryChange, handleVisionResolutionChange, + isShowSingleRun, + hideSingleRun, + varInputs, + runningStatus, + handleRun, + handleStop, } } diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index d899e2a516..ea853070dd 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -59,6 +59,11 @@ export type Variable = { value_selector: ValueSelector } +export type VariableWithValue = { + key: string + value: string +} + export enum InputVarType { textInput = 'text-input', paragraph = 'paragraph', diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index 23d1e00e59..bdfa99d593 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -22,6 +22,11 @@ const translation = { latestPublished: 'Latest Published', restore: 'Restore', }, + singleRun: { + testRun: 'Test Run ', + startRun: 'Start Run', + running: 'Running', + }, tabs: { 'searchBlock': 'Search block', 'blocks': 'Blocks', diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts index eacecf5dd7..ae920e7ff1 100644 --- a/web/i18n/zh-Hans/workflow.ts +++ b/web/i18n/zh-Hans/workflow.ts @@ -22,6 +22,11 @@ const translation = { latestPublished: '最新发布', restore: '恢复', }, + singleRun: { + testRun: '测试运行 ', + startRun: '开始运行', + running: '运行中', + }, tabs: { 'searchBlock': '搜索节点', 'blocks': '节点',