config-credentials.tsx 6.8 KB

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