You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

inputs-panel.tsx 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import {
  2. memo,
  3. useCallback,
  4. useMemo,
  5. } from 'react'
  6. import { useTranslation } from 'react-i18next'
  7. import { useNodes } from 'reactflow'
  8. import FormItem from '../nodes/_base/components/before-run-form/form-item'
  9. import {
  10. BlockEnum,
  11. InputVarType,
  12. WorkflowRunningStatus,
  13. } from '../types'
  14. import {
  15. useStore,
  16. useWorkflowStore,
  17. } from '../store'
  18. import { useWorkflowRun } from '../hooks'
  19. import type { StartNodeType } from '../nodes/start/types'
  20. import { TransferMethod } from '../../base/text-generation/types'
  21. import Button from '@/app/components/base/button'
  22. import { useFeatures } from '@/app/components/base/features/hooks'
  23. import {
  24. getProcessedInputs,
  25. } from '@/app/components/base/chat/chat/utils'
  26. import { useCheckInputsForms } from '@/app/components/base/chat/chat/check-input-forms-hooks'
  27. type Props = {
  28. onRun: () => void
  29. }
  30. const InputsPanel = ({ onRun }: Props) => {
  31. const { t } = useTranslation()
  32. const workflowStore = useWorkflowStore()
  33. const { inputs } = useStore(s => ({
  34. inputs: s.inputs,
  35. setInputs: s.setInputs,
  36. }))
  37. const fileSettings = useFeatures(s => s.features.file)
  38. const nodes = useNodes<StartNodeType>()
  39. const files = useStore(s => s.files)
  40. const workflowRunningData = useStore(s => s.workflowRunningData)
  41. const {
  42. handleRun,
  43. } = useWorkflowRun()
  44. const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
  45. const startVariables = startNode?.data.variables
  46. const { checkInputsForm } = useCheckInputsForms()
  47. const initialInputs = { ...inputs }
  48. if (startVariables) {
  49. startVariables.forEach((variable) => {
  50. if (variable.default)
  51. initialInputs[variable.variable] = variable.default
  52. if (inputs[variable.variable] !== undefined)
  53. initialInputs[variable.variable] = inputs[variable.variable]
  54. })
  55. }
  56. const variables = useMemo(() => {
  57. const data = startVariables || []
  58. if (fileSettings?.image?.enabled) {
  59. return [
  60. ...data,
  61. {
  62. type: InputVarType.files,
  63. variable: '__image',
  64. required: false,
  65. label: 'files',
  66. },
  67. ]
  68. }
  69. return data
  70. }, [fileSettings?.image?.enabled, startVariables])
  71. const handleValueChange = (variable: string, v: any) => {
  72. const {
  73. inputs,
  74. setInputs,
  75. } = workflowStore.getState()
  76. if (variable === '__image') {
  77. workflowStore.setState({
  78. files: v,
  79. })
  80. }
  81. else {
  82. setInputs({
  83. ...inputs,
  84. [variable]: v,
  85. })
  86. }
  87. }
  88. const doRun = useCallback(() => {
  89. if (!checkInputsForm(initialInputs, variables as any))
  90. return
  91. onRun()
  92. handleRun({ inputs: getProcessedInputs(initialInputs, variables as any), files })
  93. }, [files, handleRun, initialInputs, onRun, variables, checkInputsForm])
  94. const canRun = useMemo(() => {
  95. if (files?.some(item => (item.transfer_method as any) === TransferMethod.local_file && !item.upload_file_id))
  96. return false
  97. return true
  98. }, [files])
  99. return (
  100. <>
  101. <div className='px-4 pb-2 pt-3'>
  102. {
  103. variables.map((variable, index) => (
  104. <div
  105. key={variable.variable}
  106. className='mb-2 last-of-type:mb-0'
  107. >
  108. <FormItem
  109. autoFocus={index === 0}
  110. className='!block'
  111. payload={variable}
  112. value={initialInputs[variable.variable]}
  113. onChange={v => handleValueChange(variable.variable, v)}
  114. />
  115. </div>
  116. ))
  117. }
  118. </div>
  119. <div className='flex items-center justify-between px-4 py-2'>
  120. <Button
  121. variant='primary'
  122. disabled={!canRun || workflowRunningData?.result?.status === WorkflowRunningStatus.Running}
  123. className='w-full'
  124. onClick={doRun}
  125. >
  126. {t('workflow.singleRun.startRun')}
  127. </Button>
  128. </div>
  129. </>
  130. )
  131. }
  132. export default memo(InputsPanel)