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 4.0KB

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