1c5bff86519b3323cb3f5f694260c3e0e0b2efe0
The *FilterBar family (FilterBar / SessionFilterBar / PurchaseFilterBar / DeviceFilterBar / PlatformFilterBar / PlayEventFilterBar) previously shared the collapsible chrome through a free `_filter_bar(fields, ...)` helper that each function called at the end. Replace that with a `_FilterBarBase` BaseComponent: it owns the chrome render() and declares `media = _FILTER_BAR_MEDIA`, and each bar is now a subclass implementing `build_fields()`. The per-entity field-building bodies move verbatim into module-level `_<entity>_fields(existing, ...)` functions that each subclass delegates to, so the large bodies are untouched (no reindentation) and the diff stays reviewable. Media still bubbles: BaseComponent.collect_media() merges the bar's own filter_bar.js with the search_select.js / range_slider.js / date_range_picker.js declared by the contained widgets. Call sites are unchanged — `FilterBar(filter_json=..., preset_list_url=...)` now instantiates a Node instead of calling a function, and both `str(bar)` and `collect_media(bar)` behave as before. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Timetracker
A simple game catalogue and play session tracker.
Development
The project uses uv to manage Python versions and dependencies.
Simply run:
make init
This installs the correct Python version, syncs all dependencies, and installs npm packages.
Afterwards, you can start the development server using make dev.
Description
Releases
23
Languages
Python
62.4%
JavaScript
17.5%
CSS
14.9%
HTML
3.8%
TypeScript
0.6%
Other
0.7%