From c2dac03979bd09d1be9e2632146a7eaaf2bd2990 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Mon, 3 Feb 2020 15:00:19 -0700 Subject: [PATCH 1/4] [Metrics UI] Setup commonly used time ranges in timepicker --- .../components/metrics_explorer/toolbar.tsx | 24 +++- .../metrics/components/time_controls.tsx | 107 ++++++++++++------ 2 files changed, 94 insertions(+), 37 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx index ab6949e2f1d065..d0d21189091386 100644 --- a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx +++ b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx @@ -4,7 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexGroup, EuiFlexItem, EuiSuperDatePicker, EuiText } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiSuperDatePicker, + EuiText, + EuiSuperDatePickerCommonRange, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; import { IIndexPattern } from 'src/plugins/data/public'; @@ -26,6 +32,7 @@ import { MetricsExplorerChartOptions as MetricsExplorerChartOptionsComponent } f import { SavedViewsToolbarControls } from '../saved_views/toolbar_control'; import { MetricExplorerViewState } from '../../pages/infrastructure/metrics_explorer/use_metric_explorer_state'; import { metricsExplorerViewSavedObjectType } from '../../../common/saved_objects/metrics_explorer_view'; +import { useKibanaUiSetting } from '../../utils/use_kibana_ui_setting'; interface Props { derivedIndexPattern: IIndexPattern; @@ -43,6 +50,12 @@ interface Props { onViewStateChange: (vs: MetricExplorerViewState) => void; } +interface QueryRange { + from: string; + to: string; + display: string; +} + export const MetricsExplorerToolbar = ({ timeRange, derivedIndexPattern, @@ -59,6 +72,14 @@ export const MetricsExplorerToolbar = ({ onViewStateChange, }: Props) => { const isDefaultOptions = options.aggregation === 'avg' && options.metrics.length === 0; + const [timepickerQuickRanges] = useKibanaUiSetting('timepicker:quickRanges'); + const commonlyUsedRanges: EuiSuperDatePickerCommonRange[] = timepickerQuickRanges + ? timepickerQuickRanges.map((r: QueryRange) => ({ + start: r.from, + end: r.to, + label: r.display, + })) + : []; return ( @@ -134,6 +155,7 @@ export const MetricsExplorerToolbar = ({ end={timeRange.to} onTimeChange={({ start, end }) => onTimeChange(start, end)} onRefresh={onRefresh} + commonlyUsedRanges={commonlyUsedRanges} /> diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx index d181aa37f59aa6..f448ee921e7f73 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx @@ -4,10 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiSuperDatePicker, OnRefreshChangeProps, OnTimeChangeProps } from '@elastic/eui'; -import React from 'react'; +import { + EuiSuperDatePicker, + OnRefreshChangeProps, + OnTimeChangeProps, + EuiSuperDatePickerCommonRange, +} from '@elastic/eui'; +import React, { useCallback } from 'react'; import euiStyled from '../../../../../../common/eui_styled_components'; import { MetricsTimeInput } from '../containers/with_metrics_time'; +import { useKibanaUiSetting } from '../../../utils/use_kibana_ui_setting'; interface MetricsTimeControlsProps { currentTimeRange: MetricsTimeInput; @@ -19,42 +25,71 @@ interface MetricsTimeControlsProps { onRefresh: () => void; } -export class MetricsTimeControls extends React.Component { - public render() { - const { currentTimeRange, isLiveStreaming, refreshInterval } = this.props; - return ( - - - - ); - } - - private handleTimeChange = ({ start, end }: OnTimeChangeProps) => { - this.props.onChangeTimeRange({ - from: start, - to: end, - interval: '>=1m', - }); - }; - - private handleRefreshChange = ({ isPaused, refreshInterval }: OnRefreshChangeProps) => { - if (isPaused) { - this.props.setAutoReload(false); - } else { - this.props.setRefreshInterval(refreshInterval); - this.props.setAutoReload(true); - } - }; +interface QueryRange { + from: string; + to: string; + display: string; } +export const MetricsTimeControls = (props: MetricsTimeControlsProps) => { + const [timepickerQuickRanges] = useKibanaUiSetting('timepicker:quickRanges'); + const { + onChangeTimeRange, + onRefresh, + currentTimeRange, + isLiveStreaming, + refreshInterval, + setAutoReload, + setRefreshInterval, + } = props; + + const commonlyUsedRanges: EuiSuperDatePickerCommonRange[] = timepickerQuickRanges + ? timepickerQuickRanges.map((r: QueryRange) => ({ + start: r.from, + end: r.to, + label: r.display, + })) + : []; + + const handleTimeChange = useCallback( + ({ start, end }: OnTimeChangeProps) => { + onChangeTimeRange({ + from: start, + to: end, + interval: '>=1m', + }); + }, + [onChangeTimeRange] + ); + + const handleRefreshChange = useCallback( + ({ isPaused, refreshInterval: _refreshInterval }: OnRefreshChangeProps) => { + if (isPaused) { + setAutoReload(false); + } else { + setRefreshInterval(_refreshInterval); + setAutoReload(true); + } + }, + [setAutoReload, setRefreshInterval] + ); + + return ( + + + + ); +}; + const MetricsTimeControlsContainer = euiStyled.div` max-width: 750px; `; From 35795e25e9e1cb46ec9b50d11c4b9edd3140ff38 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 4 Feb 2020 09:17:22 -0700 Subject: [PATCH 2/4] Fixing tests by mocking out useKibanaUISetting --- .../pages/metrics/components/time_controls.test.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.test.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.test.tsx index 624a2bb4a6f0f7..91e25fd8ef5854 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.test.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.test.tsx @@ -3,6 +3,18 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +jest.mock('../../../utils/use_kibana_ui_setting', () => ({ + _esModule: true, + useKibanaUiSetting: jest.fn(() => [ + [ + { + from: 'now/d', + to: 'now/d', + display: 'Today', + }, + ], + ]), +})); import React from 'react'; import { MetricsTimeControls } from './time_controls'; From 3d5e85edf1c0e5dcfc8540f4ebd0a2756401a41e Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 7 Feb 2020 12:06:28 -0700 Subject: [PATCH 3/4] add definition override to useKibanaUISetting for timepicker:quickRanges; reduce duplicate code for mapping quick ranges --- .../components/metrics_explorer/toolbar.tsx | 15 ++----------- .../metrics/components/time_controls.tsx | 22 +++---------------- ...picker_quickranges_to_datepicker_ranges.ts | 19 ++++++++++++++++ .../public/utils/use_kibana_ui_setting.ts | 19 ++++++++++++++-- 4 files changed, 41 insertions(+), 34 deletions(-) create mode 100644 x-pack/legacy/plugins/infra/public/utils/map_timepicker_quickranges_to_datepicker_ranges.ts diff --git a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx index d0d21189091386..bf6740858b4a68 100644 --- a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx +++ b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx @@ -33,6 +33,7 @@ import { SavedViewsToolbarControls } from '../saved_views/toolbar_control'; import { MetricExplorerViewState } from '../../pages/infrastructure/metrics_explorer/use_metric_explorer_state'; import { metricsExplorerViewSavedObjectType } from '../../../common/saved_objects/metrics_explorer_view'; import { useKibanaUiSetting } from '../../utils/use_kibana_ui_setting'; +import { mapKibanaQuickRangesToDatePickerRanges } from '../../utils/map_timepicker_quickranges_to_datepicker_ranges'; interface Props { derivedIndexPattern: IIndexPattern; @@ -50,12 +51,6 @@ interface Props { onViewStateChange: (vs: MetricExplorerViewState) => void; } -interface QueryRange { - from: string; - to: string; - display: string; -} - export const MetricsExplorerToolbar = ({ timeRange, derivedIndexPattern, @@ -73,13 +68,7 @@ export const MetricsExplorerToolbar = ({ }: Props) => { const isDefaultOptions = options.aggregation === 'avg' && options.metrics.length === 0; const [timepickerQuickRanges] = useKibanaUiSetting('timepicker:quickRanges'); - const commonlyUsedRanges: EuiSuperDatePickerCommonRange[] = timepickerQuickRanges - ? timepickerQuickRanges.map((r: QueryRange) => ({ - start: r.from, - end: r.to, - label: r.display, - })) - : []; + const commonlyUsedRanges = mapKibanaQuickRangesToDatePickerRanges(timepickerQuickRanges); return ( diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx index f448ee921e7f73..1546966c10a1e5 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx @@ -4,16 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiSuperDatePicker, - OnRefreshChangeProps, - OnTimeChangeProps, - EuiSuperDatePickerCommonRange, -} from '@elastic/eui'; +import { EuiSuperDatePicker, OnRefreshChangeProps, OnTimeChangeProps } from '@elastic/eui'; import React, { useCallback } from 'react'; import euiStyled from '../../../../../../common/eui_styled_components'; import { MetricsTimeInput } from '../containers/with_metrics_time'; import { useKibanaUiSetting } from '../../../utils/use_kibana_ui_setting'; +import { mapKibanaQuickRangesToDatePickerRanges } from '../../../utils/map_timepicker_quickranges_to_datepicker_ranges'; interface MetricsTimeControlsProps { currentTimeRange: MetricsTimeInput; @@ -25,12 +21,6 @@ interface MetricsTimeControlsProps { onRefresh: () => void; } -interface QueryRange { - from: string; - to: string; - display: string; -} - export const MetricsTimeControls = (props: MetricsTimeControlsProps) => { const [timepickerQuickRanges] = useKibanaUiSetting('timepicker:quickRanges'); const { @@ -43,13 +33,7 @@ export const MetricsTimeControls = (props: MetricsTimeControlsProps) => { setRefreshInterval, } = props; - const commonlyUsedRanges: EuiSuperDatePickerCommonRange[] = timepickerQuickRanges - ? timepickerQuickRanges.map((r: QueryRange) => ({ - start: r.from, - end: r.to, - label: r.display, - })) - : []; + const commonlyUsedRanges = mapKibanaQuickRangesToDatePickerRanges(timepickerQuickRanges); const handleTimeChange = useCallback( ({ start, end }: OnTimeChangeProps) => { diff --git a/x-pack/legacy/plugins/infra/public/utils/map_timepicker_quickranges_to_datepicker_ranges.ts b/x-pack/legacy/plugins/infra/public/utils/map_timepicker_quickranges_to_datepicker_ranges.ts new file mode 100644 index 00000000000000..68fac1ef6c0845 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/utils/map_timepicker_quickranges_to_datepicker_ranges.ts @@ -0,0 +1,19 @@ +/* + * 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 { EuiSuperDatePickerCommonRange } from '@elastic/eui'; +import { TimePickerQuickRange } from './use_kibana_ui_setting'; + +export const mapKibanaQuickRangesToDatePickerRanges = ( + timepickerQuickRanges: TimePickerQuickRange[] | undefined +): EuiSuperDatePickerCommonRange[] => + timepickerQuickRanges + ? timepickerQuickRanges.map(r => ({ + start: r.from, + end: r.to, + label: r.display, + })) + : []; diff --git a/x-pack/legacy/plugins/infra/public/utils/use_kibana_ui_setting.ts b/x-pack/legacy/plugins/infra/public/utils/use_kibana_ui_setting.ts index ce39a31c0fc3fd..2fe74dfe1625db 100644 --- a/x-pack/legacy/plugins/infra/public/utils/use_kibana_ui_setting.ts +++ b/x-pack/legacy/plugins/infra/public/utils/use_kibana_ui_setting.ts @@ -25,7 +25,22 @@ import useObservable from 'react-use/lib/useObservable'; * Unlike the `useState`, it doesn't give type guarantees for the value, * because the underlying `UiSettingsClient` doesn't support that. */ -export const useKibanaUiSetting = (key: string, defaultValue?: any) => { + +export interface TimePickerQuickRange { + from: string; + to: string; + display: string; +} + +export function useKibanaUiSetting( + key: 'timepicker:quickRanges', + defaultValue?: TimePickerQuickRange[] +): [ + TimePickerQuickRange[], + (key: 'timepicker:quickRanges', value: TimePickerQuickRange[]) => Promise +]; + +export function useKibanaUiSetting(key: string, defaultValue?: any) { const uiSettingsClient = npSetup.core.uiSettings; const uiSetting$ = useMemo(() => uiSettingsClient.get$(key, defaultValue), [ @@ -41,4 +56,4 @@ export const useKibanaUiSetting = (key: string, defaultValue?: any) => { ]); return [uiSetting, setUiSetting]; -}; +} From 2fa03f2f41c050fc61bcc4f2218ebfe5f62376d2 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 7 Feb 2020 14:09:51 -0700 Subject: [PATCH 4/4] Fixing types --- .../infra/public/components/metrics_explorer/toolbar.tsx | 8 +------- .../plugins/infra/public/utils/use_kibana_ui_setting.ts | 5 +++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx index bf6740858b4a68..839e40e057c9ac 100644 --- a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx +++ b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/toolbar.tsx @@ -4,13 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiFlexGroup, - EuiFlexItem, - EuiSuperDatePicker, - EuiText, - EuiSuperDatePickerCommonRange, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSuperDatePicker, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; import { IIndexPattern } from 'src/plugins/data/public'; diff --git a/x-pack/legacy/plugins/infra/public/utils/use_kibana_ui_setting.ts b/x-pack/legacy/plugins/infra/public/utils/use_kibana_ui_setting.ts index 2fe74dfe1625db..b3697db81fb6eb 100644 --- a/x-pack/legacy/plugins/infra/public/utils/use_kibana_ui_setting.ts +++ b/x-pack/legacy/plugins/infra/public/utils/use_kibana_ui_setting.ts @@ -40,6 +40,11 @@ export function useKibanaUiSetting( (key: 'timepicker:quickRanges', value: TimePickerQuickRange[]) => Promise ]; +export function useKibanaUiSetting( + key: string, + defaultValue?: any +): [any, (key: string, value: any) => Promise]; + export function useKibanaUiSetting(key: string, defaultValue?: any) { const uiSettingsClient = npSetup.core.uiSettings;