Commit 48570c62 by Hugo Häggmark Committed by GitHub

Made sure that DataSourceOption displays value and fires onChange/onBlur events (#15757)

* Fixed #15682 

* fix: Add hideTimeOverride to state since we need to control the Switch

* fix: Back the maxDataPoints change, we need to keep it as a string

Co-authored-by:johannes.schill@polyester.se
parent 59045029
import React, { FC } from 'react'; import React, { FC, ChangeEvent } from 'react';
import { FormLabel } from '@grafana/ui'; import { FormLabel } from '@grafana/ui';
interface Props { interface Props {
label: string; label: string;
placeholder?: string; placeholder?: string;
name?: string; name: string;
value?: string; value: string;
onChange?: (evt: any) => void; onBlur: (event: ChangeEvent<HTMLInputElement>) => void;
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
tooltipInfo?: any; tooltipInfo?: any;
} }
export const DataSourceOptions: FC<Props> = ({ label, placeholder, name, value, onChange, tooltipInfo }) => { export const DataSourceOption: FC<Props> = ({ label, placeholder, name, value, onBlur, onChange, tooltipInfo }) => {
return ( return (
<div className="gf-form gf-form--flex-end"> <div className="gf-form gf-form--flex-end">
<FormLabel tooltip={tooltipInfo}>{label}</FormLabel> <FormLabel tooltip={tooltipInfo}>{label}</FormLabel>
...@@ -20,10 +21,10 @@ export const DataSourceOptions: FC<Props> = ({ label, placeholder, name, value, ...@@ -20,10 +21,10 @@ export const DataSourceOptions: FC<Props> = ({ label, placeholder, name, value,
placeholder={placeholder} placeholder={placeholder}
name={name} name={name}
spellCheck={false} spellCheck={false}
onBlur={evt => onChange(evt.target.value)} onBlur={onBlur}
onChange={onChange}
value={value}
/> />
</div> </div>
); );
}; };
export default DataSourceOptions;
// Libraries // Libraries
import React, { PureComponent } from 'react'; import React, { PureComponent, ChangeEvent, FocusEvent } from 'react';
// Utils // Utils
import { isValidTimeSpan } from 'app/core/utils/rangeutil'; import { isValidTimeSpan } from 'app/core/utils/rangeutil';
...@@ -9,7 +9,7 @@ import { Switch } from '@grafana/ui'; ...@@ -9,7 +9,7 @@ import { Switch } from '@grafana/ui';
import { Input } from 'app/core/components/Form'; import { Input } from 'app/core/components/Form';
import { EventsWithValidation } from 'app/core/components/Form/Input'; import { EventsWithValidation } from 'app/core/components/Form/Input';
import { InputStatus } from 'app/core/components/Form/Input'; import { InputStatus } from 'app/core/components/Form/Input';
import DataSourceOption from './DataSourceOption'; import { DataSourceOption } from './DataSourceOption';
import { FormLabel } from '@grafana/ui'; import { FormLabel } from '@grafana/ui';
// Types // Types
...@@ -43,32 +43,79 @@ interface Props { ...@@ -43,32 +43,79 @@ interface Props {
interface State { interface State {
relativeTime: string; relativeTime: string;
timeShift: string; timeShift: string;
cacheTimeout: string;
maxDataPoints: string;
interval: string;
hideTimeOverride: boolean;
} }
export class QueryOptions extends PureComponent<Props, State> { export class QueryOptions extends PureComponent<Props, State> {
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{' '}
<code>1m</code> if your data is written every minute. Access auto interval via variable{' '}
<code>$__interval</code> for time range string and <code>$__interval_ms</code> for numeric variable that can
be used in math expressions.
</>
),
},
};
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
relativeTime: props.panel.timeFrom || '', relativeTime: props.panel.timeFrom || '',
timeShift: props.panel.timeShift || '', timeShift: props.panel.timeShift || '',
cacheTimeout: props.panel.cacheTimeout || '',
maxDataPoints: props.panel.maxDataPoints || '',
interval: props.panel.interval || '',
hideTimeOverride: props.panel.hideTimeOverride || false,
}; };
} }
onRelativeTimeChange = event => { onRelativeTimeChange = (event: ChangeEvent<HTMLInputElement>) => {
this.setState({ this.setState({
relativeTime: event.target.value, relativeTime: event.target.value,
}); });
}; };
onTimeShiftChange = event => { onTimeShiftChange = (event: ChangeEvent<HTMLInputElement>) => {
this.setState({ this.setState({
timeShift: event.target.value, timeShift: event.target.value,
}); });
}; };
onOverrideTime = (evt, status: InputStatus) => { onOverrideTime = (event: FocusEvent<HTMLInputElement>, status: InputStatus) => {
const { value } = evt.target; const { value } = event.target;
const { panel } = this.props; const { panel } = this.props;
const emptyToNullValue = emptyToNull(value); const emptyToNullValue = emptyToNull(value);
if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) { if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) {
...@@ -77,8 +124,8 @@ export class QueryOptions extends PureComponent<Props, State> { ...@@ -77,8 +124,8 @@ export class QueryOptions extends PureComponent<Props, State> {
} }
}; };
onTimeShift = (evt, status: InputStatus) => { onTimeShift = (event: FocusEvent<HTMLInputElement>, status: InputStatus) => {
const { value } = evt.target; const { value } = event.target;
const { panel } = this.props; const { panel } = this.props;
const emptyToNullValue = emptyToNull(value); const emptyToNullValue = emptyToNull(value);
if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) { if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) {
...@@ -89,77 +136,49 @@ export class QueryOptions extends PureComponent<Props, State> { ...@@ -89,77 +136,49 @@ export class QueryOptions extends PureComponent<Props, State> {
onToggleTimeOverride = () => { onToggleTimeOverride = () => {
const { panel } = this.props; const { panel } = this.props;
panel.hideTimeOverride = !panel.hideTimeOverride; 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(); panel.refresh();
}; };
renderOptions() { onDataSourceOptionChange = (panelKey: string) => (event: ChangeEvent<HTMLInputElement>) => {
const { datasource, panel } = this.props; this.setState({ ...this.state, [panelKey]: event.target.value });
};
renderOptions = () => {
const { datasource } = this.props;
const { queryOptions } = datasource.meta; const { queryOptions } = datasource.meta;
if (!queryOptions) { if (!queryOptions) {
return null; return null;
} }
const onChangeFn = (panelKey: string) => {
return (value: string | number) => {
panel[panelKey] = value;
panel.refresh();
};
};
const allOptions = {
cacheTimeout: {
label: 'Cache timeout',
placeholder: '60',
name: 'cacheTimeout',
value: panel.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',
value: panel.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',
value: panel.interval,
panelKey: 'interval',
tooltipInfo: (
<>
A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '}
<code>1m</code> if your data is written every minute. Access auto interval via variable{' '}
<code>$__interval</code> for time range string and <code>$__interval_ms</code> for numeric variable that can
be used in math expressions.
</>
),
},
};
return Object.keys(queryOptions).map(key => { return Object.keys(queryOptions).map(key => {
const options = allOptions[key]; const options = this.allOptions[key];
return <DataSourceOption key={key} {...options} onChange={onChangeFn(allOptions[key].panelKey || key)} />; const panelKey = options.panelKey || key;
return (
<DataSourceOption
key={key}
{...options}
onChange={this.onDataSourceOptionChange(panelKey)}
onBlur={this.onDataSourceOptionBlur(panelKey)}
value={this.state[panelKey]}
/>
);
}); });
} };
render() { render() {
const hideTimeOverride = this.props.panel.hideTimeOverride; const { hideTimeOverride } = this.state;
const { relativeTime, timeShift } = this.state; const { relativeTime, timeShift } = this.state;
return ( return (
<div className="gf-form-inline"> <div className="gf-form-inline">
{this.renderOptions()} {this.renderOptions()}
......
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