Group the Volumes page by the stack that owns each volume (0.54.0)
CI / check (push) Successful in 12m18s
CI / build-and-push (push) Successful in 1m55s

A flat volume list is sorted by name, and because Docker names a compose volume
<project>_<name> that already puts a stack's volumes next to each other. What it
does not do is say so: you read prefixes down the column to work out where one
stack's volumes end and the next begins, and `arr-stack_config`,
`arr-stack_downloads`, `immich_model-cache` is exactly as hard to scan as it
looks.

So the stack becomes a heading instead of a prefix repeated on every row. Each
group carries the stack's icon and name, its volume count, how many are unused,
and — once sizes have been computed — what the stack costs on disk, which is the
number you actually want when you are deciding what to clear out. The rows below
drop the prefix and show the part that differs: `pgdata`, not `immich_pgdata`.
The full name stays in the row's title attribute, since that is what you need
when typing a docker command.

Ordering: stacks by the name the user gave them rather than by the slug (an id
of "zz-project" for a stack called "Alpha" should sort under A), and volumes
belonging to no stack appended last, never sorted in — they are the ones you
scroll past rather than look for.

The case that turned out to be worth building for is the third one. A volume
keeps its compose label after the stack is gone, so it is neither owned nor
loose. Putting it in the unassigned group would hide it among portainer_data and
friends; instead it keeps its own heading, marked "stack removed". A flat list
made that invisible, and it is precisely where forgotten data sits.

No server change: the owning stack has been on every volume all along, from the
com.docker.compose.project label. The grouping is a pure function in lib/ rather
than logic inside the page, so the ordering rules are tested directly — ten
cases, including the deleted-stack group and that the unassigned group stays
last when the only real stack sorts after it.

The row markup moved into its own component on the way past. Nesting it one
level deeper inside the group left its indentation two stops adrift, and a 70-
line <tr> inline in a double map was already the least readable thing in the file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
menzelj
2026-09-17 15:02:34 +02:00
co-authored by Claude Opus 5
parent 76a228314a
commit d7c4f06e67
6 changed files with 400 additions and 55 deletions
+29 -2
View File
@@ -13,6 +13,28 @@ as intuitive as Dockge, as capable as Portainer for Compose workflows.
> (Auto-update) + Phase 23 (Secrets & configs) + Phase 24 (Design System v2)
> complete.
## Upgrading to 0.54.0 — nothing to do
**The Volumes page is grouped by stack.** Docker names a compose volume
`<project>_<name>`, so an alphabetical list already put a stack's volumes next
to each other — but you were left reading prefixes to work out whose was whose.
Each stack is now a heading, with its icon, its name, and how many volumes it
owns (plus how many are unused, and their total size once you hit *Compute
sizes*). The rows below it drop the prefix and show only the part that differs:
`pgdata`, not `immich_pgdata`.
Stacks are ordered by the name you gave them, and **volumes that belong to no
stack come last** — they are the ones you scroll past rather than look for.
One group is worth knowing about: volumes still labelled with a compose project
that is no longer a stack. They are not loose, so they do not land in the
unassigned group; they get their own heading marked **stack removed**. That is
where data left behind by a deleted stack collects, and it was previously
invisible in a flat list.
Nothing moved on the server and no endpoint changed — the owning stack was
already on every volume.
## Upgrading to 0.53.0 — nothing to do
A dark-mode fix. 0.52.0 put every app logo on a white tile so that black line
@@ -535,8 +557,13 @@ it is what your saved destination credentials are encrypted with.
### Phase 16 — Volumes page
- **New Volumes page** (sidebar). Lists Docker volumes with driver, owning stack,
in-use containers and mountpoint.
- **New Volumes page** (sidebar). Lists Docker volumes with driver, in-use
containers and mountpoint, **grouped by the stack that owns them** — each
group headed by the stack's icon and name with its volume count, unused count
and total size, and the rows under it stripped of the `<project>_` prefix.
Stacks sort by display name; volumes belonging to no stack come last. Volumes
still labelled with a stack that has been deleted form their own group, marked
*stack removed* — that is where forgotten data collects.
- Admin actions: delete a volume (with an in-use warning + force option) and
**Prune unused**; an *Only unused* filter.
- **Volume sizes** are loaded on demand via a *Compute sizes* button (runs