Label UI: tree management, page assignment, and sidebar filter #44

Closed
opened 2026-07-04 14:52:21 +02:00 by fable-5 · 1 comment
Collaborator

Context

Users need to create/organize labels and filter the sidebar by them.

Scope

Pond settings section 'Labels': tree view with create/rename/recolor/move (drag or menu)/delete; page-level label picker (multi-select with search, shows hierarchy); sidebar: label filter (select one or more labels, shows matching pages incl. descendant-label matches), label chips on page list entries (colored).

Acceptance criteria

  • full label lifecycle works in the UI (e2e)
  • filtering by a parent label includes pages tagged with its children
  • label picker on a page saves immediately and updates the sidebar
  • keyboard-accessible tree operations

Technical notes

  • Vision §Bereiche (hierarchy, classic page tree possible but not enforced).

Dependencies

Depends on #26, #43.

Size: ~1.5 days


Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add de and en), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.

## Context Users need to create/organize labels and filter the sidebar by them. ## Scope Pond settings section 'Labels': tree view with create/rename/recolor/move (drag or menu)/delete; page-level label picker (multi-select with search, shows hierarchy); sidebar: label filter (select one or more labels, shows matching pages incl. descendant-label matches), label chips on page list entries (colored). ## Acceptance criteria - [ ] full label lifecycle works in the UI (e2e) - [ ] filtering by a parent label includes pages tagged with its children - [ ] label picker on a page saves immediately and updates the sidebar - [ ] keyboard-accessible tree operations ## Technical notes - Vision §Bereiche (hierarchy, classic page tree possible but not enforced). ## Dependencies Depends on #26, #43. **Size**: ~1.5 days --- *Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add `de` **and** `en`), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.*
fable-5 added this to the M4 — Organization & search milestone 2026-07-04 14:52:21 +02:00
fable-5 added the
frontend
label 2026-07-04 14:52:21 +02:00
Collaborator

Implemented in 03e72242d3e164adf201a0481da24b4921984e88 (Claude Opus 4.8). Pipeline green (CI: lint/typecheck/test + all e2e packs incl. the new labels pack; CD: deploy Test → smoke → promote Int).

Browser-verified end to end locally (isolated full stack, both e2e tests green):

  • label lifecycle works from the pond settings UI: keyboard-created root label, add sub-label, rename, delete child + root. ✓
  • page picker assigns a label and the sidebar filter includes descendants: picker assign saves immediately → sidebar chip appears; filtering by the parent label shows the page tagged with its child and hides the untagged page; clearing restores it. ✓

Live-verified on Test (test.dorfteich.cloud): GET /ponds/:id/pages now returns labelIds per page, reflecting an assigned (child) label — the data the sidebar chips and filter run on. ✓

Acceptance criteria

  • full label lifecycle works in the UI (e2e)
  • filtering by a parent label includes pages tagged with its children (sidebar expands the selection to each label's subtree via the shared collectSubtreeIds)
  • label picker on a page saves immediately and updates the sidebar (assign/unassign → invalidates page-labels + the pond pages query)
  • keyboard-accessible tree operations (every op is a native button/input/select)

Notes

  • Pond settings live at /p/:pondSlug/settings (new PondSettingsPage, hosting the LabelManager); the sidebar links owners there. Future pond config joins this page.
  • Reusable flattenLabelTree added to packages/shared; PageListItemView carries labelIds so the sidebar needs no per-page label calls.
  • Chip text colour is chosen per background by luminance so user-picked label colours stay legible.
  • Move rejects targets inside the label's own subtree (client-side, mirroring the api's cycle check).
  • i18n labels namespace (de + en).

Two e2e lessons captured for later frontend work: the UI language follows the signed-in user's profile locale (auth-context calls i18n.changeLanguage(user.locale)), so ?lng=/browser locale don't win — label-UI e2e selectors are language-independent (CSS classes + label names); and getByText(labelName) also matches the move-dropdown <option>s across rows, so rows are located via .label-node__name.

Next M4 issue: #45 (manual page ordering with drag-and-drop).

Implemented in `03e72242d3e164adf201a0481da24b4921984e88` (Claude Opus 4.8). Pipeline green (CI: lint/typecheck/test + all e2e packs incl. the new **labels** pack; CD: deploy Test → smoke → promote Int). **Browser-verified end to end locally** (isolated full stack, both e2e tests green): - `label lifecycle works from the pond settings UI`: keyboard-created root label, add sub-label, rename, delete child + root. ✓ - `page picker assigns a label and the sidebar filter includes descendants`: picker assign saves immediately → sidebar chip appears; filtering by the **parent** label shows the page tagged with its **child** and hides the untagged page; clearing restores it. ✓ **Live-verified on Test** (`test.dorfteich.cloud`): `GET /ponds/:id/pages` now returns `labelIds` per page, reflecting an assigned (child) label — the data the sidebar chips and filter run on. ✓ **Acceptance criteria** - [x] full label lifecycle works in the UI (e2e) - [x] filtering by a parent label includes pages tagged with its children (sidebar expands the selection to each label's subtree via the shared `collectSubtreeIds`) - [x] label picker on a page saves immediately and updates the sidebar (assign/unassign → invalidates `page-labels` + the pond `pages` query) - [x] keyboard-accessible tree operations (every op is a native button/input/select) **Notes** - Pond settings live at `/p/:pondSlug/settings` (new `PondSettingsPage`, hosting the `LabelManager`); the sidebar links owners there. Future pond config joins this page. - Reusable `flattenLabelTree` added to `packages/shared`; `PageListItemView` carries `labelIds` so the sidebar needs no per-page label calls. - Chip text colour is chosen per background by luminance so user-picked label colours stay legible. - Move rejects targets inside the label's own subtree (client-side, mirroring the api's cycle check). - i18n `labels` namespace (de + en). **Two e2e lessons captured for later frontend work:** the UI language follows the signed-in user's profile locale (`auth-context` calls `i18n.changeLanguage(user.locale)`), so `?lng=`/browser locale don't win — label-UI e2e selectors are language-independent (CSS classes + label names); and `getByText(labelName)` also matches the move-dropdown `<option>`s across rows, so rows are located via `.label-node__name`. Next M4 issue: #45 (manual page ordering with drag-and-drop).
Sign in to join this conversation.
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#44
No description provided.