feat(web): Table view — client-side filter + sortable column headers - #589
Conversation
…ders Two paired UX additions to the Table view (List | Table | Graph): - Search input above the table (`<input data-search-input>` inside a `data-search-filter`/`data-search-scope` container) hooks into the existing v2-search-filter.js — no new JS needed. Each row carries `data-search-text` with CN, SAM, mail, DN concatenated so the substring filter matches both visible and adjacent attributes. - Column headers are now anchor links that toggle the active sort. Server-side sort via ?sort=col&dir=asc|desc (URL captures state for back/forward + bookmarking). Clicking the active column flips dir; clicking another resets to asc. Active-column heading shows ↑ / ↓. New helpers in internal/web/table_sort.go: - normaliseSortDir, sortUsersTable, sortGroupsTable, sortComputersTable - Status sort puts enabled rows first under asc — the more useful default than alphabetical "Disabled" / "Enabled". Tests: - TestNormaliseSortDir + per-entity sort tests cover ascending/ descending, status semantics, unknown-key fallback to CN. - TestHandleUsersV2_TableMode marker assertion updated to match the new sort-link / search-input markup. The cookie-persisted view selection from the previous PR is unaffected — sort/dir don't persist across views (they're meaningful only inside Table view), and the existing filterQS stays threaded through the header links so column clicks keep ?ou=, ?memberOf=, etc. Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
There was a problem hiding this comment.
Automated approval for maintainer PR
All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #589 +/- ##
==========================================
- Coverage 70.00% 69.94% -0.06%
==========================================
Files 33 34 +1
Lines 3357 3437 +80
==========================================
+ Hits 2350 2404 +54
- Misses 849 873 +24
- Partials 158 160 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Code Review
This pull request implements server-side sorting and client-side filtering for the table views of users, groups, and computers. It introduces a new table_sort.go utility for handling sorting logic with stable secondary keys, updates the web handlers to process sort parameters, and enhances the templates with a search input and sortable column headers. Corresponding CSS and unit tests have also been added. I have no feedback to provide.
There was a problem hiding this comment.
Pull request overview
Adds table-view enhancements in the V2 web UI by introducing a client-side text filter for table rows and server-side sorting via clickable column headers, keeping sort state in the URL query string.
Changes:
- Add search input +
data-search-*wiring in Table view templates to reusev2-search-filter.jsfor client-side row filtering. - Add server-side table sorting (
?sort=...&dir=asc|desc) for users/groups/computers, plus sortable<th>header links. - Add unit tests for the new sort helpers and update existing handler test assertions for the new markup.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/web/users_v2_handler.go | Parses sort params for table view, sorts users server-side, passes sort state to template. |
| internal/web/groups_v2_handler.go | Parses sort params for table view, sorts groups server-side, passes sort state to template. |
| internal/web/computers_v2_handler.go | Parses sort params for table view, sorts computers server-side, passes sort state to template. |
| internal/web/templates/list_table_v2.templ | Adds filter UI + sortable headers; builds sort hrefs and search haystacks per row. |
| internal/web/table_sort.go | Implements in-place sort helpers for users/groups/computers and normalizes direction. |
| internal/web/table_sort_test.go | Unit coverage for sort helpers and direction normalization. |
| internal/web/graph_v2_handler_test.go | Updates table-mode marker assertions for new header/link/filter markup. |
| internal/web/static/app.css | Styles the new search input and sortable header links/indicators. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Five concrete fixes from Copilot review: - Skip the CN pre-sort in users/groups/computers handlers when the Table view is active; the table applies its own (sortKey, sortDir) immediately after, so the unconditional sortXByCN was an unnecessary O(n log n) pass. - stringLess helper centralises the case-insensitive comparison + DN tie-break. Earlier the tie-break used `a == b` (case-sensitive) while the comparison used `strings.ToLower`, so two values differing only in case fell through to input-slice order. Now uses strings.EqualFold so the tie-break fires when the primary comparison considers them equal. Applied to sortUsersTable, sortGroupsTable (cn + dn cases), and sortComputersTable. - Drop data-search-count from the table's count <p>. v2-search- filter.js rewrites the element to "<n> items" on every keystroke, so the initial "1 users" flips to "0 items" once the user types — ugly noun churn beats live count. - Comment fix: buildSortHref → buildTableSortHref (renamed earlier to dodge a collision with graph_v2.templ's helper of the same name; the comment didn't follow). - Comment fix: "Plain ascii arrows" → describe the actual Unicode ↑/↓ glyphs. Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
There was a problem hiding this comment.
Automated approval for maintainer PR
All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.
Summary
Closes the deferred follow-up from the live-review polish session (#588 handoff): the Table view now has a search input above the table and clickable column headers that toggle a server-side sort.
What ships
Client-side filter
<input data-search-input>inside adata-search-filter/data-search-scopecontainer).v2-search-filter.js(no new JS needed). Rows hide via thehiddenattribute when the haystack doesn't match.data-search-texton each<tr>concatenates CN, SAM, mail (where present), and DN so the substring filter matches visible and adjacent attributes.data-search-countmechanism.Escclears the input.Server-side sortable headers
?sort=col&dir=asc|descplus the preserved filter QS — so back/forward navigation and bookmarking work, no JS required.asc. The active column shows↑/↓.Tests
TestNormaliseSortDir+ per-entity sort tests (ascending/descending, status semantics, unknown-key fallback to CN, members count desc).TestHandleUsersV2_TableModemarker assertion updated to match the new sort-link / search-input markup.Out of scope
Test plan
go test ./internal/web/ -count=1— passgolangci-lint run ./...— 0 issuesgo build ./...— cleantempl generate— clean