Implement fleet status page with full table view, bulk actions, and camera fly-to
Features implemented: - Full table with sortable columns: Name, MAC, Role, Position, Firmware, RSSI, Status, Uptime, Actions - Role dropdown for changing node roles - Position column with camera fly-to on click - Firmware version with update badge - Bulk actions: Update All, Re-baseline All, Export Config, Import Config, CSV Report - Node actions: Restart, Update, Remove, Identify (blink LED) - Responsive design for desktop and mobile - Toast notifications and modal dialogs
This commit is contained in:
parent
78bf88a7ff
commit
b55147b8d9
3 changed files with 109 additions and 1 deletions
|
|
@ -1051,6 +1051,64 @@ body.fleet-page {
|
|||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
/* Import Modal */
|
||||
.file-input {
|
||||
width: 100%;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-control);
|
||||
color: var(--text-primary);
|
||||
font-size: var(--text-sm);
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.file-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--blue-9);
|
||||
}
|
||||
|
||||
.import-info {
|
||||
margin-top: var(--space-4);
|
||||
padding: var(--space-3);
|
||||
background: var(--overlay);
|
||||
border-radius: var(--radius-control);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.import-info p {
|
||||
margin: var(--space-2) 0;
|
||||
}
|
||||
|
||||
.import-warning-text {
|
||||
color: var(--alert);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
/* Position Column */
|
||||
.col-position {
|
||||
min-width: 100px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
.position-link {
|
||||
color: var(--blue-9);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.position-link:hover {
|
||||
color: var(--blue-10);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.position-empty {
|
||||
color: var(--text-muted);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
Toast Notifications
|
||||
============================================ */
|
||||
|
|
|
|||
|
|
@ -60,13 +60,25 @@
|
|||
<span class="icon">↻</span>
|
||||
<span class="label">Refresh</span>
|
||||
</button>
|
||||
<button id="fleet-rebaseline-btn" class="btn btn-secondary" title="Re-baseline all links">
|
||||
<span class="icon">↻</span>
|
||||
<span class="label">Re-baseline All</span>
|
||||
</button>
|
||||
<button id="fleet-update-all-btn" class="btn btn-action" title="Update all nodes to latest firmware">
|
||||
<span class="icon">↑</span>
|
||||
<span class="label">Update All</span>
|
||||
</button>
|
||||
<button id="fleet-export-btn" class="btn btn-secondary" title="Export configuration">
|
||||
<span class="icon">↓</span>
|
||||
<span class="label">Export</span>
|
||||
</button>
|
||||
<button id="fleet-import-btn" class="btn btn-secondary" title="Import configuration">
|
||||
<span class="icon">↑</span>
|
||||
<span class="label">Import</span>
|
||||
</button>
|
||||
<button id="fleet-download-btn" class="btn btn-secondary" title="Download CSV report">
|
||||
<span class="icon">↓</span>
|
||||
<span class="label">Download Report</span>
|
||||
<span class="label">CSV Report</span>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
|
@ -140,6 +152,9 @@
|
|||
<th class="col-uptime sortable" data-sort="uptime">
|
||||
Uptime
|
||||
</th>
|
||||
<th class="col-position sortable" data-sort="position">
|
||||
Position
|
||||
</th>
|
||||
<th class="col-role sortable" data-sort="role">
|
||||
Role
|
||||
</th>
|
||||
|
|
@ -264,6 +279,28 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="import-modal" style="display: none;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>Import Configuration</h3>
|
||||
<button class="modal-close" data-modal="import-modal">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Select a configuration file to import. This will replace all nodes, zones, and settings.</p>
|
||||
<input type="file" id="import-file-input" accept=".json" class="file-input">
|
||||
<div class="import-info" id="import-info" style="display: none;">
|
||||
<p><strong>File:</strong> <span id="import-filename"></span></p>
|
||||
<p><strong>Nodes:</strong> <span id="import-nodes-count">0</span></p>
|
||||
<p class="import-warning-text">This action cannot be undone. Existing configuration will be replaced.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary modal-close" data-modal="import-modal">Cancel</button>
|
||||
<button class="btn btn-primary" id="import-confirm-btn" disabled>Import</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast-container" id="toast-container"></div>
|
||||
|
||||
<!-- Mobile bottom nav -->
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@
|
|||
// Header actions
|
||||
refreshBtn: document.getElementById('fleet-refresh-btn'),
|
||||
updateAllBtn: document.getElementById('fleet-update-all-btn'),
|
||||
rebaselineBtn: document.getElementById('fleet-rebaseline-btn'),
|
||||
exportBtn: document.getElementById('fleet-export-btn'),
|
||||
importBtn: document.getElementById('fleet-import-btn'),
|
||||
downloadBtn: document.getElementById('fleet-download-btn'),
|
||||
|
||||
// Empty state
|
||||
|
|
@ -115,6 +118,16 @@
|
|||
removeNodeCount: document.getElementById('remove-node-count'),
|
||||
removeNodeList: document.getElementById('remove-node-list'),
|
||||
|
||||
// Import modal elements
|
||||
importModal: document.getElementById('import-modal'),
|
||||
importFileInput: document.getElementById('import-file-input'),
|
||||
importConfirmBtn: document.getElementById('import-confirm-btn'),
|
||||
importInfo: document.getElementById('import-info'),
|
||||
importFilename: document.getElementById('import-filename'),
|
||||
importNodesCount: document.getElementById('import-nodes-count'),
|
||||
// Hidden file input for export
|
||||
exportFileInput: document.getElementById('export-file-input'),
|
||||
|
||||
// Unpaired elements
|
||||
unpairedSummary: document.getElementById('fleet-unpaired-summary'),
|
||||
unpairedCount: document.getElementById('fleet-unpaired'),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue