feat: network diagrams UX overhaul — icons, empty canvas, properties panel
- Colorize: semantic category colors for all device types (network=blue, security=orange, compute=emerald, endpoint=amber, storage=violet, cloud=cyan, infra=steel); better icons (Router, ShieldAlert, Boxes, Package, Gauge, PlugZap, Video, Radio); MiniMap uses category colors - Onboard: centered AI generate prompt on empty canvas with 5 MSP-specific example chips, ⌘↵ shortcut, spinner; AIAssistPanel only shown with nodes - Arrange: properties panel — status badge grid at top, fields grouped into Network (IP/Subnet/VLAN) and Hardware (Hostname/Vendor/Model/Role) sections - Delight: segmented topology color bar on listing cards; backend returns category_counts via single extra query on list endpoint - Harden: real PNG export via html-to-image + getNodesBounds/getViewportForBounds - Polish: ChevronDown replaces unicode ▾, click-outside for client filter, consistent spinner in empty prompt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import type { LucideIcon } from 'lucide-react'
|
||||
import {
|
||||
Network, Layers, Shield, Wifi, Server, Monitor, Box, Cloud,
|
||||
Printer, Smartphone, HardDrive, Scale, Database, CloudCog,
|
||||
Cpu, Tablet, Laptop, BatteryCharging, LayoutGrid, RectangleVertical,
|
||||
Cable, Camera, KeyRound, Globe,
|
||||
Router, Layers, ShieldAlert, Wifi, Server, Monitor, Boxes, Package, Cloud,
|
||||
Printer, Smartphone, HardDrive, Gauge, Database, CloudCog,
|
||||
Cpu, Tablet, Laptop, BatteryCharging, RectangleVertical,
|
||||
Cable, Camera, KeyRound, Globe, Video, PlugZap, Radio,
|
||||
} from 'lucide-react'
|
||||
|
||||
export interface DeviceRenderConfig {
|
||||
@@ -11,49 +11,78 @@ export interface DeviceRenderConfig {
|
||||
color: string
|
||||
}
|
||||
|
||||
// Category-semantic color palette — each color carries meaning:
|
||||
// Network (blue) — backbone connectivity layer
|
||||
// Security (orange) — critical/protective elements
|
||||
// Compute (emerald)— running workloads and VMs
|
||||
// Endpoint (amber) — user-facing devices
|
||||
// Storage (violet) — data at rest
|
||||
// Cloud (cyan) — external/internet-connected
|
||||
// Infra (steel) — physical/passive hardware
|
||||
export const NETWORK_COLOR = '#60a5fa'
|
||||
export const SECURITY_COLOR = '#f97316'
|
||||
export const COMPUTE_COLOR = '#34d399'
|
||||
export const ENDPOINT_COLOR = '#fbbf24'
|
||||
export const STORAGE_COLOR = '#a78bfa'
|
||||
export const CLOUD_COLOR = '#67e8f9'
|
||||
export const INFRA_COLOR = '#94a3b8'
|
||||
|
||||
const SYSTEM_DEVICE_ICONS: Record<string, DeviceRenderConfig> = {
|
||||
'router': { icon: Network, color: 'var(--color-accent)' },
|
||||
'switch': { icon: Layers, color: 'var(--color-text-muted-foreground)' },
|
||||
'firewall': { icon: Shield, color: 'var(--color-accent)' },
|
||||
'access-point': { icon: Wifi, color: 'var(--color-text-muted-foreground)' },
|
||||
'load-balancer': { icon: Scale, color: 'var(--color-text-muted-foreground)' },
|
||||
'server': { icon: Server, color: 'var(--color-text-muted-foreground)' },
|
||||
'workstation': { icon: Monitor, color: 'var(--color-text-muted-foreground)' },
|
||||
'vm': { icon: Box, color: 'var(--color-text-muted-foreground)' },
|
||||
'container': { icon: Cpu, color: 'var(--color-text-muted-foreground)' },
|
||||
'nas': { icon: Database, color: 'var(--color-text-muted-foreground)' },
|
||||
'san': { icon: HardDrive, color: 'var(--color-text-muted-foreground)' },
|
||||
'cloud-storage': { icon: CloudCog, color: 'var(--color-text-muted-foreground)' },
|
||||
'cloud': { icon: Cloud, color: 'var(--color-text-muted-foreground)' },
|
||||
'aws': { icon: Cloud, color: 'var(--color-text-muted-foreground)' },
|
||||
'azure': { icon: Cloud, color: 'var(--color-text-muted-foreground)' },
|
||||
'gcp': { icon: Cloud, color: 'var(--color-text-muted-foreground)' },
|
||||
'isp': { icon: Globe, color: 'var(--color-accent)' },
|
||||
'printer': { icon: Printer, color: 'var(--color-text-muted-foreground)' },
|
||||
'phone': { icon: Smartphone, color: 'var(--color-text-muted-foreground)' },
|
||||
'iot': { icon: HardDrive, color: 'var(--color-text-muted-foreground)' },
|
||||
'camera': { icon: Camera, color: 'var(--color-text-muted-foreground)' },
|
||||
'tablet': { icon: Tablet, color: 'var(--color-text-muted-foreground)' },
|
||||
'laptop': { icon: Laptop, color: 'var(--color-text-muted-foreground)' },
|
||||
'ups': { icon: BatteryCharging, color: 'var(--color-text-muted-foreground)' },
|
||||
'pdu': { icon: LayoutGrid, color: 'var(--color-text-muted-foreground)' },
|
||||
'rack': { icon: RectangleVertical, color: 'var(--color-text-muted-foreground)' },
|
||||
'patch-panel': { icon: Cable, color: 'var(--color-text-muted-foreground)' },
|
||||
'nvr': { icon: Camera, color: 'var(--color-text-muted-foreground)' },
|
||||
'badge-reader': { icon: KeyRound, color: 'var(--color-text-muted-foreground)' },
|
||||
// Network layer
|
||||
'router': { icon: Router, color: NETWORK_COLOR },
|
||||
'switch': { icon: Layers, color: NETWORK_COLOR },
|
||||
'access-point': { icon: Wifi, color: NETWORK_COLOR },
|
||||
'load-balancer': { icon: Gauge, color: NETWORK_COLOR },
|
||||
|
||||
// Security
|
||||
'firewall': { icon: ShieldAlert, color: SECURITY_COLOR },
|
||||
'badge-reader': { icon: KeyRound, color: SECURITY_COLOR },
|
||||
|
||||
// Compute
|
||||
'server': { icon: Server, color: COMPUTE_COLOR },
|
||||
'vm': { icon: Boxes, color: COMPUTE_COLOR },
|
||||
'container': { icon: Package, color: COMPUTE_COLOR },
|
||||
|
||||
// Storage
|
||||
'nas': { icon: Database, color: STORAGE_COLOR },
|
||||
'san': { icon: HardDrive, color: STORAGE_COLOR },
|
||||
'cloud-storage': { icon: CloudCog, color: STORAGE_COLOR },
|
||||
|
||||
// Cloud / Internet
|
||||
'cloud': { icon: Cloud, color: CLOUD_COLOR },
|
||||
'aws': { icon: Cloud, color: CLOUD_COLOR },
|
||||
'azure': { icon: Cloud, color: CLOUD_COLOR },
|
||||
'gcp': { icon: Cloud, color: CLOUD_COLOR },
|
||||
'isp': { icon: Globe, color: CLOUD_COLOR },
|
||||
|
||||
// Endpoints
|
||||
'workstation': { icon: Monitor, color: ENDPOINT_COLOR },
|
||||
'laptop': { icon: Laptop, color: ENDPOINT_COLOR },
|
||||
'tablet': { icon: Tablet, color: ENDPOINT_COLOR },
|
||||
'phone': { icon: Smartphone, color: ENDPOINT_COLOR },
|
||||
'printer': { icon: Printer, color: ENDPOINT_COLOR },
|
||||
|
||||
// Infrastructure / physical
|
||||
'ups': { icon: BatteryCharging, color: INFRA_COLOR },
|
||||
'pdu': { icon: PlugZap, color: INFRA_COLOR },
|
||||
'rack': { icon: RectangleVertical, color: INFRA_COLOR },
|
||||
'patch-panel': { icon: Cable, color: INFRA_COLOR },
|
||||
'camera': { icon: Camera, color: INFRA_COLOR },
|
||||
'nvr': { icon: Video, color: INFRA_COLOR },
|
||||
'iot': { icon: Radio, color: INFRA_COLOR },
|
||||
}
|
||||
|
||||
const CATEGORY_DEFAULTS: Record<string, DeviceRenderConfig> = {
|
||||
'network': { icon: Network, color: 'var(--color-text-muted-foreground)' },
|
||||
'compute': { icon: Server, color: 'var(--color-text-muted-foreground)' },
|
||||
'storage': { icon: Database, color: 'var(--color-text-muted-foreground)' },
|
||||
'cloud': { icon: Cloud, color: 'var(--color-text-muted-foreground)' },
|
||||
'endpoint': { icon: Monitor, color: 'var(--color-text-muted-foreground)' },
|
||||
'infrastructure': { icon: LayoutGrid, color: 'var(--color-text-muted-foreground)' },
|
||||
'security': { icon: Shield, color: 'var(--color-text-muted-foreground)' },
|
||||
'network': { icon: Router, color: NETWORK_COLOR },
|
||||
'compute': { icon: Server, color: COMPUTE_COLOR },
|
||||
'storage': { icon: Database, color: STORAGE_COLOR },
|
||||
'cloud': { icon: Cloud, color: CLOUD_COLOR },
|
||||
'endpoint': { icon: Monitor, color: ENDPOINT_COLOR },
|
||||
'infrastructure': { icon: PlugZap, color: INFRA_COLOR },
|
||||
'security': { icon: ShieldAlert, color: SECURITY_COLOR },
|
||||
}
|
||||
|
||||
const FALLBACK: DeviceRenderConfig = { icon: Box, color: 'var(--color-text-muted-foreground)' }
|
||||
const FALLBACK: DeviceRenderConfig = { icon: Cpu, color: INFRA_COLOR }
|
||||
|
||||
export function getDeviceRenderConfig(slug: string, category?: string): DeviceRenderConfig {
|
||||
if (SYSTEM_DEVICE_ICONS[slug]) return SYSTEM_DEVICE_ICONS[slug]
|
||||
@@ -62,13 +91,23 @@ export function getDeviceRenderConfig(slug: string, category?: string): DeviceRe
|
||||
}
|
||||
|
||||
export const CATEGORY_LABELS: Record<string, string> = {
|
||||
'network': 'Network',
|
||||
'compute': 'Compute',
|
||||
'storage': 'Storage',
|
||||
'cloud': 'Cloud',
|
||||
'endpoint': 'Endpoints',
|
||||
'network': 'Network',
|
||||
'compute': 'Compute',
|
||||
'storage': 'Storage',
|
||||
'cloud': 'Cloud',
|
||||
'endpoint': 'Endpoints',
|
||||
'infrastructure': 'Infrastructure',
|
||||
'security': 'Security',
|
||||
'security': 'Security',
|
||||
}
|
||||
|
||||
export const CATEGORY_COLORS: Record<string, string> = {
|
||||
'network': NETWORK_COLOR,
|
||||
'compute': COMPUTE_COLOR,
|
||||
'storage': STORAGE_COLOR,
|
||||
'cloud': CLOUD_COLOR,
|
||||
'endpoint': ENDPOINT_COLOR,
|
||||
'infrastructure': INFRA_COLOR,
|
||||
'security': SECURITY_COLOR,
|
||||
}
|
||||
|
||||
export const CATEGORY_ORDER = ['network', 'compute', 'storage', 'cloud', 'endpoint', 'infrastructure', 'security']
|
||||
|
||||
Reference in New Issue
Block a user