From d077c68e9661ab1caf9e4ebbc25206fdff356a23 Mon Sep 17 00:00:00 2001 From: mpuckett Date: Thu, 14 May 2026 18:22:01 -0500 Subject: [PATCH] Added fields for managed info --- README.md | 7 ++++- src/App.tsx | 68 +++++++++++++++++++++++++++++++++++++++++++++- src/types.ts | 4 +++ src/utils/model.ts | 8 ++++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e028d51..0d77e6e 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,11 @@ Datacenter Modeler is a React-based web application for designing datacenter rac - Edit component port-map properties for Switch, Firewall, Storage Switch, Router, Server, Blade Chassis, Storage Array, and KVM: - Dynamic port map with Port ID, Cable ID, and VLAN fields - VLAN defaults to 1 for new component ports +- Edit managed-device properties for Switch, Firewall, Storage Switch, Router, Server, Blade Chassis, Storage Array, and KVM: + - Managed status + - IP address/hostname + - URL + - User - Edit PDU-specific properties: - Horizontal rack mount or vertical side mount - Horizontal size from 1U to 12U @@ -149,7 +154,7 @@ Diagram data is stored as JSON with this top-level shape: } ``` -Each rack/cabinet contains its own metadata and an array of installed equipment. Equipment records include type, name, size, U position, manufacturer/model details, asset information, power, notes, and display color. Patch panel and network-capable component records also include structured port map metadata. PDU records include mounting orientation, side placement for vertical PDUs, input voltage, output port definitions, and managed-device connection metadata. +Each rack/cabinet contains its own metadata and an array of installed equipment. Equipment records include type, name, size, U position, manufacturer/model details, asset information, power, notes, and display color. Patch panel and network-capable component records also include structured port map metadata. Network-capable components and PDUs can store managed-device connection metadata. ## Project Structure diff --git a/src/App.tsx b/src/App.tsx index d8a3741..3d90e14 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -536,6 +536,10 @@ export default function App() { ? ` | ${item.patchPanelMedium === 'fiberoptic' ? 'Fiber optic' : 'Copper'} | ${item.patchPanelPorts} ports | ${item.patchPanelPortMap.length} mapped` : ''; const networkPortDetails = PORT_MAPPED_COMPONENTS.has(item.type) ? ` | ${item.networkPorts.length} mapped ports` : ''; + const managedDetails = + PORT_MAPPED_COMPONENTS.has(item.type) && item.managed + ? ` | Managed ${item.managedHostname || 'no host'}` + : ''; const pduDetails = item.type === 'pdu' ? ` | ${item.pduMount === 'vertical' ? `Vertical ${item.pduSide}, ${item.sizeU}U wide` : `Horizontal ${item.sizeU}U`} | In ${item.pduInputVoltage || 'n/a'} | ${item.pduOutputPorts.length} outputs${item.pduManaged ? ` | Managed ${item.pduHostname || 'no host'}` : ''}` @@ -544,7 +548,7 @@ export default function App() { item.type === 'pdu' && item.pduMount === 'vertical' ? `${item.pduSide === 'left' ? 'Left' : 'Right'} side` : `U${item.uStart}-${item.uStart + item.sizeU - 1}`; - const line = `${rackPosition}: ${item.name} | ${item.manufacturer || 'n/a'} ${item.model || ''} | ${item.assetTag || 'no asset tag'}${patchPanelDetails}${networkPortDetails}${pduDetails}`; + const line = `${rackPosition}: ${item.name} | ${item.manufacturer || 'n/a'} ${item.model || ''} | ${item.assetTag || 'no asset tag'}${patchPanelDetails}${networkPortDetails}${managedDetails}${pduDetails}`; pdf.text(line.slice(0, 115), margin + 12, y); y += 14; }); @@ -1443,6 +1447,68 @@ function PropertiesPanel({ )} + {PORT_MAPPED_COMPONENTS.has(selectedEquipment.type) && ( + <> + + + Managed Device + + + + Managed + + + onEquipmentChange(selectedEquipmentRack.id, selectedEquipment.id, { + managed: (value as number) === 1, + }) + } + /> + + {selectedEquipment.managed && ( + <> + + onEquipmentChange(selectedEquipmentRack.id, selectedEquipment.id, { + managedHostname: event.target.value, + }) + } + fullWidth + /> + + onEquipmentChange(selectedEquipmentRack.id, selectedEquipment.id, { + managedUrl: event.target.value, + }) + } + fullWidth + /> + + onEquipmentChange(selectedEquipmentRack.id, selectedEquipment.id, { + managedUser: event.target.value, + }) + } + fullWidth + /> + + )} + + )} {selectedEquipment.type === 'pdu' && ( <> diff --git a/src/types.ts b/src/types.ts index 9cf4fb1..728ed09 100644 --- a/src/types.ts +++ b/src/types.ts @@ -69,6 +69,10 @@ export interface Equipment { patchPanelPorts: number; patchPanelPortMap: PatchPanelPort[]; networkPorts: NetworkPort[]; + managed: boolean; + managedHostname: string; + managedUrl: string; + managedUser: string; pduMount: PduMount; pduSide: PduSide; pduInputVoltage: string; diff --git a/src/utils/model.ts b/src/utils/model.ts index e0b1c6b..e0612cf 100644 --- a/src/utils/model.ts +++ b/src/utils/model.ts @@ -57,6 +57,10 @@ export const createEquipment = (type: string, rack: RackContainer, preferredU: n patchPanelPorts: libraryItem.type === 'patch-panel' ? 24 : 0, patchPanelPortMap: [], networkPorts: [], + managed: false, + managedHostname: '', + managedUrl: '', + managedUser: '', pduMount: 'horizontal', pduSide: 'right', pduInputVoltage: '', @@ -186,6 +190,10 @@ export const normalizeDiagram = (value: unknown): DiagramData => { patchPanelPorts: clampNumber(item.patchPanelPorts, 0, 10000, libraryItem.type === 'patch-panel' ? 24 : 0), patchPanelPortMap: normalizePatchPanelPorts(legacyItem.patchPanelPortMap, legacyItem.patchPanelPortIdentification), networkPorts: normalizeNetworkPorts(legacyItem.networkPorts ?? legacyItem.switchPorts), + managed: Boolean(item.managed), + managedHostname: item.managedHostname || '', + managedUrl: item.managedUrl || '', + managedUser: item.managedUser || '', pduMount, pduSide: item.pduSide === 'left' ? 'left' : 'right', pduInputVoltage: item.pduInputVoltage || '',