diff --git a/web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/use-last-run.ts b/web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/use-last-run.ts index 4199266282..8f4f8bf5a2 100644 --- a/web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/use-last-run.ts +++ b/web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/use-last-run.ts @@ -15,6 +15,7 @@ import useHttpRequestSingleRunFormParams from '@/app/components/workflow/nodes/h import useIterationSingleRunFormParams from '@/app/components/workflow/nodes/iteration/use-single-run-form-params' import useDocExtractorSingleRunFormParams from '@/app/components/workflow/nodes/document-extractor/use-single-run-form-params' import useLoopSingleRunFormParams from '@/app/components/workflow/nodes/loop/use-single-run-form-params' +import useIfElseSingleRunFormParams from '@/app/components/workflow/nodes/if-else/use-single-run-form-params' import { BlockEnum } from '@/app/components/workflow/types' import { useNodesSyncDraft, @@ -34,7 +35,7 @@ const singleRunFormParamsHooks: Record = { [BlockEnum.DocExtractor]: useDocExtractorSingleRunFormParams, [BlockEnum.Loop]: useLoopSingleRunFormParams, [BlockEnum.Start]: useStartSingleRunFormParams, - [BlockEnum.IfElse]: undefined, + [BlockEnum.IfElse]: useIfElseSingleRunFormParams, [BlockEnum.VariableAggregator]: undefined, [BlockEnum.End]: undefined, [BlockEnum.Answer]: undefined, @@ -68,6 +69,7 @@ const useLastRun = ({ handleRun: doCallRunApi, getInputVars, toVarInputs, + varSelectorsToVarInputs, runInputData, runInputDataRef, setRunInputData, @@ -82,6 +84,7 @@ const useLastRun = ({ getInputVars, setRunInputData, toVarInputs, + varSelectorsToVarInputs, }) const callRunApi = async (data: Record) => { 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 index 8579a5f034..10acf2c5b7 100644 --- 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 @@ -521,6 +521,24 @@ const useOneStepRun = ({ return varInputs } + const varSelectorsToVarInputs = (valueSelectors: ValueSelector[]): InputVar[] => { + return valueSelectors.map((item) => { + const varInfo = getNodeInfoById(availableNodesIncludeParent, item[0])?.data + return { + type: InputVarType.textInput, + required: true, + label: { + nodeType: varInfo?.type, + nodeName: varInfo?.title || availableNodesIncludeParent[0]?.data.title, // default start node title + variable: isSystemVar(item) ? item.join('.') : item[item.length - 1], + isChatVar: isConversationVar(item), + }, + variable: isSystemVar(item) ? `#${item.join('.')}#` : `${item.join('.')}`, + value_selector: item, + } + }) + } + const getInputVars = (textList: string[]) => { const valueSelectors: ValueSelector[] = [] textList.forEach((text) => { @@ -551,6 +569,7 @@ const useOneStepRun = ({ hideSingleRun, showSingleRun, toVarInputs, + varSelectorsToVarInputs, getInputVars, runningStatus, isCompleted, diff --git a/web/app/components/workflow/nodes/if-else/use-single-run-form-params.ts b/web/app/components/workflow/nodes/if-else/use-single-run-form-params.ts new file mode 100644 index 0000000000..89df801c8b --- /dev/null +++ b/web/app/components/workflow/nodes/if-else/use-single-run-form-params.ts @@ -0,0 +1,125 @@ +import type { MutableRefObject } from 'react' +import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types' +import { useCallback } from 'react' +import type { CaseItem, Condition, IfElseNodeType } from './types' + +type Params = { + id: string, + payload: IfElseNodeType, + runInputData: Record + runInputDataRef: MutableRefObject> + getInputVars: (textList: string[]) => InputVar[] + setRunInputData: (data: Record) => void + toVarInputs: (variables: Variable[]) => InputVar[] + varSelectorsToVarInputs: (variables: ValueSelector[]) => InputVar[] +} +const useSingleRunFormParams = ({ + payload, + runInputData, + setRunInputData, + getInputVars, + varSelectorsToVarInputs, +}: Params) => { + const setInputVarValues = useCallback((newPayload: Record) => { + setRunInputData(newPayload) + }, [setRunInputData]) + const inputVarValues = (() => { + const vars: Record = {} + Object.keys(runInputData) + .forEach((key) => { + vars[key] = runInputData[key] + }) + return vars + })() + + const getVarSelectorsFromCase = (caseItem: CaseItem): ValueSelector[] => { + const vars: ValueSelector[] = [] + if (caseItem.conditions && caseItem.conditions.length) { + caseItem.conditions.forEach((condition) => { + // eslint-disable-next-line ts/no-use-before-define + const conditionVars = getVarSelectorsFromCondition(condition) + vars.push(...conditionVars) + }) + } + return vars + } + + const getVarSelectorsFromCondition = (condition: Condition) => { + const vars: ValueSelector[] = [] + if (condition.variable_selector) + vars.push(condition.variable_selector) + + if (condition.sub_variable_condition && condition.sub_variable_condition.conditions?.length) + vars.push(...getVarSelectorsFromCase(condition.sub_variable_condition)) + return vars + } + + const getInputVarsFromCase = (caseItem: CaseItem): InputVar[] => { + const vars: InputVar[] = [] + if (caseItem.conditions && caseItem.conditions.length) { + caseItem.conditions.forEach((condition) => { + // eslint-disable-next-line ts/no-use-before-define + const conditionVars = getInputVarsFromConditionValue(condition) + vars.push(...conditionVars) + }) + } + return vars + } + + const getInputVarsFromConditionValue = (condition: Condition): InputVar[] => { + const vars: InputVar[] = [] + if (condition.value && typeof condition.value === 'string') { + const inputVars = getInputVars([condition.value]) + vars.push(...inputVars) + } + + if (condition.sub_variable_condition && condition.sub_variable_condition.conditions?.length) + vars.push(...getInputVarsFromCase(condition.sub_variable_condition)) + + return vars + } + + const forms = (() => { + const allInputs: ValueSelector[] = [] + const inputVarsFromValue: InputVar[] = [] + if (payload.cases && payload.cases.length) { + payload.cases.forEach((caseItem) => { + const caseVars = getVarSelectorsFromCase(caseItem) + allInputs.push(...caseVars) + inputVarsFromValue.push(...getInputVarsFromCase(caseItem)) + }) + } + + if (payload.conditions && payload.conditions.length) { + payload.conditions.forEach((condition) => { + const conditionVars = getVarSelectorsFromCondition(condition) + allInputs.push(...conditionVars) + inputVarsFromValue.push(...getInputVarsFromConditionValue(condition)) + }) + } + + const varInputs = [...varSelectorsToVarInputs(allInputs), ...inputVarsFromValue] + // remove duplicate inputs + const existVarsKey: Record = {} + const uniqueVarInputs: InputVar[] = [] + varInputs.forEach((input) => { + if (!existVarsKey[input.variable]) { + existVarsKey[input.variable] = true + uniqueVarInputs.push(input) + } + }) + return [ + { + inputs: uniqueVarInputs, + values: inputVarValues, + onChange: setInputVarValues, + }, + ] + })() + + return { + forms, + } +} + +export default useSingleRunFormParams