Phase 4 — P4-07: per-host tags + dashboard chip-row filter #15

Merged
steve merged 2 commits from p4-07-host-tags into main 2026-05-05 11:55:12 +01:00
Owner

Closes P4-07.

The tags JSON column has been on hosts since Phase 1 but had no edit surface and no filter. Wires both — small, mostly UI plumbing.

What's in

Free-form tags with autocomplete (option C from the brainstorm). No tags table, no "create tag first" ceremony. Operators type comma-separated; the UI offers a <datalist> of tags already in use across the fleet so prod doesn't drift to production / Production. Lowercased / trimmed / deduped server-side on save.

Inline editor on the host detail header. + add tags (or edit tags when some exist) reveals an input with autocomplete + a Save button. Persistent field-help line below the input — "Comma-separated. Lowercased automatically." — visible always, not just as a placeholder hint that vanishes when the field has a value (operator feedback caught this).

Dashboard chip-row above the host table:

filter: [All] [db] [london] [prod]

Active chip highlighted via a new .tag-active style. ?tag=foo filters the list and the count switches to N of M. Tag chips on the host detail header double as quick-filters into the dashboard.

Changes

  • Store: SetHostTags(ctx, hostID, tags), DistinctHostTags(ctx) (uses SQLite json_each to union tags across the fleet).
  • HTTP: operator-band POST /hosts/{id}/tags audited as host.tags_updated.
  • UI: host_chrome partial + dashboard page; new .tag-active CSS; tag chips on host header link to /?tag=….

Test plan

  • go test ./...
  • Add tags to a host via the inline editor — chips render, datalist autocomplete works
  • Dashboard chip-row appears once at least one tag exists
  • Click a chip → host list filters; All clears the filter
  • Click a tag chip on a host header → dashboard pre-filtered to that tag
  • Comma-separated input survives whitespace, mixed case, duplicates
Closes **P4-07**. The `tags` JSON column has been on `hosts` since Phase 1 but had no edit surface and no filter. Wires both — small, mostly UI plumbing. ## What's in **Free-form tags with autocomplete** (option C from the brainstorm). No `tags` table, no "create tag first" ceremony. Operators type comma-separated; the UI offers a `<datalist>` of tags already in use across the fleet so `prod` doesn't drift to `production` / `Production`. Lowercased / trimmed / deduped server-side on save. **Inline editor on the host detail header.** `+ add tags` (or `edit tags` when some exist) reveals an input with autocomplete + a Save button. Persistent `field-help` line below the input — "Comma-separated. Lowercased automatically." — visible always, not just as a placeholder hint that vanishes when the field has a value (operator feedback caught this). **Dashboard chip-row** above the host table: ``` filter: [All] [db] [london] [prod] ``` Active chip highlighted via a new `.tag-active` style. `?tag=foo` filters the list and the count switches to `N of M`. Tag chips on the host detail header double as quick-filters into the dashboard. ## Changes - **Store**: `SetHostTags(ctx, hostID, tags)`, `DistinctHostTags(ctx)` (uses SQLite `json_each` to union tags across the fleet). - **HTTP**: operator-band `POST /hosts/{id}/tags` audited as `host.tags_updated`. - **UI**: `host_chrome` partial + `dashboard` page; new `.tag-active` CSS; tag chips on host header link to `/?tag=…`. ## Test plan - [x] `go test ./...` - [x] Add tags to a host via the inline editor — chips render, datalist autocomplete works - [x] Dashboard chip-row appears once at least one tag exists - [x] Click a chip → host list filters; `All` clears the filter - [x] Click a tag chip on a host header → dashboard pre-filtered to that tag - [x] Comma-separated input survives whitespace, mixed case, duplicates
steve added 2 commits 2026-05-05 11:52:45 +01:00
ui(tags): edit-button label, Save-tags width, persistent help text
CI / Test (store) (pull_request) Successful in 44s
CI / Test (rest) (pull_request) Successful in 48s
CI / Test (server-http) (pull_request) Successful in 1m8s
CI / Lint (pull_request) Successful in 37s
CI / Build (windows/amd64) (pull_request) Successful in 39s
CI / Build (linux/amd64) (pull_request) Successful in 21s
CI / Build (linux/arm64) (pull_request) Successful in 26s
36fd9050fe
steve merged commit 4b48925edf into main 2026-05-05 11:55:12 +01:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/restic-manager#15