mirror of
https://github.com/langgenius/dify.git
synced 2026-04-05 19:52:03 +08: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'
|
'use client'
|
||||||
import type { FC } from 'react'
|
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 * as React from 'react'
|
||||||
import { useMemo, useState } from 'react'
|
import { useCallback, useMemo, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Divider from '@/app/components/base/divider'
|
import Divider from '@/app/components/base/divider'
|
||||||
import FloatRightContainer from '@/app/components/base/float-right-container'
|
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 Metadata from '@/app/components/datasets/metadata/metadata-document'
|
||||||
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
|
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
|
||||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
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 { useRouter, useSearchParams } from '@/next/navigation'
|
||||||
import { useDocumentDetail, useDocumentMetadata, useInvalidDocumentList } from '@/service/knowledge/use-document'
|
import { useDocumentDetail, useDocumentMetadata, useInvalidDocumentList } from '@/service/knowledge/use-document'
|
||||||
import { useCheckSegmentBatchImportProgress, useChildSegmentListKey, useSegmentBatchImport, useSegmentListKey } from '@/service/knowledge/use-segment'
|
import { useCheckSegmentBatchImportProgress, useChildSegmentListKey, useSegmentBatchImport, useSegmentListKey } from '@/service/knowledge/use-segment'
|
||||||
@@ -32,6 +32,14 @@ type DocumentDetailProps = {
|
|||||||
documentId: string
|
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 DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
@@ -89,6 +97,12 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
|||||||
datasetId,
|
datasetId,
|
||||||
documentId,
|
documentId,
|
||||||
params: { metadata: 'without' },
|
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({
|
const { data: documentMetadata } = useDocumentMetadata({
|
||||||
@@ -97,19 +111,15 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
|||||||
params: { metadata: 'only' },
|
params: { metadata: 'only' },
|
||||||
})
|
})
|
||||||
|
|
||||||
const backToPrev = () => {
|
const backToPrev = useCallback(() => {
|
||||||
const queryString = searchParams.toString()
|
const queryString = searchParams.toString()
|
||||||
const backPath = `/datasets/${datasetId}/documents${queryString ? `?${queryString}` : ''}`
|
const backPath = `/datasets/${datasetId}/documents${queryString ? `?${queryString}` : ''}`
|
||||||
router.push(backPath)
|
router.push(backPath)
|
||||||
}
|
}, [searchParams, datasetId, router])
|
||||||
|
|
||||||
const isDetailLoading = !documentDetail && !error
|
const isDetailLoading = !documentDetail && !error
|
||||||
|
|
||||||
const embedding = ['queuing', 'indexing', 'paused'].includes((documentDetail?.display_status || '').toLowerCase())
|
const embedding = NON_TERMINAL_DISPLAY_STATUSES.has(documentDetail?.display_status as DocumentDisplayStatus)
|
||||||
|
|
||||||
const isLegacyDataSourceInfo = (info?: DataSourceInfo): info is LegacyDataSourceInfo => {
|
|
||||||
return !!info && 'upload_file' in info
|
|
||||||
}
|
|
||||||
|
|
||||||
const documentUploadFile = useMemo(() => {
|
const documentUploadFile = useMemo(() => {
|
||||||
if (!documentDetail?.data_source_info)
|
if (!documentDetail?.data_source_info)
|
||||||
@@ -123,7 +133,7 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
|||||||
const invalidChildChunkList = useInvalid(useChildSegmentListKey)
|
const invalidChildChunkList = useInvalid(useChildSegmentListKey)
|
||||||
const invalidDocumentList = useInvalidDocumentList(datasetId)
|
const invalidDocumentList = useInvalidDocumentList(datasetId)
|
||||||
|
|
||||||
const handleOperate = (operateName?: string) => {
|
const handleOperate = useCallback((operateName?: string) => {
|
||||||
invalidDocumentList()
|
invalidDocumentList()
|
||||||
if (operateName === 'delete') {
|
if (operateName === 'delete') {
|
||||||
backToPrev()
|
backToPrev()
|
||||||
@@ -138,7 +148,7 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
|||||||
}, 5000)
|
}, 5000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}, [invalidDocumentList, backToPrev, detailMutate, invalidChunkList, invalidChildChunkList])
|
||||||
|
|
||||||
const parentMode = useMemo(() => {
|
const parentMode = useMemo(() => {
|
||||||
return documentDetail?.document_process_rule?.rules?.parent_mode || documentDetail?.dataset_process_rule?.rules?.parent_mode || 'paragraph'
|
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'
|
return chunkMode === ChunkingMode.parentChild && parentMode === 'full-doc'
|
||||||
}, [documentDetail?.doc_form, parentMode])
|
}, [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 backButtonLabel = t('operation.back', { ns: 'common' })
|
||||||
const metadataToggleLabel = `${showMetadata
|
const metadataToggleLabel = `${showMetadata
|
||||||
? t('operation.close', { ns: 'common' })
|
? t('operation.close', { ns: 'common' })
|
||||||
: t('operation.view', { ns: 'common' })} ${t('metadata.title', { ns: 'datasetDocuments' })}`
|
: t('operation.view', { ns: 'common' })} ${t('metadata.title', { ns: 'datasetDocuments' })}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DocumentContext.Provider value={{
|
<DocumentContext.Provider value={contextValue}>
|
||||||
datasetId,
|
|
||||||
documentId,
|
|
||||||
docForm: documentDetail?.doc_form as ChunkingMode,
|
|
||||||
parentMode,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex h-full flex-col bg-background-default">
|
<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 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
|
<button
|
||||||
@@ -198,30 +230,21 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
|||||||
<Divider type="vertical" className="!mx-3 !h-[14px] !bg-divider-regular" />
|
<Divider type="vertical" className="!mx-3 !h-[14px] !bg-divider-regular" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<StatusItem
|
{documentDetail && (
|
||||||
status={documentDetail?.display_status || 'available'}
|
<StatusItem
|
||||||
scene="detail"
|
status={documentDetail.display_status || 'available'}
|
||||||
errorMessage={documentDetail?.error || ''}
|
scene="detail"
|
||||||
textCls="font-semibold text-xs uppercase"
|
errorMessage={documentDetail.error || ''}
|
||||||
detail={{
|
textCls="font-semibold text-xs uppercase"
|
||||||
enabled: documentDetail?.enabled || false,
|
detail={statusDetail}
|
||||||
archived: documentDetail?.archived || false,
|
datasetId={datasetId}
|
||||||
id: documentId,
|
onUpdate={handleOperate}
|
||||||
}}
|
/>
|
||||||
datasetId={datasetId}
|
)}
|
||||||
onUpdate={handleOperate}
|
|
||||||
/>
|
|
||||||
<Operations
|
<Operations
|
||||||
scene="detail"
|
scene="detail"
|
||||||
embeddingAvailable={embeddingAvailable}
|
embeddingAvailable={embeddingAvailable}
|
||||||
detail={{
|
detail={operationsDetail}
|
||||||
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}
|
datasetId={datasetId}
|
||||||
onUpdate={handleOperate}
|
onUpdate={handleOperate}
|
||||||
className="!w-[200px]"
|
className="!w-[200px]"
|
||||||
@@ -272,7 +295,7 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
|
|||||||
className="mr-2 mt-3"
|
className="mr-2 mt-3"
|
||||||
datasetId={datasetId}
|
datasetId={datasetId}
|
||||||
documentId={documentId}
|
documentId={documentId}
|
||||||
docDetail={{ ...documentDetail, ...documentMetadata, doc_type: documentMetadata?.doc_type === 'others' ? '' : documentMetadata?.doc_type } as FullDocumentDetail}
|
docDetail={docDetail}
|
||||||
/>
|
/>
|
||||||
</FloatRightContainer>
|
</FloatRightContainer>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -133,15 +133,19 @@ export const useSyncWebsite = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const useDocumentDetailKey = [NAME_SPACE, 'documentDetail', 'withoutMetaData']
|
const useDocumentDetailKey = [NAME_SPACE, 'documentDetail', 'withoutMetaData']
|
||||||
|
type DocumentDetailRefetchInterval = UseQueryOptions<DocumentDetailResponse>['refetchInterval']
|
||||||
|
|
||||||
export const useDocumentDetail = (payload: {
|
export const useDocumentDetail = (payload: {
|
||||||
datasetId: string
|
datasetId: string
|
||||||
documentId: string
|
documentId: string
|
||||||
params: { metadata: MetadataType }
|
params: { metadata: MetadataType }
|
||||||
|
refetchInterval?: DocumentDetailRefetchInterval
|
||||||
}) => {
|
}) => {
|
||||||
const { datasetId, documentId, params } = payload
|
const { datasetId, documentId, params, refetchInterval } = payload
|
||||||
return useQuery<DocumentDetailResponse>({
|
return useQuery<DocumentDetailResponse>({
|
||||||
queryKey: [...useDocumentDetailKey, 'withoutMetaData', datasetId, documentId, params],
|
queryKey: [...useDocumentDetailKey, 'withoutMetaData', datasetId, documentId, params],
|
||||||
queryFn: () => get<DocumentDetailResponse>(`/datasets/${datasetId}/documents/${documentId}`, { params }),
|
queryFn: () => get<DocumentDetailResponse>(`/datasets/${datasetId}/documents/${documentId}`, { params }),
|
||||||
|
refetchInterval,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user