From 241be2c1f4e24865f58e2a97001357e975756309 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Tue, 10 Jan 2023 10:29:24 +0100 Subject: [PATCH 01/15] Add discover data store --- .../main/hooks/use_discover_state.ts | 24 +- .../discover_data_state_container.test.ts | 89 +++++++ .../services/discover_data_state_container.ts | 226 ++++++++++++++++++ .../main/services/discover_state.ts | 32 ++- 4 files changed, 356 insertions(+), 15 deletions(-) create mode 100644 src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts create mode 100644 src/plugins/discover/public/application/main/services/discover_data_state_container.ts diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index 6eefb25580969..613e52cf9f27d 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -18,14 +18,11 @@ import { getDiscoverStateContainer } from '../services/discover_state'; import { getStateDefaults } from '../utils/get_state_defaults'; import { DiscoverServices } from '../../../build_services'; import { loadDataView, resolveDataView } from '../utils/resolve_data_view'; -import { useSavedSearch as useSavedSearchData } from './use_saved_search'; import { MODIFY_COLUMNS_ON_SWITCH, - SEARCH_FIELDS_FROM_SOURCE, SEARCH_ON_PAGE_LOAD_SETTING, SORT_DEFAULT_ORDER_SETTING, } from '../../../../common'; -import { useSearchSession } from './use_search_session'; import { FetchStatus } from '../../types'; import { getDataViewAppState } from '../utils/get_switch_data_view_app_state'; import { DataTableRecord } from '../../../types'; @@ -45,7 +42,6 @@ export function useDiscoverState({ }) { const { uiSettings, data, filterManager, dataViews, toastNotifications, trackUiMetric } = services; - const useNewFieldsApi = useMemo(() => !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), [uiSettings]); const { timefilter } = data.query.timefilter; const dataView = savedSearch.searchSource.getField('index')!; @@ -78,7 +74,7 @@ export function useDiscoverState({ /** * Search session logic */ - const searchSessionManager = useSearchSession({ services, history, stateContainer, savedSearch }); + const searchSessionManager = stateContainer.searchSessionManager; const initialFetchStatus: FetchStatus = useMemo(() => { // A saved search is created on every page load, so we check the ID to see if we're loading a @@ -121,15 +117,7 @@ export function useDiscoverState({ /** * Data fetching logic */ - const { data$, refetch$, reset, inspectorAdapters } = useSavedSearchData({ - initialFetchStatus, - searchSessionManager, - savedSearch, - searchSource, - services, - stateContainer, - useNewFieldsApi, - }); + const { data$, refetch$, reset, inspectorAdapters } = stateContainer.dataState; /** * State changes (data view, columns), when a text base query result is returned */ @@ -156,6 +144,14 @@ export function useDiscoverState({ return () => stopSync(); }, [stateContainer, filterManager, data, dataView]); + /** + * Data store subscribing to trigger fetching + */ + useEffect(() => { + const stopSync = stateContainer.dataState.subscribe(); + return () => stopSync(); + }, [stateContainer]); + /** * Track state changes that should trigger a fetch */ diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts new file mode 100644 index 0000000000000..848e31edebb85 --- /dev/null +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { Subject } from 'rxjs'; +import { waitFor } from '@testing-library/react'; +import { discoverServiceMock } from '../../../__mocks__/services'; +import { savedSearchMockWithSQL } from '../../../__mocks__/saved_search'; +import { getDiscoverStateContainer } from './discover_state'; +import { FetchStatus } from '../../types'; +import { setUrlTracker } from '../../../kibana_services'; +import { urlTrackerMock } from '../../../__mocks__/url_tracker.mock'; +import { RecordRawType } from './discover_data_state_container'; +import { createBrowserHistory } from 'history'; +import { getDiscoverStateMock } from '../../../__mocks__/discover_state.mock'; + +setUrlTracker(urlTrackerMock); +describe('test getDataStateContainer', () => { + test('return is valid', async () => { + const stateContainer = getDiscoverStateMock({ isTimeBased: true }); + const dataState = stateContainer.dataState; + + expect(dataState.refetch$).toBeInstanceOf(Subject); + expect(dataState.data$.main$.getValue().fetchStatus).toBe(FetchStatus.LOADING); + expect(dataState.data$.documents$.getValue().fetchStatus).toBe(FetchStatus.LOADING); + expect(dataState.data$.totalHits$.getValue().fetchStatus).toBe(FetchStatus.LOADING); + expect(dataState.data$.charts$.getValue().fetchStatus).toBe(FetchStatus.LOADING); + }); + test('refetch$ triggers a search', async () => { + const stateContainer = getDiscoverStateMock({ isTimeBased: true }); + + discoverServiceMock.data.query.timefilter.timefilter.getTime = jest.fn(() => { + return { from: '2021-05-01T20:00:00Z', to: '2021-05-02T20:00:00Z' }; + }); + const dataState = stateContainer.dataState; + + const unsubscribe = dataState.subscribe(); + + dataState.refetch$.next(undefined); + await waitFor(() => { + expect(dataState.data$.main$.value.fetchStatus).toBe('complete'); + }); + + expect(dataState.data$.totalHits$.value.result).toBe(0); + expect(dataState.data$.documents$.value.result).toEqual([]); + unsubscribe(); + }); + + test('reset sets back to initial state', async () => { + const stateContainer = getDiscoverStateMock({ isTimeBased: true }); + + discoverServiceMock.data.query.timefilter.timefilter.getTime = jest.fn(() => { + return { from: '2021-05-01T20:00:00Z', to: '2021-05-02T20:00:00Z' }; + }); + + const dataState = stateContainer.dataState; + const unsubscribe = dataState.subscribe(); + + await waitFor(() => { + expect(dataState.data$.main$.value.fetchStatus).toBe(FetchStatus.LOADING); + }); + + dataState.refetch$.next(undefined); + + await waitFor(() => { + expect(dataState.data$.main$.value.fetchStatus).toBe(FetchStatus.COMPLETE); + }); + dataState.reset(); + await waitFor(() => { + expect(dataState.data$.main$.value.fetchStatus).toBe(FetchStatus.LOADING); + }); + + unsubscribe(); + }); + + test('useSavedSearch returns plain record raw type', async () => { + const history = createBrowserHistory(); + const stateContainer = getDiscoverStateContainer({ + savedSearch: savedSearchMockWithSQL, + services: discoverServiceMock, + history, + }); + + expect(stateContainer.dataState.data$.main$.getValue().recordRawType).toBe(RecordRawType.PLAIN); + }); +}); diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts new file mode 100644 index 0000000000000..915c691c6db05 --- /dev/null +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts @@ -0,0 +1,226 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { BehaviorSubject, Subject } from 'rxjs'; +import { RequestAdapter } from '@kbn/inspector-plugin/common'; +import { AutoRefreshDoneFn } from '@kbn/data-plugin/public'; +import { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { AggregateQuery, Query } from '@kbn/es-query'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import { ReduxLikeStateContainer } from '@kbn/kibana-utils-plugin/common'; +import { DataTableRecord } from '../../../types'; +import { AppState } from './discover_app_state_container'; +import { DiscoverServices } from '../../../build_services'; +import { DiscoverSearchSessionManager } from './discover_search_session'; +import { getRawRecordType } from '../utils/get_raw_record_type'; +import { SEARCH_FIELDS_FROM_SOURCE, SEARCH_ON_PAGE_LOAD_SETTING } from '../../../../common'; +import { FetchStatus } from '../../types'; +import { getFetch$ } from '../utils/get_fetch_observable'; +import { validateTimeRange } from '../utils/validate_time_range'; +import { fetchAll } from '../utils/fetch_all'; +import { sendResetMsg } from '../hooks/use_saved_search_messages'; + +export interface SavedSearchData { + main$: DataMain$; + documents$: DataDocuments$; + totalHits$: DataTotalHits$; + charts$: DataCharts$; + availableFields$: AvailableFields$; +} + +export type DataMain$ = BehaviorSubject; +export type DataDocuments$ = BehaviorSubject; +export type DataTotalHits$ = BehaviorSubject; +export type DataCharts$ = BehaviorSubject; +export type AvailableFields$ = BehaviorSubject; +export type DataRefetch$ = Subject; + +export interface UseSavedSearch { + refetch$: DataRefetch$; + data$: SavedSearchData; + reset: () => void; + inspectorAdapters: { requests: RequestAdapter }; +} + +export enum RecordRawType { + /** + * Documents returned Elasticsearch, nested structure + */ + DOCUMENT = 'document', + /** + * Data returned e.g. SQL queries, flat structure + * */ + PLAIN = 'plain', +} + +export type DataRefetchMsg = 'reset' | undefined; + +export interface DataMsg { + fetchStatus: FetchStatus; + error?: Error; + recordRawType?: RecordRawType; + query?: AggregateQuery | Query | undefined; +} + +export interface DataMainMsg extends DataMsg { + foundDocuments?: boolean; +} + +export interface DataDocumentsMsg extends DataMsg { + result?: DataTableRecord[]; +} + +export interface DataTotalHitsMsg extends DataMsg { + fetchStatus: FetchStatus; + error?: Error; + result?: number; +} + +export interface DataChartsMessage extends DataMsg { + response?: SearchResponse; +} + +export interface DataAvailableFieldsMsg extends DataMsg { + fields?: string[]; +} + +export interface DataStateContainer { + fetch: () => void; + data$: SavedSearchData; + refetch$: DataRefetch$; + subscribe: () => () => void; + reset: () => void; + inspectorAdapters: { requests: RequestAdapter }; + initialFetchStatus: FetchStatus; +} + +export function getDataStateContainer({ + services, + searchSessionManager, + getAppState, + getSavedSearch, + appStateContainer, +}: { + services: DiscoverServices; + searchSessionManager: DiscoverSearchSessionManager; + getAppState: () => AppState; + getSavedSearch: () => SavedSearch; + appStateContainer: ReduxLikeStateContainer; +}): DataStateContainer { + const { data } = services; + const inspectorAdapters = { requests: new RequestAdapter() }; + const appState = getAppState(); + const recordRawType = getRawRecordType(appState.query); + /** + * The observable to trigger data fetching in UI + * By refetch$.next('reset') rows and fieldcounts are reset to allow e.g. editing of runtime fields + * to be processed correctly + */ + const refetch$ = new Subject(); + const shouldSearchOnPageLoad = + services.uiSettings.get(SEARCH_ON_PAGE_LOAD_SETTING) || + getSavedSearch().id !== undefined || + !services.timefilter.getRefreshInterval().pause || + searchSessionManager.hasSearchSessionIdInURL(); + const initialFetchStatus = shouldSearchOnPageLoad + ? FetchStatus.LOADING + : FetchStatus.UNINITIALIZED; + + /** + * The observables the UI (aka React component) subscribes to get notified about + * the changes in the data fetching process (high level: fetching started, data was received) + */ + const initialState = { fetchStatus: initialFetchStatus, recordRawType }; + const dataSubjects: SavedSearchData = { + main$: new BehaviorSubject(initialState), + documents$: new BehaviorSubject(initialState), + totalHits$: new BehaviorSubject(initialState), + charts$: new BehaviorSubject(initialState), + availableFields$: new BehaviorSubject(initialState), + }; + + let autoRefreshDone: AutoRefreshDoneFn | undefined; + /** + * handler emitted by `timefilter.getAutoRefreshFetch$()` + * to notify when data completed loading and to start a new autorefresh loop + */ + const setAutoRefreshDone = (fn: AutoRefreshDoneFn | undefined) => { + autoRefreshDone = fn; + }; + const fetch$ = getFetch$({ + setAutoRefreshDone, + data, + main$: dataSubjects.main$, + refetch$, + searchSource: getSavedSearch().searchSource, + searchSessionManager, + initialFetchStatus, + }); + let abortController: AbortController; + + function subscribe() { + const subscription = fetch$.subscribe(async (val) => { + if ( + !validateTimeRange(data.query.timefilter.timefilter.getTime(), services.toastNotifications) + ) { + return; + } + inspectorAdapters.requests.reset(); + + abortController?.abort(); + abortController = new AbortController(); + const prevAutoRefreshDone = autoRefreshDone; + + await fetchAll(dataSubjects, getSavedSearch().searchSource, val === 'reset', { + abortController, + data, + initialFetchStatus, + inspectorAdapters, + searchSessionId: searchSessionManager.getNextSearchSessionId(), + services, + appStateContainer, + savedSearch: getSavedSearch(), + useNewFieldsApi: !services.uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), + }); + + // If the autoRefreshCallback is still the same as when we started i.e. there was no newer call + // replacing this current one, call it to make sure we tell that the auto refresh is done + // and a new one can be scheduled. + if (autoRefreshDone === prevAutoRefreshDone) { + // if this function was set and is executed, another refresh fetch can be triggered + autoRefreshDone?.(); + autoRefreshDone = undefined; + } + }); + + return () => { + abortController?.abort(); + subscription.unsubscribe(); + }; + } + + const fetchQuery = (resetQuery?: boolean) => { + if (resetQuery) { + refetch$.next('reset'); + } else { + refetch$.next(undefined); + } + return refetch$; + }; + + const reset = () => sendResetMsg(dataSubjects, initialFetchStatus); + + return { + fetch: fetchQuery, + data$: dataSubjects, + refetch$, + subscribe, + reset, + inspectorAdapters, + initialFetchStatus, + }; +} diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts index 52e0d6e72fbf5..79d55f9f475c0 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -29,6 +29,8 @@ import { } from '@kbn/data-plugin/public'; import { DataView } from '@kbn/data-views-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { DataStateContainer, getDataStateContainer } from './discover_data_state_container'; +import { DiscoverSearchSessionManager } from './discover_search_session'; import { DiscoverAppLocatorParams, DISCOVER_APP_LOCATOR } from '../../../../common'; import { AppState } from './discover_app_state_container'; import { @@ -52,7 +54,7 @@ interface DiscoverStateContainerParams { /** * Browser history */ - history?: History; + history: History; /** * The current savedSearch */ @@ -76,6 +78,14 @@ export interface DiscoverStateContainer { * Internal state that's used at several places in the UI */ internalState: InternalStateContainer; + /** + * Service for handling search sessions + */ + searchSessionManager: DiscoverSearchSessionManager; + /** + * Data fetching related state + **/ + dataState: DataStateContainer; /** * Initialize state with filters and query, start state syncing */ @@ -179,6 +189,14 @@ export function getDiscoverStateContainer({ ...(toasts && withNotifyOnErrors(toasts)), }); + /** + * Search session logic + */ + const searchSessionManager = new DiscoverSearchSessionManager({ + history, + session: services.data.search.session, + }); + const appStateFromUrl = cleanupUrlState(stateStorage.get(APP_STATE_URL_KEY) as AppStateUrl); let initialAppState = handleSourceColumnState( @@ -234,6 +252,16 @@ export function getDiscoverStateContainer({ } }; + const dataStateContainer = getDataStateContainer({ + services, + searchSessionManager, + getAppState: appStateContainer.getState, + getSavedSearch: () => { + return { savedSearch, searchSource: savedSearch.searchSource.createChild() }; + }, + appStateContainer, + }); + const setDataView = (dataView: DataView) => { internalStateContainer.transitions.setDataView(dataView); }; @@ -255,6 +283,8 @@ export function getDiscoverStateContainer({ kbnUrlStateStorage: stateStorage, appState: appStateContainerModified, internalState: internalStateContainer, + dataState: dataStateContainer, + searchSessionManager, startSync: () => { const { start, stop } = syncAppState(); start(); From dbf6ec87418421b5bb4bf2149a8d7324a1f4a490 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 10 Jan 2023 09:36:44 +0000 Subject: [PATCH 02/15] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- .../security_solution/public/management/cypress/tsconfig.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json b/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json index af09fee04643f..a99e4af76fe2e 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json +++ b/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json @@ -22,6 +22,8 @@ "path": "../../../tsconfig.json", "force": true }, - "@kbn/security-plugin" + "@kbn/security-plugin", + "@kbn/securitysolution-list-constants", + "@kbn/fleet-plugin" ] } From ea1f881c0faff99c3d08b3ac1e25438a3ac20640 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Tue, 10 Jan 2023 23:59:34 +0100 Subject: [PATCH 03/15] improve use_discover_state.ts --- .../main/hooks/use_discover_state.ts | 25 ++++--------------- .../services/discover_data_state_container.ts | 9 +++---- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index 613e52cf9f27d..e9e5d2cd28473 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -12,18 +12,14 @@ import { isOfAggregateQueryType } from '@kbn/es-query'; import { type DataView, DataViewType } from '@kbn/data-views-plugin/public'; import { SavedSearch, getSavedSearch } from '@kbn/saved-search-plugin/public'; import type { SortOrder } from '@kbn/saved-search-plugin/public'; +import { FetchStatus } from '../../types'; import { useTextBasedQueryLanguage } from './use_text_based_query_language'; import { useUrlTracking } from './use_url_tracking'; import { getDiscoverStateContainer } from '../services/discover_state'; import { getStateDefaults } from '../utils/get_state_defaults'; import { DiscoverServices } from '../../../build_services'; import { loadDataView, resolveDataView } from '../utils/resolve_data_view'; -import { - MODIFY_COLUMNS_ON_SWITCH, - SEARCH_ON_PAGE_LOAD_SETTING, - SORT_DEFAULT_ORDER_SETTING, -} from '../../../../common'; -import { FetchStatus } from '../../types'; +import { MODIFY_COLUMNS_ON_SWITCH, SORT_DEFAULT_ORDER_SETTING } from '../../../../common'; import { getDataViewAppState } from '../utils/get_switch_data_view_app_state'; import { DataTableRecord } from '../../../types'; import { restoreStateFromSavedSearch } from '../../../services/saved_searches/restore_from_saved_search'; @@ -42,7 +38,6 @@ export function useDiscoverState({ }) { const { uiSettings, data, filterManager, dataViews, toastNotifications, trackUiMetric } = services; - const { timefilter } = data.query.timefilter; const dataView = savedSearch.searchSource.getField('index')!; @@ -76,17 +71,6 @@ export function useDiscoverState({ */ const searchSessionManager = stateContainer.searchSessionManager; - const initialFetchStatus: FetchStatus = useMemo(() => { - // A saved search is created on every page load, so we check the ID to see if we're loading a - // previously saved search or if it is just transient - const shouldSearchOnPageLoad = - uiSettings.get(SEARCH_ON_PAGE_LOAD_SETTING) || - savedSearch.id !== undefined || - timefilter.getRefreshInterval().pause === false || - searchSessionManager.hasSearchSessionIdInURL(); - return shouldSearchOnPageLoad ? FetchStatus.LOADING : FetchStatus.UNINITIALIZED; - }, [uiSettings, savedSearch.id, searchSessionManager, timefilter]); - /** * Adhoc data views functionality */ @@ -117,7 +101,8 @@ export function useDiscoverState({ /** * Data fetching logic */ - const { data$, refetch$, reset, inspectorAdapters } = stateContainer.dataState; + const { data$, refetch$, reset, inspectorAdapters, initialFetchStatus } = + stateContainer.dataState; /** * State changes (data view, columns), when a text base query result is returned */ @@ -300,7 +285,7 @@ export function useDiscoverState({ * Trigger data fetching on dataView or savedSearch changes */ useEffect(() => { - if (dataView) { + if (dataView && initialFetchStatus === FetchStatus.LOADING) { refetch$.next(undefined); } }, [initialFetchStatus, refetch$, dataView, savedSearch.id]); diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts index 915c691c6db05..99e661aae7951 100644 --- a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts @@ -12,6 +12,7 @@ import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { AggregateQuery, Query } from '@kbn/es-query'; import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { ReduxLikeStateContainer } from '@kbn/kibana-utils-plugin/common'; +import { InspectorAdapters } from '../hooks/use_inspector'; import { DataTableRecord } from '../../../types'; import { AppState } from './discover_app_state_container'; import { DiscoverServices } from '../../../build_services'; @@ -28,22 +29,21 @@ export interface SavedSearchData { main$: DataMain$; documents$: DataDocuments$; totalHits$: DataTotalHits$; - charts$: DataCharts$; availableFields$: AvailableFields$; } export type DataMain$ = BehaviorSubject; export type DataDocuments$ = BehaviorSubject; export type DataTotalHits$ = BehaviorSubject; -export type DataCharts$ = BehaviorSubject; export type AvailableFields$ = BehaviorSubject; + export type DataRefetch$ = Subject; export interface UseSavedSearch { refetch$: DataRefetch$; data$: SavedSearchData; reset: () => void; - inspectorAdapters: { requests: RequestAdapter }; + inspectorAdapters: InspectorAdapters; } export enum RecordRawType { @@ -75,8 +75,6 @@ export interface DataDocumentsMsg extends DataMsg { } export interface DataTotalHitsMsg extends DataMsg { - fetchStatus: FetchStatus; - error?: Error; result?: number; } @@ -139,7 +137,6 @@ export function getDataStateContainer({ main$: new BehaviorSubject(initialState), documents$: new BehaviorSubject(initialState), totalHits$: new BehaviorSubject(initialState), - charts$: new BehaviorSubject(initialState), availableFields$: new BehaviorSubject(initialState), }; From d6956595c15cb6a7e11975c3a74c42d083e15f66 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Fri, 13 Jan 2023 00:31:39 +0100 Subject: [PATCH 04/15] fixing tests --- .../application/main/hooks/use_discover_state.ts | 7 +++++++ .../application/main/services/discover_state.ts | 3 +-- .../application/main/utils/get_fetch_observable.ts | 13 ++----------- .../apps/discover/group2/_search_on_page_load.ts | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index e9e5d2cd28473..9066ac6ece50c 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -180,6 +180,13 @@ export function useDiscoverState({ stateContainer.actions.setDataView(nextDataView); } + if ( + dataViewChanged && + stateContainer.dataState.initialFetchStatus === FetchStatus.UNINITIALIZED + ) { + return; + } + if ( chartDisplayChanged || chartIntervalChanged || diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts index 79d55f9f475c0..1c601ba95001d 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -257,11 +257,10 @@ export function getDiscoverStateContainer({ searchSessionManager, getAppState: appStateContainer.getState, getSavedSearch: () => { - return { savedSearch, searchSource: savedSearch.searchSource.createChild() }; + return { ...savedSearch, searchSource: savedSearch.searchSource.createChild() }; }, appStateContainer, }); - const setDataView = (dataView: DataView) => { internalStateContainer.transitions.setDataView(dataView); }; diff --git a/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts b/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts index 984d0737dfb31..3a5dd042dcfd7 100644 --- a/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts +++ b/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ import { merge } from 'rxjs'; -import { debounceTime, filter, skip, tap } from 'rxjs/operators'; +import { debounceTime, filter, tap } from 'rxjs/operators'; import type { AutoRefreshDoneFn, @@ -38,7 +38,7 @@ export function getFetch$({ }) { const { timefilter } = data.query.timefilter; const { filterManager } = data.query; - let fetch$ = merge( + return merge( refetch$, filterManager.getFetches$(), timefilter.getFetch$(), @@ -60,13 +60,4 @@ export function getFetch$({ data.query.queryString.getUpdates$(), searchSessionManager.newSearchSessionIdFromURL$.pipe(filter((sessionId) => !!sessionId)) ).pipe(debounceTime(100)); - - /** - * Skip initial fetch when discover:searchOnPageLoad is disabled. - */ - if (initialFetchStatus === FetchStatus.UNINITIALIZED) { - fetch$ = fetch$.pipe(skip(1)); - } - - return fetch$; } diff --git a/test/functional/apps/discover/group2/_search_on_page_load.ts b/test/functional/apps/discover/group2/_search_on_page_load.ts index 2f3ad427335cd..b7011964bc372 100644 --- a/test/functional/apps/discover/group2/_search_on_page_load.ts +++ b/test/functional/apps/discover/group2/_search_on_page_load.ts @@ -39,7 +39,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { return nrOfFetches === fetchesNumber; }; - describe('usage of discover:searchOnPageLoad', () => { + describe.only('usage of discover:searchOnPageLoad', () => { before(async function () { await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']); log.debug('load kibana index with default index pattern'); From 52a68f26cc03b6f96a4a5c653ed4055eee996673 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Fri, 13 Jan 2023 10:13:31 +0100 Subject: [PATCH 05/15] fix sharing --- .../discover/public/utils/get_sharing_data.test.ts | 11 +++++++---- .../discover/public/utils/get_sharing_data.ts | 13 ++++++++----- .../apps/discover/group2/_search_on_page_load.ts | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/plugins/discover/public/utils/get_sharing_data.test.ts b/src/plugins/discover/public/utils/get_sharing_data.test.ts index 103a40423dc35..d1d636a2d1c83 100644 --- a/src/plugins/discover/public/utils/get_sharing_data.test.ts +++ b/src/plugins/discover/public/utils/get_sharing_data.test.ts @@ -78,6 +78,12 @@ describe('getSharingData', () => { const { getSearchSource } = await getSharingData(searchSourceMock, {}, services); expect(getSearchSource()).toMatchInlineSnapshot(` Object { + "fields": Array [ + Object { + "field": "*", + "include_unmapped": "true", + }, + ], "index": "the-data-view-id", "sort": Array [ Object { @@ -194,10 +200,7 @@ describe('getSharingData', () => { test('fields conditionally do not have prepended timeField', async () => { services.uiSettings = { get: (key: string) => { - if (key === DOC_HIDE_TIME_COLUMN_SETTING) { - return true; - } - return false; + return key === DOC_HIDE_TIME_COLUMN_SETTING; }, } as unknown as IUiSettingsClient; diff --git a/src/plugins/discover/public/utils/get_sharing_data.ts b/src/plugins/discover/public/utils/get_sharing_data.ts index dfbdcc49e90a4..8ad4903e3f7e2 100644 --- a/src/plugins/discover/public/utils/get_sharing_data.ts +++ b/src/plugins/discover/public/utils/get_sharing_data.ts @@ -96,11 +96,14 @@ export async function getSharingData( * Discover does not set fields, since having all fields is needed for the UI. */ const useFieldsApi = !config.get(SEARCH_FIELDS_FROM_SOURCE); - if (useFieldsApi && columns.length) { - searchSource.setField( - 'fields', - columns.map((field) => ({ field, include_unmapped: 'true' })) - ); + if (useFieldsApi) { + searchSource.removeField('fieldsFromSource'); + if (columns.length) { + const fields = columns.map((field) => ({ field, include_unmapped: 'true' })); + searchSource.setField('fields', fields); + } else { + searchSource.setField('fields', [{ field: '*', include_unmapped: 'true' }]); + } } return searchSource.getSerializedFields(true); }, diff --git a/test/functional/apps/discover/group2/_search_on_page_load.ts b/test/functional/apps/discover/group2/_search_on_page_load.ts index b7011964bc372..2f3ad427335cd 100644 --- a/test/functional/apps/discover/group2/_search_on_page_load.ts +++ b/test/functional/apps/discover/group2/_search_on_page_load.ts @@ -39,7 +39,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { return nrOfFetches === fetchesNumber; }; - describe.only('usage of discover:searchOnPageLoad', () => { + describe('usage of discover:searchOnPageLoad', () => { before(async function () { await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']); log.debug('load kibana index with default index pattern'); From ae290d842ca83ecd18b49c48d8cf71024dba4ac0 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Mon, 16 Jan 2023 11:59:43 +0100 Subject: [PATCH 06/15] Fix search session --- .../main/hooks/use_discover_state.ts | 5 +++-- .../main/hooks/use_search_session.test.ts | 5 ++--- .../main/hooks/use_search_session.ts | 19 +------------------ 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index 9066ac6ece50c..756de4154eeca 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -12,6 +12,7 @@ import { isOfAggregateQueryType } from '@kbn/es-query'; import { type DataView, DataViewType } from '@kbn/data-views-plugin/public'; import { SavedSearch, getSavedSearch } from '@kbn/saved-search-plugin/public'; import type { SortOrder } from '@kbn/saved-search-plugin/public'; +import { useSearchSession } from './use_search_session'; import { FetchStatus } from '../../types'; import { useTextBasedQueryLanguage } from './use_text_based_query_language'; import { useUrlTracking } from './use_url_tracking'; @@ -62,14 +63,14 @@ export function useDiscoverState({ const { setUrlTracking } = useUrlTracking(savedSearch, dataView); - const { appState, replaceUrlAppState } = stateContainer; + const { appState, replaceUrlAppState, searchSessionManager } = stateContainer; const [state, setState] = useState(appState.getState()); /** * Search session logic */ - const searchSessionManager = stateContainer.searchSessionManager; + useSearchSession({ services, stateContainer, savedSearch }); /** * Adhoc data views functionality diff --git a/src/plugins/discover/public/application/main/hooks/use_search_session.test.ts b/src/plugins/discover/public/application/main/hooks/use_search_session.test.ts index 931d652d031c5..4f483a3e01c31 100644 --- a/src/plugins/discover/public/application/main/hooks/use_search_session.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_search_session.test.ts @@ -25,14 +25,13 @@ describe('test useSearchSession', () => { const nextId = 'id'; discoverServiceMock.data.search.session.start = jest.fn(() => nextId); - const { result } = renderHook(() => { + renderHook(() => { return useSearchSession({ services: discoverServiceMock, - history, stateContainer, savedSearch: savedSearchMock, }); }); - expect(result.current.getNextSearchSessionId()).toBe('id'); + expect(stateContainer.searchSessionManager.getNextSearchSessionId()).toBe('id'); }); }); diff --git a/src/plugins/discover/public/application/main/hooks/use_search_session.ts b/src/plugins/discover/public/application/main/hooks/use_search_session.ts index 5592993b90d55..8dadbd9015f1e 100644 --- a/src/plugins/discover/public/application/main/hooks/use_search_session.ts +++ b/src/plugins/discover/public/application/main/hooks/use_search_session.ts @@ -5,11 +5,9 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { useMemo, useEffect } from 'react'; -import { History } from 'history'; +import { useEffect } from 'react'; import { noSearchSessionStorageCapabilityMessage } from '@kbn/data-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; -import { DiscoverSearchSessionManager } from '../services/discover_search_session'; import { createSearchSessionRestorationDataProvider, DiscoverStateContainer, @@ -18,27 +16,14 @@ import { DiscoverServices } from '../../../build_services'; export function useSearchSession({ services, - history, stateContainer, savedSearch, }: { services: DiscoverServices; stateContainer: DiscoverStateContainer; - history: History; savedSearch: SavedSearch; }) { const { data, capabilities } = services; - /** - * Search session logic - */ - const searchSessionManager = useMemo( - () => - new DiscoverSearchSessionManager({ - history, - session: data.search.session, - }), - [data.search.session, history] - ); useEffect(() => { data.search.session.enableStorage( @@ -58,6 +43,4 @@ export function useSearchSession({ } ); }, [capabilities.discover.storeSearchSession, data, savedSearch, stateContainer.appState]); - - return searchSessionManager; } From 96e32ddeb2f96a1e3c1e710e5f38cbdad7ae4874 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Mon, 16 Jan 2023 12:00:29 +0100 Subject: [PATCH 07/15] Fix type error --- .../main/services/discover_data_state_container.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts index 848e31edebb85..3ab0302395a73 100644 --- a/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts @@ -27,7 +27,6 @@ describe('test getDataStateContainer', () => { expect(dataState.data$.main$.getValue().fetchStatus).toBe(FetchStatus.LOADING); expect(dataState.data$.documents$.getValue().fetchStatus).toBe(FetchStatus.LOADING); expect(dataState.data$.totalHits$.getValue().fetchStatus).toBe(FetchStatus.LOADING); - expect(dataState.data$.charts$.getValue().fetchStatus).toBe(FetchStatus.LOADING); }); test('refetch$ triggers a search', async () => { const stateContainer = getDiscoverStateMock({ isTimeBased: true }); From b5f6b59a1869e314398354b481724316eae03952 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Mon, 16 Jan 2023 17:12:12 +0100 Subject: [PATCH 08/15] Fix tests and add comments --- src/plugins/discover/public/__mocks__/services.ts | 4 ++++ .../application/main/hooks/use_discover_state.ts | 1 + .../application/main/services/discover_state.test.ts | 1 + .../application/main/services/discover_state.ts | 2 ++ src/plugins/discover/public/utils/get_sharing_data.ts | 11 +++++------ 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/plugins/discover/public/__mocks__/services.ts b/src/plugins/discover/public/__mocks__/services.ts index d21bc4fc115b3..648ba828489bf 100644 --- a/src/plugins/discover/public/__mocks__/services.ts +++ b/src/plugins/discover/public/__mocks__/services.ts @@ -43,6 +43,10 @@ export function createDiscoverServicesMock(): DiscoverServices { dataPlugin.query.timefilter.timefilter.getTime = jest.fn(() => { return { from: 'now-15m', to: 'now' }; }); + dataPlugin.query.timefilter.timefilter.getRefreshInterval = jest.fn(() => { + return { pause: true, value: 1000 }; + }); + dataPlugin.query.timefilter.timefilter.calculateBounds = jest.fn(calculateBounds); dataPlugin.query.getState = jest.fn(() => ({ query: { query: '', language: 'lucene' }, diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index 756de4154eeca..d9dbca9a9de8e 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -185,6 +185,7 @@ export function useDiscoverState({ dataViewChanged && stateContainer.dataState.initialFetchStatus === FetchStatus.UNINITIALIZED ) { + // stop execution if given data view has changed, and it's not configured to initially start a search in Discover return; } diff --git a/src/plugins/discover/public/application/main/services/discover_state.test.ts b/src/plugins/discover/public/application/main/services/discover_state.test.ts index 8136ced9f4ff3..f3ed93a3394df 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.test.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.test.ts @@ -157,6 +157,7 @@ describe('Test discover state with legacy migration', () => { describe('createSearchSessionRestorationDataProvider', () => { let mockSavedSearch: SavedSearch = {} as unknown as SavedSearch; + history = createBrowserHistory(); const mockDataPlugin = dataPluginMock.createStartContract(); const searchSessionInfoProvider = createSearchSessionRestorationDataProvider({ data: mockDataPlugin, diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts index 1c601ba95001d..7a8493c87c1f9 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -257,6 +257,8 @@ export function getDiscoverStateContainer({ searchSessionManager, getAppState: appStateContainer.getState, getSavedSearch: () => { + // Simulating the behavior of the removed hook to always create a clean searchSource child that + // we then use to add query, filters, etc., will be removed soon. return { ...savedSearch, searchSource: savedSearch.searchSource.createChild() }; }, appStateContainer, diff --git a/src/plugins/discover/public/utils/get_sharing_data.ts b/src/plugins/discover/public/utils/get_sharing_data.ts index 8ad4903e3f7e2..9a32a2431649b 100644 --- a/src/plugins/discover/public/utils/get_sharing_data.ts +++ b/src/plugins/discover/public/utils/get_sharing_data.ts @@ -98,12 +98,11 @@ export async function getSharingData( const useFieldsApi = !config.get(SEARCH_FIELDS_FROM_SOURCE); if (useFieldsApi) { searchSource.removeField('fieldsFromSource'); - if (columns.length) { - const fields = columns.map((field) => ({ field, include_unmapped: 'true' })); - searchSource.setField('fields', fields); - } else { - searchSource.setField('fields', [{ field: '*', include_unmapped: 'true' }]); - } + const fields = columns.length + ? columns.map((field) => ({ field, include_unmapped: 'true' })) + : [{ field: '*', include_unmapped: 'true' }]; + + searchSource.setField('fields', fields); } return searchSource.getSerializedFields(true); }, From 6c6b055cd459c84cf3d5ffc973b93d2ff80e497d Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Mon, 16 Jan 2023 18:06:49 +0100 Subject: [PATCH 09/15] Add documentation --- .../services/discover_data_state_container.ts | 38 ++++++++++++++----- .../main/utils/get_fetch_observable.ts | 2 - 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts index 99e661aae7951..a4c8a3c27fcae 100644 --- a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts @@ -12,7 +12,6 @@ import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { AggregateQuery, Query } from '@kbn/es-query'; import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { ReduxLikeStateContainer } from '@kbn/kibana-utils-plugin/common'; -import { InspectorAdapters } from '../hooks/use_inspector'; import { DataTableRecord } from '../../../types'; import { AppState } from './discover_app_state_container'; import { DiscoverServices } from '../../../build_services'; @@ -39,13 +38,6 @@ export type AvailableFields$ = BehaviorSubject; export type DataRefetch$ = Subject; -export interface UseSavedSearch { - refetch$: DataRefetch$; - data$: SavedSearchData; - reset: () => void; - inspectorAdapters: InspectorAdapters; -} - export enum RecordRawType { /** * Documents returned Elasticsearch, nested structure @@ -87,15 +79,42 @@ export interface DataAvailableFieldsMsg extends DataMsg { } export interface DataStateContainer { + /** + * Implicitly starting fetching data from ES + */ fetch: () => void; + /** + * Container of data observables (orchestration, data table, total hits, available fields) + */ data$: SavedSearchData; + /** + * Observable triggering fetching data from ES + */ refetch$: DataRefetch$; + /** + * Start subscribing to other observables that trigger data fetches + */ subscribe: () => () => void; + /** + * resetting all data observable to initial state + */ reset: () => void; + /** + * Available Inspector Adaptor allowing to get details about recent requests to ES + */ inspectorAdapters: { requests: RequestAdapter }; + /** + * Initial fetch status + * UNINITIALIZED: data is not fetched initially, without user triggering it + * LOADING: data is fetched initially (when Discover is rendered, or data views are switched) + */ initialFetchStatus: FetchStatus; } - +/** + * Container responsible for fetching of data in Discover Main + * Either by triggering requests to Elasticsearch directly, or by + * orchestrating unified plugins / components like the histogram + */ export function getDataStateContainer({ services, searchSessionManager, @@ -155,7 +174,6 @@ export function getDataStateContainer({ refetch$, searchSource: getSavedSearch().searchSource, searchSessionManager, - initialFetchStatus, }); let abortController: AbortController; diff --git a/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts b/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts index 3a5dd042dcfd7..0d94b5746bcae 100644 --- a/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts +++ b/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts @@ -26,7 +26,6 @@ export function getFetch$({ main$, refetch$, searchSessionManager, - initialFetchStatus, }: { setAutoRefreshDone: (val: AutoRefreshDoneFn | undefined) => void; data: DataPublicPluginStart; @@ -34,7 +33,6 @@ export function getFetch$({ refetch$: DataRefetch$; searchSessionManager: DiscoverSearchSessionManager; searchSource: ISearchSource; - initialFetchStatus: FetchStatus; }) { const { timefilter } = data.query.timefilter; const { filterManager } = data.query; From 1e4f2ae24e0be8893af71b38961fd43142bf631b Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Mon, 16 Jan 2023 18:07:19 +0100 Subject: [PATCH 10/15] Remove `use_saved_search.ts` --- .../main/hooks/use_saved_search.test.tsx | 171 ------------ .../main/hooks/use_saved_search.ts | 243 ------------------ 2 files changed, 414 deletions(-) delete mode 100644 src/plugins/discover/public/application/main/hooks/use_saved_search.test.tsx delete mode 100644 src/plugins/discover/public/application/main/hooks/use_saved_search.ts diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search.test.tsx b/src/plugins/discover/public/application/main/hooks/use_saved_search.test.tsx deleted file mode 100644 index c598df55b1d1d..0000000000000 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search.test.tsx +++ /dev/null @@ -1,171 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import { Subject } from 'rxjs'; -import { renderHook } from '@testing-library/react-hooks'; -import { createSearchSessionMock } from '../../../__mocks__/search_session'; -import { discoverServiceMock } from '../../../__mocks__/services'; -import { savedSearchMock, savedSearchMockWithSQL } from '../../../__mocks__/saved_search'; -import { RecordRawType, useSavedSearch } from './use_saved_search'; -import { getDiscoverStateContainer } from '../services/discover_state'; -import { useDiscoverState } from './use_discover_state'; -import { FetchStatus } from '../../types'; -import { setUrlTracker } from '../../../kibana_services'; -import { urlTrackerMock } from '../../../__mocks__/url_tracker.mock'; -import React from 'react'; -import { DiscoverMainProvider } from '../services/discover_state_provider'; - -setUrlTracker(urlTrackerMock); -describe('test useSavedSearch', () => { - test('useSavedSearch return is valid', async () => { - const { history, searchSessionManager } = createSearchSessionMock(); - const stateContainer = getDiscoverStateContainer({ - savedSearch: savedSearchMock, - services: discoverServiceMock, - history, - }); - - const { result } = renderHook(() => { - return useSavedSearch({ - initialFetchStatus: FetchStatus.LOADING, - savedSearch: savedSearchMock, - searchSessionManager, - searchSource: savedSearchMock.searchSource.createCopy(), - services: discoverServiceMock, - stateContainer, - useNewFieldsApi: true, - }); - }); - - expect(result.current.refetch$).toBeInstanceOf(Subject); - expect(result.current.data$.main$.getValue().fetchStatus).toBe(FetchStatus.LOADING); - expect(result.current.data$.documents$.getValue().fetchStatus).toBe(FetchStatus.LOADING); - expect(result.current.data$.totalHits$.getValue().fetchStatus).toBe(FetchStatus.LOADING); - }); - test('refetch$ triggers a search', async () => { - const { history, searchSessionManager } = createSearchSessionMock(); - const stateContainer = getDiscoverStateContainer({ - savedSearch: savedSearchMock, - services: discoverServiceMock, - history, - }); - - discoverServiceMock.data.query.timefilter.timefilter.getTime = jest.fn(() => { - return { from: '2021-05-01T20:00:00Z', to: '2021-05-02T20:00:00Z' }; - }); - - const { result: resultState } = renderHook( - () => { - return useDiscoverState({ - services: discoverServiceMock, - history, - savedSearch: savedSearchMock, - setExpandedDoc: jest.fn(), - }); - }, - { - wrapper: ({ children }: { children: React.ReactElement }) => ( - {children} - ), - } - ); - - const { result, waitForValueToChange } = renderHook(() => { - return useSavedSearch({ - initialFetchStatus: FetchStatus.LOADING, - savedSearch: savedSearchMock, - searchSessionManager, - searchSource: resultState.current.searchSource, - services: discoverServiceMock, - stateContainer, - useNewFieldsApi: true, - }); - }); - - result.current.refetch$.next(undefined); - - await waitForValueToChange(() => { - return result.current.data$.main$.value.fetchStatus === 'complete'; - }); - - expect(result.current.data$.totalHits$.value.result).toBe(0); - expect(result.current.data$.documents$.value.result).toEqual([]); - }); - - test('reset sets back to initial state', async () => { - const { history, searchSessionManager } = createSearchSessionMock(); - const stateContainer = getDiscoverStateContainer({ - savedSearch: savedSearchMock, - services: discoverServiceMock, - history, - }); - - discoverServiceMock.data.query.timefilter.timefilter.getTime = jest.fn(() => { - return { from: '2021-05-01T20:00:00Z', to: '2021-05-02T20:00:00Z' }; - }); - - const { result: resultState } = renderHook( - () => { - return useDiscoverState({ - services: discoverServiceMock, - history, - savedSearch: savedSearchMock, - setExpandedDoc: jest.fn(), - }); - }, - { - wrapper: ({ children }: { children: React.ReactElement }) => ( - {children} - ), - } - ); - - const { result, waitForValueToChange } = renderHook(() => { - return useSavedSearch({ - initialFetchStatus: FetchStatus.LOADING, - savedSearch: savedSearchMock, - searchSessionManager, - searchSource: resultState.current.searchSource, - services: discoverServiceMock, - stateContainer, - useNewFieldsApi: true, - }); - }); - - result.current.refetch$.next(undefined); - - await waitForValueToChange(() => { - return result.current.data$.main$.value.fetchStatus === FetchStatus.COMPLETE; - }); - - result.current.reset(); - expect(result.current.data$.main$.value.fetchStatus).toBe(FetchStatus.LOADING); - }); - - test('useSavedSearch returns plain record raw type', async () => { - const { history, searchSessionManager } = createSearchSessionMock(); - const stateContainer = getDiscoverStateContainer({ - savedSearch: savedSearchMockWithSQL, - services: discoverServiceMock, - history, - }); - - const { result } = renderHook(() => { - return useSavedSearch({ - initialFetchStatus: FetchStatus.LOADING, - savedSearch: savedSearchMockWithSQL, - searchSessionManager, - searchSource: savedSearchMockWithSQL.searchSource.createCopy(), - services: discoverServiceMock, - stateContainer, - useNewFieldsApi: true, - }); - }); - - expect(result.current.data$.main$.getValue().recordRawType).toBe(RecordRawType.PLAIN); - }); -}); diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search.ts deleted file mode 100644 index 7f7e4700925a6..0000000000000 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts +++ /dev/null @@ -1,243 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import { useCallback, useEffect, useMemo, useRef } from 'react'; -import { BehaviorSubject, Subject } from 'rxjs'; -import type { AutoRefreshDoneFn } from '@kbn/data-plugin/public'; -import { ISearchSource } from '@kbn/data-plugin/public'; -import { RequestAdapter } from '@kbn/inspector-plugin/public'; -import { SavedSearch } from '@kbn/saved-search-plugin/public'; -import { AggregateQuery, Query } from '@kbn/es-query'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; -import { getRawRecordType } from '../utils/get_raw_record_type'; -import { DiscoverServices } from '../../../build_services'; -import { DiscoverSearchSessionManager } from '../services/discover_search_session'; -import { DiscoverStateContainer } from '../services/discover_state'; -import { validateTimeRange } from '../utils/validate_time_range'; -import { useSingleton } from './use_singleton'; -import { FetchStatus } from '../../types'; -import { fetchAll } from '../utils/fetch_all'; -import { useBehaviorSubject } from './use_behavior_subject'; -import { sendResetMsg } from './use_saved_search_messages'; -import { getFetch$ } from '../utils/get_fetch_observable'; -import type { DataTableRecord } from '../../../types'; -import type { InspectorAdapters } from './use_inspector'; - -export interface SavedSearchData { - main$: DataMain$; - documents$: DataDocuments$; - totalHits$: DataTotalHits$; - availableFields$: AvailableFields$; -} - -export type DataMain$ = BehaviorSubject; -export type DataDocuments$ = BehaviorSubject; -export type DataTotalHits$ = BehaviorSubject; -export type AvailableFields$ = BehaviorSubject; - -export type DataRefetch$ = Subject; - -export interface UseSavedSearch { - refetch$: DataRefetch$; - data$: SavedSearchData; - reset: () => void; - inspectorAdapters: InspectorAdapters; -} - -export enum RecordRawType { - /** - * Documents returned Elasticsearch, nested structure - */ - DOCUMENT = 'document', - /** - * Data returned e.g. SQL queries, flat structure - * */ - PLAIN = 'plain', -} - -export type DataRefetchMsg = 'reset' | undefined; - -export interface DataMsg { - fetchStatus: FetchStatus; - error?: Error; - recordRawType?: RecordRawType; - query?: AggregateQuery | Query | undefined; -} - -export interface DataMainMsg extends DataMsg { - foundDocuments?: boolean; -} - -export interface DataDocumentsMsg extends DataMsg { - result?: DataTableRecord[]; -} - -export interface DataTotalHitsMsg extends DataMsg { - result?: number; -} - -export interface DataChartsMessage extends DataMsg { - response?: SearchResponse; -} - -export interface DataAvailableFieldsMsg extends DataMsg { - fields?: string[]; -} - -/** - * This hook return 2 observables, refetch$ allows to trigger data fetching, data$ to subscribe - * to the data fetching - */ -export const useSavedSearch = ({ - initialFetchStatus, - savedSearch, - searchSessionManager, - searchSource, - services, - stateContainer, - useNewFieldsApi, -}: { - initialFetchStatus: FetchStatus; - savedSearch: SavedSearch; - searchSessionManager: DiscoverSearchSessionManager; - searchSource: ISearchSource; - services: DiscoverServices; - stateContainer: DiscoverStateContainer; - useNewFieldsApi: boolean; -}) => { - const { data, filterManager } = services; - const timefilter = data.query.timefilter.timefilter; - const { query } = stateContainer.appState.getState(); - - const recordRawType = useMemo(() => getRawRecordType(query), [query]); - - const inspectorAdapters = useMemo(() => ({ requests: new RequestAdapter() }), []); - - /** - * The observables the UI (aka React component) subscribes to get notified about - * the changes in the data fetching process (high level: fetching started, data was received) - */ - const initialState = { fetchStatus: initialFetchStatus, recordRawType }; - const main$: DataMain$ = useBehaviorSubject(initialState) as DataMain$; - const documents$: DataDocuments$ = useBehaviorSubject(initialState) as DataDocuments$; - const totalHits$: DataTotalHits$ = useBehaviorSubject(initialState) as DataTotalHits$; - const availableFields$: AvailableFields$ = useBehaviorSubject(initialState) as AvailableFields$; - - const dataSubjects = useMemo(() => { - return { - main$, - documents$, - totalHits$, - availableFields$, - }; - }, [main$, documents$, totalHits$, availableFields$]); - - /** - * The observable to trigger data fetching in UI - * By refetch$.next('reset') rows and fieldcounts are reset to allow e.g. editing of runtime fields - * to be processed correctly - */ - const refetch$ = useSingleton(() => new Subject()); - - /** - * Values that shouldn't trigger re-rendering when changed - */ - const refs = useRef<{ - autoRefreshDone?: AutoRefreshDoneFn; - }>({}); - - /** - * This part takes care of triggering the data fetching by creating and subscribing - * to an observable of various possible changes in state - */ - useEffect(() => { - /** - * handler emitted by `timefilter.getAutoRefreshFetch$()` - * to notify when data completed loading and to start a new autorefresh loop - */ - const setAutoRefreshDone = (fn: AutoRefreshDoneFn | undefined) => { - refs.current.autoRefreshDone = fn; - }; - const fetch$ = getFetch$({ - setAutoRefreshDone, - data, - main$, - refetch$, - searchSessionManager, - searchSource, - initialFetchStatus, - }); - let abortController: AbortController; - - const subscription = fetch$.subscribe(async (val) => { - if (!validateTimeRange(timefilter.getTime(), services.toastNotifications)) { - return; - } - inspectorAdapters.requests.reset(); - - abortController?.abort(); - abortController = new AbortController(); - const autoRefreshDone = refs.current.autoRefreshDone; - - await fetchAll(dataSubjects, searchSource, val === 'reset', { - abortController, - appStateContainer: stateContainer.appState, - data, - initialFetchStatus, - inspectorAdapters, - savedSearch, - searchSessionId: searchSessionManager.getNextSearchSessionId(), - services, - useNewFieldsApi, - }); - - // If the autoRefreshCallback is still the same as when we started i.e. there was no newer call - // replacing this current one, call it to make sure we tell that the auto refresh is done - // and a new one can be scheduled. - if (autoRefreshDone === refs.current.autoRefreshDone) { - // if this function was set and is executed, another refresh fetch can be triggered - refs.current.autoRefreshDone?.(); - refs.current.autoRefreshDone = undefined; - } - }); - - return () => { - abortController?.abort(); - subscription.unsubscribe(); - }; - }, [ - data, - data.query.queryString, - dataSubjects, - filterManager, - initialFetchStatus, - inspectorAdapters, - main$, - refetch$, - savedSearch, - searchSessionManager, - searchSessionManager.newSearchSessionIdFromURL$, - searchSource, - services, - services.toastNotifications, - stateContainer.appState, - timefilter, - useNewFieldsApi, - ]); - - const reset = useCallback( - () => sendResetMsg(dataSubjects, initialFetchStatus), - [dataSubjects, initialFetchStatus] - ); - - return { - refetch$, - data$: dataSubjects, - reset, - inspectorAdapters, - }; -}; From 2202d1d318b72d58006662d1c034282ae1c4ab00 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Mon, 16 Jan 2023 19:22:49 +0100 Subject: [PATCH 11/15] Fix types --- .../components/field_stats_table/field_stats_table.tsx | 6 +++++- .../components/layout/__stories__/get_layout_props.ts | 2 +- .../main/components/layout/discover_documents.test.tsx | 2 +- .../main/components/layout/discover_documents.tsx | 2 +- .../components/layout/discover_histogram_layout.test.tsx | 2 +- .../main/components/layout/discover_layout.test.tsx | 2 +- .../main/components/layout/discover_layout.tsx | 2 +- .../main/components/layout/discover_main_content.test.tsx | 2 +- .../main/components/layout/discover_main_content.tsx | 2 +- .../public/application/main/components/layout/types.ts | 2 +- .../components/layout/use_discover_histogram.test.tsx | 2 +- .../main/components/layout/use_discover_histogram.ts | 2 +- .../deprecated_stats/discover_field_details.test.tsx | 2 +- .../sidebar/deprecated_stats/discover_field_details.tsx | 2 +- .../main/components/sidebar/discover_field.test.tsx | 2 +- .../main/components/sidebar/discover_field.tsx | 2 +- .../main/components/sidebar/discover_sidebar.test.tsx | 2 +- .../main/components/sidebar/discover_sidebar.tsx | 2 +- .../sidebar/discover_sidebar_responsive.test.tsx | 6 +++++- .../components/sidebar/discover_sidebar_responsive.tsx | 6 +++++- .../public/application/main/hooks/use_data_state.ts | 2 +- .../main/hooks/use_saved_search_messages.test.ts | 2 +- .../application/main/hooks/use_saved_search_messages.ts | 3 +-- .../main/hooks/use_test_based_query_language.test.ts | 2 +- .../main/hooks/use_text_based_query_language.ts | 2 +- .../main/services/discover_data_state_container.ts | 8 ++++---- .../public/application/main/utils/fetch_all.test.ts | 3 +-- .../discover/public/application/main/utils/fetch_all.ts | 2 +- .../public/application/main/utils/get_fetch_observable.ts | 2 +- .../application/main/utils/get_fetch_observeable.test.ts | 4 +--- .../application/main/utils/get_raw_record_type.test.ts | 2 +- .../public/application/main/utils/get_raw_record_type.ts | 2 +- .../public/embeddable/saved_search_embeddable.tsx | 2 +- 33 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx index 88479e0ee10b0..745bf0cc754a3 100644 --- a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx +++ b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx @@ -23,7 +23,11 @@ import { css } from '@emotion/react'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { FIELD_STATISTICS_LOADED } from './constants'; import type { DiscoverStateContainer } from '../../services/discover_state'; -import { AvailableFields$, DataRefetch$, DataTotalHits$ } from '../../hooks/use_saved_search'; +import { + AvailableFields$, + DataRefetch$, + DataTotalHits$, +} from '../../services/discover_data_state_container'; export interface RandomSamplingOption { mode: 'random_sampling'; seed: string; diff --git a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts index f5b64ebf85adc..3d7e72b32bb12 100644 --- a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts +++ b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts @@ -18,7 +18,7 @@ import { DataMain$, DataTotalHits$, RecordRawType, -} from '../../../hooks/use_saved_search'; +} from '../../../services/discover_data_state_container'; import { buildDataTableRecordList } from '../../../../../utils/build_data_record'; import { esHits } from '../../../../../__mocks__/es_hits'; import { SavedSearch } from '../../../../..'; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx index c6af7846a4d23..3683278523e91 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx @@ -13,7 +13,7 @@ import { setHeaderActionMenuMounter } from '../../../../kibana_services'; import { esHits } from '../../../../__mocks__/es_hits'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; import { DiscoverStateContainer } from '../../services/discover_state'; -import { DataDocuments$ } from '../../hooks/use_saved_search'; +import { DataDocuments$ } from '../../services/discover_data_state_container'; import { discoverServiceMock } from '../../../../__mocks__/services'; import { FetchStatus } from '../../../types'; import { DiscoverDocuments, onResize } from './discover_documents'; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx index fbded519b956a..5a7f030f22e18 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx @@ -29,7 +29,7 @@ import { HIDE_ANNOUNCEMENTS, } from '../../../../../common'; import { useColumns } from '../../../../hooks/use_data_grid_columns'; -import { DataDocuments$, RecordRawType } from '../../hooks/use_saved_search'; +import { DataDocuments$, RecordRawType } from '../../services/discover_data_state_container'; import { DiscoverStateContainer } from '../../services/discover_state'; import { useDataState } from '../../hooks/use_data_state'; import { DocTableInfinite } from '../../../../components/doc_table/doc_table_infinite'; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx index 48eeaaaef4ac8..95adf8d6cc46d 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx @@ -18,7 +18,7 @@ import { DataMain$, DataTotalHits$, RecordRawType, -} from '../../hooks/use_saved_search'; +} from '../../services/discover_data_state_container'; import { discoverServiceMock } from '../../../../__mocks__/services'; import { FetchStatus } from '../../../types'; import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx index 6a9bd2d381d98..ce2cdf41ff444 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx @@ -28,7 +28,7 @@ import { DataRefetch$, DataTotalHits$, RecordRawType, -} from '../../hooks/use_saved_search'; +} from '../../services/discover_data_state_container'; import { createDiscoverServicesMock } from '../../../../__mocks__/services'; import { FetchStatus } from '../../../types'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index c9f52bd548f25..0266272fad058 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -38,7 +38,7 @@ import { DiscoverTopNav } from '../top_nav/discover_topnav'; import { DocViewFilterFn } from '../../../../services/doc_views/doc_views_types'; import { getResultState } from '../../utils/get_result_state'; import { DiscoverUninitialized } from '../uninitialized/uninitialized'; -import { DataMainMsg, RecordRawType } from '../../hooks/use_saved_search'; +import { DataMainMsg, RecordRawType } from '../../services/discover_data_state_container'; import { useColumns } from '../../../../hooks/use_data_grid_columns'; import { FetchStatus } from '../../../types'; import { useDataState } from '../../hooks/use_data_state'; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx index a98d3cd85bbb4..e1e986e37aa1e 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx @@ -18,7 +18,7 @@ import { DataMain$, DataTotalHits$, RecordRawType, -} from '../../hooks/use_saved_search'; +} from '../../services/discover_data_state_container'; import { createDiscoverServicesMock } from '../../../../__mocks__/services'; import { FetchStatus } from '../../../types'; import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx index f91de3b2a02d3..fed7278d97b41 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx @@ -16,7 +16,7 @@ import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DataTableRecord } from '../../../../types'; import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle'; import { DocViewFilterFn } from '../../../../services/doc_views/doc_views_types'; -import { DataRefetch$, SavedSearchData } from '../../hooks/use_saved_search'; +import { DataRefetch$, SavedSearchData } from '../../services/discover_data_state_container'; import { DiscoverStateContainer } from '../../services/discover_state'; import { FieldStatisticsTab } from '../field_stats_table'; import { DiscoverDocuments } from './discover_documents'; diff --git a/src/plugins/discover/public/application/main/components/layout/types.ts b/src/plugins/discover/public/application/main/components/layout/types.ts index f2a8ebe9269e8..bb3383a916525 100644 --- a/src/plugins/discover/public/application/main/components/layout/types.ts +++ b/src/plugins/discover/public/application/main/components/layout/types.ts @@ -12,7 +12,7 @@ import type { ISearchSource } from '@kbn/data-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { DataTableRecord } from '../../../../types'; import { DiscoverStateContainer } from '../../services/discover_state'; -import { DataRefetch$, SavedSearchData } from '../../hooks/use_saved_search'; +import { DataRefetch$, SavedSearchData } from '../../services/discover_data_state_container'; import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; import type { InspectorAdapters } from '../../hooks/use_inspector'; diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx index 950b2d4571a40..1a75dfdb75f60 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx @@ -17,7 +17,7 @@ import { DataMain$, DataTotalHits$, RecordRawType, -} from '../../hooks/use_saved_search'; +} from '../../services/discover_data_state_container'; import type { DiscoverStateContainer } from '../../services/discover_state'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts index 53ddc74ad99d6..a4e6472eb62b4 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts @@ -21,7 +21,7 @@ import { useAppStateSelector } from '../../services/discover_app_state_container import { getUiActions } from '../../../../kibana_services'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { useDataState } from '../../hooks/use_data_state'; -import type { SavedSearchData } from '../../hooks/use_saved_search'; +import type { SavedSearchData } from '../../services/discover_data_state_container'; import type { DiscoverStateContainer } from '../../services/discover_state'; import { FetchStatus } from '../../../types'; import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; diff --git a/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx index 535459c880988..e31445344b82b 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx @@ -15,7 +15,7 @@ import { DataViewField } from '@kbn/data-views-plugin/public'; import { stubDataView, stubLogstashDataView } from '@kbn/data-views-plugin/common/data_view.stub'; import { BehaviorSubject } from 'rxjs'; import { FetchStatus } from '../../../../types'; -import { DataDocuments$ } from '../../../hooks/use_saved_search'; +import { DataDocuments$ } from '../../../services/discover_data_state_container'; import { getDataTableRecords } from '../../../../../__fixtures__/real_hits'; describe('discover sidebar field details', function () { diff --git a/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx index d1f32ae8df8fb..0a3d1b5c58072 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx @@ -14,8 +14,8 @@ import { DataViewField, DataView } from '@kbn/data-views-plugin/public'; import { DiscoverFieldBucket } from './discover_field_bucket'; import { Bucket } from './types'; import { getDetails, isValidFieldDetails } from './get_details'; -import { DataDocuments$ } from '../../../hooks/use_saved_search'; import { FetchStatus } from '../../../../types'; +import { DataDocuments$ } from '../../../services/discover_data_state_container'; interface DiscoverFieldDetailsProps { /** diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx index c25a6c5010e7e..88a5660db3017 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx @@ -19,7 +19,7 @@ import { stubDataView } from '@kbn/data-views-plugin/common/data_view.stub'; import { DiscoverAppStateProvider } from '../../services/discover_app_state_container'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; import { FetchStatus } from '../../../types'; -import { DataDocuments$ } from '../../hooks/use_saved_search'; +import { DataDocuments$ } from '../../services/discover_data_state_container'; import { getDataTableRecords } from '../../../../__fixtures__/real_hits'; import * as DetailsUtil from './deprecated_stats/get_details'; import { createDiscoverServicesMock } from '../../../../__mocks__/services'; diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx index 89b143cf46cd3..3c4567bdc66dc 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx @@ -36,7 +36,7 @@ import { getFieldTypeName } from '../../../../utils/get_field_type_name'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { SHOW_LEGACY_FIELD_TOP_VALUES, PLUGIN_ID } from '../../../../../common'; import { getUiActions } from '../../../../kibana_services'; -import { type DataDocuments$ } from '../../hooks/use_saved_search'; +import { type DataDocuments$ } from '../../services/discover_data_state_container'; const FieldInfoIcon: React.FC = memo(() => ( (data$: BehaviorSubject) { const [fetchState, setFetchState] = useState(data$.getValue()); diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts index 5973d679b6b1c..4f22bf84147f1 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts @@ -16,7 +16,7 @@ import { } from './use_saved_search_messages'; import { FetchStatus } from '../../types'; import { BehaviorSubject } from 'rxjs'; -import { DataMainMsg, RecordRawType } from './use_saved_search'; +import { DataMainMsg, RecordRawType } from '../services/discover_data_state_container'; import { filter } from 'rxjs/operators'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts index ab121f76e15a0..cd69acf4fe21d 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts @@ -15,8 +15,7 @@ import type { DataMsg, DataTotalHits$, SavedSearchData, -} from './use_saved_search'; - +} from '../services/discover_data_state_container'; /** * Sends COMPLETE message to the main$ observable with the information * that no documents have been found, allowing Discover to show a no diff --git a/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts b/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts index db94bd6638568..0f1b6488f3681 100644 --- a/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts @@ -13,7 +13,7 @@ import { discoverServiceMock } from '../../../__mocks__/services'; import { useTextBasedQueryLanguage } from './use_text_based_query_language'; import { BehaviorSubject } from 'rxjs'; import { FetchStatus } from '../../types'; -import { DataDocuments$, RecordRawType } from './use_saved_search'; +import { DataDocuments$, RecordRawType } from '../services/discover_data_state_container'; import { DataTableRecord } from '../../../types'; import { AggregateQuery, Query } from '@kbn/es-query'; import { dataViewMock } from '../../../__mocks__/data_view'; diff --git a/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts b/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts index 220a3f1702faa..b47c7145904bf 100644 --- a/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts +++ b/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts @@ -16,7 +16,7 @@ import { useCallback, useEffect, useRef } from 'react'; import type { DataViewsContract } from '@kbn/data-views-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import type { DiscoverStateContainer } from '../services/discover_state'; -import type { DataDocuments$ } from './use_saved_search'; +import type { DataDocuments$ } from '../services/discover_data_state_container'; import { FetchStatus } from '../../types'; const MAX_NUM_OF_COLUMNS = 50; diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts index a4c8a3c27fcae..6d2a0b94a5c4b 100644 --- a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts @@ -6,23 +6,23 @@ * Side Public License, v 1. */ import { BehaviorSubject, Subject } from 'rxjs'; -import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { AutoRefreshDoneFn } from '@kbn/data-plugin/public'; +import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { AggregateQuery, Query } from '@kbn/es-query'; import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { ReduxLikeStateContainer } from '@kbn/kibana-utils-plugin/common'; -import { DataTableRecord } from '../../../types'; +import { getRawRecordType } from '../utils/get_raw_record_type'; import { AppState } from './discover_app_state_container'; import { DiscoverServices } from '../../../build_services'; import { DiscoverSearchSessionManager } from './discover_search_session'; -import { getRawRecordType } from '../utils/get_raw_record_type'; import { SEARCH_FIELDS_FROM_SOURCE, SEARCH_ON_PAGE_LOAD_SETTING } from '../../../../common'; import { FetchStatus } from '../../types'; -import { getFetch$ } from '../utils/get_fetch_observable'; import { validateTimeRange } from '../utils/validate_time_range'; import { fetchAll } from '../utils/fetch_all'; import { sendResetMsg } from '../hooks/use_saved_search_messages'; +import { getFetch$ } from '../utils/get_fetch_observable'; +import { DataTableRecord } from '../../../types'; export interface SavedSearchData { main$: DataMain$; diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts index b11389c24b054..95b1cd7618b4d 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts @@ -21,8 +21,7 @@ import { DataTotalHitsMsg, RecordRawType, SavedSearchData, -} from '../hooks/use_saved_search'; - +} from '../services/discover_data_state_container'; import { fetchDocuments } from './fetch_documents'; import { fetchSql } from './fetch_sql'; import { buildDataTableRecord } from '../../../utils/build_data_record'; diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.ts b/src/plugins/discover/public/application/main/utils/fetch_all.ts index f698d999662ce..c2a3c0856af06 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.ts @@ -23,7 +23,7 @@ import { import { updateSearchSource } from './update_search_source'; import { fetchDocuments } from './fetch_documents'; import { FetchStatus } from '../../types'; -import { DataMsg, RecordRawType, SavedSearchData } from '../hooks/use_saved_search'; +import { DataMsg, RecordRawType, SavedSearchData } from '../services/discover_data_state_container'; import { DiscoverServices } from '../../../build_services'; import { fetchSql } from './fetch_sql'; diff --git a/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts b/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts index 0d94b5746bcae..71490f05ac6ce 100644 --- a/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts +++ b/src/plugins/discover/public/application/main/utils/get_fetch_observable.ts @@ -14,7 +14,7 @@ import type { ISearchSource, } from '@kbn/data-plugin/public'; import { FetchStatus } from '../../types'; -import { DataMain$, DataRefetch$ } from '../hooks/use_saved_search'; +import { DataMain$, DataRefetch$ } from '../services/discover_data_state_container'; import { DiscoverSearchSessionManager } from '../services/discover_search_session'; /** diff --git a/src/plugins/discover/public/application/main/utils/get_fetch_observeable.test.ts b/src/plugins/discover/public/application/main/utils/get_fetch_observeable.test.ts index 67dc63b421706..10e1b397dc657 100644 --- a/src/plugins/discover/public/application/main/utils/get_fetch_observeable.test.ts +++ b/src/plugins/discover/public/application/main/utils/get_fetch_observeable.test.ts @@ -11,7 +11,7 @@ import { getFetch$ } from './get_fetch_observable'; import { FetchStatus } from '../../types'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { createSearchSessionMock } from '../../../__mocks__/search_session'; -import { DataRefetch$ } from '../hooks/use_saved_search'; +import { DataRefetch$ } from '../services/discover_data_state_container'; import { savedSearchMock, savedSearchMockWithTimeField } from '../../../__mocks__/saved_search'; function createDataMock( @@ -63,7 +63,6 @@ describe('getFetchObservable', () => { data: createDataMock(new Subject(), new Subject(), new Subject(), new Subject()), searchSessionManager: searchSessionManagerMock.searchSessionManager, searchSource: savedSearchMock.searchSource, - initialFetchStatus: FetchStatus.LOADING, }); fetch$.subscribe(() => { @@ -95,7 +94,6 @@ describe('getFetchObservable', () => { data: dataMock, searchSessionManager: searchSessionManagerMock.searchSessionManager, searchSource: savedSearchMockWithTimeField.searchSource, - initialFetchStatus: FetchStatus.LOADING, }); const fetchfnMock = jest.fn(); diff --git a/src/plugins/discover/public/application/main/utils/get_raw_record_type.test.ts b/src/plugins/discover/public/application/main/utils/get_raw_record_type.test.ts index 879ece28a527f..146a5a80a125f 100644 --- a/src/plugins/discover/public/application/main/utils/get_raw_record_type.test.ts +++ b/src/plugins/discover/public/application/main/utils/get_raw_record_type.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { RecordRawType } from '../hooks/use_saved_search'; +import { RecordRawType } from '../services/discover_data_state_container'; import { getRawRecordType } from './get_raw_record_type'; describe('getRawRecordType', () => { diff --git a/src/plugins/discover/public/application/main/utils/get_raw_record_type.ts b/src/plugins/discover/public/application/main/utils/get_raw_record_type.ts index 8a2fc81f06a82..356939e4f2dfd 100644 --- a/src/plugins/discover/public/application/main/utils/get_raw_record_type.ts +++ b/src/plugins/discover/public/application/main/utils/get_raw_record_type.ts @@ -12,7 +12,7 @@ import { isOfAggregateQueryType, getAggregateQueryMode, } from '@kbn/es-query'; -import { RecordRawType } from '../hooks/use_saved_search'; +import { RecordRawType } from '../services/discover_data_state_container'; export function getRawRecordType(query?: Query | AggregateQuery) { if (query && isOfAggregateQueryType(query) && getAggregateQueryMode(query) === 'sql') { diff --git a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx index 96c23d085afcf..80527141cde3a 100644 --- a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx +++ b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx @@ -37,7 +37,7 @@ import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { METRIC_TYPE } from '@kbn/analytics'; import { VIEW_MODE } from '../../common/constants'; import { getSortForEmbeddable, SortPair } from '../utils/sorting'; -import { RecordRawType } from '../application/main/hooks/use_saved_search'; +import { RecordRawType } from '../application/main/services/discover_data_state_container'; import { buildDataTableRecord } from '../utils/build_data_record'; import { DataTableRecord, EsHitRecord } from '../types'; import { ISearchEmbeddable, SearchInput, SearchOutput } from './types'; From 47e8f276b84dc038270c152af03ee4c69945342f Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 18 Jan 2023 18:56:47 +0000 Subject: [PATCH 12/15] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../public/application/main/components/layout/types.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/discover/public/application/main/components/layout/types.ts b/src/plugins/discover/public/application/main/components/layout/types.ts index 734b6b65cf708..e0f1ec594d1ae 100644 --- a/src/plugins/discover/public/application/main/components/layout/types.ts +++ b/src/plugins/discover/public/application/main/components/layout/types.ts @@ -12,7 +12,11 @@ import type { ISearchSource } from '@kbn/data-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { DataTableRecord } from '../../../../types'; import { DiscoverStateContainer } from '../../services/discover_state'; -import { DataFetch$, DataRefetch$, SavedSearchData } from '../../services/discover_data_state_container'; +import { + DataFetch$, + DataRefetch$, + SavedSearchData, +} from '../../services/discover_data_state_container'; import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; import type { InspectorAdapters } from '../../hooks/use_inspector'; From 2b3a5d2eec213631d2bef29c2558ee69d7547685 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Wed, 18 Jan 2023 20:13:19 +0100 Subject: [PATCH 13/15] Cleanup code --- .../field_stats_table/field_stats_table.tsx | 27 +++++++------------ .../layout/discover_documents.test.tsx | 4 +-- .../components/layout/discover_documents.tsx | 5 ++-- .../layout/discover_histogram_layout.test.tsx | 6 ++--- .../layout/discover_histogram_layout.tsx | 8 ++---- .../layout/discover_layout.test.tsx | 9 ++----- .../components/layout/discover_layout.tsx | 25 +++++++---------- .../layout/discover_main_content.test.tsx | 5 ++-- .../layout/discover_main_content.tsx | 9 ------- .../main/components/layout/types.ts | 4 --- .../application/main/discover_main_app.tsx | 6 ----- .../main/hooks/use_discover_state.ts | 5 +--- 12 files changed, 32 insertions(+), 81 deletions(-) diff --git a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx index 745bf0cc754a3..bf28344aed402 100644 --- a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx +++ b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx @@ -23,11 +23,7 @@ import { css } from '@emotion/react'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { FIELD_STATISTICS_LOADED } from './constants'; import type { DiscoverStateContainer } from '../../services/discover_state'; -import { - AvailableFields$, - DataRefetch$, - DataTotalHits$, -} from '../../services/discover_data_state_container'; +import { DataTotalHits$ } from '../../services/discover_data_state_container'; export interface RandomSamplingOption { mode: 'random_sampling'; seed: string; @@ -110,15 +106,12 @@ export interface FieldStatisticsTableProps { * @param eventName */ trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; - savedSearchRefetch$?: DataRefetch$; - availableFields$?: AvailableFields$; searchSessionId?: string; savedSearchDataTotalHits$?: DataTotalHits$; } export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { const { - availableFields$, dataView, savedSearch, query, @@ -127,10 +120,9 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { stateContainer, onAddFilter, trackUiMetric, - savedSearchRefetch$, searchSessionId, - savedSearchDataTotalHits$, } = props; + const totalHits$ = stateContainer?.dataState.data$.totalHits$; const services = useDiscoverServices(); const [embeddable, setEmbeddable] = useState< | ErrorEmbeddable @@ -145,13 +137,14 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { ); useEffect(() => { + const availableFields$ = stateContainer?.dataState.data$.availableFields$; const sub = embeddable?.getOutput$().subscribe((output: DataVisualizerGridEmbeddableOutput) => { if (output.showDistributions !== undefined && stateContainer) { stateContainer.setAppState({ hideAggregatedPreview: !output.showDistributions }); } }); - const refetch = savedSearchRefetch$?.subscribe(() => { + const refetch = stateContainer?.dataState.refetch$.subscribe(() => { if (embeddable && !isErrorEmbeddable(embeddable)) { embeddable.updateInput({ lastReloadRequestTime: Date.now() }); } @@ -168,7 +161,7 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { refetch?.unsubscribe(); fields?.unsubscribe(); }; - }, [embeddable, stateContainer, savedSearchRefetch$, availableFields$]); + }, [embeddable, stateContainer]); useEffect(() => { if (embeddable && !isErrorEmbeddable(embeddable)) { @@ -181,10 +174,8 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { visibleFieldNames: columns, onAddFilter, sessionId: searchSessionId, - fieldsToFetch: availableFields$?.getValue().fields, - totalDocuments: savedSearchDataTotalHits$ - ? savedSearchDataTotalHits$.getValue()?.result - : undefined, + fieldsToFetch: stateContainer?.dataState.data$.availableFields$?.getValue().fields, + totalDocuments: totalHits$ ? totalHits$.getValue()?.result : undefined, samplingOption: { mode: 'normal_sampling', shardSize: 5000, @@ -202,8 +193,8 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { filters, onAddFilter, searchSessionId, - availableFields$, - savedSearchDataTotalHits$, + totalHits$, + stateContainer, ]); useEffect(() => { diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx index 3683278523e91..d73c1163c8a0f 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx @@ -39,14 +39,14 @@ function mountComponent(fetchStatus: FetchStatus, hits: EsHitRecord[]) { }) as DataDocuments$; const stateContainer = getDiscoverStateMock({}); stateContainer.setAppState({ index: dataViewMock.id }); + stateContainer.dataState.data$.documents$ = documents$; const props = { expandedDoc: undefined, dataView: dataViewMock, onAddFilter: jest.fn(), savedSearch: savedSearchMock, - documents$, - searchSource: documents$, + searchSource: savedSearchMock.searchSource, setExpandedDoc: jest.fn(), state: { columns: [] }, stateContainer, diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx index 5a7f030f22e18..647a6561b7cf0 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx @@ -29,7 +29,7 @@ import { HIDE_ANNOUNCEMENTS, } from '../../../../../common'; import { useColumns } from '../../../../hooks/use_data_grid_columns'; -import { DataDocuments$, RecordRawType } from '../../services/discover_data_state_container'; +import { RecordRawType } from '../../services/discover_data_state_container'; import { DiscoverStateContainer } from '../../services/discover_state'; import { useDataState } from '../../hooks/use_data_state'; import { DocTableInfinite } from '../../../../components/doc_table/doc_table_infinite'; @@ -59,7 +59,6 @@ export const onResize = ( }; function DiscoverDocumentsComponent({ - documents$, expandedDoc, dataView, onAddFilter, @@ -68,7 +67,6 @@ function DiscoverDocumentsComponent({ stateContainer, onFieldEdited, }: { - documents$: DataDocuments$; expandedDoc?: DataTableRecord; dataView: DataView; navigateTo: (url: string) => void; @@ -79,6 +77,7 @@ function DiscoverDocumentsComponent({ onFieldEdited?: () => void; }) { const services = useDiscoverServices(); + const documents$ = stateContainer.dataState.data$.documents$; const { dataViews, capabilities, uiSettings } = services; const [query, sort, rowHeight, rowsPerPage, grid, columns, index] = useAppStateSelector( (state) => { diff --git a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx index f88292413a316..765e8edfcdbaf 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { Subject, BehaviorSubject, of } from 'rxjs'; +import { BehaviorSubject, of } from 'rxjs'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { esHits } from '../../../../__mocks__/es_hits'; import { dataViewMock } from '../../../../__mocks__/data_view'; @@ -117,6 +117,7 @@ const mountComponent = ({ session.getSession$.mockReturnValue(new BehaviorSubject('123')); const stateContainer = getStateContainer(); + stateContainer.dataState.data$ = savedSearchData$; const props: DiscoverHistogramLayoutProps = { isPlainRecord, @@ -124,9 +125,6 @@ const mountComponent = ({ navigateTo: jest.fn(), setExpandedDoc: jest.fn(), savedSearch, - savedSearchData$, - savedSearchFetch$: new Subject(), - savedSearchRefetch$: new Subject(), stateContainer, onFieldEdited: jest.fn(), columns: [], diff --git a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx index 68a7d9cb98ef5..28a6d6c051787 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx @@ -15,7 +15,6 @@ import type { DiscoverSearchSessionManager } from '../../services/discover_searc import type { InspectorAdapters } from '../../hooks/use_inspector'; import { type DiscoverMainContentProps, DiscoverMainContent } from './discover_main_content'; import { ResetSearchButton } from './reset_search_button'; -import { DataFetch$ } from '../../services/discover_data_state_container'; export interface DiscoverHistogramLayoutProps extends DiscoverMainContentProps { resetSavedSearch: () => void; @@ -23,7 +22,6 @@ export interface DiscoverHistogramLayoutProps extends DiscoverMainContentProps { resizeRef: RefObject; inspectorAdapters: InspectorAdapters; searchSessionManager: DiscoverSearchSessionManager; - savedSearchFetch$: DataFetch$; } export const DiscoverHistogramLayout = ({ @@ -31,8 +29,6 @@ export const DiscoverHistogramLayout = ({ dataView, resetSavedSearch, savedSearch, - savedSearchData$, - savedSearchFetch$, stateContainer, isTimeBased, resizeRef, @@ -47,14 +43,14 @@ export const DiscoverHistogramLayout = ({ isPlainRecord, stateContainer, savedSearch, - savedSearchData$, + savedSearchData$: stateContainer.dataState.data$, }; const histogramProps = useDiscoverHistogram({ isTimeBased, inspectorAdapters, searchSessionManager, - savedSearchFetch$, + savedSearchFetch$: stateContainer.dataState.fetch$, ...commonProps, }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx index 15d4bb2e49739..13994b401b044 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { Subject, BehaviorSubject, of } from 'rxjs'; +import { BehaviorSubject, of } from 'rxjs'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import type { Query, AggregateQuery } from '@kbn/es-query'; import { setHeaderActionMenuMounter } from '../../../../kibana_services'; @@ -24,9 +24,7 @@ import { dataViewWithTimefieldMock } from '../../../../__mocks__/data_view_with_ import { AvailableFields$, DataDocuments$, - DataFetch$, DataMain$, - DataRefetch$, DataTotalHits$, RecordRawType, } from '../../services/discover_data_state_container'; @@ -93,7 +91,7 @@ function mountComponent( result: Number(esHits.length), }) as DataTotalHits$; - const savedSearchData$ = { + stateContainer.dataState.data$ = { main$, documents$, totalHits$, @@ -115,9 +113,6 @@ function mountComponent( onUpdateQuery: jest.fn(), resetSavedSearch: jest.fn(), savedSearch: savedSearchMock, - savedSearchData$, - savedSearchFetch$: new Subject() as DataFetch$, - savedSearchRefetch$: new Subject() as DataRefetch$, searchSource: searchSourceMock, state: { columns: [], query, hideChart: false, interval: 'auto' }, stateContainer, diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index 8529b4721a2a7..8f1dcc4ba8dfb 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -62,10 +62,7 @@ export function DiscoverLayout({ onChangeDataView, onUpdateQuery, setExpandedDoc, - savedSearchFetch$, - savedSearchRefetch$, resetSavedSearch, - savedSearchData$, savedSearch, searchSource, stateContainer, @@ -86,7 +83,7 @@ export function DiscoverLayout({ spaces, inspector, } = useDiscoverServices(); - const { main$ } = savedSearchData$; + const { main$ } = stateContainer.dataState.data$; const [query, savedQuery, filters, columns, sort] = useAppStateSelector((state) => [ state.query, state.savedQuery, @@ -166,8 +163,8 @@ export function DiscoverLayout({ if (!dataView.isPersisted()) { await updateAdHocDataViewId(dataView); } - savedSearchRefetch$.next('reset'); - }, [dataView, savedSearchRefetch$, updateAdHocDataViewId]); + stateContainer.dataState.refetch$.next('reset'); + }, [dataView, stateContainer, updateAdHocDataViewId]); const onDisableFilters = useCallback(() => { const disabledFilters = filterManager @@ -224,7 +221,11 @@ export function DiscoverLayout({ } if (resultState === 'uninitialized') { - return savedSearchRefetch$.next(undefined)} />; + return ( + stateContainer.dataState.refetch$.next(undefined)} + /> + ); } return ( @@ -237,9 +238,6 @@ export function DiscoverLayout({ expandedDoc={expandedDoc} setExpandedDoc={setExpandedDoc} savedSearch={savedSearch} - savedSearchData$={savedSearchData$} - savedSearchFetch$={savedSearchFetch$} - savedSearchRefetch$={savedSearchRefetch$} stateContainer={stateContainer} isTimeBased={isTimeBased} columns={currentColumns} @@ -271,9 +269,6 @@ export function DiscoverLayout({ resetSavedSearch, resultState, savedSearch, - savedSearchData$, - savedSearchFetch$, - savedSearchRefetch$, searchSessionManager, setExpandedDoc, stateContainer, @@ -328,7 +323,7 @@ export function DiscoverLayout({ diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx index e1e986e37aa1e..054fc36cdbc3e 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { Subject, BehaviorSubject, of } from 'rxjs'; +import { BehaviorSubject, of } from 'rxjs'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { esHits } from '../../../../__mocks__/es_hits'; import { dataViewMock } from '../../../../__mocks__/data_view'; @@ -89,6 +89,7 @@ const mountComponent = ({ availableFields$, }; const stateContainer = getDiscoverStateMock({ isTimeBased: true }); + stateContainer.dataState.data$ = savedSearchData$; stateContainer.setAppState({ interval: 'auto', hideChart, @@ -101,8 +102,6 @@ const mountComponent = ({ navigateTo: jest.fn(), setExpandedDoc: jest.fn(), savedSearch, - savedSearchData$, - savedSearchRefetch$: new Subject(), stateContainer, onFieldEdited: jest.fn(), columns: [], diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx index fed7278d97b41..c6deff28f62ed 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx @@ -16,7 +16,6 @@ import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DataTableRecord } from '../../../../types'; import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle'; import { DocViewFilterFn } from '../../../../services/doc_views/doc_views_types'; -import { DataRefetch$, SavedSearchData } from '../../services/discover_data_state_container'; import { DiscoverStateContainer } from '../../services/discover_state'; import { FieldStatisticsTab } from '../field_stats_table'; import { DiscoverDocuments } from './discover_documents'; @@ -27,8 +26,6 @@ export interface DiscoverMainContentProps { savedSearch: SavedSearch; isPlainRecord: boolean; navigateTo: (url: string) => void; - savedSearchData$: SavedSearchData; - savedSearchRefetch$: DataRefetch$; stateContainer: DiscoverStateContainer; expandedDoc?: DataTableRecord; setExpandedDoc: (doc?: DataTableRecord) => void; @@ -42,8 +39,6 @@ export const DiscoverMainContent = ({ dataView, isPlainRecord, navigateTo, - savedSearchData$, - savedSearchRefetch$, expandedDoc, setExpandedDoc, viewMode, @@ -85,7 +80,6 @@ export const DiscoverMainContent = ({ )} {viewMode === VIEW_MODE.DOCUMENT_LEVEL ? ( ) : ( )} diff --git a/src/plugins/discover/public/application/main/components/layout/types.ts b/src/plugins/discover/public/application/main/components/layout/types.ts index 734b6b65cf708..0d9b0c37e3009 100644 --- a/src/plugins/discover/public/application/main/components/layout/types.ts +++ b/src/plugins/discover/public/application/main/components/layout/types.ts @@ -12,7 +12,6 @@ import type { ISearchSource } from '@kbn/data-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { DataTableRecord } from '../../../../types'; import { DiscoverStateContainer } from '../../services/discover_state'; -import { DataFetch$, DataRefetch$, SavedSearchData } from '../../services/discover_data_state_container'; import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; import type { InspectorAdapters } from '../../hooks/use_inspector'; @@ -28,9 +27,6 @@ export interface DiscoverLayoutProps { expandedDoc?: DataTableRecord; setExpandedDoc: (doc?: DataTableRecord) => void; savedSearch: SavedSearch; - savedSearchData$: SavedSearchData; - savedSearchFetch$: DataFetch$; - savedSearchRefetch$: DataRefetch$; searchSource: ISearchSource; stateContainer: DiscoverStateContainer; persistDataView: (dataView: DataView) => Promise; diff --git a/src/plugins/discover/public/application/main/discover_main_app.tsx b/src/plugins/discover/public/application/main/discover_main_app.tsx index 92f155f57bafc..50caf6aa15e68 100644 --- a/src/plugins/discover/public/application/main/discover_main_app.tsx +++ b/src/plugins/discover/public/application/main/discover_main_app.tsx @@ -49,14 +49,11 @@ export function DiscoverMainApp(props: DiscoverMainProps) { * State related logic */ const { - data$, inspectorAdapters, onChangeDataView, onUpdateQuery, persistDataView, updateAdHocDataViewId, - fetch$, - refetch$, resetSavedSearch, searchSource, stateContainer, @@ -118,9 +115,6 @@ export function DiscoverMainApp(props: DiscoverMainProps) { setExpandedDoc={setExpandedDoc} navigateTo={navigateTo} savedSearch={savedSearch} - savedSearchData$={data$} - savedSearchFetch$={fetch$} - savedSearchRefetch$={refetch$} searchSource={searchSource} stateContainer={stateContainer} persistDataView={persistDataView} diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index 81a4f04bebe02..f5b3949e103a9 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -102,7 +102,7 @@ export function useDiscoverState({ /** * Data fetching logic */ - const { data$, fetch$, refetch$, reset, inspectorAdapters, initialFetchStatus } = + const { data$, refetch$, reset, inspectorAdapters, initialFetchStatus } = stateContainer.dataState; /** * State changes (data view, columns), when a text base query result is returned @@ -310,10 +310,7 @@ export function useDiscoverState({ }, [dataView, stateContainer]); return { - data$, inspectorAdapters, - fetch$, - refetch$, resetSavedSearch, onChangeDataView, onUpdateQuery, From 30950d578f9226301c2c4f08e8928ce2c8dc7f67 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Thu, 19 Jan 2023 07:28:49 +0100 Subject: [PATCH 14/15] Address review comments --- .../field_stats_table/field_stats_table.tsx | 2 -- .../main/services/discover_data_state_container.ts | 13 ++++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx index bf28344aed402..b01a05f932e13 100644 --- a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx +++ b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx @@ -23,7 +23,6 @@ import { css } from '@emotion/react'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { FIELD_STATISTICS_LOADED } from './constants'; import type { DiscoverStateContainer } from '../../services/discover_state'; -import { DataTotalHits$ } from '../../services/discover_data_state_container'; export interface RandomSamplingOption { mode: 'random_sampling'; seed: string; @@ -107,7 +106,6 @@ export interface FieldStatisticsTableProps { */ trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; searchSessionId?: string; - savedSearchDataTotalHits$?: DataTotalHits$; } export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts index 8c79718f627fb..5cadb099c483e 100644 --- a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts @@ -136,7 +136,8 @@ export function getDataStateContainer({ getSavedSearch: () => SavedSearch; appStateContainer: ReduxLikeStateContainer; }): DataStateContainer { - const { data } = services; + const { data, uiSettings, toastNotifications } = services; + const { timefilter } = data.query.timefilter; const inspectorAdapters = { requests: new RequestAdapter() }; const appState = getAppState(); const recordRawType = getRawRecordType(appState.query); @@ -147,9 +148,9 @@ export function getDataStateContainer({ */ const refetch$ = new Subject(); const shouldSearchOnPageLoad = - services.uiSettings.get(SEARCH_ON_PAGE_LOAD_SETTING) || + uiSettings.get(SEARCH_ON_PAGE_LOAD_SETTING) || getSavedSearch().id !== undefined || - !services.timefilter.getRefreshInterval().pause || + !timefilter.getRefreshInterval().pause || searchSessionManager.hasSearchSessionIdInURL(); const initialFetchStatus = shouldSearchOnPageLoad ? FetchStatus.LOADING @@ -183,9 +184,7 @@ export function getDataStateContainer({ searchSource: getSavedSearch().searchSource, searchSessionManager, }).pipe( - filter(() => - validateTimeRange(data.query.timefilter.timefilter.getTime(), services.toastNotifications) - ), + filter(() => validateTimeRange(timefilter.getTime(), toastNotifications)), tap(() => inspectorAdapters.requests.reset()), map((val) => ({ reset: val === 'reset', @@ -210,7 +209,7 @@ export function getDataStateContainer({ services, appStateContainer, savedSearch: getSavedSearch(), - useNewFieldsApi: !services.uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), + useNewFieldsApi: !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), }); // If the autoRefreshCallback is still the same as when we started i.e. there was no newer call From 12dbf3ac1e7904dd4dad9011a60c6a4f772cfa68 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Thu, 19 Jan 2023 08:38:48 +0100 Subject: [PATCH 15/15] Improve test --- .../main/services/discover_data_state_container.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts index 3ab0302395a73..fcdce1b76a1a0 100644 --- a/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts @@ -38,6 +38,9 @@ describe('test getDataStateContainer', () => { const unsubscribe = dataState.subscribe(); + expect(dataState.data$.totalHits$.value.result).toBe(undefined); + expect(dataState.data$.documents$.value.result).toEqual(undefined); + dataState.refetch$.next(undefined); await waitFor(() => { expect(dataState.data$.main$.value.fetchStatus).toBe('complete');