Repository navigation
Table: quick text filter across all columns (#1881) - #1894
Conversation
|
Trekmeester: included in batch #1915 (run 36779344325). It lands with it when green; if this PR's own tests fail there, I take it out and say why here. |
|
In the batch run on current develop (run 36828210149), the only failing test was Generated by Claude Code |
A "Find rows…" field next to Filter and Columns keeps the rows where any visible column shows the text, case-insensitive: text and markdown as plain text, numbers as formatted (and as typed), dates and timestamps as displayed, a ticked checkbox as its column label, references and select tags by title, multi-value cells by any item. It narrows the view's own column-filtered, sorted collection on the client, so it combines with both. While active it walks every page of that collection, not just the 30 rows loaded. The same filtered rows feed the table, timer, board, issue list and calendar views; dashboards and app views don't show it. Session state only: it resets when you switch views or leave the table. Clear with the x or Escape; below 40rem it folds into a search icon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With text in "Find rows…", the totals under the table (sum, average, min, max, count, and the per-group breakdown) now cover the matching rows — the rows on screen and the ones the footer counts — instead of every row the column filters let through. The store can't be asked about the quick filter's rows, so they are computed client-side by `aggregateRows`, which mirrors the store's rules (`aggregate.rs`). With the field empty, the store's totals pass through unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
95e1c39 to
17dd0ed
Compare
Closes #1881
Adds a Find rows… field to the table view's toolbar, next to Filter and Columns. It keeps the rows where any visible column shows the text, ignoring case.
What it matches (the displayed value, per datatype)
a bfindsa **b**1234.5)calendarDateToLocalDate+formatDate, Show date-only values as dates, not UTC-midnight timestamps #1812). Timestamps are matched with their timeComputed columns (durations, days-since) and row-action buttons are not searched.
How it combines with filters and sorting
It narrows the view's own collection, which already has the column filters and sort applied, on the client, and keeps that order. The table, timer, board, issue list and calendar all read the same narrowed rows through one small adapter (
subjectListCollection). So the field works in every view kind that shows rows. It is hidden for dashboards and app views.While it is active:
aggregateRowsintableAggregates.ts, mirroring the store's rules inaggregate.rs:countcounts rows with a value, the other functions skip rows without a number, computed columns are evaluated with the column's own generator). With the field empty, the store's totals are used unchanged.Persistence: none
The text is session state in
TableResource, tagged with the view it was typed in. Switching views or leaving the table resets it. It is never written to the View resource. Clear it with the ✕ or with Escape. Escape on an empty field folds it closed on a phone.Paging and performance
The grid fetches 30 rows per page. While the field has text, the quick filter walks every page of the view's collection (
getAllMembers, as the board and calendar already do). So it also finds rows you haven't scrolled to, not just the loaded page. Nothing extra is fetched while the field is empty. Each row's display text is built once, and rebuilt only when a row, column or title changes. A keystroke is then just a substring test per row, which is fine for a few thousand rows. The first keystroke on a very large table pays for loading every row once.Phone width
Below 40rem the field folds into a search icon. Tapping it opens the field. It stays open while it has text and folds back when you leave it empty.
Tests
quickFilter.test.ts(vitest, 18 tests): matching for string, markdown, integer, float/percentage, date (long and default numeric formats), timestamp, checkbox, reference (by title and by subject fallback), multi-value tags, localized text, any-column row matching, order preservation, empty query, unloaded rows, and collecting reference subjects.tableAggregates.test.ts:aggregateRowsfollows the store's semantics (count vs. sum/avg over missing values, numeric strings, date max, a computed product column, no value vs. zero on no rows, breakdown by first tag and by month).QuickFilterField.test.tsx(component, 7 tests): a realStorewith local rows. Covers: typing filters (by text, by reference title, by checkbox label); clearing with ✕ restores all rows; Escape clears; ✕ only while there is text; combining with a column filter (it only narrows what the column filter lets through, and dropping the column filter keeps the text). Totals: with the quick filter active, sum and average cover only the matching rows and agree with the row count; clearing restores the full totals; with a column filter as well, the totals cover only what both let through, and no match reads "—", not 0.Screenshots
Before (develop) and after, at desktop and at 375 px. The PNGs are handed to the developer in chat, because
ghcan't upload images. I'll attach them here on request.1881-before-desktop.png1881-before-375.png1881-after-desktop-filtered.png1881-after-desktop-status.png1881-after-desktop-with-column-filter.png1881-after-desktop-nomatch.png1881-after-375-collapsed.png1881-after-375-filtered.png1881-totals-desktop-before.png1881-totals-desktop-after.png1881-totals-mobile-before.png1881-totals-mobile-after.pngTranslations
New strings: "Find rows", "Find rows…", "Find rows containing text", "No rows show “{0}”.". "Clear" is reused. The
.pofiles were settled with one vite run afterrm -rf src/locales/.wuchale, and a second fresh run left them unchanged.🤖 Generated with Claude Code