import type { DocumentRevisionChunk, LogicalDocument, LogicalDocumentRevision, } from '@dify/contracts/knowledge-fs/types.gen' import { Button } from '@langgenius/dify-ui/button' import { toast } from '@langgenius/dify-ui/toast' import copy from 'copy-to-clipboard' import { useEffect, useMemo } from 'react' import { useTranslation } from 'react-i18next' import { chunkCharacterCount, chunkContentParts, chunkMetadataEntries, } from './document-detail-model' function formatBytes(bytes: number, locale: string) { const numberFormat = new Intl.NumberFormat(locale, { maximumFractionDigits: 1 }) if (bytes < 1024) return `${numberFormat.format(bytes)} B` const units = ['KB', 'MB', 'GB'] let value = bytes / 1024 let unit = units[0] for (let index = 1; index < units.length && value >= 1024; index++) { value /= 1024 unit = units[index] } return `${new Intl.NumberFormat(locale, { maximumFractionDigits: value >= 10 ? 0 : 1, }).format(value)} ${unit}` } function formatDate(value: string | undefined, locale: string) { if (!value) return '—' const date = new Date(value) if (Number.isNaN(date.getTime())) return value return new Intl.DateTimeFormat(locale, { dateStyle: 'medium', timeStyle: 'short', }).format(date) } export function DocumentChunkDetail({ document, chunks, chunksComplete, locale, revision, selectedChunkId, }: { document: LogicalDocument chunks: DocumentRevisionChunk[] chunksComplete: boolean locale: string revision?: Exclude selectedChunkId?: string }) { const { t } = useTranslation('dataset') const { t: tCommon } = useTranslation('common') const selectedChunk = useMemo( () => chunks.find((chunk) => chunk.id === selectedChunkId) ?? chunks[0], [chunks, selectedChunkId], ) const characterCount = useMemo( () => chunks.reduce((total, chunk) => total + chunkCharacterCount(chunk.text), 0), [chunks], ) const averageChunkLength = chunks.length ? Math.round(characterCount / chunks.length) : 0 const sizeBytes = revision?.sizeBytes ?? document.active?.sizeBytes const sourceName = typeof document.userMetadata.sourceName === 'string' ? document.userMetadata.sourceName : undefined const retrievalCount = typeof document.userMetadata.retrievalCount === 'number' ? document.userMetadata.retrievalCount : undefined useEffect(() => { if (!selectedChunkId) return globalThis.document ?.getElementById(`document-chunk-${selectedChunkId}`) ?.scrollIntoView({ block: 'nearest' }) }, [selectedChunkId]) return ( <>
{!chunksComplete && (

{t(($) => $['newKnowledge.documentContentIncomplete'])}

)} {chunks.length ? (
{chunks.map((chunk) => { const content = chunkContentParts(chunk.text) return (

{content.heading || t(($) => $['newKnowledge.chunkHeading'], { position: chunk.ordinal })}

{t(($) => $['newKnowledge.chunkLocation'], { position: chunk.ordinal })}

{content.body && (

{content.body}

)} {!chunk.text && (

{t(($) => $['newKnowledge.emptyChunk'])}

)}
) })}
) : (
{t(($) => $['newKnowledge.selectChunk'])}
)}
) }