Commit a7897b94 by Torkel Ödegaard

Merge branch 'graph-legend-v5' of https://github.com/alexanderzobnin/grafana…

Merge branch 'graph-legend-v5' of https://github.com/alexanderzobnin/grafana into alexanderzobnin-graph-legend-v5
parents 87ceeb08 9bff005f
......@@ -52,6 +52,8 @@ import {gfPageDirective} from './components/gf_page';
import {orgSwitcher} from './components/org_switcher';
import {profiler} from './profiler';
import {registerAngularDirectives} from './angular_wrappers';
import {updateLegendValues} from './time_series2';
import TimeSeries from './time_series2';
import {searchResultsDirective} from './components/search/search_results';
export {
......@@ -85,5 +87,7 @@ export {
geminiScrollbar,
gfPageDirective,
orgSwitcher,
TimeSeries,
updateLegendValues,
searchResultsDirective
};
import kbn from 'app/core/utils/kbn';
import {getFlotTickDecimals} from 'app/core/utils/ticks';
import _ from 'lodash';
function matchSeriesOverride(aliasOrRegex, seriesAlias) {
......@@ -16,6 +17,43 @@ function translateFillOption(fill) {
return fill === 0 ? 0.001 : fill/10;
}
/**
* Calculate decimals for legend and update values for each series.
* @param data series data
* @param panel
* @param height Graph height
*/
export function updateLegendValues(data: TimeSeries[], panel, height) {
for (let i = 0; i < data.length; i++) {
let series = data[i];
let yaxes = panel.yaxes;
let axis = yaxes[series.yaxis - 1];
let {tickDecimals, scaledDecimals} = getFlotTickDecimals(data, axis, height);
let formater = kbn.valueFormats[panel.yaxes[series.yaxis - 1].format];
// decimal override
if (_.isNumber(panel.decimals)) {
series.updateLegendValues(formater, panel.decimals, null);
} else {
// auto decimals
// legend and tooltip gets one more decimal precision
// than graph legend ticks
tickDecimals = (tickDecimals || -1) + 1;
series.updateLegendValues(formater, tickDecimals, scaledDecimals + 2);
}
}
}
export function getDataMinMax(data: TimeSeries[]) {
const datamin = _.minBy(data, (series) => {
return series.stats.min;
}).stats.min;
const datamax = _.maxBy(data, (series: TimeSeries) => {
return series.stats.max;
}).stats.max;
return {datamin, datamax};
}
export default class TimeSeries {
datapoints: any;
id: string;
......
import {getDataMinMax} from 'app/core/time_series2';
/**
* Calculate tick step.
* Implementation from d3-array (ticks.js)
......@@ -32,6 +34,7 @@ export function getScaledDecimals(decimals, tick_size) {
/**
* Calculate tick size based on min and max values, number of ticks and precision.
* Implementation from Flot.
* @param min Axis minimum
* @param max Axis maximum
* @param noTicks Number of ticks
......@@ -65,3 +68,107 @@ export function getFlotTickSize(min: number, max: number, noTicks: number, tickD
return size;
}
/**
* Calculate axis range (min and max).
* Implementation from Flot.
*/
export function getFlotRange(panelMin, panelMax, datamin, datamax) {
const autoscaleMargin = 0.02;
let min = +(panelMin != null ? panelMin : datamin);
let max = +(panelMax != null ? panelMax : datamax);
let delta = max - min;
if (delta === 0.0) {
// Grafana fix: wide Y min and max using increased wideFactor
// when all series values are the same
var wideFactor = 0.25;
var widen = Math.abs(max === 0 ? 1 : max * wideFactor);
if (panelMin === null) {
min -= widen;
}
// always widen max if we couldn't widen min to ensure we
// don't fall into min == max which doesn't work
if (panelMax == null || panelMin != null) {
max += widen;
}
} else {
// consider autoscaling
var margin = autoscaleMargin;
if (margin != null) {
if (panelMin == null) {
min -= delta * margin;
// make sure we don't go below zero if all values
// are positive
if (min < 0 && datamin != null && datamin >= 0) {
min = 0;
}
}
if (panelMax == null) {
max += delta * margin;
if (max > 0 && datamax != null && datamax <= 0) {
max = 0;
}
}
}
}
return {min, max};
}
/**
* Estimate number of ticks for Y axis.
* Implementation from Flot.
*/
export function getFlotNumberOfTicks(height, ticks?) {
let noTicks;
if (typeof ticks === "number" && ticks > 0) {
noTicks = ticks;
} else {
// heuristic based on the model a*sqrt(x) fitted to
// some data points that seemed reasonable
noTicks = 0.3 * Math.sqrt(height);
}
return noTicks;
}
/**
* Calculate tick decimals.
* Implementation from Flot.
*/
export function getFlotTickDecimals(data, axis, height) {
let {datamin, datamax} = getDataMinMax(data);
let {min, max} = getFlotRange(axis.min, axis.max, datamin, datamax);
let noTicks = getFlotNumberOfTicks(height);
let tickDecimals, maxDec;
let delta = (max - min) / noTicks;
let dec = -Math.floor(Math.log(delta) / Math.LN10);
let magn = Math.pow(10, -dec);
// norm is between 1.0 and 10.0
let norm = delta / magn;
let size;
if (norm < 1.5) {
size = 1;
} else if (norm < 3) {
size = 2;
// special case for 2.5, requires an extra decimal
if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
size = 2.5;
++dec;
}
} else if (norm < 7.5) {
size = 5;
} else {
size = 10;
}
size *= magn;
tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
// grafana addition
const scaledDecimals = tickDecimals - Math.floor(Math.log(size) / Math.LN10);
return {tickDecimals, scaledDecimals};
}
......@@ -87,6 +87,8 @@ describe('grafanaGraph', function() {
$.plot = ctx.plotSpy = sinon.spy();
ctrl.events.emit('render', ctx.data);
ctrl.events.emit('render-legend');
ctrl.events.emit('legend-rendering-complete');
ctx.plotData = ctx.plotSpy.getCall(0).args[1];
ctx.plotOptions = ctx.plotSpy.getCall(0).args[2];
}));
......
......@@ -27,6 +27,7 @@
text-align: center;
width: calc(100% - $spacer);
padding-top: 6px;
position: relative;
.popover-content {
padding: 0;
......
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