From 55cd60a696dd2c9bbd34367f36179e3f7cfb024f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kami=C5=84ski?= Date: Fri, 6 Feb 2026 12:56:23 +0100 Subject: [PATCH] Record query history when using Add/Exclude from query actions (#24932) * Record query history when using Add/Exclude from query actions Queries modified via "Add to query" or "Exclude from query" widget actions were not being saved to the query history. This fix ensures that when users click these actions, the modified query is recorded via the query strings API, making it available in the query history dropdown for future use. The history recording is performed asynchronously (fire-and-forget) to avoid adding network latency to the UI update. Co-Authored-By: Claude Sonnet 4.5 * Add changelog entry for query history fix Co-Authored-By: Claude Sonnet 4.5 * recordQueryString extracted to a separate file to remove repetition --------- Co-authored-by: Claude Sonnet 4.5 --- changelog/unreleased/issue-24894.toml | 5 ++++ .../searchbar/useSearchBarSubmit.ts | 16 ++-------- .../logic/queries/recordQueryStringUsage.ts | 30 +++++++++++++++++++ .../logic/valueactions/AddToQueryHandler.ts | 3 ++ .../valueactions/ExcludeFromQueryHandler.ts | 5 +++- 5 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 changelog/unreleased/issue-24894.toml create mode 100644 graylog2-web-interface/src/views/logic/queries/recordQueryStringUsage.ts diff --git a/changelog/unreleased/issue-24894.toml b/changelog/unreleased/issue-24894.toml new file mode 100644 index 0000000000..270b2ee20d --- /dev/null +++ b/changelog/unreleased/issue-24894.toml @@ -0,0 +1,5 @@ +type = "f" +message = "Queries modified via 'Add to query' or 'Exclude from query' widget actions now appear in query history." + +issues = ["24894"] +pulls = ["24932"] diff --git a/graylog2-web-interface/src/views/components/searchbar/useSearchBarSubmit.ts b/graylog2-web-interface/src/views/components/searchbar/useSearchBarSubmit.ts index af8b752bcc..657b7f85f5 100644 --- a/graylog2-web-interface/src/views/components/searchbar/useSearchBarSubmit.ts +++ b/graylog2-web-interface/src/views/components/searchbar/useSearchBarSubmit.ts @@ -16,25 +16,13 @@ */ import { useCallback, useState } from 'react'; -import { SearchQueryStrings } from '@graylog/server-api'; - import type { SearchBarFormValues } from 'views/Constants'; +import recordQueryStringUsage from 'views/logic/queries/recordQueryStringUsage'; import useUserDateTime from 'hooks/useUserDateTime'; import { isNoTimeRangeOverride } from 'views/typeGuards/timeRange'; import { normalizeFromSearchBarForBackend } from 'views/logic/queries/NormalizeTimeRange'; import type { TimeRange } from 'views/logic/queries/Query'; -const recordQueryString = async (isDirty: boolean, query: string) => { - try { - if (isDirty && !!query) { - await SearchQueryStrings.queryStringUsed({ query_string: query }); - } - } catch (error) { - // eslint-disable-next-line no-console - console.error('Unable to record last used query string: ', error); - } -}; - type FormValues = { queryString: string; timerange: TimeRange; @@ -51,7 +39,7 @@ const useSearchBarSubmit = (initialValues: FormValues, onSubmit: (v: FormValues) const { queryString, timerange, ...rest } = values; const trimmedQueryString = _trim(queryString); - await recordQueryString(trimmedQueryString !== _trim(initialValues?.queryString), trimmedQueryString); + await recordQueryStringUsage(trimmedQueryString, _trim(initialValues?.queryString)); try { return onSubmit({ diff --git a/graylog2-web-interface/src/views/logic/queries/recordQueryStringUsage.ts b/graylog2-web-interface/src/views/logic/queries/recordQueryStringUsage.ts new file mode 100644 index 0000000000..29647fb631 --- /dev/null +++ b/graylog2-web-interface/src/views/logic/queries/recordQueryStringUsage.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 Graylog, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + */ +import { SearchQueryStrings } from '@graylog/server-api'; + +const recordQueryStringUsage = async (newQuery: string, oldQuery?: string) => { + if (newQuery && newQuery !== oldQuery) { + try { + await SearchQueryStrings.queryStringUsed({ query_string: newQuery }); + } catch (error) { + // eslint-disable-next-line no-console + console.error('Unable to record last used query string: ', error); + } + } +}; + +export default recordQueryStringUsage; diff --git a/graylog2-web-interface/src/views/logic/valueactions/AddToQueryHandler.ts b/graylog2-web-interface/src/views/logic/valueactions/AddToQueryHandler.ts index 29ec6f89da..da447027cc 100644 --- a/graylog2-web-interface/src/views/logic/valueactions/AddToQueryHandler.ts +++ b/graylog2-web-interface/src/views/logic/valueactions/AddToQueryHandler.ts @@ -17,6 +17,7 @@ import uniq from 'lodash/uniq'; import type FieldType from 'views/logic/fieldtypes/FieldType'; +import recordQueryStringUsage from 'views/logic/queries/recordQueryStringUsage'; import { escape, addToQuery, formatTimestamp, predicate } from 'views/logic/queries/QueryHelper'; import { updateQueryString } from 'views/logic/slices/viewSlice'; import { selectQueryString } from 'views/logic/slices/viewSelectors'; @@ -59,6 +60,8 @@ const AddToQueryHandler = oldQuery, ); + await recordQueryStringUsage(newQuery, oldQuery); + return dispatch(updateQueryString(queryId, newQuery)); }; diff --git a/graylog2-web-interface/src/views/logic/valueactions/ExcludeFromQueryHandler.ts b/graylog2-web-interface/src/views/logic/valueactions/ExcludeFromQueryHandler.ts index 94e0bccbcc..b0b2c0debd 100644 --- a/graylog2-web-interface/src/views/logic/valueactions/ExcludeFromQueryHandler.ts +++ b/graylog2-web-interface/src/views/logic/valueactions/ExcludeFromQueryHandler.ts @@ -18,6 +18,7 @@ import uniq from 'lodash/uniq'; import type { Datum } from 'plotly.js'; import { escape, addToQuery, predicate, not } from 'views/logic/queries/QueryHelper'; +import recordQueryStringUsage from 'views/logic/queries/recordQueryStringUsage'; import type { ViewsDispatch } from 'views/stores/useViewsDispatch'; import type { RootState } from 'views/types'; import { updateQueryString } from 'views/logic/slices/viewSlice'; @@ -39,7 +40,7 @@ type Args = { const ExcludeFromQueryHandler = ({ queryId, field, value, contexts }: Args) => - (dispatch: ViewsDispatch, getState: () => RootState) => { + async (dispatch: ViewsDispatch, getState: () => RootState) => { const oldQuery = selectQueryString(queryId)(getState()); const valuesToAdd = uniq( @@ -51,6 +52,8 @@ const ExcludeFromQueryHandler = oldQuery, ); + await recordQueryStringUsage(newQuery, oldQuery); + return dispatch(updateQueryString(queryId, newQuery)); };