From 4511763bacb0dbe5631a634532206467fb65ecbe Mon Sep 17 00:00:00 2001 From: Pouzor Date: Sun, 8 Mar 2026 12:00:11 +0100 Subject: [PATCH] fix: persist custom_icon on canvas save + add CCTV icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - NodeSave schema was missing custom_icon field — icon reset to default on reload - handleSave was not including custom_icon in the payload - CameraNode now uses Cctv icon (clearer than Camera) - Added 'cctv' entry to ICON_REGISTRY for the icon picker --- backend/app/schemas/canvas.py | 1 + frontend/src/App.tsx | 1 + frontend/src/components/canvas/nodes/index.tsx | 4 ++-- frontend/src/utils/nodeIcons.ts | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/app/schemas/canvas.py b/backend/app/schemas/canvas.py index abf4da2..3eee05c 100644 --- a/backend/app/schemas/canvas.py +++ b/backend/app/schemas/canvas.py @@ -22,6 +22,7 @@ class NodeSave(BaseModel): parent_id: str | None = None container_mode: bool = False custom_colors: dict[str, Any] | None = None + custom_icon: str | None = None pos_x: float = 0 pos_y: float = 0 diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f11d439..feb888c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -53,6 +53,7 @@ export default function App() { parent_id: n.data.parent_id ?? null, container_mode: n.data.container_mode ?? false, custom_colors: n.data.custom_colors ?? null, + custom_icon: n.data.custom_icon ?? null, pos_x: n.position.x, pos_y: n.position.y, })) diff --git a/frontend/src/components/canvas/nodes/index.tsx b/frontend/src/components/canvas/nodes/index.tsx index 1df32f7..21ef288 100644 --- a/frontend/src/components/canvas/nodes/index.tsx +++ b/frontend/src/components/canvas/nodes/index.tsx @@ -1,7 +1,7 @@ import { type NodeProps, type Node } from '@xyflow/react' import { Globe, Router, Network, Server, Layers, Box, Container, - HardDrive, Cpu, Wifi, Circle, Camera, + HardDrive, Cpu, Wifi, Circle, Cctv, } from 'lucide-react' import { BaseNode } from './BaseNode' import type { NodeData } from '@/types' @@ -18,5 +18,5 @@ export const LxcNode = (props: N) => export const IotNode = (props: N) => export const ApNode = (props: N) => -export const CameraNode = (props: N) => +export const CameraNode = (props: N) => export const GenericNode = (props: N) => diff --git a/frontend/src/utils/nodeIcons.ts b/frontend/src/utils/nodeIcons.ts index 6b934f5..d63058b 100644 --- a/frontend/src/utils/nodeIcons.ts +++ b/frontend/src/utils/nodeIcons.ts @@ -2,7 +2,7 @@ import { // Infrastructure (node types) Globe, Router, Network, Server, Layers, Box, Container, HardDrive, Cpu, Wifi, Circle, // Media - Play, Film, Tv, Tv2, Music, Camera, Video, Headphones, Clapperboard, + Play, Film, Tv, Tv2, Music, Camera, Video, Headphones, Clapperboard, Cctv, // Monitoring & Observability Activity, BarChart2, LineChart, Eye, Bell, Gauge, Monitor, // Storage & Databases @@ -57,6 +57,7 @@ export const ICON_REGISTRY: IconEntry[] = [ { key: 'headphones', label: 'Audiobookshelf', category: 'Media', icon: Headphones }, { key: 'video', label: 'Video / Streaming', category: 'Media', icon: Video }, { key: 'camera', label: 'Camera / Frigate', category: 'Media', icon: Camera }, + { key: 'cctv', label: 'CCTV / IP Camera', category: 'Media', icon: Cctv }, // --- Monitoring --- { key: 'activity', label: 'Prometheus / Uptime', category: 'Monitoring', icon: Activity },