index.tsx 5.5 KB

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