您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

authorized-in-node.tsx 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import {
  2. memo,
  3. useCallback,
  4. useState,
  5. } from 'react'
  6. import { useTranslation } from 'react-i18next'
  7. import { RiArrowDownSLine } from '@remixicon/react'
  8. import Button from '@/app/components/base/button'
  9. import Indicator from '@/app/components/header/indicator'
  10. import cn from '@/utils/classnames'
  11. import type {
  12. Credential,
  13. PluginPayload,
  14. } from './types'
  15. import {
  16. Authorized,
  17. usePluginAuth,
  18. } from '.'
  19. type AuthorizedInNodeProps = {
  20. pluginPayload: PluginPayload
  21. onAuthorizationItemClick: (id: string) => void
  22. credentialId?: string
  23. }
  24. const AuthorizedInNode = ({
  25. pluginPayload,
  26. onAuthorizationItemClick,
  27. credentialId,
  28. }: AuthorizedInNodeProps) => {
  29. const { t } = useTranslation()
  30. const [isOpen, setIsOpen] = useState(false)
  31. const {
  32. canApiKey,
  33. canOAuth,
  34. credentials,
  35. disabled,
  36. invalidPluginCredentialInfo,
  37. } = usePluginAuth(pluginPayload, isOpen || !!credentialId)
  38. const renderTrigger = useCallback((open?: boolean) => {
  39. let label = ''
  40. let removed = false
  41. if (!credentialId) {
  42. label = t('plugin.auth.workspaceDefault')
  43. }
  44. else {
  45. const credential = credentials.find(c => c.id === credentialId)
  46. label = credential ? credential.name : t('plugin.auth.authRemoved')
  47. removed = !credential
  48. }
  49. return (
  50. <Button
  51. size='small'
  52. className={cn(
  53. open && !removed && 'bg-components-button-ghost-bg-hover',
  54. removed && 'bg-transparent text-text-destructive',
  55. )}
  56. >
  57. <Indicator
  58. className='mr-1.5'
  59. color={removed ? 'red' : 'green'}
  60. />
  61. {label}
  62. <RiArrowDownSLine
  63. className={cn(
  64. 'h-3.5 w-3.5 text-components-button-ghost-text',
  65. removed && 'text-text-destructive',
  66. )}
  67. />
  68. </Button>
  69. )
  70. }, [credentialId, credentials, t])
  71. const extraAuthorizationItems: Credential[] = [
  72. {
  73. id: '__workspace_default__',
  74. name: t('plugin.auth.workspaceDefault'),
  75. provider: '',
  76. is_default: !credentialId,
  77. isWorkspaceDefault: true,
  78. },
  79. ]
  80. const handleAuthorizationItemClick = useCallback((id: string) => {
  81. onAuthorizationItemClick(id)
  82. setIsOpen(false)
  83. }, [
  84. onAuthorizationItemClick,
  85. setIsOpen,
  86. ])
  87. return (
  88. <Authorized
  89. pluginPayload={pluginPayload}
  90. credentials={credentials}
  91. canOAuth={canOAuth}
  92. canApiKey={canApiKey}
  93. renderTrigger={renderTrigger}
  94. isOpen={isOpen}
  95. onOpenChange={setIsOpen}
  96. offset={4}
  97. placement='bottom-end'
  98. triggerPopupSameWidth={false}
  99. popupClassName='w-[360px]'
  100. disabled={disabled}
  101. disableSetDefault
  102. onItemClick={handleAuthorizationItemClick}
  103. extraAuthorizationItems={extraAuthorizationItems}
  104. showItemSelectedIcon
  105. selectedCredentialId={credentialId || '__workspace_default__'}
  106. onUpdate={invalidPluginCredentialInfo}
  107. />
  108. )
  109. }
  110. export default memo(AuthorizedInNode)