index.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import React, { useState } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import {
  4. RiDeleteBinLine,
  5. RiEditLine,
  6. } from '@remixicon/react'
  7. import type { CreateExternalAPIReq } from '../declarations'
  8. import type { ExternalAPIItem } from '@/models/datasets'
  9. import { checkUsageExternalAPI, deleteExternalAPI, fetchExternalAPI, updateExternalAPI } from '@/service/datasets'
  10. import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development'
  11. import { useExternalKnowledgeApi } from '@/context/external-knowledge-api-context'
  12. import { useModalContext } from '@/context/modal-context'
  13. import ActionButton from '@/app/components/base/action-button'
  14. import Confirm from '@/app/components/base/confirm'
  15. type ExternalKnowledgeAPICardProps = {
  16. api: ExternalAPIItem
  17. }
  18. const ExternalKnowledgeAPICard: React.FC<ExternalKnowledgeAPICardProps> = ({ api }) => {
  19. const { setShowExternalKnowledgeAPIModal } = useModalContext()
  20. const [showConfirm, setShowConfirm] = useState(false)
  21. const [isHovered, setIsHovered] = useState(false)
  22. const [usageCount, setUsageCount] = useState(0)
  23. const { mutateExternalKnowledgeApis } = useExternalKnowledgeApi()
  24. const { t } = useTranslation()
  25. const handleEditClick = async () => {
  26. try {
  27. const response = await fetchExternalAPI({ apiTemplateId: api.id })
  28. const formValue: CreateExternalAPIReq = {
  29. name: response.name,
  30. settings: {
  31. endpoint: response.settings.endpoint,
  32. api_key: response.settings.api_key,
  33. },
  34. }
  35. setShowExternalKnowledgeAPIModal({
  36. payload: formValue,
  37. onSaveCallback: () => {
  38. mutateExternalKnowledgeApis()
  39. },
  40. onCancelCallback: () => {
  41. mutateExternalKnowledgeApis()
  42. },
  43. isEditMode: true,
  44. datasetBindings: response.dataset_bindings,
  45. onEditCallback: async (updatedData: CreateExternalAPIReq) => {
  46. try {
  47. await updateExternalAPI({
  48. apiTemplateId: api.id,
  49. body: {
  50. ...response,
  51. name: updatedData.name,
  52. settings: {
  53. ...response.settings,
  54. endpoint: updatedData.settings.endpoint,
  55. api_key: updatedData.settings.api_key,
  56. },
  57. },
  58. })
  59. mutateExternalKnowledgeApis()
  60. }
  61. catch (error) {
  62. console.error('Error updating external knowledge API:', error)
  63. }
  64. },
  65. })
  66. }
  67. catch (error) {
  68. console.error('Error fetching external knowledge API data:', error)
  69. }
  70. }
  71. const handleDeleteClick = async () => {
  72. try {
  73. const usage = await checkUsageExternalAPI({ apiTemplateId: api.id })
  74. if (usage.is_using)
  75. setUsageCount(usage.count)
  76. setShowConfirm(true)
  77. }
  78. catch (error) {
  79. console.error('Error checking external API usage:', error)
  80. }
  81. }
  82. const handleConfirmDelete = async () => {
  83. try {
  84. const response = await deleteExternalAPI({ apiTemplateId: api.id })
  85. if (response && response.result === 'success') {
  86. setShowConfirm(false)
  87. mutateExternalKnowledgeApis()
  88. }
  89. else {
  90. console.error('Failed to delete external API')
  91. }
  92. }
  93. catch (error) {
  94. console.error('Error deleting external knowledge API:', error)
  95. }
  96. }
  97. return (
  98. <>
  99. <div className={`flex p-2 pl-3 items-start self-stretch rounded-lg border-[0.5px]
  100. border-components-panel-border-subtle bg-components-panel-on-panel-item-bg
  101. shadows-shadow-xs ${isHovered ? 'bg-state-destructive-hover border-state-destructive-border' : ''}`}
  102. >
  103. <div className='flex py-1 flex-col justify-center items-start gap-1.5 flex-grow'>
  104. <div className='flex items-center gap-1 self-stretch text-text-secondary'>
  105. <ApiConnectionMod className='w-4 h-4' />
  106. <div className='system-sm-medium'>{api.name}</div>
  107. </div>
  108. <div className='self-stretch text-text-tertiary system-xs-regular'>{api.settings.endpoint}</div>
  109. </div>
  110. <div className='flex items-start gap-1'>
  111. <ActionButton onClick={handleEditClick}>
  112. <RiEditLine className='w-4 h-4 text-text-tertiary hover:text-text-secondary' />
  113. </ActionButton>
  114. <ActionButton
  115. className='hover:bg-state-destructive-hover'
  116. onClick={handleDeleteClick}
  117. onMouseEnter={() => setIsHovered(true)}
  118. onMouseLeave={() => setIsHovered(false)}
  119. >
  120. <RiDeleteBinLine className='w-4 h-4 text-text-tertiary hover:text-text-destructive' />
  121. </ActionButton>
  122. </div>
  123. </div>
  124. {showConfirm && (
  125. <Confirm
  126. isShow={showConfirm}
  127. title={`${t('dataset.deleteExternalAPIConfirmWarningContent.title.front')} ${api.name}${t('dataset.deleteExternalAPIConfirmWarningContent.title.end')}`}
  128. content={
  129. usageCount > 0
  130. ? `${t('dataset.deleteExternalAPIConfirmWarningContent.content.front')} ${usageCount} ${t('dataset.deleteExternalAPIConfirmWarningContent.content.end')}`
  131. : t('dataset.deleteExternalAPIConfirmWarningContent.noConnectionContent')
  132. }
  133. type='warning'
  134. onConfirm={handleConfirmDelete}
  135. onCancel={() => setShowConfirm(false)}
  136. />
  137. )}
  138. </>
  139. )
  140. }
  141. export default ExternalKnowledgeAPICard