(ui) Make host diagnostics easier to scan

Replace the raw host check table with diagnostic cards and group effective
runtime config into operator-focused sections for backup target, connection,
and selection/retention details.

Refs #26
This commit is contained in:
2026-05-21 14:03:43 +02:00
parent ab5291b8d3
commit 212813e066

View File

@@ -229,26 +229,25 @@
<div class="metric"><div class="label">Failed</div><div class="value">{{ host_check_summary.failed }}</div></div> <div class="metric"><div class="label">Failed</div><div class="value">{{ host_check_summary.failed }}</div></div>
<div class="metric"><div class="label">Skipped</div><div class="value">{{ host_check_summary.skipped }}</div></div> <div class="metric"><div class="label">Skipped</div><div class="value">{{ host_check_summary.skipped }}</div></div>
</section> </section>
<table> <div class="record-list">
<thead> {% for check in host_checks %}
<tr> <article class="record-card">
<th>Status</th> <div class="record-card-header">
<th>Check</th> <div class="record-title">
<th>Message</th> <strong>{{ check.name }}</strong>
<th>Detail</th> <span class="muted">{{ check.message }}</span>
</tr> </div>
</thead> <span class="status {{ check.status }}">{{ check.status }}</span>
<tbody> </div>
{% for check in host_checks %} {% if check.detail %}
<tr> <div class="record-fact">
<td><span class="status {{ check.status }}">{{ check.status }}</span></td> <span class="label">Detail</span>
<td>{{ check.name }}</td> <span class="muted">{{ check.detail }}</span>
<td>{{ check.message }}</td> </div>
<td class="muted">{{ check.detail }}</td> {% endif %}
</tr> </article>
{% endfor %} {% endfor %}
</tbody> </div>
</table>
</section> </section>
<div class="panel-grid"> <div class="panel-grid">
@@ -346,39 +345,74 @@
{% if effective_config %} {% if effective_config %}
<section class="panel"> <section class="panel">
<h2>Effective Config</h2> <h2>Effective Config</h2>
<div class="two-col"> <p class="muted">Runtime settings after global defaults and host overrides are combined.</p>
<div class="stack"> <div class="record-list">
<div><strong>Backup source:</strong> {{ effective_config.source_root }}</div> <article class="record-card">
<div><strong>Destination subdir:</strong> {{ effective_config.destination_subdir|default:"none" }}</div> <div class="record-card-header">
<div><strong>SSH:</strong> {{ effective_config.ssh.user }}@{{ host.address }}:{{ effective_config.ssh.port }}</div> <div class="record-title">
<div><strong>SSH key:</strong> {{ effective_config.ssh.credential|default:"none selected" }}</div> <strong>Backup target</strong>
<div><strong>SSH options:</strong> {{ effective_config.ssh.options|join:" " }}</div> <span class="muted">Source and destination used by rsync.</span>
<div><strong>Rsync binary:</strong> {{ effective_config.rsync.binary }}</div> </div>
<div><strong>Rsync args:</strong> {{ effective_config.rsync.args|join:" " }}</div>
<div><strong>Timeout:</strong> {{ effective_config.rsync.timeout_seconds }}s</div>
<div><strong>Bandwidth limit:</strong> {{ effective_config.rsync.bwlimit_kbps }} KB/s</div>
<div>
<strong>Retention:</strong>
d{{ effective_config.retention.daily }}
w{{ effective_config.retention.weekly }}
m{{ effective_config.retention.monthly }}
y{{ effective_config.retention.yearly }}
</div> </div>
</div> <div class="record-facts">
<div class="stack"> <div class="record-fact"><span class="label">Backup source:</span><strong>{{ effective_config.source_root }}</strong></div>
<div><strong>Includes:</strong> {{ effective_config.includes|length }}</div> <div class="record-fact"><span class="label">Destination subdir:</span><strong>{{ effective_config.destination_subdir|default:"none" }}</strong></div>
{% if effective_config.includes %} </div>
<pre>{{ effective_config.includes|join:"&#10;" }}</pre> </article>
{% else %} <article class="record-card">
<div class="muted">No include rules configured.</div> <div class="record-card-header">
{% endif %} <div class="record-title">
<div><strong>Excludes:</strong> {{ effective_config.excludes|length }}</div> <strong>Connection</strong>
{% if effective_config.excludes %} <span class="muted">SSH and rsync execution settings.</span>
<pre>{{ effective_config.excludes|join:"&#10;" }}</pre> </div>
{% else %} </div>
<div class="muted">No exclude rules configured.</div> <div class="record-facts">
{% endif %} <div class="record-fact"><span class="label">SSH:</span><strong>{{ effective_config.ssh.user }}@{{ host.address }}:{{ effective_config.ssh.port }}</strong></div>
</div> <div class="record-fact"><span class="label">SSH key:</span><strong>{{ effective_config.ssh.credential|default:"none selected" }}</strong></div>
<div class="record-fact"><span class="label">SSH options:</span><span>{{ effective_config.ssh.options|join:" " }}</span></div>
<div class="record-fact"><span class="label">Rsync binary:</span><strong>{{ effective_config.rsync.binary }}</strong></div>
<div class="record-fact"><span class="label">Rsync args:</span><span>{{ effective_config.rsync.args|join:" " }}</span></div>
<div class="record-fact"><span class="label">Timeout:</span><strong>{{ effective_config.rsync.timeout_seconds }}s</strong></div>
<div class="record-fact"><span class="label">Bandwidth limit:</span><strong>{{ effective_config.rsync.bwlimit_kbps }} KB/s</strong></div>
</div>
</article>
<article class="record-card">
<div class="record-card-header">
<div class="record-title">
<strong>Selection &amp; retention</strong>
<span class="muted">Include/exclude rules and retention counts.</span>
</div>
</div>
<div class="record-facts">
<div class="record-fact">
<span class="label">Retention:</span>
<strong>
d{{ effective_config.retention.daily }}
w{{ effective_config.retention.weekly }}
m{{ effective_config.retention.monthly }}
y{{ effective_config.retention.yearly }}
</strong>
</div>
<div class="record-fact"><span class="label">Includes:</span><strong>{{ effective_config.includes|length }}</strong></div>
<div class="record-fact"><span class="label">Excludes:</span><strong>{{ effective_config.excludes|length }}</strong></div>
</div>
<div class="two-col">
<div class="stack">
{% if effective_config.includes %}
<pre>{{ effective_config.includes|join:"&#10;" }}</pre>
{% else %}
<div class="muted">No include rules configured.</div>
{% endif %}
</div>
<div class="stack">
{% if effective_config.excludes %}
<pre>{{ effective_config.excludes|join:"&#10;" }}</pre>
{% else %}
<div class="muted">No exclude rules configured.</div>
{% endif %}
</div>
</div>
</article>
</div> </div>
</section> </section>
{% endif %} {% endif %}