index.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 s from './index.module.css'
  6. import NoData from './no-data'
  7. import Firecrawl from './firecrawl'
  8. import JinaReader from './jina-reader'
  9. import cn from '@/utils/classnames'
  10. import { useModalContext } from '@/context/modal-context'
  11. import type { CrawlOptions, CrawlResultItem } from '@/models/datasets'
  12. import { fetchDataSources } from '@/service/datasets'
  13. import { type DataSourceItem, DataSourceProvider } from '@/models/common'
  14. type Props = {
  15. onPreview: (payload: CrawlResultItem) => void
  16. checkedCrawlResult: CrawlResultItem[]
  17. onCheckedCrawlResultChange: (payload: CrawlResultItem[]) => void
  18. onCrawlProviderChange: (provider: DataSourceProvider) => void
  19. onJobIdChange: (jobId: string) => void
  20. crawlOptions: CrawlOptions
  21. onCrawlOptionsChange: (payload: CrawlOptions) => void
  22. }
  23. const Website: FC<Props> = ({
  24. onPreview,
  25. checkedCrawlResult,
  26. onCheckedCrawlResultChange,
  27. onCrawlProviderChange,
  28. onJobIdChange,
  29. crawlOptions,
  30. onCrawlOptionsChange,
  31. }) => {
  32. const { t } = useTranslation()
  33. const { setShowAccountSettingModal } = useModalContext()
  34. const [isLoaded, setIsLoaded] = useState(false)
  35. const [selectedProvider, setSelectedProvider] = useState<DataSourceProvider>(DataSourceProvider.jinaReader)
  36. const [sources, setSources] = useState<DataSourceItem[]>([])
  37. useEffect(() => {
  38. onCrawlProviderChange(selectedProvider)
  39. }, [selectedProvider, onCrawlProviderChange])
  40. const checkSetApiKey = useCallback(async () => {
  41. const res = await fetchDataSources() as any
  42. setSources(res.sources)
  43. // If users have configured one of the providers, select it.
  44. const availableProviders = res.sources.filter((item: DataSourceItem) =>
  45. [DataSourceProvider.jinaReader, DataSourceProvider.fireCrawl].includes(item.provider),
  46. )
  47. if (availableProviders.length > 0)
  48. setSelectedProvider(availableProviders[0].provider)
  49. }, [])
  50. useEffect(() => {
  51. checkSetApiKey().then(() => {
  52. setIsLoaded(true)
  53. })
  54. // eslint-disable-next-line react-hooks/exhaustive-deps
  55. }, [])
  56. const handleOnConfig = useCallback(() => {
  57. setShowAccountSettingModal({
  58. payload: 'data-source',
  59. onCancelCallback: checkSetApiKey,
  60. })
  61. }, [checkSetApiKey, setShowAccountSettingModal])
  62. if (!isLoaded)
  63. return null
  64. return (
  65. <div>
  66. <div className="mb-4">
  67. <div className="system-md-medium mb-2 text-text-secondary">
  68. {t('datasetCreation.stepOne.website.chooseProvider')}
  69. </div>
  70. <div className="flex space-x-2">
  71. <button
  72. className={cn('flex items-center justify-center rounded-lg px-4 py-2',
  73. selectedProvider === DataSourceProvider.jinaReader
  74. ? 'system-sm-medium border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary'
  75. : `system-sm-regular border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary
  76. hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs hover:shadow-shadow-shadow-3`,
  77. )}
  78. onClick={() => setSelectedProvider(DataSourceProvider.jinaReader)}
  79. >
  80. <span className={cn(s.jinaLogo, 'mr-2')} />
  81. <span>Jina Reader</span>
  82. </button>
  83. <button
  84. className={cn('rounded-lg px-4 py-2',
  85. selectedProvider === DataSourceProvider.fireCrawl
  86. ? 'system-sm-medium border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary'
  87. : `system-sm-regular border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary
  88. hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs hover:shadow-shadow-shadow-3`,
  89. )}
  90. onClick={() => setSelectedProvider(DataSourceProvider.fireCrawl)}
  91. >
  92. 🔥 Firecrawl
  93. </button>
  94. </div>
  95. </div>
  96. {
  97. selectedProvider === DataSourceProvider.fireCrawl
  98. ? sources.find(source => source.provider === DataSourceProvider.fireCrawl)
  99. ? (
  100. <Firecrawl
  101. onPreview={onPreview}
  102. checkedCrawlResult={checkedCrawlResult}
  103. onCheckedCrawlResultChange={onCheckedCrawlResultChange}
  104. onJobIdChange={onJobIdChange}
  105. crawlOptions={crawlOptions}
  106. onCrawlOptionsChange={onCrawlOptionsChange}
  107. />
  108. )
  109. : (
  110. <NoData onConfig={handleOnConfig} provider={selectedProvider} />
  111. )
  112. : sources.find(source => source.provider === DataSourceProvider.jinaReader)
  113. ? (
  114. <JinaReader
  115. onPreview={onPreview}
  116. checkedCrawlResult={checkedCrawlResult}
  117. onCheckedCrawlResultChange={onCheckedCrawlResultChange}
  118. onJobIdChange={onJobIdChange}
  119. crawlOptions={crawlOptions}
  120. onCrawlOptionsChange={onCrawlOptionsChange}
  121. />
  122. )
  123. : (
  124. <NoData onConfig={handleOnConfig} provider={selectedProvider} />
  125. )
  126. }
  127. </div>
  128. )
  129. }
  130. export default React.memo(Website)