import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"; import type { NodePopupContent, EdgePopupContent } from "./type"; import { getNodeColor } from "./node-colors"; import { useMemo } from "react"; import { useTheme } from "remix-themes"; import dayjs from "dayjs"; /** * Format a date string into a readable format */ export function formatDate( dateString?: string | null, format: string = "MMM D, YYYY", ): string { if (!dateString) return "Unknown"; try { return dayjs(dateString).format(format); } catch (error) { console.error("Error formatting date:", error); return "Invalid date"; } } interface GraphPopoversProps { showNodePopup: boolean; showEdgePopup: boolean; nodePopupContent: NodePopupContent | null; edgePopupContent: EdgePopupContent | null; onOpenChange?: (open: boolean) => void; labelColorMap?: Map; } export function GraphPopovers({ showNodePopup, nodePopupContent, onOpenChange, labelColorMap, }: GraphPopoversProps) { const [resolvedTheme] = useTheme(); const isDarkMode = resolvedTheme === "dark"; const primaryNodeLabel = useMemo((): string | null => { if (!nodePopupContent) { return null; } // Check if node has primaryLabel property (GraphNode) const nodeAny = nodePopupContent.node as any; if ( nodeAny.attributes.nodeType && typeof nodeAny.attributes.nodeType === "string" ) { return nodeAny.attributes.nodeType; } // Fall back to original logic with labels const primaryLabel = nodePopupContent.node.labels?.find( (label) => label !== "Entity", ); return primaryLabel || "Entity"; }, [nodePopupContent]); // Get the color for the primary label const labelColor = useMemo(() => { if (!primaryNodeLabel || !labelColorMap) return ""; return getNodeColor(primaryNodeLabel, isDarkMode, labelColorMap); }, [primaryNodeLabel, isDarkMode, labelColorMap]); const attributesToDisplay = useMemo(() => { if (!nodePopupContent) { return []; } const entityProperties = Object.fromEntries( Object.entries(nodePopupContent.node.attributes || {}).filter(([key]) => { return key !== "labels" && !key.includes("Embedding"); }), ); return Object.entries(entityProperties).map(([key, value]) => ({ key, value, })); }, [nodePopupContent]); return (
e.preventDefault()} >

Node Details

{primaryNodeLabel && ( {primaryNodeLabel} )}
{attributesToDisplay.length > 0 && (
{attributesToDisplay.map(({ key, value }) => (

{key.charAt(0).toUpperCase() + key.slice(1).toLowerCase()} : {" "} {typeof value === "object" ? JSON.stringify(value) : String(value)}

))}
)}
); }