12d527aad6
Make designs (canvases) fully user-manageable: create with a chosen name and icon, rename, change icon, and delete. Replaces the hardcoded "New Electrical Design" button with a generic "New Canvas" flow. - Add Design.icon column + migration that backfills legacy rows (electrical -> zap, others -> dashboard) - DesignModal: name input + curated lucide icon picker (create + edit) - Sidebar switcher gains per-canvas edit/delete; delete guards the last canvas and confirms - designStore: addDesign/updateDesign/removeDesign with active reassignment - Fix data loss on design switch: abort load when the save fails and keep unsaved edits; skip the save-old step when the previous canvas was deleted - designsApi create/update carry icon; design_type kept for back-compat Tests: backend design CRUD (icon + cascade + last-canvas guard), designStore actions, designIcons resolver, DesignModal create/edit/validation. ha-relevant: yes
45 lines
1.7 KiB
TypeScript
45 lines
1.7 KiB
TypeScript
import {
|
|
LayoutDashboard, Zap, Network, Server, HardDrive, Cpu, Wifi, Router,
|
|
Database, Cloud, Home, Globe, Lightbulb, Factory, Plug, Boxes,
|
|
} from 'lucide-react'
|
|
import type { LucideIcon } from 'lucide-react'
|
|
|
|
export interface DesignIconEntry {
|
|
key: string
|
|
label: string
|
|
icon: LucideIcon
|
|
}
|
|
|
|
/** Curated icon set offered when creating/editing a canvas design. Keys are
|
|
* stable strings persisted on `Design.icon`. */
|
|
export const DESIGN_ICONS: DesignIconEntry[] = [
|
|
{ key: 'dashboard', label: 'Dashboard', icon: LayoutDashboard },
|
|
{ key: 'network', label: 'Network', icon: Network },
|
|
{ key: 'zap', label: 'Electrical', icon: Zap },
|
|
{ key: 'server', label: 'Server', icon: Server },
|
|
{ key: 'harddrive', label: 'Storage', icon: HardDrive },
|
|
{ key: 'cpu', label: 'Compute', icon: Cpu },
|
|
{ key: 'wifi', label: 'Wireless', icon: Wifi },
|
|
{ key: 'router', label: 'Router', icon: Router },
|
|
{ key: 'database', label: 'Database', icon: Database },
|
|
{ key: 'cloud', label: 'Cloud', icon: Cloud },
|
|
{ key: 'home', label: 'Home', icon: Home },
|
|
{ key: 'globe', label: 'Internet', icon: Globe },
|
|
{ key: 'lightbulb', label: 'Lighting', icon: Lightbulb },
|
|
{ key: 'factory', label: 'Industrial', icon: Factory },
|
|
{ key: 'plug', label: 'Power', icon: Plug },
|
|
{ key: 'boxes', label: 'Cluster', icon: Boxes },
|
|
]
|
|
|
|
export const DEFAULT_DESIGN_ICON = 'dashboard'
|
|
|
|
const ICON_MAP: Record<string, LucideIcon> = Object.fromEntries(
|
|
DESIGN_ICONS.map((e) => [e.key, e.icon]),
|
|
)
|
|
|
|
/** Resolve a persisted design icon key to a lucide component. Unknown/empty
|
|
* keys fall back to the dashboard icon so the UI never breaks on legacy data. */
|
|
export function resolveDesignIcon(key?: string | null): LucideIcon {
|
|
return (key && ICON_MAP[key]) || LayoutDashboard
|
|
}
|