Form.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import { useState } from 'react'
  2. import type { FC } from 'react'
  3. import { ValidatingTip } from '../../key-validator/ValidateStatus'
  4. import type {
  5. CredentialFormSchema,
  6. CredentialFormSchemaRadio,
  7. CredentialFormSchemaSecretInput,
  8. CredentialFormSchemaSelect,
  9. CredentialFormSchemaTextInput,
  10. FormValue,
  11. } from '../declarations'
  12. import { FormTypeEnum } from '../declarations'
  13. import { useLanguage } from '../hooks'
  14. import Input from './Input'
  15. import { SimpleSelect } from '@/app/components/base/select'
  16. type FormProps = {
  17. value: FormValue
  18. onChange: (val: FormValue) => void
  19. formSchemas: CredentialFormSchema[]
  20. validating: boolean
  21. validatedSuccess?: boolean
  22. showOnVariableMap: Record<string, string[]>
  23. isEditMode: boolean
  24. }
  25. const Form: FC<FormProps> = ({
  26. value,
  27. onChange,
  28. formSchemas,
  29. validating,
  30. validatedSuccess,
  31. showOnVariableMap,
  32. isEditMode,
  33. }) => {
  34. const language = useLanguage()
  35. const [changeKey, setChangeKey] = useState('')
  36. const handleFormChange = (key: string, val: string) => {
  37. if (isEditMode && (key === '__model_type' || key === '__model_name'))
  38. return
  39. setChangeKey(key)
  40. const shouldClearVariable: Record<string, string | undefined> = {}
  41. if (showOnVariableMap[key]?.length) {
  42. showOnVariableMap[key].forEach((clearVariable) => {
  43. shouldClearVariable[clearVariable] = undefined
  44. })
  45. }
  46. onChange({ ...value, [key]: val, ...shouldClearVariable })
  47. }
  48. const renderField = (formSchema: CredentialFormSchema) => {
  49. if (formSchema.type === FormTypeEnum.textInput || formSchema.type === FormTypeEnum.secretInput) {
  50. const {
  51. variable,
  52. label,
  53. placeholder,
  54. required,
  55. show_on,
  56. } = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
  57. if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
  58. return null
  59. const disabed = isEditMode && (variable === '__model_type' || variable === '__model_name')
  60. return (
  61. <div key={variable} className='py-3'>
  62. <div className='py-2 text-sm text-gray-900'>
  63. {label[language]}
  64. {
  65. required && (
  66. <span className='ml-1 text-red-500'>*</span>
  67. )
  68. }
  69. </div>
  70. <Input
  71. className={`${disabed && 'cursor-not-allowed opacity-60'}`}
  72. value={value[variable] as string}
  73. onChange={val => handleFormChange(variable, val)}
  74. validated={validatedSuccess}
  75. placeholder={placeholder?.[language]}
  76. disabled={disabed}
  77. />
  78. {validating && changeKey === variable && <ValidatingTip />}
  79. </div>
  80. )
  81. }
  82. if (formSchema.type === FormTypeEnum.radio) {
  83. const {
  84. options,
  85. variable,
  86. label,
  87. show_on,
  88. required,
  89. } = formSchema as CredentialFormSchemaRadio
  90. if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
  91. return null
  92. const disabed = isEditMode && (variable === '__model_type' || variable === '__model_name')
  93. return (
  94. <div key={variable} className='py-3'>
  95. <div className='py-2 text-sm text-gray-900'>
  96. {label[language]}
  97. {
  98. required && (
  99. <span className='ml-1 text-red-500'>*</span>
  100. )
  101. }
  102. </div>
  103. <div className={`grid grid-cols-${options?.length} gap-3`}>
  104. {
  105. options.filter((option) => {
  106. if (option.show_on.length)
  107. return option.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value)
  108. return true
  109. }).map(option => (
  110. <div
  111. className={`
  112. flex items-center px-3 py-2 rounded-lg border border-gray-100 bg-gray-25 cursor-pointer
  113. ${value[variable] === option.value && 'bg-white border-[1.5px] border-primary-400 shadow-sm'}
  114. ${disabed && '!cursor-not-allowed opacity-60'}
  115. `}
  116. onClick={() => handleFormChange(variable, option.value)}
  117. key={`${variable}-${option.value}`}
  118. >
  119. <div className={`
  120. flex justify-center items-center mr-2 w-4 h-4 border border-gray-300 rounded-full
  121. ${value[variable] === option.value && 'border-[5px] border-primary-600'}
  122. `} />
  123. <div className='text-sm text-gray-900'>{option.label[language]}</div>
  124. </div>
  125. ))
  126. }
  127. </div>
  128. {validating && changeKey === variable && <ValidatingTip />}
  129. </div>
  130. )
  131. }
  132. if (formSchema.type === 'select') {
  133. const {
  134. options,
  135. variable,
  136. label,
  137. show_on,
  138. required,
  139. placeholder,
  140. } = formSchema as CredentialFormSchemaSelect
  141. if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
  142. return null
  143. return (
  144. <div key={variable} className='py-3'>
  145. <div className='py-2 text-sm text-gray-900'>
  146. {label[language]}
  147. {
  148. required && (
  149. <span className='ml-1 text-red-500'>*</span>
  150. )
  151. }
  152. </div>
  153. <SimpleSelect
  154. defaultValue={value[variable] as string}
  155. items={options.filter((option) => {
  156. if (option.show_on.length)
  157. return option.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value)
  158. return true
  159. }).map(option => ({ value: option.value, name: option.label[language] }))}
  160. onSelect={item => handleFormChange(variable, item.value as string)}
  161. placeholder={placeholder?.[language]}
  162. />
  163. {validating && changeKey === variable && <ValidatingTip />}
  164. </div>
  165. )
  166. }
  167. }
  168. return (
  169. <div>
  170. {
  171. formSchemas.map(formSchema => renderField(formSchema))
  172. }
  173. </div>
  174. )
  175. }
  176. export default Form