diff --git a/x-pack/legacy/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap index 12b9afb661da15..c330676e9219eb 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap @@ -1,5 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`BarChartBaseComponent render with customized configs should 2 render BarSeries 1`] = `[Function]`; - exports[`BarChartBaseComponent render with default configs if no customized configs given should 2 render BarSeries 1`] = `[Function]`; diff --git a/x-pack/legacy/plugins/siem/public/components/charts/areachart.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/areachart.test.tsx index 27f0222b96b77f..3c2de28ae423cf 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/areachart.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/areachart.test.tsx @@ -331,7 +331,7 @@ describe('AreaChart', () => { }); it(`should render area chart`, () => { - expect(shallowWrapper.find('WrappedByAutoSizer')).toHaveLength(1); + expect(shallowWrapper.find('AreaChartBase')).toHaveLength(1); expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(0); }); }); @@ -344,7 +344,7 @@ describe('AreaChart', () => { }); it(`should render a chart place holder`, () => { - expect(shallowWrapper.find('WrappedByAutoSizer')).toHaveLength(0); + expect(shallowWrapper.find('AreaChartBase')).toHaveLength(0); expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(1); }); } diff --git a/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx b/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx index b66cc77e30aad2..f3b2b736ed87de 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx @@ -146,8 +146,4 @@ export const AreaChartComponent: React.FC = ({ areaChar ); }; -AreaChartComponent.displayName = 'AreaChartComponent'; - export const AreaChart = React.memo(AreaChartComponent); - -AreaChart.displayName = 'AreaChart'; diff --git a/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx index 0b6635b04d3808..272c41833f3685 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { BarChartBaseComponent, BarChartComponent } from './barchart'; import { ChartSeriesData } from './common'; -import { BarSeries, ScaleType, Axis } from '@elastic/charts'; +import { Chart, BarSeries, Axis, ScaleType } from '@elastic/charts'; jest.mock('../../lib/kibana'); @@ -139,7 +139,7 @@ describe('BarChartBaseComponent', () => { }); it('should render two bar series', () => { - expect(shallowWrapper.find('Chart')).toHaveLength(1); + expect(shallowWrapper.find(Chart)).toHaveLength(1); }); }); @@ -167,7 +167,6 @@ describe('BarChartBaseComponent', () => { }); it(`should ${mockBarChartData.length} render BarSeries`, () => { - expect(shallow).toMatchSnapshot(); expect(shallowWrapper.find(BarSeries)).toHaveLength(mockBarChartData.length); }); @@ -265,7 +264,7 @@ describe('BarChartBaseComponent', () => { }); it('should not render without height and width', () => { - expect(shallowWrapper.find('Chart')).toHaveLength(0); + expect(shallowWrapper.find(Chart)).toHaveLength(0); }); }); }); @@ -278,7 +277,7 @@ describe.each(chartDataSets)('BarChart with valid data [%o]', data => { }); it(`should render chart`, () => { - expect(shallowWrapper.find('WrappedByAutoSizer')).toHaveLength(1); + expect(shallowWrapper.find('BarChartBase')).toHaveLength(1); expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(0); }); }); @@ -291,7 +290,7 @@ describe.each(chartHolderDataSets)('BarChart with invalid data [%o]', data => { }); it(`should render a ChartPlaceHolder`, () => { - expect(shallowWrapper.find('WrappedByAutoSizer')).toHaveLength(0); + expect(shallowWrapper.find('BarChartBase')).toHaveLength(0); expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(1); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/charts/common.tsx b/x-pack/legacy/plugins/siem/public/components/charts/common.tsx index 03b412f5756466..7377bcbe7050fa 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/common.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/common.tsx @@ -16,7 +16,9 @@ import { TickFormatter, Position, } from '@elastic/charts'; +import React, { useMemo } from 'react'; import styled from 'styled-components'; + import { useUiSetting } from '../../lib/kibana'; import { DEFAULT_DARK_MODE } from '../../../common/constants'; @@ -54,7 +56,7 @@ export interface ChartSeriesData { color?: string | undefined; } -export const WrappedByAutoSizer = styled.div<{ height?: string }>` +const WrappedByAutoSizerComponent = styled.div<{ height?: string }>` ${style => ` height: ${style.height != null ? style.height : defaultChartHeight}; @@ -66,7 +68,9 @@ export const WrappedByAutoSizer = styled.div<{ height?: string }>` } `; -WrappedByAutoSizer.displayName = 'WrappedByAutoSizer'; +WrappedByAutoSizerComponent.displayName = 'WrappedByAutoSizer'; + +export const WrappedByAutoSizer = React.memo(WrappedByAutoSizerComponent); export enum SeriesType { BAR = 'bar', @@ -96,8 +100,9 @@ const theme: PartialTheme = { export const useTheme = () => { const isDarkMode = useUiSetting(DEFAULT_DARK_MODE); const defaultTheme = isDarkMode ? DARK_THEME : LIGHT_THEME; + const themeValue = useMemo(() => mergeWithDefaultTheme(theme, defaultTheme), []); - return mergeWithDefaultTheme(theme, defaultTheme); + return themeValue; }; export const chartDefaultSettings = { diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx index cf958bfd75d3b2..7d84403b87f8d0 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React, { createContext, useContext, useEffect } from 'react'; import { Draggable, @@ -14,6 +13,7 @@ import { } from 'react-beautiful-dnd'; import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { EuiPortal } from '@elastic/eui'; import { dragAndDropActions } from '../../store/drag_and_drop'; @@ -122,7 +122,7 @@ const DraggableWrapperComponent = React.memo( }, (prevProps, nextProps) => { return ( - isEqual(prevProps.dataProvider, nextProps.dataProvider) && + deepEqual(prevProps.dataProvider, nextProps.dataProvider) && prevProps.render !== nextProps.render && prevProps.truncate === nextProps.truncate ); diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx index 2a4d08ea214bc4..a913186d9ad3b9 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx @@ -5,10 +5,10 @@ */ import { EuiPanel } from '@elastic/eui'; -import deepEqual from 'fast-deep-equal'; -import { getOr, isEmpty, isEqual, union } from 'lodash/fp'; +import { getOr, isEmpty, union } from 'lodash/fp'; import React, { useMemo } from 'react'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import useResizeObserver from 'use-resize-observer/polyfilled'; import { BrowserFields } from '../../containers/source'; @@ -228,7 +228,7 @@ const EventsViewerComponent: React.FC = ({ export const EventsViewer = React.memo( EventsViewerComponent, (prevProps, nextProps) => - isEqual(prevProps.browserFields, nextProps.browserFields) && + deepEqual(prevProps.browserFields, nextProps.browserFields) && prevProps.columns === nextProps.columns && prevProps.dataProviders === nextProps.dataProviders && prevProps.deletedEventIds === nextProps.deletedEventIds && @@ -241,9 +241,9 @@ export const EventsViewer = React.memo( prevProps.itemsPerPage === nextProps.itemsPerPage && prevProps.itemsPerPageOptions === nextProps.itemsPerPageOptions && prevProps.kqlMode === nextProps.kqlMode && - isEqual(prevProps.query, nextProps.query) && + deepEqual(prevProps.query, nextProps.query) && prevProps.start === nextProps.start && prevProps.sort === nextProps.sort && - isEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) && + deepEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) && prevProps.utilityBar === nextProps.utilityBar ); diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx index 762ae8497dadba..9b31be40dd9557 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React, { useCallback, useMemo, useEffect } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store'; import { inputsActions, timelineActions } from '../../store/actions'; @@ -197,23 +197,23 @@ export const StatefulEventsViewer = connector( StatefulEventsViewerComponent, (prevProps, nextProps) => prevProps.id === nextProps.id && - isEqual(prevProps.columns, nextProps.columns) && - isEqual(prevProps.dataProviders, nextProps.dataProviders) && + deepEqual(prevProps.columns, nextProps.columns) && + deepEqual(prevProps.dataProviders, nextProps.dataProviders) && prevProps.deletedEventIds === nextProps.deletedEventIds && prevProps.end === nextProps.end && - isEqual(prevProps.filters, nextProps.filters) && + deepEqual(prevProps.filters, nextProps.filters) && prevProps.isLive === nextProps.isLive && prevProps.itemsPerPage === nextProps.itemsPerPage && - isEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && + deepEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && prevProps.kqlMode === nextProps.kqlMode && - isEqual(prevProps.query, nextProps.query) && - isEqual(prevProps.sort, nextProps.sort) && + deepEqual(prevProps.query, nextProps.query) && + deepEqual(prevProps.sort, nextProps.sort) && prevProps.start === nextProps.start && - isEqual(prevProps.pageFilters, nextProps.pageFilters) && + deepEqual(prevProps.pageFilters, nextProps.pageFilters) && prevProps.showCheckboxes === nextProps.showCheckboxes && prevProps.showRowRenderers === nextProps.showRowRenderers && prevProps.start === nextProps.start && - isEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) && + deepEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) && prevProps.utilityBar === nextProps.utilityBar ) ); diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx index eb41773bb21c86..22fc9f27ce26c7 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx @@ -6,7 +6,7 @@ import { EuiBadge } from '@elastic/eui'; import { defaultTo, getOr } from 'lodash/fp'; -import React from 'react'; +import React, { useCallback } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; @@ -58,28 +58,39 @@ export const FlyoutComponent = React.memo( timelineId, usersViewing, width, - }) => ( - <> - - showTimeline({ id: timelineId, show: false })} + }) => { + const handleClose = useCallback(() => showTimeline({ id: timelineId, show: false }), [ + showTimeline, + timelineId, + ]); + const handleOpen = useCallback(() => showTimeline({ id: timelineId, show: true }), [ + showTimeline, + timelineId, + ]); + + return ( + <> + + + {children} + + + - {children} - - - showTimeline({ id: timelineId, show: true })} - /> - - ) + onOpen={handleOpen} + /> + + ); + } ); FlyoutComponent.displayName = 'FlyoutComponent'; diff --git a/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx b/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx index 405a8f060948e3..d6f8143745356f 100644 --- a/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx @@ -5,7 +5,7 @@ */ import { EuiButtonEmpty, EuiButtonIcon } from '@elastic/eui'; -import { getOr } from 'lodash/fp'; +import { getOr, omit } from 'lodash/fp'; import React, { useCallback } from 'react'; import { connect } from 'react-redux'; import { ActionCreator } from 'typescript-fsa'; @@ -162,7 +162,11 @@ const makeMapStateToProps = () => { const getGlobalQuery = inputsSelectors.globalQueryByIdSelector(); const getTimelineQuery = inputsSelectors.timelineQueryByIdSelector(); const mapStateToProps = (state: State, { inputId = 'global', queryId }: OwnProps) => { - return inputId === 'global' ? getGlobalQuery(state, queryId) : getTimelineQuery(state, queryId); + const props = + inputId === 'global' ? getGlobalQuery(state, queryId) : getTimelineQuery(state, queryId); + // refetch caused unnecessary component rerender and it was even not used + const propsWithoutRefetch = omit('refetch', props); + return propsWithoutRefetch; }; return mapStateToProps; }; diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx b/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx index e40cc887ab5ff4..8a754cb47475f2 100644 --- a/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx @@ -4,11 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import isEqual from 'lodash/fp/isEqual'; -import deepEqual from 'fast-deep-equal'; import React, { useEffect } from 'react'; import { connect } from 'react-redux'; import { compose } from 'redux'; +import deepEqual from 'fast-deep-equal'; import { useKibana } from '../../lib/kibana'; import { RouteSpyState } from '../../utils/route/types'; @@ -81,8 +80,8 @@ export const SiemNavigationRedux = compose< (prevProps, nextProps) => prevProps.pathName === nextProps.pathName && prevProps.search === nextProps.search && - isEqual(prevProps.navTabs, nextProps.navTabs) && - isEqual(prevProps.urlState, nextProps.urlState) && + deepEqual(prevProps.navTabs, nextProps.navTabs) && + deepEqual(prevProps.urlState, nextProps.urlState) && deepEqual(prevProps.state, nextProps.state) ) ); diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx index 853ba7ae234142..678faff7654db8 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx @@ -7,7 +7,7 @@ /* eslint-disable react/display-name */ import { has } from 'lodash/fp'; -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { hostsActions } from '../../../../store/hosts'; @@ -100,10 +100,12 @@ const AuthenticationTableComponent = React.memo( [type, updateTableActivePage] ); + const columns = useMemo(() => getAuthenticationColumnsCurated(type), [type]); + return ( ( [type, updateTableActivePage] ); + const columns = useMemo(() => getUncommonColumnsCurated(type), [type]); + return ( ]; -export const getNetworkDnsColumns = (type: networkModel.NetworkType): NetworkDnsColumns => [ +export const getNetworkDnsColumns = (): NetworkDnsColumns => [ { field: `node.${NetworkDnsFields.dnsName}`, name: i18n.REGISTERED_DOMAIN, diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx index f3fe98936a55de..c1dd96c5c96f91 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { networkActions } from '../../../../store/actions'; import { @@ -93,7 +93,7 @@ export const NetworkDnsTableComponent = React.memo( field: criteria.sort.field.split('.')[1] as NetworkDnsFields, direction: criteria.sort.direction as Direction, }; - if (!isEqual(newDnsSortField, sort)) { + if (!deepEqual(newDnsSortField, sort)) { updateNetworkTable({ networkType: type, tableType, @@ -115,10 +115,12 @@ export const NetworkDnsTableComponent = React.memo( [type, updateNetworkTable, isPtrIncluded] ); + const columns = useMemo(() => getNetworkDnsColumns(), []); + return ( = ({ const sorting = { field: `node.${NetworkHttpFields.requestCount}`, direction: sort.direction }; + const columns = useMemo(() => getNetworkHttpColumns(tableType), [tableType]); + return ( = ({ field: field as NetworkTopTablesFields, direction: newSortDirection as Direction, }; - if (!isEqual(newTopNFlowSort, sort)) { + if (!deepEqual(newTopNFlowSort, sort)) { updateNetworkTable({ networkType: type, tableType, diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx index 77abae68b76bfe..d1512699cc709c 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { networkActions } from '../../../../store/network'; import { TlsEdges, TlsSortField, TlsFields, Direction } from '../../../../graphql/types'; @@ -91,7 +91,7 @@ const TlsTableComponent = React.memo( field: getSortFromString(splitField[splitField.length - 1]), direction: criteria.sort.direction as Direction, }; - if (!isEqual(newTlsSort, sort)) { + if (!deepEqual(newTlsSort, sort)) { updateNetworkTable({ networkType: type, tableType, @@ -103,10 +103,12 @@ const TlsTableComponent = React.memo( [sort, type, tableType, updateNetworkTable] ); + const columns = useMemo(() => getTlsColumns(tlsTableId), [tlsTableId]); + return ( ( field: getSortFromString(splitField[splitField.length - 1]), direction: criteria.sort.direction as Direction, }; - if (!isEqual(newUsersSort, sort)) { + if (!deepEqual(newUsersSort, sort)) { updateNetworkTable({ networkType: type, tableType, @@ -109,10 +109,15 @@ const UsersTableComponent = React.memo( [sort, type, updateNetworkTable] ); + const columns = useMemo(() => getUsersColumns(flowTarget, usersTableId), [ + flowTarget, + usersTableId, + ]); + return ( = ({ data, loading ); }; -OverviewHostStatsComponent.displayName = 'OverviewHostStatsComponent'; - export const OverviewHostStats = React.memo(OverviewHostStatsComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network_stats/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network_stats/index.tsx index 260b1d6895140d..ca947c29bc3822 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network_stats/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network_stats/index.tsx @@ -130,7 +130,7 @@ const AccordionContent = styled.div` margin-top: 8px; `; -export const OverviewNetworkStats = React.memo(({ data, loading }) => { +const OverviewNetworkStatsComponent: React.FC = ({ data, loading }) => { const allNetworkStats = getOverviewNetworkStats(data); const allNetworkStatsCount = allNetworkStats.reduce((total, stat) => total + stat.count, 0); @@ -190,6 +190,6 @@ export const OverviewNetworkStats = React.memo(({ data, lo })} ); -}); +}; -OverviewNetworkStats.displayName = 'OverviewNetworkStats'; +export const OverviewNetworkStats = React.memo(OverviewNetworkStatsComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx index 03a8143c89517f..557d389aefee92 100644 --- a/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React, { memo, useState, useEffect, useMemo, useCallback } from 'react'; +import deepEqual from 'fast-deep-equal'; import { Filter, @@ -64,7 +64,7 @@ export const QueryBar = memo( const onQuerySubmit = useCallback( (payload: { dateRange: TimeRange; query?: Query }) => { - if (payload.query != null && !isEqual(payload.query, filterQuery)) { + if (payload.query != null && !deepEqual(payload.query, filterQuery)) { onSubmitQuery(payload.query); } }, @@ -73,7 +73,7 @@ export const QueryBar = memo( const onQueryChange = useCallback( (payload: { dateRange: TimeRange; query?: Query }) => { - if (payload.query != null && !isEqual(payload.query, draftQuery)) { + if (payload.query != null && !deepEqual(payload.query, draftQuery)) { setDraftQuery(payload.query); onChangedQuery(payload.query); } diff --git a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx index cb5729ad8e26e5..2513004af84dd6 100644 --- a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx @@ -4,12 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getOr, isEqual, set } from 'lodash/fp'; +import { getOr, set } from 'lodash/fp'; import React, { memo, useEffect, useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { Subscription } from 'rxjs'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { FilterManager, IIndexPattern, TimeRange, Query, Filter } from 'src/plugins/data/public'; import { SavedQuery } from 'src/legacy/core_plugins/data/public'; @@ -60,7 +61,6 @@ const SearchBarComponent = memo( setSavedQuery, setSearchBarFilter, start, - timelineId, toStr, updateSearch, dataTestSubj, @@ -108,7 +108,7 @@ const SearchBarComponent = memo( updateSearchBar.start = payload.dateRange.from; } - if (payload.query != null && !isEqual(payload.query, filterQuery)) { + if (payload.query != null && !deepEqual(payload.query, filterQuery)) { isStateUpdated = true; updateSearchBar = set('query', payload.query, updateSearchBar); } diff --git a/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx b/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx index 33159387214e43..b8192cce11e5aa 100644 --- a/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx +++ b/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx @@ -5,8 +5,9 @@ */ import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { isEmpty, isEqual, uniqWith } from 'lodash/fp'; +import { isEmpty, uniqWith } from 'lodash/fp'; import React from 'react'; +import deepEqual from 'fast-deep-equal'; import { DESTINATION_IP_FIELD_NAME, SOURCE_IP_FIELD_NAME } from '../ip'; import { DESTINATION_PORT_FIELD_NAME, SOURCE_PORT_FIELD_NAME, Port } from '../port'; @@ -115,7 +116,7 @@ const IpAdressesWithPorts = React.memo<{ return ( - {uniqWith(isEqual, ipPortPairs).map( + {uniqWith(deepEqual, ipPortPairs).map( ipPortPair => ipPortPair.ip != null && ( diff --git a/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap index 69596ba8f33250..ef077ece19f923 100644 --- a/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap @@ -94,7 +94,6 @@ exports[`Stat Items Component disable charts it renders the default widget 1`] = isInspected={false} loading={false} queryId="statItems" - refetch={null} selectedInspectIndex={0} setIsInspected={[Function]} title="KPI HOSTS" @@ -328,7 +327,6 @@ exports[`Stat Items Component disable charts it renders the default widget 2`] = isInspected={false} loading={false} queryId="statItems" - refetch={null} selectedInspectIndex={0} setIsInspected={[Function]} title="KPI HOSTS" @@ -632,7 +630,6 @@ exports[`Stat Items Component rendering kpis with charts it renders the default isInspected={false} loading={false} queryId="statItems" - refetch={null} selectedInspectIndex={0} setIsInspected={[Function]} title="KPI UNIQUE_PRIVATE_IPS" diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap index 3fcd258b79147c..372930ee3167df 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap @@ -8,7 +8,7 @@ exports[`Timeline rendering renders correctly against snapshot 1`] = ` justifyContent="flexStart" > - = ({ browserFields, id, indexPattern, @@ -60,7 +60,7 @@ export const TimelineHeaderComponent = ({ onToggleDataProviderExcluded, show, showCallOutUnauthorizedMsg, -}: Props) => ( +}) => ( {showCallOutUnauthorizedMsg && ( ); -TimelineHeaderComponent.displayName = 'TimelineHeaderComponent'; - export const TimelineHeader = React.memo(TimelineHeaderComponent); - -TimelineHeader.displayName = 'TimelineHeader'; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx index d782d0366f041c..0ce6bc16f1325a 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React, { useEffect, useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { WithSource } from '../../containers/source'; import { useSignalIndex } from '../../containers/detection_engine/signals/use_signal_index'; @@ -215,11 +215,11 @@ const StatefulTimelineComponent = React.memo( prevProps.show === nextProps.show && prevProps.showCallOutUnauthorizedMsg === nextProps.showCallOutUnauthorizedMsg && prevProps.start === nextProps.start && - isEqual(prevProps.columns, nextProps.columns) && - isEqual(prevProps.dataProviders, nextProps.dataProviders) && - isEqual(prevProps.filters, nextProps.filters) && - isEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && - isEqual(prevProps.sort, nextProps.sort) + deepEqual(prevProps.columns, nextProps.columns) && + deepEqual(prevProps.dataProviders, nextProps.dataProviders) && + deepEqual(prevProps.filters, nextProps.filters) && + deepEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && + deepEqual(prevProps.sort, nextProps.sort) ); } ); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx index 96b8df6d8ada70..7f662cdb2f1b44 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx @@ -4,9 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual, isEmpty } from 'lodash/fp'; +import { isEmpty } from 'lodash/fp'; import React, { memo, useCallback, useState, useEffect } from 'react'; import { Subscription } from 'rxjs'; +import deepEqual from 'fast-deep-equal'; import { IIndexPattern, @@ -127,7 +128,7 @@ export const QueryBarTimeline = memo( const filterWithoutDropArea = filterManager .getFilters() .filter((f: Filter) => f.meta.controlledBy !== timelineFilterDropArea); - if (!isEqual(filters, filterWithoutDropArea)) { + if (!deepEqual(filters, filterWithoutDropArea)) { filterManager.setFilters(filters); } }, [filters]); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx index d1904fd5d9aac2..87061bdbb5d02a 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getOr, isEqual } from 'lodash/fp'; +import { getOr } from 'lodash/fp'; import React, { useCallback } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; +import deepEqual from 'fast-deep-equal'; import { Filter, IIndexPattern } from '../../../../../../../../src/plugins/data/public'; import { BrowserFields } from '../../../containers/source'; @@ -152,15 +153,15 @@ const StatefulSearchOrFilterComponent = React.memo( prevProps.isRefreshPaused === nextProps.isRefreshPaused && prevProps.refreshInterval === nextProps.refreshInterval && prevProps.timelineId === nextProps.timelineId && - isEqual(prevProps.browserFields, nextProps.browserFields) && - isEqual(prevProps.dataProviders, nextProps.dataProviders) && - isEqual(prevProps.filters, nextProps.filters) && - isEqual(prevProps.filterQuery, nextProps.filterQuery) && - isEqual(prevProps.filterQueryDraft, nextProps.filterQueryDraft) && - isEqual(prevProps.indexPattern, nextProps.indexPattern) && - isEqual(prevProps.kqlMode, nextProps.kqlMode) && - isEqual(prevProps.savedQueryId, nextProps.savedQueryId) && - isEqual(prevProps.timelineId, nextProps.timelineId) + deepEqual(prevProps.browserFields, nextProps.browserFields) && + deepEqual(prevProps.dataProviders, nextProps.dataProviders) && + deepEqual(prevProps.filters, nextProps.filters) && + deepEqual(prevProps.filterQuery, nextProps.filterQuery) && + deepEqual(prevProps.filterQueryDraft, nextProps.filterQueryDraft) && + deepEqual(prevProps.indexPattern, nextProps.indexPattern) && + deepEqual(prevProps.kqlMode, nextProps.kqlMode) && + deepEqual(prevProps.savedQueryId, nextProps.savedQueryId) && + deepEqual(prevProps.timelineId, nextProps.timelineId) ); } ); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx index c9ff0296a40e27..58bbbef328ddf9 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx @@ -229,8 +229,4 @@ export const TimelineComponent: React.FC = ({ ); }; -TimelineComponent.displayName = 'TimelineComponent'; - export const Timeline = React.memo(TimelineComponent); - -Timeline.displayName = 'Timeline'; diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx index e656ec3496d8dc..294e41a1faa7b4 100644 --- a/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React from 'react'; import { compose, Dispatch } from 'redux'; import { connect } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { timelineActions } from '../../store/actions'; import { RouteSpyState } from '../../utils/route/types'; @@ -39,7 +39,7 @@ export const UrlStateRedux = compose - prevProps.pathName === nextProps.pathName && isEqual(prevProps.urlState, nextProps.urlState) + prevProps.pathName === nextProps.pathName && deepEqual(prevProps.urlState, nextProps.urlState) ) ); diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx index deaf9bbf5011d8..a7704e0e86970a 100644 --- a/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx +++ b/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual, difference, isEmpty } from 'lodash/fp'; +import { difference, isEmpty } from 'lodash/fp'; import { useEffect, useRef, useState } from 'react'; +import deepEqual from 'fast-deep-equal'; import { useKibana } from '../../lib/kibana'; import { useApolloClient } from '../../utils/apollo_context'; @@ -77,7 +78,7 @@ export const useUrlStateHooks = ({ const updatedUrlStateString = getParamFromQueryString(getQueryStringFromLocation(mySearch), urlKey) ?? newUrlStateString; - if (isInitializing || !isEqual(updatedUrlStateString, newUrlStateString)) { + if (isInitializing || !deepEqual(updatedUrlStateString, newUrlStateString)) { urlStateToUpdate = [ ...urlStateToUpdate, { @@ -157,7 +158,7 @@ export const useUrlStateHooks = ({ if (isInitializing && pageName != null && pageName !== '') { handleInitialize(type); setIsInitializing(false); - } else if (!isEqual(urlState, prevProps.urlState) && !isInitializing) { + } else if (!deepEqual(urlState, prevProps.urlState) && !isInitializing) { let mySearch = search; URL_STATE_KEYS[type].forEach((urlKey: KeyUrlState) => { if ( diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx index b7ad41b8ba1bb2..06c4d1054bca4f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEmpty, isEqual, get } from 'lodash/fp'; +import { isEmpty, get } from 'lodash/fp'; import { useEffect, useState, Dispatch, SetStateAction } from 'react'; +import deepEqual from 'fast-deep-equal'; import { IIndexPattern } from '../../../../../../../../src/plugins/data/public'; import { @@ -41,7 +42,7 @@ export const useFetchIndexPatterns = (defaultIndices: string[] = []): Return => const [, dispatchToaster] = useStateToaster(); useEffect(() => { - if (!isEqual(defaultIndices, indices)) { + if (!deepEqual(defaultIndices, indices)) { setIndices(defaultIndices); } }, [defaultIndices, indices]); diff --git a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx index caf597d02c835f..4632e9aee3fdd1 100644 --- a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useEffect } from 'react'; +import React, { useCallback, useState, useEffect } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { inputsModel, inputsSelectors, State } from '../../store'; @@ -41,6 +41,17 @@ export const GlobalTimeComponent: React.FC = ({ }) => { 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); @@ -56,9 +67,8 @@ export const GlobalTimeComponent: React.FC = ({ isInitializing, from, to, - setQuery: ({ id, inspect, loading, refetch }: SetQuery) => - setGlobalQuery({ inputId: 'global', id, inspect, loading, refetch }), - deleteQuery: ({ id }: { id: string }) => deleteOneQuery({ inputId: 'global', id }), + setQuery, + deleteQuery, })} ); diff --git a/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx b/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx index 4d6ab757fdea7a..db618f216d83e7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx @@ -5,10 +5,10 @@ */ import { ApolloQueryResult, NetworkStatus } from 'apollo-client'; -import { isEqual } from 'lodash/fp'; import memoizeOne from 'memoize-one'; import React from 'react'; import { FetchMoreOptions, FetchMoreQueryOptions, OperationVariables } from 'react-apollo'; +import deepEqual from 'fast-deep-equal'; import { ESQuery } from '../../common/typed_json'; import { inputsModel } from '../store/model'; @@ -85,7 +85,7 @@ export class QueryTemplatePaginated< public isItAValidLoading(loading: boolean, variables: TVariables, networkStatus: NetworkStatus) { if ( !this.myLoading && - (!isEqual(variables, this.queryVariables) || networkStatus === NetworkStatus.refetch) && + (!deepEqual(variables, this.queryVariables) || networkStatus === NetworkStatus.refetch) && loading ) { this.myLoading = true; diff --git a/x-pack/legacy/plugins/siem/public/containers/source/index.tsx b/x-pack/legacy/plugins/siem/public/containers/source/index.tsx index 0336e4a9a977b9..e454421ca955d6 100644 --- a/x-pack/legacy/plugins/siem/public/containers/source/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/source/index.tsx @@ -10,6 +10,7 @@ import { Query } from 'react-apollo'; import React, { useEffect, useMemo, useState } from 'react'; import memoizeOne from 'memoize-one'; import { IIndexPattern } from 'src/plugins/data/public'; + import { useUiSetting$ } from '../../lib/kibana'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx index 92f6740e4d767a..2d9b1ee844b4ba 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx @@ -12,9 +12,11 @@ import { HistogramBarSeries, Position, Settings, + ChartSizeArray, } from '@elastic/charts'; -import React from 'react'; +import React, { useMemo } from 'react'; import { EuiProgress } from '@elastic/eui'; + import { useTheme } from '../../../../components/charts/common'; import { histogramDateTimeFormatter } from '../../../../components/utils'; import { HistogramData } from './types'; @@ -43,6 +45,14 @@ export const SignalsHistogram = React.memo( }) => { const theme = useTheme(); + const chartSize: ChartSizeArray = useMemo(() => ['100%', chartHeight], [chartHeight]); + const xAxisId = useMemo(() => getAxisId('signalsHistogramAxisX'), []); + const yAxisId = useMemo(() => getAxisId('signalsHistogramAxisY'), []); + const id = useMemo(() => getSpecId('signalsHistogram'), []); + const yAccessors = useMemo(() => ['y'], []); + const splitSeriesAccessors = useMemo(() => ['g'], []); + const tickFormat = useMemo(() => histogramDateTimeFormatter([from, to]), [from, to]); + return ( <> {loading && ( @@ -54,7 +64,7 @@ export const SignalsHistogram = React.memo( /> )} - + ( theme={theme} /> - + - + @@ -84,4 +90,5 @@ export const SignalsHistogram = React.memo( ); } ); + SignalsHistogram.displayName = 'SignalsHistogram'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx index 88795f9195e68d..fbe854c1ee346f 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx @@ -5,10 +5,10 @@ */ import { EuiFormRow, EuiMutationObserver } from '@elastic/eui'; -import { isEqual } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Subscription } from 'rxjs'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { Filter, @@ -99,7 +99,7 @@ export const QueryBarDefineRule = ({ const newFilters = filterManager.getFilters(); const { filters } = field.value as FieldValueQueryBar; - if (!isEqual(filters, newFilters)) { + if (!deepEqual(filters, newFilters)) { field.setValue({ ...(field.value as FieldValueQueryBar), filters: newFilters }); } } @@ -117,10 +117,10 @@ export const QueryBarDefineRule = ({ let isSubscribed = true; async function updateFilterQueryFromValue() { const { filters, query, saved_id: savedId } = field.value as FieldValueQueryBar; - if (!isEqual(query, queryDraft)) { + if (!deepEqual(query, queryDraft)) { setQueryDraft(query); } - if (!isEqual(filters, filterManager.getFilters())) { + if (!deepEqual(filters, filterManager.getFilters())) { filterManager.setFilters(filters); } if ( @@ -148,7 +148,7 @@ export const QueryBarDefineRule = ({ const onSubmitQuery = useCallback( (newQuery: Query, timefilter?: SavedQueryTimeFilter) => { const { query } = field.value as FieldValueQueryBar; - if (!isEqual(query, newQuery)) { + if (!deepEqual(query, newQuery)) { field.setValue({ ...(field.value as FieldValueQueryBar), query: newQuery }); } }, @@ -158,7 +158,7 @@ export const QueryBarDefineRule = ({ const onChangedQuery = useCallback( (newQuery: Query) => { const { query } = field.value as FieldValueQueryBar; - if (!isEqual(query, newQuery)) { + if (!deepEqual(query, newQuery)) { field.setValue({ ...(field.value as FieldValueQueryBar), query: newQuery }); } }, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/index.tsx index 2c9173cbeb694a..ac457d7345c29e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/index.tsx @@ -12,8 +12,8 @@ import { EuiLoadingSpinner, EuiText, } from '@elastic/eui'; -import { isEqual } from 'lodash/fp'; import React, { memo, useCallback, useEffect, useState } from 'react'; +import deepEqual from 'fast-deep-equal'; import { useRuleStatus, RuleInfoStatus } from '../../../../../containers/detection_engine/rules'; import { FormattedDate } from '../../../../../components/formatted_date'; @@ -43,7 +43,7 @@ const RuleStatusComponent: React.FC = ({ ruleId, ruleEnabled }) }, [fetchRuleStatus, myRuleEnabled, ruleId, ruleEnabled, setMyRuleEnabled]); useEffect(() => { - if (!isEqual(currentStatus, ruleStatus?.current_status)) { + if (!deepEqual(currentStatus, ruleStatus?.current_status)) { setCurrentStatus(ruleStatus?.current_status ?? null); } }, [currentStatus, ruleStatus, setCurrentStatus]); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx index 45da7d081333e9..431d793d6e68a5 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx @@ -13,9 +13,9 @@ import { EuiSpacer, EuiButtonEmpty, } from '@elastic/eui'; -import { isEqual } from 'lodash/fp'; import React, { FC, memo, useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { setFieldValue } from '../../helpers'; import { RuleStepProps, RuleStep, AboutStepRule } from '../../types'; @@ -103,7 +103,7 @@ const StepAboutRuleComponent: FC = ({ useEffect(() => { const { isNew, ...initDefaultValue } = myStepData; - if (defaultValues != null && !isEqual(initDefaultValue, defaultValues)) { + if (defaultValues != null && !deepEqual(initDefaultValue, defaultValues)) { const myDefaultValues = { ...defaultValues, isNew: false, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx index 920a9f2dfe56ca..773eb44efb26c5 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx @@ -11,9 +11,10 @@ import { EuiFlexItem, EuiButton, } from '@elastic/eui'; -import { isEmpty, isEqual } from 'lodash/fp'; +import { isEmpty } from 'lodash/fp'; import React, { FC, memo, useCallback, useState, useEffect } from 'react'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { IIndexPattern } from '../../../../../../../../../../src/plugins/data/public'; import { useFetchIndexPatterns } from '../../../../../containers/detection_engine/rules'; @@ -126,9 +127,9 @@ const StepDefineRuleComponent: FC = ({ useEffect(() => { if (indicesConfig != null && defaultValues != null) { const myDefaultValues = getStepDefaultValue(indicesConfig, defaultValues); - if (!isEqual(myDefaultValues, myStepData)) { + if (!deepEqual(myDefaultValues, myStepData)) { setMyStepData(myDefaultValues); - setLocalUseIndicesConfig(isEqual(myDefaultValues.index, indicesConfig)); + setLocalUseIndicesConfig(deepEqual(myDefaultValues.index, indicesConfig)); setFieldValue(form, schema, myDefaultValues); } } @@ -212,13 +213,13 @@ const StepDefineRuleComponent: FC = ({ {({ index }) => { if (index != null) { - if (isEqual(index, indicesConfig) && !localUseIndicesConfig) { + if (deepEqual(index, indicesConfig) && !localUseIndicesConfig) { setLocalUseIndicesConfig(true); } - if (!isEqual(index, indicesConfig) && localUseIndicesConfig) { + if (!deepEqual(index, indicesConfig) && localUseIndicesConfig) { setLocalUseIndicesConfig(false); } - if (index != null && !isEmpty(index) && !isEqual(index, mylocalIndicesConfig)) { + if (index != null && !isEmpty(index) && !deepEqual(index, mylocalIndicesConfig)) { setMyLocalIndicesConfig(index); } } diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx index cfbb0a622c7219..2e2c7e068dd857 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx @@ -5,8 +5,8 @@ */ import { EuiHorizontalRule, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; -import { isEqual } from 'lodash/fp'; import React, { FC, memo, useCallback, useEffect, useState } from 'react'; +import deepEqual from 'fast-deep-equal'; import { setFieldValue } from '../../helpers'; import { RuleStep, RuleStepProps, ScheduleStepRule } from '../../types'; @@ -62,7 +62,7 @@ const StepScheduleRuleComponent: FC = ({ useEffect(() => { const { isNew, ...initDefaultValue } = myStepData; - if (defaultValues != null && !isEqual(initDefaultValue, defaultValues)) { + if (defaultValues != null && !deepEqual(initDefaultValue, defaultValues)) { const myDefaultValues = { ...defaultValues, isNew: false, diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx index 41eb620850a7fd..f5efd9248029da 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx @@ -73,32 +73,25 @@ export const HostDetailsTabs = React.memo( return ( - } - /> - } - /> - } - /> - ( - - )} - /> - } - /> - } - /> + + + + + + + + + + + + + + + + + + + ); } diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx index 0b83710a132935..80c35e5563c1db 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { memo } from 'react'; +import React, { memo, useCallback } from 'react'; import { Route, Switch } from 'react-router-dom'; import { HostsTabsProps } from './types'; @@ -22,7 +22,7 @@ import { } from './navigation'; import { HostAlertsQueryTabBody } from './navigation/alerts_query_tab_body'; -const HostsTabs = memo( +export const HostsTabs = memo( ({ deleteQuery, filterQuery, @@ -44,49 +44,48 @@ const HostsTabs = memo( startDate: from, type, indexPattern, - narrowDateRange: (score: Anomaly, interval: string) => { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }, + narrowDateRange: useCallback( + (score: Anomaly, interval: string) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }, + [setAbsoluteRangeDatePicker] + ), + updateDateRange: useCallback( + (min: number, max: number) => { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }, + [setAbsoluteRangeDatePicker] + ), }; return ( - } - /> - } - /> - } - /> - ( - - )} - /> - } - /> - } - /> + + + + + + + + + + + + + + + + + + ); } ); HostsTabs.displayName = 'HostsTabs'; - -export { HostsTabs }; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx b/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx index 23a619db97ee4c..b6b54b68ac06a0 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx @@ -23,77 +23,82 @@ import { TlsQueryTabBody } from './tls_query_tab_body'; import { Anomaly } from '../../../components/ml/types'; import { NetworkAlertsQueryTabBody } from './alerts_query_tab_body'; -export const NetworkRoutes = ({ - networkPagePath, - type, - to, - filterQuery, - isInitializing, - from, - indexPattern, - setQuery, - setAbsoluteRangeDatePicker, -}: NetworkRoutesProps) => { - const narrowDateRange = useCallback( - (score: Anomaly, interval: string) => { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }, - [setAbsoluteRangeDatePicker] - ); +export const NetworkRoutes = React.memo( + ({ + networkPagePath, + type, + to, + filterQuery, + isInitializing, + from, + indexPattern, + setQuery, + setAbsoluteRangeDatePicker, + }) => { + const narrowDateRange = useCallback( + (score: Anomaly, interval: string) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }, + [setAbsoluteRangeDatePicker] + ); + const updateDateRange = useCallback( + (min: number, max: number) => { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }, + [setAbsoluteRangeDatePicker] + ); - const networkAnomaliesFilterQuery = { - bool: { - should: [ - { - exists: { - field: 'source.ip', + const networkAnomaliesFilterQuery = { + bool: { + should: [ + { + exists: { + field: 'source.ip', + }, }, - }, - { - exists: { - field: 'destination.ip', + { + exists: { + field: 'destination.ip', + }, }, - }, - ], - minimum_should_match: 1, - }, - }; + ], + minimum_should_match: 1, + }, + }; - const commonProps = { - startDate: from, - endDate: to, - skip: isInitializing, - type, - narrowDateRange, - setQuery, - filterQuery, - }; + const commonProps = { + startDate: from, + endDate: to, + skip: isInitializing, + type, + narrowDateRange, + setQuery, + filterQuery, + }; - const tabProps = { - ...commonProps, - indexPattern, - }; + const tabProps = { + ...commonProps, + indexPattern, + updateDateRange, + }; - const anomaliesProps = { - ...commonProps, - anomaliesFilterQuery: networkAnomaliesFilterQuery, - AnomaliesTableComponent: AnomaliesNetworkTable, - }; + const anomaliesProps = { + ...commonProps, + anomaliesFilterQuery: networkAnomaliesFilterQuery, + AnomaliesTableComponent: AnomaliesNetworkTable, + }; - return ( - - } - /> - ( + return ( + + + + + <> @@ -118,31 +123,25 @@ export const NetworkRoutes = ({ - )} - /> - } - /> - } - /> - ( + + + + + + + + - )} - /> - } - /> - - ); -}; + + + + + + ); + } +); NetworkRoutes.displayName = 'NetworkRoutes'; diff --git a/x-pack/legacy/plugins/siem/public/routes.tsx b/x-pack/legacy/plugins/siem/public/routes.tsx index cbb58a473e8ea0..a989fa9873435e 100644 --- a/x-pack/legacy/plugins/siem/public/routes.tsx +++ b/x-pack/legacy/plugins/siem/public/routes.tsx @@ -20,8 +20,12 @@ const PageRouterComponent: FC = ({ history }) => ( - } /> - } /> + + + + + + diff --git a/x-pack/legacy/plugins/siem/public/utils/kql/use_update_kql.tsx b/x-pack/legacy/plugins/siem/public/utils/kql/use_update_kql.tsx index 213b881bd20843..af993588f7e0dc 100644 --- a/x-pack/legacy/plugins/siem/public/utils/kql/use_update_kql.tsx +++ b/x-pack/legacy/plugins/siem/public/utils/kql/use_update_kql.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import { Dispatch } from 'redux'; import { IIndexPattern } from 'src/plugins/data/public'; +import deepEqual from 'fast-deep-equal'; import { KueryFilterQuery } from '../../store'; import { applyKqlFilterQuery as dispatchApplyTimelineFilterQuery } from '../../store/timeline/actions'; @@ -29,7 +29,7 @@ export const useUpdateKql = ({ timelineId, }: UseUpdateKqlProps): RefetchKql => { const updateKql: RefetchKql = (dispatch: Dispatch) => { - if (kueryFilterQueryDraft != null && !isEqual(kueryFilterQuery, kueryFilterQueryDraft)) { + if (kueryFilterQueryDraft != null && !deepEqual(kueryFilterQuery, kueryFilterQueryDraft)) { if (storeType === 'timelineType' && timelineId != null) { dispatch( dispatchApplyTimelineFilterQuery({ diff --git a/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx b/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx index c88562abef6ae0..ddee2359b28ba4 100644 --- a/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx +++ b/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx @@ -5,7 +5,6 @@ */ import * as H from 'history'; -import { isEqual } from 'lodash/fp'; import { memo, useEffect, useState } from 'react'; import { withRouter } from 'react-router-dom'; import deepEqual from 'fast-deep-equal'; @@ -35,7 +34,7 @@ export const SpyRouteComponent = memo( } }, [search]); useEffect(() => { - if (pageName && !isEqual(route.pathName, pathname)) { + if (pageName && !deepEqual(route.pathName, pathname)) { if (isInitializing && detailName == null) { dispatch({ type: 'updateRouteWithOutSearch', diff --git a/x-pack/package.json b/x-pack/package.json index ea76b3e26ee0bb..52087647cac8cb 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -106,6 +106,7 @@ "@types/uuid": "^3.4.4", "@types/xml-crypto": "^1.4.0", "@types/xml2js": "^0.4.5", + "@welldone-software/why-did-you-render": "^4.0.0", "abab": "^1.0.4", "axios": "^0.19.0", "babel-jest": "^24.9.0", diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index 978271166cc058..723da7cef6a777 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -36,7 +36,7 @@ "x-pack/test_utils/*" ], "plugins/*": ["src/legacy/core_plugins/*/public/"], - "fixtures/*": ["src/fixtures/*"] + "fixtures/*": ["src/fixtures/*"], }, "types": [ "node", diff --git a/yarn.lock b/yarn.lock index e824aceeed8479..13268334de33b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6355,6 +6355,13 @@ text-table "^0.2.0" webpack-log "^1.1.2" +"@welldone-software/why-did-you-render@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-4.0.0.tgz#cc98c996f5a06ea55bd07dc99ba4b4d68af93332" + integrity sha512-PjqriZ8Ak9biP2+kOcIrg+NwsFwWVhGV03Hm+ns84YBCArn+hWBKM9rMBEU6e62I1qyrYF2/G9yktNpEmfWfJA== + dependencies: + lodash "^4" + "@wry/context@^0.4.0": version "0.4.1" resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.1.tgz#b3e23ca036035cbad0bd9711269352dd03a6fe3c" @@ -20455,7 +20462,7 @@ lodash.uniqby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= -lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.5: +lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.5: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==