mirror of
https://github.com/langgenius/dify.git
synced 2026-03-31 18:00:55 -04:00
fix(web): fix document detail page status inconsistency with list page (#33740)
Co-authored-by: fisher <1186907891@qq.com> Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Co-authored-by: Crazywoola <100913391+crazywoola@users.noreply.github.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { DataSourceInfo, FileItem, FullDocumentDetail, LegacyDataSourceInfo } from '@/models/datasets'
|
||||
import type { DataSourceInfo, DocumentDisplayStatus, FileItem, FullDocumentDetail, LegacyDataSourceInfo } from '@/models/datasets'
|
||||
import * as React from 'react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import FloatRightContainer from '@/app/components/base/float-right-container'
|
||||
@@ -11,7 +11,7 @@ import Toast from '@/app/components/base/toast'
|
||||
import Metadata from '@/app/components/datasets/metadata/metadata-document'
|
||||
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { ChunkingMode } from '@/models/datasets'
|
||||
import { ChunkingMode, DisplayStatusList } from '@/models/datasets'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { useDocumentDetail, useDocumentMetadata, useInvalidDocumentList } from '@/service/knowledge/use-document'
|
||||
import { useCheckSegmentBatchImportProgress, useChildSegmentListKey, useSegmentBatchImport, useSegmentListKey } from '@/service/knowledge/use-segment'
|
||||
@@ -32,6 +32,14 @@ type DocumentDetailProps = {
|
||||
documentId: string
|
||||
}
|
||||
|
||||
const NON_TERMINAL_DISPLAY_STATUSES = new Set<typeof DisplayStatusList[number]>(
|
||||
DisplayStatusList.filter(s => s === 'queuing' || s === 'indexing' || s === 'paused'),
|
||||
)
|
||||
|
||||
const isLegacyDataSourceInfo = (info?: DataSourceInfo): info is LegacyDataSourceInfo => {
|
||||
return !!info && 'upload_file' in info
|
||||
}
|
||||
|
||||
const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
||||
const router = useRouter()
|
||||
const searchParams = useSearchParams()
|
||||
@@ -89,6 +97,12 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
||||
datasetId,
|
||||
documentId,
|
||||
params: { metadata: 'without' },
|
||||
refetchInterval: (query) => {
|
||||
const status = query.state.data?.display_status
|
||||
if (!status || NON_TERMINAL_DISPLAY_STATUSES.has(status))
|
||||
return 2500
|
||||
return false
|
||||
},
|
||||
})
|
||||
|
||||
const { data: documentMetadata } = useDocumentMetadata({
|
||||
@@ -97,19 +111,15 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
||||
params: { metadata: 'only' },
|
||||
})
|
||||
|
||||
const backToPrev = () => {
|
||||
const backToPrev = useCallback(() => {
|
||||
const queryString = searchParams.toString()
|
||||
const backPath = `/datasets/${datasetId}/documents${queryString ? `?${queryString}` : ''}`
|
||||
router.push(backPath)
|
||||
}
|
||||
}, [searchParams, datasetId, router])
|
||||
|
||||
const isDetailLoading = !documentDetail && !error
|
||||
|
||||
const embedding = ['queuing', 'indexing', 'paused'].includes((documentDetail?.display_status || '').toLowerCase())
|
||||
|
||||
const isLegacyDataSourceInfo = (info?: DataSourceInfo): info is LegacyDataSourceInfo => {
|
||||
return !!info && 'upload_file' in info
|
||||
}
|
||||
const embedding = NON_TERMINAL_DISPLAY_STATUSES.has(documentDetail?.display_status as DocumentDisplayStatus)
|
||||
|
||||
const documentUploadFile = useMemo(() => {
|
||||
if (!documentDetail?.data_source_info)
|
||||
@@ -123,7 +133,7 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
||||
const invalidChildChunkList = useInvalid(useChildSegmentListKey)
|
||||
const invalidDocumentList = useInvalidDocumentList(datasetId)
|
||||
|
||||
const handleOperate = (operateName?: string) => {
|
||||
const handleOperate = useCallback((operateName?: string) => {
|
||||
invalidDocumentList()
|
||||
if (operateName === 'delete') {
|
||||
backToPrev()
|
||||
@@ -138,7 +148,7 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
||||
}, 5000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [invalidDocumentList, backToPrev, detailMutate, invalidChunkList, invalidChildChunkList])
|
||||
|
||||
const parentMode = useMemo(() => {
|
||||
return documentDetail?.document_process_rule?.rules?.parent_mode || documentDetail?.dataset_process_rule?.rules?.parent_mode || 'paragraph'
|
||||
@@ -149,19 +159,41 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
||||
return chunkMode === ChunkingMode.parentChild && parentMode === 'full-doc'
|
||||
}, [documentDetail?.doc_form, parentMode])
|
||||
|
||||
const contextValue = useMemo(() => ({
|
||||
datasetId,
|
||||
documentId,
|
||||
docForm: documentDetail?.doc_form as ChunkingMode,
|
||||
parentMode,
|
||||
}), [datasetId, documentId, documentDetail?.doc_form, parentMode])
|
||||
|
||||
const statusDetail = useMemo(() => ({
|
||||
enabled: documentDetail?.enabled || false,
|
||||
archived: documentDetail?.archived || false,
|
||||
id: documentId,
|
||||
}), [documentDetail?.enabled, documentDetail?.archived, documentId])
|
||||
|
||||
const operationsDetail = useMemo(() => ({
|
||||
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 || '',
|
||||
}), [documentDetail?.name, documentDetail?.enabled, documentDetail?.archived, documentId, documentDetail?.data_source_type, documentDetail?.doc_form])
|
||||
|
||||
const docDetail = useMemo(() => ({
|
||||
...documentDetail,
|
||||
...documentMetadata,
|
||||
doc_type: documentMetadata?.doc_type === 'others' ? '' : documentMetadata?.doc_type,
|
||||
} as FullDocumentDetail), [documentDetail, documentMetadata])
|
||||
|
||||
const backButtonLabel = t('operation.back', { ns: 'common' })
|
||||
const metadataToggleLabel = `${showMetadata
|
||||
? t('operation.close', { ns: 'common' })
|
||||
: t('operation.view', { ns: 'common' })} ${t('metadata.title', { ns: 'datasetDocuments' })}`
|
||||
|
||||
return (
|
||||
<DocumentContext.Provider value={{
|
||||
datasetId,
|
||||
documentId,
|
||||
docForm: documentDetail?.doc_form as ChunkingMode,
|
||||
parentMode,
|
||||
}}
|
||||
>
|
||||
<DocumentContext.Provider value={contextValue}>
|
||||
<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">
|
||||
<button
|
||||
@@ -198,30 +230,21 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
||||
<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}
|
||||
/>
|
||||
{documentDetail && (
|
||||
<StatusItem
|
||||
status={documentDetail.display_status || 'available'}
|
||||
scene="detail"
|
||||
errorMessage={documentDetail.error || ''}
|
||||
textCls="font-semibold text-xs uppercase"
|
||||
detail={statusDetail}
|
||||
datasetId={datasetId}
|
||||
onUpdate={handleOperate}
|
||||
/>
|
||||
)}
|
||||
<Operations
|
||||
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 || '',
|
||||
}}
|
||||
detail={operationsDetail}
|
||||
datasetId={datasetId}
|
||||
onUpdate={handleOperate}
|
||||
className="!w-[200px]"
|
||||
@@ -272,7 +295,7 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
||||
className="mr-2 mt-3"
|
||||
datasetId={datasetId}
|
||||
documentId={documentId}
|
||||
docDetail={{ ...documentDetail, ...documentMetadata, doc_type: documentMetadata?.doc_type === 'others' ? '' : documentMetadata?.doc_type } as FullDocumentDetail}
|
||||
docDetail={docDetail}
|
||||
/>
|
||||
</FloatRightContainer>
|
||||
</div>
|
||||
|
||||
@@ -133,15 +133,19 @@ export const useSyncWebsite = () => {
|
||||
}
|
||||
|
||||
const useDocumentDetailKey = [NAME_SPACE, 'documentDetail', 'withoutMetaData']
|
||||
type DocumentDetailRefetchInterval = UseQueryOptions<DocumentDetailResponse>['refetchInterval']
|
||||
|
||||
export const useDocumentDetail = (payload: {
|
||||
datasetId: string
|
||||
documentId: string
|
||||
params: { metadata: MetadataType }
|
||||
refetchInterval?: DocumentDetailRefetchInterval
|
||||
}) => {
|
||||
const { datasetId, documentId, params } = payload
|
||||
const { datasetId, documentId, params, refetchInterval } = payload
|
||||
return useQuery<DocumentDetailResponse>({
|
||||
queryKey: [...useDocumentDetailKey, 'withoutMetaData', datasetId, documentId, params],
|
||||
queryFn: () => get<DocumentDetailResponse>(`/datasets/${datasetId}/documents/${documentId}`, { params }),
|
||||
refetchInterval,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user