v0.12.0 – Global search, field filters & sortable columns
Lists used to appear only in the order records sit in the data block, and there was no way to look anything up across a file: finding the largest value, the nearest deadline, or one record among hundreds meant scanning by eye. This release adds two standard table-tool capabilities to the single-file app, implemented entirely client-side over the embedded data block.
Global search and field filters (OPEN-17)
- The header now has a search box that runs a live, case-insensitive full-text search across all fields of all entities — including record IDs, attachment filenames (never base64 payloads), resolved titles of reference fields, and calculated fields. Match counts per entity show on the tabs, matches are highlighted with
<mark>. - Per-entity field filters in a sidebar, typed by field type: text contains, choice multi-select, number range, date range. Facet fields keep their quick-filter chips with counts. Active filters appear as removable chips above the table, with "clear all" from two chips up.
- Filters combine with AND between fields, OR within a multi-select. Empty number fields don't fall through range checks (
Number("") === 0trap covered). - Entities whose schema has no filterable types simply get no filter UI but stay searchable.
Sortable columns (OPEN-18)
- Click a column header to sort ascending, click again for descending, click a third time to return to the original data-block order. Arrow indicator and
aria-sortreflect the active state. - Comparison is type-aware: numbers numerically (
10sorts after9, not as text), dates chronologically, text and enums with locale-awarelocaleComparein the current UI language. Reference columns sort by the resolved title of the target record, not the raw ID; attachments by filename. - Empty values group consistently at the bottom in both directions; ties break over the data-block order, so sorting never flickers.
Decisions worth knowing
- Search, filter and sort state lives only in component/session state. Nothing touches
localStorage,IndexedDB, or the embedded data block — underfile://those stores are unreliable, and Save continues to write a new HTML file with the data block as the single source of truth. Reload intentionally resets view state. - Sorting logic lives in
src/lib/sort.js, search insrc/lib/search.js; both are pure-function modules covered by new assertions in all three test suites.
Behavior changes for existing files
- Every entity list now opens sorted ascending by its first column instead of raw data-block order. Clicking the active header twice more returns you to the original order for the session.
schema.searchis no longer read. The old per-entity list-search configuration is superseded by the global header search, which needs no schema configuration. Existing entries are ignored harmlessly, but remove them when you next touch the domain.
Consciously not included
- Multi-level sorting (primary + secondary key chosen by the user), persisting sort preference beyond the session, and sorting inside dashboard widgets.
- The remaining feature requests from the August ideas round are still in development and will ship in a later release: per-record duplication (OPEN-20), multi-select with bulk actions (OPEN-19) and metric tiles for the dashboard (OPEN-21).
Full changelog: v0.11.0...v0.12.0
