feat(lists): wire dead list controls (VAPP-15) #13

Merged
David merged 2 commits from feat/wire-list-controls into main 2026-06-07 00:06:24 +02:00
Owner

Resolves VAPP-15.

Wires every dead list control on /devices, /events, and the topbar so each does what it says or is removed. All filtering is client-side over the already-fetched rows, so no server work was added.

Changes

  • Devices page: status chips are now buttons backed by a StatusFilter signal; their counts stay computed from the full row set so they hold steady across filters. A name/id substring filter reads the shared topbar search. "Export CSV" builds an RFC 4180 CSV (name, id, mesh, status, platform, address, agent, last seen) from exactly the filtered rows and downloads it via a Blob + transient anchor click on web (no-op on desktop, which has no DOM). The dead "Bulk action" button is removed.
  • Topbar: the global search input is wired to a DeviceSearch context signal provided at the app root; typing navigates to /devices on the first keystroke and narrows the list from any page. Placeholder shrinks to "Search devices". The dead "Invite" button is removed.
  • Events page: severity chips filter client-side via a SeverityFilter signal; the filter-expression input implements its own placeholder, source:<text> narrows by source and any other text is a substring match on the message.
  • Cargo.toml: adds wasm-bindgen / js-sys / web-sys to the wasm32 target for the CSV download. All three were already resolved transitively, so no new crate is pulled in (lock only gains them as direct deps).

Acceptance criteria

  • Status chips filter the device table and stay consistent with their counts
  • Topbar search filters devices by name or id substring from any page
  • Events filter chips and expression input narrow the table (severity, source:, substring)
  • Export CSV downloads exactly the filtered rows
  • Bulk action and Invite buttons no longer render
  • No control on /devices, /events, or the topbar is a no-op

Verification

cargo check (server + wasm32), cargo clippy -D warnings (server + wasm32), cargo fmt --check, and cargo test --features server all pass locally.

Resolves VAPP-15. Wires every dead list control on `/devices`, `/events`, and the topbar so each does what it says or is removed. All filtering is client-side over the already-fetched rows, so no server work was added. ## Changes - **Devices page**: status chips are now buttons backed by a `StatusFilter` signal; their counts stay computed from the full row set so they hold steady across filters. A name/id substring filter reads the shared topbar search. "Export CSV" builds an RFC 4180 CSV (name, id, mesh, status, platform, address, agent, last seen) from exactly the filtered rows and downloads it via a `Blob` + transient anchor click on web (no-op on desktop, which has no DOM). The dead "Bulk action" button is removed. - **Topbar**: the global search input is wired to a `DeviceSearch` context signal provided at the app root; typing navigates to `/devices` on the first keystroke and narrows the list from any page. Placeholder shrinks to "Search devices". The dead "Invite" button is removed. - **Events page**: severity chips filter client-side via a `SeverityFilter` signal; the filter-expression input implements its own placeholder, `source:<text>` narrows by source and any other text is a substring match on the message. - **Cargo.toml**: adds `wasm-bindgen` / `js-sys` / `web-sys` to the wasm32 target for the CSV download. All three were already resolved transitively, so no new crate is pulled in (lock only gains them as direct deps). ## Acceptance criteria - [x] Status chips filter the device table and stay consistent with their counts - [x] Topbar search filters devices by name or id substring from any page - [x] Events filter chips and expression input narrow the table (severity, source:, substring) - [x] Export CSV downloads exactly the filtered rows - [x] Bulk action and Invite buttons no longer render - [x] No control on /devices, /events, or the topbar is a no-op ## Verification `cargo check` (server + wasm32), `cargo clippy -D warnings` (server + wasm32), `cargo fmt --check`, and `cargo test --features server` all pass locally.
feat(lists): wire device/event filters, search, CSV export
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 46s
424b15baa1
Every rendered control on /devices, /events, and the topbar now does what it says or is removed.

Devices page: status chips are buttons backed by a StatusFilter signal; their counts stay computed from the full set so they hold steady across filters. A name/id substring filter reads the shared topbar search. "Export CSV" builds an RFC 4180 CSV (name, id, mesh, status, platform, address, agent, last seen) from exactly the filtered rows and downloads it via a Blob + transient anchor click on web; the desktop build compiles it to a no-op. The dead "Bulk action" button is removed.

Topbar: the global search input is wired to a DeviceSearch context signal provided at the app root; typing navigates to /devices on the first keystroke and narrows the list. Placeholder shrinks to "Search devices". The dead "Invite" button is removed.

Events page: severity chips filter client-side via a SeverityFilter signal; the filter-expression input implements its own placeholder, `source:<text>` narrows by source and any other text is a substring match on the message.

Adds wasm-bindgen/js-sys/web-sys to the wasm32 target for the CSV download; all three were already resolved transitively, so no new crate is pulled in.

#VAPP-15

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: David Randall <David@NiceGuyIT.biz>
Author
Owner

Resolved the merge conflicts with main (PR #14's enrollment dialog landed in the same topbar and devices-page regions). Topbar: kept this PR's Invite removal and main's wired + New Device (opens the enrollment dialog). Devices page: kept main's empty-state/else structure with this PR's filtered rows feeding the table; the empty state keys off the full set so filters cannot fake an empty fleet. Verified against a live server with an enrolled agent: devices page shows the device, Export CSV and the chip buttons, search input bound, Bulk action and Invite gone, + New Device present; events page renders the filter expression input with live events. just check clean (7 tests).

Resolved the merge conflicts with main (PR #14's enrollment dialog landed in the same topbar and devices-page regions). Topbar: kept this PR's Invite removal and main's wired + New Device (opens the enrollment dialog). Devices page: kept main's empty-state/else structure with this PR's filtered rows feeding the table; the empty state keys off the full set so filters cannot fake an empty fleet. Verified against a live server with an enrolled agent: devices page shows the device, Export CSV and the chip buttons, search input bound, Bulk action and Invite gone, + New Device present; events page renders the filter expression input with live events. just check clean (7 tests).
Merge branch 'main' into feat/wire-list-controls
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 50s
Create release / Create release from merged PR (pull_request) Has been skipped
ea19589aa3
David merged commit 946d0f4301 into main 2026-06-07 00:06:24 +02:00
David deleted branch feat/wire-list-controls 2026-06-07 00:06:24 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
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
psa-systems/vervain-apps!13
No description provided.