Restructure app to use LotusGuild Terminal Design System v1.2
Lint / Python (flake8) (push) Failing after 45s
Lint / JS (eslint) (push) Successful in 7s
Security / Python Security (bandit) (push) Failing after 1m22s
Test / Python Tests (pytest) (push) Successful in 51s
Lint / Notify on failure (push) Successful in 2s
Lint / Deploy (push) Has been skipped
Lint / Python (flake8) (push) Failing after 45s
Lint / JS (eslint) (push) Successful in 7s
Security / Python Security (bandit) (push) Failing after 1m22s
Test / Python Tests (pytest) (push) Successful in 51s
Lint / Notify on failure (push) Successful in 2s
Lint / Deploy (push) Has been skipped
Replace custom phosphor-green terminal aesthetic with the lt-* component system from base.css/base.js. All templates now inherit the LotusGuild multi-accent Anduril palette via variable aliases in style.css, and use lt-header, lt-nav, lt-card, lt-table, lt-btn, lt-modal, lt-badge etc. Custom components (topology, inspector chassis, link debug, SFP panels) are preserved with color values updated to base.css palette variables. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+75
-69
@@ -18,14 +18,14 @@
|
||||
</div>
|
||||
<div class="status-meta">
|
||||
<span class="last-check" id="last-check">{{ last_check }}</span>
|
||||
<button class="btn-refresh" onclick="refreshAll()">↻ REFRESH</button>
|
||||
<button class="lt-btn lt-btn-ghost lt-btn-sm" onclick="refreshAll()">↻ REFRESH</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Network topology + host grid ───────────────────────────────── -->
|
||||
<section class="section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Network Hosts</h2>
|
||||
<section class="g-section">
|
||||
<div class="g-section-header">
|
||||
<h2 class="g-section-title">Network Hosts</h2>
|
||||
</div>
|
||||
|
||||
<div class="topology" id="topology-diagram">
|
||||
@@ -102,7 +102,7 @@
|
||||
|
||||
<!-- Pro 24 PoE → host bus section -->
|
||||
<div class="topo-vc">
|
||||
<div class="topo-vc-wire" style="background:var(--border);opacity:.5;"></div>
|
||||
<div class="topo-vc-wire" style="background:var(--border-color);opacity:.5;"></div>
|
||||
</div>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════════
|
||||
@@ -161,7 +161,7 @@
|
||||
<div class="topo-legend-item"><span class="topo-legend-line-wan"></span> WAN / uplink</div>
|
||||
<div class="topo-legend-item"><span class="topo-legend-line-10g"></span> 10G SFP+ (Ceph / VLAN90)</div>
|
||||
<div class="topo-legend-item"><span class="topo-legend-line-1g"></span> 1G DHCP (mgmt)</div>
|
||||
<div class="topo-legend-item" style="border:1px dashed var(--border); padding:1px 5px; font-size:.56em; color:var(--text-muted);">dashed border = off-rack</div>
|
||||
<div class="topo-legend-item" style="border:1px dashed var(--border-color); padding:1px 5px; font-size:.56em; color:var(--text-muted);">dashed border = off-rack</div>
|
||||
</div>
|
||||
|
||||
</div><!-- /topo-v2 -->
|
||||
@@ -201,7 +201,7 @@
|
||||
{% endif %}
|
||||
|
||||
<div class="host-actions">
|
||||
<button class="btn-sm btn-suppress"
|
||||
<button class="lt-btn lt-btn-ghost lt-btn-sm btn-suppress"
|
||||
data-sup-type="host"
|
||||
data-sup-name="{{ name }}"
|
||||
data-sup-detail=""
|
||||
@@ -209,7 +209,7 @@
|
||||
🔕 Suppress
|
||||
</button>
|
||||
<a href="{{ url_for('links_page') }}#{{ name }}"
|
||||
class="btn-sm btn-secondary" style="text-decoration:none">
|
||||
class="lt-btn lt-btn-secondary lt-btn-sm" style="text-decoration:none">
|
||||
↗ Links
|
||||
</a>
|
||||
</div>
|
||||
@@ -222,12 +222,13 @@
|
||||
|
||||
<!-- ── UniFi devices ────────────────────────────────────────────────── -->
|
||||
{% if snapshot.unifi %}
|
||||
<section class="section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">UniFi Devices</h2>
|
||||
<section class="g-section">
|
||||
<div class="g-section-header">
|
||||
<h2 class="g-section-title">UniFi Devices</h2>
|
||||
</div>
|
||||
<div class="table-wrap">
|
||||
<table class="data-table" id="unifi-table">
|
||||
<div class="lt-table-wrap">
|
||||
<table class="lt-table" id="unifi-table">
|
||||
<caption class="lt-sr-only">UniFi network devices</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
@@ -251,7 +252,7 @@
|
||||
<td>{{ d.ip }}</td>
|
||||
<td>
|
||||
{% if not d.connected %}
|
||||
<button class="btn-sm btn-suppress"
|
||||
<button class="lt-btn lt-btn-ghost lt-btn-sm btn-suppress"
|
||||
data-sup-type="unifi_device"
|
||||
data-sup-name="{{ d.name }}"
|
||||
data-sup-detail="">
|
||||
@@ -268,11 +269,11 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- ── Active alerts ───────────────────────────────────────────────── -->
|
||||
<section class="section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Active Alerts</h2>
|
||||
<section class="g-section">
|
||||
<div class="g-section-header">
|
||||
<h2 class="g-section-title">Active Alerts</h2>
|
||||
{% if summary.critical or summary.warning %}
|
||||
<span class="section-badge">{{ (summary.critical or 0) + (summary.warning or 0) }}</span>
|
||||
<span class="g-section-badge">{{ (summary.critical or 0) + (summary.warning or 0) }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="events-table-wrap">
|
||||
@@ -280,8 +281,9 @@
|
||||
{% if total_active is defined and total_active > events|length %}
|
||||
<div class="pagination-notice">Showing {{ events|length }} of {{ total_active }} active alerts — <a href="/api/events?limit=1000">view all via API</a></div>
|
||||
{% endif %}
|
||||
<div class="table-wrap">
|
||||
<table class="data-table" id="events-table">
|
||||
<div class="lt-table-wrap">
|
||||
<table class="lt-table" id="events-table">
|
||||
<caption class="lt-sr-only">Active network alerts</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Sev</th>
|
||||
@@ -300,7 +302,7 @@
|
||||
{% for e in events %}
|
||||
{% if e.severity != 'info' %}
|
||||
<tr class="row-{{ e.severity }}">
|
||||
<td><span class="badge badge-{{ e.severity }}">{{ e.severity }}</span></td>
|
||||
<td><span class="lt-badge badge-{{ e.severity }}">{{ e.severity }}</span></td>
|
||||
<td>{{ e.event_type | replace('_', ' ') }}</td>
|
||||
<td><strong>{{ e.target_name }}</strong></td>
|
||||
<td>{{ e.target_detail or '–' }}</td>
|
||||
@@ -319,7 +321,7 @@
|
||||
{% else %}–{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn-sm btn-suppress"
|
||||
<button class="lt-btn lt-btn-ghost lt-btn-sm btn-suppress"
|
||||
data-sup-type="{{ 'unifi_device' if e.event_type == 'unifi_device_offline' else 'interface' if e.event_type == 'interface_down' else 'host' }}"
|
||||
data-sup-name="{{ e.target_name }}"
|
||||
data-sup-detail="{{ e.target_detail or '' }}"
|
||||
@@ -341,13 +343,14 @@
|
||||
|
||||
<!-- ── Recently Resolved (last 24h) ───────────────────────────────── -->
|
||||
{% if recent_resolved %}
|
||||
<section class="section">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Recently Resolved</h2>
|
||||
<span class="section-badge section-badge-resolved">{{ recent_resolved | length }} in last 24h</span>
|
||||
<section class="g-section">
|
||||
<div class="g-section-header">
|
||||
<h2 class="g-section-title">Recently Resolved</h2>
|
||||
<span class="g-section-badge g-section-badge-resolved">{{ recent_resolved | length }} in last 24h</span>
|
||||
</div>
|
||||
<div class="table-wrap">
|
||||
<table class="data-table">
|
||||
<div class="lt-table-wrap">
|
||||
<table class="lt-table">
|
||||
<caption class="lt-sr-only">Recently resolved alerts</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Sev</th>
|
||||
@@ -361,7 +364,7 @@
|
||||
<tbody>
|
||||
{% for e in recent_resolved %}
|
||||
<tr class="row-resolved">
|
||||
<td><span class="badge badge-resolved">{{ e.severity }}</span></td>
|
||||
<td><span class="lt-badge badge-resolved">{{ e.severity }}</span></td>
|
||||
<td>{{ e.event_type | replace('_', ' ') }}</td>
|
||||
<td><strong>{{ e.target_name }}</strong></td>
|
||||
<td>{{ e.target_detail or '–' }}</td>
|
||||
@@ -378,50 +381,53 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- ── Quick-suppress modal ─────────────────────────────────────────── -->
|
||||
<div id="suppress-modal" class="modal-overlay" style="display:none">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h3>Suppress Alert</h3>
|
||||
<button class="modal-close" onclick="closeSuppressModal()">✕</button>
|
||||
<div id="suppress-modal" class="lt-modal-backdrop" style="display:none"
|
||||
role="dialog" aria-modal="true" aria-labelledby="suppress-modal-title">
|
||||
<div class="lt-modal">
|
||||
<div class="lt-modal-header">
|
||||
<h3 class="lt-modal-title" id="suppress-modal-title">Suppress Alert</h3>
|
||||
<button type="button" class="lt-modal-close" onclick="closeSuppressModal()" aria-label="Close">✕</button>
|
||||
</div>
|
||||
<form id="suppress-form" onsubmit="submitSuppress(event)">
|
||||
<div class="form-group" style="margin-bottom:10px">
|
||||
<label>Target Type</label>
|
||||
<select id="sup-type" name="target_type" onchange="updateSuppressForm()">
|
||||
<option value="host">Host (all interfaces)</option>
|
||||
<option value="interface">Specific Interface</option>
|
||||
<option value="unifi_device">UniFi Device</option>
|
||||
<option value="all">Global Maintenance</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" id="sup-name-group" style="margin-bottom:10px">
|
||||
<label>Target Name</label>
|
||||
<input type="text" id="sup-name" name="target_name" placeholder="e.g. large1">
|
||||
</div>
|
||||
<div class="form-group" id="sup-detail-group" style="margin-bottom:10px;display:none">
|
||||
<label>Interface <span class="form-hint">(interface type only)</span></label>
|
||||
<input type="text" id="sup-detail" name="target_detail" placeholder="e.g. enp35s0">
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:10px">
|
||||
<label>Reason <span class="required">*</span></label>
|
||||
<input type="text" id="sup-reason" name="reason"
|
||||
placeholder="e.g. Planned switch reboot" required>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0">
|
||||
<label>Duration</label>
|
||||
<div class="duration-pills">
|
||||
<button type="button" class="pill" onclick="setDuration(30, this)">30 min</button>
|
||||
<button type="button" class="pill" onclick="setDuration(60, this)">1 hr</button>
|
||||
<button type="button" class="pill" onclick="setDuration(240, this)">4 hr</button>
|
||||
<button type="button" class="pill" onclick="setDuration(480, this)">8 hr</button>
|
||||
<button type="button" class="pill pill-manual active" onclick="setDuration(null, this)">Manual ∞</button>
|
||||
<div class="lt-modal-body">
|
||||
<div class="lt-form-group" style="margin-bottom:12px">
|
||||
<label class="lt-label" for="sup-type">Target Type</label>
|
||||
<select class="lt-select" id="sup-type" name="target_type" onchange="updateSuppressForm()">
|
||||
<option value="host">Host (all interfaces)</option>
|
||||
<option value="interface">Specific Interface</option>
|
||||
<option value="unifi_device">UniFi Device</option>
|
||||
<option value="all">Global Maintenance</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="lt-form-group" id="sup-name-group" style="margin-bottom:12px">
|
||||
<label class="lt-label" for="sup-name">Target Name</label>
|
||||
<input type="text" class="lt-input" id="sup-name" name="target_name" placeholder="e.g. large1">
|
||||
</div>
|
||||
<div class="lt-form-group" id="sup-detail-group" style="margin-bottom:12px;display:none">
|
||||
<label class="lt-label" for="sup-detail">Interface <span class="lt-field-hint">(interface type only)</span></label>
|
||||
<input type="text" class="lt-input" id="sup-detail" name="target_detail" placeholder="e.g. enp35s0">
|
||||
</div>
|
||||
<div class="lt-form-group" style="margin-bottom:12px">
|
||||
<label class="lt-label" for="sup-reason">Reason <span class="required">*</span></label>
|
||||
<input type="text" class="lt-input" id="sup-reason" name="reason"
|
||||
placeholder="e.g. Planned switch reboot" required>
|
||||
</div>
|
||||
<div class="lt-form-group" style="margin-bottom:0">
|
||||
<label class="lt-label">Duration</label>
|
||||
<div class="duration-pills">
|
||||
<button type="button" class="pill" onclick="setDuration(30, this)">30 min</button>
|
||||
<button type="button" class="pill" onclick="setDuration(60, this)">1 hr</button>
|
||||
<button type="button" class="pill" onclick="setDuration(240, this)">4 hr</button>
|
||||
<button type="button" class="pill" onclick="setDuration(480, this)">8 hr</button>
|
||||
<button type="button" class="pill pill-manual active" onclick="setDuration(null, this)">Manual ∞</button>
|
||||
</div>
|
||||
<input type="hidden" id="sup-expires" name="expires_minutes" value="">
|
||||
<div class="lt-field-hint" id="duration-hint">Persists until manually removed.</div>
|
||||
</div>
|
||||
<input type="hidden" id="sup-expires" name="expires_minutes" value="">
|
||||
<div class="form-hint" id="duration-hint">Persists until manually removed.</div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeSuppressModal()">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Apply</button>
|
||||
<div class="lt-modal-footer">
|
||||
<button type="button" class="lt-btn lt-btn-secondary" onclick="closeSuppressModal()">Cancel</button>
|
||||
<button type="submit" class="lt-btn lt-btn-primary">Apply</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user