= ({
if (isShowSingleRun) {
const form = getCustomRunForm({
nodeId: id,
+ flowId: configsMap?.flowId || '',
+ flowType: configsMap?.flowType || FlowType.appFlow,
payload: data,
+ setRunResult,
+ setIsRunAfterSingleRun,
+ isPaused,
+ isRunAfterSingleRun,
onSuccess: handleAfterCustomSingleRun,
onCancel: hideSingleRun,
+ appendNodeInspectVars,
})
return (
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 becef81252..21462de939 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
@@ -174,7 +174,7 @@ const useLastRun =
({
})
const toSubmitData = useCallback((data: Record) => {
- if(!isIterationNode && !isLoopNode)
+ if (!isIterationNode && !isLoopNode)
return data
const allVarObject = singleRunParams?.allVarObject || {}
@@ -183,7 +183,7 @@ const useLastRun = ({
const [varSectorStr, nodeId] = key.split(DELIMITER)
formattedData[`${nodeId}.${allVarObject[key].inSingleRunPassedKey}`] = data[varSectorStr]
})
- if(isIterationNode) {
+ if (isIterationNode) {
const iteratorInputKey = `${id}.input_selector`
formattedData[iteratorInputKey] = data[iteratorInputKey]
}
@@ -203,7 +203,7 @@ const useLastRun = ({
const initShowLastRunTab = useStore(s => s.initShowLastRunTab)
const [tabType, setTabType] = useState(initShowLastRunTab ? TabType.lastRun : TabType.settings)
useEffect(() => {
- if(initShowLastRunTab)
+ if (initShowLastRunTab)
setTabType(TabType.lastRun)
setInitShowLastRunTab(false)
@@ -212,7 +212,7 @@ const useLastRun = ({
const handleRunWithParams = async (data: Record) => {
const { isValid } = checkValid()
- if(!isValid)
+ if (!isValid)
return
setNodeRunning()
setIsRunAfterSingleRun(true)
@@ -236,14 +236,14 @@ const useLastRun = ({
const values: Record = {}
form.inputs.forEach(({ variable, getVarValueFromDependent }) => {
const isGetValueFromDependent = getVarValueFromDependent || !variable.includes('.')
- if(isGetValueFromDependent && !singleRunParams?.getDependentVar)
+ if (isGetValueFromDependent && !singleRunParams?.getDependentVar)
return
const selector = isGetValueFromDependent ? (singleRunParams?.getDependentVar(variable) || []) : variable.slice(1, -1).split('.')
- if(!selector || selector.length === 0)
+ if (!selector || selector.length === 0)
return
const [nodeId, varName] = selector.slice(0, 2)
- if(!isStartNode && nodeId === id) { // inner vars like loop vars
+ if (!isStartNode && nodeId === id) { // inner vars like loop vars
values[variable] = true
return
}
@@ -257,7 +257,7 @@ const useLastRun = ({
}
const isAllVarsHasValue = (vars?: ValueSelector[]) => {
- if(!vars || vars.length === 0)
+ if (!vars || vars.length === 0)
return true
return vars.every((varItem) => {
const [nodeId, varName] = varItem.slice(0, 2)
@@ -267,7 +267,7 @@ const useLastRun = ({
}
const isSomeVarsHasValue = (vars?: ValueSelector[]) => {
- if(!vars || vars.length === 0)
+ if (!vars || vars.length === 0)
return true
return vars.some((varItem) => {
const [nodeId, varName] = varItem.slice(0, 2)
@@ -294,7 +294,7 @@ const useLastRun = ({
}
const checkAggregatorVarsSet = (vars: ValueSelector[][]) => {
- if(!vars || vars.length === 0)
+ if (!vars || vars.length === 0)
return true
// in each group, at last one set is ok
return vars.every((varItem) => {
@@ -310,9 +310,9 @@ const useLastRun = ({
const handleSingleRun = () => {
const { isValid } = checkValid()
- if(!isValid)
+ if (!isValid)
return
- if(isCustomRunNode) {
+ if (isCustomRunNode) {
showSingleRun()
return
}
@@ -335,6 +335,7 @@ const useLastRun = ({
...oneStepRunRes,
tabType,
isRunAfterSingleRun,
+ setIsRunAfterSingleRun,
setTabType: handleTabClicked,
handleAfterCustomSingleRun,
singleRunParams,
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 1582e8d36d..4970d99c40 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
@@ -663,6 +663,7 @@ const useOneStepRun = ({
runInputDataRef,
setRunInputData: handleSetRunInputData,
runResult,
+ setRunResult: doSetRunResult,
iterationRunResult,
loopRunResult,
setNodeRunning,
diff --git a/web/app/components/workflow/nodes/data-source/before-run-form.tsx b/web/app/components/workflow/nodes/data-source/before-run-form.tsx
index daf451e54c..e34984faa1 100644
--- a/web/app/components/workflow/nodes/data-source/before-run-form.tsx
+++ b/web/app/components/workflow/nodes/data-source/before-run-form.tsx
@@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
-import type { CustomRunFormProps, DataSourceNodeType } from './types'
+import type { CustomRunFormProps } from './types'
import { DatasourceType } from '@/models/pipeline'
import LocalFile from '@/app/components/datasets/documents/create-from-pipeline/data-source/local-file'
import OnlineDocuments from '@/app/components/datasets/documents/create-from-pipeline/data-source/online-documents'
@@ -13,18 +13,24 @@ import Button from '@/app/components/base/button'
import { useTranslation } from 'react-i18next'
import DataSourceProvider from '@/app/components/datasets/documents/create-from-pipeline/data-source/store/provider'
import PanelWrap from '../_base/components/before-run-form/panel-wrap'
+import useBeforeRunForm from './hooks/use-before-run-form'
-const BeforeRunForm: FC = ({
- nodeId,
- payload,
- onSuccess,
- onCancel,
-}) => {
+const BeforeRunForm: FC = (props) => {
+ const {
+ nodeId,
+ payload,
+ onCancel,
+ } = props
const { t } = useTranslation()
- const datasourceType = payload.provider_type
- const datasourceNodeData = payload as DataSourceNodeType
const dataSourceStore = useDataSourceStore()
+ const {
+ isPending,
+ handleRunWithSyncDraft,
+ datasourceType,
+ datasourceNodeData,
+ } = useBeforeRunForm(props)
+
const { clearOnlineDocumentData } = useOnlineDocument()
const { clearWebsiteCrawlData } = useWebsiteCrawl()
const { clearOnlineDriveData } = useOnlineDrive()
@@ -44,10 +50,6 @@ const BeforeRunForm: FC = ({
setCurrentCredentialId(credentialId)
}, [dataSourceStore])
- const handleRun = useCallback(() => {
- onSuccess()
- }, [onSuccess])
-
return (
= ({
{datasourceType === DatasourceType.localFile && (
)}
{datasourceType === DatasourceType.onlineDocument && (
)}
@@ -71,6 +74,7 @@ const BeforeRunForm: FC = ({
)}
@@ -78,12 +82,22 @@ const BeforeRunForm: FC = ({
)}
-
-
+
+
diff --git a/web/app/components/workflow/nodes/data-source/hooks/use-before-run-form.ts b/web/app/components/workflow/nodes/data-source/hooks/use-before-run-form.ts
new file mode 100644
index 0000000000..36540d6217
--- /dev/null
+++ b/web/app/components/workflow/nodes/data-source/hooks/use-before-run-form.ts
@@ -0,0 +1,180 @@
+import { useStoreApi } from 'reactflow'
+import type { CustomRunFormProps, DataSourceNodeType } from '../types'
+import { useEffect, useRef } from 'react'
+import { useNodeDataUpdate, useNodesSyncDraft } from '../../../hooks'
+import { NodeRunningStatus } from '../../../types'
+import { useInvalidLastRun } from '@/service/use-workflow'
+import type { NodeRunResult } from '@/types/workflow'
+import { fetchNodeInspectVars } from '@/service/workflow'
+import { FlowType } from '@/types/common'
+import { useDatasourceSingleRun } from '@/service/use-pipeline'
+import { useDataSourceStore } from '@/app/components/datasets/documents/create-from-pipeline/data-source/store'
+import { DatasourceType } from '@/models/pipeline'
+import { TransferMethod } from '@/types/app'
+
+const useBeforeRunForm = ({
+ nodeId,
+ flowId,
+ flowType,
+ payload,
+ setRunResult,
+ isPaused,
+ isRunAfterSingleRun,
+ setIsRunAfterSingleRun,
+ onSuccess,
+ appendNodeInspectVars,
+}: CustomRunFormProps) => {
+ const store = useStoreApi()
+ const dataSourceStore = useDataSourceStore()
+ const isPausedRef = useRef(isPaused)
+ const { handleNodeDataUpdate } = useNodeDataUpdate()
+
+ const datasourceType = payload.provider_type as DatasourceType
+ const datasourceNodeData = payload as DataSourceNodeType
+
+ useEffect(() => {
+ isPausedRef.current = isPaused
+ }, [isPaused])
+
+ const runningStatus = payload._singleRunningStatus || NodeRunningStatus.NotStart
+
+ const setNodeRunning = () => {
+ handleNodeDataUpdate({
+ id: nodeId,
+ data: {
+ ...payload,
+ _singleRunningStatus: NodeRunningStatus.Running,
+ },
+ })
+ }
+
+ const invalidLastRun = useInvalidLastRun(flowType, flowId, nodeId)
+
+ const updateRunResult = async (data: NodeRunResult) => {
+ const isPaused = isPausedRef.current
+
+ // The backend don't support pause the single run, so the frontend handle the pause state.
+ if (isPaused)
+ return
+
+ const canRunLastRun = !isRunAfterSingleRun || runningStatus === NodeRunningStatus.Succeeded
+ if (!canRunLastRun) {
+ setRunResult(data)
+ return
+ }
+
+ // run fail may also update the inspect vars when the node set the error default output.
+ const vars = await fetchNodeInspectVars(FlowType.ragPipeline, flowId, nodeId)
+ const { getNodes } = store.getState()
+ const nodes = getNodes()
+ appendNodeInspectVars(nodeId, vars, nodes)
+ if (data?.status === NodeRunningStatus.Succeeded)
+ onSuccess()
+ }
+
+ const { mutateAsync: handleDatasourceSingleRun, isPending } = useDatasourceSingleRun()
+
+ const handleRun = () => {
+ let datasourceInfo: Record