Form.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import React, { useState } 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. type FormProps = {
  9. className?: string
  10. itemClassName?: string
  11. fieldLabelClassName?: string
  12. value: CreateExternalAPIReq
  13. onChange: (val: CreateExternalAPIReq) => void
  14. formSchemas: FormSchema[]
  15. inputClassName?: string
  16. }
  17. const Form: FC<FormProps> = React.memo(({
  18. className,
  19. itemClassName,
  20. fieldLabelClassName,
  21. value,
  22. onChange,
  23. formSchemas,
  24. inputClassName,
  25. }) => {
  26. const { t, i18n } = useTranslation()
  27. const [changeKey, setChangeKey] = useState('')
  28. const handleFormChange = (key: string, val: string) => {
  29. setChangeKey(key)
  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 justify-between items-center w-full">
  49. <label className={cn(fieldLabelClassName, 'text-text-secondary system-sm-semibold')} 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={'https://docs.dify.ai/guides/knowledge-base/external-knowledge-api-documentation' || '/'}
  56. target='_blank'
  57. rel='noopener noreferrer'
  58. className='text-text-accent body-xs-regular flex items-center'
  59. >
  60. <RiBookOpenLine className='w-3 h-3 text-text-accent mr-1' />
  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 justify-center items-start gap-4 self-stretch', className)}>
  79. {formSchemas.map(formSchema => renderField(formSchema))}
  80. </form>
  81. )
  82. })
  83. export default Form