mirror of https://github.com/grafana/grafana
parent
889518e8e1
commit
3f1adf1390
@ -0,0 +1,167 @@ |
||||
// Libraries
|
||||
import React, { PureComponent } from 'react'; |
||||
|
||||
// Utils
|
||||
import { isValidTimeSpan } from 'app/core/utils/rangeutil'; |
||||
|
||||
// Components
|
||||
import { Switch } from 'app/core/components/Switch/Switch'; |
||||
import { Input } from 'app/core/components/Form'; |
||||
import { EventsWithValidation } from 'app/core/components/Form/Input'; |
||||
import { InputStatus } from 'app/core/components/Form/Input'; |
||||
import DataSourceOption from './DataSourceOption'; |
||||
|
||||
// Types
|
||||
import { PanelModel } from '../panel_model'; |
||||
import { ValidationEvents, DataSourceSelectItem } from 'app/types'; |
||||
|
||||
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; |
||||
} |
||||
|
||||
export class QueryOptions extends PureComponent<Props> { |
||||
onOverrideTime = (evt, status: InputStatus) => { |
||||
const { value } = evt.target; |
||||
const { panel } = this.props; |
||||
const emptyToNullValue = emptyToNull(value); |
||||
if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) { |
||||
panel.timeFrom = emptyToNullValue; |
||||
panel.refresh(); |
||||
} |
||||
}; |
||||
|
||||
onTimeShift = (evt, status: InputStatus) => { |
||||
const { value } = evt.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; |
||||
panel.hideTimeOverride = !panel.hideTimeOverride; |
||||
panel.refresh(); |
||||
}; |
||||
|
||||
renderOptions() { |
||||
const { datasource, panel } = this.props; |
||||
const { queryOptions } = datasource.meta; |
||||
|
||||
if (!queryOptions) { |
||||
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 => { |
||||
const options = allOptions[key]; |
||||
return <DataSourceOption key={key} {...options} onChange={onChangeFn(allOptions[key].panelKey || key)} />; |
||||
}); |
||||
} |
||||
|
||||
render = () => { |
||||
const hideTimeOverride = this.props.panel.hideTimeOverride; |
||||
return ( |
||||
<div className="gf-form-inline"> |
||||
{this.renderOptions()} |
||||
|
||||
<div className="gf-form"> |
||||
<span className="gf-form-label">Relative time</span> |
||||
<Input |
||||
type="text" |
||||
className="width-6" |
||||
placeholder="1h" |
||||
onBlur={this.onOverrideTime} |
||||
validationEvents={timeRangeValidationEvents} |
||||
hideErrorMessage={true} |
||||
/> |
||||
</div> |
||||
|
||||
<div className="gf-form"> |
||||
<span className="gf-form-label">Time shift</span> |
||||
<Input |
||||
type="text" |
||||
className="width-6" |
||||
placeholder="1h" |
||||
onBlur={this.onTimeShift} |
||||
validationEvents={timeRangeValidationEvents} |
||||
hideErrorMessage={true} |
||||
/> |
||||
</div> |
||||
|
||||
<div className="gf-form-inline"> |
||||
<Switch label="Hide time info" checked={hideTimeOverride} onChange={this.onToggleTimeOverride} /> |
||||
</div> |
||||
</div> |
||||
); |
||||
}; |
||||
} |
@ -1,97 +0,0 @@ |
||||
import React, { PureComponent } from 'react'; |
||||
import { Switch } from 'app/core/components/Switch/Switch'; |
||||
import { Input } from 'app/core/components/Form'; |
||||
import { isValidTimeSpan } from 'app/core/utils/rangeutil'; |
||||
import { ValidationEvents } from 'app/types'; |
||||
import { EventsWithValidation } from 'app/core/components/Form/Input'; |
||||
import { PanelModel } from '../panel_model'; |
||||
import { InputStatus } from 'app/core/components/Form/Input'; |
||||
|
||||
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; |
||||
} |
||||
|
||||
export class TimeRangeOptions extends PureComponent<Props> { |
||||
onOverrideTime = (evt, status: InputStatus) => { |
||||
const { value } = evt.target; |
||||
const { panel } = this.props; |
||||
const emptyToNullValue = emptyToNull(value); |
||||
if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) { |
||||
panel.timeFrom = emptyToNullValue; |
||||
panel.refresh(); |
||||
} |
||||
}; |
||||
|
||||
onTimeShift = (evt, status: InputStatus) => { |
||||
const { value } = evt.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; |
||||
panel.hideTimeOverride = !panel.hideTimeOverride; |
||||
panel.refresh(); |
||||
}; |
||||
|
||||
render = () => { |
||||
const hideTimeOverride = this.props.panel.hideTimeOverride; |
||||
return ( |
||||
<> |
||||
<h5 className="section-heading">Time Range</h5> |
||||
|
||||
<div className="gf-form-group"> |
||||
<div className="gf-form"> |
||||
<span className="gf-form-label width-12">Override relative time</span> |
||||
<Input |
||||
type="text" |
||||
className="gf-form-input max-width-8" |
||||
placeholder="1h" |
||||
onBlur={this.onOverrideTime} |
||||
validationEvents={timeRangeValidationEvents} |
||||
hideErrorMessage={true} |
||||
/> |
||||
</div> |
||||
|
||||
<div className="gf-form"> |
||||
<span className="gf-form-label width-12">Add time shift</span> |
||||
<Input |
||||
type="text" |
||||
className="gf-form-input max-width-8" |
||||
placeholder="1h" |
||||
onBlur={this.onTimeShift} |
||||
validationEvents={timeRangeValidationEvents} |
||||
hideErrorMessage={true} |
||||
/> |
||||
</div> |
||||
|
||||
<div className="gf-form-inline"> |
||||
<Switch label="Hide time override info" checked={hideTimeOverride} onChange={this.onToggleTimeOverride} /> |
||||
</div> |
||||
</div> |
||||
</> |
||||
); |
||||
}; |
||||
} |
@ -1,37 +1,49 @@ |
||||
<div class="editor-row"> |
||||
<div class="section gf-form-group"> |
||||
<h5 class="section-heading">Info</h5> |
||||
<div class="gf-form"> |
||||
<span class="gf-form-label width-7">Title</span> |
||||
<input type="text" class="gf-form-input width-25" ng-model='ctrl.panel.title' ng-model-onblur></input> |
||||
</div> |
||||
<div class="gf-form gf-form--v-stretch"> |
||||
<span class="gf-form-label width-7">Description</span> |
||||
<textarea class="gf-form-input width-25" rows="3" ng-model="ctrl.panel.description" ng-model-onblur placeholder="Panel description, supports markdown & links"></textarea> |
||||
</div> |
||||
<gf-form-switch class="gf-form" label-class="width-7" switch-class="max-width-6" label="Transparent" checked="ctrl.panel.transparent" on-change="ctrl.render()"></gf-form-switch> |
||||
</div> |
||||
|
||||
<div class="section gf-form-group"> |
||||
<h5 class="section-heading">Repeat</h5> |
||||
<div class="gf-form"> |
||||
<span class="gf-form-label width-9">For each value of</span> |
||||
<dash-repeat-option panel="ctrl.panel"></dash-repeat-option> |
||||
</div> |
||||
<div class="gf-form" ng-show="ctrl.panel.repeat"> |
||||
<span class="gf-form-label width-9">Direction</span> |
||||
<select class="gf-form-input" ng-model="ctrl.panel.repeatDirection" ng-options="f.value as f.text for f in [{value: 'v', text: 'Vertical'}, {value: 'h', text: 'Horizontal'}]"> |
||||
<option value=""></option> |
||||
</select> |
||||
</div> |
||||
<div class="gf-form" ng-show="ctrl.panel.repeat && ctrl.panel.repeatDirection == 'h'"> |
||||
<span class="gf-form-label width-9">Min width</span> |
||||
<select class="gf-form-input" ng-model="ctrl.panel.minSpan" ng-options="f for f in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]"> |
||||
<option value=""></option> |
||||
</select> |
||||
</div> |
||||
</div> |
||||
|
||||
<panel-links-editor panel="ctrl.panel"></panel-links-editor> |
||||
<div class="panel-option-section"> |
||||
<div class="panel-option-section__header">Information</div> |
||||
<div class="panel-option-section__body"> |
||||
<div class="section"> |
||||
<div class="gf-form"> |
||||
<span class="gf-form-label width-7">Title</span> |
||||
<input type="text" class="gf-form-input width-25" ng-model='ctrl.panel.title' ng-model-onblur></input> |
||||
</div> |
||||
<gf-form-switch class="gf-form" label-class="width-7" switch-class="max-width-6" label="Transparent" checked="ctrl.panel.transparent" on-change="ctrl.render()"></gf-form-switch> |
||||
</div> |
||||
<div class="section"> |
||||
<div class="gf-form gf-form--v-stretch"> |
||||
<span class="gf-form-label width-7">Description</span> |
||||
<textarea class="gf-form-input width-25" rows="5" ng-model="ctrl.panel.description" ng-model-onblur placeholder="Panel description, supports markdown & links"></textarea> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="panel-option-section"> |
||||
<div class="panel-option-section__header">Repeating</div> |
||||
<div class="panel-option-section__body"> |
||||
<div class="section"> |
||||
<div class="gf-form"> |
||||
<span class="gf-form-label width-9">Repat</span> |
||||
<dash-repeat-option panel="ctrl.panel"></dash-repeat-option> |
||||
</div> |
||||
<div class="gf-form" ng-show="ctrl.panel.repeat"> |
||||
<span class="gf-form-label width-9">Direction</span> |
||||
<select class="gf-form-input" ng-model="ctrl.panel.repeatDirection" ng-options="f.value as f.text for f in [{value: 'v', text: 'Vertical'}, {value: 'h', text: 'Horizontal'}]"> |
||||
<option value=""></option> |
||||
</select> |
||||
</div> |
||||
<div class="gf-form" ng-show="ctrl.panel.repeat && ctrl.panel.repeatDirection == 'h'"> |
||||
<span class="gf-form-label width-9">Min width</span> |
||||
<select class="gf-form-input" ng-model="ctrl.panel.minSpan" ng-options="f for f in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]"> |
||||
<option value=""></option> |
||||
</select> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="panel-option-section"> |
||||
<div class="panel-option-section__header">Drildown Links</div> |
||||
<div class="panel-option-section__body"> |
||||
<panel-links-editor panel="ctrl.panel"></panel-links-editor> |
||||
</div> |
||||
</div> |
||||
|
Loading…
Reference in new issue