feat: UI redesign (CSS system, DNS widget, Traefik dashboard widget)
- Replace base.html style block with full CSS design system using custom properties (dark theme, cards, tables, badges, dots, widgets) - Add DNS blueprint (fablednetmon/dns/) with /dns/ and /dns/rows routes + templates - Add Traefik /widget route and widget.html fragment for dashboard - Update dashboard: DNS + Traefik widgets, traefik_enabled config detection - Update all templates to use new CSS classes (page-title, section-title, card-flush, table, badge-*, dot-*, btn-*) - Register dns_bp in app.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,14 +2,14 @@
|
||||
{% block title %}Browse Playbooks — FabledNetMon{% endblock %}
|
||||
{% block content %}
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;">
|
||||
<h1 style="color:#c0c0ff;">Browse Playbooks</h1>
|
||||
<h1 class="page-title" style="margin-bottom:0;">Browse Playbooks</h1>
|
||||
<a href="/ansible/" style="color:#a0a0ff;font-size:0.9rem;">← Run History</a>
|
||||
</div>
|
||||
|
||||
{% if view_contents is defined %}
|
||||
<div class="card">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:1rem;">
|
||||
<h3 style="color:#8080ff;">{{ view_path }}</h3>
|
||||
<h3 class="section-title">{{ view_path }}</h3>
|
||||
<a href="/ansible/browse" style="color:#a0a0ff;font-size:0.85rem;">← Back to browse</a>
|
||||
</div>
|
||||
<pre style="background:#0a0a1a;padding:1rem;border-radius:4px;overflow-x:auto;font-size:0.8rem;color:#c0c0c0;max-height:600px;overflow-y:auto;">{{ view_contents }}</pre>
|
||||
@@ -26,7 +26,7 @@
|
||||
{% for sd in source_data %}
|
||||
<div class="card" style="margin-bottom:1.5rem;">
|
||||
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem;">
|
||||
<h3 style="color:#8080ff;">{{ sd.source.name }}</h3>
|
||||
<h3 class="section-title">{{ sd.source.name }}</h3>
|
||||
<span style="color:#404060;font-size:0.8rem;background:#12122a;padding:0.2rem 0.5rem;border-radius:3px;">{{ sd.source.type }}</span>
|
||||
<span style="color:#505070;font-size:0.8rem;">{{ sd.source.path }}</span>
|
||||
</div>
|
||||
@@ -34,25 +34,25 @@
|
||||
{% if not sd.playbooks %}
|
||||
<p style="color:#606080;font-size:0.9rem;">No playbooks found at this path.</p>
|
||||
{% else %}
|
||||
<table style="width:100%;border-collapse:collapse;margin-bottom:1rem;">
|
||||
<table class="table" style="margin-bottom:1rem;">
|
||||
<thead>
|
||||
<tr style="background:#12122a;">
|
||||
<th style="padding:0.5rem 0.75rem;text-align:left;color:#a0a0c0;font-weight:normal;font-size:0.82rem;">Playbook</th>
|
||||
<th style="padding:0.5rem 0.75rem;text-align:left;color:#a0a0c0;font-weight:normal;font-size:0.82rem;width:120px;"></th>
|
||||
<tr>
|
||||
<th>Playbook</th>
|
||||
<th style="width:120px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pb in sd.playbooks %}
|
||||
<tr style="border-top:1px solid #1a1a3a;">
|
||||
<td style="padding:0.5rem 0.75rem;color:#c0c0e0;font-size:0.88rem;font-family:monospace;">{{ pb }}</td>
|
||||
<td style="padding:0.5rem 0.75rem;">
|
||||
<a href="/ansible/browse/{{ sd.source.name }}/{{ pb }}" style="color:#6060c0;font-size:0.82rem;margin-right:0.75rem;">View</a>
|
||||
<tr>
|
||||
<td style="font-family:ui-monospace,monospace;font-size:0.88rem;">{{ pb }}</td>
|
||||
<td class="td-actions">
|
||||
<a href="/ansible/browse/{{ sd.source.name }}/{{ pb }}" class="btn btn-sm btn-ghost" style="margin-right:0.5rem;">View</a>
|
||||
<a href="#run-form-{{ sd.source.name }}"
|
||||
onclick="document.getElementById('run-form-{{ sd.source.name }}').style.display='block';
|
||||
document.getElementById('run-playbook-{{ sd.source.name }}').value='{{ pb }}';
|
||||
document.getElementById('run-playbook-display-{{ sd.source.name }}').value='{{ pb }}';
|
||||
return false;"
|
||||
style="color:#a0a0ff;font-size:0.82rem;">Run</a>
|
||||
class="btn btn-sm btn-ghost">Run</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -60,19 +60,19 @@
|
||||
</table>
|
||||
|
||||
{# Run trigger form for this source #}
|
||||
<div id="run-form-{{ sd.source.name }}" style="display:none;background:#12122a;border-radius:4px;padding:1rem;border:1px solid #2a2a4a;">
|
||||
<h4 style="color:#8080ff;margin-bottom:0.75rem;">Trigger Run</h4>
|
||||
<div id="run-form-{{ sd.source.name }}" style="display:none;background:var(--bg-elevated);border-radius:6px;padding:1rem;border:1px solid var(--border-mid);">
|
||||
<h4 class="section-title" style="margin-bottom:0.75rem;">Trigger Run</h4>
|
||||
<form hx-post="/ansible/runs" hx-target="#run-result-{{ sd.source.name }}" hx-swap="innerHTML">
|
||||
<input type="hidden" name="source_name" value="{{ sd.source.name }}">
|
||||
<input type="hidden" id="run-playbook-{{ sd.source.name }}" name="playbook_path" value="">
|
||||
<div class="form-group">
|
||||
<label>Playbook</label>
|
||||
<input type="text" id="run-playbook-display-{{ sd.source.name }}"
|
||||
readonly style="color:#8080a0;" value="">
|
||||
readonly style="color:var(--text-muted);" value="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Inventory</label>
|
||||
<select name="inventory_path" style="width:100%;padding:0.5rem 0.75rem;background:#0f0f1e;border:1px solid #3a3a5a;border-radius:4px;color:#e0e0e0;font-size:1rem;">
|
||||
<select name="inventory_path">
|
||||
{% for inv in sd.inventories %}
|
||||
<option value="{{ inv }}">{{ inv }}</option>
|
||||
{% endfor %}
|
||||
@@ -81,8 +81,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Or enter inventory path manually</label>
|
||||
<input type="text" id="manual-inv-{{ sd.source.name }}" placeholder="inventories/production/hosts"
|
||||
style="color:#c0c0e0;">
|
||||
<input type="text" id="manual-inv-{{ sd.source.name }}" placeholder="inventories/production/hosts">
|
||||
</div>
|
||||
<div style="display:flex;gap:0.75rem;align-items:center;">
|
||||
<button type="button" class="btn"
|
||||
@@ -90,7 +89,7 @@
|
||||
if(manual){this.closest('form').querySelector('[name=inventory_path]').value=manual;}
|
||||
htmx.trigger(this.closest('form'),'submit');">Execute</button>
|
||||
<a href="#" onclick="document.getElementById('run-form-{{ sd.source.name }}').style.display='none';return false;"
|
||||
style="color:#606080;font-size:0.9rem;">Cancel</a>
|
||||
class="btn btn-ghost btn-sm">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
<div id="run-result-{{ sd.source.name }}" style="margin-top:1rem;"></div>
|
||||
|
||||
@@ -2,37 +2,37 @@
|
||||
{% block title %}Ansible Runs — FabledNetMon{% endblock %}
|
||||
{% block content %}
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;">
|
||||
<h1 style="color:#c0c0ff;">Ansible Runs</h1>
|
||||
<h1 class="page-title" style="margin-bottom:0;">Ansible Runs</h1>
|
||||
<a href="/ansible/browse" class="btn">Browse Playbooks</a>
|
||||
</div>
|
||||
{% if not runs %}
|
||||
<div class="card">
|
||||
<p style="color:#606080;">No runs yet. <a href="/ansible/browse" style="color:#a0a0ff;">Browse playbooks</a> to trigger a run.</p>
|
||||
<p style="color:var(--text-muted);">No runs yet. <a href="/ansible/browse">Browse playbooks</a> to trigger a run.</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="card" style="padding:0;overflow:hidden;">
|
||||
<table style="width:100%;border-collapse:collapse;">
|
||||
<div class="card-flush">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr style="background:#12122a;">
|
||||
<th style="padding:0.75rem 1rem;text-align:left;color:#a0a0c0;font-weight:normal;font-size:0.85rem;">Playbook</th>
|
||||
<th style="padding:0.75rem 1rem;text-align:left;color:#a0a0c0;font-weight:normal;font-size:0.85rem;">Source</th>
|
||||
<th style="padding:0.75rem 1rem;text-align:left;color:#a0a0c0;font-weight:normal;font-size:0.85rem;">Status</th>
|
||||
<th style="padding:0.75rem 1rem;text-align:left;color:#a0a0c0;font-weight:normal;font-size:0.85rem;">Started</th>
|
||||
<th style="padding:0.75rem 1rem;text-align:left;color:#a0a0c0;font-weight:normal;font-size:0.85rem;"></th>
|
||||
<tr>
|
||||
<th>Playbook</th>
|
||||
<th>Source</th>
|
||||
<th>Status</th>
|
||||
<th>Started</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for run in runs %}
|
||||
{% set status_color = {"running": "#a0a000", "success": "#40a040", "failed": "#a04040", "interrupted": "#806040"}.get(run.status.value, "#808080") %}
|
||||
<tr style="border-top:1px solid #2a2a4a;">
|
||||
<td style="padding:0.75rem 1rem;color:#e0e0e0;font-size:0.9rem;">{{ run.playbook_path }}</td>
|
||||
<td style="padding:0.75rem 1rem;color:#8080a0;font-size:0.9rem;">{{ run.source_name }}</td>
|
||||
<td style="padding:0.75rem 1rem;">
|
||||
{% set status_color = {"running": "var(--yellow)", "success": "var(--green)", "failed": "var(--red)", "interrupted": "var(--orange)"}.get(run.status.value, "var(--text-muted)") %}
|
||||
<tr>
|
||||
<td style="font-size:0.9rem;">{{ run.playbook_path }}</td>
|
||||
<td style="color:var(--text-muted);font-size:0.9rem;">{{ run.source_name }}</td>
|
||||
<td>
|
||||
<span style="color:{{ status_color }};font-size:0.85rem;font-weight:bold;">{{ run.status.value.upper() }}</span>
|
||||
</td>
|
||||
<td style="padding:0.75rem 1rem;color:#606080;font-size:0.85rem;">{{ run.started_at.strftime("%Y-%m-%d %H:%M") }}</td>
|
||||
<td style="padding:0.75rem 1rem;">
|
||||
<a href="/ansible/runs/{{ run.id }}" style="color:#a0a0ff;font-size:0.85rem;">View</a>
|
||||
<td style="color:var(--text-muted);font-size:0.85rem;">{{ run.started_at.strftime("%Y-%m-%d %H:%M") }}</td>
|
||||
<td class="td-actions">
|
||||
<a href="/ansible/runs/{{ run.id }}" class="btn btn-sm btn-ghost">View</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% block content %}
|
||||
<div style="display:flex;align-items:center;gap:1rem;margin-bottom:1.5rem;">
|
||||
<a href="/ansible/" style="color:#6060c0;font-size:0.9rem;">← Runs</a>
|
||||
<h1 style="color:#c0c0ff;">Run Detail</h1>
|
||||
<h1 class="page-title" style="margin-bottom:0;">Run Detail</h1>
|
||||
</div>
|
||||
|
||||
{% set status_color = {"running": "#a0a000", "success": "#40a040", "failed": "#a04040", "interrupted": "#806040"}.get(run.status.value, "#808080") %}
|
||||
|
||||
Reference in New Issue
Block a user