Skip to content

Add faceted search with operators and saved searches - #2431

Open
ramiadavid wants to merge 1 commit into
freelensapp:mainfrom
ramiadavid:feature/advanced-search
Open

ramiadavid wants to merge 1 commit into
freelensapp:mainfrom
ramiadavid:feature/advanced-search

Conversation

@ramiadavid

@ramiadavid ramiadavid commented Aug 26, 2026

Copy link
Copy Markdown

Fixes #1536

Description of changes:

Search boxes now build facets: type text, pick a field from the dropdown, and it
becomes a removable chip inside the field. Values within a facet are OR-ed and
separate facets are AND-ed, which covers the and / or / not combinations the
issue asks for.

image

Six operators: : contains, = equals, =~ matches regex, !: does not contain,
!= not equals, !~ does not match regex. Picking one re-filters immediately;
committing a chip freezes it, so a chip keeps meaning what it meant when it was
added.

The issue suggested Slack's syntax as a possible pattern. This goes with visible
chips instead of modifiers typed into the query, so the active filter is always on
screen and there is no syntax to learn. Happy to revisit if you would rather have the
Slack style.

Named saved searches per view, persisted with the user's preferences. Applying one
restores the whole query.

image

Eight views expose named fields: Pods, Deployments, Services, Events, Nodes, Secrets,
Config Maps and Namespaces. Every other view keeps exactly its current behaviour,
offering only "All fields".

Design notes worth a reviewer's attention:

A facet naming a field the current view does not have is skipped and shown struck
through
, not applied. Applying it would empty the list for a positive operator and
filter nothing for a negative one, so the same chip would look broken or lie about
being applied depending on its operator. It is kept, so it applies again on a view
that does have the field - which matters because the linked search carries facets
across views. The label travels with the facet, so the chip still reads properly
where the field is unknown.

image
  • search keeps its meaning; searchOp and facets are new params beside it, so
    existing links and searchUrlParam.set(...) callers (the catalog's label badges,
    for one) behave exactly as before. A malformed facets param degrades to "no
    facets" rather than breaking the view.
  • Regular expressions are unanchored: in a search box =~ ngin has to find
    my-nginx. Anchor explicitly with ^...$.
  • Negative operators with several values mean "none of them". OR-ing negations would
    be true for almost everything.
  • Input gains a contentLeft prop, symmetric to the existing contentRight, so the
    chips render inside the field. It is the only change here touching a shared
    component, and it is purely additive.
  • The linked search now carries the whole query rather than just the text. Carrying
    only the text turned a faceted search into a bare query when navigating away and
    back, since routing pushes a path with no query string.

Testing:

  • 157 new unit tests covering the facet model, the operators, URL round-tripping and
    the filtering through ItemListLayout.
  • Full core suite green on Linux: 2626 passed, 0 failed.
  • type:check, biome check and build:di clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

Advanced Search

1 participant