diff --git a/x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.tsx index 98bb6434ddafd..65f225c054598 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.tsx @@ -48,6 +48,7 @@ import { displaySuccessToast, displayErrorToast, } from '../../../common/components/toasters'; +import { getInvestigateInResolverAction } from '../../../timelines/components/timeline/body/helpers'; interface OwnProps { timelineId: TimelineIdLiteral; @@ -331,13 +332,14 @@ export const AlertsTableComponent: React.FC = ({ useEffect(() => { initializeTimeline({ - id: timelineId, - documentType: i18n.ALERTS_DOCUMENT_TYPE, defaultModel: alertsDefaultModel, + documentType: i18n.ALERTS_DOCUMENT_TYPE, footerText: i18n.TOTAL_COUNT_OF_ALERTS, + id: timelineId, loadingText: i18n.LOADING_ALERTS, - title: i18n.ALERTS_TABLE_TITLE, selectAll: canUserCRUD ? selectAll : false, + timelineRowActions: [getInvestigateInResolverAction({ dispatch, timelineId })], + title: i18n.ALERTS_TABLE_TITLE, }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/x-pack/plugins/security_solution/public/common/components/alerts_viewer/alerts_table.tsx b/x-pack/plugins/security_solution/public/common/components/alerts_viewer/alerts_table.tsx index 6783fcbd17582..12b2853f8f7e1 100644 --- a/x-pack/plugins/security_solution/public/common/components/alerts_viewer/alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/common/components/alerts_viewer/alerts_table.tsx @@ -69,7 +69,7 @@ const AlertsTableComponent: React.FC = ({ }) => { const dispatch = useDispatch(); const alertsFilter = useMemo(() => [...defaultAlertsFilters, ...pageFilters], [pageFilters]); - const { initializeTimeline, setTimelineRowActions } = useManageTimeline(); + const { initializeTimeline } = useManageTimeline(); useEffect(() => { initializeTimeline({ @@ -77,13 +77,10 @@ const AlertsTableComponent: React.FC = ({ documentType: i18n.ALERTS_DOCUMENT_TYPE, defaultModel: alertsDefaultModel, footerText: i18n.TOTAL_COUNT_OF_ALERTS, + timelineRowActions: [getInvestigateInResolverAction({ dispatch, timelineId })], title: i18n.ALERTS_TABLE_TITLE, unit: i18n.UNIT, }); - setTimelineRowActions({ - id: timelineId, - timelineRowActions: [getInvestigateInResolverAction({ dispatch, timelineId })], - }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.test.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.test.tsx index 3507b0f8c447d..432e369cdd0f6 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.test.tsx @@ -18,7 +18,7 @@ import { useAddToTimeline } from '../../hooks/use_add_to_timeline'; import { DraggableWrapperHoverContent } from './draggable_wrapper_hover_content'; import { ManageGlobalTimeline, - timelineDefaults, + getTimelineDefaults, } from '../../../timelines/components/manage_timeline'; import { TimelineId } from '../../../../common/types/timeline'; @@ -152,10 +152,7 @@ describe('DraggableWrapperHoverContent', () => { beforeEach(() => { onFilterAdded = jest.fn(); const manageTimelineForTesting = { - [timelineId]: { - ...timelineDefaults, - id: timelineId, - }, + [timelineId]: getTimelineDefaults(timelineId), }; wrapper = mount( @@ -249,8 +246,7 @@ describe('DraggableWrapperHoverContent', () => { const manageTimelineForTesting = { [timelineId]: { - ...timelineDefaults, - id: timelineId, + ...getTimelineDefaults(timelineId), filterManager, }, }; diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx index 9e38b14c4334a..910030d41a23e 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx @@ -7,7 +7,6 @@ import { EuiPanel } from '@elastic/eui'; import { getOr, isEmpty, union } from 'lodash/fp'; import React, { useEffect, useMemo, useState } from 'react'; -import { useDispatch } from 'react-redux'; import styled from 'styled-components'; import deepEqual from 'fast-deep-equal'; @@ -35,7 +34,6 @@ import { } from '../../../../../../../src/plugins/data/public'; import { inputsModel } from '../../store'; import { useManageTimeline } from '../../../timelines/components/manage_timeline'; -import { getInvestigateInResolverAction } from '../../../timelines/components/timeline/body/helpers'; const DEFAULT_EVENTS_VIEWER_HEIGHT = 500; @@ -93,7 +91,6 @@ const EventsViewerComponent: React.FC = ({ toggleColumn, utilityBar, }) => { - const dispatch = useDispatch(); const columnsHeader = isEmpty(columns) ? defaultHeaders : columns; const kibana = useKibana(); const { filterManager } = useKibana().services.data.query; @@ -103,16 +100,8 @@ const EventsViewerComponent: React.FC = ({ getManageTimelineById, setIsTimelineLoading, setTimelineFilterManager, - setTimelineRowActions, } = useManageTimeline(); - useEffect(() => { - setTimelineRowActions({ - id, - timelineRowActions: [getInvestigateInResolverAction({ dispatch, timelineId: id })], - }); - }, [setTimelineRowActions, id, dispatch]); - useEffect(() => { setIsTimelineLoading({ id, isLoading: isQueryLoading }); // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx index 503e9983692f1..da6ec784af6d4 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx @@ -25,7 +25,7 @@ import { Props } from './top_n'; import { StatefulTopN } from '.'; import { ManageGlobalTimeline, - timelineDefaults, + getTimelineDefaults, } from '../../../timelines/components/manage_timeline'; import { TimelineId } from '../../../../common/types/timeline'; @@ -272,8 +272,7 @@ describe('StatefulTopN', () => { filterManager = new FilterManager(mockUiSettingsForFilterManager); const manageTimelineForTesting = { [TimelineId.active]: { - ...timelineDefaults, - id: TimelineId.active, + ...getTimelineDefaults(TimelineId.active), filterManager, }, }; @@ -351,8 +350,7 @@ describe('StatefulTopN', () => { const manageTimelineForTesting = { [TimelineId.active]: { - ...timelineDefaults, - id: TimelineId.active, + ...getTimelineDefaults(TimelineId.active), filterManager, documentType: 'alerts', }, diff --git a/x-pack/plugins/security_solution/public/hosts/pages/navigation/events_query_tab_body.tsx b/x-pack/plugins/security_solution/public/hosts/pages/navigation/events_query_tab_body.tsx index 64cfacaeaf6dc..58026a28a04ce 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/navigation/events_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/navigation/events_query_tab_body.tsx @@ -5,6 +5,7 @@ */ import React, { useEffect } from 'react'; +import { useDispatch } from 'react-redux'; import { TimelineId } from '../../../../common/types/timeline'; import { StatefulEventsViewer } from '../../../common/components/events_viewer'; import { HostsComponentsQueryProps } from './types'; @@ -18,6 +19,7 @@ import { MatrixHistogramContainer } from '../../../common/components/matrix_hist import * as i18n from '../translations'; import { HistogramType } from '../../../graphql/types'; import { useManageTimeline } from '../../../timelines/components/manage_timeline'; +import { getInvestigateInResolverAction } from '../../../timelines/components/timeline/body/helpers'; const EVENTS_HISTOGRAM_ID = 'eventsOverTimeQuery'; @@ -57,13 +59,17 @@ export const EventsQueryTabBody = ({ startDate, }: HostsComponentsQueryProps) => { const { initializeTimeline } = useManageTimeline(); + const dispatch = useDispatch(); useEffect(() => { initializeTimeline({ id: TimelineId.hostsPageEvents, defaultModel: eventsDefaultModel, + timelineRowActions: [ + getInvestigateInResolverAction({ dispatch, timelineId: TimelineId.hostsPageEvents }), + ], }); - }, [initializeTimeline]); + }, [dispatch, initializeTimeline]); useEffect(() => { return () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx index 3b40c36fccd16..c71087de4a07e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx @@ -6,6 +6,7 @@ import React, { createContext, useCallback, useContext, useReducer } from 'react'; import { noop } from 'lodash/fp'; + // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { FilterManager } from '../../../../../../../src/plugins/data/public/query/filter_manager'; import { TimelineRowAction } from '../timeline/body/actions'; @@ -22,6 +23,7 @@ interface ManageTimelineInit { indexToAdd?: string[] | null; loadingText?: string; selectAll?: boolean; + timelineRowActions: TimelineRowAction[]; title?: string; unit?: (totalCount: number) => string; } @@ -73,19 +75,20 @@ type ActionManageTimeline = payload: { filterManager: FilterManager }; }; -export const timelineDefaults = { +export const getTimelineDefaults = (id: string) => ({ indexToAdd: null, defaultModel: timelineDefaultModel, loadingText: i18n.LOADING_EVENTS, footerText: i18nF.TOTAL_COUNT_OF_EVENTS, documentType: i18nF.TOTAL_COUNT_OF_EVENTS, selectAll: false, + id, isLoading: false, queryFields: [], timelineRowActions: [], title: i18n.EVENTS, unit: (n: number) => i18n.UNIT(n), -}; +}); const reducerManageTimeline = ( state: ManageTimelineById, action: ActionManageTimeline @@ -95,7 +98,7 @@ const reducerManageTimeline = ( return { ...state, [action.id]: { - ...timelineDefaults, + ...getTimelineDefaults(action.id), ...state[action.id], ...action.payload, }, @@ -216,8 +219,8 @@ const useTimelineManager = (manageTimelineForTesting?: ManageTimelineById): UseT if (state[id] != null) { return state[id]; } - initializeTimeline({ id }); - return { ...timelineDefaults, id }; + initializeTimeline({ id, timelineRowActions: [] }); + return getTimelineDefaults(id); }, [initializeTimeline, state] ); @@ -236,7 +239,7 @@ const useTimelineManager = (manageTimelineForTesting?: ManageTimelineById): UseT }; const init = { - getManageTimelineById: (id: string) => ({ ...timelineDefaults, id }), + getManageTimelineById: (id: string) => getTimelineDefaults(id), getTimelineFilterManager: () => undefined, setIndexToAdd: () => undefined, isManagedTimeline: () => false, @@ -245,6 +248,7 @@ const init = { setTimelineRowActions: () => noop, setTimelineFilterManager: () => noop, }; + const ManageTimelineContext = createContext(init); export const useManageTimeline = () => useContext(ManageTimelineContext); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx index 8855cba7a4c89..ae00edf5d1429 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx @@ -194,8 +194,7 @@ export const EventColumnView = React.memo( , ] : grouped.icon; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [button, ecsData, timelineActions, isPopoverOpen]); // , isPopoverOpen, closePopover, onButtonClick]); + }, [button, closePopover, id, onClickCb, ecsData, timelineActions, isPopoverOpen]); return ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/data_providers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/data_providers.test.tsx index 1c85b6e6d72bf..3a8c0d8831217 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/data_providers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/data_providers.test.tsx @@ -13,7 +13,7 @@ import { useMountAppended } from '../../../../common/utils/use_mount_appended'; import { DataProviders } from '.'; import { DataProvider } from './data_provider'; import { mockDataProviders } from './mock/mock_data_providers'; -import { ManageGlobalTimeline, timelineDefaults } from '../../manage_timeline'; +import { ManageGlobalTimeline, getTimelineDefaults } from '../../manage_timeline'; import { FilterManager } from '../../../../../../../../src/plugins/data/public/query/filter_manager'; import { createKibanaCoreStartMock } from '../../../../common/mock/kibana_core'; const mockUiSettingsForFilterManager = createKibanaCoreStartMock().uiSettings; @@ -28,8 +28,7 @@ describe('DataProviders', () => { test('renders correctly against snapshot', () => { const manageTimelineForTesting = { foo: { - ...timelineDefaults, - id: 'foo', + ...getTimelineDefaults('foo'), filterManager, }, }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.test.tsx index 3ad83914c73b9..9dc0b76224458 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.test.tsx @@ -16,7 +16,7 @@ import { mockDataProviders } from './mock/mock_data_providers'; import { Providers } from './providers'; import { DELETE_CLASS_NAME, ENABLE_CLASS_NAME, EXCLUDE_CLASS_NAME } from './provider_item_actions'; import { useMountAppended } from '../../../../common/utils/use_mount_appended'; -import { ManageGlobalTimeline, timelineDefaults } from '../../manage_timeline'; +import { ManageGlobalTimeline, getTimelineDefaults } from '../../manage_timeline'; const mockUiSettingsForFilterManager = createKibanaCoreStartMock().uiSettings; @@ -27,8 +27,7 @@ describe('Providers', () => { const manageTimelineForTesting = { foo: { - ...timelineDefaults, - id: 'foo', + ...getTimelineDefaults('foo'), filterManager, isLoading, }, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx index 18deaf0158723..ed7f8a447c51d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx @@ -177,12 +177,11 @@ export const TimelineComponent: React.FC = ({ setIndexToAdd, setIsTimelineLoading, setTimelineFilterManager, - setTimelineRowActions, } = useManageTimeline(); useEffect(() => { - initializeTimeline({ id, indexToAdd }); - setTimelineRowActions({ + initializeTimeline({ id, + indexToAdd, timelineRowActions: [getInvestigateInResolverAction({ dispatch, timelineId: id })], }); // eslint-disable-next-line react-hooks/exhaustive-deps