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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import React, { memo, useCallback } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import { useEmbeddedChatbotContext } from '../context'
  4. import Input from '@/app/components/base/input'
  5. import Textarea from '@/app/components/base/textarea'
  6. import { PortalSelect } from '@/app/components/base/select'
  7. import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader'
  8. import { InputVarType } from '@/app/components/workflow/types'
  9. import BoolInput from '@/app/components/workflow/nodes/_base/components/before-run-form/bool-input'
  10. import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
  11. import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
  12. type Props = {
  13. showTip?: boolean
  14. }
  15. const InputsFormContent = ({ showTip }: Props) => {
  16. const { t } = useTranslation()
  17. const {
  18. appParams,
  19. inputsForms,
  20. currentConversationId,
  21. currentConversationInputs,
  22. setCurrentConversationInputs,
  23. newConversationInputs,
  24. newConversationInputsRef,
  25. handleNewConversationInputsChange,
  26. } = useEmbeddedChatbotContext()
  27. const inputsFormValue = currentConversationId ? currentConversationInputs : newConversationInputs
  28. const handleFormChange = useCallback((variable: string, value: any) => {
  29. setCurrentConversationInputs({
  30. ...currentConversationInputs,
  31. [variable]: value,
  32. })
  33. handleNewConversationInputsChange({
  34. ...newConversationInputsRef.current,
  35. [variable]: value,
  36. })
  37. }, [newConversationInputsRef, handleNewConversationInputsChange, currentConversationInputs, setCurrentConversationInputs])
  38. const visibleInputsForms = inputsForms.filter(form => form.hide !== true)
  39. return (
  40. <div className='space-y-4'>
  41. {visibleInputsForms.map(form => (
  42. <div key={form.variable} className='space-y-1'>
  43. {form.type !== InputVarType.checkbox && (
  44. <div className='flex h-6 items-center gap-1'>
  45. <div className='system-md-semibold text-text-secondary'>{form.label}</div>
  46. {!form.required && (
  47. <div className='system-xs-regular text-text-tertiary'>{t('appDebug.variableTable.optional')}</div>
  48. )}
  49. </div>
  50. )}
  51. {form.type === InputVarType.textInput && (
  52. <Input
  53. value={inputsFormValue?.[form.variable] || ''}
  54. onChange={e => handleFormChange(form.variable, e.target.value)}
  55. placeholder={form.label}
  56. />
  57. )}
  58. {form.type === InputVarType.number && (
  59. <Input
  60. type='number'
  61. value={inputsFormValue?.[form.variable] || ''}
  62. onChange={e => handleFormChange(form.variable, e.target.value)}
  63. placeholder={form.label}
  64. />
  65. )}
  66. {form.type === InputVarType.paragraph && (
  67. <Textarea
  68. value={inputsFormValue?.[form.variable] || ''}
  69. onChange={e => handleFormChange(form.variable, e.target.value)}
  70. placeholder={form.label}
  71. />
  72. )}
  73. {form.type === InputVarType.checkbox && (
  74. <BoolInput
  75. name={form.label}
  76. value={inputsFormValue?.[form.variable]}
  77. required={form.required}
  78. onChange={value => handleFormChange(form.variable, value)}
  79. />
  80. )}
  81. {form.type === InputVarType.select && (
  82. <PortalSelect
  83. popupClassName='w-[200px]'
  84. value={inputsFormValue?.[form.variable] ?? form.default ?? ''}
  85. items={form.options.map((option: string) => ({ value: option, name: option }))}
  86. onSelect={item => handleFormChange(form.variable, item.value as string)}
  87. placeholder={form.label}
  88. />
  89. )}
  90. {form.type === InputVarType.singleFile && (
  91. <FileUploaderInAttachmentWrapper
  92. value={inputsFormValue?.[form.variable] ? [inputsFormValue?.[form.variable]] : []}
  93. onChange={files => handleFormChange(form.variable, files[0])}
  94. fileConfig={{
  95. allowed_file_types: form.allowed_file_types,
  96. allowed_file_extensions: form.allowed_file_extensions,
  97. allowed_file_upload_methods: form.allowed_file_upload_methods,
  98. number_limits: 1,
  99. fileUploadConfig: (appParams as any).system_parameters,
  100. }}
  101. />
  102. )}
  103. {form.type === InputVarType.multiFiles && (
  104. <FileUploaderInAttachmentWrapper
  105. value={inputsFormValue?.[form.variable] || []}
  106. onChange={files => handleFormChange(form.variable, files)}
  107. fileConfig={{
  108. allowed_file_types: form.allowed_file_types,
  109. allowed_file_extensions: form.allowed_file_extensions,
  110. allowed_file_upload_methods: form.allowed_file_upload_methods,
  111. number_limits: form.max_length,
  112. fileUploadConfig: (appParams as any).system_parameters,
  113. }}
  114. />
  115. )}
  116. {form.type === InputVarType.jsonObject && (
  117. <CodeEditor
  118. language={CodeLanguage.json}
  119. value={inputsFormValue?.[form.variable] || ''}
  120. onChange={v => handleFormChange(form.variable, v)}
  121. noWrapper
  122. className='bg h-[80px] overflow-y-auto rounded-[10px] bg-components-input-bg-normal p-1'
  123. placeholder={
  124. <div className='whitespace-pre'>{form.json_schema}</div>
  125. }
  126. />
  127. )}
  128. </div>
  129. ))}
  130. {showTip && (
  131. <div className='system-xs-regular text-text-tertiary'>{t('share.chat.chatFormTip')}</div>
  132. )}
  133. </div>
  134. )
  135. }
  136. export default memo(InputsFormContent)