From 227be5a53fdaade7d178a6bfe2e0910f29383a2a Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 13 Sep 2021 13:52:42 -0400 Subject: [PATCH] [Security Solution] Timeline uses existing filter manager (#111732) (#111969) * use existing filterManager * remove unused default value * unit test * fix type Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Angela Chuang <6295984+angorayc@users.noreply.github.com> --- .../hover_actions/use_hover_action_items.tsx | 13 ++++++++----- .../timeline/query_tab_content/index.tsx | 17 ++++++++++++++--- .../public/timelines/store/timeline/helpers.ts | 1 + .../timelines/store/timeline/reducer.test.ts | 18 ++++++++++++++++++ 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.tsx b/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.tsx index f717a72ab8ad5..7d480c9e4b04f 100644 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.tsx +++ b/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.tsx @@ -20,6 +20,7 @@ import { SourcererScopeName } from '../../store/sourcerer/model'; import { useSourcererScope } from '../../containers/sourcerer'; import { timelineSelectors } from '../../../timelines/store/timeline'; import { ShowTopNButton } from './actions/show_top_n'; +import { FilterManager } from '../../../../../../../src/plugins/data/public'; export interface UseHoverActionItemsProps { dataProvider?: DataProvider | DataProvider[]; @@ -74,7 +75,7 @@ export const useHoverActionItems = ({ values, }: UseHoverActionItemsProps): UseHoverActionItems => { const kibana = useKibana(); - const { timelines } = kibana.services; + const { timelines, uiSettings } = kibana.services; // Common actions used by the alert table and alert flyout const { getAddToTimelineButton, @@ -84,17 +85,19 @@ export const useHoverActionItems = ({ getFilterOutValueButton, getOverflowButton, } = timelines.getHoverActions(); - const filterManagerBackup = useMemo(() => kibana.services.data.query.filterManager, [ kibana.services.data.query.filterManager, ]); const getManageTimeline = useMemo(() => timelineSelectors.getManageTimelineById(), []); - const { filterManager: activeFilterMananager } = useDeepEqualSelector((state) => + const { filterManager: activeFilterManager } = useDeepEqualSelector((state) => getManageTimeline(state, timelineId ?? '') ); const filterManager = useMemo( - () => (timelineId === TimelineId.active ? activeFilterMananager : filterManagerBackup), - [timelineId, activeFilterMananager, filterManagerBackup] + () => + timelineId === TimelineId.active + ? activeFilterManager ?? new FilterManager(uiSettings) + : filterManagerBackup, + [uiSettings, timelineId, activeFilterManager, filterManagerBackup] ); // Regarding data from useManageTimeline: diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx index abbb991c274da..3dc2d98f16462 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx @@ -14,7 +14,7 @@ import { EuiBadge, } from '@elastic/eui'; import { isEmpty } from 'lodash/fp'; -import React, { useState, useMemo, useEffect, useCallback } from 'react'; +import React, { useMemo, useEffect, useCallback } from 'react'; import styled from 'styled-components'; import { Dispatch } from 'redux'; import { connect, ConnectedProps, useDispatch } from 'react-redux'; @@ -60,6 +60,7 @@ import { activeTimeline } from '../../../containers/active_timeline_context'; import { DetailsPanel } from '../../side_panel'; import { ExitFullScreen } from '../../../../common/components/exit_full_screen'; import { defaultControlColumn } from '../body/control_columns'; +import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; const TimelineHeaderContainer = styled.div` margin-top: 6px; @@ -193,7 +194,17 @@ export const QueryTabContentComponent: React.FC = ({ } = useSourcererScope(SourcererScopeName.timeline); const { uiSettings } = useKibana().services; - const [filterManager] = useState(new FilterManager(uiSettings)); + + const getManageTimeline = useMemo(() => timelineSelectors.getManageTimelineById(), []); + const { filterManager: activeFilterManager } = useDeepEqualSelector((state) => + getManageTimeline(state, timelineId ?? '') + ); + + const filterManager = useMemo(() => activeFilterManager ?? new FilterManager(uiSettings), [ + activeFilterManager, + uiSettings, + ]); + const esQueryConfig = useMemo(() => esQuery.getEsQueryConfig(uiSettings), [uiSettings]); const kqlQuery: { query: string; @@ -256,7 +267,7 @@ export const QueryTabContentComponent: React.FC = ({ id: timelineId, }) ); - }, [filterManager, timelineId, dispatch]); + }, [activeFilterManager, dispatch, filterManager, timelineId, uiSettings]); const [ isQueryLoading, diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts index 7c07410a2789a..6ee844958aeed 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts @@ -156,6 +156,7 @@ export const addTimelineToStore = ({ ...timelineById, [id]: { ...timeline, + filterManager: timelineById[id].filterManager, isLoading: timelineById[id].isLoading, initialized: timelineById[id].initialized, dateRange: diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts index c0dcba6920b60..eceafb9b56cdd 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts @@ -52,6 +52,7 @@ import { TimelineModel } from './model'; import { timelineDefaults } from './defaults'; import { TimelineById } from './types'; import { Direction } from '../../../../common/search_strategy'; +import { FilterManager } from '../../../../../../../src/plugins/data/public'; jest.mock('../../../common/components/url_state/normalize_time_range.ts'); jest.mock('../../../common/utils/default_date_settings', () => { @@ -63,6 +64,8 @@ jest.mock('../../../common/utils/default_date_settings', () => { }; }); +const mockFilterManager = {} as FilterManager; + const basicDataProvider: DataProvider = { and: [], id: '123', @@ -97,6 +100,7 @@ const basicTimeline: TimelineModel = { eventIdToNoteIds: {}, excludedRowRendererIds: [], expandedDetail: {}, + filterManager: mockFilterManager, highlightedDropAndProviderId: '', historyIds: [], id: 'foo', @@ -194,6 +198,20 @@ describe('Timeline', () => { }, }); }); + + test('should contain existing filterManager', () => { + const update = addTimelineToStore({ + id: 'foo', + timeline: { + ...basicTimeline, + status: TimelineStatus.immutable, + timelineType: TimelineType.template, + }, + timelineById: timelineByIdMock, + }); + + expect(update.foo.filterManager).toEqual(mockFilterManager); + }); }); describe('#addNewTimeline', () => {