[ML] Fix date picker not allowing unpause when refresh interval is 0 (#142005)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Quynh Nguyen (Quinn) 2022-09-30 11:33:56 -05:00 committed by GitHub
parent f415b3b98f
commit e7c2983173
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 378 additions and 122 deletions

View file

@ -15,6 +15,6 @@
"licensing"
],
"optionalPlugins": [],
"requiredBundles": ["fieldFormats"],
"requiredBundles": ["fieldFormats", "kibanaReact"],
"extraPublicDirs": ["common"]
}

View file

@ -7,19 +7,33 @@
// TODO Consolidate with duplicate component `DatePickerWrapper` in
// `x-pack/plugins/data_visualizer/public/application/common/components/date_picker_wrapper/date_picker_wrapper.tsx`
// `x-pack/plugins/ml/public/application/components/navigation_menu/date_picker_wrapper/date_picker_wrapper.tsx`
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { Subscription } from 'rxjs';
import { debounce } from 'lodash';
import { EuiSuperDatePicker, OnRefreshProps } from '@elastic/eui';
import {
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiSuperDatePicker,
OnRefreshProps,
OnTimeChangeProps,
} from '@elastic/eui';
import type { TimeRange } from '@kbn/es-query';
import { TimeHistoryContract, UI_SETTINGS } from '@kbn/data-plugin/public';
import { TimefilterContract, TimeHistoryContract, UI_SETTINGS } from '@kbn/data-plugin/public';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import useObservable from 'react-use/lib/useObservable';
import { map } from 'rxjs/operators';
import { toMountPoint, wrapWithTheme } from '@kbn/kibana-react-plugin/public';
import { useUrlState } from '../../hooks/use_url_state';
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
import { aiopsRefresh$ } from '../../application/services/timefilter_refresh_service';
const DEFAULT_REFRESH_INTERVAL_MS = 5000;
interface TimePickerQuickRange {
from: string;
to: string;
@ -49,19 +63,64 @@ function getRecentlyUsedRangesFactory(timeHistory: TimeHistoryContract) {
};
}
function updateLastRefresh(timeRange: OnRefreshProps) {
function updateLastRefresh(timeRange?: OnRefreshProps) {
aiopsRefresh$.next({ lastRefresh: Date.now(), timeRange });
}
export const useRefreshIntervalUpdates = (timefilter: TimefilterContract) => {
return useObservable(
timefilter.getRefreshIntervalUpdate$().pipe(map(timefilter.getRefreshInterval)),
timefilter.getRefreshInterval()
);
};
export const useTimeRangeUpdates = (timefilter: TimefilterContract, absolute = false) => {
const getTimeCallback = absolute
? timefilter.getAbsoluteTime.bind(timefilter)
: timefilter.getTime.bind(timefilter);
return useObservable(timefilter.getTimeUpdate$().pipe(map(getTimeCallback)), getTimeCallback());
};
export const DatePickerWrapper: FC = () => {
const { uiSettings, data } = useAiopsAppContext();
const { timefilter, history } = data.query.timefilter;
const services = useAiopsAppContext();
const { toasts } = services.notifications;
const config = services.uiSettings;
const { timefilter, history } = services.data.query.timefilter;
const theme$ = services.theme.theme$;
const [globalState, setGlobalState] = useUrlState('_g');
const getRecentlyUsedRanges = getRecentlyUsedRangesFactory(history);
const refreshInterval: RefreshInterval =
globalState?.refreshInterval ?? timefilter.getRefreshInterval();
const timeFilterRefreshInterval = useRefreshIntervalUpdates(timefilter);
const time = useTimeRangeUpdates(timefilter);
useEffect(
function syncTimRangeFromUrlState() {
if (globalState?.time !== undefined) {
timefilter.setTime({
from: globalState.time.from,
to: globalState.time.to,
});
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[globalState?.time?.from, globalState?.time?.to, globalState?.time?.ts]
);
useEffect(
function syncRefreshIntervalFromUrlState() {
if (globalState?.refreshInterval !== undefined) {
timefilter.setRefreshInterval({
pause: !!globalState?.refreshInterval?.pause,
value: globalState?.refreshInterval?.value,
});
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[globalState?.refreshInterval]
);
// eslint-disable-next-line react-hooks/exhaustive-deps
const setRefreshInterval = useCallback(
@ -71,7 +130,6 @@ export const DatePickerWrapper: FC = () => {
[setGlobalState]
);
const [time, setTime] = useState(timefilter.getTime());
const [recentlyUsedRanges, setRecentlyUsedRanges] = useState(getRecentlyUsedRanges());
const [isAutoRefreshSelectorEnabled, setIsAutoRefreshSelectorEnabled] = useState(
timefilter.isAutoRefreshSelectorEnabled()
@ -80,8 +138,69 @@ export const DatePickerWrapper: FC = () => {
timefilter.isTimeRangeSelectorEnabled()
);
const dateFormat = uiSettings.get('dateFormat');
const timePickerQuickRanges = uiSettings.get<TimePickerQuickRange[]>(
const refreshInterval = useMemo(
(): RefreshInterval => globalState?.refreshInterval ?? timeFilterRefreshInterval,
// eslint-disable-next-line react-hooks/exhaustive-deps
[JSON.stringify(globalState?.refreshInterval), timeFilterRefreshInterval]
);
useEffect(
function warnAboutShortRefreshInterval() {
const isResolvedFromUrlState = !!globalState?.refreshInterval;
const isTooShort = refreshInterval.value < DEFAULT_REFRESH_INTERVAL_MS;
// Only warn about short interval with enabled auto-refresh.
if (!isTooShort || refreshInterval.pause) return;
toasts.addWarning(
{
title: isResolvedFromUrlState
? i18n.translate('xpack.aiops.datePicker.shortRefreshIntervalURLWarningMessage', {
defaultMessage:
'The refresh interval in the URL is shorter than the minimum supported by Machine Learning.',
})
: i18n.translate(
'xpack.aiops.datePicker.shortRefreshIntervalTimeFilterWarningMessage',
{
defaultMessage:
'The refresh interval in Advanced Settings is shorter than the minimum supported by Machine Learning.',
}
),
text: toMountPoint(
wrapWithTheme(
<EuiButton
onClick={setRefreshInterval.bind(null, {
pause: refreshInterval.pause,
value: DEFAULT_REFRESH_INTERVAL_MS,
})}
>
<FormattedMessage
id="xpack.aiops.index.pageRefreshResetButton"
defaultMessage="Set to {defaultInterval}"
values={{
defaultInterval: `${DEFAULT_REFRESH_INTERVAL_MS / 1000}s`,
}}
/>
</EuiButton>,
theme$
)
),
},
{ toastLifeTimeMs: 30000 }
);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[
// eslint-disable-next-line react-hooks/exhaustive-deps
JSON.stringify(refreshInterval),
// eslint-disable-next-line react-hooks/exhaustive-deps
JSON.stringify(globalState?.refreshInterval),
setRefreshInterval,
]
);
const dateFormat = config.get('dateFormat');
const timePickerQuickRanges = config.get<TimePickerQuickRange[]>(
UI_SETTINGS.TIMEPICKER_QUICK_RANGES
);
@ -97,22 +216,7 @@ export const DatePickerWrapper: FC = () => {
useEffect(() => {
const subscriptions = new Subscription();
const refreshIntervalUpdate$ = timefilter.getRefreshIntervalUpdate$();
if (refreshIntervalUpdate$ !== undefined) {
subscriptions.add(
refreshIntervalUpdate$.subscribe((r) => {
setRefreshInterval(timefilter.getRefreshInterval());
})
);
}
const timeUpdate$ = timefilter.getTimeUpdate$();
if (timeUpdate$ !== undefined) {
subscriptions.add(
timeUpdate$.subscribe((v) => {
setTime(timefilter.getTime());
})
);
}
const enabledUpdated$ = timefilter.getEnabledUpdated$();
if (enabledUpdated$ !== undefined) {
subscriptions.add(
@ -126,15 +230,21 @@ export const DatePickerWrapper: FC = () => {
return function cleanup() {
subscriptions.unsubscribe();
};
}, [setRefreshInterval, timefilter]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
function updateFilter({ start, end }: Duration) {
const newTime = { from: start, to: end };
// Update timefilter for controllers listening for changes
timefilter.setTime(newTime);
setTime(newTime);
setRecentlyUsedRanges(getRecentlyUsedRanges());
}
const updateTimeFilter = useCallback(
({ start, end }: OnTimeChangeProps) => {
setRecentlyUsedRanges(getRecentlyUsedRanges());
setGlobalState('time', {
from: start,
to: end,
...(start === 'now' || end === 'now' ? { ts: Date.now() } : {}),
});
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[setGlobalState]
);
function updateInterval({
isPaused: pause,
@ -146,26 +256,41 @@ export const DatePickerWrapper: FC = () => {
setRefreshInterval({ pause, value });
}
/**
* Enforce pause when it's set to false with 0 refresh interval.
*/
const isPaused = refreshInterval.pause || (!refreshInterval.pause && !refreshInterval.value);
return isAutoRefreshSelectorEnabled || isTimeRangeSelectorEnabled ? (
<div className="mlNavigationMenu__datePickerWrapper">
<EuiSuperDatePicker
start={time.from}
end={time.to}
isPaused={isPaused}
isAutoRefreshOnly={!isTimeRangeSelectorEnabled}
refreshInterval={refreshInterval.value}
onTimeChange={updateFilter}
onRefresh={updateLastRefresh}
onRefreshChange={updateInterval}
recentlyUsedRanges={recentlyUsedRanges}
dateFormat={dateFormat}
commonlyUsedRanges={commonlyUsedRanges}
/>
</div>
<EuiFlexGroup
gutterSize="s"
alignItems="center"
className="mlNavigationMenu__datePickerWrapper"
>
<EuiFlexItem grow={false}>
<EuiSuperDatePicker
start={time.from}
end={time.to}
isPaused={refreshInterval.pause}
isAutoRefreshOnly={!isTimeRangeSelectorEnabled}
refreshInterval={refreshInterval.value || DEFAULT_REFRESH_INTERVAL_MS}
onTimeChange={updateTimeFilter}
onRefresh={updateLastRefresh}
onRefreshChange={updateInterval}
recentlyUsedRanges={recentlyUsedRanges}
dateFormat={dateFormat}
commonlyUsedRanges={commonlyUsedRanges}
/>
</EuiFlexItem>
{isTimeRangeSelectorEnabled ? null : (
<EuiFlexItem grow={false}>
<EuiButton
fill
color="primary"
iconType={'refresh'}
onClick={() => updateLastRefresh()}
data-test-subj="aiOpsRefreshPageButton"
>
<FormattedMessage id="xpack.aiops.pageRefreshButton" defaultMessage="Refresh" />
</EuiButton>
</EuiFlexItem>
)}
</EuiFlexGroup>
) : null;
};

View file

@ -15,6 +15,7 @@ import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
import type { SharePluginStart } from '@kbn/share-plugin/public';
import type { CoreStart, CoreSetup, HttpStart, IUiSettingsClient } from '@kbn/core/public';
import type { ThemeServiceStart } from '@kbn/core/public';
export interface AiopsAppDependencies {
application: CoreStart['application'];
@ -24,6 +25,7 @@ export interface AiopsAppDependencies {
http: HttpStart;
notifications: CoreSetup['notifications'];
storage: IStorageWrapper;
theme: ThemeServiceStart;
uiSettings: IUiSettingsClient;
unifiedSearch: UnifiedSearchPublicPluginStart;
share: SharePluginStart;

View file

@ -5,17 +5,35 @@
* 2.0.
*/
// TODO Consolidate with duplicate component `DatePickerWrapper` in
// `x-pack/plugins/aiops/public/components/date_picker_wrapper/date_picker_wrapper.tsx`
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { Subscription } from 'rxjs';
import { debounce } from 'lodash';
import { EuiSuperDatePicker, OnRefreshProps } from '@elastic/eui';
import {
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiSuperDatePicker,
OnRefreshProps,
OnTimeChangeProps,
} from '@elastic/eui';
import type { TimeRange } from '@kbn/es-query';
import { TimeHistoryContract, UI_SETTINGS } from '@kbn/data-plugin/public';
import { useUrlState } from '../../util/url_state';
import { i18n } from '@kbn/i18n';
import { wrapWithTheme } from '@kbn/kibana-react-plugin/public';
import { FormattedMessage } from '@kbn/i18n-react';
import {
useRefreshIntervalUpdates,
useTimeRangeUpdates,
} from '../../../index_data_visualizer/hooks/use_time_filter';
import { useDataVisualizerKibana } from '../../../kibana_context';
import { dataVisualizerRefresh$ } from '../../../index_data_visualizer/services/timefilter_refresh_service';
import { useUrlState } from '../../util/url_state';
const DEFAULT_REFRESH_INTERVAL_MS = 5000;
interface TimePickerQuickRange {
from: string;
@ -46,20 +64,52 @@ function getRecentlyUsedRangesFactory(timeHistory: TimeHistoryContract) {
};
}
function updateLastRefresh(timeRange: OnRefreshProps) {
function updateLastRefresh(timeRange?: OnRefreshProps) {
dataVisualizerRefresh$.next({ lastRefresh: Date.now(), timeRange });
}
// FIXME: Consolidate this component with ML and AIOps's component
export const DatePickerWrapper: FC = () => {
const { services } = useDataVisualizerKibana();
const {
services,
notifications: { toasts },
} = useDataVisualizerKibana();
const config = services.uiSettings;
const theme$ = services.theme.theme$;
const { timefilter, history } = services.data.query.timefilter;
const [globalState, setGlobalState] = useUrlState('_g');
const getRecentlyUsedRanges = getRecentlyUsedRangesFactory(history);
const refreshInterval: RefreshInterval =
globalState?.refreshInterval ?? timefilter.getRefreshInterval();
const timeFilterRefreshInterval = useRefreshIntervalUpdates();
const time = useTimeRangeUpdates();
useEffect(
function syncTimRangeFromUrlState() {
if (globalState?.time !== undefined) {
timefilter.setTime({
from: globalState.time.from,
to: globalState.time.to,
});
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[globalState?.time?.from, globalState?.time?.to, globalState?.time?.ts]
);
useEffect(
function syncRefreshIntervalFromUrlState() {
if (globalState?.refreshInterval !== undefined) {
timefilter.setRefreshInterval({
pause: !!globalState?.refreshInterval?.pause,
value: globalState?.refreshInterval?.value,
});
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[globalState?.refreshInterval]
);
// eslint-disable-next-line react-hooks/exhaustive-deps
const setRefreshInterval = useCallback(
@ -69,7 +119,6 @@ export const DatePickerWrapper: FC = () => {
[setGlobalState]
);
const [time, setTime] = useState(timefilter.getTime());
const [recentlyUsedRanges, setRecentlyUsedRanges] = useState(getRecentlyUsedRanges());
const [isAutoRefreshSelectorEnabled, setIsAutoRefreshSelectorEnabled] = useState(
timefilter.isAutoRefreshSelectorEnabled()
@ -78,6 +127,57 @@ export const DatePickerWrapper: FC = () => {
timefilter.isTimeRangeSelectorEnabled()
);
const refreshInterval = useMemo(
(): RefreshInterval => globalState?.refreshInterval ?? timeFilterRefreshInterval,
// eslint-disable-next-line react-hooks/exhaustive-deps
[JSON.stringify(globalState?.refreshInterval), timeFilterRefreshInterval]
);
useEffect(
function warnAboutShortRefreshInterval() {
const isTooShort = refreshInterval.value < DEFAULT_REFRESH_INTERVAL_MS;
// Only warn about short interval with enabled auto-refresh.
if (!isTooShort || refreshInterval.pause) return;
toasts.warning({
title: i18n.translate(
'xpack.dataVisualizer.index.datePicker.shortRefreshIntervalURLWarningMessage',
{
defaultMessage:
'The refresh interval in the URL is shorter than the minimum supported by Machine Learning.',
}
),
body: wrapWithTheme(
<EuiButton
onClick={setRefreshInterval.bind(null, {
pause: refreshInterval.pause,
value: DEFAULT_REFRESH_INTERVAL_MS,
})}
>
<FormattedMessage
id="xpack.dataVisualizer.index.pageRefreshResetButton"
defaultMessage="Set to {defaultInterval}"
values={{
defaultInterval: `${DEFAULT_REFRESH_INTERVAL_MS / 1000}s`,
}}
/>
</EuiButton>,
theme$
),
toastLifeTimeMs: 30000,
});
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[
// eslint-disable-next-line react-hooks/exhaustive-deps
JSON.stringify(refreshInterval),
// eslint-disable-next-line react-hooks/exhaustive-deps
JSON.stringify(globalState?.refreshInterval),
setRefreshInterval,
]
);
const dateFormat = config.get('dateFormat');
const timePickerQuickRanges = config.get<TimePickerQuickRange[]>(
UI_SETTINGS.TIMEPICKER_QUICK_RANGES
@ -95,22 +195,7 @@ export const DatePickerWrapper: FC = () => {
useEffect(() => {
const subscriptions = new Subscription();
const refreshIntervalUpdate$ = timefilter.getRefreshIntervalUpdate$();
if (refreshIntervalUpdate$ !== undefined) {
subscriptions.add(
refreshIntervalUpdate$.subscribe((r) => {
setRefreshInterval(timefilter.getRefreshInterval());
})
);
}
const timeUpdate$ = timefilter.getTimeUpdate$();
if (timeUpdate$ !== undefined) {
subscriptions.add(
timeUpdate$.subscribe((v) => {
setTime(timefilter.getTime());
})
);
}
const enabledUpdated$ = timefilter.getEnabledUpdated$();
if (enabledUpdated$ !== undefined) {
subscriptions.add(
@ -124,15 +209,21 @@ export const DatePickerWrapper: FC = () => {
return function cleanup() {
subscriptions.unsubscribe();
};
}, [setRefreshInterval, timefilter]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
function updateFilter({ start, end }: Duration) {
const newTime = { from: start, to: end };
// Update timefilter for controllers listening for changes
timefilter.setTime(newTime);
setTime(newTime);
setRecentlyUsedRanges(getRecentlyUsedRanges());
}
const updateTimeFilter = useCallback(
({ start, end }: OnTimeChangeProps) => {
setRecentlyUsedRanges(getRecentlyUsedRanges());
setGlobalState('time', {
from: start,
to: end,
...(start === 'now' || end === 'now' ? { ts: Date.now() } : {}),
});
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[setGlobalState]
);
function updateInterval({
isPaused: pause,
@ -144,26 +235,44 @@ export const DatePickerWrapper: FC = () => {
setRefreshInterval({ pause, value });
}
/**
* Enforce pause when it's set to false with 0 refresh interval.
*/
const isPaused = refreshInterval.pause || (!refreshInterval.pause && !refreshInterval.value);
return isAutoRefreshSelectorEnabled || isTimeRangeSelectorEnabled ? (
<div className="mlNavigationMenu__datePickerWrapper">
<EuiSuperDatePicker
start={time.from}
end={time.to}
isPaused={isPaused}
isAutoRefreshOnly={!isTimeRangeSelectorEnabled}
refreshInterval={refreshInterval.value}
onTimeChange={updateFilter}
onRefresh={updateLastRefresh}
onRefreshChange={updateInterval}
recentlyUsedRanges={recentlyUsedRanges}
dateFormat={dateFormat}
commonlyUsedRanges={commonlyUsedRanges}
/>
</div>
<EuiFlexGroup
gutterSize="s"
alignItems="center"
className="mlNavigationMenu__datePickerWrapper"
>
<EuiFlexItem grow={false}>
<EuiSuperDatePicker
start={time.from}
end={time.to}
isPaused={refreshInterval.pause}
isAutoRefreshOnly={!isTimeRangeSelectorEnabled}
refreshInterval={refreshInterval.value || DEFAULT_REFRESH_INTERVAL_MS}
onTimeChange={updateTimeFilter}
onRefresh={updateLastRefresh}
onRefreshChange={updateInterval}
recentlyUsedRanges={recentlyUsedRanges}
dateFormat={dateFormat}
commonlyUsedRanges={commonlyUsedRanges}
/>
</EuiFlexItem>
{isTimeRangeSelectorEnabled ? null : (
<EuiFlexItem grow={false}>
<EuiButton
fill
color="primary"
iconType={'refresh'}
onClick={() => updateLastRefresh()}
data-test-subj="dataVisualizerRefreshPageButton"
>
<FormattedMessage
id="xpack.dataVisualizer.index.pageRefreshButton"
defaultMessage="Refresh"
/>
</EuiButton>
</EuiFlexItem>
)}
</EuiFlexGroup>
) : null;
};

View file

@ -6,6 +6,8 @@
*/
import { useEffect } from 'react';
import useObservable from 'react-use/lib/useObservable';
import { map } from 'rxjs/operators';
import { useDataVisualizerKibana } from '../../kibana_context';
interface UseTimefilterOptions {
@ -36,3 +38,22 @@ export const useTimefilter = ({
return timefilter;
};
export const useRefreshIntervalUpdates = () => {
const timefilter = useTimefilter();
return useObservable(
timefilter.getRefreshIntervalUpdate$().pipe(map(timefilter.getRefreshInterval)),
timefilter.getRefreshInterval()
);
};
export const useTimeRangeUpdates = (absolute = false) => {
const timefilter = useTimefilter();
const getTimeCallback = absolute
? timefilter.getAbsoluteTime.bind(timefilter)
: timefilter.getTime.bind(timefilter);
return useObservable(timefilter.getTimeUpdate$().pipe(map(getTimeCallback)), getTimeCallback());
};

View file

@ -57,6 +57,7 @@ export const ExplainLogRateSpikesPage: FC = () => {
'storage',
'uiSettings',
'unifiedSearch',
'theme',
])}
/>
)}

View file

@ -57,6 +57,7 @@ export const LogCategorizationPage: FC = () => {
'storage',
'uiSettings',
'unifiedSearch',
'theme',
])}
/>
)}

View file

@ -123,7 +123,7 @@ describe('Navigation Menu: <DatePickerWrapper />', () => {
refreshSubscription.unsubscribe();
});
test('should not allow disabled pause with 0 refresh interval', () => {
test('should set interval to default of 5s when pause is disabled and refresh interval is 0', () => {
// arrange
(useUrlState as jest.Mock).mockReturnValue([{ refreshInterval: { pause: false, value: 0 } }]);
@ -137,9 +137,10 @@ describe('Navigation Menu: <DatePickerWrapper />', () => {
render(<DatePickerWrapper />);
// assert
expect(displayWarningSpy).not.toHaveBeenCalled();
// Show warning that the interval set is too short
expect(displayWarningSpy).toHaveBeenCalled();
const calledWith = MockedEuiSuperDatePicker.mock.calls[0][0];
expect(calledWith.isPaused).toBe(true);
expect(calledWith.isPaused).toBe(false);
expect(calledWith.refreshInterval).toBe(5000);
});

View file

@ -126,18 +126,11 @@ export const DatePickerWrapper: FC = () => {
timefilter.isTimeRangeSelectorEnabled()
);
const refreshInterval = useMemo((): RefreshInterval => {
const resultInterval = globalState?.refreshInterval ?? timeFilterRefreshInterval;
/**
* Enforce pause when it's set to false with 0 refresh interval.
*/
const pause = resultInterval.pause || (!resultInterval.pause && resultInterval.value <= 0);
const value = resultInterval.value;
return { value, pause };
const refreshInterval = useMemo(
(): RefreshInterval => globalState?.refreshInterval ?? timeFilterRefreshInterval,
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(globalState?.refreshInterval), timeFilterRefreshInterval]);
[JSON.stringify(globalState?.refreshInterval), timeFilterRefreshInterval]
);
useEffect(
function warnAboutShortRefreshInterval() {
@ -251,6 +244,9 @@ export const DatePickerWrapper: FC = () => {
isPaused: boolean;
refreshInterval: number;
}) {
if (pause === false && value <= 0) {
setRefreshInterval({ pause, value: 5000 });
}
setRefreshInterval({ pause, value });
}