interface update
This commit is contained in:
22
app.py
22
app.py
@ -83,13 +83,23 @@ class UnifiAPI:
|
|||||||
|
|
||||||
diagnostics = {
|
diagnostics = {
|
||||||
'state': details.get('state', 'unknown'),
|
'state': details.get('state', 'unknown'),
|
||||||
'system': {
|
'interfaces': {
|
||||||
'cpu': details.get('system_stats', {}).get('cpu', 0),
|
'ports': {}
|
||||||
'memory': details.get('system_stats', {}).get('mem', 0),
|
}
|
||||||
'temperature': details.get('general_temperature', 0)
|
|
||||||
},
|
|
||||||
'interfaces': self._parse_interfaces(details.get('port_table', []))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Parse port information
|
||||||
|
for port in details.get('port_table', []):
|
||||||
|
diagnostics['interfaces']['ports'][f"Port {port.get('port_idx')}"] = {
|
||||||
|
'state': 'up' if port.get('up') else 'down',
|
||||||
|
'speed': {
|
||||||
|
'current': port.get('speed', 0),
|
||||||
|
'max': port.get('max_speed', 0)
|
||||||
|
},
|
||||||
|
'poe': port.get('poe_enable', False),
|
||||||
|
'media': port.get('media', 'unknown')
|
||||||
|
}
|
||||||
|
|
||||||
return diagnostics
|
return diagnostics
|
||||||
|
|
||||||
def _parse_interfaces(self, interfaces):
|
def _parse_interfaces(self, interfaces):
|
||||||
|
|||||||
@ -21,6 +21,13 @@ function updateDeviceStatus() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleInterfaces(header) {
|
||||||
|
const list = header.nextElementSibling;
|
||||||
|
const icon = header.querySelector('.expand-icon');
|
||||||
|
list.classList.toggle('collapsed');
|
||||||
|
icon.style.transform = list.classList.contains('collapsed') ? 'rotate(-90deg)' : 'rotate(0deg)';
|
||||||
|
}
|
||||||
|
|
||||||
function updateInterfaceStatus(deviceName, interfaces) {
|
function updateInterfaceStatus(deviceName, interfaces) {
|
||||||
const interfaceList = document.querySelector(`.interface-group[data-device-name="${deviceName}"] .interface-list`);
|
const interfaceList = document.querySelector(`.interface-group[data-device-name="${deviceName}"] .interface-list`);
|
||||||
if (interfaceList && interfaces) {
|
if (interfaceList && interfaces) {
|
||||||
@ -30,7 +37,7 @@ function updateInterfaceStatus(deviceName, interfaces) {
|
|||||||
<div class="interface-item">
|
<div class="interface-item">
|
||||||
<span class="port-name">${portName}</span>
|
<span class="port-name">${portName}</span>
|
||||||
<span class="port-speed">${port.speed.current}/${port.speed.max} Mbps</span>
|
<span class="port-speed">${port.speed.current}/${port.speed.max} Mbps</span>
|
||||||
<span class="port-status ${port.state.toLowerCase()}">${port.state}</span>
|
<span class="port-status ${port.state}">${port.state}</span>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -125,19 +125,45 @@ body {
|
|||||||
.value {
|
.value {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
.interface-header {
|
||||||
.interface-item {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: rgba(0,111,255,0.05);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interface-header:hover {
|
||||||
|
background: rgba(0,111,255,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.interface-list {
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: auto;
|
||||||
|
transition: max-height 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interface-list.collapsed {
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interface-item {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr auto;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.port-status {
|
.port-status {
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.port-status.up {
|
.port-status.up {
|
||||||
@ -150,6 +176,18 @@ body {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.expand-icon {
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapsed + .expand-icon {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.port-speed {
|
||||||
|
font-family: monospace;
|
||||||
|
color: var(--secondary-color);
|
||||||
|
}
|
||||||
.metrics-list {
|
.metrics-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
|||||||
@ -32,13 +32,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="metric-card">
|
<div class="metric-card expandable">
|
||||||
<h2>Interface Status</h2>
|
<h2>Interface Status</h2>
|
||||||
<div id="interface-details">
|
<div id="interface-details">
|
||||||
{%- for device in devices %}
|
{%- for device in devices %}
|
||||||
<div class="interface-group" data-device-name="{{ device.name }}">
|
<div class="interface-group" data-device-name="{{ device.name }}">
|
||||||
<h3>{{ device.name }}</h3>
|
<div class="interface-header" onclick="toggleInterfaces(this)">
|
||||||
<div class="interface-list"></div>
|
<h3>{{ device.name }}</h3>
|
||||||
|
<span class="expand-icon">▼</span>
|
||||||
|
</div>
|
||||||
|
<div class="interface-list collapsed"></div>
|
||||||
</div>
|
</div>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user