feat(ui): Disk, Traefik, UniFi and Settings say things plainly (#5212)
#5212 "Plain labels: no raw ids, scopes, metric keys or unexplained jargon", batch 3: - Disk page: each tile says what it holds. "Writable layers" becomes "Container files" and Build cache says it is safe to clear. Shared is "Shared with other images" with a tooltip, and "dangling" is gone. Untagged images show by id instead of "<none>", a capped list says "The 50 largest of N images", and each host shows "as of" its report. - Traefik: an expired certificate reads "expired 12 days ago", not "-12 days" (cert_left). The Traffic empty state knows whether the access log is on: off points to Settings → Plugins → Traefik; on says to check the mounted log path. - Moments use |ago with an exact UTC tooltip: UniFi last seen, alarms, events, speed test and DPI; AI token last used. - Settings: the Auth tab is "Authentication" like its breadcrumb, plugin fields read "Metrics URL" not metrics_url (field_label), a source's pull interval is "every 1h", and the last report time drops the ISO "T". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -85,14 +85,17 @@ def split_routers(routers: list[dict]) -> tuple[list[dict], list[dict]]:
|
||||
return problems, healthy
|
||||
|
||||
|
||||
def _access_log() -> dict:
|
||||
"""The plugin's access_log settings ({} when unset or malformed)."""
|
||||
cfg = current_app.config["PLUGINS"]["traefik"].get("access_log", {})
|
||||
return cfg if isinstance(cfg, dict) else {}
|
||||
|
||||
|
||||
@traefik_bp.get("/")
|
||||
@require_role(UserRole.viewer)
|
||||
async def index():
|
||||
poll_interval = current_app.config.get("MONITORS_POLL_INTERVAL", 60)
|
||||
_al_cfg = current_app.config["PLUGINS"]["traefik"].get("access_log", {})
|
||||
if not isinstance(_al_cfg, dict):
|
||||
_al_cfg = {}
|
||||
access_log_enabled = _al_cfg.get("enabled", False)
|
||||
access_log_enabled = bool(_access_log().get("enabled", False))
|
||||
current_range = request.args.get("range", DEFAULT_RANGE)
|
||||
return await render_template(
|
||||
"traefik/index.html",
|
||||
@@ -368,8 +371,10 @@ async def traffic():
|
||||
rows = result.scalars().all()
|
||||
|
||||
if not rows:
|
||||
al = _access_log()
|
||||
return await render_template(
|
||||
"traefik/traffic.html", summary=None, history=[], range_key=range_key
|
||||
"traefik/traffic.html", summary=None, history=[], range_key=range_key,
|
||||
access_log_enabled=bool(al.get("enabled", False)), access_log_path=al.get("path", ""),
|
||||
)
|
||||
|
||||
total = sum(r.total_requests for r in rows)
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
<tr>
|
||||
<td style="word-break:break-all;">{{ cert.cn }}</td>
|
||||
<td class="field-hint">{{ cert.not_after.strftime("%Y-%m-%d") }}</td>
|
||||
<td style="text-align:right;white-space:nowrap;" class="tone-{{ status_info(status_class(cert.days_remaining, 'tls_days'))[0] }}">{{ cert.days_remaining|int }} days</td>
|
||||
<td style="text-align:right;white-space:nowrap;" class="tone-{{ status_info(status_class(cert.days_remaining, 'tls_days'))[0] }}">{{ cert_left(cert.days_remaining) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
@@ -92,9 +92,13 @@
|
||||
|
||||
{% else %}
|
||||
<div class="card" style="color:var(--text-muted);font-size:0.85rem;">
|
||||
No access log data yet.
|
||||
{% if not access_log_enabled %}
|
||||
Enable <code>access_log.enabled: true</code> in your plugin config and bind-mount the Traefik log directory.
|
||||
The access log is off. Turn it on in <a href="/settings/plugins/traefik/">Settings → Plugins → Traefik</a>,
|
||||
and mount Traefik's log directory into Steward so it can read the file.
|
||||
{% else %}
|
||||
No requests in the last {{ range_key }}. The access log is on; if this stays empty, check that
|
||||
{% if access_log_path %}<code>{{ access_log_path }}</code>{% else %}the log path{% endif %} is mounted into Steward
|
||||
and that Traefik is writing to it.
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div style="display:flex;justify-content:space-between;font-size:0.8rem;padding:0.15rem 0;
|
||||
{% if cert.days_remaining < 7 %}color:var(--red);{% else %}color:var(--yellow);{% endif %}">
|
||||
<span>⚠ {{ cert.cn }}</span>
|
||||
<span>{{ cert.days_remaining | int }}d</span>
|
||||
<span>{{ cert_left(cert.days_remaining) }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user