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.6KB

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. type Props = {
  16. onPreview: (payload: CrawlResultItem) => void
  17. checkedCrawlResult: CrawlResultItem[]
  18. onCheckedCrawlResultChange: (payload: CrawlResultItem[]) => void
  19. onCrawlProviderChange: (provider: DataSourceProvider) => void
  20. onJobIdChange: (jobId: string) => void
  21. crawlOptions: CrawlOptions
  22. onCrawlOptionsChange: (payload: CrawlOptions) => void
  23. }
  24. const Website: FC<Props> = ({
  25. onPreview,
  26. checkedCrawlResult,
  27. onCheckedCrawlResultChange,
  28. onCrawlProviderChange,
  29. onJobIdChange,
  30. crawlOptions,
  31. onCrawlOptionsChange,
  32. }) => {
  33. const { t } = useTranslation()
  34. const { setShowAccountSettingModal } = useModalContext()
  35. const [isLoaded, setIsLoaded] = useState(false)
  36. const [selectedProvider, setSelectedProvider] = useState<DataSourceProvider>(DataSourceProvider.jinaReader)
  37. const [sources, setSources] = useState<DataSourceItem[]>([])
  38. useEffect(() => {
  39. onCrawlProviderChange(selectedProvider)
  40. }, [selectedProvider, onCrawlProviderChange])
  41. const checkSetApiKey = useCallback(async () => {
  42. const res = await fetchDataSources() as any
  43. setSources(res.sources)
  44. // If users have configured one of the providers, select it.
  45. const availableProviders = res.sources.filter((item: DataSourceItem) =>
  46. [
  47. DataSourceProvider.jinaReader,
  48. DataSourceProvider.fireCrawl,
  49. DataSourceProvider.waterCrawl,
  50. ].includes(item.provider),
  51. )
  52. if (availableProviders.length > 0)
  53. setSelectedProvider(availableProviders[0].provider)
  54. }, [])
  55. useEffect(() => {
  56. checkSetApiKey().then(() => {
  57. setIsLoaded(true)
  58. })
  59. // eslint-disable-next-line react-hooks/exhaustive-deps
  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. <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. <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. <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)