index.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. 'use client'
  2. import React, { useCallback, useEffect, useState } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import AppUnavailable from '../../base/app-unavailable'
  5. import StepsNavBar from './steps-nav-bar'
  6. import StepOne from './step-one'
  7. import StepTwo from './step-two'
  8. import StepThree from './step-three'
  9. import { DataSourceType } from '@/models/datasets'
  10. import type { DataSet, FileItem, createDocumentResponse } from '@/models/datasets'
  11. import { fetchDataSource } from '@/service/common'
  12. import { fetchDatasetDetail } from '@/service/datasets'
  13. import type { NotionPage } from '@/models/common'
  14. import { useModalContext } from '@/context/modal-context'
  15. import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
  16. type DatasetUpdateFormProps = {
  17. datasetId?: string
  18. }
  19. const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
  20. const { t } = useTranslation()
  21. const { setShowAccountSettingModal } = useModalContext()
  22. const [hasConnection, setHasConnection] = useState(true)
  23. const [dataSourceType, setDataSourceType] = useState<DataSourceType>(DataSourceType.FILE)
  24. const [step, setStep] = useState(1)
  25. const [indexingTypeCache, setIndexTypeCache] = useState('')
  26. const [fileList, setFiles] = useState<FileItem[]>([])
  27. const [result, setResult] = useState<createDocumentResponse | undefined>()
  28. const [hasError, setHasError] = useState(false)
  29. const { data: embeddingsDefaultModel } = useDefaultModel(2)
  30. const [notionPages, setNotionPages] = useState<NotionPage[]>([])
  31. const updateNotionPages = (value: NotionPage[]) => {
  32. setNotionPages(value)
  33. }
  34. const updateFileList = (preparedFiles: FileItem[]) => {
  35. setFiles(preparedFiles)
  36. }
  37. const updateFile = (fileItem: FileItem, progress: number, list: FileItem[]) => {
  38. const targetIndex = list.findIndex(file => file.fileID === fileItem.fileID)
  39. list[targetIndex] = {
  40. ...list[targetIndex],
  41. progress,
  42. }
  43. setFiles([...list])
  44. // use follow code would cause dirty list update problem
  45. // const newList = list.map((file) => {
  46. // if (file.fileID === fileItem.fileID) {
  47. // return {
  48. // ...fileItem,
  49. // progress,
  50. // }
  51. // }
  52. // return file
  53. // })
  54. // setFiles(newList)
  55. }
  56. const updateIndexingTypeCache = (type: string) => {
  57. setIndexTypeCache(type)
  58. }
  59. const updateResultCache = (res?: createDocumentResponse) => {
  60. setResult(res)
  61. }
  62. const nextStep = useCallback(() => {
  63. setStep(step + 1)
  64. }, [step, setStep])
  65. const changeStep = useCallback((delta: number) => {
  66. setStep(step + delta)
  67. }, [step, setStep])
  68. const checkNotionConnection = async () => {
  69. const { data } = await fetchDataSource({ url: '/data-source/integrates' })
  70. const hasConnection = data.filter(item => item.provider === 'notion') || []
  71. setHasConnection(hasConnection.length > 0)
  72. }
  73. useEffect(() => {
  74. checkNotionConnection()
  75. }, [])
  76. const [detail, setDetail] = useState<DataSet | null>(null)
  77. useEffect(() => {
  78. (async () => {
  79. if (datasetId) {
  80. try {
  81. const detail = await fetchDatasetDetail(datasetId)
  82. setDetail(detail)
  83. }
  84. catch (e) {
  85. setHasError(true)
  86. }
  87. }
  88. })()
  89. }, [datasetId])
  90. if (hasError)
  91. return <AppUnavailable code={500} unknownReason={t('datasetCreation.error.unavailable') as string} />
  92. return (
  93. <div className='flex' style={{ height: 'calc(100vh - 56px)' }}>
  94. <div className="flex flex-col w-11 sm:w-56 overflow-y-auto bg-white border-r border-gray-200 shrink-0">
  95. <StepsNavBar step={step} datasetId={datasetId} />
  96. </div>
  97. <div className="grow bg-white">
  98. {step === 1 && <StepOne
  99. hasConnection={hasConnection}
  100. onSetting={() => setShowAccountSettingModal({ payload: 'data-source' })}
  101. datasetId={datasetId}
  102. dataSourceType={dataSourceType}
  103. dataSourceTypeDisable={!!detail?.data_source_type}
  104. changeType={setDataSourceType}
  105. files={fileList}
  106. updateFile={updateFile}
  107. updateFileList={updateFileList}
  108. notionPages={notionPages}
  109. updateNotionPages={updateNotionPages}
  110. onStepChange={nextStep}
  111. />}
  112. {(step === 2 && (!datasetId || (datasetId && !!detail))) && <StepTwo
  113. hasSetAPIKEY={!!embeddingsDefaultModel}
  114. onSetting={() => setShowAccountSettingModal({ payload: 'provider' })}
  115. indexingType={detail?.indexing_technique}
  116. datasetId={datasetId}
  117. dataSourceType={dataSourceType}
  118. files={fileList.map(file => file.file)}
  119. notionPages={notionPages}
  120. onStepChange={changeStep}
  121. updateIndexingTypeCache={updateIndexingTypeCache}
  122. updateResultCache={updateResultCache}
  123. />}
  124. {step === 3 && <StepThree
  125. datasetId={datasetId}
  126. datasetName={detail?.name}
  127. indexingType={detail?.indexing_technique || indexingTypeCache}
  128. creationCache={result}
  129. />}
  130. </div>
  131. </div>
  132. )
  133. }
  134. export default DatasetUpdateForm