Skip to content

feat: persist models page filters across navigations#733

Open
fergusfinn wants to merge 2 commits intomainfrom
feat/persist-model-filters
Open

feat: persist models page filters across navigations#733
fergusfinn wants to merge 2 commits intomainfrom
feat/persist-model-filters

Conversation

@fergusfinn
Copy link
Contributor

Summary

  • Adds usePersistedFilter hook — URL search params as source of truth, localStorage as fallback for when params are absent
  • Migrates all models page filters (endpoint, groups, model type, accessible only) to use it consistently
  • Fixes handleTabChange clobbering other URL params when switching between grid/status views

How it works

  • User sets a filter → written to both URL params and localStorage
  • User visits /models with no params → localStorage defaults kick in (sticky preferences)
  • User visits /models?groups=abc&type=virtual → URL takes precedence (shareable links)
  • User clears filters → localStorage cleaned up, URL params removed

Test plan

  • Set group + endpoint filters, navigate away, come back — filters should persist
  • Copy URL with filter params, open in new tab — should show same filtered view
  • Clear all filters — should reset to defaults, localStorage cleaned up
  • Switch between grid/status view — other filter params should not be lost

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.
@railway-app
Copy link

railway-app bot commented Feb 19, 2026

🚅 Deployed to the control-layer-pr-733 environment in industrious-light

Service Status Web Updated (UTC)
control-layer ✅ Success (View Logs) Web Feb 19, 2026 at 8:15 am

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines 123 to 126

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 usePersistedFilter hook to sync filter state between URL params and localStorage.
  • 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments