207 lines
8.3 KiB
HTML
207 lines
8.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Datacenter Designer</title>
|
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='80' font-size='80'>🏢</text></svg>">
|
|
<link rel="stylesheet" href="css/style.css">
|
|
<!-- ag-Grid -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community@31/styles/ag-grid.css"/>
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community@31/styles/ag-theme-alpine.css"/>
|
|
</head>
|
|
<body>
|
|
<!-- Top Toolbar -->
|
|
<div class="toolbar">
|
|
<div class="project-selector">
|
|
<select id="projectSelect" class="form-select">
|
|
<option value="1">Loading...</option>
|
|
</select>
|
|
</div>
|
|
<div class="view-switcher-group">
|
|
<div class="view-switcher">
|
|
<button id="physicalViewBtn" class="btn-view active" title="Physical layout with racks">Physical</button>
|
|
<button id="logicalViewBtn" class="btn-view" title="Logical topology without racks">Logical</button>
|
|
</div>
|
|
<div class="view-switcher">
|
|
<button id="racksTableBtn" class="btn-view" title="Toggle racks table view">Racks</button>
|
|
<button id="devicesTableBtn" class="btn-view" title="Toggle devices table view">Devices</button>
|
|
<button id="connectionsTableBtn" class="btn-view" title="Toggle connections table view">Connections</button>
|
|
</div>
|
|
</div>
|
|
<div class="toolbar-spacer"></div>
|
|
<div class="toolbar-info">
|
|
<input type="number" id="zoomInput" class="zoom-input" min="10" max="300" step="10" value="100" title="Enter zoom percentage">
|
|
<span class="zoom-unit">%</span>
|
|
<button id="fitViewBtn" class="btn-sm" title="Fit all racks in view">Fit</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main Content Area with Split Panes -->
|
|
<div class="main-content">
|
|
<!-- Canvas Container (Top Pane) -->
|
|
<div id="canvasPane" class="canvas-pane">
|
|
<div id="canvasWrapper"></div>
|
|
</div>
|
|
|
|
<!-- Resize Handle -->
|
|
<div id="resizeHandle" class="resize-handle hidden"></div>
|
|
|
|
<!-- Table Container (Bottom Pane) -->
|
|
<div id="tablePane" class="table-pane hidden">
|
|
<div class="table-toolbar">
|
|
<button id="addTableRowBtn" class="btn btn-primary">+ Add Row</button>
|
|
<button id="deleteTableRowBtn" class="btn btn-secondary">Delete Selected</button>
|
|
<div style="flex: 1;"></div>
|
|
<button id="exportExcelBtn" class="btn btn-success" title="Export all tables to Excel (.xlsx)">Export to Excel</button>
|
|
</div>
|
|
<div id="tableContent" class="ag-theme-alpine"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Context Menu -->
|
|
<div id="contextMenu" class="context-menu hidden">
|
|
<ul id="contextMenuList"></ul>
|
|
</div>
|
|
|
|
<!-- Port Selection Modal -->
|
|
<div id="portModal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 id="portModalTitle">Select Port</h3>
|
|
<button class="modal-close" id="portModalClose">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="portList" class="port-list"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add Rack Modal -->
|
|
<div id="addRackModal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>Add Rack(s)</h3>
|
|
<button class="modal-close" id="addRackModalClose">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label for="rackCount">Number of racks:</label>
|
|
<input type="number" id="rackCount" min="1" max="20" value="3" class="form-input">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="rackPrefix">Name prefix:</label>
|
|
<input type="text" id="rackPrefix" value="RACK" class="form-input" placeholder="RACK">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Position:</label>
|
|
<div class="radio-group">
|
|
<label>
|
|
<input type="radio" name="rowPosition" value="continue" checked>
|
|
Continue row
|
|
<select id="continueRowSelect" class="form-select" style="margin-left: 8px; min-width: 80px; display: inline-block;">
|
|
<option value="0">1</option>
|
|
</select>
|
|
</label>
|
|
<label><input type="radio" name="rowPosition" value="below"> New row below</label>
|
|
<label><input type="radio" name="rowPosition" value="above"> New row above</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="preview-box">
|
|
<strong>Preview:</strong>
|
|
<div id="rackNamePreview" class="preview-names">RACK01, RACK02, RACK03</div>
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
<button id="createRacksBtn" class="btn btn-primary">Create</button>
|
|
<button id="cancelRacksBtn" class="btn btn-secondary">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add Device Modal -->
|
|
<div id="addDeviceModal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>Add Device</h3>
|
|
<button class="modal-close" id="addDeviceModalClose">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label>Select device type:</label>
|
|
<div id="deviceTypeList" class="device-type-grid"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Manage Projects Modal -->
|
|
<div id="manageProjectsModal" class="modal hidden">
|
|
<div class="modal-content modal-large">
|
|
<div class="modal-header">
|
|
<h3>Manage Projects</h3>
|
|
<button class="modal-close" id="manageProjectsModalClose">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="projects-toolbar">
|
|
<button id="newProjectBtnFromManage" class="btn btn-primary">+ New Project</button>
|
|
<div style="flex: 1;"></div>
|
|
<button id="exportProjectBtn" class="btn btn-secondary" title="Export current project to JSON file">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
<polyline points="7 10 12 15 17 10"></polyline>
|
|
<line x1="12" y1="15" x2="12" y2="3"></line>
|
|
</svg>
|
|
Export Project
|
|
</button>
|
|
<button id="importProjectBtn" class="btn btn-secondary" title="Import project from JSON file">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
<polyline points="17 8 12 3 7 8"></polyline>
|
|
<line x1="12" y1="3" x2="12" y2="15"></line>
|
|
</svg>
|
|
Import Project
|
|
</button>
|
|
<input type="file" id="importProjectInput" accept=".json" style="display: none;">
|
|
</div>
|
|
<div id="projectsList" class="projects-list"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- New/Edit Project Modal -->
|
|
<div id="projectFormModal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 id="projectFormTitle">New Project</h3>
|
|
<button class="modal-close" id="projectFormModalClose">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label for="projectName">Project name:</label>
|
|
<input type="text" id="projectName" class="form-input" placeholder="My Datacenter Project">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="projectDescription">Description (optional):</label>
|
|
<textarea id="projectDescription" class="form-input" rows="3" placeholder="Project description..."></textarea>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button id="saveProjectBtn" class="btn btn-primary">Save</button>
|
|
<button id="cancelProjectBtn" class="btn btn-secondary">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scripts -->
|
|
<script src="https://cdn.jsdelivr.net/npm/ag-grid-community@31/dist/ag-grid-community.min.js"></script>
|
|
<script src="https://unpkg.com/konva@9/konva.min.js"></script>
|
|
<script src="https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js"></script>
|
|
<script src="js/app.js" type="module"></script>
|
|
</body>
|
|
</html>
|