Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

endpoint-list.tsx 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import React, { useMemo } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import { useDocLink } from '@/context/i18n'
  4. import { useBoolean } from 'ahooks'
  5. import {
  6. RiAddLine,
  7. RiApps2AddLine,
  8. RiBookOpenLine,
  9. } from '@remixicon/react'
  10. import EndpointModal from './endpoint-modal'
  11. import EndpointCard from './endpoint-card'
  12. import { NAME_FIELD } from './utils'
  13. import { toolCredentialToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
  14. import ActionButton from '@/app/components/base/action-button'
  15. import Tooltip from '@/app/components/base/tooltip'
  16. import Toast from '@/app/components/base/toast'
  17. import {
  18. useCreateEndpoint,
  19. useEndpointList,
  20. useInvalidateEndpointList,
  21. } from '@/service/use-endpoints'
  22. import type { PluginDetail } from '@/app/components/plugins/types'
  23. import cn from '@/utils/classnames'
  24. type Props = {
  25. detail: PluginDetail
  26. }
  27. const EndpointList = ({ detail }: Props) => {
  28. const { t } = useTranslation()
  29. const docLink = useDocLink()
  30. const pluginUniqueID = detail.plugin_unique_identifier
  31. const declaration = detail.declaration.endpoint
  32. const showTopBorder = detail.declaration.tool
  33. const { data } = useEndpointList(detail.plugin_id)
  34. const invalidateEndpointList = useInvalidateEndpointList()
  35. const [isShowEndpointModal, {
  36. setTrue: showEndpointModal,
  37. setFalse: hideEndpointModal,
  38. }] = useBoolean(false)
  39. const formSchemas = useMemo(() => {
  40. return toolCredentialToFormSchemas([NAME_FIELD, ...declaration.settings])
  41. }, [declaration.settings])
  42. const { mutate: createEndpoint } = useCreateEndpoint({
  43. onSuccess: async () => {
  44. await invalidateEndpointList(detail.plugin_id)
  45. hideEndpointModal()
  46. },
  47. onError: () => {
  48. Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') })
  49. },
  50. })
  51. const handleCreate = (state: Record<string, any>) => createEndpoint({
  52. pluginUniqueID,
  53. state,
  54. })
  55. if (!data)
  56. return null
  57. return (
  58. <div className={cn('border-divider-subtle px-4 py-2', showTopBorder && 'border-t')}>
  59. <div className='system-sm-semibold-uppercase mb-1 flex h-6 items-center justify-between text-text-secondary'>
  60. <div className='flex items-center gap-0.5'>
  61. {t('plugin.detailPanel.endpoints')}
  62. <Tooltip
  63. position='right'
  64. popupClassName='w-[240px] p-4 rounded-xl bg-components-panel-bg-blur border-[0.5px] border-components-panel-border'
  65. popupContent={
  66. <div className='flex flex-col gap-2'>
  67. <div className='flex h-8 w-8 items-center justify-center rounded-lg border-[0.5px] border-components-panel-border-subtle bg-background-default-subtle'>
  68. <RiApps2AddLine className='h-4 w-4 text-text-tertiary' />
  69. </div>
  70. <div className='system-xs-regular text-text-tertiary'>{t('plugin.detailPanel.endpointsTip')}</div>
  71. <a
  72. href={docLink('/plugins/schema-definition/endpoint')}
  73. target='_blank'
  74. rel='noopener noreferrer'
  75. >
  76. <div className='system-xs-regular inline-flex cursor-pointer items-center gap-1 text-text-accent'>
  77. <RiBookOpenLine className='h-3 w-3' />
  78. {t('plugin.detailPanel.endpointsDocLink')}
  79. </div>
  80. </a>
  81. </div>
  82. }
  83. />
  84. </div>
  85. <ActionButton onClick={showEndpointModal}>
  86. <RiAddLine className='h-4 w-4' />
  87. </ActionButton>
  88. </div>
  89. {data.endpoints.length === 0 && (
  90. <div className='system-xs-regular mb-1 flex justify-center rounded-[10px] bg-background-section p-3 text-text-tertiary'>{t('plugin.detailPanel.endpointsEmpty')}</div>
  91. )}
  92. <div className='flex flex-col gap-2'>
  93. {data.endpoints.map((item, index) => (
  94. <EndpointCard
  95. key={index}
  96. data={item}
  97. handleChange={() => invalidateEndpointList(detail.plugin_id)}
  98. />
  99. ))}
  100. </div>
  101. {isShowEndpointModal && (
  102. <EndpointModal
  103. formSchemas={formSchemas}
  104. onCancel={hideEndpointModal}
  105. onSaved={handleCreate}
  106. />
  107. )}
  108. </div>
  109. )
  110. }
  111. export default EndpointList