Commit 1760fdd5 by Elliot Pryde Committed by GitHub

Explore: respect min_refresh_interval (#27988)

* Explore: respect min_refresh_interval

Fixes #27494

* fixup! Explore: respect min_refresh_interval

* fixup! Explore: respect min_refresh_interval

* UI: export defaultIntervals from refresh picker

* fixup! Explore: respect min_refresh_interval

Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
parent 392c5bdf
...@@ -549,9 +549,11 @@ Number dashboard versions to keep (per dashboard). Default: `20`, Minimum: `1`. ...@@ -549,9 +549,11 @@ Number dashboard versions to keep (per dashboard). Default: `20`, Minimum: `1`.
> Only available in Grafana v6.7+. > Only available in Grafana v6.7+.
This prevents users from setting the dashboard refresh interval of a lower than given interval. Per default this is 5 seconds. This feature prevents users from setting the dashboard refresh interval to a lower value than a given interval value. The default interval value is 5 seconds.
The interval string is a possibly signed sequence of decimal numbers, followed by a unit suffix (ms, s, m, h, d), e.g. `30s` or `1m`. The interval string is a possibly signed sequence of decimal numbers, followed by a unit suffix (ms, s, m, h, d), e.g. `30s` or `1m`.
As of Grafana v7.3, this also limits the refresh interval options in Explore.
### default_home_dashboard_path ### default_home_dashboard_path
Path to the default home dashboard. If this value is empty, then Grafana uses StaticRootPath + "dashboards/home.json" Path to the default home dashboard. If this value is empty, then Grafana uses StaticRootPath + "dashboards/home.json"
......
...@@ -9,6 +9,7 @@ import memoizeOne from 'memoize-one'; ...@@ -9,6 +9,7 @@ import memoizeOne from 'memoize-one';
import { GrafanaTheme } from '@grafana/data'; import { GrafanaTheme } from '@grafana/data';
import { withTheme } from '../../themes'; import { withTheme } from '../../themes';
// Default intervals used in the refresh picker component
export const defaultIntervals = ['5s', '10s', '30s', '1m', '5m', '15m', '30m', '1h', '2h', '1d']; export const defaultIntervals = ['5s', '10s', '30s', '1m', '5m', '15m', '30m', '1h', '2h', '1d'];
const getStyles = memoizeOne((theme: GrafanaTheme) => { const getStyles = memoizeOne((theme: GrafanaTheme) => {
......
...@@ -22,7 +22,7 @@ export { EmptySearchResult } from './EmptySearchResult/EmptySearchResult'; ...@@ -22,7 +22,7 @@ export { EmptySearchResult } from './EmptySearchResult/EmptySearchResult';
export { PieChart, PieChartType } from './PieChart/PieChart'; export { PieChart, PieChartType } from './PieChart/PieChart';
export { UnitPicker } from './UnitPicker/UnitPicker'; export { UnitPicker } from './UnitPicker/UnitPicker';
export { StatsPicker } from './StatsPicker/StatsPicker'; export { StatsPicker } from './StatsPicker/StatsPicker';
export { RefreshPicker } from './RefreshPicker/RefreshPicker'; export { RefreshPicker, defaultIntervals } from './RefreshPicker/RefreshPicker';
export { TimeRangePicker } from './TimePicker/TimeRangePicker'; export { TimeRangePicker } from './TimePicker/TimeRangePicker';
export { TimeOfDayPicker } from './TimePicker/TimeOfDayPicker'; export { TimeOfDayPicker } from './TimePicker/TimeOfDayPicker';
export { TimeZonePicker } from './TimePicker/TimeZonePicker'; export { TimeZonePicker } from './TimePicker/TimeZonePicker';
......
...@@ -12,12 +12,11 @@ import { TimeRange } from '@grafana/data'; ...@@ -12,12 +12,11 @@ import { TimeRange } from '@grafana/data';
import { updateTimeZoneForSession } from 'app/features/profile/state/reducers'; import { updateTimeZoneForSession } from 'app/features/profile/state/reducers';
// Components // Components
import { RefreshPicker, withTheme, stylesFactory, Themeable } from '@grafana/ui'; import { RefreshPicker, withTheme, stylesFactory, Themeable, defaultIntervals } from '@grafana/ui';
import { TimePickerWithHistory } from 'app/core/components/TimePicker/TimePickerWithHistory'; import { TimePickerWithHistory } from 'app/core/components/TimePicker/TimePickerWithHistory';
// Utils & Services // Utils & Services
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { defaultIntervals } from '@grafana/ui/src/components/RefreshPicker/RefreshPicker';
import { appEvents } from 'app/core/core'; import { appEvents } from 'app/core/core';
const getStyles = stylesFactory((theme: GrafanaTheme) => { const getStyles = stylesFactory((theme: GrafanaTheme) => {
......
import React from 'react'; import React from 'react';
import { render, screen } from '@testing-library/react'; import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event'; import userEvent from '@testing-library/user-event';
import { defaultIntervals } from '@grafana/ui/src/components/RefreshPicker/RefreshPicker'; import { defaultIntervals } from '@grafana/ui';
import { AutoRefreshIntervals, getValidIntervals, Props, validateIntervals } from './AutoRefreshIntervals'; import { AutoRefreshIntervals, getValidIntervals, Props, validateIntervals } from './AutoRefreshIntervals';
import { TimeSrv } from '../../services/TimeSrv'; import { TimeSrv } from '../../services/TimeSrv';
......
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { Input, Tooltip } from '@grafana/ui'; import { Input, Tooltip, defaultIntervals } from '@grafana/ui';
import { defaultIntervals } from '@grafana/ui/src/components/RefreshPicker/RefreshPicker';
import { getTimeSrv } from '../../services/TimeSrv'; import { getTimeSrv } from '../../services/TimeSrv';
......
import React from 'react';
import { RunButton, Props } from './RunButton';
import { RefreshPicker } from '@grafana/ui';
import { shallow } from 'enzyme';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
const setup = (propOverrides?: object) => {
const props: Props = {
splitted: false,
loading: false,
isLive: false,
onRun: jest.fn(),
refreshInterval: '5m',
onChangeRefreshInterval: jest.fn(),
showDropdown: false,
};
Object.assign(props, propOverrides);
const wrapper = shallow(<RunButton {...props} />);
return wrapper;
};
const validIntervals = ['1d'];
jest.mock('app/features/dashboard/services/TimeSrv', () => ({
getTimeSrv: jest.fn().mockReturnValue({
getValidIntervals(intervals: string[]): string[] {
return validIntervals;
},
}),
}));
const getTimeSrvMock = (getTimeSrv as any) as jest.Mock<TimeSrv>;
beforeEach(() => {
getTimeSrvMock.mockClear();
});
describe('RunButton', () => {
describe('if showdropdown is set', () => {
it('should render a RefreshPicker with only valid intervals', () => {
const wrapper = setup({ showDropdown: true });
expect(wrapper.find(RefreshPicker)).toHaveLength(1);
expect(wrapper.find(RefreshPicker).props().intervals).toEqual(validIntervals);
});
});
});
import React from 'react'; import React from 'react';
import { RefreshPicker } from '@grafana/ui'; import { RefreshPicker, defaultIntervals } from '@grafana/ui';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import memoizeOne from 'memoize-one'; import memoizeOne from 'memoize-one';
import { css } from 'emotion'; import { css } from 'emotion';
...@@ -7,6 +7,8 @@ import classNames from 'classnames'; ...@@ -7,6 +7,8 @@ import classNames from 'classnames';
import { ResponsiveButton } from './ResponsiveButton'; import { ResponsiveButton } from './ResponsiveButton';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
const getStyles = memoizeOne(() => { const getStyles = memoizeOne(() => {
return { return {
selectButtonOverride: css` selectButtonOverride: css`
...@@ -18,7 +20,7 @@ const getStyles = memoizeOne(() => { ...@@ -18,7 +20,7 @@ const getStyles = memoizeOne(() => {
}; };
}); });
type Props = { export type Props = {
splitted: boolean; splitted: boolean;
loading: boolean; loading: boolean;
isLive: boolean; isLive: boolean;
...@@ -31,6 +33,7 @@ type Props = { ...@@ -31,6 +33,7 @@ type Props = {
export function RunButton(props: Props) { export function RunButton(props: Props) {
const { splitted, loading, onRun, onChangeRefreshInterval, refreshInterval, showDropdown, isLive } = props; const { splitted, loading, onRun, onChangeRefreshInterval, refreshInterval, showDropdown, isLive } = props;
const styles = getStyles(); const styles = getStyles();
const intervals = getTimeSrv().getValidIntervals(defaultIntervals);
const runButton = ( const runButton = (
<ResponsiveButton <ResponsiveButton
...@@ -57,6 +60,7 @@ export function RunButton(props: Props) { ...@@ -57,6 +60,7 @@ export function RunButton(props: Props) {
styles.selectButtonOverride styles.selectButtonOverride
}`} }`}
refreshButton={runButton} refreshButton={runButton}
intervals={intervals}
/> />
); );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment