diff --git a/docs/sources/administration/configuration.md b/docs/sources/administration/configuration.md index 51ba6d5e8d2..e7bbdcb8827 100644 --- a/docs/sources/administration/configuration.md +++ b/docs/sources/administration/configuration.md @@ -549,9 +549,11 @@ Number dashboard versions to keep (per dashboard). Default: `20`, Minimum: `1`. > 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`. +As of Grafana v7.3, this also limits the refresh interval options in Explore. + ### default_home_dashboard_path Path to the default home dashboard. If this value is empty, then Grafana uses StaticRootPath + "dashboards/home.json" diff --git a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx index ffd38f08439..933fdf56d0f 100644 --- a/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx +++ b/packages/grafana-ui/src/components/RefreshPicker/RefreshPicker.tsx @@ -9,6 +9,7 @@ import memoizeOne from 'memoize-one'; import { GrafanaTheme } from '@grafana/data'; 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']; const getStyles = memoizeOne((theme: GrafanaTheme) => { diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index 585052693c6..11f36309f99 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -22,7 +22,7 @@ export { EmptySearchResult } from './EmptySearchResult/EmptySearchResult'; export { PieChart, PieChartType } from './PieChart/PieChart'; export { UnitPicker } from './UnitPicker/UnitPicker'; export { StatsPicker } from './StatsPicker/StatsPicker'; -export { RefreshPicker } from './RefreshPicker/RefreshPicker'; +export { RefreshPicker, defaultIntervals } from './RefreshPicker/RefreshPicker'; export { TimeRangePicker } from './TimePicker/TimeRangePicker'; export { TimeOfDayPicker } from './TimePicker/TimeOfDayPicker'; export { TimeZonePicker } from './TimePicker/TimeZonePicker'; diff --git a/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx b/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx index 6b75bc6d2ef..8f3cdb02ef9 100644 --- a/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx @@ -12,12 +12,11 @@ import { TimeRange } from '@grafana/data'; import { updateTimeZoneForSession } from 'app/features/profile/state/reducers'; // 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'; // Utils & Services import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; -import { defaultIntervals } from '@grafana/ui/src/components/RefreshPicker/RefreshPicker'; import { appEvents } from 'app/core/core'; const getStyles = stylesFactory((theme: GrafanaTheme) => { diff --git a/public/app/features/dashboard/components/DashboardSettings/AutoRefreshIntervals.test.tsx b/public/app/features/dashboard/components/DashboardSettings/AutoRefreshIntervals.test.tsx index a9cf7edf21c..0cc87cacf08 100644 --- a/public/app/features/dashboard/components/DashboardSettings/AutoRefreshIntervals.test.tsx +++ b/public/app/features/dashboard/components/DashboardSettings/AutoRefreshIntervals.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; 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 { TimeSrv } from '../../services/TimeSrv'; diff --git a/public/app/features/dashboard/components/DashboardSettings/AutoRefreshIntervals.tsx b/public/app/features/dashboard/components/DashboardSettings/AutoRefreshIntervals.tsx index 9d7ee31c3a3..b17c72cebbd 100644 --- a/public/app/features/dashboard/components/DashboardSettings/AutoRefreshIntervals.tsx +++ b/public/app/features/dashboard/components/DashboardSettings/AutoRefreshIntervals.tsx @@ -1,6 +1,5 @@ import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { Input, Tooltip } from '@grafana/ui'; -import { defaultIntervals } from '@grafana/ui/src/components/RefreshPicker/RefreshPicker'; +import { Input, Tooltip, defaultIntervals } from '@grafana/ui'; import { getTimeSrv } from '../../services/TimeSrv'; diff --git a/public/app/features/explore/RunButton.test.tsx b/public/app/features/explore/RunButton.test.tsx new file mode 100644 index 00000000000..c006c602318 --- /dev/null +++ b/public/app/features/explore/RunButton.test.tsx @@ -0,0 +1,47 @@ +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(); + 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; + +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); + }); + }); +}); diff --git a/public/app/features/explore/RunButton.tsx b/public/app/features/explore/RunButton.tsx index abd43166c1d..ab4f7634f6c 100644 --- a/public/app/features/explore/RunButton.tsx +++ b/public/app/features/explore/RunButton.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { RefreshPicker } from '@grafana/ui'; +import { RefreshPicker, defaultIntervals } from '@grafana/ui'; import { selectors } from '@grafana/e2e-selectors'; import memoizeOne from 'memoize-one'; import { css } from 'emotion'; @@ -7,6 +7,8 @@ import classNames from 'classnames'; import { ResponsiveButton } from './ResponsiveButton'; +import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; + const getStyles = memoizeOne(() => { return { selectButtonOverride: css` @@ -18,7 +20,7 @@ const getStyles = memoizeOne(() => { }; }); -type Props = { +export type Props = { splitted: boolean; loading: boolean; isLive: boolean; @@ -31,6 +33,7 @@ type Props = { export function RunButton(props: Props) { const { splitted, loading, onRun, onChangeRefreshInterval, refreshInterval, showDropdown, isLive } = props; const styles = getStyles(); + const intervals = getTimeSrv().getValidIntervals(defaultIntervals); const runButton = ( ); }