// // SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // "use client" import { useState } from "react" import { CheckCircle, AlertCircle, Loader2, Trash2, FileText, Table, Edit, Eye, Network, Download, Info } from "lucide-react" import { useDocuments } from "@/contexts/document-context" import { DocumentActions } from "@/components/document-actions" import { useShiftSelect } from "@/hooks/use-shift-select" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Button } from "@/components/ui/button" import type { Triple } from "@/utils/text-processing" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" import { downloadDocument } from "@/lib/utils" import { toast } from "@/hooks/use-toast" export interface DocumentsTableProps { onTabChange?: (tab: string) => void; } export function DocumentsTable({ onTabChange }: DocumentsTableProps) { const { documents, deleteDocuments, updateTriples } = useDocuments() const [showTriplesDialog, setShowTriplesDialog] = useState(false) const [currentDocumentId, setCurrentDocumentId] = useState(null) const [editableTriples, setEditableTriples] = useState([]) const [editingTripleIndex, setEditingTripleIndex] = useState(null) // Use shift-select hook for document selection const { selectedItems: selectedDocuments, setSelectedItems: setSelectedDocuments, handleItemClick, handleSelectAll, isSelected } = useShiftSelect({ items: documents, getItemId: (doc) => doc.id, canSelect: () => true, // All documents can be selected in this table onSelectionChange: (selectedIds) => { // Optional: handle selection change if needed } }) const handleDeleteSelected = () => { if (selectedDocuments.length === 0) return if (confirm(`Are you sure you want to delete ${selectedDocuments.length} selected document(s)?`)) { deleteDocuments(selectedDocuments) setSelectedDocuments([]) } } const openTriplesDialog = (documentId: string) => { const document = documents.find(doc => doc.id === documentId); if (document && document.triples) { setCurrentDocumentId(documentId); setEditableTriples([...document.triples]); setShowTriplesDialog(true); } } const saveTriples = () => { if (currentDocumentId) { updateTriples(currentDocumentId, editableTriples); setShowTriplesDialog(false); } } const updateTriple = (index: number, field: 'subject' | 'predicate' | 'object', value: string) => { const newTriples = [...editableTriples]; newTriples[index] = { ...newTriples[index], [field]: value }; setEditableTriples(newTriples); } const deleteTriple = (index: number) => { const newTriples = [...editableTriples]; newTriples.splice(index, 1); setEditableTriples(newTriples); } const addNewTriple = () => { setEditableTriples([...editableTriples, { subject: '', predicate: '', object: '' }]); setEditingTripleIndex(editableTriples.length); } const getStatusIcon = (status: string) => { switch (status) { case "New": return case "Processing": return case "Processed": return case "Error": return default: return } } // Show different columns based on document processing state const showTriplesColumn = documents.some(doc => doc.status === 'Processed') return (
0} onChange={handleSelectAll} disabled={documents.length === 0} />
{selectedDocuments.length > 0 ? ( {selectedDocuments.length} selected ) : ( Select all documents )} {documents.length > 0 && ( {documents.length} total document{documents.length !== 1 ? 's' : ''} )}
{selectedDocuments.length > 0 && ( )}
{showTriplesColumn && } {documents.length === 0 ? ( ) : ( documents.map((doc) => ( handleItemClick(doc, e)}> {showTriplesColumn && ( )} )) )}
Name Status Upload Status Size (KB)TriplesActions

No documents uploaded yet

Get started by uploading markdown, CSV, text, or JSON files to extract knowledge graphs

Supported: .md, .csv, .txt, .json
e.stopPropagation()}> handleItemClick(doc, e)} />
{doc.name}
{getStatusIcon(doc.status)} {doc.status}
{doc.uploadStatus}
{doc.size} {doc.status === "Processed" && doc.triples ? (
{doc.triples.length}
) : doc.status === "Error" ? ( Error ) : ( - )}
Edit Knowledge Graph Triples View and edit the extracted triples before processing into your graph database
{editableTriples.length} Triples

Subject-Predicate-Object relationships

{editableTriples.map((triple, index) => ( ))}
Subject Predicate Object Actions
{editingTripleIndex === index ? ( updateTriple(index, 'subject', e.target.value)} className="w-full bg-background border border-input rounded p-2 text-sm text-foreground focus:ring-2 focus:ring-primary/50 focus:border-primary" /> ) : ( {triple.subject} )} {editingTripleIndex === index ? ( updateTriple(index, 'predicate', e.target.value)} className="w-full bg-background border border-input rounded p-2 text-sm text-foreground focus:ring-2 focus:ring-primary/50 focus:border-primary" /> ) : ( {triple.predicate} )} {editingTripleIndex === index ? ( updateTriple(index, 'object', e.target.value)} className="w-full bg-background border border-input rounded p-2 text-sm text-foreground focus:ring-2 focus:ring-primary/50 focus:border-primary" /> ) : ( {triple.object} )}
{editingTripleIndex === index ? ( ) : ( )}
) }