| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 | 
							- 'use client'
 
- import type { FC } from 'react'
 
- import React, { useMemo, useState } from 'react'
 
- import { createContext, useContext, useContextSelector } from 'use-context-selector'
 
- import { useTranslation } from 'react-i18next'
 
- import { useRouter } from 'next/navigation'
 
- import { RiArrowLeftLine, RiLayoutRight2Line } from '@remixicon/react'
 
- import DocumentPicker from '../../common/document-picker'
 
- import Completed from './completed'
 
- import Embedding from './embedding'
 
- import Metadata from '@/app/components/datasets/metadata/metadata-document'
 
- import { ProcessStatus } from './segment-add'
 
- import BatchModal from './batch-modal'
 
- import style from './style.module.css'
 
- import cn from '@/utils/classnames'
 
- import Loading from '@/app/components/base/loading'
 
- import { ToastContext } from '@/app/components/base/toast'
 
- import type { ChunkingMode, ParentMode, ProcessMode } from '@/models/datasets'
 
- import { useDatasetDetailContext } from '@/context/dataset-detail'
 
- import FloatRightContainer from '@/app/components/base/float-right-container'
 
- import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
 
- import { LayoutRight2LineMod } from '@/app/components/base/icons/src/public/knowledge'
 
- import { useCheckSegmentBatchImportProgress, useChildSegmentListKey, useSegmentBatchImport, useSegmentListKey } from '@/service/knowledge/use-segment'
 
- import { useDocumentDetail, useDocumentMetadata, useInvalidDocumentList } from '@/service/knowledge/use-document'
 
- import { useInvalid } from '@/service/use-base'
 
- type DocumentContextValue = {
 
-   datasetId?: string
 
-   documentId?: string
 
-   docForm: string
 
-   mode?: ProcessMode
 
-   parentMode?: ParentMode
 
- }
 
- export const DocumentContext = createContext<DocumentContextValue>({ docForm: '' })
 
- export const useDocumentContext = (selector: (value: DocumentContextValue) => any) => {
 
-   return useContextSelector(DocumentContext, selector)
 
- }
 
- type DocumentTitleProps = {
 
-   datasetId: string
 
-   extension?: string
 
-   name?: string
 
-   processMode?: ProcessMode
 
-   parent_mode?: ParentMode
 
-   iconCls?: string
 
-   textCls?: string
 
-   wrapperCls?: string
 
- }
 
- export const DocumentTitle: FC<DocumentTitleProps> = ({ datasetId, extension, name, processMode, parent_mode, wrapperCls }) => {
 
-   const router = useRouter()
 
-   return (
 
-     <div className={cn('flex flex-1 items-center justify-start', wrapperCls)}>
 
-       <DocumentPicker
 
-         datasetId={datasetId}
 
-         value={{
 
-           name,
 
-           extension,
 
-           processMode,
 
-           parentMode: parent_mode,
 
-         }}
 
-         onChange={(doc) => {
 
-           router.push(`/datasets/${datasetId}/documents/${doc.id}`)
 
-         }}
 
-       />
 
-     </div>
 
-   )
 
- }
 
- type Props = {
 
-   datasetId: string
 
-   documentId: string
 
- }
 
- const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
 
-   const router = useRouter()
 
-   const { t } = useTranslation()
 
-   const media = useBreakpoints()
 
-   const isMobile = media === MediaType.mobile
 
-   const { notify } = useContext(ToastContext)
 
-   const { dataset } = useDatasetDetailContext()
 
-   const embeddingAvailable = !!dataset?.embedding_available
 
-   const [showMetadata, setShowMetadata] = useState(!isMobile)
 
-   const [newSegmentModalVisible, setNewSegmentModalVisible] = useState(false)
 
-   const [batchModalVisible, setBatchModalVisible] = useState(false)
 
-   const [importStatus, setImportStatus] = useState<ProcessStatus | string>()
 
-   const showNewSegmentModal = () => setNewSegmentModalVisible(true)
 
-   const showBatchModal = () => setBatchModalVisible(true)
 
-   const hideBatchModal = () => setBatchModalVisible(false)
 
-   const resetProcessStatus = () => setImportStatus('')
 
-   const { mutateAsync: checkSegmentBatchImportProgress } = useCheckSegmentBatchImportProgress()
 
-   const checkProcess = async (jobID: string) => {
 
-     await checkSegmentBatchImportProgress({ jobID }, {
 
-       onSuccess: (res) => {
 
-         setImportStatus(res.job_status)
 
-         if (res.job_status === ProcessStatus.WAITING || res.job_status === ProcessStatus.PROCESSING)
 
-           setTimeout(() => checkProcess(res.job_id), 2500)
 
-         if (res.job_status === ProcessStatus.ERROR)
 
-           notify({ type: 'error', message: `${t('datasetDocuments.list.batchModal.runError')}` })
 
-       },
 
-       onError: (e) => {
 
-         notify({ type: 'error', message: `${t('datasetDocuments.list.batchModal.runError')}${'message' in e ? `: ${e.message}` : ''}` })
 
-       },
 
-     })
 
-   }
 
-   const { mutateAsync: segmentBatchImport } = useSegmentBatchImport()
 
-   const runBatch = async (csv: File) => {
 
-     const formData = new FormData()
 
-     formData.append('file', csv)
 
-     await segmentBatchImport({
 
-       url: `/datasets/${datasetId}/documents/${documentId}/segments/batch_import`,
 
-       body: formData,
 
-     }, {
 
-       onSuccess: (res) => {
 
-         setImportStatus(res.job_status)
 
-         checkProcess(res.job_id)
 
-       },
 
-       onError: (e) => {
 
-         notify({ type: 'error', message: `${t('datasetDocuments.list.batchModal.runError')}${'message' in e ? `: ${e.message}` : ''}` })
 
-       },
 
-     })
 
-   }
 
-   const { data: documentDetail, error, refetch: detailMutate } = useDocumentDetail({
 
-     datasetId,
 
-     documentId,
 
-     params: { metadata: 'without' },
 
-   })
 
-   const { data: documentMetadata, error: metadataErr, refetch: metadataMutate } = useDocumentMetadata({
 
-     datasetId,
 
-     documentId,
 
-     params: { metadata: 'only' },
 
-   })
 
-   const backToPrev = () => {
 
-     router.push(`/datasets/${datasetId}/documents`)
 
-   }
 
-   const isDetailLoading = !documentDetail && !error
 
-   const isMetadataLoading = !documentMetadata && !metadataErr
 
-   const embedding = ['queuing', 'indexing', 'paused'].includes((documentDetail?.display_status || '').toLowerCase())
 
-   const invalidChunkList = useInvalid(useSegmentListKey)
 
-   const invalidChildChunkList = useInvalid(useChildSegmentListKey)
 
-   const invalidDocumentList = useInvalidDocumentList(datasetId)
 
-   const handleOperate = (operateName?: string) => {
 
-     invalidDocumentList()
 
-     if (operateName === 'delete') {
 
-       backToPrev()
 
-     }
 
-     else {
 
-       detailMutate()
 
-       // If operation is not rename, refresh the chunk list after 5 seconds
 
-       if (operateName) {
 
-         setTimeout(() => {
 
-           invalidChunkList()
 
-           invalidChildChunkList()
 
-         }, 5000)
 
-       }
 
-     }
 
-   }
 
-   const mode = useMemo(() => {
 
-     return documentDetail?.document_process_rule?.mode
 
-   }, [documentDetail?.document_process_rule])
 
-   const parentMode = useMemo(() => {
 
-     return documentDetail?.document_process_rule?.rules?.parent_mode
 
-   }, [documentDetail?.document_process_rule])
 
-   const isFullDocMode = useMemo(() => {
 
-     return mode === 'hierarchical' && parentMode === 'full-doc'
 
-   }, [mode, parentMode])
 
-   return (
 
-     <DocumentContext.Provider value={{
 
-       datasetId,
 
-       documentId,
 
-       docForm: documentDetail?.doc_form || '',
 
-       mode,
 
-       parentMode,
 
-     }}>
 
-       <div className='flex h-full flex-col bg-background-default'>
 
-         <div className='flex min-h-16 flex-wrap items-center justify-between border-b border-b-divider-subtle py-2.5 pl-3 pr-4'>
 
-           <div onClick={backToPrev} className={'flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-full hover:bg-components-button-tertiary-bg'}>
 
-             <RiArrowLeftLine className='h-4 w-4 text-components-button-ghost-text hover:text-text-tertiary' />
 
-           </div>
 
-           <DocumentTitle
 
-             datasetId={datasetId}
 
-             extension={documentDetail?.data_source_info?.upload_file?.extension}
 
-             name={documentDetail?.name}
 
-             wrapperCls='mr-2'
 
-             parent_mode={parentMode}
 
-             processMode={mode}
 
-           />
 
-           <div className='flex flex-wrap items-center'>
 
-             {/* {embeddingAvailable && documentDetail && !documentDetail.archived && !isFullDocMode && ( */}
 
-             {/*  <> */}
 
-             {/*    <SegmentAdd */}
 
-             {/*      importStatus={importStatus} */}
 
-             {/*      clearProcessStatus={resetProcessStatus} */}
 
-             {/*      showNewSegmentModal={showNewSegmentModal} */}
 
-             {/*      showBatchModal={showBatchModal} */}
 
-             {/*      embedding={embedding} */}
 
-             {/*    /> */}
 
-             {/*    <Divider type='vertical' className='!mx-3 !h-[14px] !bg-divider-regular' /> */}
 
-             {/*  </> */}
 
-             {/* )} */}
 
-             {/* <StatusItem */}
 
-             {/*  status={documentDetail?.display_status || 'available'} */}
 
-             {/*  scene='detail' */}
 
-             {/*  errorMessage={documentDetail?.error || ''} */}
 
-             {/*  textCls='font-semibold text-xs uppercase' */}
 
-             {/*  detail={{ */}
 
-             {/*    enabled: documentDetail?.enabled || false, */}
 
-             {/*    archived: documentDetail?.archived || false, */}
 
-             {/*    id: documentId, */}
 
-             {/*  }} */}
 
-             {/*  datasetId={datasetId} */}
 
-             {/*  onUpdate={handleOperate} */}
 
-             {/* /> */}
 
-             {/* <OperationAction */}
 
-             {/*  scene='detail' */}
 
-             {/*  embeddingAvailable={embeddingAvailable} */}
 
-             {/*  detail={{ */}
 
-             {/*    name: documentDetail?.name || '', */}
 
-             {/*    enabled: documentDetail?.enabled || false, */}
 
-             {/*    archived: documentDetail?.archived || false, */}
 
-             {/*    id: documentId, */}
 
-             {/*    data_source_type: documentDetail?.data_source_type || '', */}
 
-             {/*    doc_form: documentDetail?.doc_form || '', */}
 
-             {/*  }} */}
 
-             {/*  datasetId={datasetId} */}
 
-             {/*  onUpdate={handleOperate} */}
 
-             {/*  className='!w-[200px]' */}
 
-             {/* /> */}
 
-             <button
 
-               className={style.layoutRightIcon}
 
-               onClick={() => setShowMetadata(!showMetadata)}
 
-             >
 
-               {
 
-                 showMetadata
 
-                   ? <LayoutRight2LineMod className='h-4 w-4 text-components-button-secondary-text' />
 
-                   : <RiLayoutRight2Line className='h-4 w-4 text-components-button-secondary-text' />
 
-               }
 
-             </button>
 
-           </div>
 
-         </div>
 
-         <div className='flex flex-1 flex-row' style={{ height: 'calc(100% - 4rem)' }}>
 
-           {isDetailLoading
 
-             ? <Loading type='app' />
 
-             : <div className={cn('flex h-full min-w-0 grow flex-col',
 
-               embedding ? '' : isFullDocMode ? 'relative pl-11 pr-11 pt-4' : 'relative pl-5 pr-11 pt-3',
 
-             )}>
 
-               {embedding
 
-                 ? <Embedding
 
-                   detailUpdate={detailMutate}
 
-                   indexingType={dataset?.indexing_technique}
 
-                   retrievalMethod={dataset?.retrieval_model_dict?.search_method}
 
-                 />
 
-                 : <Completed
 
-                   embeddingAvailable={embeddingAvailable}
 
-                   showNewSegmentModal={newSegmentModalVisible}
 
-                   onNewSegmentModalChange={setNewSegmentModalVisible}
 
-                   importStatus={importStatus}
 
-                   archived={documentDetail?.archived}
 
-                 />
 
-               }
 
-             </div>
 
-           }
 
-           <FloatRightContainer showClose isOpen={showMetadata} onClose={() => setShowMetadata(false)} isMobile={isMobile} panelClassname='!justify-start' footer={null}>
 
-             <Metadata
 
-               className='mr-2 mt-3'
 
-               datasetId={datasetId}
 
-               documentId={documentId}
 
-               docDetail={{ ...documentDetail, ...documentMetadata, doc_type: documentMetadata?.doc_type === 'others' ? '' : documentMetadata?.doc_type } as any}
 
-             />
 
-           </FloatRightContainer>
 
-         </div>
 
-         <BatchModal
 
-           isShow={batchModalVisible}
 
-           onCancel={hideBatchModal}
 
-           onConfirm={runBatch}
 
-           docForm={documentDetail?.doc_form as ChunkingMode}
 
-         />
 
-       </div>
 
-     </DocumentContext.Provider>
 
-   )
 
- }
 
- export default DocumentDetail
 
 
  |