diff --git a/x-pack/plugins/security_solution/public/alerts/components/alerts_histogram_panel/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/alerts_histogram_panel/index.tsx index b002700d7eff0..533a9d51a9bcd 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/alerts_histogram_panel/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/alerts_histogram_panel/index.tsx @@ -11,6 +11,7 @@ import styled from 'styled-components'; import { isEmpty } from 'lodash/fp'; import uuid from 'uuid'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { DEFAULT_NUMBER_FORMAT, APP_ID } from '../../../../common/constants'; import { UpdateDateRange } from '../../../common/components/charts/common'; import { LegendItem } from '../../../common/components/charts/draggable_legend_item'; @@ -28,7 +29,7 @@ import { alertsHistogramOptions } from './config'; import { formatAlertsData, getAlertsHistogramQuery, showInitialLoadingSpinner } from './helpers'; import { AlertsHistogram } from './alerts_histogram'; import * as i18n from './translations'; -import { RegisterQuery, AlertsHistogramOption, AlertsAggregation, AlertsTotal } from './types'; +import { AlertsHistogramOption, AlertsAggregation, AlertsTotal } from './types'; import { LinkButton } from '../../../common/components/links'; import { SecurityPageName } from '../../../app/types'; @@ -52,12 +53,11 @@ const ViewAlertsFlexItem = styled(EuiFlexItem)` margin-left: 24px; `; -interface AlertsHistogramPanelProps { +interface AlertsHistogramPanelProps + extends Pick { chartHeight?: number; defaultStackByOption?: AlertsHistogramOption; - deleteQuery?: ({ id }: { id: string }) => void; filters?: Filter[]; - from: number; headerChildren?: React.ReactNode; /** Override all defaults, and only display this field */ onlyField?: string; @@ -65,13 +65,11 @@ interface AlertsHistogramPanelProps { legendPosition?: Position; panelHeight?: number; signalIndexName: string | null; - setQuery: (params: RegisterQuery) => void; showLinkToAlerts?: boolean; showTotalAlertsCount?: boolean; stackByOptions?: AlertsHistogramOption[]; timelineId?: string; title?: string; - to: number; updateDateRange: UpdateDateRange; } diff --git a/x-pack/plugins/security_solution/public/alerts/components/detection_engine_header_page/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/detection_engine_header_page/index.tsx index a3e76557a6ff5..78a18dc336e5b 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/detection_engine_header_page/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/detection_engine_header_page/index.tsx @@ -22,3 +22,5 @@ DetectionEngineHeaderPageComponent.defaultProps = { }; export const DetectionEngineHeaderPage = React.memo(DetectionEngineHeaderPageComponent); + +DetectionEngineHeaderPage.displayName = 'DetectionEngineHeaderPage'; diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.test.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.test.tsx index d033bc25e9801..fa7c85c95d87b 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.test.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.test.tsx @@ -17,6 +17,11 @@ import { useWithSource } from '../../../common/containers/source'; jest.mock('../../components/user_info'); jest.mock('../../../common/containers/source'); jest.mock('../../../common/components/link_to'); +jest.mock('../../../common/containers/use_global_time', () => ({ + useGlobalTime: jest + .fn() + .mockReturnValue({ from: 0, isInitializing: false, to: 0, setQuery: jest.fn() }), +})); jest.mock('react-router-dom', () => { const originalModule = jest.requireActual('react-router-dom'); diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx index dc0b22c82af3e..5c525a8553477 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx @@ -12,7 +12,7 @@ import { connect, ConnectedProps } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { SecurityPageName } from '../../../app/types'; import { TimelineId } from '../../../../common/types/timeline'; -import { GlobalTime } from '../../../common/containers/global_time'; +import { useGlobalTime } from '../../../common/containers/use_global_time'; import { useWithSource } from '../../../common/containers/source'; import { UpdateDateRange } from '../../../common/components/charts/common'; import { FiltersGlobal } from '../../../common/components/filters_global'; @@ -44,6 +44,7 @@ export const DetectionEnginePageComponent: React.FC = ({ query, setAbsoluteRangeDatePicker, }) => { + const { to, from, deleteQuery, setQuery } = useGlobalTime(); const { loading, isSignalIndexExists, @@ -131,36 +132,28 @@ export const DetectionEnginePageComponent: React.FC = ({ - - {({ to, from, deleteQuery, setQuery }) => ( - <> - <> - - - - - - )} - + + + ) : ( diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.test.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.test.tsx index 0acb18082379a..11099e8cfc755 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.test.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.test.tsx @@ -18,6 +18,12 @@ import { useParams } from 'react-router-dom'; jest.mock('../../../../../common/components/link_to'); jest.mock('../../../../components/user_info'); jest.mock('../../../../../common/containers/source'); +jest.mock('../../../../../common/containers/use_global_time', () => ({ + useGlobalTime: jest + .fn() + .mockReturnValue({ from: 0, isInitializing: false, to: 0, setQuery: jest.fn() }), +})); + jest.mock('react-router-dom', () => { const originalModule = jest.requireActual('react-router-dom'); @@ -50,6 +56,6 @@ describe('RuleDetailsPageComponent', () => { } ); - expect(wrapper.find('GlobalTime')).toHaveLength(1); + expect(wrapper.find('DetectionEngineHeaderPage')).toHaveLength(1); }); }); diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx index 2ec603546983e..b937e95c0a57e 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx @@ -56,7 +56,7 @@ import { StepPanel } from '../../../../components/rules/step_panel'; import { getStepsData, redirectToDetections, userHasNoPermissions } from '../helpers'; import * as ruleI18n from '../translations'; import * as i18n from './translations'; -import { GlobalTime } from '../../../../../common/containers/global_time'; +import { useGlobalTime } from '../../../../../common/containers/use_global_time'; import { alertsHistogramOptions } from '../../../../components/alerts_histogram_panel/config'; import { inputsSelectors } from '../../../../../common/store/inputs'; import { State } from '../../../../../common/store'; @@ -103,6 +103,7 @@ export const RuleDetailsPageComponent: FC = ({ query, setAbsoluteRangeDatePicker, }) => { + const { to, from, deleteQuery, setQuery } = useGlobalTime(); const { loading, isSignalIndexExists, @@ -263,169 +264,164 @@ export const RuleDetailsPageComponent: FC = ({ {hasIndexWrite != null && !hasIndexWrite && } {userHasNoPermissions(canUserCRUD) && } {indicesExist ? ( - - {({ to, from, deleteQuery, setQuery }) => ( - - - - - - - - {detectionI18n.LAST_ALERT} - {': '} - {lastAlerts} - , - ] - : []), - , - ]} - title={title} - > - + + + + + + + + {detectionI18n.LAST_ALERT} + {': '} + {lastAlerts} + , + ] + : []), + , + ]} + title={title} + > + + + + + + + + + - - - + {ruleI18n.EDIT_RULE_SETTINGS} + - - - - - {ruleI18n.EDIT_RULE_SETTINGS} - - - - - - + - - {ruleError} - - - - + + + + {ruleError} + + + + + + + + + + + {defineRuleData != null && ( + + )} + - - - - - - {defineRuleData != null && ( - - )} - - - - - - {scheduleRuleData != null && ( - - )} - - - + + + + {scheduleRuleData != null && ( + + )} + + + + + {tabs} + + {ruleDetailTab === RuleDetailTabs.alerts && ( + <> + - {tabs} - - {ruleDetailTab === RuleDetailTabs.alerts && ( - <> - - - {ruleId != null && ( - - )} - - )} - {ruleDetailTab === RuleDetailTabs.exceptions && ( - )} - {ruleDetailTab === RuleDetailTabs.failures && } - - - )} - + + )} + {ruleDetailTab === RuleDetailTabs.exceptions && ( + + )} + {ruleDetailTab === RuleDetailTabs.failures && } + + ) : ( diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx index 31f7e1b7fac7c..16fe2a6669ff0 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx @@ -31,7 +31,7 @@ import { GetTitle, GetSubTitle, } from '../../components/matrix_histogram/types'; -import { SetQuery } from '../../../hosts/pages/navigation/types'; +import { GlobalTimeArgs } from '../../containers/use_global_time'; import { QueryTemplateProps } from '../../containers/query_template'; import { setAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { InputsModelId } from '../../store/inputs/constants'; @@ -48,7 +48,7 @@ export interface OwnProps extends QueryTemplateProps { legendPosition?: Position; mapping?: MatrixHistogramMappingTypes; showSpacer?: boolean; - setQuery: SetQuery; + setQuery: GlobalTimeArgs['setQuery']; setAbsoluteRangeDatePickerTarget?: InputsModelId; showLegend?: boolean; stackByOptions: MatrixHistogramOption[]; diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts index f388409b443db..ff0816758cb0c 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts @@ -8,10 +8,10 @@ import { EuiTitleSize } from '@elastic/eui'; import { ScaleType, Position, TickFormatter } from '@elastic/charts'; import { ActionCreator } from 'redux'; import { ESQuery } from '../../../../common/typed_json'; -import { SetQuery } from '../../../hosts/pages/navigation/types'; import { InputsModelId } from '../../store/inputs/constants'; import { HistogramType } from '../../../graphql/types'; import { UpdateDateRange } from '../charts/common'; +import { GlobalTimeArgs } from '../../containers/use_global_time'; export type MatrixHistogramMappingTypes = Record< string, @@ -47,15 +47,15 @@ interface MatrixHistogramBasicProps { from: number; to: number; }>; - endDate: number; + endDate: GlobalTimeArgs['to']; headerChildren?: React.ReactNode; hideHistogramIfEmpty?: boolean; id: string; legendPosition?: Position; mapping?: MatrixHistogramMappingTypes; panelHeight?: number; - setQuery: SetQuery; - startDate: number; + setQuery: GlobalTimeArgs['setQuery']; + startDate: GlobalTimeArgs['from']; stackByOptions: MatrixHistogramOption[]; subtitle?: string | GetSubTitle; title?: string | GetTitle; diff --git a/x-pack/plugins/security_solution/public/common/components/page/manage_query.tsx b/x-pack/plugins/security_solution/public/common/components/page/manage_query.tsx index 9e78f704b0f05..02d9a62f2890e 100644 --- a/x-pack/plugins/security_solution/public/common/components/page/manage_query.tsx +++ b/x-pack/plugins/security_solution/public/common/components/page/manage_query.tsx @@ -9,16 +9,14 @@ import { omit } from 'lodash/fp'; import React from 'react'; import { inputsModel } from '../../store'; -import { SetQuery } from '../../../hosts/pages/navigation/types'; +import { GlobalTimeArgs } from '../../containers/use_global_time'; -interface OwnProps { - deleteQuery?: ({ id }: { id: string }) => void; +interface OwnProps extends Pick { headerChildren?: React.ReactNode; id: string; legendPosition?: Position; loading: boolean; refetch: inputsModel.Refetch; - setQuery: SetQuery; inspect?: inputsModel.InspectQuery; } diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx index b453760ebcf09..0b2f1f1e35cc7 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { connect, ConnectedProps } from 'react-redux'; -import { GlobalTime } from '../../containers/global_time'; +import { useGlobalTime } from '../../containers/use_global_time'; import { BrowserFields } from '../../containers/source'; import { useKibana } from '../../lib/kibana'; import { @@ -104,60 +104,55 @@ const StatefulTopNComponent: React.FC = ({ value, }) => { const kibana = useKibana(); + const { from, deleteQuery, setQuery, to } = useGlobalTime(); const options = getOptions( timelineId === TimelineId.active ? activeTimelineEventType : undefined ); return ( - - {({ from, deleteQuery, setQuery, to }) => ( - - )} - + ); }; diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx index 7d19bf21271aa..5e2fd998224c6 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx @@ -9,10 +9,10 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import { ActionCreator } from 'typescript-fsa'; +import { GlobalTimeArgs } from '../../containers/use_global_time'; import { EventsByDataset } from '../../../overview/components/events_by_dataset'; import { SignalsByCategory } from '../../../overview/components/signals_by_category'; import { Filter, IIndexPattern, Query } from '../../../../../../../src/plugins/data/public'; -import { inputsModel } from '../../store'; import { InputsModelId } from '../../store/inputs/constants'; import { EventType } from '../../../timelines/store/timeline/model'; @@ -43,13 +43,11 @@ const TopNContent = styled.div` } `; -export interface Props { +export interface Props extends Pick { combinedQueries?: string; defaultView: EventType; - deleteQuery?: ({ id }: { id: string }) => void; field: string; filters: Filter[]; - from: number; indexPattern: IIndexPattern; indexToAdd?: string[] | null; options: TopNOption[]; @@ -60,13 +58,6 @@ export interface Props { to: number; }>; setAbsoluteRangeDatePickerTarget: InputsModelId; - setQuery: (params: { - id: string; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch; - }) => void; - to: number; timelineId?: string; toggleTopN: () => void; onFilterAdded?: () => void; diff --git a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/types.ts b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/types.ts index a2009809a9916..d716df70246f7 100644 --- a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/types.ts +++ b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/types.ts @@ -7,7 +7,7 @@ import { ESTermQuery } from '../../../../../common/typed_json'; import { NarrowDateRange } from '../../../components/ml/types'; import { UpdateDateRange } from '../../../components/charts/common'; -import { SetQuery } from '../../../../hosts/pages/navigation/types'; +import { GlobalTimeArgs } from '../../use_global_time'; import { FlowTarget } from '../../../../graphql/types'; import { HostsType } from '../../../../hosts/store/model'; import { NetworkType } from '../../../../network/store//model'; @@ -22,11 +22,11 @@ export type AnomaliesQueryTabBodyProps = QueryTabBodyProps & { // eslint-disable-next-line @typescript-eslint/no-explicit-any AnomaliesTableComponent: React.NamedExoticComponent; deleteQuery?: ({ id }: { id: string }) => void; - endDate: number; + endDate: GlobalTimeArgs['to']; flowTarget?: FlowTarget; narrowDateRange: NarrowDateRange; - setQuery: SetQuery; - startDate: number; + setQuery: GlobalTimeArgs['setQuery']; + startDate: GlobalTimeArgs['from']; skip: boolean; updateDateRange?: UpdateDateRange; hideHistogramIfEmpty?: boolean; diff --git a/x-pack/plugins/security_solution/public/common/containers/global_time/index.tsx b/x-pack/plugins/security_solution/public/common/containers/global_time/index.tsx deleted file mode 100644 index 9c9778c7074ee..0000000000000 --- a/x-pack/plugins/security_solution/public/common/containers/global_time/index.tsx +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useCallback, useState, useEffect } from 'react'; -import { connect, ConnectedProps } from 'react-redux'; - -import { inputsModel, inputsSelectors, State } from '../../store'; -import { inputsActions } from '../../store/actions'; - -interface SetQuery { - id: string; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch | inputsModel.RefetchKql; -} - -export interface GlobalTimeArgs { - from: number; - to: number; - setQuery: ({ id, inspect, loading, refetch }: SetQuery) => void; - deleteQuery?: ({ id }: { id: string }) => void; - isInitializing: boolean; -} - -interface OwnProps { - children: (args: GlobalTimeArgs) => React.ReactNode; -} - -type GlobalTimeProps = OwnProps & PropsFromRedux; - -export const GlobalTimeComponent: React.FC = ({ - children, - deleteAllQuery, - deleteOneQuery, - from, - to, - setGlobalQuery, -}) => { - const [isInitializing, setIsInitializing] = useState(true); - - const setQuery = useCallback( - ({ id, inspect, loading, refetch }: SetQuery) => - setGlobalQuery({ inputId: 'global', id, inspect, loading, refetch }), - [setGlobalQuery] - ); - - const deleteQuery = useCallback( - ({ id }: { id: string }) => deleteOneQuery({ inputId: 'global', id }), - [deleteOneQuery] - ); - - useEffect(() => { - if (isInitializing) { - setIsInitializing(false); - } - return () => { - deleteAllQuery({ id: 'global' }); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return ( - <> - {children({ - isInitializing, - from, - to, - setQuery, - deleteQuery, - })} - - ); -}; - -const mapStateToProps = (state: State) => { - const timerange: inputsModel.TimeRange = inputsSelectors.globalTimeRangeSelector(state); - return { - from: timerange.from, - to: timerange.to, - }; -}; - -const mapDispatchToProps = { - deleteAllQuery: inputsActions.deleteAllQuery, - deleteOneQuery: inputsActions.deleteOneQuery, - setGlobalQuery: inputsActions.setQuery, -}; - -export const connector = connect(mapStateToProps, mapDispatchToProps); - -type PropsFromRedux = ConnectedProps; - -export const GlobalTime = connector(React.memo(GlobalTimeComponent)); - -GlobalTime.displayName = 'GlobalTime'; diff --git a/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.test.tsx new file mode 100644 index 0000000000000..9d5f1740b0276 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.test.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { act, renderHook } from '@testing-library/react-hooks'; + +import { useGlobalTime } from '.'; + +jest.mock('react-redux', () => { + const originalModule = jest.requireActual('react-redux'); + + return { + ...originalModule, + useDispatch: jest.fn().mockReturnValue(jest.fn()), + useSelector: jest.fn().mockReturnValue({ from: 0, to: 0 }), + }; +}); + +describe('useGlobalTime', () => { + test('returns memoized value', () => { + const { result, rerender } = renderHook(() => useGlobalTime()); + + const result1 = result.current; + act(() => rerender()); + const result2 = result.current; + + expect(result1).toBe(result2); + expect(result1.from).toBe(0); + expect(result1.to).toBe(0); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.tsx b/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.tsx new file mode 100644 index 0000000000000..b63616ecbcf56 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useCallback, useState, useEffect, useMemo } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; + +import { inputsSelectors } from '../../store'; +import { inputsActions } from '../../store/actions'; +import { SetQuery, DeleteQuery } from './types'; + +export const useGlobalTime = () => { + const dispatch = useDispatch(); + const { from, to } = useSelector(inputsSelectors.globalTimeRangeSelector); + const [isInitializing, setIsInitializing] = useState(true); + + const setQuery = useCallback( + ({ id, inspect, loading, refetch }: SetQuery) => + dispatch(inputsActions.setQuery({ inputId: 'global', id, inspect, loading, refetch })), + [dispatch] + ); + + const deleteQuery = useCallback( + ({ id }: DeleteQuery) => dispatch(inputsActions.deleteOneQuery({ inputId: 'global', id })), + [dispatch] + ); + + useEffect(() => { + if (isInitializing) { + setIsInitializing(false); + } + return () => { + dispatch(inputsActions.deleteAllQuery({ id: 'global' })); + }; + }, [dispatch, isInitializing]); + + const memoizedReturn = useMemo( + () => ({ + isInitializing, + from, + to, + setQuery, + deleteQuery, + }), + [deleteQuery, from, isInitializing, setQuery, to] + ); + + return memoizedReturn; +}; + +export type GlobalTimeArgs = Omit, 'deleteQuery'> & + Partial, 'deleteQuery'>>; diff --git a/x-pack/plugins/security_solution/public/common/containers/use_global_time/types.ts b/x-pack/plugins/security_solution/public/common/containers/use_global_time/types.ts new file mode 100644 index 0000000000000..9903c29202b29 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/containers/use_global_time/types.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { inputsActions } from '../../store/actions'; + +export type SetQuery = Pick< + Parameters[0], + 'id' | 'inspect' | 'loading' | 'refetch' +>; + +export type DeleteQuery = Pick[0], 'id'>; diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.test.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.test.tsx index e520facf285c2..cce48a1e605b2 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.test.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.test.tsx @@ -21,6 +21,12 @@ jest.mock('../../../common/containers/source', () => ({ useWithSource: jest.fn().mockReturnValue({ indicesExist: true, indexPattern: mockIndexPattern }), })); +jest.mock('../../../common/containers/use_global_time', () => ({ + useGlobalTime: jest + .fn() + .mockReturnValue({ from: 0, isInitializing: false, to: 0, setQuery: jest.fn() }), +})); + // Test will fail because we will to need to mock some core services to make the test work // For now let's forget about SiemSearchBar and QueryBar jest.mock('../../../common/components/search_bar', () => ({ diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.tsx index 505d0f37ca039..acde0cbe1d42b 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/details_tabs.tsx @@ -12,6 +12,7 @@ import { scoreIntervalToDateTime } from '../../../common/components/ml/score/sco import { Anomaly } from '../../../common/components/ml/types'; import { HostsTableType } from '../../store/model'; import { AnomaliesQueryTabBody } from '../../../common/containers/anomalies/anomalies_query_tab_body'; +import { useGlobalTime } from '../../../common/containers/use_global_time'; import { AnomaliesHostTable } from '../../../common/components/ml/tables/anomalies_host_table'; import { HostDetailsTabsProps } from './types'; @@ -28,17 +29,13 @@ import { export const HostDetailsTabs = React.memo( ({ pageFilters, - deleteQuery, filterQuery, - from, - isInitializing, detailName, setAbsoluteRangeDatePicker, - setQuery, - to, indexPattern, hostDetailsPagePath, }) => { + const { from, to, isInitializing, deleteQuery, setQuery } = useGlobalTime(); const narrowDateRange = useCallback( (score: Anomaly, interval: string) => { const fromTo = scoreIntervalToDateTime(score, interval); diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx index 1c66a9edc1947..46823f037b61c 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx @@ -27,6 +27,7 @@ import { SiemSearchBar } from '../../../common/components/search_bar'; import { WrapperPage } from '../../../common/components/wrapper_page'; import { HostOverviewByNameQuery } from '../../containers/hosts/overview'; import { KpiHostDetailsQuery } from '../../containers/kpi_host_details'; +import { useGlobalTime } from '../../../common/containers/use_global_time'; import { useWithSource } from '../../../common/containers/source'; import { LastEventIndexKey } from '../../../graphql/types'; import { useKibana } from '../../../common/lib/kibana'; @@ -50,17 +51,13 @@ const KpiHostDetailsManage = manageQuery(KpiHostsComponent); const HostDetailsComponent = React.memo( ({ filters, - from, - isInitializing, query, setAbsoluteRangeDatePicker, setHostDetailsTablesActivePageToZero, - setQuery, - to, detailName, - deleteQuery, hostDetailsPagePath, }) => { + const { to, from, deleteQuery, setQuery, isInitializing } = useGlobalTime(); useEffect(() => { setHostDetailsTablesActivePageToZero(); }, [setHostDetailsTablesActivePageToZero, detailName]); diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/types.ts b/x-pack/plugins/security_solution/public/hosts/pages/details/types.ts index aa6288d473c91..7a440964c31ea 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/types.ts +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/types.ts @@ -32,7 +32,7 @@ interface HostDetailsComponentDispatchProps extends HostBodyComponentDispatchPro setHostDetailsTablesActivePageToZero: ActionCreator; } -export interface HostDetailsProps extends HostsQueryProps { +export interface HostDetailsProps { detailName: string; hostDetailsPagePath: string; } diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts.test.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts.test.tsx index 1ea3a3020a1d5..566f8f23efd39 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts.test.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/hosts.test.tsx @@ -59,15 +59,8 @@ const mockHistory = { listen: jest.fn(), }; -const to = new Date('2018-03-23T18:49:23.132Z').valueOf(); -const from = new Date('2018-03-24T03:33:52.253Z').valueOf(); - describe('Hosts - rendering', () => { const hostProps: HostsComponentProps = { - from, - to, - setQuery: jest.fn(), - isInitializing: false, hostsPagePath: '', }; diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx index f5cc651a30443..90438aec7c27e 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx @@ -22,6 +22,7 @@ import { manageQuery } from '../../common/components/page/manage_query'; import { SiemSearchBar } from '../../common/components/search_bar'; import { WrapperPage } from '../../common/components/wrapper_page'; import { KpiHostsQuery } from '../containers/kpi_hosts'; +import { useGlobalTime } from '../../common/containers/use_global_time'; import { useWithSource } from '../../common/containers/source'; import { LastEventIndexKey } from '../../graphql/types'; import { useKibana } from '../../common/lib/kibana'; @@ -44,17 +45,8 @@ import { HostsTableType } from '../store/model'; const KpiHostsComponentManage = manageQuery(KpiHostsComponent); export const HostsComponent = React.memo( - ({ - deleteQuery, - isInitializing, - filters, - from, - query, - setAbsoluteRangeDatePicker, - setQuery, - to, - hostsPagePath, - }) => { + ({ filters, query, setAbsoluteRangeDatePicker, hostsPagePath }) => { + const { to, from, deleteQuery, setQuery, isInitializing } = useGlobalTime(); const capabilities = useMlCapabilities(); const kibana = useKibana(); const { tabName } = useParams(); diff --git a/x-pack/plugins/security_solution/public/hosts/pages/index.tsx b/x-pack/plugins/security_solution/public/hosts/pages/index.tsx index c2285cf0a97e1..75cd36924dbba 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/index.tsx @@ -11,7 +11,6 @@ import { HostDetails } from './details'; import { HostsTableType } from '../store/model'; import { MlHostConditionalContainer } from '../../common/components/ml/conditional_links/ml_host_conditional_container'; -import { GlobalTime } from '../../common/containers/global_time'; import { Hosts } from './hosts'; import { hostsPagePath, hostDetailsPagePath } from './types'; @@ -36,72 +35,49 @@ type Props = Partial> & { url: string }; export const HostsContainer = React.memo(({ url }) => { const history = useHistory(); + return ( - - {({ to, from, setQuery, deleteQuery, isInitializing }) => ( - - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - { - history.replace(`${detailName}/${HostsTableType.authentications}${search}`); - return null; - }} - /> + + ( + + )} + /> + + + + } + /> + { + history.replace(`${detailName}/${HostsTableType.authentications}${search}`); + return null; + }} + /> - { - history.replace(`${HostsTableType.hosts}${search}`); - return null; - }} - /> - - )} - + { + history.replace(`${HostsTableType.hosts}${search}`); + return null; + }} + /> + ); }); diff --git a/x-pack/plugins/security_solution/public/hosts/pages/navigation/types.ts b/x-pack/plugins/security_solution/public/hosts/pages/navigation/types.ts index 76f56fe1718aa..ddee940d11799 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/navigation/types.ts +++ b/x-pack/plugins/security_solution/public/hosts/pages/navigation/types.ts @@ -7,8 +7,7 @@ import { ESTermQuery } from '../../../../common/typed_json'; import { Filter, IIndexPattern } from '../../../../../../../src/plugins/data/public'; import { NarrowDateRange } from '../../../common/components/ml/types'; -import { InspectQuery, Refetch } from '../../../common/store/inputs/model'; - +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { HostsTableType, HostsType } from '../../store/model'; import { NavTab } from '../../../common/components/navigation/types'; import { UpdateDateRange } from '../../../common/components/charts/common'; @@ -24,31 +23,19 @@ type KeyHostsNavTab = KeyHostsNavTabWithoutMlPermission | KeyHostsNavTabWithMlPe export type HostsNavTab = Record; -export type SetQuery = ({ - id, - inspect, - loading, - refetch, -}: { - id: string; - inspect: InspectQuery | null; - loading: boolean; - refetch: Refetch; -}) => void; - export interface QueryTabBodyProps { type: HostsType; - startDate: number; - endDate: number; + startDate: GlobalTimeArgs['from']; + endDate: GlobalTimeArgs['to']; filterQuery?: string | ESTermQuery; } export type HostsComponentsQueryProps = QueryTabBodyProps & { - deleteQuery?: ({ id }: { id: string }) => void; + deleteQuery?: GlobalTimeArgs['deleteQuery']; indexPattern: IIndexPattern; pageFilters?: Filter[]; skip: boolean; - setQuery: SetQuery; + setQuery: GlobalTimeArgs['setQuery']; updateDateRange?: UpdateDateRange; narrowDateRange?: NarrowDateRange; }; diff --git a/x-pack/plugins/security_solution/public/hosts/pages/types.ts b/x-pack/plugins/security_solution/public/hosts/pages/types.ts index ffd17b0ef46f6..2c9ca4e4d27d9 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/types.ts +++ b/x-pack/plugins/security_solution/public/hosts/pages/types.ts @@ -8,23 +8,26 @@ import { IIndexPattern } from 'src/plugins/data/public'; import { ActionCreator } from 'typescript-fsa'; import { hostsModel } from '../store'; -import { GlobalTimeArgs } from '../../common/containers/global_time'; +import { GlobalTimeArgs } from '../../common/containers/use_global_time'; import { InputsModelId } from '../../common/store/inputs/constants'; export const hostsPagePath = '/'; export const hostDetailsPagePath = `/:detailName`; -export type HostsTabsProps = HostsComponentProps & { - filterQuery: string; - type: hostsModel.HostsType; - indexPattern: IIndexPattern; - setAbsoluteRangeDatePicker: ActionCreator<{ - id: InputsModelId; - from: number; - to: number; - }>; -}; +export type HostsTabsProps = HostsComponentProps & + GlobalTimeArgs & { + filterQuery: string; + type: hostsModel.HostsType; + indexPattern: IIndexPattern; + setAbsoluteRangeDatePicker: ActionCreator<{ + id: InputsModelId; + from: number; + to: number; + }>; + }; export type HostsQueryProps = GlobalTimeArgs; -export type HostsComponentProps = HostsQueryProps & { hostsPagePath: string }; +export interface HostsComponentProps { + hostsPagePath: string; +} diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx index 33eadad9aa774..76e197063fb8a 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { useIndexPatterns } from '../../../common/hooks/use_index_patterns'; import { EmbeddedMapComponent } from './embedded_map'; -import { SetQuery } from './types'; const mockUseIndexPatterns = useIndexPatterns as jest.Mock; jest.mock('../../../common/hooks/use_index_patterns'); @@ -18,7 +17,7 @@ mockUseIndexPatterns.mockImplementation(() => [true, []]); jest.mock('../../../common/lib/kibana'); describe('EmbeddedMapComponent', () => { - let setQuery: SetQuery; + let setQuery: jest.Mock; beforeEach(() => { setQuery = jest.fn(); diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index 6470fc270d0bf..81aa4b1671fca 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -15,13 +15,13 @@ import { getIndexPatternTitleIdMapping } from '../../../common/hooks/api/helpers import { useIndexPatterns } from '../../../common/hooks/use_index_patterns'; import { Loader } from '../../../common/components/loader'; import { displayErrorToast, useStateToaster } from '../../../common/components/toasters'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { Embeddable } from './embeddable'; import { EmbeddableHeader } from './embeddable_header'; import { createEmbeddable, findMatchingIndexPatterns } from './embedded_map_helpers'; import { IndexPatternsMissingPrompt } from './index_patterns_missing_prompt'; import { MapToolTip } from './map_tool_tip/map_tool_tip'; import * as i18n from './translations'; -import { SetQuery } from './types'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { MapEmbeddable } from '../../../../../../plugins/maps/public/embeddable'; import { Query, Filter } from '../../../../../../../src/plugins/data/public'; @@ -73,7 +73,7 @@ export interface EmbeddedMapProps { filters: Filter[]; startDate: number; endDate: number; - setQuery: SetQuery; + setQuery: GlobalTimeArgs['setQuery']; } export const EmbeddedMapComponent = ({ diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map_helpers.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map_helpers.tsx index b0f8e2cc02403..c58e53d07acba 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map_helpers.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map_helpers.tsx @@ -8,7 +8,7 @@ import uuid from 'uuid'; import React from 'react'; import { OutPortal, PortalNode } from 'react-reverse-portal'; import minimatch from 'minimatch'; -import { IndexPatternMapping, SetQuery } from './types'; +import { IndexPatternMapping } from './types'; import { getLayerList } from './map_config'; import { MAP_SAVED_OBJECT_TYPE } from '../../../../../maps/public'; import { @@ -30,6 +30,7 @@ import { ErrorEmbeddable, } from '../../../../../../../src/plugins/embeddable/public'; import { IndexPatternSavedObject } from '../../../common/hooks/types'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; /** * Creates MapEmbeddable with provided initial configuration @@ -49,9 +50,9 @@ export const createEmbeddable = async ( filters: Filter[], indexPatterns: IndexPatternMapping[], query: Query, - startDate: number, - endDate: number, - setQuery: SetQuery, + startDate: GlobalTimeArgs['from'], + endDate: GlobalTimeArgs['to'], + setQuery: GlobalTimeArgs['setQuery'], portalNode: PortalNode, embeddableApi: EmbeddableStart ): Promise => { diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/types.ts b/x-pack/plugins/security_solution/public/network/components/embeddables/types.ts index e3ca3c5b84289..700071f88a4b5 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/types.ts +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/types.ts @@ -6,7 +6,6 @@ // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { RenderTooltipContentParams } from '../../../../../maps/public/classes/tooltips/tooltip_property'; -import { inputsModel } from '../../../common/store/inputs'; export interface IndexPatternMapping { title: string; @@ -29,12 +28,10 @@ export interface LayerMappingCollection { [indexPatternTitle: string]: LayerMapping; } -export type SetQuery = (params: { - id: string; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch; -}) => void; +export interface MapFeature { + id: number; + layerId: string; +} export interface FeatureGeometry { coordinates: [number]; diff --git a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx index 2bae19ce89aec..72e3161de5373 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx @@ -36,7 +36,7 @@ import { GetSubTitle, } from '../../../common/components/matrix_histogram/types'; import { UpdateDateRange } from '../../../common/components/charts/common'; -import { SetQuery } from '../../../hosts/pages/navigation/types'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { networkModel, networkSelectors } from '../../store'; const ID = 'networkDnsQuery'; @@ -67,7 +67,7 @@ interface DnsHistogramOwnProps extends QueryTemplatePaginatedProps { isDnsHistogram?: boolean; query: DocumentNode; scaleType: ScaleType; - setQuery: SetQuery; + setQuery: GlobalTimeArgs['setQuery']; showLegend?: boolean; stackByOptions: MatrixHistogramOption[]; subtitle?: string | GetSubTitle; diff --git a/x-pack/plugins/security_solution/public/network/pages/index.tsx b/x-pack/plugins/security_solution/public/network/pages/index.tsx index c7a8a5f705dfe..9ac05cc98bb45 100644 --- a/x-pack/plugins/security_solution/public/network/pages/index.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/index.tsx @@ -13,7 +13,6 @@ import { FlowTarget } from '../../graphql/types'; import { IPDetails } from './ip_details'; import { Network } from './network'; -import { GlobalTime } from '../../common/containers/global_time'; import { getNetworkRoutePath } from './navigation'; import { NetworkRouteType } from './navigation/types'; import { MlNetworkConditionalContainer } from '../../common/components/ml/conditional_links/ml_network_conditional_container'; @@ -36,71 +35,48 @@ const NetworkContainerComponent: React.FC = () => { ); return ( - - {({ to, from, setQuery, deleteQuery, isInitializing }) => ( - - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - { - history.replace(`ip/${detailName}/${FlowTarget.source}${search}`); - return null; - }} - /> - { - history.replace(`${NetworkRouteType.flows}${search}`); - return null; - }} - /> - - )} - + + ( + + )} + /> + + + + } + /> + { + history.replace(`ip/${detailName}/${FlowTarget.source}${search}`); + return null; + }} + /> + { + history.replace(`${NetworkRouteType.flows}${search}`); + return null; + }} + /> + ); }; diff --git a/x-pack/plugins/security_solution/public/network/pages/ip_details/index.test.tsx b/x-pack/plugins/security_solution/public/network/pages/ip_details/index.test.tsx index 962a6269f8488..92f39228f07a7 100644 --- a/x-pack/plugins/security_solution/public/network/pages/ip_details/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/ip_details/index.test.tsx @@ -33,6 +33,11 @@ type GlobalWithFetch = NodeJS.Global & { fetch: jest.Mock }; jest.mock('../../../common/lib/kibana'); jest.mock('../../../common/containers/source'); +jest.mock('../../../common/containers/use_global_time', () => ({ + useGlobalTime: jest + .fn() + .mockReturnValue({ from: 0, isInitializing: false, to: 0, setQuery: jest.fn() }), +})); // Test will fail because we will to need to mock some core services to make the test work // For now let's forget about SiemSearchBar and QueryBar diff --git a/x-pack/plugins/security_solution/public/network/pages/ip_details/index.tsx b/x-pack/plugins/security_solution/public/network/pages/ip_details/index.tsx index 162b3a7c158d5..6686b40e3c429 100644 --- a/x-pack/plugins/security_solution/public/network/pages/ip_details/index.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/ip_details/index.tsx @@ -9,6 +9,7 @@ import React, { useCallback, useEffect } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; +import { useGlobalTime } from '../../../common/containers/use_global_time'; import { FiltersGlobal } from '../../../common/components/filters_global'; import { HeaderPage } from '../../../common/components/header_page'; import { LastEventTime } from '../../../common/components/last_event_time'; @@ -51,14 +52,11 @@ export const IPDetailsComponent: React.FC { + const { to, from, setQuery, isInitializing } = useGlobalTime(); const type = networkModel.NetworkType.details; const narrowDateRange = useCallback( (score, interval) => { diff --git a/x-pack/plugins/security_solution/public/network/pages/ip_details/types.ts b/x-pack/plugins/security_solution/public/network/pages/ip_details/types.ts index 02d83208884b4..75fb5007f2701 100644 --- a/x-pack/plugins/security_solution/public/network/pages/ip_details/types.ts +++ b/x-pack/plugins/security_solution/public/network/pages/ip_details/types.ts @@ -8,16 +8,15 @@ import { IIndexPattern } from 'src/plugins/data/public'; import { ESTermQuery } from '../../../../common/typed_json'; import { NetworkType } from '../../store/model'; -import { InspectQuery, Refetch } from '../../../common/store/inputs/model'; import { FlowTarget, FlowTargetSourceDest } from '../../../graphql/types'; -import { GlobalTimeArgs } from '../../../common/containers/global_time'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; export const type = NetworkType.details; -export type IPDetailsComponentProps = GlobalTimeArgs & { +export interface IPDetailsComponentProps { detailName: string; flowTarget: FlowTarget; -}; +} export interface OwnProps { type: NetworkType; @@ -26,17 +25,7 @@ export interface OwnProps { filterQuery: string | ESTermQuery; ip: string; skip: boolean; - setQuery: ({ - id, - inspect, - loading, - refetch, - }: { - id: string; - inspect: InspectQuery | null; - loading: boolean; - refetch: Refetch; - }) => void; + setQuery: GlobalTimeArgs['setQuery']; } export type NetworkComponentsQueryProps = OwnProps & { diff --git a/x-pack/plugins/security_solution/public/network/pages/navigation/types.ts b/x-pack/plugins/security_solution/public/network/pages/navigation/types.ts index 433ed7fffd741..6986d10ad3523 100644 --- a/x-pack/plugins/security_solution/public/network/pages/navigation/types.ts +++ b/x-pack/plugins/security_solution/public/network/pages/navigation/types.ts @@ -10,7 +10,7 @@ import { IIndexPattern } from '../../../../../../../src/plugins/data/common'; import { NavTab } from '../../../common/components/navigation/types'; import { FlowTargetSourceDest } from '../../../graphql/types'; import { networkModel } from '../../store'; -import { GlobalTimeArgs } from '../../../common/containers/global_time'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { SetAbsoluteRangeDatePicker } from '../types'; import { NarrowDateRange } from '../../../common/components/ml/types'; diff --git a/x-pack/plugins/security_solution/public/network/pages/network.tsx b/x-pack/plugins/security_solution/public/network/pages/network.tsx index 4275c1641f517..bdaac1ac049e5 100644 --- a/x-pack/plugins/security_solution/public/network/pages/network.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/network.tsx @@ -23,6 +23,7 @@ import { KpiNetworkComponent } from '..//components/kpi_network'; import { SiemSearchBar } from '../../common/components/search_bar'; import { WrapperPage } from '../../common/components/wrapper_page'; import { KpiNetworkQuery } from '../../network/containers/kpi_network'; +import { useGlobalTime } from '../../common/containers/use_global_time'; import { useWithSource } from '../../common/containers/source'; import { LastEventIndexKey } from '../../graphql/types'; import { useKibana } from '../../common/lib/kibana'; @@ -47,13 +48,10 @@ const NetworkComponent = React.memo( query, setAbsoluteRangeDatePicker, networkPagePath, - to, - from, - setQuery, - isInitializing, hasMlUserPermissions, capabilitiesFetched, }) => { + const { to, from, setQuery, isInitializing } = useGlobalTime(); const kibana = useKibana(); const { tabName } = useParams(); diff --git a/x-pack/plugins/security_solution/public/network/pages/types.ts b/x-pack/plugins/security_solution/public/network/pages/types.ts index e4170ee4b908b..54ff5a8d50b8e 100644 --- a/x-pack/plugins/security_solution/public/network/pages/types.ts +++ b/x-pack/plugins/security_solution/public/network/pages/types.ts @@ -7,7 +7,6 @@ import { RouteComponentProps } from 'react-router-dom'; import { ActionCreator } from 'typescript-fsa'; import { InputsModelId } from '../../common/store/inputs/constants'; -import { GlobalTimeArgs } from '../../common/containers/global_time'; export type SetAbsoluteRangeDatePicker = ActionCreator<{ id: InputsModelId; @@ -15,9 +14,8 @@ export type SetAbsoluteRangeDatePicker = ActionCreator<{ to: number; }>; -export type NetworkComponentProps = Partial> & - GlobalTimeArgs & { - networkPagePath: string; - hasMlUserPermissions: boolean; - capabilitiesFetched: boolean; - }; +export type NetworkComponentProps = Partial> & { + networkPagePath: string; + hasMlUserPermissions: boolean; + capabilitiesFetched: boolean; +}; diff --git a/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx b/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx index 03e8279f01db7..6e59d81a1eae9 100644 --- a/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx @@ -19,7 +19,6 @@ import { IIndexPattern, Query, } from '../../../../../../../src/plugins/data/public'; -import { inputsModel } from '../../../common/store'; import { HostsTableType, HostsType } from '../../../hosts/store/model'; import * as i18n from '../../pages/translations'; @@ -29,6 +28,7 @@ import { } from '../../../common/components/alerts_viewer/histogram_configs'; import { MatrixHisrogramConfigs } from '../../../common/components/matrix_histogram/types'; import { getTabsOnHostsUrl } from '../../../common/components/link_to/redirect_to_hosts'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { SecurityPageName } from '../../../app/types'; import { useFormatUrl } from '../../../common/components/link_to'; import { LinkButton } from '../../../common/components/links'; @@ -39,20 +39,11 @@ const NO_FILTERS: Filter[] = []; const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; const DEFAULT_STACK_BY = 'event.module'; -interface Props { - deleteQuery?: ({ id }: { id: string }) => void; +interface Props extends Pick { filters?: Filter[]; - from: number; hideHeaderChildren?: boolean; indexPattern: IIndexPattern; query?: Query; - setQuery: (params: { - id: string; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch; - }) => void; - to: number; } const AlertsByCategoryComponent: React.FC = ({ diff --git a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx index 1773af86a382f..23f5998f44111 100644 --- a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx @@ -20,7 +20,7 @@ import { IIndexPattern, Query, } from '../../../../../../../src/plugins/data/public'; -import { inputsModel } from '../../../common/store'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; const HorizontalSpacer = styled(EuiFlexItem)` width: 24px; @@ -29,18 +29,10 @@ const HorizontalSpacer = styled(EuiFlexItem)` const NO_FILTERS: Filter[] = []; const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; -interface Props { +interface Props extends Pick { filters?: Filter[]; - from: number; indexPattern: IIndexPattern; query?: Query; - setQuery: (params: { - id: string; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch; - }) => void; - to: number; } const EventCountsComponent: React.FC = ({ diff --git a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx index 7d42f744a2613..f18fccee50e22 100644 --- a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx @@ -27,9 +27,9 @@ import { IIndexPattern, Query, } from '../../../../../../../src/plugins/data/public'; -import { inputsModel } from '../../../common/store'; import { HostsTableType, HostsType } from '../../../hosts/store/model'; import { InputsModelId } from '../../../common/store/inputs/constants'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import * as i18n from '../../pages/translations'; import { SecurityPageName } from '../../../app/types'; @@ -42,26 +42,17 @@ const DEFAULT_STACK_BY = 'event.dataset'; const ID = 'eventsByDatasetOverview'; -interface Props { +interface Props extends Pick { combinedQueries?: string; - deleteQuery?: ({ id }: { id: string }) => void; filters?: Filter[]; - from: number; headerChildren?: React.ReactNode; indexPattern: IIndexPattern; indexToAdd?: string[] | null; onlyField?: string; query?: Query; setAbsoluteRangeDatePickerTarget?: InputsModelId; - setQuery: (params: { - id: string; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch; - }) => void; showSpacer?: boolean; timelineId?: string; - to: number; } const getHistogramOption = (fieldName: string): MatrixHistogramOption => ({ diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx index 195bb4fa0807a..583c76d1464a8 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx @@ -18,26 +18,16 @@ import { useUiSetting$, useKibana } from '../../../common/lib/kibana'; import { getHostsUrl, useFormatUrl } from '../../../common/components/link_to'; import { getOverviewHostStats, OverviewHostStats } from '../overview_host_stats'; import { manageQuery } from '../../../common/components/page/manage_query'; -import { inputsModel } from '../../../common/store/inputs'; import { InspectButtonContainer } from '../../../common/components/inspect'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { SecurityPageName } from '../../../app/types'; import { LinkButton } from '../../../common/components/links'; export interface OwnProps { - startDate: number; - endDate: number; + startDate: GlobalTimeArgs['from']; + endDate: GlobalTimeArgs['to']; filterQuery?: ESQuery | string; - setQuery: ({ - id, - inspect, - loading, - refetch, - }: { - id: string; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch; - }) => void; + setQuery: GlobalTimeArgs['setQuery']; } const OverviewHostStatsManage = manageQuery(OverviewHostStats); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx index a3760863bcb62..8282eaeb63c28 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx @@ -19,28 +19,18 @@ import { ID as OverviewNetworkQueryId, OverviewNetworkQuery, } from '../../containers/overview_network'; -import { inputsModel } from '../../../common/store/inputs'; import { getOverviewNetworkStats, OverviewNetworkStats } from '../overview_network_stats'; import { getNetworkUrl, useFormatUrl } from '../../../common/components/link_to'; import { InspectButtonContainer } from '../../../common/components/inspect'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { SecurityPageName } from '../../../app/types'; import { LinkButton } from '../../../common/components/links'; export interface OverviewNetworkProps { - startDate: number; - endDate: number; + startDate: GlobalTimeArgs['from']; + endDate: GlobalTimeArgs['to']; filterQuery?: ESQuery | string; - setQuery: ({ - id, - inspect, - loading, - refetch, - }: { - id: string; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch; - }) => void; + setQuery: GlobalTimeArgs['setQuery']; } const OverviewNetworkStatsManage = manageQuery(OverviewNetworkStats); diff --git a/x-pack/plugins/security_solution/public/overview/components/signals_by_category/index.tsx b/x-pack/plugins/security_solution/public/overview/components/signals_by_category/index.tsx index 41152dabe2ad8..8b62df60b257f 100644 --- a/x-pack/plugins/security_solution/public/overview/components/signals_by_category/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/signals_by_category/index.tsx @@ -11,19 +11,17 @@ import { alertsHistogramOptions } from '../../../alerts/components/alerts_histog import { useSignalIndex } from '../../../alerts/containers/detection_engine/alerts/use_signal_index'; import { SetAbsoluteRangeDatePicker } from '../../../network/pages/types'; import { Filter, IIndexPattern, Query } from '../../../../../../../src/plugins/data/public'; -import { inputsModel } from '../../../common/store'; import { InputsModelId } from '../../../common/store/inputs/constants'; import * as i18n from '../../pages/translations'; import { UpdateDateRange } from '../../../common/components/charts/common'; +import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; const DEFAULT_STACK_BY = 'signal.rule.threat.tactic.name'; const NO_FILTERS: Filter[] = []; -interface Props { - deleteQuery?: ({ id }: { id: string }) => void; +interface Props extends Pick { filters?: Filter[]; - from: number; headerChildren?: React.ReactNode; indexPattern: IIndexPattern; /** Override all defaults, and only display this field */ @@ -31,14 +29,7 @@ interface Props { query?: Query; setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker; setAbsoluteRangeDatePickerTarget?: InputsModelId; - setQuery: (params: { - id: string; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch; - }) => void; timelineId?: string; - to: number; } const SignalsByCategoryComponent: React.FC = ({ diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx index bf5e7f0c211b1..9613a1e7210a3 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx @@ -19,6 +19,11 @@ import { Overview } from './index'; jest.mock('../../common/lib/kibana'); jest.mock('../../common/containers/source'); +jest.mock('../../common/containers/use_global_time', () => ({ + useGlobalTime: jest + .fn() + .mockReturnValue({ from: 0, isInitializing: false, to: 0, setQuery: jest.fn() }), +})); // Test will fail because we will to need to mock some core services to make the test work // For now let's forget about SiemSearchBar and QueryBar diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx index b8b8a67024c9f..2a522d3ea8fde 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx @@ -5,7 +5,7 @@ */ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import React, { useState, useMemo } from 'react'; +import React, { useCallback, useState, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; import { Query, Filter } from 'src/plugins/data/public'; @@ -15,7 +15,7 @@ import { AlertsByCategory } from '../components/alerts_by_category'; import { FiltersGlobal } from '../../common/components/filters_global'; import { SiemSearchBar } from '../../common/components/search_bar'; import { WrapperPage } from '../../common/components/wrapper_page'; -import { GlobalTime } from '../../common/containers/global_time'; +import { useGlobalTime } from '../../common/containers/use_global_time'; import { useWithSource } from '../../common/containers/source'; import { EventsByDataset } from '../components/events_by_dataset'; import { EventCounts } from '../components/event_counts'; @@ -46,6 +46,7 @@ const OverviewComponent: React.FC = ({ return [ENDPOINT_METADATA_INDEX]; }, []); + const { from, deleteQuery, setQuery, to } = useGlobalTime(); const { indicesExist, indexPattern } = useWithSource(); const { indicesExist: metadataIndexExists } = useWithSource( 'default', @@ -59,10 +60,10 @@ const OverviewComponent: React.FC = ({ ); const [dismissMessage, setDismissMessage] = useState(hasDismissEndpointNoticeMessage); - const dismissEndpointNotice = () => { + const dismissEndpointNotice = useCallback(() => { setDismissMessage(true); addMessage('management', 'dismissEndpointNotice'); - }; + }, [addMessage]); return ( <> @@ -85,59 +86,55 @@ const OverviewComponent: React.FC = ({ - - {({ from, deleteQuery, setQuery, to }) => ( - - - - - - - - - - - - - - - - - - - )} - + + + + + + + + + + + + + + + + + +