diff --git a/frontend/src/components/canvas/nodes/index.tsx b/frontend/src/components/canvas/nodes/index.tsx
index aec536d..4a71324 100644
--- a/frontend/src/components/canvas/nodes/index.tsx
+++ b/frontend/src/components/canvas/nodes/index.tsx
@@ -23,4 +23,5 @@ export const PrinterNode = (props: N) =>
export const ComputerNode = (props: N) =>
export const CplNode = (props: N) =>
export const DockerNode = (props: N) =>
+export const DockerContainerNode = (props: N) =>
export const GenericNode = (props: N) =>
diff --git a/frontend/src/components/canvas/nodes/nodeTypes.ts b/frontend/src/components/canvas/nodes/nodeTypes.ts
index 00ae141..a70c4dc 100644
--- a/frontend/src/components/canvas/nodes/nodeTypes.ts
+++ b/frontend/src/components/canvas/nodes/nodeTypes.ts
@@ -1,4 +1,4 @@
-import { IspNode, RouterNode, SwitchNode, ServerNode, VmNode, LxcNode, NasNode, IotNode, ApNode, CameraNode, PrinterNode, ComputerNode, CplNode, DockerNode, GenericNode } from './index'
+import { IspNode, RouterNode, SwitchNode, ServerNode, VmNode, LxcNode, NasNode, IotNode, ApNode, CameraNode, PrinterNode, ComputerNode, CplNode, DockerNode, DockerContainerNode, GenericNode } from './index'
import { ProxmoxGroupNode } from './ProxmoxGroupNode'
import { GroupRectNode } from './GroupRectNode'
import { GroupNode } from './GroupNode'
@@ -19,6 +19,7 @@ export const nodeTypes = {
computer: ComputerNode,
cpl: CplNode,
docker: DockerNode,
+ docker_container: DockerContainerNode,
generic: GenericNode,
groupRect: GroupRectNode,
group: GroupNode,
diff --git a/frontend/src/components/modals/NodeModal.tsx b/frontend/src/components/modals/NodeModal.tsx
index c39f078..6f50fee 100644
--- a/frontend/src/components/modals/NodeModal.tsx
+++ b/frontend/src/components/modals/NodeModal.tsx
@@ -1,4 +1,4 @@
-import { createElement, useState } from 'react'
+import { Fragment, createElement, useState } from 'react'
import { RotateCcw, ChevronDown } from 'lucide-react'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
@@ -11,7 +11,7 @@ import { ICON_REGISTRY, ICON_CATEGORIES, NODE_TYPE_DEFAULT_ICONS } from '@/utils
const NODE_TYPE_GROUPS: { label: string; types: NodeType[] }[] = [
{ label: 'Hardware', types: ['isp', 'router', 'switch', 'server', 'nas', 'ap', 'printer'] },
- { label: 'Virtualization', types: ['proxmox', 'vm', 'lxc', 'docker'] },
+ { label: 'Virtualization', types: ['proxmox', 'vm', 'lxc', 'docker', 'docker_container'] },
{ label: 'IoT', types: ['iot', 'camera', 'cpl'] },
{ label: 'Generic', types: ['computer', 'generic', 'groupRect'] },
]
@@ -78,11 +78,11 @@ export function NodeModal({ open, onClose, onSubmit, initial, title = 'Add Node'
diff --git a/frontend/src/components/modals/SearchModal.tsx b/frontend/src/components/modals/SearchModal.tsx
index 10f4b5c..824eb53 100644
--- a/frontend/src/components/modals/SearchModal.tsx
+++ b/frontend/src/components/modals/SearchModal.tsx
@@ -4,6 +4,7 @@ import { Search } from 'lucide-react'
import { useCanvasStore } from '@/stores/canvasStore'
import { scanApi } from '@/api/client'
import type { PendingDevice } from '@/components/modals/PendingDeviceModal'
+import { NODE_TYPE_LABELS } from '@/types'
interface SearchModalProps {
open: boolean
@@ -89,7 +90,7 @@ export function SearchModal({ open, onClose, onOpenPending }: SearchModalProps)
className="flex items-center gap-3 px-4 py-2 hover:bg-[#21262d] cursor-pointer"
onClick={() => handleSelectNode(node.id)}
>
- {node.data.type}
+ {NODE_TYPE_LABELS[node.data.type] ?? node.data.type}
{node.data.label}
{node.data.ip && (
{node.data.ip}
diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts
index 2481349..5e522eb 100644
--- a/frontend/src/types/index.ts
+++ b/frontend/src/types/index.ts
@@ -14,6 +14,7 @@ export type NodeType =
| 'computer'
| 'cpl'
| 'docker'
+ | 'docker_container'
| 'generic'
| 'groupRect'
| 'group'
@@ -127,6 +128,7 @@ export const NODE_TYPE_LABELS: Record = {
computer: 'Computer',
cpl: 'CPL / Powerline',
docker: 'Docker Host',
+ docker_container: 'Docker Container',
generic: 'Generic Device',
groupRect: 'Group Rectangle',
group: 'Node Group',
diff --git a/frontend/src/utils/__tests__/themes.test.ts b/frontend/src/utils/__tests__/themes.test.ts
index aa06ea5..0b93166 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', 'switch', 'server', 'proxmox', 'vm', 'lxc',
- 'nas', 'iot', 'ap', 'camera', 'printer', 'computer', 'cpl', 'docker', 'generic', 'groupRect',
+ 'nas', 'iot', 'ap', 'camera', 'printer', 'computer', 'cpl', 'docker', '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 6dbf5f5..dc44049 100644
--- a/frontend/src/utils/nodeIcons.ts
+++ b/frontend/src/utils/nodeIcons.ts
@@ -133,6 +133,7 @@ export const NODE_TYPE_DEFAULT_ICONS: Record = {
computer: Monitor,
cpl: PlugZap,
docker: Anchor,
+ docker_container: Container,
generic: Circle,
group: Circle,
groupRect: Circle,
diff --git a/frontend/src/utils/themes.ts b/frontend/src/utils/themes.ts
index 23d0be0..1d5c90a 100644
--- a/frontend/src/utils/themes.ts
+++ b/frontend/src/utils/themes.ts
@@ -57,6 +57,7 @@ export const THEMES: Record = {
computer: { border: '#a855f7', icon: '#a855f7' },
cpl: { border: '#e3b341', icon: '#e3b341' },
docker: { border: '#2496ED', icon: '#2496ED' },
+ docker_container: { border: '#38bdf8', icon: '#38bdf8' },
generic: { border: '#8b949e', icon: '#8b949e' },
groupRect:{ border: '#00d4ff', icon: '#00d4ff' },
group: { border: '#00d4ff', icon: '#00d4ff' },
@@ -112,6 +113,7 @@ export const THEMES: Record = {
computer: { border: '#c084fc', icon: '#c084fc' },
cpl: { border: '#fbbf24', icon: '#fbbf24' },
docker: { border: '#2496ED', icon: '#2496ED' },
+ docker_container: { border: '#38bdf8', icon: '#38bdf8' },
generic: { border: '#94a3b8', icon: '#94a3b8' },
groupRect:{ border: '#22d3ee', icon: '#22d3ee' },
group: { border: '#22d3ee', icon: '#22d3ee' },
@@ -167,6 +169,7 @@ export const THEMES: Record = {
computer: { border: '#7c3aed', icon: '#7c3aed' },
cpl: { border: '#b45309', icon: '#b45309' },
docker: { border: '#2496ED', icon: '#2496ED' },
+ docker_container: { border: '#0ea5e9', icon: '#0ea5e9' },
generic: { border: '#6b7280', icon: '#6b7280' },
groupRect:{ border: '#0284c7', icon: '#0284c7' },
group: { border: '#0284c7', icon: '#0284c7' },
@@ -222,6 +225,7 @@ export const THEMES: Record = {
computer: { border: '#ff00ff', icon: '#ff00ff' },
cpl: { border: '#ffff00', icon: '#ffff00' },
docker: { border: '#00aaff', icon: '#00aaff' },
+ docker_container: { border: '#00ddff', icon: '#00ddff' },
generic: { border: '#8888ff', icon: '#8888ff' },
groupRect:{ border: '#00ffff', icon: '#00ffff' },
group: { border: '#00ffff', icon: '#00ffff' },
@@ -277,6 +281,7 @@ export const THEMES: Record = {
computer: { border: '#008822', icon: '#008822' },
cpl: { border: '#66ff33', icon: '#66ff33' },
docker: { border: '#00cc88', icon: '#00cc88' },
+ docker_container: { border: '#00dd99', icon: '#00dd99' },
generic: { border: '#006600', icon: '#006600' },
groupRect:{ border: '#00ff41', icon: '#00ff41' },
group: { border: '#00ff41', icon: '#00ff41' },