diff --git a/containers/libreportal/frontend/js/components/admin/system-storage-page.js b/containers/libreportal/frontend/js/components/admin/system-storage-page.js index f3a4e88..c606c1f 100644 --- a/containers/libreportal/frontend/js/components/admin/system-storage-page.js +++ b/containers/libreportal/frontend/js/components/admin/system-storage-page.js @@ -202,22 +202,41 @@ class SystemStoragePage { const palette = SystemStoragePage.PALETTE; const colorFor = i => palette[i % palette.length]; - // ---- Headline: on-disk usage by app (the disk question that matters) ---- + // ---- Headline: ONE donut covering everything — a slice per app, then + // Docker's own categories (images, build cache). Colours run continuously + // across the whole list so app and Docker slices stay distinct, and the + // legend lists them all. This is the unified "where's my disk going" view. const appTotal = (as && as.total) || 0; - const appSegs = appRows.map((a, i) => ({ color: colorFor(i), data: { size: a.bytes || 0 } })); - const headline = appRows.length + const appSegs = appRows.map((a, i) => ({ label: a.app, color: colorFor(i), data: { size: a.bytes || 0 } })); + const dockerCats = d ? SystemStoragePage.segmentsFrom(d).map((s, j) => ({ ...s, color: colorFor(appSegs.length + j) })) : []; + const allSegs = [...appSegs, ...dockerCats]; + const grandTotal = allSegs.reduce((t, s) => t + ((s.data && s.data.size) || 0), 0); + const legend = ` + `; + const headline = allSegs.length ? `
-
${SystemStoragePage.donutSvg(appSegs, appTotal, 'app data')}
+
+ ${SystemStoragePage.donutSvg(allSegs, grandTotal, 'in use')} + ${legend} +
App data on disk ${fmt.bytes(appTotal)} - ${appRows.length} app${appRows.length === 1 ? '' : 's'}${as && as.total_external ? ` · ${fmt.bytes(as.total_external)} on external drives` : ''} + ${appRows.length} app${appRows.length === 1 ? '' : 's'}${as && as.total_external ? ` · ${fmt.bytes(as.total_external)} external` : ''}
- ${d ? `
- Docker engine - ${fmt.bytes(d.total || 0)} - ${fmt.bytes(d.reclaimable || 0)} reclaimable + ${d ? `
+ Docker reclaimable + ${fmt.bytes(d.reclaimable || 0)} + of ${fmt.bytes(d.total || 0)} engine overhead
` : ''}
` @@ -262,10 +281,9 @@ class SystemStoragePage { // plus the largest images. The cleanup view, clearly separate from data. let dockerSection = ''; if (d) { - const segments = SystemStoragePage.segmentsFrom(d); const total = d.total || 0; const recl = d.reclaimable || 0; - const cards = segments.map(s => { + const cards = dockerCats.map(s => { const v = s.data || {}; const pct = v.size && total ? (v.size / total) * 100 : 0; const rPct = v.size ? (v.reclaimable / v.size) * 100 : 0;