// Libraries import React, { PureComponent, ChangeEvent, FocusEvent } from 'react'; // Utils import { isValidTimeSpan } from '@grafana/data/src/utils/rangeutil'; // Components import { DataSourceSelectItem, EventsWithValidation, Input, InputStatus, Switch, ValidationEvents } from '@grafana/ui'; import { DataSourceOption } from './DataSourceOption'; import { FormLabel } from '@grafana/ui'; // Types import { PanelModel } from '../state'; const timeRangeValidationEvents: ValidationEvents = { [EventsWithValidation.onBlur]: [ { rule: value => { if (!value) { return true; } return isValidTimeSpan(value); }, errorMessage: 'Not a valid timespan', }, ], }; const emptyToNull = (value: string) => { return value === '' ? null : value; }; interface Props { panel: PanelModel; datasource: DataSourceSelectItem; } interface State { relativeTime: string; timeShift: string; cacheTimeout: string; maxDataPoints: string; interval: string; hideTimeOverride: boolean; } export class QueryOptions extends PureComponent { allOptions = { cacheTimeout: { label: 'Cache timeout', placeholder: '60', name: 'cacheTimeout', tooltipInfo: ( <> If your time series store has a query cache this option can override the default cache timeout. Specify a numeric value in seconds. ), }, maxDataPoints: { label: 'Max data points', placeholder: 'auto', name: 'maxDataPoints', tooltipInfo: ( <> The maximum data points the query should return. For graphs this is automatically set to one data point per pixel. ), }, minInterval: { label: 'Min time interval', placeholder: '0', name: 'minInterval', panelKey: 'interval', tooltipInfo: ( <> A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '} 1m if your data is written every minute. Access auto interval via variable{' '} $__interval for time range string and $__interval_ms for numeric variable that can be used in math expressions. ), }, }; constructor(props) { super(props); this.state = { relativeTime: props.panel.timeFrom || '', timeShift: props.panel.timeShift || '', cacheTimeout: props.panel.cacheTimeout || '', maxDataPoints: props.panel.maxDataPoints || '', interval: props.panel.interval || '', hideTimeOverride: props.panel.hideTimeOverride || false, }; } onRelativeTimeChange = (event: ChangeEvent) => { this.setState({ relativeTime: event.target.value, }); }; onTimeShiftChange = (event: ChangeEvent) => { this.setState({ timeShift: event.target.value, }); }; onOverrideTime = (event: FocusEvent, status: InputStatus) => { const { value } = event.target; const { panel } = this.props; const emptyToNullValue = emptyToNull(value); if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) { panel.timeFrom = emptyToNullValue; panel.refresh(); } }; onTimeShift = (event: FocusEvent, status: InputStatus) => { const { value } = event.target; const { panel } = this.props; const emptyToNullValue = emptyToNull(value); if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) { panel.timeShift = emptyToNullValue; panel.refresh(); } }; onToggleTimeOverride = () => { const { panel } = this.props; this.setState({ hideTimeOverride: !this.state.hideTimeOverride }, () => { panel.hideTimeOverride = this.state.hideTimeOverride; panel.refresh(); }); }; onDataSourceOptionBlur = (panelKey: string) => () => { const { panel } = this.props; panel[panelKey] = this.state[panelKey]; panel.refresh(); }; onDataSourceOptionChange = (panelKey: string) => (event: ChangeEvent) => { this.setState({ ...this.state, [panelKey]: event.target.value }); }; renderOptions = () => { const { datasource } = this.props; const { queryOptions } = datasource.meta; if (!queryOptions) { return null; } return Object.keys(queryOptions).map(key => { const options = this.allOptions[key]; const panelKey = options.panelKey || key; return ( ); }); }; render() { const { hideTimeOverride } = this.state; const { relativeTime, timeShift } = this.state; return (
{this.renderOptions()}
Relative time
Time shift
{(timeShift || relativeTime) && (
)}
); } }