From 93b1398b5c651cfa8df8250778dd1e1bb42d4d8c Mon Sep 17 00:00:00 2001 From: chihlasm Date: Sat, 4 Apr 2026 14:24:25 +0000 Subject: [PATCH] refactor: DeviceNode uses BaseNode, BaseHandle, StatusIndicator, Tooltip Replaces hand-rolled node layout with composable React Flow UI components. Status is now a border effect instead of a dot. Hover tooltip shows hostname, IP, vendor, role, notes. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../components/network/nodes/DeviceNode.tsx | 82 +++++++++++++------ 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/frontend/src/components/network/nodes/DeviceNode.tsx b/frontend/src/components/network/nodes/DeviceNode.tsx index b0de9f61..4335b38d 100644 --- a/frontend/src/components/network/nodes/DeviceNode.tsx +++ b/frontend/src/components/network/nodes/DeviceNode.tsx @@ -1,6 +1,9 @@ import { memo } from 'react' -import { Handle, Position, type NodeProps } from '@xyflow/react' -import { cn } from '@/lib/utils' +import { Position, type NodeProps } from '@xyflow/react' +import { BaseNode, BaseNodeHeader, BaseNodeHeaderTitle, BaseNodeContent } from '../ui/base-node' +import { BaseHandle } from '../ui/base-handle' +import { NodeStatusIndicator, type NodeStatus } from '../ui/node-status-indicator' +import { NodeTooltip, NodeTooltipTrigger, NodeTooltipContent } from '../ui/node-tooltip' import { getDeviceRenderConfig } from './deviceRegistry' import type { DeviceProperties } from '@/types' @@ -12,39 +15,64 @@ export interface DeviceNodeData { [key: string]: unknown } -const STATUS_COLORS: Record = { - online: 'bg-emerald-400', - offline: 'bg-red-400', - degraded: 'bg-yellow-400', - unknown: 'bg-gray-500', +function TooltipRow({ label, value }: { label: string; value: string | null | undefined }) { + if (!value) return null + return ( +
+ {label} + {value} +
+ ) } function DeviceNodeComponent({ data, selected }: NodeProps) { const nodeData = data as unknown as DeviceNodeData const { icon: Icon, color } = getDeviceRenderConfig(nodeData.deviceType, nodeData.category) - const status = nodeData.properties?.status || 'unknown' + const status = (nodeData.properties?.status || 'unknown') as NodeStatus const ip = nodeData.properties?.ip + const props = nodeData.properties || {} + + const hasTooltipContent = props.hostname || props.ip || props.vendor || props.model || props.role || props.notes return ( -
-
- - {nodeData.label} - {ip && ( - {ip} - )} - - - - -
+ + + + + + + + {nodeData.label} + + + {ip && ( + + {ip} + + )} + + + + + + + {hasTooltipContent && ( + +
+ + + {(props.vendor || props.model) && ( + + )} + + {props.notes && ( + 100 ? props.notes.slice(0, 100) + '...' : props.notes} /> + )} +
+
+ )} +
+
) }