From 702ef102e678457f2b93775245d967b96bf55372 Mon Sep 17 00:00:00 2001 From: Patryk Kopycinski Date: Mon, 17 Aug 2020 21:45:36 +0200 Subject: [PATCH 1/4] [Security Solution] Fix setting the initial Kibana filters --- .../common/components/search_bar/index.tsx | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx index de60bca73cedf..678c15f2790ee 100644 --- a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx @@ -80,14 +80,16 @@ const SearchBarComponent = memo( filterManager, } = data.query; - if (fromStr != null && toStr != null) { - timefilter.setTime({ from: fromStr, to: toStr }); - } else if (start != null && end != null) { - timefilter.setTime({ - from: new Date(start).toISOString(), - to: new Date(end).toISOString(), - }); - } + useEffect(() => { + if (fromStr != null && toStr != null) { + timefilter.setTime({ from: fromStr, to: toStr }); + } else if (start != null && end != null) { + timefilter.setTime({ + from: new Date(start).toISOString(), + to: new Date(end).toISOString(), + }); + } + }, [end, fromStr, start, timefilter, toStr]); const onQuerySubmit = useCallback( (payload: { dateRange: TimeRange; query?: Query }) => { @@ -135,8 +137,7 @@ const SearchBarComponent = memo( window.setTimeout(() => updateSearch(updateSearchBar), 0); }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [id, end, filterQuery, fromStr, queries, start, toStr] + [id, toStr, end, fromStr, start, filterManager, filterQuery, queries, updateSearch] ); const onRefresh = useCallback( @@ -155,16 +156,14 @@ const SearchBarComponent = memo( queries.forEach((q) => q.refetch && (q.refetch as inputsModel.Refetch)()); } }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [id, queries, filterManager] + [updateSearch, id, filterManager, queries] ); const onSaved = useCallback( (newSavedQuery: SavedQuery) => { setSavedQuery({ id, savedQuery: newSavedQuery }); }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [id] + [id, setSavedQuery] ); const onSavedQueryUpdated = useCallback( @@ -200,8 +199,7 @@ const SearchBarComponent = memo( updateSearch(updateSearchBar); }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [id, end, fromStr, start, toStr] + [id, toStr, end, fromStr, start, filterManager, updateSearch] ); const onClearSavedQuery = useCallback(() => { @@ -223,8 +221,7 @@ const SearchBarComponent = memo( filterManager, }); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [id, end, filterManager, fromStr, start, toStr, savedQuery]); + }, [savedQuery, updateSearch, id, toStr, end, fromStr, start, filterManager]); useEffect(() => { let isSubscribed = true; @@ -243,6 +240,9 @@ const SearchBarComponent = memo( }) ); + // for the initial state + setSearchBarFilter({ id, filters: filterManager.getFilters() }); + return () => { isSubscribed = false; subscriptions.unsubscribe(); From d42a73e9e5263b1f3572b8a4af85d5ca195e9e24 Mon Sep 17 00:00:00 2001 From: Patryk Kopycinski Date: Tue, 18 Aug 2020 10:59:58 +0200 Subject: [PATCH 2/4] add unit test --- src/plugins/data/public/mocks.ts | 2 +- .../components/search_bar/index.test.tsx | 44 +++++++++++++++++++ .../common/components/search_bar/index.tsx | 21 +++++---- 3 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/common/components/search_bar/index.test.tsx diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 78e40cfedd906..0eb0e3b658045 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -61,7 +61,7 @@ const createStartContract = (): Start => { query: queryStartMock, ui: { IndexPatternSelect: jest.fn(), - SearchBar: jest.fn(), + SearchBar: jest.fn().mockReturnValue(null), }, indexPatterns: ({ createField: jest.fn(() => {}), diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.test.tsx new file mode 100644 index 0000000000000..356456c777791 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.test.tsx @@ -0,0 +1,44 @@ +/* + * 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 from 'react'; +import { mount } from 'enzyme'; + +import { InputsModelId } from '../../store/inputs/constants'; +import { SearchBarComponent } from '.'; +import { TestProviders } from '../../mock'; + +jest.mock('../../lib/kibana'); + +describe('SearchBarComponent', () => { + const props = { + id: 'global' as InputsModelId, + indexPattern: { + fields: [], + title: '', + }, + updateSearch: jest.fn(), + setSavedQuery: jest.fn(), + setSearchBarFilter: jest.fn(), + end: '', + start: '', + toStr: '', + fromStr: '', + isLoading: false, + filterQuery: { + query: '', + language: '', + }, + queries: [], + savedQuery: undefined, + }; + + it('calls setSearchBarFilter on mount', () => { + mount(, { wrappingComponent: TestProviders }); + + expect(props.setSearchBarFilter).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx index 678c15f2790ee..eedb965986067 100644 --- a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx @@ -33,7 +33,6 @@ import { filterQuerySelector, fromStrSelector, isLoadingSelector, - kindSelector, queriesSelector, savedQuerySelector, startSelector, @@ -57,7 +56,7 @@ const SearchBarContainer = styled.div` } `; -const SearchBarComponent = memo( +export const SearchBarComponent = memo( ({ end, filterQuery, @@ -74,11 +73,15 @@ const SearchBarComponent = memo( updateSearch, dataTestSubj, }) => { - const { data } = useKibana().services; const { - timefilter: { timefilter }, - filterManager, - } = data.query; + data: { + query: { + timefilter: { timefilter }, + filterManager, + }, + ui: { SearchBar }, + }, + } = useKibana().services; useEffect(() => { if (fromStr != null && toStr != null) { @@ -249,10 +252,12 @@ const SearchBarComponent = memo( }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const indexPatterns = useMemo(() => [indexPattern], [indexPattern]); + return ( - { const getEndSelector = endSelector(); const getFromStrSelector = fromStrSelector(); const getIsLoadingSelector = isLoadingSelector(); - const getKindSelector = kindSelector(); const getQueriesSelector = queriesSelector(); const getStartSelector = startSelector(); const getToStrSelector = toStrSelector(); @@ -292,7 +296,6 @@ const makeMapStateToProps = () => { fromStr: getFromStrSelector(inputsRange), filterQuery: getFilterQuerySelector(inputsRange), isLoading: getIsLoadingSelector(inputsRange), - kind: getKindSelector(inputsRange), queries: getQueriesSelector(inputsRange), savedQuery: getSavedQuerySelector(inputsRange), start: getStartSelector(inputsRange), From e0b07a625a33a481aec0a479a5b5bf38a2bd8f36 Mon Sep 17 00:00:00 2001 From: Patryk Kopycinski Date: Wed, 19 Aug 2020 22:41:16 +0200 Subject: [PATCH 3/4] keep appState in kibana storage --- .../public/common/components/search_bar/index.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx index eedb965986067..e9b414f9a37f8 100644 --- a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx @@ -43,6 +43,8 @@ import { networkActions } from '../../../network/store'; import { timelineActions } from '../../../timelines/store/timeline'; import { useKibana } from '../../lib/kibana'; +const APP_STATE_STORAGE_KEY = 'securitySolution.searchBar.appState'; + interface SiemSearchBarProps { id: InputsModelId; indexPattern: IIndexPattern; @@ -81,6 +83,7 @@ export const SearchBarComponent = memo( }, ui: { SearchBar }, }, + storage, } = useKibana().services; useEffect(() => { @@ -226,6 +229,15 @@ export const SearchBarComponent = memo( } }, [savedQuery, updateSearch, id, toStr, end, fromStr, start, filterManager]); + const saveAppStateToStorage = useCallback( + (filters: Filter[]) => storage.set(APP_STATE_STORAGE_KEY, filters), + [storage] + ); + + const getAppStateFromStorage = useCallback(() => storage.get(APP_STATE_STORAGE_KEY) ?? [], [ + storage, + ]); + useEffect(() => { let isSubscribed = true; const subscriptions = new Subscription(); @@ -234,6 +246,7 @@ export const SearchBarComponent = memo( filterManager.getUpdates$().subscribe({ next: () => { if (isSubscribed) { + saveAppStateToStorage(filterManager.getAppFilters()); setSearchBarFilter({ id, filters: filterManager.getFilters(), @@ -244,7 +257,7 @@ export const SearchBarComponent = memo( ); // for the initial state - setSearchBarFilter({ id, filters: filterManager.getFilters() }); + filterManager.setAppFilters(getAppStateFromStorage()); return () => { isSubscribed = false; From 43a675885eb582a0d4b7ee550fd9232cea5fbc87 Mon Sep 17 00:00:00 2001 From: Patryk Kopycinski Date: Wed, 19 Aug 2020 23:28:27 +0200 Subject: [PATCH 4/4] fix logic --- .../public/common/components/search_bar/index.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx index e9b414f9a37f8..2dc44fd48e66d 100644 --- a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx @@ -258,6 +258,10 @@ export const SearchBarComponent = memo( // for the initial state filterManager.setAppFilters(getAppStateFromStorage()); + setSearchBarFilter({ + id, + filters: filterManager.getFilters(), + }); return () => { isSubscribed = false;