diff --git a/frontend/src/components/canvas/nodes/index.tsx b/frontend/src/components/canvas/nodes/index.tsx index 6bf6eff..1cb114b 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, Cctv, Printer, Monitor, PlugZap, Anchor, Package, Flame, Radio, Antenna, + HardDrive, Cpu, Wifi, Circle, Cctv, Printer, Monitor, Laptop, Smartphone, PlugZap, Anchor, Package, Flame, Radio, Antenna, } from 'lucide-react' import { BaseNode } from './BaseNode' import type { NodeData } from '@/types' @@ -22,6 +22,8 @@ export const ApNode = (props: N) => export const CameraNode = (props: N) => export const PrinterNode = (props: N) => export const ComputerNode = (props: N) => +export const LaptopNode = (props: N) => +export const MobileNode = (props: N) => export const CplNode = (props: N) => export const DockerHostNode = (props: N) => export const DockerContainerNode = (props: N) => diff --git a/frontend/src/components/canvas/nodes/nodeTypes.ts b/frontend/src/components/canvas/nodes/nodeTypes.ts index 34d25ec..38e427f 100644 --- a/frontend/src/components/canvas/nodes/nodeTypes.ts +++ b/frontend/src/components/canvas/nodes/nodeTypes.ts @@ -1,4 +1,4 @@ -import { IspNode, RouterNode, FirewallNode, SwitchNode, ServerNode, VmNode, LxcNode, NasNode, IotNode, ApNode, CameraNode, PrinterNode, ComputerNode, CplNode, DockerHostNode, DockerContainerNode, GenericNode, ZigbeeCoordinatorNode, ZigbeeRouterNode, ZigbeeEndDeviceNode } from './index' +import { IspNode, RouterNode, FirewallNode, SwitchNode, ServerNode, VmNode, LxcNode, NasNode, IotNode, ApNode, CameraNode, PrinterNode, ComputerNode, LaptopNode, MobileNode, CplNode, DockerHostNode, DockerContainerNode, GenericNode, ZigbeeCoordinatorNode, ZigbeeRouterNode, ZigbeeEndDeviceNode } from './index' import { ProxmoxGroupNode } from './ProxmoxGroupNode' import { GroupRectNode } from './GroupRectNode' import { GroupNode } from './GroupNode' @@ -19,6 +19,8 @@ export const nodeTypes = { camera: CameraNode, printer: PrinterNode, computer: ComputerNode, + laptop: LaptopNode, + mobile: MobileNode, cpl: CplNode, docker_host: DockerHostNode, docker_container: DockerContainerNode, diff --git a/frontend/src/components/modals/CustomStyleModal.tsx b/frontend/src/components/modals/CustomStyleModal.tsx index 20aaac1..09391a0 100644 --- a/frontend/src/components/modals/CustomStyleModal.tsx +++ b/frontend/src/components/modals/CustomStyleModal.tsx @@ -2,7 +2,7 @@ import { useState, useCallback } from 'react' import { toast } from 'sonner' import { Globe, Router, Network, Server, Layers, Box, Container, HardDrive, - Cpu, Wifi, Camera, Printer, Monitor, PlugZap, Anchor, Package, Circle, Flame, + Cpu, Wifi, Camera, Printer, Monitor, Laptop, Smartphone, PlugZap, Anchor, Package, Circle, Flame, Radio, Zap, Lightbulb, type LucideIcon, } from 'lucide-react' @@ -21,7 +21,7 @@ import { NODE_TYPE_LABELS, EDGE_TYPE_LABELS } from '@/types' const EDITABLE_NODE_TYPES: NodeType[] = [ 'isp', 'router', 'firewall', 'switch', 'server', 'proxmox', 'vm', 'lxc', 'nas', - 'iot', 'ap', 'camera', 'printer', 'computer', 'cpl', 'docker_host', + 'iot', 'ap', 'camera', 'printer', 'computer', 'laptop', 'mobile', 'cpl', 'docker_host', 'docker_container', 'zigbee_coordinator', 'zigbee_router', 'zigbee_enddevice', 'generic', ] @@ -31,7 +31,7 @@ const EDITABLE_EDGE_TYPES: EdgeType[] = ['ethernet', 'wifi', 'iot', 'vlan', 'vir const NODE_ICONS: Record = { isp: Globe, router: Router, firewall: Flame, switch: Network, server: Server, proxmox: Layers, vm: Box, lxc: Container, nas: HardDrive, iot: Cpu, ap: Wifi, - camera: Camera, printer: Printer, computer: Monitor, cpl: PlugZap, + camera: Camera, printer: Printer, computer: Monitor, laptop: Laptop, mobile: Smartphone, cpl: PlugZap, docker_host: Anchor, docker_container: Package, zigbee_coordinator: Radio, zigbee_router: Zap, zigbee_enddevice: Lightbulb, generic: Circle, diff --git a/frontend/src/components/modals/NodeModal.tsx b/frontend/src/components/modals/NodeModal.tsx index d5b851f..274954b 100644 --- a/frontend/src/components/modals/NodeModal.tsx +++ b/frontend/src/components/modals/NodeModal.tsx @@ -18,7 +18,8 @@ const NODE_TYPE_GROUPS: { label: string; types: NodeType[] }[] = [ { label: 'Virtualization', types: ['proxmox', 'vm', 'lxc', 'docker_host', 'docker_container'] }, { label: 'IoT', types: ['iot', 'camera', 'cpl'] }, { label: 'Zigbee', types: ['zigbee_coordinator', 'zigbee_router', 'zigbee_enddevice'] }, - { label: 'Generic', types: ['computer', 'generic', 'groupRect'] }, + { label: 'Personal', types: ['computer', 'laptop', 'mobile'] }, + { label: 'Generic', types: ['generic', 'groupRect'] }, ] const CHECK_METHODS: CheckMethod[] = ['none', 'ping', 'http', 'https', 'tcp', 'ssh', 'prometheus', 'health'] diff --git a/frontend/src/types/__tests__/types.test.ts b/frontend/src/types/__tests__/types.test.ts index 57e6efd..0ccf129 100644 --- a/frontend/src/types/__tests__/types.test.ts +++ b/frontend/src/types/__tests__/types.test.ts @@ -4,7 +4,7 @@ import type { CheckMethod } from '@/types' describe('NODE_TYPE_LABELS', () => { it('has an entry for every node type', () => { - const expectedTypes = ['isp', 'router', 'firewall', 'switch', 'server', 'proxmox', 'vm', 'lxc', 'nas', 'iot', 'ap', 'camera', 'generic'] + const expectedTypes = ['isp', 'router', 'firewall', 'switch', 'server', 'proxmox', 'vm', 'lxc', 'nas', 'iot', 'ap', 'camera', 'laptop', 'mobile', 'generic'] expectedTypes.forEach((t) => { expect(NODE_TYPE_LABELS).toHaveProperty(t) expect(typeof NODE_TYPE_LABELS[t as keyof typeof NODE_TYPE_LABELS]).toBe('string') diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 37939a8..17932b4 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -13,6 +13,8 @@ export type NodeType = | 'camera' | 'printer' | 'computer' + | 'laptop' + | 'mobile' | 'cpl' | 'docker_host' | 'docker_container' @@ -143,6 +145,8 @@ export const NODE_TYPE_LABELS: Record = { camera: 'Camera', printer: 'Printer', computer: 'Computer', + laptop: 'Laptop', + mobile: 'Phone / Mobile', cpl: 'CPL / Powerline', docker_host: 'Docker Host', docker_container: 'Docker Container', diff --git a/frontend/src/utils/__tests__/themes.test.ts b/frontend/src/utils/__tests__/themes.test.ts index 1a4b103..74e7937 100644 --- a/frontend/src/utils/__tests__/themes.test.ts +++ b/frontend/src/utils/__tests__/themes.test.ts @@ -4,7 +4,7 @@ import type { NodeType, EdgeType, NodeStatus } from '@/types' const NODE_TYPES: NodeType[] = [ 'isp', 'router', 'firewall', 'switch', 'server', 'proxmox', 'vm', 'lxc', - 'nas', 'iot', 'ap', 'camera', 'printer', 'computer', 'cpl', 'docker_host', 'docker_container', 'generic', 'groupRect', + 'nas', 'iot', 'ap', 'camera', 'printer', 'computer', 'laptop', 'mobile', 'cpl', 'docker_host', 'docker_container', 'generic', 'groupRect', ] const EDGE_TYPES: EdgeType[] = ['ethernet', 'wifi', 'iot', 'vlan', 'virtual', 'cluster'] const STATUS_TYPES: NodeStatus[] = ['online', 'offline', 'pending', 'unknown'] diff --git a/frontend/src/utils/nodeIcons.ts b/frontend/src/utils/nodeIcons.ts index c781d0a..6a5d2a3 100644 --- a/frontend/src/utils/nodeIcons.ts +++ b/frontend/src/utils/nodeIcons.ts @@ -24,7 +24,7 @@ import { // Communications Mail, MessageSquare, Phone, // Misc devices - Printer, Smartphone, Search, Filter, BookOpen, PlugZap, Type, + Printer, Smartphone, Laptop, Search, Filter, BookOpen, PlugZap, Type, } from 'lucide-react' import type { LucideIcon } from 'lucide-react' @@ -50,6 +50,7 @@ export const ICON_REGISTRY: IconEntry[] = [ { key: 'wifi', label: 'Access Point', category: 'Infrastructure', icon: Wifi }, { key: 'circle', label: 'Generic', category: 'Infrastructure', icon: Circle }, { key: 'monitor', label: 'Workstation', category: 'Infrastructure', icon: Monitor }, + { key: 'laptop', label: 'Laptop', category: 'Infrastructure', icon: Laptop }, { key: 'smartphone', label: 'Phone / Mobile', category: 'Infrastructure', icon: Smartphone }, { key: 'printer', label: 'Printer', category: 'Infrastructure', icon: Printer }, { key: 'plugzap', label: 'CPL / Powerline', category: 'Infrastructure', icon: PlugZap }, @@ -167,6 +168,8 @@ export const NODE_TYPE_DEFAULT_ICONS: Record = { camera: Cctv, printer: Printer, computer: Monitor, + laptop: Laptop, + mobile: Smartphone, cpl: PlugZap, docker_host: Anchor, docker_container: Package, diff --git a/frontend/src/utils/themes.ts b/frontend/src/utils/themes.ts index 82c03e4..bce150a 100644 --- a/frontend/src/utils/themes.ts +++ b/frontend/src/utils/themes.ts @@ -56,6 +56,8 @@ export const THEMES: Record = { camera: { border: '#8b949e', icon: '#8b949e' }, printer: { border: '#8b949e', icon: '#8b949e' }, computer: { border: '#a855f7', icon: '#a855f7' }, + laptop: { border: '#a855f7', icon: '#a855f7' }, + mobile: { border: '#ec4899', icon: '#ec4899' }, cpl: { border: '#e3b341', icon: '#e3b341' }, docker_host: { border: '#2496ED', icon: '#2496ED' }, docker_container: { border: '#0ea5e9', icon: '#0ea5e9' }, @@ -117,6 +119,8 @@ export const THEMES: Record = { camera: { border: '#94a3b8', icon: '#94a3b8' }, printer: { border: '#94a3b8', icon: '#94a3b8' }, computer: { border: '#c084fc', icon: '#c084fc' }, + laptop: { border: '#c084fc', icon: '#c084fc' }, + mobile: { border: '#ec4899', icon: '#ec4899' }, cpl: { border: '#fbbf24', icon: '#fbbf24' }, docker_host: { border: '#2496ED', icon: '#2496ED' }, docker_container: { border: '#38bdf8', icon: '#38bdf8' }, @@ -178,6 +182,8 @@ export const THEMES: Record = { camera: { border: '#6b7280', icon: '#6b7280' }, printer: { border: '#6b7280', icon: '#6b7280' }, computer: { border: '#7c3aed', icon: '#7c3aed' }, + laptop: { border: '#7c3aed', icon: '#7c3aed' }, + mobile: { border: '#db2777', icon: '#db2777' }, cpl: { border: '#b45309', icon: '#b45309' }, docker_host: { border: '#2496ED', icon: '#2496ED' }, docker_container: { border: '#0369a1', icon: '#0369a1' }, @@ -239,6 +245,8 @@ export const THEMES: Record = { camera: { border: '#8888ff', icon: '#8888ff' }, printer: { border: '#8888ff', icon: '#8888ff' }, computer: { border: '#ff00ff', icon: '#ff00ff' }, + laptop: { border: '#ff00ff', icon: '#ff00ff' }, + mobile: { border: '#ff3399', icon: '#ff3399' }, cpl: { border: '#ffff00', icon: '#ffff00' }, docker_host: { border: '#00aaff', icon: '#00aaff' }, docker_container: { border: '#00ddff', icon: '#00ddff' }, @@ -300,6 +308,8 @@ export const THEMES: Record = { camera: { border: '#005500', icon: '#005500' }, printer: { border: '#005500', icon: '#005500' }, computer: { border: '#008822', icon: '#008822' }, + laptop: { border: '#008822', icon: '#008822' }, + mobile: { border: '#00cc66', icon: '#00cc66' }, cpl: { border: '#66ff33', icon: '#66ff33' }, docker_host: { border: '#00cc88', icon: '#00cc88' }, docker_container: { border: '#00aacc', icon: '#00aacc' }, @@ -361,6 +371,8 @@ export const THEMES: Record = { camera: { border: '#8b949e', icon: '#8b949e' }, printer: { border: '#8b949e', icon: '#8b949e' }, computer: { border: '#a855f7', icon: '#a855f7' }, + laptop: { border: '#a855f7', icon: '#a855f7' }, + mobile: { border: '#ec4899', icon: '#ec4899' }, cpl: { border: '#e3b341', icon: '#e3b341' }, docker_host: { border: '#2496ED', icon: '#2496ED' }, docker_container: { border: '#0ea5e9', icon: '#0ea5e9' },