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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. // eslint-disable-next-line react-hooks/exhaustive-deps
  61. }, [])
  62. const handleOnConfig = useCallback(() => {
  63. setShowAccountSettingModal({
  64. payload: 'data-source',
  65. onCancelCallback: checkSetApiKey,
  66. })
  67. }, [checkSetApiKey, setShowAccountSettingModal])
  68. if (!isLoaded)
  69. return null
  70. const source = sources.find(source => source.provider === selectedProvider)
  71. return (
  72. <div>
  73. <div className="mb-4">
  74. <div className="system-md-medium mb-2 text-text-secondary">
  75. {t('datasetCreation.stepOne.website.chooseProvider')}
  76. </div>
  77. <div className="flex space-x-2">
  78. {ENABLE_WEBSITE_JINAREADER && <button
  79. className={cn('flex items-center justify-center rounded-lg px-4 py-2',
  80. selectedProvider === DataSourceProvider.jinaReader
  81. ? 'system-sm-medium border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary'
  82. : `system-sm-regular border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary
  83. hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs hover:shadow-shadow-shadow-3`,
  84. )}
  85. onClick={() => setSelectedProvider(DataSourceProvider.jinaReader)}
  86. >
  87. <span className={cn(s.jinaLogo, 'mr-2')}/>
  88. <span>Jina Reader</span>
  89. </button>}
  90. {ENABLE_WEBSITE_FIRECRAWL && <button
  91. className={cn('rounded-lg px-4 py-2',
  92. selectedProvider === DataSourceProvider.fireCrawl
  93. ? 'system-sm-medium border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary'
  94. : `system-sm-regular border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary
  95. hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs hover:shadow-shadow-shadow-3`,
  96. )}
  97. onClick={() => setSelectedProvider(DataSourceProvider.fireCrawl)}
  98. >
  99. 🔥 Firecrawl
  100. </button>}
  101. {ENABLE_WEBSITE_WATERCRAWL && <button
  102. className={cn('flex items-center justify-center rounded-lg px-4 py-2',
  103. selectedProvider === DataSourceProvider.waterCrawl
  104. ? 'system-sm-medium border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary'
  105. : `system-sm-regular border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary
  106. hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs hover:shadow-shadow-shadow-3`,
  107. )}
  108. onClick={() => setSelectedProvider(DataSourceProvider.waterCrawl)}
  109. >
  110. <span className={cn(s.watercrawlLogo, 'mr-2')}/>
  111. <span>WaterCrawl</span>
  112. </button>}
  113. </div>
  114. </div>
  115. {source && selectedProvider === DataSourceProvider.fireCrawl && (
  116. <Firecrawl
  117. onPreview={onPreview}
  118. checkedCrawlResult={checkedCrawlResult}
  119. onCheckedCrawlResultChange={onCheckedCrawlResultChange}
  120. onJobIdChange={onJobIdChange}
  121. crawlOptions={crawlOptions}
  122. onCrawlOptionsChange={onCrawlOptionsChange}
  123. />
  124. )}
  125. {source && selectedProvider === DataSourceProvider.waterCrawl && (
  126. <Watercrawl
  127. onPreview={onPreview}
  128. checkedCrawlResult={checkedCrawlResult}
  129. onCheckedCrawlResultChange={onCheckedCrawlResultChange}
  130. onJobIdChange={onJobIdChange}
  131. crawlOptions={crawlOptions}
  132. onCrawlOptionsChange={onCrawlOptionsChange}
  133. />
  134. )}
  135. {source && selectedProvider === DataSourceProvider.jinaReader && (
  136. <JinaReader
  137. onPreview={onPreview}
  138. checkedCrawlResult={checkedCrawlResult}
  139. onCheckedCrawlResultChange={onCheckedCrawlResultChange}
  140. onJobIdChange={onJobIdChange}
  141. crawlOptions={crawlOptions}
  142. onCrawlOptionsChange={onCrawlOptionsChange}
  143. />
  144. )}
  145. {!source && (
  146. <NoData onConfig={handleOnConfig} provider={selectedProvider}/>
  147. )}
  148. </div>
  149. )
  150. }
  151. export default React.memo(Website)