config-credentials.tsx 6.6 KB

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