config-credentials.tsx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import Tooltip from '@/app/components/base/tooltip'
  6. import cn from '@/utils/classnames'
  7. import type { Credential } from '@/app/components/tools/types'
  8. import Drawer from '@/app/components/base/drawer-plus'
  9. import Button from '@/app/components/base/button'
  10. import Radio from '@/app/components/base/radio/ui'
  11. import { AuthHeaderPrefix, AuthType } from '@/app/components/tools/types'
  12. type Props = {
  13. positionCenter?: boolean
  14. credential: Credential
  15. onChange: (credential: Credential) => void
  16. onHide: () => void
  17. }
  18. const keyClassNames = 'py-2 leading-5 text-sm font-medium text-gray-900'
  19. type ItemProps = {
  20. text: string
  21. value: AuthType | AuthHeaderPrefix
  22. isChecked: boolean
  23. onClick: (value: AuthType | AuthHeaderPrefix) => void
  24. }
  25. const SelectItem: FC<ItemProps> = ({ text, value, isChecked, onClick }) => {
  26. return (
  27. <div
  28. className={cn(isChecked ? 'border-[2px] border-indigo-600 shadow-sm bg-white' : 'border border-gray-100', 'mb-2 flex items-center h-9 pl-3 w-[150px] rounded-xl bg-gray-25 hover:bg-gray-50 cursor-pointer space-x-2')}
  29. onClick={() => onClick(value)}
  30. >
  31. <Radio isChecked={isChecked} />
  32. <div className='text-sm font-normal text-gray-900'>{text}</div>
  33. </div>
  34. )
  35. }
  36. const ConfigCredential: FC<Props> = ({
  37. positionCenter,
  38. credential,
  39. onChange,
  40. onHide,
  41. }) => {
  42. const { t } = useTranslation()
  43. const [tempCredential, setTempCredential] = React.useState<Credential>(credential)
  44. return (
  45. <Drawer
  46. isShow
  47. positionCenter={positionCenter}
  48. onHide={onHide}
  49. title={t('tools.createTool.authMethod.title')!}
  50. panelClassName='mt-2 !w-[520px] h-fit'
  51. maxWidthClassName='!max-w-[520px]'
  52. height={'fit-content'}
  53. headerClassName='!border-b-black/5'
  54. body={
  55. <div className='pt-2 px-6'>
  56. <div className='space-y-4'>
  57. <div>
  58. <div className={keyClassNames}>{t('tools.createTool.authMethod.type')}</div>
  59. <div className='flex space-x-3'>
  60. <SelectItem
  61. text={t('tools.createTool.authMethod.types.none')}
  62. value={AuthType.none}
  63. isChecked={tempCredential.auth_type === AuthType.none}
  64. onClick={value => setTempCredential({ ...tempCredential, auth_type: value as AuthType })}
  65. />
  66. <SelectItem
  67. text={t('tools.createTool.authMethod.types.api_key')}
  68. value={AuthType.apiKey}
  69. isChecked={tempCredential.auth_type === AuthType.apiKey}
  70. onClick={value => setTempCredential({
  71. ...tempCredential,
  72. auth_type: value as AuthType,
  73. api_key_header: tempCredential.api_key_header || 'Authorization',
  74. api_key_value: tempCredential.api_key_value || '',
  75. api_key_header_prefix: tempCredential.api_key_header_prefix || AuthHeaderPrefix.custom,
  76. })}
  77. />
  78. </div>
  79. </div>
  80. {tempCredential.auth_type === AuthType.apiKey && (
  81. <>
  82. <div className={keyClassNames}>{t('tools.createTool.authHeaderPrefix.title')}</div>
  83. <div className='flex space-x-3'>
  84. <SelectItem
  85. text={t('tools.createTool.authHeaderPrefix.types.basic')}
  86. value={AuthHeaderPrefix.basic}
  87. isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.basic}
  88. onClick={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value as AuthHeaderPrefix })}
  89. />
  90. <SelectItem
  91. text={t('tools.createTool.authHeaderPrefix.types.bearer')}
  92. value={AuthHeaderPrefix.bearer}
  93. isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.bearer}
  94. onClick={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value as AuthHeaderPrefix })}
  95. />
  96. <SelectItem
  97. text={t('tools.createTool.authHeaderPrefix.types.custom')}
  98. value={AuthHeaderPrefix.custom}
  99. isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.custom}
  100. onClick={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value as AuthHeaderPrefix })}
  101. />
  102. </div>
  103. <div>
  104. <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
  105. {t('tools.createTool.authMethod.key')}
  106. <Tooltip
  107. popupContent={
  108. <div className='w-[261px] text-gray-500'>
  109. {t('tools.createTool.authMethod.keyTooltip')}
  110. </div>
  111. }
  112. triggerClassName='ml-0.5 w-4 h-4'
  113. />
  114. </div>
  115. <input
  116. value={tempCredential.api_key_header}
  117. onChange={e => setTempCredential({ ...tempCredential, api_key_header: e.target.value })}
  118. className='w-full h-10 px-3 text-sm font-normal border border-transparent bg-gray-100 rounded-lg grow outline-none focus:bg-components-input-bg-active focus:border-components-input-border-active focus:shadow-xs'
  119. placeholder={t('tools.createTool.authMethod.types.apiKeyPlaceholder')!}
  120. />
  121. </div>
  122. <div>
  123. <div className={keyClassNames}>{t('tools.createTool.authMethod.value')}</div>
  124. <input
  125. value={tempCredential.api_key_value}
  126. onChange={e => setTempCredential({ ...tempCredential, api_key_value: e.target.value })}
  127. className='w-full h-10 px-3 text-sm font-normal border border-transparent bg-gray-100 rounded-lg grow outline-none focus:bg-components-input-bg-active focus:border-components-input-border-active focus:shadow-xs'
  128. placeholder={t('tools.createTool.authMethod.types.apiValuePlaceholder')!}
  129. />
  130. </div>
  131. </>)}
  132. </div>
  133. <div className='mt-4 shrink-0 flex justify-end space-x-2 py-4'>
  134. <Button onClick={onHide}>{t('common.operation.cancel')}</Button>
  135. <Button variant='primary' onClick={() => {
  136. onChange(tempCredential)
  137. onHide()
  138. }}>{t('common.operation.save')}</Button>
  139. </div>
  140. </div>
  141. }
  142. />
  143. )
  144. }
  145. export default React.memo(ConfigCredential)