diff --git a/app.py b/app.py index 2446478..949ed06 100644 --- a/app.py +++ b/app.py @@ -813,7 +813,12 @@ def get_unraid_stats(): headers = {"x-api-key": UNRAID_API_KEY, "Content-Type": "application/json"} query = """{ vars { version } - array { state disks { fsSize fsFree type } } + array { + state + disks { name device fsSize fsFree type temp isSpinning } + caches { name device fsSize fsFree type temp isSpinning } + parities { name device temp isSpinning } + } }""" try: resp = requests.post(url, json={"query": query}, headers=headers, @@ -828,6 +833,26 @@ def get_unraid_stats(): free_bytes = sum(int(dk.get("fsFree", 0) or 0) for dk in data_disks) used_bytes = total_bytes - free_bytes used_pct = round(used_bytes / total_bytes * 100) if total_bytes else 0 + + def disk_row(dk, with_usage=True): + row = { + "name": dk.get("name") or dk.get("device") or "disk", + "device": dk.get("device", ""), + "temp": dk.get("temp"), + "spinning": dk.get("isSpinning"), + } + if with_usage: + dtotal = int(dk.get("fsSize", 0) or 0) + dfree = int(dk.get("fsFree", 0) or 0) + dused = dtotal - dfree + row.update({ + "total": fmt_bytes(dtotal), + "used": fmt_bytes(dused), + "free": fmt_bytes(dfree), + "used_pct": round(dused / dtotal * 100) if dtotal else 0, + }) + return row + return { "status": "ok", "source": "api", @@ -838,6 +863,9 @@ def get_unraid_stats(): "array_used": fmt_bytes(used_bytes), "array_free": fmt_bytes(free_bytes), "array_used_pct": used_pct, + "disks": [disk_row(dk) for dk in data_disks], + "caches": [disk_row(dk) for dk in arr.get("caches", [])], + "parities": [disk_row(dk, with_usage=False) for dk in arr.get("parities", [])], } except Exception: pass diff --git a/static/css/dashboard.css b/static/css/dashboard.css index 3adc388..88d82b6 100644 --- a/static/css/dashboard.css +++ b/static/css/dashboard.css @@ -433,6 +433,9 @@ dd.is-accent { color: var(--accent); } width: 100%; min-height: 38px; } +/* Sits below the request pills, which use --row-h — match it so the + button reads as one more row rather than a shorter tacked-on control. */ +.show-more.show-more-row { min-height: var(--row-h); } /* ── Indexers ───────────────────────────────────────── */ /* One indexer per line, built to the same rhythm as the Ombi request rows @@ -529,6 +532,36 @@ dd.is-accent { color: var(--accent); } } .req-sub { font-size: var(--fs-xs); color: var(--text-3); } +/* ── Storage — per-disk breakdown ──────────────────────── */ +/* Same row anatomy as indexer/request rows: name/sub on the left, a status + badge on the right. Data + cache disks get a usage meter; parity disks + (no filesystem) are rendered compact — name and temp only. */ +.disk-list { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.85rem; } +.disk-item { + display: flex; + align-items: center; + gap: 0.7rem; + min-height: var(--row-h); + padding: 0.6rem 0.7rem; + background: var(--surface-2); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + min-width: 0; +} +.disk-info { min-width: 0; flex: 1; } +.disk-name { + font-size: var(--fs-sm); font-weight: 600; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} +.disk-sub { font-size: var(--fs-xs); color: var(--text-3); } +.disk-meter.meter { margin-top: 0.4rem; height: 4px; } +.disk-list-compact { margin-top: 0.5rem; } +.disk-item-compact { justify-content: space-between; padding: 0.5rem 0.7rem; min-height: auto; } +.disk-item-compact .disk-name { flex: 1; } +.badge.temp-ok { background: var(--ok-dim); color: var(--ok); } +.badge.temp-warn { background: var(--warn-dim); color: var(--warn); } +.badge.temp-danger { background: var(--danger-dim); color: var(--danger); } + /* ── Insights top lists ─────────────────────────────── */ .top-list { display: flex; flex-direction: column; gap: 0.4rem; } .top-item { diff --git a/templates/dashboard.html b/templates/dashboard.html index 26a1928..d509b23 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -170,6 +170,47 @@ {% if unraid.source == "local" %}

Container disk usage ({{ unraid.mount }}). Set UNRAID_API_KEY for full array stats.

{% endif %} + + {% if unraid.disks or unraid.caches %} +
+ {% for dk in unraid.disks + unraid.caches %} + {% set dpct = dk.used_pct %} +
+
+
{{ dk.name }}
+
{{ dk.used }} of {{ dk.total }}
+
+
+
+
+ {% if dk.spinning == false %} + Standby + {% elif dk.temp is not none %} + {{ dk.temp }}°C + {% endif %} +
+ {% endfor %} +
+ {% endif %} + + {% if unraid.parities %} +
+ {% for dk in unraid.parities %} +
+
{{ dk.name }}
+ {% if dk.spinning == false %} + Standby + {% elif dk.temp is not none %} + {{ dk.temp }}°C + {% endif %} +
+ {% endfor %} +
+ {% endif %} + {% else %} {{ service_error("Unraid", unraid.error) }} {% endif %} @@ -362,7 +403,7 @@ {% endfor %} {% if ombi.recent | length > 5 %} - {% endif %} {% else %}