Skip to content

Carry search filters into widget replay search#26151

Merged
dennisoelkers merged 3 commits into
masterfrom
feature/replay-search-with-filters
May 29, 2026
Merged

Carry search filters into widget replay search#26151
dennisoelkers merged 3 commits into
masterfrom
feature/replay-search-with-filters

Conversation

@dennisoelkers

@dennisoelkers dennisoelkers commented May 28, 2026

Copy link
Copy Markdown
Member

Note: This needs a backport to previous versions.

Description

When clicking "Replay search" on a dashboard widget that has search filters configured, the resulting search now includes those filters. Previously they were dropped, so the replayed search returned a broader result set than the widget.

Filters are persisted to local storage under the replay session-id (alongside parameters) and picked up by NewSearchPage when it builds the saved search view.

Motivation and Context

Fixes Graylog2/graylog-plugin-enterprise#8869. The replay button promises to land the user on the same search the widget ran, but it was only forwarding query/timerange/streams/parameters — search filters were silently lost.

How Has This Been Tested?

  • Extended ReplaySearchButton.test.tsx:
    • link gets a session-id when filters are present
    • no session-id when neither parameters nor filters are present (or filters list is empty)
    • on click, filters are written to local storage under the session id and NewSearchPage can read them back
  • Verified manually in a dashboard widget with search filters configured: replaying lands on a search containing the same filters.

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Refactoring (non-breaking change)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have requested a documentation update.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.

dennisoelkers and others added 3 commits May 28, 2026 10:53
Replaying a dashboard widget previously dropped any search filters
configured on it — only the query string, time range, streams, and
parameters travelled along. ReplaySearchButton now also accepts the
widget's `filters` (a `FiltersType` list of `SearchFilter`), serialises
them into the local-storage payload that the new search page pulls out
via the `session-id` query param, and ensures the session-id is added
to the URL whenever filters or parameters are present.

NewSearchPage's session reader is widened to extract `filters` from the
stored payload and forwards them via `useCreateSavedSearch` →
`ViewGenerator` → `QueryGenerator` (which already accepts a 6th
`searchFilters` positional arg, just lacking a caller).

Also realigns `QueryGenerator`'s `SearchFilter` import to `views/types`
to match what `Query.filters` actually stores — the previous
`components/event-definitions/event-definitions-types` flavour required
fields (`id`, `title`, `disabled`, `negation`) that widget filters
don't necessarily carry.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@dennisoelkers dennisoelkers requested review from Copilot and linuspahl and removed request for linuspahl May 28, 2026 09:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR carries dashboard widget search filters through replay search so the replayed search matches the widget’s original query context.

Changes:

  • Persists widget filters with replay session state and restores them in NewSearchPage.
  • Threads searchFilters through saved-search/view/query generation.
  • Adds replay-button tests and an unreleased changelog entry.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
graylog2-web-interface/src/views/pages/NewSearchPage.tsx Reads replay state including filters from local storage and passes filters into saved search creation.
graylog2-web-interface/src/views/logic/views/ViewGenerator.ts Forwards restored filters into query generation.
graylog2-web-interface/src/views/logic/views/UseCreateSavedSearch.ts Adds searchFilters to saved search creation props.
graylog2-web-interface/src/views/logic/queries/QueryGenerator.ts Uses the canonical views SearchFilter type.
graylog2-web-interface/src/views/components/widgets/WidgetActionsMenu.tsx Supplies widget filters to the replay search button.
graylog2-web-interface/src/views/components/widgets/ReplaySearchButton.tsx Adds filter-aware session IDs and persists filters on replay.
graylog2-web-interface/src/views/components/widgets/ReplaySearchButton.test.tsx Covers replay links and local-storage persistence for filters.
changelog/unreleased/pr-26151.toml Adds a bug-fix changelog entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

timeRange,
queryString,
parameters,
searchFilters,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

TIL: toHaveBeenCalledWith (and other equality-checking assertions) do not consider {} to be different from { foo: undefined }. The idea is that a consumer of it would not experience a different behavior when accessing that subkey (i.e. argument.foo would be undefined for both {} and { foo: undefined }). So this comment from Copilot is not false, but not relevant/not an issue for the current change.

@linuspahl linuspahl self-assigned this May 29, 2026

@linuspahl linuspahl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Works as described. Tested the following scenario:

User A (non-admin)

  1. creates a search filter and a dashboard
  2. shares the dashboard with User B (non-admin)
  3. User B opens dashboard and replays search for a widget.

User B sees a new search where the search filter is displayed and marked as "shared with me". Once User B tries to save the search, they see an alert for "A copy for 1 referenced search filter will be created, because of missing permissions."

This behavior makes sense imo.

@dennisoelkers dennisoelkers merged commit a4d1554 into master May 29, 2026
27 of 28 checks passed
@dennisoelkers dennisoelkers deleted the feature/replay-search-with-filters branch May 29, 2026 10:51
dennisoelkers added a commit that referenced this pull request May 29, 2026
* Carry search filters into widget replay search

Replaying a dashboard widget previously dropped any search filters
configured on it — only the query string, time range, streams, and
parameters travelled along. ReplaySearchButton now also accepts the
widget's `filters` (a `FiltersType` list of `SearchFilter`), serialises
them into the local-storage payload that the new search page pulls out
via the `session-id` query param, and ensures the session-id is added
to the URL whenever filters or parameters are present.

NewSearchPage's session reader is widened to extract `filters` from the
stored payload and forwards them via `useCreateSavedSearch` →
`ViewGenerator` → `QueryGenerator` (which already accepts a 6th
`searchFilters` positional arg, just lacking a caller).

Also realigns `QueryGenerator`'s `SearchFilter` import to `views/types`
to match what `Query.filters` actually stores — the previous
`components/event-definitions/event-definitions-types` flavour required
fields (`id`, `title`, `disabled`, `negation`) that widget filters
don't necessarily carry.



* Add changelog snippet for #26151

---------


(cherry picked from commit a4d1554)

Co-authored-by: Dennis Oelkers <dennis@graylog.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
dennisoelkers added a commit that referenced this pull request May 29, 2026
* Carry search filters into widget replay search

Replaying a dashboard widget previously dropped any search filters
configured on it — only the query string, time range, streams, and
parameters travelled along. ReplaySearchButton now also accepts the
widget's `filters` (a `FiltersType` list of `SearchFilter`), serialises
them into the local-storage payload that the new search page pulls out
via the `session-id` query param, and ensures the session-id is added
to the URL whenever filters or parameters are present.

NewSearchPage's session reader is widened to extract `filters` from the
stored payload and forwards them via `useCreateSavedSearch` →
`ViewGenerator` → `QueryGenerator` (which already accepts a 6th
`searchFilters` positional arg, just lacking a caller).

Also realigns `QueryGenerator`'s `SearchFilter` import to `views/types`
to match what `Query.filters` actually stores — the previous
`components/event-definitions/event-definitions-types` flavour required
fields (`id`, `title`, `disabled`, `negation`) that widget filters
don't necessarily carry.



* Add changelog snippet for #26151

---------


(cherry picked from commit a4d1554)

Co-authored-by: Dennis Oelkers <dennis@graylog.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
dennisoelkers added a commit that referenced this pull request Jun 1, 2026
* Carry search filters into widget replay search

Replaying a dashboard widget previously dropped any search filters
configured on it — only the query string, time range, streams, and
parameters travelled along. ReplaySearchButton now also accepts the
widget's `filters` (a `FiltersType` list of `SearchFilter`), serialises
them into the local-storage payload that the new search page pulls out
via the `session-id` query param, and ensures the session-id is added
to the URL whenever filters or parameters are present.

NewSearchPage's session reader is widened to extract `filters` from the
stored payload and forwards them via `useCreateSavedSearch` →
`ViewGenerator` → `QueryGenerator` (which already accepts a 6th
`searchFilters` positional arg, just lacking a caller).

Also realigns `QueryGenerator`'s `SearchFilter` import to `views/types`
to match what `Query.filters` actually stores — the previous
`components/event-definitions/event-definitions-types` flavour required
fields (`id`, `title`, `disabled`, `negation`) that widget filters
don't necessarily carry.



* Add changelog snippet for #26151

---------


(cherry picked from commit a4d1554)

Co-authored-by: Dennis Oelkers <dennis@graylog.com>
Co-authored-by: Claude Opus 4.7 <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.

3 participants