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.

Form.tsx 2.8KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import React from 'react'
  2. import type { FC } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import { RiBookOpenLine } from '@remixicon/react'
  5. import type { CreateExternalAPIReq, FormSchema } from '../declarations'
  6. import Input from '@/app/components/base/input'
  7. import cn from '@/utils/classnames'
  8. import { useDocLink } from '@/context/i18n'
  9. type FormProps = {
  10. className?: string
  11. itemClassName?: string
  12. fieldLabelClassName?: string
  13. value: CreateExternalAPIReq
  14. onChange: (val: CreateExternalAPIReq) => void
  15. formSchemas: FormSchema[]
  16. inputClassName?: string
  17. }
  18. const Form: FC<FormProps> = React.memo(({
  19. className,
  20. itemClassName,
  21. fieldLabelClassName,
  22. value,
  23. onChange,
  24. formSchemas,
  25. inputClassName,
  26. }) => {
  27. const { t, i18n } = useTranslation()
  28. const docLink = useDocLink()
  29. const handleFormChange = (key: string, val: string) => {
  30. if (key === 'name') {
  31. onChange({ ...value, [key]: val })
  32. }
  33. else {
  34. onChange({
  35. ...value,
  36. settings: {
  37. ...value.settings,
  38. [key]: val,
  39. },
  40. })
  41. }
  42. }
  43. const renderField = (formSchema: FormSchema) => {
  44. const { variable, type, label, required } = formSchema
  45. const fieldValue = variable === 'name' ? value[variable] : (value.settings[variable as keyof typeof value.settings] || '')
  46. return (
  47. <div key={variable} className={cn(itemClassName, 'flex flex-col items-start gap-1 self-stretch')}>
  48. <div className="flex w-full items-center justify-between">
  49. <label className={cn(fieldLabelClassName, 'system-sm-semibold text-text-secondary')} htmlFor={variable}>
  50. {label[i18n.language] || label.en_US}
  51. {required && <span className='ml-1 text-red-500'>*</span>}
  52. </label>
  53. {variable === 'endpoint' && (
  54. <a
  55. href={docLink('/guides/knowledge-base/connect-external-knowledge-base') || '/'}
  56. target='_blank'
  57. rel='noopener noreferrer'
  58. className='body-xs-regular flex items-center text-text-accent'
  59. >
  60. <RiBookOpenLine className='mr-1 h-3 w-3 text-text-accent' />
  61. {t('dataset.externalAPIPanelDocumentation')}
  62. </a>
  63. )}
  64. </div>
  65. <Input
  66. type={type === 'secret' ? 'password' : 'text'}
  67. id={variable}
  68. name={variable}
  69. value={fieldValue}
  70. onChange={val => handleFormChange(variable, val.target.value)}
  71. required={required}
  72. className={cn(inputClassName)}
  73. />
  74. </div>
  75. )
  76. }
  77. return (
  78. <form className={cn('flex flex-col items-start justify-center gap-4 self-stretch', className)}>
  79. {formSchemas.map(formSchema => renderField(formSchema))}
  80. </form>
  81. )
  82. })
  83. Form.displayName = 'Form'
  84. export default Form