feat: persist models page filters across navigations#733
feat: persist models page filters across navigations#733fergusfinn wants to merge 2 commits intomainfrom
Conversation
Add usePersistedFilter hook that uses URL search params as the source of truth with localStorage fallback for when params are absent. This means filter selections survive page navigations while remaining shareable via URL. All models page filters (endpoint, groups, model type, accessible only) now use this hook consistently. Also fixes handleTabChange clobbering other URL params when switching view modes.
|
🚅 Deployed to the control-layer-pr-733 environment in industrious-light
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 55c652db5f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Reset all filters with a single search-param update
All four setters in handleClearFilters now call usePersistedFilter, and each of those performs its own setSearchParams navigation. Because search-param updates are not queued like React state updates, these back-to-back calls can overwrite each other, so clicking Clear filters may leave some query params (for example endpoint, groups, or type) behind and keep filters active. Build and apply one combined URL update for the reset path instead of issuing multiple setter calls.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Validate model-type param before treating it as enum
filterModelType is now sourced from URL/localStorage as an arbitrary string, but this line force-casts it to "all" | "virtual" | "hosted". With an invalid value like ?type=foo (or stale persisted data), ModelsContent interprets it as is_composite=false, which applies hosted-only filtering instead of falling back to all, returning incorrect results. Normalize unrecognized values to all before passing them downstream.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds persisted filter state to the Models page by making URL search params the source of truth and using localStorage as a fallback when params are absent, improving shareability and “sticky” preferences across navigations.
Changes:
- Introduces
usePersistedFilterhook to sync filter state between URL params andlocalStorage. - Migrates Models page filters (endpoint, groups, type, accessible-only) to use the new hook.
- Updates tab switching to preserve existing URL params when changing view modes.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| dashboard/src/hooks/usePersistedFilter.ts | New hook implementing URL-param-driven filters with localStorage fallback/persistence. |
| dashboard/src/components/features/models/Models/Models.tsx | Adopts usePersistedFilter for Models filters and fixes tab change URL param clobbering. |
- Remove unused FilterDefaults interface (TS6196) - Fix overload signature compatibility with strict mode (TS2394) - Use stable module-level constant for empty groups array fallback - Validate model type from URL/localStorage against allowed values - Batch-clear all filter params in handleClearFilters to avoid back-to-back setSearchParams race condition - Export clearPersistedFilters helper for atomic reset
Summary
usePersistedFilterhook — URL search params as source of truth, localStorage as fallback for when params are absenthandleTabChangeclobbering other URL params when switching between grid/status viewsHow it works
/modelswith no params → localStorage defaults kick in (sticky preferences)/models?groups=abc&type=virtual→ URL takes precedence (shareable links)Test plan