TDS polish: lt-frame tables, lt-stats-grid link summary, settings-aware refresh
Lint / Python (flake8) (push) Successful in 40s
Lint / JS (eslint) (push) Successful in 8s
Security / Python Security (bandit) (push) Failing after 42s
Test / Python Tests (pytest) (push) Successful in 50s
Lint / Notify on failure (push) Has been skipped
Lint / Deploy (push) Successful in 3s

- links.html: replace custom link-summary-panel with lt-stats-grid/lt-stat-card
  showing total interfaces, ports down, errors, and PoE load
- suppressions.html: wrap active suppressions and history tables in lt-frame
  with lt-section-header labels
- inspector.html: wire auto-refresh to gandalfSettings (respects interval pill),
  fix updated timestamp to use locale time

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 17:15:48 -04:00
parent b393d94e81
commit c3aa3bea6f
3 changed files with 130 additions and 90 deletions
+81 -66
View File
@@ -85,33 +85,38 @@
</div>
<div id="active-sup-wrap">
{% if active %}
<div class="lt-table-wrap">
<table class="lt-table" id="active-sup-table">
<caption class="lt-sr-only">Active suppression rules</caption>
<thead>
<tr>
<th>Type</th><th>Target</th><th>Detail</th><th>Reason</th>
<th>By</th><th>Created</th><th>Expires</th><th>Actions</th>
</tr>
</thead>
<tbody>
{% for s in active %}
<tr id="sup-row-{{ s.id }}">
{%- set _sup_badge = {'host':'badge-warning','interface':'badge-info','unifi_device':'badge-purple','all':'badge-critical'} -%}
<td><span class="lt-badge {{ _sup_badge.get(s.target_type, 'badge-neutral') }}">{{ s.target_type }}</span></td>
<td>{{ s.target_name or 'all' }}</td>
<td>{{ s.target_detail or '' }}</td>
<td>{{ s.reason }}</td>
<td>{{ s.suppressed_by }}</td>
<td class="ts-cell">{{ s.created_at }}</td>
<td class="ts-cell">{% if s.expires_at %}{{ s.expires_at }}{% else %}<em>manual</em>{% endif %}</td>
<td>
<button class="lt-btn lt-btn-danger lt-btn-sm" data-action="remove-sup" data-sup-id="{{ s.id }}">Remove</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="lt-frame">
<span class="lt-frame-bl">&#x255A;</span>
<span class="lt-frame-br">&#x255D;</span>
<div class="lt-section-header">Active Rules</div>
<div class="lt-table-wrap">
<table class="lt-table" id="active-sup-table">
<caption class="lt-sr-only">Active suppression rules</caption>
<thead>
<tr>
<th>Type</th><th>Target</th><th>Detail</th><th>Reason</th>
<th>By</th><th>Created</th><th>Expires</th><th>Actions</th>
</tr>
</thead>
<tbody>
{% for s in active %}
<tr id="sup-row-{{ s.id }}">
{%- set _sup_badge = {'host':'badge-warning','interface':'badge-info','unifi_device':'badge-purple','all':'badge-critical'} -%}
<td><span class="lt-badge {{ _sup_badge.get(s.target_type, 'badge-neutral') }}">{{ s.target_type }}</span></td>
<td>{{ s.target_name or 'all' }}</td>
<td>{{ s.target_detail or '' }}</td>
<td>{{ s.reason }}</td>
<td>{{ s.suppressed_by }}</td>
<td class="ts-cell">{{ s.created_at }}</td>
<td class="ts-cell">{% if s.expires_at %}{{ s.expires_at }}{% else %}<em>manual</em>{% endif %}</td>
<td>
<button class="lt-btn lt-btn-danger lt-btn-sm" data-action="remove-sup" data-sup-id="{{ s.id }}">Remove</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<div class="lt-empty-state lt-empty-state--sm" id="no-active-msg">
@@ -130,36 +135,41 @@
<span class="g-section-badge">{{ history | length }}</span>
</div>
{% if history %}
<div class="lt-table-wrap">
<table class="lt-table lt-table-sm">
<caption class="lt-sr-only">Suppression history</caption>
<thead>
<tr>
<th>Type</th><th>Target</th><th>Detail</th><th>Reason</th>
<th>By</th><th>Created</th><th>Expires</th><th>Active</th>
</tr>
</thead>
<tbody>
{% for s in history %}
<tr class="{% if not s.active %}row-resolved{% endif %}">
<td>{{ s.target_type }}</td>
<td>{{ s.target_name or 'all' }}</td>
<td>{{ s.target_detail or '' }}</td>
<td>{{ s.reason }}</td>
<td>{{ s.suppressed_by }}</td>
<td class="ts-cell">{{ s.created_at }}</td>
<td class="ts-cell">{% if s.expires_at %}{{ s.expires_at }}{% else %}<em>manual</em>{% endif %}</td>
<td>
{% if s.active %}
<span class="lt-badge badge-ok">Yes</span>
{% else %}
<span class="lt-badge badge-neutral">No</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="lt-frame">
<span class="lt-frame-bl">&#x255A;</span>
<span class="lt-frame-br">&#x255D;</span>
<div class="lt-section-header">Suppression Log</div>
<div class="lt-table-wrap">
<table class="lt-table lt-table-sm">
<caption class="lt-sr-only">Suppression history</caption>
<thead>
<tr>
<th>Type</th><th>Target</th><th>Detail</th><th>Reason</th>
<th>By</th><th>Created</th><th>Expires</th><th>Active</th>
</tr>
</thead>
<tbody>
{% for s in history %}
<tr class="{% if not s.active %}row-resolved{% endif %}">
<td>{{ s.target_type }}</td>
<td>{{ s.target_name or 'all' }}</td>
<td>{{ s.target_detail or '' }}</td>
<td>{{ s.reason }}</td>
<td>{{ s.suppressed_by }}</td>
<td class="ts-cell">{{ s.created_at }}</td>
<td class="ts-cell">{% if s.expires_at %}{{ s.expires_at }}{% else %}<em>manual</em>{% endif %}</td>
<td>
{% if s.active %}
<span class="lt-badge badge-ok">Yes</span>
{% else %}
<span class="lt-badge badge-neutral">No</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<div class="lt-empty-state lt-empty-state--sm">
@@ -237,15 +247,20 @@
<td><button class="lt-btn lt-btn-danger lt-btn-sm" data-action="remove-sup" data-sup-id="${s.id}">Remove</button></td>
</tr>`).join('');
wrap.innerHTML = `
<div class="lt-table-wrap">
<table class="lt-table" id="active-sup-table">
<caption class="lt-sr-only">Active suppression rules</caption>
<thead><tr>
<th>Type</th><th>Target</th><th>Detail</th><th>Reason</th>
<th>By</th><th>Created</th><th>Expires</th><th>Actions</th>
</tr></thead>
<tbody>${tbody}</tbody>
</table>
<div class="lt-frame">
<span class="lt-frame-bl">&#x255A;</span>
<span class="lt-frame-br">&#x255D;</span>
<div class="lt-section-header">Active Rules</div>
<div class="lt-table-wrap">
<table class="lt-table" id="active-sup-table">
<caption class="lt-sr-only">Active suppression rules</caption>
<thead><tr>
<th>Type</th><th>Target</th><th>Detail</th><th>Reason</th>
<th>By</th><th>Created</th><th>Expires</th><th>Actions</th>
</tr></thead>
<tbody>${tbody}</tbody>
</table>
</div>
</div>`;
}