form.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { useTranslation } from 'react-i18next'
  2. import { useChatWithHistoryContext } from '../context'
  3. import Input from './form-input'
  4. import { PortalSelect } from '@/app/components/base/select'
  5. import { InputVarType } from '@/app/components/workflow/types'
  6. import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader'
  7. const Form = () => {
  8. const { t } = useTranslation()
  9. const {
  10. inputsForms,
  11. newConversationInputs,
  12. newConversationInputsRef,
  13. handleNewConversationInputsChange,
  14. isMobile,
  15. } = useChatWithHistoryContext()
  16. const handleFormChange = (variable: string, value: any) => {
  17. handleNewConversationInputsChange({
  18. ...newConversationInputsRef.current,
  19. [variable]: value,
  20. })
  21. }
  22. const renderField = (form: any) => {
  23. const {
  24. label,
  25. required,
  26. variable,
  27. options,
  28. } = form
  29. if (form.type === 'text-input' || form.type === 'paragraph') {
  30. return (
  31. <Input
  32. form={form}
  33. value={newConversationInputs[variable]}
  34. onChange={handleFormChange}
  35. />
  36. )
  37. }
  38. if (form.type === 'number') {
  39. return (
  40. <input
  41. className="grow h-9 rounded-lg bg-gray-100 px-2.5 outline-none appearance-none"
  42. type="number"
  43. value={newConversationInputs[variable] || ''}
  44. onChange={e => handleFormChange(variable, e.target.value)}
  45. placeholder={`${label}${!required ? `(${t('appDebug.variableTable.optional')})` : ''}`}
  46. />
  47. )
  48. }
  49. if (form.type === InputVarType.singleFile) {
  50. return (
  51. <FileUploaderInAttachmentWrapper
  52. value={newConversationInputs[variable] ? [newConversationInputs[variable]] : []}
  53. onChange={files => handleFormChange(variable, files[0])}
  54. fileConfig={{
  55. allowed_file_types: form.allowed_file_types,
  56. allowed_file_extensions: form.allowed_file_extensions,
  57. allowed_file_upload_methods: form.allowed_file_upload_methods,
  58. number_limits: 1,
  59. }}
  60. />
  61. )
  62. }
  63. if (form.type === InputVarType.multiFiles) {
  64. return (
  65. <FileUploaderInAttachmentWrapper
  66. value={newConversationInputs[variable]}
  67. onChange={files => handleFormChange(variable, files)}
  68. fileConfig={{
  69. allowed_file_types: form.allowed_file_types,
  70. allowed_file_extensions: form.allowed_file_extensions,
  71. allowed_file_upload_methods: form.allowed_file_upload_methods,
  72. number_limits: form.max_length,
  73. }}
  74. />
  75. )
  76. }
  77. return (
  78. <PortalSelect
  79. popupClassName='w-[200px]'
  80. value={newConversationInputs[variable]}
  81. items={options.map((option: string) => ({ value: option, name: option }))}
  82. onSelect={item => handleFormChange(variable, item.value as string)}
  83. placeholder={`${label}${!required ? `(${t('appDebug.variableTable.optional')})` : ''}`}
  84. />
  85. )
  86. }
  87. if (!inputsForms.length)
  88. return null
  89. return (
  90. <div className='mb-4 py-2'>
  91. {
  92. inputsForms.map(form => (
  93. <div
  94. key={form.variable}
  95. className={`flex mb-3 last-of-type:mb-0 text-sm text-gray-900 ${isMobile && '!flex-wrap'}`}
  96. >
  97. <div className={`shrink-0 mr-2 py-2 w-[128px] ${isMobile && '!w-full'}`}>{form.label}</div>
  98. {renderField(form)}
  99. </div>
  100. ))
  101. }
  102. </div>
  103. )
  104. }
  105. export default Form