From 280db347f428ca818be50f92f8be938575f43e0f Mon Sep 17 00:00:00 2001 From: Jacek Kolezynski Date: Wed, 19 Feb 2025 16:43:10 +0100 Subject: [PATCH] [Security Solution] Fix editing in KQL Query Bar (#208212) **Partially resolves: #203523** ## Summary Fixing the issue of KQL query bar edit component not showing properly long multiline KQL queries. The query now isn't fully visible, and it's not possible to navigate with Up/Down keyboard keys. It's also not possible to scroll down, as the component doesn't allow to insert new line symbols. I am fixing the behavior by: - setting the `bubbleSubmitEvent={true}` so that the key press can propagate to higher components and be served properly. This fixes the problem of not allowing to enter new lines. - I am not touching the broken behavior of Up/Down arrow keys, which intercepts the event and instead of moving the cursor, iterates items in the Suggestions panel, which is counterintuitive. Separate issue will be created for the Kibana Visualization team. - I am modifying one css style in Kibana Visualization to set height to and adding a class to set proper alignment of buttons. # BEFORE - Not possible to insert new lines. - Arrow DOWN takes focus to Suggestions Panel, then together with Arrow UP it is used to iterate the suggestions - When textarea grows it gets hidden below the parent's panel https://github.com/user-attachments/assets/d97b81e3-7409-4089-865d-89ee702744f9 # AFTER - Possible to insert new lines - Behavior of DOWN / UP Arrows stays the same - When textarea grows the whole panel resizes https://github.com/user-attachments/assets/3a59923b-0fb1-49e7-b11d-55474f465ca2 https://github.com/user-attachments/assets/48efd325-1c66-43ca-9936-69ef37b4ee7a (cherry picked from commit 8159319d75a3563228378a54492cb27919efea18) --- .../query_string_input/query_bar_top_row.tsx | 4 +- .../public/search_bar/search_bar.tsx | 2 + .../common/components/query_bar/index.tsx | 82 +++++++++++++------ .../query_bar_field/query_field.tsx | 3 + .../components/step_define_rule/index.tsx | 1 + .../fields/kql_query/kql_query_edit.tsx | 1 + 6 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src/platform/plugins/shared/unified_search/public/query_string_input/query_bar_top_row.tsx b/src/platform/plugins/shared/unified_search/public/query_string_input/query_bar_top_row.tsx index d6bab939c1efc..c5eef28a71797 100644 --- a/src/platform/plugins/shared/unified_search/public/query_string_input/query_bar_top_row.tsx +++ b/src/platform/plugins/shared/unified_search/public/query_string_input/query_bar_top_row.tsx @@ -187,6 +187,7 @@ export interface QueryBarTopRowProps renderQueryInputAppend?: () => React.ReactNode; disableExternalPadding?: boolean; onESQLDocsFlyoutVisibilityChanged?: ESQLMenuPopoverProps['onESQLDocsFlyoutVisibilityChanged']; + bubbleSubmitEvent?: boolean; } export const SharingMetaFields = React.memo(function SharingMetaFields({ @@ -661,7 +662,7 @@ export const QueryBarTopRow = React.memo( function renderFilterButtonGroup() { return ( (Boolean(props.showAddFilter) || Boolean(props.prepend)) && ( - + void; // Autorefresh onRefreshChange?: (options: { isPaused: boolean; refreshInterval: number }) => void; + bubbleSubmitEvent?: boolean; } export interface SearchBarOwnProps { @@ -662,6 +663,7 @@ class SearchBarUI extends C renderQueryInputAppend={this.props.renderQueryInputAppend} disableExternalPadding={this.props.displayStyle === 'withBorders'} onESQLDocsFlyoutVisibilityChanged={this.props.onESQLDocsFlyoutVisibilityChanged} + bubbleSubmitEvent={this.props.bubbleSubmitEvent} /> ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/query_bar/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/query_bar/index.tsx index 793ca853598b3..c3ac1553e4ece 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/query_bar/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/query_bar/index.tsx @@ -6,6 +6,7 @@ */ import { cloneDeep, isEmpty } from 'lodash'; +import type { PropsWithChildren, FC } from 'react'; import React, { memo, useMemo, useCallback, useState, useEffect } from 'react'; import deepEqual from 'fast-deep-equal'; @@ -16,6 +17,7 @@ import type { DataView } from '@kbn/data-views-plugin/public'; import type { SearchBarProps } from '@kbn/unified-search-plugin/public'; import { SearchBar } from '@kbn/unified-search-plugin/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { css, Global } from '@emotion/react'; import { useKibana } from '../../lib/kibana'; import { convertToQueryType } from './convert_to_query_type'; @@ -37,11 +39,33 @@ export interface QueryBarComponentProps { onSavedQuery: (savedQuery: SavedQuery | undefined) => void; displayStyle?: SearchBarProps['displayStyle']; isDisabled?: boolean; + bubbleSubmitEvent?: boolean; } export const isDataView = (obj: unknown): obj is DataView => obj != null && typeof obj === 'object' && Object.hasOwn(obj, 'getName'); +const CustomStylesWrapper: FC> = ({ children }) => { + const wrapperClassName = 'ruleEditQueryBarWrapper'; + + const customCss = css` + .${wrapperClassName} .kbnQueryBar__filterButtonGroup { + align-self: start; + } + + .${wrapperClassName} .kbnQueryBar__wrap { + height: auto !important; + } + `; + + return ( + <> + +
{children}
+ + ); +}; + export const QueryBar = memo( ({ dateRangeFrom, @@ -61,6 +85,7 @@ export const QueryBar = memo( dataTestSubj, displayStyle, isDisabled, + bubbleSubmitEvent, }) => { const { data } = useKibana().services; const [dataView, setDataView] = useState(); @@ -156,33 +181,36 @@ export const QueryBar = memo( const timeHistory = useMemo(() => new TimeHistory(new Storage(localStorage)), []); const arrDataView = useMemo(() => (dataView != null ? [dataView] : []), [dataView]); return ( - + + + ); } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/query_bar_field/query_field.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/query_bar_field/query_field.tsx index 5694b7b432c85..32feeca8080b7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/query_bar_field/query_field.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/query_bar_field/query_field.tsx @@ -45,6 +45,7 @@ export interface QueryBarFieldProps { onSavedQueryError?: () => void; defaultSavedQuery?: SavedQuery | undefined; onOpenTimeline?: (timeline: TimelineModel) => void; + bubbleSubmitEvent?: boolean; } const actionTimelineToHide: ActionTimelineToShow[] = ['duplicate', 'createFrom']; @@ -80,6 +81,7 @@ export const QueryBarField = ({ resetToSavedQuery, onOpenTimeline, onSavedQueryError, + bubbleSubmitEvent, }: QueryBarFieldProps) => { const { value: fieldValue, setValue: setFieldValue } = field as FieldHook; const [originalHeight, setOriginalHeight] = useState(-1); @@ -286,6 +288,7 @@ export const QueryBarField = ({ hideSavedQuery={false} displayStyle="inPage" isDisabled={isDisabled} + bubbleSubmitEvent={bubbleSubmitEvent} /> )} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx index c5c3f1754b048..c5f400135faea 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx @@ -505,6 +505,7 @@ const StepDefineRuleComponent: FC = ({ onSavedQueryError: handleSavedQueryError, defaultSavedQuery, onOpenTimeline, + bubbleSubmitEvent: true, } as QueryBarFieldProps } /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/kql_query/kql_query_edit.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/kql_query/kql_query_edit.tsx index f377e17d8e23b..c6666203a6274 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/kql_query/kql_query_edit.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/three_way_diff/final_edit/fields/kql_query/kql_query_edit.tsx @@ -68,6 +68,7 @@ export function KqlQueryEdit({ isDisabled: isSavedQueryRule, defaultSavedQuery: savedQuery, resetToSavedQuery: isSavedQueryRule, + bubbleSubmitEvent: true, }} />