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:
@@ -229,6 +229,37 @@ SOURCES: dict[str, str] = {
|
||||
}
|
||||
|
||||
|
||||
def cert_left(days: float | None) -> str:
|
||||
"""Time left on a certificate: "12 days", "1 day", "today", or "expired
|
||||
3 days ago" rather than "-3 days"."""
|
||||
if days is None:
|
||||
return NONE
|
||||
whole = int(days)
|
||||
if days < 0:
|
||||
gone = int(-days)
|
||||
return "expired today" if gone == 0 else f"expired {gone} day{'s' if gone != 1 else ''} ago"
|
||||
if whole == 0:
|
||||
return "expires today"
|
||||
return f"{whole} day{'s' if whole != 1 else ''}"
|
||||
|
||||
|
||||
# Words a settings key spells in lower case that read in capitals.
|
||||
_ACRONYMS = {"url": "URL", "urls": "URLs", "ssl": "SSL", "tls": "TLS", "ip": "IP", "api": "API",
|
||||
"dns": "DNS", "http": "HTTP", "https": "HTTPS", "snmp": "SNMP", "oid": "OID",
|
||||
"oids": "OIDs", "id": "ID", "geoip": "GeoIP", "db": "database", "mmdb": "MMDB",
|
||||
"wan": "WAN", "dpi": "DPI", "smtp": "SMTP"}
|
||||
|
||||
|
||||
def field_label(key: str) -> str:
|
||||
"""A config key as a form label: "metrics_url" → "Metrics URL",
|
||||
"scrape_interval_seconds" → "Scrape interval seconds"."""
|
||||
words = [_ACRONYMS.get(w.lower(), w) for w in str(key or "").replace("-", "_").split("_") if w]
|
||||
if not words:
|
||||
return ""
|
||||
words[0] = words[0][:1].upper() + words[0][1:]
|
||||
return " ".join(words)
|
||||
|
||||
|
||||
def metric_label(name: str) -> str:
|
||||
entry = METRICS.get(name or "")
|
||||
return entry[0] if entry else (name or "").replace("_", " ")
|
||||
|
||||
Reference in New Issue
Block a user