mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboards: Allow custom quick time ranges specified in dashboard model (#93724)
* TimeRangePicker: allow to customize quick ranges per dashboard * TimeRangePicker: show selected custom time range using its name * rangeutil: add tests for describeTextRange + quickRanges * Fix up tests, and add an extra case for hidden time ranges * Don't construct an object to find options, add findRangeInOptions util * fix type errors detected by TypeScript --------- Co-authored-by: joshhunt <josh@trtr.co>
This commit is contained in:
parent
cfae9d20d2
commit
eb2f8182c0
@ -136,6 +136,18 @@ The grid has a negative gravity that moves panels up if there is empty space abo
|
|||||||
"now": true,
|
"now": true,
|
||||||
"hidden": false,
|
"hidden": false,
|
||||||
"nowDelay": "",
|
"nowDelay": "",
|
||||||
|
"quick_ranges": [
|
||||||
|
{
|
||||||
|
"display": "Last 6 hours"
|
||||||
|
"from": "now-6h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"display": "Last 7 days"
|
||||||
|
"from": "now-7d",
|
||||||
|
"to": "now"
|
||||||
|
}
|
||||||
|
],
|
||||||
"refresh_intervals": [
|
"refresh_intervals": [
|
||||||
"5s",
|
"5s",
|
||||||
"10s",
|
"10s",
|
||||||
@ -163,6 +175,7 @@ Usage of the fields is explained below:
|
|||||||
| **now** | |
|
| **now** | |
|
||||||
| **hidden** | whether timepicker is hidden or not |
|
| **hidden** | whether timepicker is hidden or not |
|
||||||
| **nowDelay** | override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values. |
|
| **nowDelay** | override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values. |
|
||||||
|
| **quick_ranges** | custom quick ranges |
|
||||||
| **refresh_intervals** | interval options available in the refresh picker dropdown |
|
| **refresh_intervals** | interval options available in the refresh picker dropdown |
|
||||||
| **status** | |
|
| **status** | |
|
||||||
| **type** | |
|
| **type** | |
|
||||||
|
@ -459,6 +459,13 @@ lineage: schemas: [{
|
|||||||
options: _
|
options: _
|
||||||
} @cuetsy(kind="interface") @grafana(TSVeneer="type")
|
} @cuetsy(kind="interface") @grafana(TSVeneer="type")
|
||||||
|
|
||||||
|
// Counterpart for TypeScript's TimeOption type.
|
||||||
|
#TimeOption: {
|
||||||
|
display: string
|
||||||
|
from: string
|
||||||
|
to: string
|
||||||
|
} @cuetsy(kind="interface") @grafana(TSVeneer="type")
|
||||||
|
|
||||||
// Time picker configuration
|
// Time picker configuration
|
||||||
// It defines the default config for the time picker and the refresh picker for the specific dashboard.
|
// It defines the default config for the time picker and the refresh picker for the specific dashboard.
|
||||||
#TimePickerConfig: {
|
#TimePickerConfig: {
|
||||||
@ -468,6 +475,8 @@ lineage: schemas: [{
|
|||||||
refresh_intervals?: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
|
refresh_intervals?: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
|
||||||
// Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.
|
// Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.
|
||||||
time_options?: [...string] | *["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
|
time_options?: [...string] | *["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
|
||||||
|
// Quick ranges for time picker.
|
||||||
|
quick_ranges?: [...#TimeOption]
|
||||||
// Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
|
// Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
|
||||||
nowDelay?: string
|
nowDelay?: string
|
||||||
} @cuetsy(kind="interface") @grafana(TSVeneer="type")
|
} @cuetsy(kind="interface") @grafana(TSVeneer="type")
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { each } from 'lodash';
|
|
||||||
|
|
||||||
import { RawTimeRange, TimeRange, TimeZone, IntervalValues, RelativeTimeRange, TimeOption } from '../types/time';
|
import { RawTimeRange, TimeRange, TimeZone, IntervalValues, RelativeTimeRange, TimeOption } from '../types/time';
|
||||||
|
|
||||||
import * as dateMath from './datemath';
|
import * as dateMath from './datemath';
|
||||||
@ -17,7 +15,7 @@ const spans: { [key: string]: { display: string; section?: number } } = {
|
|||||||
y: { display: 'year' },
|
y: { display: 'year' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const rangeOptions: TimeOption[] = [
|
const BASE_RANGE_OPTIONS: TimeOption[] = [
|
||||||
{ from: 'now/d', to: 'now/d', display: 'Today' },
|
{ from: 'now/d', to: 'now/d', display: 'Today' },
|
||||||
{ from: 'now/d', to: 'now', display: 'Today so far' },
|
{ from: 'now/d', to: 'now', display: 'Today so far' },
|
||||||
{ from: 'now/w', to: 'now/w', display: 'This week' },
|
{ from: 'now/w', to: 'now/w', display: 'This week' },
|
||||||
@ -66,7 +64,7 @@ const rangeOptions: TimeOption[] = [
|
|||||||
{ from: 'now/fy', to: 'now/fy', display: 'This fiscal year' },
|
{ from: 'now/fy', to: 'now/fy', display: 'This fiscal year' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const hiddenRangeOptions: TimeOption[] = [
|
const HIDDEN_RANGE_OPTIONS: TimeOption[] = [
|
||||||
{ from: 'now', to: 'now+1m', display: 'Next minute' },
|
{ from: 'now', to: 'now+1m', display: 'Next minute' },
|
||||||
{ from: 'now', to: 'now+5m', display: 'Next 5 minutes' },
|
{ from: 'now', to: 'now+5m', display: 'Next 5 minutes' },
|
||||||
{ from: 'now', to: 'now+15m', display: 'Next 15 minutes' },
|
{ from: 'now', to: 'now+15m', display: 'Next 15 minutes' },
|
||||||
@ -86,13 +84,11 @@ const hiddenRangeOptions: TimeOption[] = [
|
|||||||
{ from: 'now', to: 'now+5y', display: 'Next 5 years' },
|
{ from: 'now', to: 'now+5y', display: 'Next 5 years' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const rangeIndex: Record<string, TimeOption> = {};
|
const STANDARD_RANGE_OPTIONS = BASE_RANGE_OPTIONS.concat(HIDDEN_RANGE_OPTIONS);
|
||||||
each(rangeOptions, (frame) => {
|
|
||||||
rangeIndex[frame.from + ' to ' + frame.to] = frame;
|
function findRangeInOptions(range: RawTimeRange, options: TimeOption[]) {
|
||||||
});
|
return options.find((option) => option.from === range.from && option.to === range.to);
|
||||||
each(hiddenRangeOptions, (frame) => {
|
}
|
||||||
rangeIndex[frame.from + ' to ' + frame.to] = frame;
|
|
||||||
});
|
|
||||||
|
|
||||||
// handles expressions like
|
// handles expressions like
|
||||||
// 5m
|
// 5m
|
||||||
@ -106,7 +102,7 @@ export function describeTextRange(expr: string): TimeOption {
|
|||||||
expr = (isLast ? 'now-' : 'now') + expr;
|
expr = (isLast ? 'now-' : 'now') + expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opt = rangeIndex[expr + ' to now'];
|
let opt = findRangeInOptions({ from: expr, to: 'now' }, STANDARD_RANGE_OPTIONS);
|
||||||
if (opt) {
|
if (opt) {
|
||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
@ -141,17 +137,15 @@ export function describeTextRange(expr: string): TimeOption {
|
|||||||
/**
|
/**
|
||||||
* Use this function to get a properly formatted string representation of a {@link @grafana/data:RawTimeRange | range}.
|
* Use this function to get a properly formatted string representation of a {@link @grafana/data:RawTimeRange | range}.
|
||||||
*
|
*
|
||||||
* @example
|
|
||||||
* ```
|
|
||||||
* // Prints "2":
|
|
||||||
* console.log(add(1,1));
|
|
||||||
* ```
|
|
||||||
* @category TimeUtils
|
* @category TimeUtils
|
||||||
* @param range - a time range (usually specified by the TimePicker)
|
* @param range - a time range (usually specified by the TimePicker)
|
||||||
|
* @param timeZone - optional time zone.
|
||||||
|
* @param quickRanges - optional dashboard's custom quick ranges to pick range names from.
|
||||||
* @alpha
|
* @alpha
|
||||||
*/
|
*/
|
||||||
export function describeTimeRange(range: RawTimeRange, timeZone?: TimeZone): string {
|
export function describeTimeRange(range: RawTimeRange, timeZone?: TimeZone, quickRanges?: TimeOption[]): string {
|
||||||
const option = rangeIndex[range.from.toString() + ' to ' + range.to.toString()];
|
const rangeOptions = quickRanges ? quickRanges.concat(STANDARD_RANGE_OPTIONS) : STANDARD_RANGE_OPTIONS;
|
||||||
|
const option = findRangeInOptions(range, rangeOptions);
|
||||||
|
|
||||||
if (option) {
|
if (option) {
|
||||||
return option.display;
|
return option.display;
|
||||||
|
@ -73,6 +73,7 @@ export type {
|
|||||||
VariableModel,
|
VariableModel,
|
||||||
DataSourceRef,
|
DataSourceRef,
|
||||||
DataTransformerConfig,
|
DataTransformerConfig,
|
||||||
|
TimeOption,
|
||||||
TimePickerConfig,
|
TimePickerConfig,
|
||||||
Panel,
|
Panel,
|
||||||
FieldConfigSource,
|
FieldConfigSource,
|
||||||
|
@ -651,6 +651,15 @@ export interface DataTransformerConfig {
|
|||||||
topic?: ('series' | 'annotations' | 'alertStates'); // replaced with common.DataTopic
|
topic?: ('series' | 'annotations' | 'alertStates'); // replaced with common.DataTopic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counterpart for TypeScript's TimeOption type.
|
||||||
|
*/
|
||||||
|
export interface TimeOption {
|
||||||
|
display: string;
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time picker configuration
|
* Time picker configuration
|
||||||
* It defines the default config for the time picker and the refresh picker for the specific dashboard.
|
* It defines the default config for the time picker and the refresh picker for the specific dashboard.
|
||||||
@ -664,6 +673,10 @@ export interface TimePickerConfig {
|
|||||||
* Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
|
* Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
|
||||||
*/
|
*/
|
||||||
nowDelay?: string;
|
nowDelay?: string;
|
||||||
|
/**
|
||||||
|
* Quick ranges for time picker.
|
||||||
|
*/
|
||||||
|
quick_ranges?: Array<TimeOption>;
|
||||||
/**
|
/**
|
||||||
* Interval options available in the refresh picker dropdown.
|
* Interval options available in the refresh picker dropdown.
|
||||||
*/
|
*/
|
||||||
@ -676,6 +689,7 @@ export interface TimePickerConfig {
|
|||||||
|
|
||||||
export const defaultTimePickerConfig: Partial<TimePickerConfig> = {
|
export const defaultTimePickerConfig: Partial<TimePickerConfig> = {
|
||||||
hidden: false,
|
hidden: false,
|
||||||
|
quick_ranges: [],
|
||||||
refresh_intervals: ['5s', '10s', '30s', '1m', '5m', '15m', '30m', '1h', '2h', '1d'],
|
refresh_intervals: ['5s', '10s', '30s', '1m', '5m', '15m', '30m', '1h', '2h', '1d'],
|
||||||
time_options: ['5m', '15m', '1h', '6h', '12h', '24h', '2d', '7d', '30d'],
|
time_options: ['5m', '15m', '1h', '6h', '12h', '24h', '2d', '7d', '30d'],
|
||||||
};
|
};
|
||||||
|
@ -62,6 +62,8 @@ export interface DataTransformerConfig<TOptions = any> extends raw.DataTransform
|
|||||||
topic?: DataTopic;
|
topic?: DataTopic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TimeOption extends raw.TimeOption {}
|
||||||
|
|
||||||
export interface TimePickerConfig extends raw.TimePickerConfig {}
|
export interface TimePickerConfig extends raw.TimePickerConfig {}
|
||||||
|
|
||||||
export const defaultDashboard = raw.defaultDashboard as Dashboard;
|
export const defaultDashboard = raw.defaultDashboard as Dashboard;
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
GrafanaTheme2,
|
GrafanaTheme2,
|
||||||
dateTimeFormat,
|
dateTimeFormat,
|
||||||
timeZoneFormatUserFriendly,
|
timeZoneFormatUserFriendly,
|
||||||
|
TimeOption,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
TimeZone,
|
TimeZone,
|
||||||
dateMath,
|
dateMath,
|
||||||
@ -55,6 +56,7 @@ export interface TimeRangePickerProps {
|
|||||||
onZoom: () => void;
|
onZoom: () => void;
|
||||||
onError?: (error?: string) => void;
|
onError?: (error?: string) => void;
|
||||||
history?: TimeRange[];
|
history?: TimeRange[];
|
||||||
|
quickRanges?: TimeOption[];
|
||||||
hideQuickRanges?: boolean;
|
hideQuickRanges?: boolean;
|
||||||
widthOverride?: number;
|
widthOverride?: number;
|
||||||
isOnCanvas?: boolean;
|
isOnCanvas?: boolean;
|
||||||
@ -81,6 +83,7 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
|
|||||||
history,
|
history,
|
||||||
onChangeTimeZone,
|
onChangeTimeZone,
|
||||||
onChangeFiscalYearStartMonth,
|
onChangeFiscalYearStartMonth,
|
||||||
|
quickRanges,
|
||||||
hideQuickRanges,
|
hideQuickRanges,
|
||||||
widthOverride,
|
widthOverride,
|
||||||
isOnCanvas,
|
isOnCanvas,
|
||||||
@ -141,7 +144,7 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
|
|||||||
const isFromAfterTo = value?.to?.isBefore(value.from);
|
const isFromAfterTo = value?.to?.isBefore(value.from);
|
||||||
const timePickerIcon = isFromAfterTo ? 'exclamation-triangle' : 'clock-nine';
|
const timePickerIcon = isFromAfterTo ? 'exclamation-triangle' : 'clock-nine';
|
||||||
|
|
||||||
const currentTimeRange = formattedRange(value, timeZone);
|
const currentTimeRange = formattedRange(value, timeZone, quickRanges);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ButtonGroup className={styles.container}>
|
<ButtonGroup className={styles.container}>
|
||||||
@ -187,7 +190,7 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
|
|||||||
fiscalYearStartMonth={fiscalYearStartMonth}
|
fiscalYearStartMonth={fiscalYearStartMonth}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
quickOptions={quickOptions}
|
quickOptions={quickRanges || quickOptions}
|
||||||
history={history}
|
history={history}
|
||||||
showHistory
|
showHistory
|
||||||
widthOverride={widthOverride}
|
widthOverride={widthOverride}
|
||||||
@ -255,9 +258,9 @@ export const TimePickerTooltip = ({ timeRange, timeZone }: { timeRange: TimeRang
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
type LabelProps = Pick<TimeRangePickerProps, 'hideText' | 'value' | 'timeZone'>;
|
type LabelProps = Pick<TimeRangePickerProps, 'hideText' | 'value' | 'timeZone' | 'quickRanges'>;
|
||||||
|
|
||||||
export const TimePickerButtonLabel = memo<LabelProps>(({ hideText, value, timeZone }) => {
|
export const TimePickerButtonLabel = memo<LabelProps>(({ hideText, value, timeZone, quickRanges }) => {
|
||||||
const styles = useStyles2(getLabelStyles);
|
const styles = useStyles2(getLabelStyles);
|
||||||
|
|
||||||
if (hideText) {
|
if (hideText) {
|
||||||
@ -266,7 +269,7 @@ export const TimePickerButtonLabel = memo<LabelProps>(({ hideText, value, timeZo
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={styles.container} aria-live="polite" aria-atomic="true">
|
<span className={styles.container} aria-live="polite" aria-atomic="true">
|
||||||
<span>{formattedRange(value, timeZone)}</span>
|
<span>{formattedRange(value, timeZone, quickRanges)}</span>
|
||||||
<span className={styles.utc}>{rangeUtil.describeTimeRangeAbbreviation(value, timeZone)}</span>
|
<span className={styles.utc}>{rangeUtil.describeTimeRangeAbbreviation(value, timeZone)}</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
@ -274,12 +277,12 @@ export const TimePickerButtonLabel = memo<LabelProps>(({ hideText, value, timeZo
|
|||||||
|
|
||||||
TimePickerButtonLabel.displayName = 'TimePickerButtonLabel';
|
TimePickerButtonLabel.displayName = 'TimePickerButtonLabel';
|
||||||
|
|
||||||
const formattedRange = (value: TimeRange, timeZone?: TimeZone) => {
|
const formattedRange = (value: TimeRange, timeZone?: TimeZone, quickRanges?: TimeOption[]) => {
|
||||||
const adjustedTimeRange = {
|
const adjustedTimeRange = {
|
||||||
to: dateMath.isMathString(value.raw.to) ? value.raw.to : value.to,
|
to: dateMath.isMathString(value.raw.to) ? value.raw.to : value.to,
|
||||||
from: dateMath.isMathString(value.raw.from) ? value.raw.from : value.from,
|
from: dateMath.isMathString(value.raw.from) ? value.raw.from : value.from,
|
||||||
};
|
};
|
||||||
return rangeUtil.describeTimeRange(adjustedTimeRange, timeZone);
|
return rangeUtil.describeTimeRange(adjustedTimeRange, timeZone, quickRanges);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => {
|
||||||
|
@ -29,6 +29,18 @@ const (
|
|||||||
DashboardCursorSyncTooltip DashboardCursorSync = 2
|
DashboardCursorSyncTooltip DashboardCursorSync = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Counterpart for TypeScript's TimeOption type.
|
||||||
|
type TimeOption struct {
|
||||||
|
Display string `json:"display"`
|
||||||
|
From string `json:"from"`
|
||||||
|
To string `json:"to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTimeOption creates a new TimeOption object.
|
||||||
|
func NewTimeOption() *TimeOption {
|
||||||
|
return &TimeOption{}
|
||||||
|
}
|
||||||
|
|
||||||
// Time picker configuration
|
// Time picker configuration
|
||||||
// It defines the default config for the time picker and the refresh picker for the specific dashboard.
|
// It defines the default config for the time picker and the refresh picker for the specific dashboard.
|
||||||
type TimePickerConfig struct {
|
type TimePickerConfig struct {
|
||||||
@ -38,6 +50,8 @@ type TimePickerConfig struct {
|
|||||||
RefreshIntervals []string `json:"refresh_intervals,omitempty"`
|
RefreshIntervals []string `json:"refresh_intervals,omitempty"`
|
||||||
// Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.
|
// Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.
|
||||||
TimeOptions []string `json:"time_options,omitempty"`
|
TimeOptions []string `json:"time_options,omitempty"`
|
||||||
|
// Quick ranges for time picker.
|
||||||
|
QuickRanges []TimeOption `json:"quick_ranges,omitempty"`
|
||||||
// Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
|
// Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
|
||||||
NowDelay *string `json:"nowDelay,omitempty"`
|
NowDelay *string `json:"nowDelay,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { rangeUtil, dateTime } from '@grafana/data';
|
import { rangeUtil, dateTime, TimeOption } from '@grafana/data';
|
||||||
|
|
||||||
describe('rangeUtil', () => {
|
describe('rangeUtil', () => {
|
||||||
describe('Can get range text described', () => {
|
describe('Can get range text described', () => {
|
||||||
@ -57,6 +57,11 @@ describe('rangeUtil', () => {
|
|||||||
expect(text).toBe('now/d+6h to now');
|
expect(text).toBe('now/d+6h to now');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('matches hidden time ranges', () => {
|
||||||
|
const text = rangeUtil.describeTimeRange({ from: 'now', to: 'now+30m' });
|
||||||
|
expect(text).toBe('Next 30 minutes');
|
||||||
|
});
|
||||||
|
|
||||||
it('Date range with absolute to now', () => {
|
it('Date range with absolute to now', () => {
|
||||||
const text = rangeUtil.describeTimeRange({
|
const text = rangeUtil.describeTimeRange({
|
||||||
from: dateTime([2014, 10, 10, 2, 3, 4]),
|
from: dateTime([2014, 10, 10, 2, 3, 4]),
|
||||||
@ -103,5 +108,17 @@ describe('rangeUtil', () => {
|
|||||||
const text = rangeUtil.describeTimeRange({ from: 'now-6h', to: 'now+1h' });
|
const text = rangeUtil.describeTimeRange({ from: 'now-6h', to: 'now+1h' });
|
||||||
expect(text).toBe('now-6h to now+1h');
|
expect(text).toBe('now-6h to now+1h');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Date range that is in custom quick ranges', () => {
|
||||||
|
const opt: TimeOption = { from: 'now-4w/w', to: 'now-1w/w', display: 'Previous 4 weeks' };
|
||||||
|
const text = rangeUtil.describeTimeRange({ from: opt.from, to: opt.to }, undefined, [opt]);
|
||||||
|
expect(text).toBe('Previous 4 weeks');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Date range description from custom quick ranges has higher priority', () => {
|
||||||
|
const opt: TimeOption = { from: 'now/d', to: 'now/d', display: 'This day' };
|
||||||
|
const text = rangeUtil.describeTimeRange({ from: opt.from, to: opt.to }, undefined, [opt]);
|
||||||
|
expect(text).toBe('This day'); // overrides 'Today'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -93,7 +93,7 @@ export class DashNavTimeControls extends Component<Props> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { dashboard, isOnCanvas } = this.props;
|
const { dashboard, isOnCanvas } = this.props;
|
||||||
const { refresh_intervals } = dashboard.timepicker;
|
const { quick_ranges, refresh_intervals } = dashboard.timepicker;
|
||||||
const intervals = getTimeSrv().getValidIntervals(refresh_intervals || defaultIntervals);
|
const intervals = getTimeSrv().getValidIntervals(refresh_intervals || defaultIntervals);
|
||||||
|
|
||||||
const timePickerValue = getTimeSrv().timeRange();
|
const timePickerValue = getTimeSrv().timeRange();
|
||||||
@ -122,6 +122,7 @@ export class DashNavTimeControls extends Component<Props> {
|
|||||||
isOnCanvas={isOnCanvas}
|
isOnCanvas={isOnCanvas}
|
||||||
onToolbarTimePickerClick={this.props.onToolbarTimePickerClick}
|
onToolbarTimePickerClick={this.props.onToolbarTimePickerClick}
|
||||||
weekStart={weekStart}
|
weekStart={weekStart}
|
||||||
|
quickRanges={quick_ranges}
|
||||||
/>
|
/>
|
||||||
<RefreshPicker
|
<RefreshPicker
|
||||||
onIntervalChanged={this.onChangeRefreshInterval}
|
onIntervalChanged={this.onChangeRefreshInterval}
|
||||||
|
Loading…
Reference in New Issue
Block a user