Group Images and Networks by stack, like Volumes (0.55.0)
CI / check (push) Successful in 12m23s
CI / build-and-push (push) Successful in 2m4s

The same argument as 0.54.0: these pages already sorted a stack's resources next
to each other, and still made you read prefixes to work out where one stack
ended and the next began. Networks are the clearest win — compose names a
stack's own network <project>_default, so the column was almost entirely prefix.

Doing it a second and third time made the shape obvious, so the grouping is now
one function and one heading component shared by all three pages rather than
three copies drifting apart. A stack looks and sorts the same wherever it turns
up. volumeGroups.ts became stackGroups.ts on the way, and the Volumes page moved
onto it with no behaviour change.

Images forced the model to grow, and this is the part worth reading. An image
carries no compose label — the backend derives its owners from the containers
running it, so ownership is a *list*, and postgres:16 may belong to four stacks
at once. Listing it under each owner would show the same image four times with
four sizes, and a page that adds up to more disk than the host has. So anything
with more than one owner is listed once in a "Shared by several stacks" group,
and the Used by column names them. Each resource appears exactly once, which
keeps the per-group totals honest.

Networks needed a second new kind. bridge, host and none belong to no stack, but
they are not leftovers either, and dropping them into the unassigned group pads
the exact list people scan for junk. They get their own group below it. The
built-in check runs before ownership is even considered, so they can never be
counted as unclaimed.

Ordering is unchanged and now stated once: stacks by display name, then shared,
then unclaimed, then built-ins. The trailing three are appended, never sorted
in, so "unassigned at the bottom" holds whatever anything is called — there is a
test for the case where the only real stack sorts after them.

Group headings gained the counts each page can actually produce: volumes show
unused and total size, images total size and how many have an update waiting,
networks how many are idle.

Both row bodies moved into their own components. Nesting them a level deeper
inside the group left the indentation adrift, and the networks row had a second
<tr> for its expanded detail riding along inside an already doubled map.

Fifteen tests on the shared grouping, including the shared and built-in groups
and a stack that has been deleted since. No server change: every one of these
already knew its stack.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
menzelj
2026-09-18 00:11:26 +02:00
co-authored by Claude Opus 5
parent d7c4f06e67
commit a2adb59526
11 changed files with 650 additions and 346 deletions
+36 -7
View File
@@ -13,6 +13,31 @@ 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.55.0 — nothing to do
**Images and Networks are grouped by stack too**, the same way Volumes were in
0.54.0: a heading per stack with its icon and name, the rows under it stripped
of the `<project>_` prefix, and anything unclaimed at the bottom. Compose names
a stack's own network `<project>_default`, so that column gets a lot quieter.
Two group kinds are new, because those two pages have cases volumes do not:
- **Shared by several stacks.** An image has no compose label — its owners are
worked out from the containers running it, so `postgres:16` can belong to four
stacks at once. Listing it under each would show the same image four times
with four sizes, and the page would add up to more disk than the host has. It
is listed once instead, and the *Used by* column names the stacks.
- **Docker built-ins.** The `bridge`, `host` and `none` networks belong to no
stack but are not leftovers either, so they sit in their own group below the
unassigned one rather than padding it.
Group headings also carry a count: volumes show unused and total size, images
total size and how many have an update waiting, networks how many are idle.
The grouping itself is now one shared function and one shared heading component
for all three pages, so a stack looks and sorts the same wherever it appears.
Nothing changed on the server — every one of these already knew its stack.
## Upgrading to 0.54.0 — nothing to do
**The Volumes page is grouped by stack.** Docker names a compose volume
@@ -395,11 +420,12 @@ it is what your saved destination credentials are encrypted with.
### Phase 9 — Networks
- **Network management**: the Networks page lists Docker networks (driver, scope,
subnet, attached containers / in-use, owning stack), with **create** (bridge /
macvlan / ipvlan / overlay, optional subnet+gateway, internal/attachable),
**delete** (default networks protected; in-use guarded by Docker), and **prune
unused**.
- **Network management**: the Networks page lists Docker networks **grouped by
the stack that owns them** (driver, scope, subnet, attached containers /
in-use), with **create** (bridge / macvlan / ipvlan / overlay, optional
subnet+gateway, internal/attachable), **delete** (default networks protected;
in-use guarded by Docker), and **prune unused**. Docker's own `bridge` / `host`
/ `none` sit in a *built-ins* group at the bottom.
- **Stack delete**: local stacks can now be deleted from the UI (stack detail and
the stack card), with a confirm dialog and an optional "keep files on disk".
@@ -588,8 +614,11 @@ it is what your saved destination credentials are encrypted with.
connect/disconnect containers — including a *Prune unused* button, which
resolves the common "all predefined address pools have been fully subnetted"
deploy error without SSH.
- **Images**: list image tags (with using-stacks) and run on-demand update
checks.
- **Images**: list image tags **grouped by the stack that uses them** and run
on-demand update checks. An image has no compose label, so its owners come
from the containers running it — which means an image can have several, and
those are listed once under *Shared by several stacks* rather than repeated
under each.
### Phase 12 — File browser