index.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useCallback, useEffect, useState } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import Panel from '../panel'
  6. import { DataSourceType } from '../panel/types'
  7. import ConfigFirecrawlModal from './config-firecrawl-modal'
  8. import ConfigJinaReaderModal from './config-jina-reader-modal'
  9. import cn from '@/utils/classnames'
  10. import s from '@/app/components/datasets/create/website/index.module.css'
  11. import { fetchDataSources, removeDataSourceApiKeyBinding } from '@/service/datasets'
  12. import type {
  13. DataSourceItem,
  14. } from '@/models/common'
  15. import { useAppContext } from '@/context/app-context'
  16. import {
  17. DataSourceProvider,
  18. } from '@/models/common'
  19. import Toast from '@/app/components/base/toast'
  20. type Props = {
  21. provider: DataSourceProvider
  22. }
  23. const DataSourceWebsite: FC<Props> = ({ provider }) => {
  24. const { t } = useTranslation()
  25. const { isCurrentWorkspaceManager } = useAppContext()
  26. const [sources, setSources] = useState<DataSourceItem[]>([])
  27. const checkSetApiKey = useCallback(async () => {
  28. const res = await fetchDataSources() as any
  29. const list = res.sources
  30. setSources(list)
  31. }, [])
  32. useEffect(() => {
  33. checkSetApiKey()
  34. // eslint-disable-next-line react-hooks/exhaustive-deps
  35. }, [])
  36. const [configTarget, setConfigTarget] = useState<DataSourceProvider | null>(null)
  37. const showConfig = useCallback((provider: DataSourceProvider) => {
  38. setConfigTarget(provider)
  39. }, [setConfigTarget])
  40. const hideConfig = useCallback(() => {
  41. setConfigTarget(null)
  42. }, [setConfigTarget])
  43. const handleAdded = useCallback(() => {
  44. checkSetApiKey()
  45. hideConfig()
  46. }, [checkSetApiKey, hideConfig])
  47. const getIdByProvider = (provider: DataSourceProvider): string | undefined => {
  48. const source = sources.find(item => item.provider === provider)
  49. return source?.id
  50. }
  51. const handleRemove = useCallback((provider: DataSourceProvider) => {
  52. return async () => {
  53. const dataSourceId = getIdByProvider(provider)
  54. if (dataSourceId) {
  55. await removeDataSourceApiKeyBinding(dataSourceId)
  56. setSources(sources.filter(item => item.provider !== provider))
  57. Toast.notify({
  58. type: 'success',
  59. message: t('common.api.remove'),
  60. })
  61. }
  62. }
  63. }, [sources, t])
  64. return (
  65. <>
  66. <Panel
  67. type={DataSourceType.website}
  68. provider={provider}
  69. isConfigured={sources.find(item => item.provider === provider) !== undefined}
  70. onConfigure={() => showConfig(provider)}
  71. readOnly={!isCurrentWorkspaceManager}
  72. configuredList={sources.filter(item => item.provider === provider).map(item => ({
  73. id: item.id,
  74. logo: ({ className }: { className: string }) => (
  75. item.provider === DataSourceProvider.fireCrawl
  76. ? (
  77. <div className={cn(className, 'flex items-center justify-center w-5 h-5 bg-white border border-gray-100 text-xs font-medium text-gray-500 rounded ml-3')}>🔥</div>
  78. )
  79. : (
  80. <div className={cn(className, 'flex items-center justify-center w-5 h-5 bg-white border border-gray-100 text-xs font-medium text-gray-500 rounded ml-3')}>
  81. <span className={s.jinaLogo} />
  82. </div>
  83. )
  84. ),
  85. name: item.provider === DataSourceProvider.fireCrawl ? 'Firecrawl' : 'Jina Reader',
  86. isActive: true,
  87. }))}
  88. onRemove={handleRemove(provider)}
  89. />
  90. {configTarget === DataSourceProvider.fireCrawl && (
  91. <ConfigFirecrawlModal onSaved={handleAdded} onCancel={hideConfig} />
  92. )}
  93. {configTarget === DataSourceProvider.jinaReader && (
  94. <ConfigJinaReaderModal onSaved={handleAdded} onCancel={hideConfig} />
  95. )}
  96. </>
  97. )
  98. }
  99. export default React.memo(DataSourceWebsite)