"use client" import { useState, useEffect } from "react" import { Network, Database, Zap, AlertCircle, RefreshCw, ChevronDown, ChevronUp, InfoIcon, Trash2 } from "lucide-react" import { Badge } from '@/components/ui/badge' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' import { Button } from "@/components/ui/button" import { VectorDBStats } from '@/types/graph' import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, DialogClose } from "@/components/ui/dialog" interface DatabaseConnectionProps { className?: string } export function DatabaseConnection({ className }: DatabaseConnectionProps) { // Neo4j/Graph DB state const [graphConnectionStatus, setGraphConnectionStatus] = useState<"connected" | "disconnected" | "checking">("disconnected") const [graphError, setGraphError] = useState(null) const [nodeCount, setNodeCount] = useState(null) const [relationshipCount, setRelationshipCount] = useState(null) const [connectionUrl, setConnectionUrl] = useState("") const [dbType, setDbType] = useState("") const [isClearingDB, setIsClearingDB] = useState(false) const [showClearDialog, setShowClearDialog] = useState(false) // Vector DB state const [vectorConnectionStatus, setVectorConnectionStatus] = useState<"connected" | "disconnected" | "checking">("disconnected") const [vectorError, setVectorError] = useState(null) const [vectorStats, setVectorStats] = useState({ nodes: 0, relationships: 0, source: 'none' }) const [isClearingVectorDB, setIsClearingVectorDB] = useState(false) const [showClearVectorDialog, setShowClearVectorDialog] = useState(false) // UI state const [expandedSection, setExpandedSection] = useState<"graph" | "vector" | null>("graph") // Check graph database connection status (Neo4j or ArangoDB) const checkGraphConnection = async () => { setGraphConnectionStatus("checking") setGraphError(null) try { // Get database type from localStorage const graphDbType = localStorage.getItem("graph_db_type") || "arangodb" setDbType(graphDbType === "arangodb" ? "ArangoDB" : "Neo4j") if (graphDbType === "neo4j") { // Neo4j connection logic const dbUrl = localStorage.getItem("NEO4J_URL") const dbUsername = localStorage.getItem("NEO4J_USERNAME") const dbPassword = localStorage.getItem("NEO4J_PASSWORD") // Add query parameters if credentials exist const queryParams = new URLSearchParams() if (dbUrl) queryParams.append("url", dbUrl) if (dbUsername) queryParams.append("username", dbUsername) if (dbPassword) queryParams.append("password", dbPassword) const queryString = queryParams.toString() const endpoint = queryString ? `/api/neo4j?${queryString}` : '/api/neo4j' const response = await fetch(endpoint) if (!response.ok) { const errorData = await response.json() const errorMessage = errorData.error || 'Failed to connect to Neo4j' console.error('Neo4j connection failed:', errorMessage) setGraphConnectionStatus("disconnected") setGraphError(errorMessage) return } const data = await response.json() setNodeCount(data.nodes?.length || 0) setRelationshipCount(data.links?.length || 0) // Use the connection URL from the API response if (data.connectionUrl) { setConnectionUrl(data.connectionUrl) } else if (dbUrl) { setConnectionUrl(dbUrl) } } else { // ArangoDB connection logic const arangoUrl = localStorage.getItem("arango_url") || "http://localhost:8529" const arangoDb = localStorage.getItem("arango_db") || "txt2kg" const arangoUser = localStorage.getItem("arango_user") || "" const arangoPassword = localStorage.getItem("arango_password") || "" // Add query parameters if credentials exist const queryParams = new URLSearchParams() if (arangoUrl) queryParams.append("url", arangoUrl) if (arangoDb) queryParams.append("dbName", arangoDb) if (arangoUser) queryParams.append("username", arangoUser) if (arangoPassword) queryParams.append("password", arangoPassword) const queryString = queryParams.toString() const endpoint = queryString ? `/api/graph-db?${queryString}` : '/api/graph-db' const response = await fetch(endpoint) if (!response.ok) { const errorData = await response.json() const errorMessage = errorData.error || 'Failed to connect to ArangoDB' console.error('ArangoDB connection failed:', errorMessage) setGraphConnectionStatus("disconnected") setGraphError(errorMessage) return } const data = await response.json() setNodeCount(data.nodes?.length || 0) setRelationshipCount(data.links?.length || 0) // Set ArangoDB connection URL setConnectionUrl(`${arangoUrl}/_db/${arangoDb}`) } setGraphConnectionStatus("connected") } catch (err) { console.error('Graph database connection error:', err) setGraphConnectionStatus("disconnected") setGraphError(err instanceof Error ? err.message : 'Unknown error connecting to database') } } // Disconnect from graph database const disconnectGraph = async () => { try { const graphDbType = localStorage.getItem("graph_db_type") || "arangodb" const endpoint = graphDbType === "neo4j" ? '/api/neo4j/disconnect' : '/api/graph-db/disconnect' const response = await fetch(endpoint, { method: 'POST', }) if (!response.ok) { const errorData = await response.json() const errorMessage = errorData.error || `Failed to disconnect from ${graphDbType}` console.error('Graph database disconnect failed:', errorMessage) setGraphError(errorMessage) return } setGraphConnectionStatus("disconnected") setNodeCount(null) setRelationshipCount(null) } catch (err) { console.error('Graph database disconnect error:', err) setGraphError(err instanceof Error ? err.message : 'Unknown error disconnecting from database') } } // Fetch vector DB stats const fetchVectorStats = async () => { try { const response = await fetch('/api/pinecone-diag/stats'); const data = await response.json(); if (response.ok) { setVectorStats({ nodes: typeof data.totalVectorCount === 'number' ? data.totalVectorCount : 0, relationships: 0, // Vector DB doesn't store relationships source: data.source || 'unknown', httpHealthy: data.httpHealthy }); // If we have a healthy HTTP connection, we're connected if (data.httpHealthy) { setVectorConnectionStatus("connected"); setVectorError(null); } else { setVectorConnectionStatus("disconnected"); setVectorError(data.error || 'Connection failed'); } } else { console.error('Failed to fetch vector DB stats:', data); setVectorConnectionStatus("disconnected"); setVectorError(data.error || 'Failed to connect to vector database'); } } catch (error) { console.error('Error fetching vector DB stats:', error); setVectorConnectionStatus("disconnected"); setVectorError(error instanceof Error ? error.message : 'Error connecting to vector database'); } }; // Check vector connection const checkVectorConnection = async () => { setVectorConnectionStatus("checking") setVectorError(null) try { await fetchVectorStats(); } catch (error) { console.error('Error connecting to Vector DB:', error) setVectorConnectionStatus("disconnected") setVectorError(error instanceof Error ? error.message : 'Unknown error connecting to Vector DB') } } // Reset vector connection state const disconnectVector = async () => { setVectorConnectionStatus("disconnected") setVectorStats({ nodes: 0, relationships: 0, source: 'none' }) } // Clear the graph database const clearGraphDatabase = async () => { if (graphConnectionStatus !== "connected") { return } setIsClearingDB(true) setGraphError(null) try { // Call API to clear the database const response = await fetch('/api/graph-db/clear', { method: 'POST', }) if (!response.ok) { const errorData = await response.json() const errorMessage = errorData.error || 'Failed to clear database' console.error('Graph database clear failed:', errorMessage) setGraphError(errorMessage) return } // Refresh graph connection to update stats await checkGraphConnection() setShowClearDialog(false) } catch (err) { console.error('Graph database clear error:', err) setGraphError(err instanceof Error ? err.message : 'Unknown error clearing database') } finally { setIsClearingDB(false) } } // Clear the vector database const clearVectorDatabase = async () => { if (vectorConnectionStatus !== "connected") { return } setIsClearingVectorDB(true) setVectorError(null) try { // Call API to clear the database const response = await fetch('/api/pinecone-diag/clear', { method: 'POST', }) if (!response.ok) { const errorData = await response.json() const errorMessage = errorData.error || 'Failed to clear vector database' console.error('Vector database clear failed:', errorMessage) setVectorError(errorMessage) return } // Refresh vector connection to update stats await checkVectorConnection() setShowClearVectorDialog(false) } catch (err) { console.error('Vector database clear error:', err) setVectorError(err instanceof Error ? err.message : 'Unknown error clearing vector database') } finally { setIsClearingVectorDB(false) } } // Check both connections on mount useEffect(() => { checkGraphConnection() checkVectorConnection() }, []) const toggleSection = (section: "graph" | "vector") => { if (expandedSection === section) { setExpandedSection(null) } else { setExpandedSection(section) } } return (
{/* Graph DB Section */} toggleSection("graph")}>
toggleSection("graph")}>

Graph DB

{graphConnectionStatus === "checking" && ( )} {graphConnectionStatus === "connected" && ( )} {graphConnectionStatus === "disconnected" && ( )}
{graphConnectionStatus === "checking" && (
Checking connection...
)} {graphConnectionStatus === "connected" && ( <>
{dbType} {connectionUrl}
{(nodeCount !== null || relationshipCount !== null) && (
{nodeCount?.toLocaleString()} nodes, {relationshipCount?.toLocaleString()} relationships
)} )} {graphConnectionStatus === "disconnected" && (
Not connected
)} {graphError && (

Error: {graphError}

)}
{graphConnectionStatus === "connected" ? ( <> Clear Database Are you sure you want to clear all data from the {dbType} database? This action cannot be undone. Warning This will permanently delete all nodes and relationships from the database. ) : ( )}
{/* Vector DB Section */} toggleSection("vector")}>
toggleSection("vector")}>

Vector DB

{vectorConnectionStatus === "checking" && ( )} {vectorConnectionStatus === "connected" && ( )} {vectorConnectionStatus === "disconnected" && ( )}
{vectorConnectionStatus === "checking" && (
Checking connection...
)} {vectorConnectionStatus === "connected" && ( <>
Pinecone direct-http
{vectorStats.nodes > 0 && (
{vectorStats.nodes.toLocaleString()} vectors
)} )} {vectorConnectionStatus === "disconnected" && (
Not connected
)} {vectorError && (

Error: {vectorError}

)}
{vectorConnectionStatus === "connected" ? ( <> Clear Pinecone Database Are you sure you want to clear all data from the Pinecone database? This action cannot be undone. Warning This will permanently delete all vectors from the Pinecone database. ) : ( )}
); }