You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.tsx 6.7KB

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