dify/web/app/components/workflow/panel/inputs-panel.tsx
Stephen Zhou a84c2d36a3
style: format with vp fmt (#38803)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-12 15:57:46 +00:00

122 lines
4.0 KiB
TypeScript

import type { StartNodeType } from '../nodes/start/types'
import { Button } from '@langgenius/dify-ui/button'
import { memo, useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useNodes } from 'reactflow'
import { useCheckInputsForms } from '@/app/components/base/chat/chat/check-input-forms-hooks'
import { getProcessedInputs } from '@/app/components/base/chat/chat/utils'
import { TransferMethod } from '../../base/text-generation/types'
import { useWorkflowRun } from '../hooks'
import { useHooksStore } from '../hooks-store'
import FormItem from '../nodes/_base/components/before-run-form/form-item'
import { useStore, useWorkflowStore } from '../store'
import { BlockEnum, InputVarType, WorkflowRunningStatus } from '../types'
type Props = Readonly<{
onRun: () => void
}>
const InputsPanel = ({ onRun }: Props) => {
const { t } = useTranslation()
const workflowStore = useWorkflowStore()
const inputs = useStore((s) => s.inputs)
const fileSettings = useHooksStore((s) => s.configsMap?.fileSettings)
const canRunWorkflow = useHooksStore((s) => s.accessControl.canRun)
const nodes = useNodes<StartNodeType>()
const files = useStore((s) => s.files)
const workflowRunningData = useStore((s) => s.workflowRunningData)
const { handleRun } = useWorkflowRun()
const startNode = nodes.find((node) => node.data.type === BlockEnum.Start)
const startVariables = startNode?.data.variables
const { checkInputsForm } = useCheckInputsForms()
const initialInputs = useMemo(() => {
const result = { ...inputs }
if (startVariables) {
startVariables.forEach((variable) => {
if (variable.default) result[variable.variable] = variable.default
if (inputs[variable.variable] !== undefined)
result[variable.variable] = inputs[variable.variable]!
})
}
return result
}, [inputs, startVariables])
const variables = useMemo(() => {
const data = startVariables || []
if (fileSettings?.image?.enabled) {
return [
...data,
{
type: InputVarType.files,
variable: '__image',
required: false,
label: 'files',
},
]
}
return data
}, [fileSettings?.image?.enabled, startVariables])
const handleValueChange = (variable: string, v: any) => {
const { inputs, setInputs } = workflowStore.getState()
if (variable === '__image') {
workflowStore.setState({
files: v,
})
} else {
setInputs({
...inputs,
[variable]: v,
})
}
}
const canRun = useMemo(() => {
const canUploadReady = !files?.some(
(item) => (item.transfer_method as any) === TransferMethod.local_file && !item.upload_file_id,
)
return canRunWorkflow && canUploadReady
}, [canRunWorkflow, files])
const doRun = useCallback(() => {
if (!canRun) return
if (!checkInputsForm(initialInputs, variables as any)) return
onRun()
handleRun({ inputs: getProcessedInputs(initialInputs, variables as any), files })
}, [canRun, files, handleRun, initialInputs, onRun, variables, checkInputsForm])
return (
<>
<div className="px-4 pt-3 pb-2">
{variables.map((variable, index) => (
<div key={variable.variable} className="mb-2 last-of-type:mb-0">
<FormItem
autoFocus={index === 0}
className="block!"
payload={variable}
value={initialInputs[variable.variable]}
onChange={(v) => handleValueChange(variable.variable, v)}
/>
</div>
))}
</div>
<div className="flex items-center justify-between px-4 py-2">
<Button
variant="primary"
disabled={
!canRun || workflowRunningData?.result?.status === WorkflowRunningStatus.Running
}
className="w-full"
onClick={doRun}
>
{t(($) => $['singleRun.startRun'], { ns: 'workflow' })}
</Button>
</div>
</>
)
}
export default memo(InputsPanel)