From e524d1b4a4498129558868bd7593a6b2a9a200d0 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Mon, 5 Oct 2020 13:10:12 +0100 Subject: [PATCH 1/8] Sync logs timestamps with wider Kibana --- .../logs/log_position/log_position_state.ts | 18 +++++++++++++++++- ..._log_entry_categories_results_url_state.tsx | 18 ++++++++++++++++-- .../use_log_entry_rate_results_url_state.tsx | 18 ++++++++++++++++-- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_position/log_position_state.ts b/x-pack/plugins/infra/public/containers/logs/log_position/log_position_state.ts index 5ac34e5df70ec..45c251b578e8c 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_position/log_position_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_position/log_position_state.ts @@ -9,6 +9,7 @@ import createContainer from 'constate'; import { useSetState } from 'react-use'; import { TimeKey } from '../../../../common/time'; import { datemathToEpochMillis, isValidDatemath } from '../../../utils/datemath'; +import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; type TimeKeyOrNull = TimeKey | null; @@ -55,7 +56,6 @@ export interface LogPositionCallbacks { updateDateRange: (newDateRage: Partial) => void; } -const DEFAULT_DATE_RANGE = { startDateExpression: 'now-1d', endDateExpression: 'now' }; const DESIRED_BUFFER_PAGES = 2; const useVisibleMidpoint = (middleKey: TimeKeyOrNull, targetPosition: TimeKeyOrNull) => { @@ -81,6 +81,13 @@ const useVisibleMidpoint = (middleKey: TimeKeyOrNull, targetPosition: TimeKeyOrN }; export const useLogPositionState: () => LogPositionStateParams & LogPositionCallbacks = () => { + const { services } = useKibanaContextForPlugin(); + const { from: sharedFrom, to: sharedTo } = services.data.query.timefilter.timefilter.getTime(); + const DEFAULT_DATE_RANGE = { + startDateExpression: sharedFrom || 'now-1d', + endDateExpression: sharedTo || 'now', + }; + // Flag to determine if `LogPositionState` has been fully initialized. // // When the page loads, there might be initial state in the URL. We want to @@ -110,6 +117,15 @@ export const useLogPositionState: () => LogPositionStateParams & LogPositionCall timestampsLastUpdate: Date.now(), }); + useEffect(() => { + // Share timestamp changes with the rest of Kibana + const { startDateExpression, endDateExpression } = dateRange; + services.data.query.timefilter.timefilter.setTime({ + from: startDateExpression, + to: endDateExpression, + }); + }, [dateRange, services.data.query.timefilter.timefilter]); + const { startKey, middleKey, endKey, pagesBeforeStart, pagesAfterEnd } = visiblePositions; const visibleMidpoint = useVisibleMidpoint(middleKey, targetPosition); diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx index bf30f96e4b741..1a3615b9a5bd5 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx @@ -4,12 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import { useEffect } from 'react'; import { fold } from 'fp-ts/lib/Either'; import { constant, identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import * as rt from 'io-ts'; import { useUrlState } from '../../../utils/use_url_state'; +import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; const autoRefreshRT = rt.union([ rt.type({ @@ -31,10 +33,13 @@ const TIME_RANGE_URL_STATE_KEY = 'timeRange'; const AUTOREFRESH_URL_STATE_KEY = 'autoRefresh'; export const useLogEntryCategoriesResultsUrlState = () => { + const { services } = useKibanaContextForPlugin(); + const { from: sharedFrom, to: sharedTo } = services.data.query.timefilter.timefilter.getTime(); + const [timeRange, setTimeRange] = useUrlState({ defaultState: { - startTime: 'now-2w', - endTime: 'now', + startTime: sharedFrom || 'now-2w', + endTime: sharedTo || 'now', }, decodeUrlState: (value: unknown) => pipe(urlTimeRangeRT.decode(value), fold(constant(undefined), identity)), @@ -43,6 +48,15 @@ export const useLogEntryCategoriesResultsUrlState = () => { writeDefaultState: true, }); + useEffect(() => { + // Share timestamp changes with the rest of Kibana + const { startTime, endTime } = timeRange; + services.data.query.timefilter.timefilter.setTime({ + from: startTime, + to: endTime, + }); + }, [timeRange, services.data.query.timefilter.timefilter]); + const [autoRefresh, setAutoRefresh] = useUrlState({ defaultState: { isPaused: false, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx index 6d4495c8d9e0f..3fc946bbcc823 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx @@ -4,12 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import { useEffect } from 'react'; import { fold } from 'fp-ts/lib/Either'; import { constant, identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import * as rt from 'io-ts'; import { useUrlState } from '../../../utils/use_url_state'; +import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; const autoRefreshRT = rt.union([ rt.type({ @@ -31,10 +33,13 @@ const TIME_RANGE_URL_STATE_KEY = 'timeRange'; const AUTOREFRESH_URL_STATE_KEY = 'autoRefresh'; export const useLogAnalysisResultsUrlState = () => { + const { services } = useKibanaContextForPlugin(); + const { from: sharedFrom, to: sharedTo } = services.data.query.timefilter.timefilter.getTime(); + const [timeRange, setTimeRange] = useUrlState({ defaultState: { - startTime: 'now-2w', - endTime: 'now', + startTime: sharedFrom || 'now-2w', + endTime: sharedTo || 'now', }, decodeUrlState: (value: unknown) => pipe(urlTimeRangeRT.decode(value), fold(constant(undefined), identity)), @@ -43,6 +48,15 @@ export const useLogAnalysisResultsUrlState = () => { writeDefaultState: true, }); + useEffect(() => { + // Share timestamp changes with the rest of Kibana + const { startTime, endTime } = timeRange; + services.data.query.timefilter.timefilter.setTime({ + from: startTime, + to: endTime, + }); + }, [timeRange, services.data.query.timefilter.timefilter]); + const [autoRefresh, setAutoRefresh] = useUrlState({ defaultState: { isPaused: false, From 492bee0be0ee640e6b771e613551b3462a1d1123 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Wed, 7 Oct 2020 15:34:34 +0100 Subject: [PATCH 2/8] Better handling of defaults --- .../public/query/timefilter/timefilter.ts | 8 +++- .../logs/log_position/log_position_state.ts | 29 +++++++----- .../hooks/use_kibana_timefilter_time.tsx | 47 +++++++++++++++++++ ...log_entry_categories_results_url_state.tsx | 25 ++++------ .../use_log_entry_rate_results_url_state.tsx | 24 ++++------ 5 files changed, 90 insertions(+), 43 deletions(-) create mode 100644 x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 5eb1546fa015f..4a579b68fa032 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -20,6 +20,7 @@ import _ from 'lodash'; import { Subject, BehaviorSubject } from 'rxjs'; import moment from 'moment'; +import { timeEnd } from 'console'; import { areRefreshIntervalsDifferent, areTimeRangesDifferent } from './lib/diff_time_picker_vals'; import { getForceNow } from './lib/get_force_now'; import { TimefilterConfig, InputTimeRange, TimeRangeBounds } from './types'; @@ -41,6 +42,8 @@ export class Timefilter { private fetch$ = new Subject(); private _time: TimeRange; + // Denotes whether setTime has been called, can be used to determine if the constructor defaults are being used. + private _isTimeTouched: boolean = false; private _refreshInterval!: RefreshInterval; private _history: TimeHistoryContract; @@ -88,8 +91,8 @@ export class Timefilter { return this.fetch$.asObservable(); }; - public getTime = (): TimeRange => { - const { from, to } = this._time; + public getTime = (defaults?: TimeRange): TimeRange => { + const { from, to } = this._isTimeTouched || !defaults ? this._time : defaults; return { ...this._time, from: moment.isMoment(from) ? from.toISOString() : from, @@ -112,6 +115,7 @@ export class Timefilter { from: newTime.from, to: newTime.to, }; + this._isTimeTouched = true; this._history.add(this._time); this.timeUpdate$.next(); this.fetch$.next(); diff --git a/x-pack/plugins/infra/public/containers/logs/log_position/log_position_state.ts b/x-pack/plugins/infra/public/containers/logs/log_position/log_position_state.ts index 45c251b578e8c..4b110fbc4e51e 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_position/log_position_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_position/log_position_state.ts @@ -9,7 +9,7 @@ import createContainer from 'constate'; import { useSetState } from 'react-use'; import { TimeKey } from '../../../../common/time'; import { datemathToEpochMillis, isValidDatemath } from '../../../utils/datemath'; -import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; +import { useKibanaTimefilterTime } from '../../../hooks/use_kibana_timefilter_time'; type TimeKeyOrNull = TimeKey | null; @@ -80,12 +80,15 @@ const useVisibleMidpoint = (middleKey: TimeKeyOrNull, targetPosition: TimeKeyOrN return store.currentValue; }; +const TIME_DEFAULTS = { from: 'now-1d', to: 'now' }; + export const useLogPositionState: () => LogPositionStateParams & LogPositionCallbacks = () => { - const { services } = useKibanaContextForPlugin(); - const { from: sharedFrom, to: sharedTo } = services.data.query.timefilter.timefilter.getTime(); + const [getTime, setTime] = useKibanaTimefilterTime(TIME_DEFAULTS); + const { from: start, to: end } = getTime(); + const DEFAULT_DATE_RANGE = { - startDateExpression: sharedFrom || 'now-1d', - endDateExpression: sharedTo || 'now', + startDateExpression: start, + endDateExpression: end, }; // Flag to determine if `LogPositionState` has been fully initialized. @@ -118,13 +121,15 @@ export const useLogPositionState: () => LogPositionStateParams & LogPositionCall }); useEffect(() => { - // Share timestamp changes with the rest of Kibana - const { startDateExpression, endDateExpression } = dateRange; - services.data.query.timefilter.timefilter.setTime({ - from: startDateExpression, - to: endDateExpression, - }); - }, [dateRange, services.data.query.timefilter.timefilter]); + if (isInitialized) { + if ( + TIME_DEFAULTS.from !== dateRange.startDateExpression || + TIME_DEFAULTS.to !== dateRange.endDateExpression + ) { + setTime({ from: dateRange.startDateExpression, to: dateRange.endDateExpression }); + } + } + }, [isInitialized, dateRange.startDateExpression, dateRange.endDateExpression, setTime]); const { startKey, middleKey, endKey, pagesBeforeStart, pagesAfterEnd } = visiblePositions; diff --git a/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx b/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx new file mode 100644 index 0000000000000..3ad608eef423a --- /dev/null +++ b/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useCallback } from 'react'; +import { useUpdateEffect, useMount } from 'react-use'; +import { useKibanaContextForPlugin } from './use_kibana'; +import { TimeRange } from '../../../../../src/plugins/data/public'; + +export const useKibanaTimefilterTime = ({ + from: fromDefault, + to: toDefault, +}: TimeRange): [typeof getTime, typeof setTime] => { + const { services } = useKibanaContextForPlugin(); + + const getTime = useCallback(() => { + return services.data.query.timefilter.timefilter.getTime({ from: fromDefault, to: toDefault }); + }, [services.data.query.timefilter.timefilter, fromDefault, toDefault]); + + const setTime = useCallback( + (timeRange: TimeRange) => { + services.data.query.timefilter.timefilter.setTime(timeRange); + }, + [services.data.query.timefilter.timefilter] + ); + + return [getTime, setTime]; +}; + +export const useSyncKibanaTimeFilterTime = (defaults: TimeRange, currentTimeRange: TimeRange) => { + const [_, setTime] = useKibanaTimefilterTime(defaults); + + // On first mount we only want to sync time with Kibana if the derived currentTimeRange (e.g. from URL params) + // differs from our defaults. + useMount(() => { + if (defaults.from !== currentTimeRange.from || defaults.to !== currentTimeRange.to) { + setTime({ from: currentTimeRange.from, to: currentTimeRange.to }); + } + }); + + // Sync explicit changes *after* mount back to Kibana + useUpdateEffect(() => { + setTime({ from: currentTimeRange.from, to: currentTimeRange.to }); + }, [currentTimeRange.from, currentTimeRange.to, setTime]); +}; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx index 1a3615b9a5bd5..1f9fa98f3ca4e 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx @@ -4,14 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useEffect } from 'react'; import { fold } from 'fp-ts/lib/Either'; import { constant, identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import * as rt from 'io-ts'; - import { useUrlState } from '../../../utils/use_url_state'; -import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; +import { + useKibanaTimefilterTime, + useSyncKibanaTimeFilterTime, +} from '../../../hooks/use_kibana_timefilter_time'; const autoRefreshRT = rt.union([ rt.type({ @@ -31,15 +32,16 @@ const urlTimeRangeRT = rt.union([stringTimeRangeRT, rt.undefined]); const TIME_RANGE_URL_STATE_KEY = 'timeRange'; const AUTOREFRESH_URL_STATE_KEY = 'autoRefresh'; +const TIME_DEFAULTS = { from: 'now-2w', to: 'now' }; export const useLogEntryCategoriesResultsUrlState = () => { - const { services } = useKibanaContextForPlugin(); - const { from: sharedFrom, to: sharedTo } = services.data.query.timefilter.timefilter.getTime(); + const [getTime, _] = useKibanaTimefilterTime(TIME_DEFAULTS); + const { from: start, to: end } = getTime(); const [timeRange, setTimeRange] = useUrlState({ defaultState: { - startTime: sharedFrom || 'now-2w', - endTime: sharedTo || 'now', + startTime: start, + endTime: end, }, decodeUrlState: (value: unknown) => pipe(urlTimeRangeRT.decode(value), fold(constant(undefined), identity)), @@ -48,14 +50,7 @@ export const useLogEntryCategoriesResultsUrlState = () => { writeDefaultState: true, }); - useEffect(() => { - // Share timestamp changes with the rest of Kibana - const { startTime, endTime } = timeRange; - services.data.query.timefilter.timefilter.setTime({ - from: startTime, - to: endTime, - }); - }, [timeRange, services.data.query.timefilter.timefilter]); + useSyncKibanaTimeFilterTime(TIME_DEFAULTS, { from: timeRange.startTime, to: timeRange.endTime }); const [autoRefresh, setAutoRefresh] = useUrlState({ defaultState: { diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx index 3fc946bbcc823..68167c319ffcb 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx @@ -4,14 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useEffect } from 'react'; import { fold } from 'fp-ts/lib/Either'; import { constant, identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import * as rt from 'io-ts'; import { useUrlState } from '../../../utils/use_url_state'; -import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; +import { + useKibanaTimefilterTime, + useSyncKibanaTimeFilterTime, +} from '../../../hooks/use_kibana_timefilter_time'; const autoRefreshRT = rt.union([ rt.type({ @@ -31,15 +33,16 @@ const urlTimeRangeRT = rt.union([stringTimeRangeRT, rt.undefined]); const TIME_RANGE_URL_STATE_KEY = 'timeRange'; const AUTOREFRESH_URL_STATE_KEY = 'autoRefresh'; +const TIME_DEFAULTS = { from: 'now-2w', to: 'now' }; export const useLogAnalysisResultsUrlState = () => { - const { services } = useKibanaContextForPlugin(); - const { from: sharedFrom, to: sharedTo } = services.data.query.timefilter.timefilter.getTime(); + const [getTime, _] = useKibanaTimefilterTime(TIME_DEFAULTS); + const { from: start, to: end } = getTime(); const [timeRange, setTimeRange] = useUrlState({ defaultState: { - startTime: sharedFrom || 'now-2w', - endTime: sharedTo || 'now', + startTime: start, + endTime: end, }, decodeUrlState: (value: unknown) => pipe(urlTimeRangeRT.decode(value), fold(constant(undefined), identity)), @@ -48,14 +51,7 @@ export const useLogAnalysisResultsUrlState = () => { writeDefaultState: true, }); - useEffect(() => { - // Share timestamp changes with the rest of Kibana - const { startTime, endTime } = timeRange; - services.data.query.timefilter.timefilter.setTime({ - from: startTime, - to: endTime, - }); - }, [timeRange, services.data.query.timefilter.timefilter]); + useSyncKibanaTimeFilterTime(TIME_DEFAULTS, { from: timeRange.startTime, to: timeRange.endTime }); const [autoRefresh, setAutoRefresh] = useUrlState({ defaultState: { From e39df69c5d1dd809ce5a2039c8e6c5c9cdec060b Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Wed, 7 Oct 2020 15:38:36 +0100 Subject: [PATCH 3/8] Remove accidental import --- src/plugins/data/public/query/timefilter/timefilter.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 4a579b68fa032..391705c66a50e 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -20,7 +20,6 @@ import _ from 'lodash'; import { Subject, BehaviorSubject } from 'rxjs'; import moment from 'moment'; -import { timeEnd } from 'console'; import { areRefreshIntervalsDifferent, areTimeRangesDifferent } from './lib/diff_time_picker_vals'; import { getForceNow } from './lib/get_force_now'; import { TimefilterConfig, InputTimeRange, TimeRangeBounds } from './types'; From 88da0b87f28c634aeaaa6266a6811feeac9b46c6 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 8 Oct 2020 13:00:45 +0100 Subject: [PATCH 4/8] Update x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix Stürmer --- .../plugins/infra/public/hooks/use_kibana_timefilter_time.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx b/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx index 3ad608eef423a..174a2b5017a33 100644 --- a/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx +++ b/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx @@ -30,7 +30,7 @@ export const useKibanaTimefilterTime = ({ }; export const useSyncKibanaTimeFilterTime = (defaults: TimeRange, currentTimeRange: TimeRange) => { - const [_, setTime] = useKibanaTimefilterTime(defaults); + const [, setTime] = useKibanaTimefilterTime(defaults); // On first mount we only want to sync time with Kibana if the derived currentTimeRange (e.g. from URL params) // differs from our defaults. From 7aa9c51bcde860554d3191fe1fa400108dc7e873 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 8 Oct 2020 13:01:05 +0100 Subject: [PATCH 5/8] Update x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix Stürmer --- .../use_log_entry_categories_results_url_state.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx index 1f9fa98f3ca4e..fa3e5eb22448f 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results_url_state.tsx @@ -35,7 +35,7 @@ const AUTOREFRESH_URL_STATE_KEY = 'autoRefresh'; const TIME_DEFAULTS = { from: 'now-2w', to: 'now' }; export const useLogEntryCategoriesResultsUrlState = () => { - const [getTime, _] = useKibanaTimefilterTime(TIME_DEFAULTS); + const [getTime] = useKibanaTimefilterTime(TIME_DEFAULTS); const { from: start, to: end } = getTime(); const [timeRange, setTimeRange] = useUrlState({ From f47fe2525c970337e1194d2fa2583a99c897c91f Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 8 Oct 2020 13:01:13 +0100 Subject: [PATCH 6/8] Update x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix Stürmer --- .../log_entry_rate/use_log_entry_rate_results_url_state.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx index 68167c319ffcb..2aca3fc58d7c7 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx @@ -36,7 +36,7 @@ const AUTOREFRESH_URL_STATE_KEY = 'autoRefresh'; const TIME_DEFAULTS = { from: 'now-2w', to: 'now' }; export const useLogAnalysisResultsUrlState = () => { - const [getTime, _] = useKibanaTimefilterTime(TIME_DEFAULTS); + const [getTime] = useKibanaTimefilterTime(TIME_DEFAULTS); const { from: start, to: end } = getTime(); const [timeRange, setTimeRange] = useUrlState({ From f8b2123dde98f65ffb3fbddf81d8c31b8cb95997 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 8 Oct 2020 13:33:12 +0100 Subject: [PATCH 7/8] Remove unnecessary wrapper --- .../public/hooks/use_kibana_timefilter_time.tsx | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx b/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx index 174a2b5017a33..b70381d26ec9b 100644 --- a/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx +++ b/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx @@ -7,26 +7,19 @@ import { useCallback } from 'react'; import { useUpdateEffect, useMount } from 'react-use'; import { useKibanaContextForPlugin } from './use_kibana'; -import { TimeRange } from '../../../../../src/plugins/data/public'; +import { TimeRange, TimefilterContract } from '../../../../../src/plugins/data/public'; export const useKibanaTimefilterTime = ({ from: fromDefault, to: toDefault, -}: TimeRange): [typeof getTime, typeof setTime] => { +}: TimeRange): [typeof getTime, TimefilterContract['setTime']] => { const { services } = useKibanaContextForPlugin(); const getTime = useCallback(() => { return services.data.query.timefilter.timefilter.getTime({ from: fromDefault, to: toDefault }); }, [services.data.query.timefilter.timefilter, fromDefault, toDefault]); - const setTime = useCallback( - (timeRange: TimeRange) => { - services.data.query.timefilter.timefilter.setTime(timeRange); - }, - [services.data.query.timefilter.timefilter] - ); - - return [getTime, setTime]; + return [getTime, services.data.query.timefilter.timefilter.setTime]; }; export const useSyncKibanaTimeFilterTime = (defaults: TimeRange, currentTimeRange: TimeRange) => { From a0be0c475c14a2b2f801e54b7bd56d08fc30b273 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 8 Oct 2020 15:42:12 +0100 Subject: [PATCH 8/8] kibana-app-arch suggestions - Move decision of using defaults to the solution consumer - Add unit tests --- .../data/public/query/timefilter/timefilter.test.ts | 8 ++++++++ src/plugins/data/public/query/timefilter/timefilter.ts | 8 ++++++-- .../public/query/timefilter/timefilter_service.mock.ts | 1 + .../infra/public/hooks/use_kibana_timefilter_time.tsx | 5 ++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/plugins/data/public/query/timefilter/timefilter.test.ts b/src/plugins/data/public/query/timefilter/timefilter.test.ts index 1280664ac8389..6c1a4eff786f6 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.test.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.test.ts @@ -54,6 +54,10 @@ function clearNowTimeStub() { delete global.nowTime; } +test('isTimeTouched is initially set to false', () => { + expect(timefilter.isTimeTouched()).toBe(false); +}); + describe('setTime', () => { let update: sinon.SinonSpy; let fetch: sinon.SinonSpy; @@ -84,6 +88,10 @@ describe('setTime', () => { }); }); + test('should update isTimeTouched', () => { + expect(timefilter.isTimeTouched()).toBe(true); + }); + test('should not add unexpected object keys to time state', () => { const unexpectedKey = 'unexpectedKey'; timefilter.setTime({ diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 391705c66a50e..01b82087cf354 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -70,6 +70,10 @@ export class Timefilter { return this._isAutoRefreshSelectorEnabled; } + public isTimeTouched() { + return this._isTimeTouched; + } + public getEnabledUpdated$ = () => { return this.enabledUpdated$.asObservable(); }; @@ -90,8 +94,8 @@ export class Timefilter { return this.fetch$.asObservable(); }; - public getTime = (defaults?: TimeRange): TimeRange => { - const { from, to } = this._isTimeTouched || !defaults ? this._time : defaults; + public getTime = (): TimeRange => { + const { from, to } = this._time; return { ...this._time, from: moment.isMoment(from) ? from.toISOString() : from, diff --git a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts index 7863000b1ace4..060257a880528 100644 --- a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts +++ b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts @@ -26,6 +26,7 @@ const createSetupContractMock = () => { const timefilterMock: jest.Mocked = { isAutoRefreshSelectorEnabled: jest.fn(), isTimeRangeSelectorEnabled: jest.fn(), + isTimeTouched: jest.fn(), getEnabledUpdated$: jest.fn(), getTimeUpdate$: jest.fn(), getRefreshIntervalUpdate$: jest.fn(), diff --git a/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx b/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx index b70381d26ec9b..e9537370f12cd 100644 --- a/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx +++ b/x-pack/plugins/infra/public/hooks/use_kibana_timefilter_time.tsx @@ -16,7 +16,10 @@ export const useKibanaTimefilterTime = ({ const { services } = useKibanaContextForPlugin(); const getTime = useCallback(() => { - return services.data.query.timefilter.timefilter.getTime({ from: fromDefault, to: toDefault }); + const timefilterService = services.data.query.timefilter.timefilter; + return timefilterService.isTimeTouched() + ? timefilterService.getTime() + : { from: fromDefault, to: toDefault }; }, [services.data.query.timefilter.timefilter, fromDefault, toDefault]); return [getTime, services.data.query.timefilter.timefilter.setTime];