"use client" import { useState, useEffect } from "react" import { useDocuments } from "@/contexts/document-context" import { CheckCircle, Loader2, FileText, AlertCircle, X } from "lucide-react" import { Switch } from "@/components/ui/switch" import { Label } from "@/components/ui/label" import { Button } from "@/components/ui/button" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" import { useRouter } from "next/navigation" import { useShiftSelect } from "@/hooks/use-shift-select" export function DocumentSelection() { const { documents, processDocuments, isProcessing } = useDocuments() const [useLangChain, setUseLangChain] = useState(false) const [useSentenceChunking, setUseSentenceChunking] = useState(true) const [useEntityExtraction, setUseEntityExtraction] = useState(true) const [processingStatus, setProcessingStatus] = useState("") const [error, setError] = useState(null) const [forceUpdate, setForceUpdate] = useState(0) const router = useRouter() // Use shift-select hook for document selection const { selectedItems: selectedDocs, setSelectedItems: setSelectedDocs, handleItemClick, handleSelectAll, isSelected } = useShiftSelect({ items: documents, getItemId: (doc) => doc.id, canSelect: (doc) => doc.status === "New" || doc.status === "Processed" || doc.status === "Error", onSelectionChange: (selectedIds) => { // Optional: handle selection change if needed } }) // Add event listener for document status changes useEffect(() => { const handleDocumentStatusChange = () => { console.log("Document status changed, forcing UI refresh"); setForceUpdate(prev => prev + 1); // Increment to force a re-render }; const handleProcessingComplete = () => { console.log("Processing complete event received, resetting UI state"); setProcessingStatus(""); // Clear the processing status message setForceUpdate(prev => prev + 1); // Force a refresh }; window.addEventListener('document-status-changed', handleDocumentStatusChange); window.addEventListener('processing-complete', handleProcessingComplete); return () => { window.removeEventListener('document-status-changed', handleDocumentStatusChange); window.removeEventListener('processing-complete', handleProcessingComplete); }; }, []); // Add automatic UI refresh every second during processing useEffect(() => { let interval: NodeJS.Timeout; if (isProcessing) { interval = setInterval(() => { setForceUpdate(prev => prev + 1); // Force UI refresh }, 1000); } return () => { if (interval) clearInterval(interval); }; }, [isProcessing]); // On component mount, default to select all documents with status "New", "Processed", or "Error" useEffect(() => { const availableDocs = documents .filter(doc => doc.status === "New" || doc.status === "Processed" || doc.status === "Error") .map(doc => doc.id) setSelectedDocs(availableDocs) }, [documents, setSelectedDocs]) const handleTabChange = (tab: string) => { const tabElement = document.querySelector(`[data-value="${tab}"]`) if (tabElement && 'click' in tabElement) { (tabElement as HTMLElement).click() } } const handleProcessDocuments = async () => { if (selectedDocs.length === 0) { setError("Please select at least one document to process") return } setError(null) setProcessingStatus("Preparing documents for processing...") try { // Update the processing status display const docNames = selectedDocs.map(id => documents.find(d => d.id === id)?.name || 'Unknown' ).join(', '); setProcessingStatus(`Processing ${selectedDocs.length} document(s): ${docNames}`); // Call processDocuments with the selected document IDs await processDocuments(selectedDocs, { useLangChain, useGraphTransformer: false, promptConfigs: undefined }) // Ensure UI is updated after processing completes setForceUpdate(prev => prev + 1); setProcessingStatus("Processing complete! Navigating to edit view..."); // Short delay before navigation to allow status update to be seen setTimeout(() => { // Navigate to the edit tab after processing handleTabChange("edit") }, 1000); } catch (error) { console.error("Error processing documents:", error) setError("Failed to process documents. Please try again.") } } const handleStopProcessing = async () => { try { // Call the stop processing API const response = await fetch('/api/stop-processing', { method: 'POST', headers: { 'Content-Type': 'application/json', }, }); if (response.ok) { setProcessingStatus("Processing stopped by user"); setError(null); // Force UI refresh to update document statuses setForceUpdate(prev => prev + 1); } else { setError("Failed to stop processing. Please try again."); } } catch (error) { console.error("Error stopping processing:", error); setError("Failed to stop processing. Please try again."); } } return (

Document Selection

Select which documents to process for triple extraction

Processing Options

{ setUseLangChain(value); // Dispatch custom event to update other components window.dispatchEvent(new CustomEvent('langChainToggled', { detail: { useLangChain: value } })); }} disabled={isProcessing} />
{/*

Leverages LangChain for knowledge extraction from documents

*/} {useLangChain && ( <>

Split documents into sentences for more accurate triple extraction

Automatically detect and extract entities from documents

)}
{error && (

{error}

)}
doc.status === "New" || doc.status === "Processed" || doc.status === "Error").length && documents.filter(doc => doc.status === "New" || doc.status === "Processed" || doc.status === "Error").length > 0} onChange={handleSelectAll} disabled={documents.filter(doc => doc.status === "New" || doc.status === "Processed" || doc.status === "Error").length === 0 || isProcessing} /> {selectedDocs.length > 0 ? ( {selectedDocs.length} selected ) : ( Select all )}
{isProcessing && ( )}
{documents.length === 0 ? (

No documents available for processing

) : ( {documents.map((doc) => ( ))}
handleItemClick(doc, e)} disabled={(doc.status !== "New" && doc.status !== "Processed" && doc.status !== "Error") || isProcessing} /> (doc.status === "New" || doc.status === "Processed" || doc.status === "Error") && !isProcessing && handleItemClick(doc, e)}> {doc.name}
{doc.status === "New" && ( )} {doc.status === "Processing" && ( )} {doc.status === "Processed" && ( )} {doc.status === "Error" && ( )} {doc.status}
{doc.size}
)}
{isProcessing && processingStatus && (
{processingStatus}
)}
) }