AgentGraph / frontend /src /components /features /context /ContextDocumentsSection.tsx
wu981526092's picture
🚀 Deploy AgentGraph: Complete agent monitoring and knowledge graph system
c2ea5ed
/**
* Context Documents Section Component
*
* Main section for managing context documents in the TraceDetailsModal
*/
import React, { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { FileText, Plus } from "lucide-react";
import { useContextDocuments } from "@/hooks/useContextDocuments";
import { ContextDocumentCard } from "@/components/features/context/ContextDocumentCard";
import { ContextUploadDialog } from "@/components/features/context/ContextUploadDialog";
import { ContextDocumentModal } from "@/components/features/context/ContextDocumentModal";
import { ContextDocument } from "@/types/context";
interface ContextDocumentsSectionProps {
traceId: string;
showHeader?: boolean; // New prop to control header visibility
triggerAdd?: number; // Prop to trigger add dialog from external button
}
export function ContextDocumentsSection({
traceId,
showHeader = true, // Default to showing header for backward compatibility
triggerAdd,
}: ContextDocumentsSectionProps) {
const {
documents,
loading,
error,
loadDocuments,
deleteDocument,
updateDocument,
} = useContextDocuments();
const [isUploadDialogOpen, setIsUploadDialogOpen] = useState(false);
const [selectedDocument, setSelectedDocument] =
useState<ContextDocument | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
// Load documents when component mounts or traceId changes
useEffect(() => {
if (traceId) {
loadDocuments(traceId);
}
}, [traceId, loadDocuments]);
// Trigger add dialog when external button is clicked
useEffect(() => {
if (triggerAdd && triggerAdd > 0) {
setIsUploadDialogOpen(true);
}
}, [triggerAdd]);
const handleAddContext = () => {
setIsUploadDialogOpen(true);
};
const handleDeleteDocument = async (contextId: string) => {
const success = await deleteDocument(traceId, contextId);
if (success) {
// Document has been removed from state by the hook
}
};
const handleViewEdit = (document: ContextDocument) => {
setSelectedDocument(document);
setIsModalOpen(true);
};
const handleModalClose = () => {
setIsModalOpen(false);
setSelectedDocument(null);
};
const handleDocumentSave = async (updates: any) => {
if (!selectedDocument) return false;
const updatedDocument = await updateDocument(
traceId,
selectedDocument.id,
updates
);
if (updatedDocument) {
setSelectedDocument(updatedDocument);
return true;
}
return false;
};
const handleDocumentDelete = async () => {
if (!selectedDocument) return false;
const success = await deleteDocument(traceId, selectedDocument.id);
if (success) {
setIsModalOpen(false);
setSelectedDocument(null);
}
return success;
};
if (error) {
return (
<div className="p-4 rounded-lg border border-destructive/20 bg-destructive/5">
<div className="flex items-center gap-2 text-destructive mb-2">
<FileText className="h-5 w-5" />
<span className="font-medium">Context Documents - Error</span>
</div>
<p className="text-sm text-destructive mb-2">{error}</p>
<Button
variant="outline"
size="sm"
onClick={() => loadDocuments(traceId)}
>
Retry
</Button>
</div>
);
}
return (
<>
<div className="space-y-4">
{showHeader && (
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<FileText className="h-5 w-5" />
<span className="font-medium">
Context Documents ({documents.length})
</span>
</div>
<Button
onClick={handleAddContext}
disabled={loading}
size="sm"
className="bg-primary hover:bg-primary/90"
data-context-add-button
>
<Plus className="h-3 w-3 mr-2" />
Add Context
</Button>
</div>
)}
{loading && documents.length === 0 ? (
<div className="text-center py-8">
<div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin mx-auto mb-2" />
<p className="text-sm text-muted-foreground">
Loading context documents...
</p>
</div>
) : documents.length === 0 ? (
<div className="text-center py-8 text-muted-foreground">
<FileText className="h-12 w-12 mx-auto mb-3 opacity-50" />
<p className="font-medium mb-2">No context documents yet</p>
<p className="text-sm mb-4">
Add domain knowledge, schemas, or guidelines to improve extraction
quality.
</p>
<Button
onClick={handleAddContext}
size="sm"
data-context-add-button
>
<Plus className="h-4 w-4 mr-2" />
Add Your First Context Document
</Button>
</div>
) : (
<div className="space-y-3">
{documents.map((document) => (
<ContextDocumentCard
key={document.id}
document={document}
onDelete={() => handleDeleteDocument(document.id)}
onViewEdit={() => handleViewEdit(document)}
/>
))}
</div>
)}
</div>
{/* Upload Dialog */}
<ContextUploadDialog
isOpen={isUploadDialogOpen}
onClose={() => setIsUploadDialogOpen(false)}
traceId={traceId}
onSuccess={() => {
setIsUploadDialogOpen(false);
loadDocuments(traceId);
}}
/>
{/* Context Document Modal */}
{selectedDocument && (
<ContextDocumentModal
document={selectedDocument}
isOpen={isModalOpen}
onClose={handleModalClose}
onSave={handleDocumentSave}
onDelete={handleDocumentDelete}
/>
)}
</>
);
}