index.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. 'use client'
  2. import React, { useMemo, useState } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import cn from 'classnames'
  5. import FilePreview from '../file-preview'
  6. import FileUploader from '../file-uploader'
  7. import NotionPagePreview from '../notion-page-preview'
  8. import EmptyDatasetCreationModal from '../empty-dataset-creation-modal'
  9. import s from './index.module.css'
  10. import type { File } from '@/models/datasets'
  11. import type { DataSourceNotionPage } from '@/models/common'
  12. import { DataSourceType } from '@/models/datasets'
  13. import Button from '@/app/components/base/button'
  14. import { NotionPageSelector } from '@/app/components/base/notion-page-selector'
  15. import { useDatasetDetailContext } from '@/context/dataset-detail'
  16. type IStepOneProps = {
  17. datasetId?: string
  18. dataSourceType?: DataSourceType
  19. dataSourceTypeDisable: Boolean
  20. hasConnection: boolean
  21. onSetting: () => void
  22. files: any[]
  23. updateFileList: (files: any[]) => void
  24. updateFile: (fileItem: any, progress: number, list: any[]) => void
  25. notionPages?: any[]
  26. updateNotionPages: (value: any[]) => void
  27. onStepChange: () => void
  28. changeType: (type: DataSourceType) => void
  29. }
  30. type Page = DataSourceNotionPage & { workspace_id: string }
  31. type NotionConnectorProps = {
  32. onSetting: () => void
  33. }
  34. export const NotionConnector = ({ onSetting }: NotionConnectorProps) => {
  35. const { t } = useTranslation()
  36. return (
  37. <div className={s.notionConnectionTip}>
  38. <span className={s.notionIcon}/>
  39. <div className={s.title}>{t('datasetCreation.stepOne.notionSyncTitle')}</div>
  40. <div className={s.tip}>{t('datasetCreation.stepOne.notionSyncTip')}</div>
  41. <Button className='h-8' type='primary' onClick={onSetting}>{t('datasetCreation.stepOne.connect')}</Button>
  42. </div>
  43. )
  44. }
  45. const StepOne = ({
  46. datasetId,
  47. dataSourceType,
  48. dataSourceTypeDisable,
  49. changeType,
  50. hasConnection,
  51. onSetting,
  52. onStepChange,
  53. files,
  54. updateFileList,
  55. updateFile,
  56. notionPages = [],
  57. updateNotionPages,
  58. }: IStepOneProps) => {
  59. const { dataset } = useDatasetDetailContext()
  60. const [showModal, setShowModal] = useState(false)
  61. const [currentFile, setCurrentFile] = useState<File | undefined>()
  62. const [currentNotionPage, setCurrentNotionPage] = useState<Page | undefined>()
  63. const { t } = useTranslation()
  64. const modalShowHandle = () => setShowModal(true)
  65. const modalCloseHandle = () => setShowModal(false)
  66. const updateCurrentFile = (file: File) => {
  67. setCurrentFile(file)
  68. }
  69. const hideFilePreview = () => {
  70. setCurrentFile(undefined)
  71. }
  72. const updateCurrentPage = (page: Page) => {
  73. setCurrentNotionPage(page)
  74. }
  75. const hideNotionPagePreview = () => {
  76. setCurrentNotionPage(undefined)
  77. }
  78. const shouldShowDataSourceTypeList = !datasetId || (datasetId && !dataset?.data_source_type)
  79. const nextDisabled = useMemo(() => {
  80. if (!files.length)
  81. return true
  82. if (files.some(file => !file.file.id))
  83. return true
  84. return false
  85. }, [files])
  86. return (
  87. <div className='flex w-full h-full'>
  88. <div className='grow overflow-y-auto relative'>
  89. {
  90. shouldShowDataSourceTypeList && (
  91. <div className={s.stepHeader}>{t('datasetCreation.steps.one')}</div>
  92. )
  93. }
  94. <div className={s.form}>
  95. {
  96. shouldShowDataSourceTypeList && (
  97. <div className={s.dataSourceTypeList}>
  98. <div
  99. className={cn(
  100. s.dataSourceItem,
  101. dataSourceType === DataSourceType.FILE && s.active,
  102. dataSourceTypeDisable && dataSourceType !== DataSourceType.FILE && s.disabled,
  103. )}
  104. onClick={() => {
  105. if (dataSourceTypeDisable)
  106. return
  107. changeType(DataSourceType.FILE)
  108. hideFilePreview()
  109. hideNotionPagePreview()
  110. }}
  111. >
  112. <span className={cn(s.datasetIcon)} />
  113. {t('datasetCreation.stepOne.dataSourceType.file')}
  114. </div>
  115. <div
  116. className={cn(
  117. s.dataSourceItem,
  118. dataSourceType === DataSourceType.NOTION && s.active,
  119. dataSourceTypeDisable && dataSourceType !== DataSourceType.NOTION && s.disabled,
  120. )}
  121. onClick={() => {
  122. if (dataSourceTypeDisable)
  123. return
  124. changeType(DataSourceType.NOTION)
  125. hideFilePreview()
  126. hideNotionPagePreview()
  127. }}
  128. >
  129. <span className={cn(s.datasetIcon, s.notion)} />
  130. {t('datasetCreation.stepOne.dataSourceType.notion')}
  131. </div>
  132. <div
  133. className={cn(s.dataSourceItem, s.disabled, dataSourceType === DataSourceType.WEB && s.active)}
  134. // onClick={() => changeType(DataSourceType.WEB)}
  135. >
  136. <span className={s.comingTag}>Coming soon</span>
  137. <span className={cn(s.datasetIcon, s.web)} />
  138. {t('datasetCreation.stepOne.dataSourceType.web')}
  139. </div>
  140. </div>
  141. )
  142. }
  143. {dataSourceType === DataSourceType.FILE && (
  144. <>
  145. <FileUploader
  146. fileList={files}
  147. titleClassName={!shouldShowDataSourceTypeList ? 'mt-[30px] !mb-[44px] !text-lg !font-semibold !text-gray-900' : undefined}
  148. prepareFileList={updateFileList}
  149. onFileListUpdate={updateFileList}
  150. onFileUpdate={updateFile}
  151. onPreview={updateCurrentFile}
  152. />
  153. <Button disabled={nextDisabled} className={s.submitButton} type='primary' onClick={onStepChange}>{t('datasetCreation.stepOne.button')}</Button>
  154. </>
  155. )}
  156. {dataSourceType === DataSourceType.NOTION && (
  157. <>
  158. {!hasConnection && <NotionConnector onSetting={onSetting} />}
  159. {hasConnection && (
  160. <>
  161. <div className='mb-8 w-[640px]'>
  162. <NotionPageSelector value={notionPages.map(page => page.page_id)} onSelect={updateNotionPages} onPreview={updateCurrentPage} />
  163. </div>
  164. <Button disabled={!notionPages.length} className={s.submitButton} type='primary' onClick={onStepChange}>{t('datasetCreation.stepOne.button')}</Button>
  165. </>
  166. )}
  167. </>
  168. )}
  169. {!datasetId && (
  170. <>
  171. <div className={s.dividerLine} />
  172. <div onClick={modalShowHandle} className={s.OtherCreationOption}>{t('datasetCreation.stepOne.emptyDatasetCreation')}</div>
  173. </>
  174. )}
  175. </div>
  176. <EmptyDatasetCreationModal show={showModal} onHide={modalCloseHandle} />
  177. </div>
  178. {currentFile && <FilePreview file={currentFile} hidePreview={hideFilePreview} />}
  179. {currentNotionPage && <NotionPagePreview currentPage={currentNotionPage} hidePreview={hideNotionPagePreview} />}
  180. </div>
  181. )
  182. }
  183. export default StepOne