feat: UI improvements — event ages, error badges, PoE bars, mismatch detection
- events table: add Last Seen column; show relative times ("3h ago") with
absolute timestamp on hover; update updateEventsTable() in app.js to match
- links.html: add error/drop/flap alert badges to interface and port card headers
- links.html: PoE power bar (draw/max ratio with colour-coded fill) and poe_mode
- links.html: stale data warning banner when link_stats are >2 minutes old
- links.html: improved error handler shows HTTP status instead of generic message
- links.html: fix collapse state persisted to localStorage (was sessionStorage,
lost on browser restart); fix collapseAll/expandAll to also persist state
- inspector.html: duplex mismatch and speed mismatch warnings in path debug panel
- inspector.html: carrier changes added to server column of path debug
- style.css: new classes — .link-alert-badge, .poe-bar-*, .path-mismatch-alert,
.error-state; fix .stale-banner to use CSS variables
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -201,6 +201,7 @@
|
||||
<th>Detail</th>
|
||||
<th>Description</th>
|
||||
<th>First Seen</th>
|
||||
<th>Last Seen</th>
|
||||
<th>Failures</th>
|
||||
<th>Ticket</th>
|
||||
<th>Actions</th>
|
||||
@@ -215,7 +216,12 @@
|
||||
<td><strong>{{ e.target_name }}</strong></td>
|
||||
<td>{{ e.target_detail or '–' }}</td>
|
||||
<td class="desc-cell" title="{{ e.description | e }}">{{ e.description | truncate(60) }}</td>
|
||||
<td class="ts-cell">{{ e.first_seen }}</td>
|
||||
<td class="ts-cell" title="{{ e.first_seen }}">
|
||||
<span class="event-age" data-ts="{{ e.first_seen }}">{{ e.first_seen }}</span>
|
||||
</td>
|
||||
<td class="ts-cell" title="{{ e.last_seen }}">
|
||||
<span class="event-age" data-ts="{{ e.last_seen }}">{{ e.last_seen }}</span>
|
||||
</td>
|
||||
<td>{{ e.consecutive_failures }}</td>
|
||||
<td>
|
||||
{% if e.ticket_id %}
|
||||
@@ -233,7 +239,7 @@
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<tr><td colspan="9" class="empty-state">No active alerts ✔</td></tr>
|
||||
<tr><td colspan="10" class="empty-state">No active alerts ✔</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -299,5 +305,26 @@
|
||||
{% block scripts %}
|
||||
<script>
|
||||
setInterval(refreshAll, 30000);
|
||||
|
||||
// ── Relative time display for event age cells ──────────────────
|
||||
function fmtRelTime(tsStr) {
|
||||
if (!tsStr) return '–';
|
||||
const d = new Date(tsStr.replace(' UTC', 'Z').replace(' ', 'T'));
|
||||
if (isNaN(d)) return tsStr;
|
||||
const secs = Math.floor((Date.now() - d) / 1000);
|
||||
if (secs < 60) return `${secs}s ago`;
|
||||
if (secs < 3600) return `${Math.floor(secs/60)}m ago`;
|
||||
if (secs < 86400) return `${Math.floor(secs/3600)}h ago`;
|
||||
return `${Math.floor(secs/86400)}d ago`;
|
||||
}
|
||||
|
||||
function updateEventAges() {
|
||||
document.querySelectorAll('.event-age[data-ts]').forEach(el => {
|
||||
el.textContent = fmtRelTime(el.dataset.ts);
|
||||
});
|
||||
}
|
||||
|
||||
updateEventAges();
|
||||
setInterval(updateEventAges, 60000);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user