Closer to the goal!

pull/10616/head
Hunter Trujillo 2017-01-04 15:13:51 -07:00 committed by Andrew Watkins
parent c2b5d3bc9d
commit db13d42818
4 changed files with 65 additions and 51 deletions

View File

@ -110,7 +110,6 @@
'no-new': 2,
'no-octal-escape': 2,
'no-octal': 2,
'no-param-reassign': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-script-url': 2,

View File

@ -4,7 +4,6 @@ import AutoRefresh from 'shared/components/AutoRefresh';
import LineGraph from 'shared/components/LineGraph';
const RefreshingLineGraph = AutoRefresh(LineGraph);
const OUT_OF_RANGE = "out of range";
export const RuleGraph = React.createClass({
propTypes: {
source: PropTypes.shape({
@ -40,32 +39,14 @@ export const RuleGraph = React.createClass({
);
}
const {value, rangeValue, operator} = rule.values;
const tenPercent = 0.1;
let lower, upper;
let upperRange, lowerRange;
if (value !== "" && operator === OUT_OF_RANGE) {
lower = Math.min(+rule.values.rangeValue, +rule.values.value);
lowerRange = lower ? lower + lower * tenPercent : null;
}
if (rangeValue !== "" && operator === OUT_OF_RANGE) {
upper = Math.max(+rule.values.rangeValue, +rule.values.value);
upperRange = upper ? upper + upper * tenPercent : null;
}
// if either value is null, Dygraph will choose a sensible default
const range = {y: [lowerRange, upperRange]};
return (
<RefreshingLineGraph
ranges={range}
queries={queries}
autoRefresh={autoRefreshMs}
underlayCallback={this.createUnderlayCallback()}
isGraphFilled={false}
overrideLineColors={kapacitorLineColors}
ruleValues={rule.values}
/>
);
},

View File

@ -2,7 +2,13 @@
import React, {PropTypes} from 'react';
import Dygraph from '../../external/dygraph';
const {arrayOf, object, array, number, bool, shape} = PropTypes;
const {
array,
arrayOf,
number,
bool,
shape,
} = PropTypes;
const LINE_COLORS = [
'#00C9FF',
@ -28,13 +34,14 @@ export default React.createClass({
y: arrayOf(number),
y2: arrayOf(number),
}),
timeSeries: array.isRequired, // eslint-disable-line react/forbid-prop-types
labels: array.isRequired, // eslint-disable-line react/forbid-prop-types
options: object, // eslint-disable-line react/forbid-prop-types
containerStyle: object, // eslint-disable-line react/forbid-prop-types
timeSeries: array.isRequired,
labels: array.isRequired,
options: shape({}),
containerStyle: shape({}),
isGraphFilled: bool,
overrideLineColors: array,
dygraphSeries: shape({}).isRequired,
ruleValues: shape({}),
},
getDefaultProps() {
@ -54,7 +61,7 @@ export default React.createClass({
componentDidMount() {
const timeSeries = this.getTimeSeries();
// dygraphSeries is a legend label and its corresponding y-axis e.g. {legendLabel1: 'y', legendLabel2: 'y2'};
const {ranges, dygraphSeries} = this.props;
const {ranges, dygraphSeries, ruleValues} = this.props;
const refs = this.refs;
const graphContainerNode = refs.graphContainer;
@ -81,7 +88,7 @@ export default React.createClass({
series: dygraphSeries,
axes: {
y: {
valueRange: getRange(timeSeries, ranges.y),
valueRange: getRange(timeSeries, ranges.y, ruleValues.value, ruleValues.rangeValue),
},
y2: {
valueRange: getRange(timeSeries, ranges.y2),
@ -141,14 +148,14 @@ export default React.createClass({
}
const timeSeries = this.getTimeSeries();
const {labels, ranges, options, dygraphSeries} = this.props;
const {labels, ranges, options, dygraphSeries, ruleValues} = this.props;
dygraph.updateOptions({
labels,
file: timeSeries,
axes: {
y: {
valueRange: getRange(timeSeries, ranges.y),
valueRange: getRange(timeSeries, ranges.y, ruleValues.value, ruleValues.rangeValue),
},
y2: {
valueRange: getRange(timeSeries, ranges.y2),
@ -172,15 +179,28 @@ export default React.createClass({
},
});
function getRange(timeSeries, override) {
const TEN_PERCENT = 0.1;
function getRange(timeSeries, override, value = null, rangeValue = null) {
if (override) {
return override;
}
let max = null;
let min = null;
const addPadding = (val) => {
if (val === null || val === '') {
return null;
}
timeSeries.forEach((series) => {
if (val < 0) {
return val - val * TEN_PERCENT;
}
return val + val * TEN_PERCENT;
};
const points = [...timeSeries, [null, addPadding(value)], [null, addPadding(rangeValue)]];
const range = points.reduce(([min, max], series) => {
for (let i = 1; i < series.length; i++) {
const val = series[i];
@ -196,13 +216,15 @@ function getRange(timeSeries, override) {
min = Math.min(min, val);
max = Math.max(max, val);
}
return [min, max];
}
});
}, [null, null]);
// Dygraph will not reliably plot X / Y axis labels if min and max are both 0
if (min === 0 && max === 0) {
if (range[0] === 0 && range[1] === 0) {
return [null, null];
}
return [min, max];
return range;
}

View File

@ -7,23 +7,34 @@ import _ from 'lodash';
import timeSeriesToDygraph from 'utils/timeSeriesToDygraph';
import lastValues from 'src/shared/parsing/lastValues';
const {
array,
arrayOf,
number,
bool,
shape,
string,
func,
} = PropTypes;
export default React.createClass({
displayName: 'LineGraph',
propTypes: {
data: PropTypes.arrayOf(PropTypes.shape({}).isRequired).isRequired,
ranges: PropTypes.shape({
y: PropTypes.arrayOf(PropTypes.number),
y2: PropTypes.arrayOf(PropTypes.number),
data: arrayOf(shape({}).isRequired).isRequired,
ranges: shape({
y: arrayOf(number),
y2: arrayOf(number),
}),
title: PropTypes.string,
isFetchingInitially: PropTypes.bool,
isRefreshing: PropTypes.bool,
underlayCallback: PropTypes.func,
isGraphFilled: PropTypes.bool,
overrideLineColors: PropTypes.array,
queries: PropTypes.arrayOf(PropTypes.shape({}).isRequired).isRequired,
showSingleStat: PropTypes.bool,
activeQueryIndex: PropTypes.number,
title: string,
isFetchingInitially: bool,
isRefreshing: bool,
underlayCallback: func,
isGraphFilled: bool,
overrideLineColors: array,
queries: arrayOf(shape({}).isRequired).isRequired,
showSingleStat: bool,
activeQueryIndex: number,
ruleValues: shape({}),
},
getDefaultProps() {
@ -50,7 +61,7 @@ export default React.createClass({
},
render() {
const {data, ranges, isFetchingInitially, isRefreshing, isGraphFilled, overrideLineColors, title, underlayCallback, queries, showSingleStat} = this.props;
const {data, ranges, isFetchingInitially, isRefreshing, isGraphFilled, overrideLineColors, title, underlayCallback, queries, showSingleStat, ruleValues} = this.props;
const {labels, timeSeries, dygraphSeries} = this._timeSeries;
// If data for this graph is being fetched for the first time, show a graph-wide spinner.
@ -99,6 +110,7 @@ export default React.createClass({
options={options}
dygraphSeries={dygraphSeries}
ranges={ranges || this.getRanges()}
ruleValues={ruleValues}
/>
{showSingleStat ? <div className="graph-single-stat single-stat">{roundedValue}</div> : null}
</div>