| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- import React, { useEffect, useState } from 'react';
- import { X } from 'lucide-react';
- import { knowledgeBaseService } from '../services/knowledgeBaseService';
- import { useLanguage } from '../contexts/LanguageContext';
- interface ChunkInfo {
- fileId: string;
- fileName: string;
- totalChunks: number;
- chunkSize: number;
- chunkOverlap: number;
- chunks: Array<{
- index: number;
- content: string;
- contentLength: number;
- startPosition: number;
- endPosition: number;
- }>;
- }
- interface ChunkInfoDrawerProps {
- isOpen: boolean;
- onClose: () => void;
- fileId: string;
- fileName: string;
- authToken: string;
- }
- export const ChunkInfoDrawer: React.FC<ChunkInfoDrawerProps> = ({
- isOpen,
- onClose,
- fileId,
- fileName,
- authToken,
- }) => {
- const { t } = useLanguage();
- const [chunkInfo, setChunkInfo] = useState<ChunkInfo | null>(null);
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState<string | null>(null);
- useEffect(() => {
- if (isOpen && fileId) {
- loadChunks();
- }
- }, [isOpen, fileId]);
- const loadChunks = async () => {
- setLoading(true);
- setError(null);
- try {
- const data = await knowledgeBaseService.getFileChunks(fileId, authToken);
- setChunkInfo(data);
- } catch (err) {
- console.error('Failed to load chunks:', err);
- setError(t('errorLoadData'));
- } finally {
- setLoading(false);
- }
- };
- if (!isOpen) return null;
- return (
- <>
- {/* Backdrop */}
- <div
- className="fixed inset-0 bg-black/50 z-[9998]"
- onClick={onClose}
- />
- {/* Drawer */}
- <div className="fixed right-0 top-0 h-full w-full md:w-2/3 lg:w-1/2 bg-white shadow-2xl z-[9999] flex flex-col">
- {/* Header */}
- <div className="flex items-center justify-between p-6 border-b border-slate-200 shrink-0">
- <div>
- <h2 className="text-xl font-semibold text-slate-800">
- {t('chunkInfo')}
- </h2>
- <p className="text-sm text-slate-500 mt-1">{fileName}</p>
- </div>
- <button
- onClick={onClose}
- className="p-2 hover:bg-slate-100 rounded-lg transition-colors"
- >
- <X className="w-5 h-5" />
- </button>
- </div>
- {/* Content */}
- <div className="flex-1 overflow-y-auto p-6">
- {loading ? (
- <div className="flex items-center justify-center h-full">
- <div className="text-slate-500">{t('loading')}</div>
- </div>
- ) : error ? (
- <div className="flex items-center justify-center h-full">
- <div className="text-red-500">{error}</div>
- </div>
- ) : chunkInfo ? (
- <div>
- {/* Summary */}
- <div className="bg-slate-50 rounded-lg p-4 mb-6 space-y-2">
- <div className="flex justify-between">
- <span className="text-slate-600">{t('totalChunks')}:</span>
- <span className="font-semibold">{chunkInfo.totalChunks}</span>
- </div>
- <div className="flex justify-between">
- <span className="text-slate-600">{t('chunkSize')}:</span>
- <span className="font-semibold">{chunkInfo.chunkSize} tokens</span>
- </div>
- <div className="flex justify-between">
- <span className="text-slate-600">{t('chunkOverlap')}:</span>
- <span className="font-semibold">{chunkInfo.chunkOverlap} tokens</span>
- </div>
- </div>
- {/* Chunks List */}
- <div className="space-y-4">
- {chunkInfo.chunks.map((chunk) => (
- <div
- key={chunk.index}
- className="border border-slate-200 rounded-lg p-4 hover:border-blue-300 transition-colors"
- >
- <div className="flex justify-between items-center mb-3">
- <span className="font-semibold text-slate-800">
- {t('chunkIndex')} #{chunk.index}
- </span>
- <span className="text-sm text-slate-500">
- {chunk.contentLength} {t('contentLength')}
- </span>
- </div>
- <div className="bg-white border border-slate-200 rounded-lg p-4 max-h-96 overflow-y-auto">
- <div className="text-slate-700 text-sm leading-7 whitespace-pre-wrap break-words" style={{ fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif' }}>
- {chunk.content}
- </div>
- </div>
- <div className="text-xs text-slate-400 mt-2">
- {t('position')}: {chunk.startPosition} - {chunk.endPosition}
- </div>
- </div>
- ))}
- </div>
- </div>
- ) : null}
- </div>
- </div>
- </>
- );
- };
|