|
import { |
|
memo, |
|
useCallback, |
|
useMemo, |
|
} from 'react' |
|
import { useTranslation } from 'react-i18next' |
|
import { useNodes } from 'reactflow' |
|
import FormItem from '../nodes/_base/components/before-run-form/form-item' |
|
import { |
|
BlockEnum, |
|
InputVarType, |
|
WorkflowRunningStatus, |
|
} from '../types' |
|
import { |
|
useStore, |
|
useWorkflowStore, |
|
} from '../store' |
|
import { useWorkflowRun } from '../hooks' |
|
import type { StartNodeType } from '../nodes/start/types' |
|
import { TransferMethod } from '../../base/text-generation/types' |
|
import Button from '@/app/components/base/button' |
|
import { useFeatures } from '@/app/components/base/features/hooks' |
|
import { |
|
getProcessedInputs, |
|
} from '@/app/components/base/chat/chat/utils' |
|
import { useCheckInputsForms } from '@/app/components/base/chat/chat/check-input-forms-hooks' |
|
|
|
type Props = { |
|
onRun: () => void |
|
} |
|
|
|
const InputsPanel = ({ onRun }: Props) => { |
|
const { t } = useTranslation() |
|
const workflowStore = useWorkflowStore() |
|
const fileSettings = useFeatures(s => s.features.file) |
|
const nodes = useNodes<StartNodeType>() |
|
const inputs = useStore(s => s.inputs) |
|
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 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 doRun = useCallback(() => { |
|
if (!checkInputsForm(inputs, variables as any)) |
|
return |
|
onRun() |
|
handleRun({ inputs: getProcessedInputs(inputs, variables as any), files }) |
|
}, [files, handleRun, inputs, onRun, variables, checkInputsForm]) |
|
|
|
const canRun = useMemo(() => { |
|
if (files?.some(item => (item.transfer_method as any) === TransferMethod.local_file && !item.upload_file_id)) |
|
return false |
|
|
|
return true |
|
}, [files]) |
|
|
|
return ( |
|
<> |
|
<div className='pt-3 px-4 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={inputs[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('workflow.singleRun.startRun')} |
|
</Button> |
|
</div> |
|
</> |
|
) |
|
} |
|
|
|
export default memo(InputsPanel) |
|
|