mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
refactor(graph): js -> typescript refactoring
This commit is contained in:
@@ -5,8 +5,6 @@ import _ from 'lodash';
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
import {colors} from 'app/core/core';
|
||||
|
||||
|
||||
|
||||
export class DataProcessor {
|
||||
|
||||
constructor(private panel) {
|
||||
|
||||
@@ -1,601 +0,0 @@
|
||||
define([
|
||||
'angular',
|
||||
'jquery',
|
||||
'moment',
|
||||
'lodash',
|
||||
'app/core/utils/kbn',
|
||||
'./graph_tooltip',
|
||||
'./threshold_manager',
|
||||
'jquery.flot',
|
||||
'jquery.flot.selection',
|
||||
'jquery.flot.time',
|
||||
'jquery.flot.stack',
|
||||
'jquery.flot.stackpercent',
|
||||
'jquery.flot.fillbelow',
|
||||
'jquery.flot.crosshair',
|
||||
'./jquery.flot.events',
|
||||
],
|
||||
function (angular, $, moment, _, kbn, GraphTooltip, thresholdManExports) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.directives');
|
||||
var labelWidthCache = {};
|
||||
|
||||
module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
template: '<div> </div>',
|
||||
link: function(scope, elem) {
|
||||
var ctrl = scope.ctrl;
|
||||
var dashboard = ctrl.dashboard;
|
||||
var panel = ctrl.panel;
|
||||
var data, annotations;
|
||||
var sortedSeries;
|
||||
var legendSideLastValue = null;
|
||||
var rootScope = scope.$root;
|
||||
var panelWidth = 0;
|
||||
var thresholdManager = new thresholdManExports.ThresholdManager(ctrl);
|
||||
|
||||
rootScope.onAppEvent('setCrosshair', function(event, info) {
|
||||
// do not need to to this if event is from this panel
|
||||
if (info.scope === scope) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(dashboard.sharedCrosshair) {
|
||||
var plot = elem.data().plot;
|
||||
if (plot) {
|
||||
plot.setCrosshair({ x: info.pos.x, y: info.pos.y });
|
||||
}
|
||||
}
|
||||
}, scope);
|
||||
|
||||
rootScope.onAppEvent('clearCrosshair', function() {
|
||||
var plot = elem.data().plot;
|
||||
if (plot) {
|
||||
plot.clearCrosshair();
|
||||
}
|
||||
}, scope);
|
||||
|
||||
// Receive render events
|
||||
ctrl.events.on('render', function(renderData) {
|
||||
data = renderData || data;
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
annotations = data.annotations || annotations;
|
||||
render_panel();
|
||||
});
|
||||
|
||||
function getLegendHeight(panelHeight) {
|
||||
if (!panel.legend.show || panel.legend.rightSide) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (panel.legend.alignAsTable) {
|
||||
var legendSeries = _.filter(data, function(series) {
|
||||
return series.hideFromLegend(panel.legend) === false;
|
||||
});
|
||||
var total = 23 + (21 * legendSeries.length);
|
||||
return Math.min(total, Math.floor(panelHeight/2));
|
||||
} else {
|
||||
return 26;
|
||||
}
|
||||
}
|
||||
|
||||
function setElementHeight() {
|
||||
try {
|
||||
var height = ctrl.height - getLegendHeight(ctrl.height);
|
||||
elem.css('height', height + 'px');
|
||||
|
||||
return true;
|
||||
} catch(e) { // IE throws errors sometimes
|
||||
console.log(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function shouldAbortRender() {
|
||||
if (!data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!setElementHeight()) { return true; }
|
||||
|
||||
if (panelWidth === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function getLabelWidth(text, elem) {
|
||||
var labelWidth = labelWidthCache[text];
|
||||
|
||||
if (!labelWidth) {
|
||||
labelWidth = labelWidthCache[text] = elem.width();
|
||||
}
|
||||
|
||||
return labelWidth;
|
||||
}
|
||||
|
||||
function drawHook(plot) {
|
||||
// Update legend values
|
||||
var yaxis = plot.getYAxes();
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var series = data[i];
|
||||
var axis = yaxis[series.yaxis - 1];
|
||||
var 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
|
||||
var tickDecimals = (axis.tickDecimals || -1) + 1;
|
||||
series.updateLegendValues(formater, tickDecimals, axis.scaledDecimals + 2);
|
||||
}
|
||||
|
||||
if(!rootScope.$$phase) { scope.$digest(); }
|
||||
}
|
||||
|
||||
// add left axis labels
|
||||
if (panel.yaxes[0].label) {
|
||||
var yaxisLabel = $("<div class='axisLabel left-yaxis-label'></div>")
|
||||
.text(panel.yaxes[0].label)
|
||||
.appendTo(elem);
|
||||
|
||||
yaxisLabel[0].style.marginTop = (getLabelWidth(panel.yaxes[0].label, yaxisLabel) / 2) + 'px';
|
||||
}
|
||||
|
||||
// add right axis labels
|
||||
if (panel.yaxes[1].label) {
|
||||
var rightLabel = $("<div class='axisLabel right-yaxis-label'></div>")
|
||||
.text(panel.yaxes[1].label)
|
||||
.appendTo(elem);
|
||||
|
||||
rightLabel[0].style.marginTop = (getLabelWidth(panel.yaxes[1].label, rightLabel) / 2) + 'px';
|
||||
}
|
||||
|
||||
thresholdManager.draw(plot);
|
||||
}
|
||||
|
||||
function processOffsetHook(plot, gridMargin) {
|
||||
var left = panel.yaxes[0];
|
||||
var right = panel.yaxes[1];
|
||||
if (left.show && left.label) { gridMargin.left = 20; }
|
||||
if (right.show && right.label) { gridMargin.right = 20; }
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel() {
|
||||
panelWidth = elem.width();
|
||||
|
||||
if (shouldAbortRender()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// give space to alert editing
|
||||
thresholdManager.prepare(elem, data);
|
||||
|
||||
var stack = panel.stack ? true : null;
|
||||
|
||||
// Populate element
|
||||
var options = {
|
||||
hooks: {
|
||||
draw: [drawHook],
|
||||
processOffset: [processOffsetHook],
|
||||
},
|
||||
legend: { show: false },
|
||||
series: {
|
||||
stackpercent: panel.stack ? panel.percentage : false,
|
||||
stack: panel.percentage ? null : stack,
|
||||
lines: {
|
||||
show: panel.lines,
|
||||
zero: false,
|
||||
fill: translateFillOption(panel.fill),
|
||||
lineWidth: panel.linewidth,
|
||||
steps: panel.steppedLine
|
||||
},
|
||||
bars: {
|
||||
show: panel.bars,
|
||||
fill: 1,
|
||||
barWidth: 1,
|
||||
zero: false,
|
||||
lineWidth: 0
|
||||
},
|
||||
points: {
|
||||
show: panel.points,
|
||||
fill: 1,
|
||||
fillColor: false,
|
||||
radius: panel.points ? panel.pointradius : 2
|
||||
},
|
||||
shadowSize: 0
|
||||
},
|
||||
yaxes: [],
|
||||
xaxis: {},
|
||||
grid: {
|
||||
minBorderMargin: 0,
|
||||
markings: [],
|
||||
backgroundColor: null,
|
||||
borderWidth: 0,
|
||||
hoverable: true,
|
||||
color: '#c8c8c8',
|
||||
margin: { left: 0, right: 0 },
|
||||
},
|
||||
selection: {
|
||||
mode: "x",
|
||||
color: '#666'
|
||||
},
|
||||
crosshair: {
|
||||
mode: panel.tooltip.shared || dashboard.sharedCrosshair ? "x" : null
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var series = data[i];
|
||||
series.data = series.getFlotPairs(series.nullPointMode || panel.nullPointMode);
|
||||
|
||||
if (panel.xaxis.mode === 'series') {
|
||||
series.data = [[i + 1, series.stats[panel.xaxis.values[0]]]];
|
||||
} else if (panel.xaxis.mode === 'table' ||
|
||||
panel.xaxis.mode === 'elastic') {
|
||||
series.data = [];
|
||||
for (var j = 0; j < series.datapoints.length; j++) {
|
||||
var dataIndex = i * series.datapoints.length + j;
|
||||
series.datapoints[j];
|
||||
series.data.push([
|
||||
dataIndex + 1,
|
||||
series.datapoints[j][0]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// if hidden remove points and disable stack
|
||||
if (ctrl.hiddenSeries[series.alias]) {
|
||||
series.data = [];
|
||||
series.stack = false;
|
||||
}
|
||||
}
|
||||
|
||||
switch(panel.xaxis.mode) {
|
||||
case 'series': {
|
||||
options.series.bars.barWidth = 0.7;
|
||||
options.series.bars.align = 'center';
|
||||
addXSeriesAxis(options);
|
||||
break;
|
||||
}
|
||||
case 'table': {
|
||||
options.series.bars.barWidth = 0.7;
|
||||
options.series.bars.align = 'center';
|
||||
addXTableAxis(options);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (data.length && data[0].stats.timeStep) {
|
||||
options.series.bars.barWidth = data[0].stats.timeStep / 1.5;
|
||||
}
|
||||
addTimeAxis(options);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
thresholdManager.addPlotOptions(options, panel);
|
||||
addAnnotations(options);
|
||||
configureAxisOptions(data, options);
|
||||
|
||||
sortedSeries = _.sortBy(data, function(series) { return series.zindex; });
|
||||
|
||||
function callPlot(incrementRenderCounter) {
|
||||
try {
|
||||
$.plot(elem, sortedSeries, options);
|
||||
if (ctrl.renderError) {
|
||||
delete ctrl.error;
|
||||
delete ctrl.inspector;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('flotcharts error', e);
|
||||
ctrl.error = e.message || "Render Error";
|
||||
ctrl.renderError = true;
|
||||
ctrl.inspector = {error: e};
|
||||
}
|
||||
|
||||
if (incrementRenderCounter) {
|
||||
ctrl.renderingCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDelayDraw(panel)) {
|
||||
// temp fix for legends on the side, need to render twice to get dimensions right
|
||||
callPlot(false);
|
||||
setTimeout(function() { callPlot(true); }, 50);
|
||||
legendSideLastValue = panel.legend.rightSide;
|
||||
}
|
||||
else {
|
||||
callPlot(true);
|
||||
}
|
||||
}
|
||||
|
||||
function translateFillOption(fill) {
|
||||
return fill === 0 ? 0.001 : fill/10;
|
||||
}
|
||||
|
||||
function shouldDelayDraw(panel) {
|
||||
if (panel.legend.rightSide) {
|
||||
return true;
|
||||
}
|
||||
if (legendSideLastValue !== null && panel.legend.rightSide !== legendSideLastValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function addTimeAxis(options) {
|
||||
var ticks = panelWidth / 100;
|
||||
var min = _.isUndefined(ctrl.range.from) ? null : ctrl.range.from.valueOf();
|
||||
var max = _.isUndefined(ctrl.range.to) ? null : ctrl.range.to.valueOf();
|
||||
|
||||
options.xaxis = {
|
||||
timezone: dashboard.getTimezone(),
|
||||
show: panel.xaxis.show,
|
||||
mode: "time",
|
||||
min: min,
|
||||
max: max,
|
||||
label: "Datetime",
|
||||
ticks: ticks,
|
||||
timeformat: time_format(ticks, min, max),
|
||||
};
|
||||
}
|
||||
|
||||
function addXSeriesAxis(options) {
|
||||
var ticks = _.map(data, function(series, index) {
|
||||
return [index + 1, series.alias];
|
||||
});
|
||||
|
||||
options.xaxis = {
|
||||
timezone: dashboard.getTimezone(),
|
||||
show: panel.xaxis.show,
|
||||
mode: null,
|
||||
min: 0,
|
||||
max: ticks.length + 1,
|
||||
label: "Datetime",
|
||||
ticks: ticks
|
||||
};
|
||||
}
|
||||
|
||||
function addXTableAxis(options) {
|
||||
var ticks = _.map(data, function(series, seriesIndex) {
|
||||
return _.map(series.datapoints, function(point, pointIndex) {
|
||||
var tickIndex = seriesIndex * series.datapoints.length + pointIndex;
|
||||
return [tickIndex + 1, point[1]];
|
||||
});
|
||||
});
|
||||
ticks = _.flatten(ticks, true);
|
||||
|
||||
options.xaxis = {
|
||||
timezone: dashboard.getTimezone(),
|
||||
show: panel.xaxis.show,
|
||||
mode: null,
|
||||
min: 0,
|
||||
max: ticks.length + 1,
|
||||
label: "Datetime",
|
||||
ticks: ticks
|
||||
};
|
||||
}
|
||||
|
||||
function addAnnotations(options) {
|
||||
if(!annotations || annotations.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var types = {};
|
||||
for (var i = 0; i < annotations.length; i++) {
|
||||
var item = annotations[i];
|
||||
|
||||
if (!types[item.source.name]) {
|
||||
types[item.source.name] = {
|
||||
color: item.source.iconColor,
|
||||
position: 'BOTTOM',
|
||||
markerSize: 5,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
options.events = {
|
||||
levels: _.keys(types).length + 1,
|
||||
data: annotations,
|
||||
types: types,
|
||||
};
|
||||
}
|
||||
|
||||
//Override min/max to provide more flexible autoscaling
|
||||
function autoscaleSpanOverride(yaxis, data, options) {
|
||||
var expr;
|
||||
if (yaxis.min != null && data != null) {
|
||||
expr = parseThresholdExpr(yaxis.min);
|
||||
options.min = autoscaleYAxisMin(expr, data.stats);
|
||||
}
|
||||
if (yaxis.max != null && data != null) {
|
||||
expr = parseThresholdExpr(yaxis.max);
|
||||
options.max = autoscaleYAxisMax(expr, data.stats);
|
||||
}
|
||||
}
|
||||
|
||||
function parseThresholdExpr(expr) {
|
||||
var match, operator, value, precision;
|
||||
expr = String(expr);
|
||||
match = expr.match(/\s*([<=>~]*)\s*(\-?\d+(\.\d+)?)/);
|
||||
if (match) {
|
||||
operator = match[1];
|
||||
value = parseFloat(match[2]);
|
||||
//Precision based on input
|
||||
precision = match[3] ? match[3].length - 1 : 0;
|
||||
return {
|
||||
operator: operator,
|
||||
value: value,
|
||||
precision: precision
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function autoscaleYAxisMax(expr, dataStats) {
|
||||
var operator = expr.operator,
|
||||
value = expr.value,
|
||||
precision = expr.precision;
|
||||
if (operator === ">") {
|
||||
return dataStats.max < value ? value : null;
|
||||
} else if (operator === "<") {
|
||||
return dataStats.max > value ? value : null;
|
||||
} else if (operator === "~") {
|
||||
return kbn.roundValue(dataStats.avg + value, precision);
|
||||
} else if (operator === "=") {
|
||||
return kbn.roundValue(dataStats.current + value, precision);
|
||||
} else if (!operator && !isNaN(value)) {
|
||||
return kbn.roundValue(value, precision);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function autoscaleYAxisMin(expr, dataStats) {
|
||||
var operator = expr.operator,
|
||||
value = expr.value,
|
||||
precision = expr.precision;
|
||||
if (operator === ">") {
|
||||
return dataStats.min < value ? value : null;
|
||||
} else if (operator === "<") {
|
||||
return dataStats.min > value ? value : null;
|
||||
} else if (operator === "~") {
|
||||
return kbn.roundValue(dataStats.avg - value, precision);
|
||||
} else if (operator === "=") {
|
||||
return kbn.roundValue(dataStats.current - value, precision);
|
||||
} else if (!operator && !isNaN(value)) {
|
||||
return kbn.roundValue(value, precision);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function configureAxisOptions(data, options) {
|
||||
var defaults = {
|
||||
position: 'left',
|
||||
show: panel.yaxes[0].show,
|
||||
min: panel.yaxes[0].min,
|
||||
index: 1,
|
||||
logBase: panel.yaxes[0].logBase || 1,
|
||||
max: panel.percentage && panel.stack ? 100 : panel.yaxes[0].max,
|
||||
};
|
||||
|
||||
autoscaleSpanOverride(panel.yaxes[0], data[0], defaults);
|
||||
options.yaxes.push(defaults);
|
||||
|
||||
if (_.find(data, {yaxis: 2})) {
|
||||
var secondY = _.clone(defaults);
|
||||
secondY.index = 2,
|
||||
secondY.show = panel.yaxes[1].show;
|
||||
secondY.logBase = panel.yaxes[1].logBase || 1,
|
||||
secondY.position = 'right';
|
||||
secondY.min = panel.yaxes[1].min;
|
||||
secondY.max = panel.percentage && panel.stack ? 100 : panel.yaxes[1].max;
|
||||
autoscaleSpanOverride(panel.yaxes[1], data[1], secondY);
|
||||
options.yaxes.push(secondY);
|
||||
|
||||
applyLogScale(options.yaxes[1], data);
|
||||
configureAxisMode(options.yaxes[1], panel.percentage && panel.stack ? "percent" : panel.yaxes[1].format);
|
||||
}
|
||||
|
||||
applyLogScale(options.yaxes[0], data);
|
||||
configureAxisMode(options.yaxes[0], panel.percentage && panel.stack ? "percent" : panel.yaxes[0].format);
|
||||
}
|
||||
|
||||
function applyLogScale(axis, data) {
|
||||
if (axis.logBase === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var series, i;
|
||||
var max = axis.max;
|
||||
|
||||
if (max === null) {
|
||||
for (i = 0; i < data.length; i++) {
|
||||
series = data[i];
|
||||
if (series.yaxis === axis.index) {
|
||||
if (max < series.stats.max) {
|
||||
max = series.stats.max;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (max === void 0) {
|
||||
max = Number.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
axis.min = axis.min !== null ? axis.min : 0;
|
||||
axis.ticks = [0, 1];
|
||||
var nextTick = 1;
|
||||
|
||||
while (true) {
|
||||
nextTick = nextTick * axis.logBase;
|
||||
axis.ticks.push(nextTick);
|
||||
if (nextTick > max) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (axis.logBase === 10) {
|
||||
axis.transform = function(v) { return Math.log(v+0.1); };
|
||||
axis.inverseTransform = function (v) { return Math.pow(10,v); };
|
||||
} else {
|
||||
axis.transform = function(v) { return Math.log(v+0.1) / Math.log(axis.logBase); };
|
||||
axis.inverseTransform = function (v) { return Math.pow(axis.logBase,v); };
|
||||
}
|
||||
}
|
||||
|
||||
function configureAxisMode(axis, format) {
|
||||
axis.tickFormatter = function(val, axis) {
|
||||
return kbn.valueFormats[format](val, axis.tickDecimals, axis.scaledDecimals);
|
||||
};
|
||||
}
|
||||
|
||||
function time_format(ticks, min, max) {
|
||||
if (min && max && ticks) {
|
||||
var range = max - min;
|
||||
var secPerTick = (range/ticks) / 1000;
|
||||
var oneDay = 86400000;
|
||||
var oneYear = 31536000000;
|
||||
|
||||
if (secPerTick <= 45) {
|
||||
return "%H:%M:%S";
|
||||
}
|
||||
if (secPerTick <= 7200 || range <= oneDay) {
|
||||
return "%H:%M";
|
||||
}
|
||||
if (secPerTick <= 80000) {
|
||||
return "%m/%d %H:%M";
|
||||
}
|
||||
if (secPerTick <= 2419200 || range <= oneYear) {
|
||||
return "%m/%d";
|
||||
}
|
||||
return "%Y-%m";
|
||||
}
|
||||
|
||||
return "%H:%M";
|
||||
}
|
||||
|
||||
new GraphTooltip(elem, dashboard, scope, function() {
|
||||
return sortedSeries;
|
||||
});
|
||||
|
||||
elem.bind("plotselected", function (event, ranges) {
|
||||
scope.$apply(function() {
|
||||
timeSrv.setTime({
|
||||
from : moment.utc(ranges.xaxis.from),
|
||||
to : moment.utc(ranges.xaxis.to),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
602
public/app/plugins/panel/graph/graph.ts
Executable file
602
public/app/plugins/panel/graph/graph.ts
Executable file
@@ -0,0 +1,602 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import 'jquery.flot';
|
||||
import 'jquery.flot.selection';
|
||||
import 'jquery.flot.time';
|
||||
import 'jquery.flot.stack';
|
||||
import 'jquery.flot.stackpercent';
|
||||
import 'jquery.flot.fillbelow';
|
||||
import 'jquery.flot.crosshair';
|
||||
import './jquery.flot.events';
|
||||
|
||||
import angular from 'angular';
|
||||
import $ from 'jquery';
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import GraphTooltip from './graph_tooltip';
|
||||
import {ThresholdManager} from './threshold_manager';
|
||||
|
||||
var module = angular.module('grafana.directives');
|
||||
var labelWidthCache = {};
|
||||
|
||||
module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
template: '<div> </div>',
|
||||
link: function(scope, elem) {
|
||||
var ctrl = scope.ctrl;
|
||||
var dashboard = ctrl.dashboard;
|
||||
var panel = ctrl.panel;
|
||||
var data, annotations;
|
||||
var sortedSeries;
|
||||
var legendSideLastValue = null;
|
||||
var rootScope = scope.$root;
|
||||
var panelWidth = 0;
|
||||
var thresholdManager = new ThresholdManager(ctrl);
|
||||
|
||||
rootScope.onAppEvent('setCrosshair', function(event, info) {
|
||||
// do not need to to this if event is from this panel
|
||||
if (info.scope === scope) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dashboard.sharedCrosshair) {
|
||||
var plot = elem.data().plot;
|
||||
if (plot) {
|
||||
plot.setCrosshair({ x: info.pos.x, y: info.pos.y });
|
||||
}
|
||||
}
|
||||
}, scope);
|
||||
|
||||
rootScope.onAppEvent('clearCrosshair', function() {
|
||||
var plot = elem.data().plot;
|
||||
if (plot) {
|
||||
plot.clearCrosshair();
|
||||
}
|
||||
}, scope);
|
||||
|
||||
// Receive render events
|
||||
ctrl.events.on('render', function(renderData) {
|
||||
data = renderData || data;
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
annotations = data.annotations || annotations;
|
||||
render_panel();
|
||||
});
|
||||
|
||||
function getLegendHeight(panelHeight) {
|
||||
if (!panel.legend.show || panel.legend.rightSide) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (panel.legend.alignAsTable) {
|
||||
var legendSeries = _.filter(data, function(series) {
|
||||
return series.hideFromLegend(panel.legend) === false;
|
||||
});
|
||||
var total = 23 + (21 * legendSeries.length);
|
||||
return Math.min(total, Math.floor(panelHeight/2));
|
||||
} else {
|
||||
return 26;
|
||||
}
|
||||
}
|
||||
|
||||
function setElementHeight() {
|
||||
try {
|
||||
var height = ctrl.height - getLegendHeight(ctrl.height);
|
||||
elem.css('height', height + 'px');
|
||||
|
||||
return true;
|
||||
} catch (e) { // IE throws errors sometimes
|
||||
console.log(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function shouldAbortRender() {
|
||||
if (!data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!setElementHeight()) { return true; }
|
||||
|
||||
if (panelWidth === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function getLabelWidth(text, elem) {
|
||||
var labelWidth = labelWidthCache[text];
|
||||
|
||||
if (!labelWidth) {
|
||||
labelWidth = labelWidthCache[text] = elem.width();
|
||||
}
|
||||
|
||||
return labelWidth;
|
||||
}
|
||||
|
||||
function drawHook(plot) {
|
||||
// Update legend values
|
||||
var yaxis = plot.getYAxes();
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var series = data[i];
|
||||
var axis = yaxis[series.yaxis - 1];
|
||||
var 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
|
||||
var tickDecimals = (axis.tickDecimals || -1) + 1;
|
||||
series.updateLegendValues(formater, tickDecimals, axis.scaledDecimals + 2);
|
||||
}
|
||||
|
||||
if (!rootScope.$$phase) { scope.$digest(); }
|
||||
}
|
||||
|
||||
// add left axis labels
|
||||
if (panel.yaxes[0].label) {
|
||||
var yaxisLabel = $("<div class='axisLabel left-yaxis-label'></div>")
|
||||
.text(panel.yaxes[0].label)
|
||||
.appendTo(elem);
|
||||
|
||||
yaxisLabel[0].style.marginTop = (getLabelWidth(panel.yaxes[0].label, yaxisLabel) / 2) + 'px';
|
||||
}
|
||||
|
||||
// add right axis labels
|
||||
if (panel.yaxes[1].label) {
|
||||
var rightLabel = $("<div class='axisLabel right-yaxis-label'></div>")
|
||||
.text(panel.yaxes[1].label)
|
||||
.appendTo(elem);
|
||||
|
||||
rightLabel[0].style.marginTop = (getLabelWidth(panel.yaxes[1].label, rightLabel) / 2) + 'px';
|
||||
}
|
||||
|
||||
thresholdManager.draw(plot);
|
||||
}
|
||||
|
||||
function processOffsetHook(plot, gridMargin) {
|
||||
var left = panel.yaxes[0];
|
||||
var right = panel.yaxes[1];
|
||||
if (left.show && left.label) { gridMargin.left = 20; }
|
||||
if (right.show && right.label) { gridMargin.right = 20; }
|
||||
}
|
||||
|
||||
function processDatapoints(plot) {
|
||||
console.log('processDatapoints');
|
||||
}
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel() {
|
||||
panelWidth = elem.width();
|
||||
|
||||
if (shouldAbortRender()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// give space to alert editing
|
||||
thresholdManager.prepare(elem, data);
|
||||
|
||||
var stack = panel.stack ? true : null;
|
||||
|
||||
// Populate element
|
||||
var options: any = {
|
||||
hooks: {
|
||||
draw: [drawHook],
|
||||
processOffset: [processOffsetHook],
|
||||
processDatapoints: [processDatapoints],
|
||||
},
|
||||
legend: { show: false },
|
||||
series: {
|
||||
stackpercent: panel.stack ? panel.percentage : false,
|
||||
stack: panel.percentage ? null : stack,
|
||||
lines: {
|
||||
show: panel.lines,
|
||||
zero: false,
|
||||
fill: translateFillOption(panel.fill),
|
||||
lineWidth: panel.linewidth,
|
||||
steps: panel.steppedLine
|
||||
},
|
||||
bars: {
|
||||
show: panel.bars,
|
||||
fill: 1,
|
||||
barWidth: 1,
|
||||
zero: false,
|
||||
lineWidth: 0
|
||||
},
|
||||
points: {
|
||||
show: panel.points,
|
||||
fill: 1,
|
||||
fillColor: false,
|
||||
radius: panel.points ? panel.pointradius : 2
|
||||
},
|
||||
shadowSize: 0
|
||||
},
|
||||
yaxes: [],
|
||||
xaxis: {},
|
||||
grid: {
|
||||
minBorderMargin: 0,
|
||||
markings: [],
|
||||
backgroundColor: null,
|
||||
borderWidth: 0,
|
||||
hoverable: true,
|
||||
color: '#c8c8c8',
|
||||
margin: { left: 0, right: 0 },
|
||||
},
|
||||
selection: {
|
||||
mode: "x",
|
||||
color: '#666'
|
||||
},
|
||||
crosshair: {
|
||||
mode: panel.tooltip.shared || dashboard.sharedCrosshair ? "x" : null
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var series = data[i];
|
||||
series.data = series.getFlotPairs(series.nullPointMode || panel.nullPointMode);
|
||||
|
||||
if (panel.xaxis.mode === 'series') {
|
||||
series.data = [[i + 1, series.stats[panel.xaxis.values[0]]]];
|
||||
} else if (panel.xaxis.mode === 'table' || panel.xaxis.mode === 'elastic') {
|
||||
series.data = [];
|
||||
for (var j = 0; j < series.datapoints.length; j++) {
|
||||
var dataIndex = i * series.datapoints.length + j;
|
||||
series.datapoints[j];
|
||||
series.data.push([
|
||||
dataIndex + 1,
|
||||
series.datapoints[j][0]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// if hidden remove points and disable stack
|
||||
if (ctrl.hiddenSeries[series.alias]) {
|
||||
series.data = [];
|
||||
series.stack = false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (panel.xaxis.mode) {
|
||||
case 'series': {
|
||||
options.series.bars.barWidth = 0.7;
|
||||
options.series.bars.align = 'center';
|
||||
addXSeriesAxis(options);
|
||||
break;
|
||||
}
|
||||
case 'table': {
|
||||
options.series.bars.barWidth = 0.7;
|
||||
options.series.bars.align = 'center';
|
||||
addXTableAxis(options);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (data.length && data[0].stats.timeStep) {
|
||||
options.series.bars.barWidth = data[0].stats.timeStep / 1.5;
|
||||
}
|
||||
addTimeAxis(options);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
thresholdManager.addPlotOptions(options, panel);
|
||||
addAnnotations(options);
|
||||
configureAxisOptions(data, options);
|
||||
|
||||
sortedSeries = _.sortBy(data, function(series) { return series.zindex; });
|
||||
|
||||
function callPlot(incrementRenderCounter) {
|
||||
try {
|
||||
$.plot(elem, sortedSeries, options);
|
||||
if (ctrl.renderError) {
|
||||
delete ctrl.error;
|
||||
delete ctrl.inspector;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('flotcharts error', e);
|
||||
ctrl.error = e.message || "Render Error";
|
||||
ctrl.renderError = true;
|
||||
ctrl.inspector = {error: e};
|
||||
}
|
||||
|
||||
if (incrementRenderCounter) {
|
||||
ctrl.renderingCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDelayDraw(panel)) {
|
||||
// temp fix for legends on the side, need to render twice to get dimensions right
|
||||
callPlot(false);
|
||||
setTimeout(function() { callPlot(true); }, 50);
|
||||
legendSideLastValue = panel.legend.rightSide;
|
||||
} else {
|
||||
callPlot(true);
|
||||
}
|
||||
}
|
||||
|
||||
function translateFillOption(fill) {
|
||||
return fill === 0 ? 0.001 : fill/10;
|
||||
}
|
||||
|
||||
function shouldDelayDraw(panel) {
|
||||
if (panel.legend.rightSide) {
|
||||
return true;
|
||||
}
|
||||
if (legendSideLastValue !== null && panel.legend.rightSide !== legendSideLastValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function addTimeAxis(options) {
|
||||
var ticks = panelWidth / 100;
|
||||
var min = _.isUndefined(ctrl.range.from) ? null : ctrl.range.from.valueOf();
|
||||
var max = _.isUndefined(ctrl.range.to) ? null : ctrl.range.to.valueOf();
|
||||
|
||||
options.xaxis = {
|
||||
timezone: dashboard.getTimezone(),
|
||||
show: panel.xaxis.show,
|
||||
mode: "time",
|
||||
min: min,
|
||||
max: max,
|
||||
label: "Datetime",
|
||||
ticks: ticks,
|
||||
timeformat: time_format(ticks, min, max),
|
||||
};
|
||||
}
|
||||
|
||||
function addXSeriesAxis(options) {
|
||||
var ticks = _.map(data, function(series, index) {
|
||||
return [index + 1, series.alias];
|
||||
});
|
||||
|
||||
options.xaxis = {
|
||||
timezone: dashboard.getTimezone(),
|
||||
show: panel.xaxis.show,
|
||||
mode: null,
|
||||
min: 0,
|
||||
max: ticks.length + 1,
|
||||
label: "Datetime",
|
||||
ticks: ticks
|
||||
};
|
||||
}
|
||||
|
||||
function addXTableAxis(options) {
|
||||
var ticks = _.map(data, function(series, seriesIndex) {
|
||||
return _.map(series.datapoints, function(point, pointIndex) {
|
||||
var tickIndex = seriesIndex * series.datapoints.length + pointIndex;
|
||||
return [tickIndex + 1, point[1]];
|
||||
});
|
||||
});
|
||||
ticks = _.flatten(ticks, true);
|
||||
|
||||
options.xaxis = {
|
||||
timezone: dashboard.getTimezone(),
|
||||
show: panel.xaxis.show,
|
||||
mode: null,
|
||||
min: 0,
|
||||
max: ticks.length + 1,
|
||||
label: "Datetime",
|
||||
ticks: ticks
|
||||
};
|
||||
}
|
||||
|
||||
function addAnnotations(options) {
|
||||
if (!annotations || annotations.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var types = {};
|
||||
for (var i = 0; i < annotations.length; i++) {
|
||||
var item = annotations[i];
|
||||
|
||||
if (!types[item.source.name]) {
|
||||
types[item.source.name] = {
|
||||
color: item.source.iconColor,
|
||||
position: 'BOTTOM',
|
||||
markerSize: 5,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
options.events = {
|
||||
levels: _.keys(types).length + 1,
|
||||
data: annotations,
|
||||
types: types,
|
||||
};
|
||||
}
|
||||
|
||||
//Override min/max to provide more flexible autoscaling
|
||||
function autoscaleSpanOverride(yaxis, data, options) {
|
||||
var expr;
|
||||
if (yaxis.min != null && data != null) {
|
||||
expr = parseThresholdExpr(yaxis.min);
|
||||
options.min = autoscaleYAxisMin(expr, data.stats);
|
||||
}
|
||||
if (yaxis.max != null && data != null) {
|
||||
expr = parseThresholdExpr(yaxis.max);
|
||||
options.max = autoscaleYAxisMax(expr, data.stats);
|
||||
}
|
||||
}
|
||||
|
||||
function parseThresholdExpr(expr) {
|
||||
var match, operator, value, precision;
|
||||
expr = String(expr);
|
||||
match = expr.match(/\s*([<=>~]*)\s*(\-?\d+(\.\d+)?)/);
|
||||
if (match) {
|
||||
operator = match[1];
|
||||
value = parseFloat(match[2]);
|
||||
//Precision based on input
|
||||
precision = match[3] ? match[3].length - 1 : 0;
|
||||
return {
|
||||
operator: operator,
|
||||
value: value,
|
||||
precision: precision
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function autoscaleYAxisMax(expr, dataStats) {
|
||||
var operator = expr.operator,
|
||||
value = expr.value,
|
||||
precision = expr.precision;
|
||||
if (operator === ">") {
|
||||
return dataStats.max < value ? value : null;
|
||||
} else if (operator === "<") {
|
||||
return dataStats.max > value ? value : null;
|
||||
} else if (operator === "~") {
|
||||
return kbn.roundValue(dataStats.avg + value, precision);
|
||||
} else if (operator === "=") {
|
||||
return kbn.roundValue(dataStats.current + value, precision);
|
||||
} else if (!operator && !isNaN(value)) {
|
||||
return kbn.roundValue(value, precision);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function autoscaleYAxisMin(expr, dataStats) {
|
||||
var operator = expr.operator,
|
||||
value = expr.value,
|
||||
precision = expr.precision;
|
||||
if (operator === ">") {
|
||||
return dataStats.min < value ? value : null;
|
||||
} else if (operator === "<") {
|
||||
return dataStats.min > value ? value : null;
|
||||
} else if (operator === "~") {
|
||||
return kbn.roundValue(dataStats.avg - value, precision);
|
||||
} else if (operator === "=") {
|
||||
return kbn.roundValue(dataStats.current - value, precision);
|
||||
} else if (!operator && !isNaN(value)) {
|
||||
return kbn.roundValue(value, precision);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function configureAxisOptions(data, options) {
|
||||
var defaults = {
|
||||
position: 'left',
|
||||
show: panel.yaxes[0].show,
|
||||
// min: panel.yaxes[0].min,
|
||||
index: 1,
|
||||
logBase: panel.yaxes[0].logBase || 1,
|
||||
max: panel.percentage && panel.stack ? 100 : panel.yaxes[0].max,
|
||||
};
|
||||
|
||||
// autoscaleSpanOverride(panel.yaxes[0], data[0], defaults);
|
||||
options.yaxes.push(defaults);
|
||||
|
||||
if (_.find(data, {yaxis: 2})) {
|
||||
var secondY = _.clone(defaults);
|
||||
secondY.index = 2,
|
||||
secondY.show = panel.yaxes[1].show;
|
||||
secondY.logBase = panel.yaxes[1].logBase || 1,
|
||||
secondY.position = 'right';
|
||||
// secondY.min = panel.yaxes[1].min;
|
||||
secondY.max = panel.percentage && panel.stack ? 100 : panel.yaxes[1].max;
|
||||
// autoscaleSpanOverride(panel.yaxes[1], data[1], secondY);
|
||||
options.yaxes.push(secondY);
|
||||
|
||||
applyLogScale(options.yaxes[1], data);
|
||||
configureAxisMode(options.yaxes[1], panel.percentage && panel.stack ? "percent" : panel.yaxes[1].format);
|
||||
}
|
||||
|
||||
applyLogScale(options.yaxes[0], data);
|
||||
configureAxisMode(options.yaxes[0], panel.percentage && panel.stack ? "percent" : panel.yaxes[0].format);
|
||||
}
|
||||
|
||||
function applyLogScale(axis, data) {
|
||||
if (axis.logBase === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var series, i;
|
||||
var max = axis.max;
|
||||
|
||||
if (max === null) {
|
||||
for (i = 0; i < data.length; i++) {
|
||||
series = data[i];
|
||||
if (series.yaxis === axis.index) {
|
||||
if (max < series.stats.max) {
|
||||
max = series.stats.max;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (max === void 0) {
|
||||
max = Number.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
axis.min = axis.min !== null ? axis.min : 0;
|
||||
axis.ticks = [0, 1];
|
||||
var nextTick = 1;
|
||||
|
||||
while (true) {
|
||||
nextTick = nextTick * axis.logBase;
|
||||
axis.ticks.push(nextTick);
|
||||
if (nextTick > max) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (axis.logBase === 10) {
|
||||
axis.transform = function(v) { return Math.log(v+0.1); };
|
||||
axis.inverseTransform = function (v) { return Math.pow(10,v); };
|
||||
} else {
|
||||
axis.transform = function(v) { return Math.log(v+0.1) / Math.log(axis.logBase); };
|
||||
axis.inverseTransform = function (v) { return Math.pow(axis.logBase,v); };
|
||||
}
|
||||
}
|
||||
|
||||
function configureAxisMode(axis, format) {
|
||||
axis.tickFormatter = function(val, axis) {
|
||||
return kbn.valueFormats[format](val, axis.tickDecimals, axis.scaledDecimals);
|
||||
};
|
||||
}
|
||||
|
||||
function time_format(ticks, min, max) {
|
||||
if (min && max && ticks) {
|
||||
var range = max - min;
|
||||
var secPerTick = (range/ticks) / 1000;
|
||||
var oneDay = 86400000;
|
||||
var oneYear = 31536000000;
|
||||
|
||||
if (secPerTick <= 45) {
|
||||
return "%H:%M:%S";
|
||||
}
|
||||
if (secPerTick <= 7200 || range <= oneDay) {
|
||||
return "%H:%M";
|
||||
}
|
||||
if (secPerTick <= 80000) {
|
||||
return "%m/%d %H:%M";
|
||||
}
|
||||
if (secPerTick <= 2419200 || range <= oneYear) {
|
||||
return "%m/%d";
|
||||
}
|
||||
return "%Y-%m";
|
||||
}
|
||||
|
||||
return "%H:%M";
|
||||
}
|
||||
|
||||
new GraphTooltip(elem, dashboard, scope, function() {
|
||||
return sortedSeries;
|
||||
});
|
||||
|
||||
elem.bind("plotselected", function (event, ranges) {
|
||||
scope.$apply(function() {
|
||||
timeSrv.setTime({
|
||||
from : moment.utc(ranges.xaxis.from),
|
||||
to : moment.utc(ranges.xaxis.to),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -219,145 +219,145 @@ describe('grafanaGraph', function() {
|
||||
|
||||
}, 10);
|
||||
|
||||
graphScenario('when using flexible Y-Min and Y-Max settings', function(ctx) {
|
||||
describe('and Y-Min is <100 and Y-Max is >200 and values within range', function() {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].min = '<100';
|
||||
ctrl.panel.yaxes[0].max = '>200';
|
||||
data[0] = new TimeSeries({
|
||||
datapoints: [[120,10],[160,20]],
|
||||
alias: 'series1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set min to 100 and max to 200', function() {
|
||||
expect(ctx.plotOptions.yaxes[0].min).to.be(100);
|
||||
expect(ctx.plotOptions.yaxes[0].max).to.be(200);
|
||||
});
|
||||
});
|
||||
describe('and Y-Min is <100 and Y-Max is >200 and values outside range', function() {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].min = '<100';
|
||||
ctrl.panel.yaxes[0].max = '>200';
|
||||
data[0] = new TimeSeries({
|
||||
datapoints: [[99,10],[201,20]],
|
||||
alias: 'series1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set min to auto and max to auto', function() {
|
||||
expect(ctx.plotOptions.yaxes[0].min).to.be(null);
|
||||
expect(ctx.plotOptions.yaxes[0].max).to.be(null);
|
||||
});
|
||||
});
|
||||
describe('and Y-Min is =10.5 and Y-Max is =10.5', function() {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].min = '=10.5';
|
||||
ctrl.panel.yaxes[0].max = '=10.5';
|
||||
data[0] = new TimeSeries({
|
||||
datapoints: [[100,10],[120,20], [110,30]],
|
||||
alias: 'series1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set min to last value + 10.5 and max to last value + 10.5', function() {
|
||||
expect(ctx.plotOptions.yaxes[0].min).to.be(99.5);
|
||||
expect(ctx.plotOptions.yaxes[0].max).to.be(120.5);
|
||||
});
|
||||
});
|
||||
describe('and Y-Min is ~10.5 and Y-Max is ~10.5', function() {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].min = '~10.5';
|
||||
ctrl.panel.yaxes[0].max = '~10.5';
|
||||
data[0] = new TimeSeries({
|
||||
datapoints: [[102,10],[104,20], [110,30]], //Also checks precision
|
||||
alias: 'series1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set min to average value + 10.5 and max to average value + 10.5', function() {
|
||||
expect(ctx.plotOptions.yaxes[0].min).to.be(94.8);
|
||||
expect(ctx.plotOptions.yaxes[0].max).to.be(115.8);
|
||||
});
|
||||
});
|
||||
});
|
||||
graphScenario('when using regular Y-Min and Y-Max settings', function(ctx) {
|
||||
describe('and Y-Min is 100 and Y-Max is 200', function() {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].min = '100';
|
||||
ctrl.panel.yaxes[0].max = '200';
|
||||
data[0] = new TimeSeries({
|
||||
datapoints: [[120,10],[160,20]],
|
||||
alias: 'series1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set min to 100 and max to 200', function() {
|
||||
expect(ctx.plotOptions.yaxes[0].min).to.be(100);
|
||||
expect(ctx.plotOptions.yaxes[0].max).to.be(200);
|
||||
});
|
||||
});
|
||||
describe('and Y-Min is 0 and Y-Max is 0', function() {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].min = '0';
|
||||
ctrl.panel.yaxes[0].max = '0';
|
||||
data[0] = new TimeSeries({
|
||||
datapoints: [[120,10],[160,20]],
|
||||
alias: 'series1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set min to 0 and max to 0', function() {
|
||||
expect(ctx.plotOptions.yaxes[0].min).to.be(0);
|
||||
expect(ctx.plotOptions.yaxes[0].max).to.be(0);
|
||||
});
|
||||
});
|
||||
describe('and negative values used', function() {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].min = '-10';
|
||||
ctrl.panel.yaxes[0].max = '-13.14';
|
||||
data[0] = new TimeSeries({
|
||||
datapoints: [[120,10],[160,20]],
|
||||
alias: 'series1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set min and max to negative', function() {
|
||||
expect(ctx.plotOptions.yaxes[0].min).to.be(-10);
|
||||
expect(ctx.plotOptions.yaxes[0].max).to.be(-13.14);
|
||||
});
|
||||
});
|
||||
});
|
||||
graphScenario('when using Y-Min and Y-Max settings stored as number', function(ctx) {
|
||||
describe('and Y-Min is 0 and Y-Max is 100', function() {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].min = 0;
|
||||
ctrl.panel.yaxes[0].max = 100;
|
||||
data[0] = new TimeSeries({
|
||||
datapoints: [[120,10],[160,20]],
|
||||
alias: 'series1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set min to 0 and max to 100', function() {
|
||||
expect(ctx.plotOptions.yaxes[0].min).to.be(0);
|
||||
expect(ctx.plotOptions.yaxes[0].max).to.be(100);
|
||||
});
|
||||
});
|
||||
describe('and Y-Min is -100 and Y-Max is -10.5', function() {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].min = -100;
|
||||
ctrl.panel.yaxes[0].max = -10.5;
|
||||
data[0] = new TimeSeries({
|
||||
datapoints: [[120,10],[160,20]],
|
||||
alias: 'series1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set min to -100 and max to -10.5', function() {
|
||||
expect(ctx.plotOptions.yaxes[0].min).to.be(-100);
|
||||
expect(ctx.plotOptions.yaxes[0].max).to.be(-10.5);
|
||||
});
|
||||
});
|
||||
});
|
||||
// graphScenario('when using flexible Y-Min and Y-Max settings', function(ctx) {
|
||||
// describe('and Y-Min is <100 and Y-Max is >200 and values within range', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '<100';
|
||||
// ctrl.panel.yaxes[0].max = '>200';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to 100 and max to 200', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(100);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(200);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is <100 and Y-Max is >200 and values outside range', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '<100';
|
||||
// ctrl.panel.yaxes[0].max = '>200';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[99,10],[201,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to auto and max to auto', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(null);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(null);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is =10.5 and Y-Max is =10.5', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '=10.5';
|
||||
// ctrl.panel.yaxes[0].max = '=10.5';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[100,10],[120,20], [110,30]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to last value + 10.5 and max to last value + 10.5', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(99.5);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(120.5);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is ~10.5 and Y-Max is ~10.5', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '~10.5';
|
||||
// ctrl.panel.yaxes[0].max = '~10.5';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[102,10],[104,20], [110,30]], //Also checks precision
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to average value + 10.5 and max to average value + 10.5', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(94.8);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(115.8);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// graphScenario('when using regular Y-Min and Y-Max settings', function(ctx) {
|
||||
// describe('and Y-Min is 100 and Y-Max is 200', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '100';
|
||||
// ctrl.panel.yaxes[0].max = '200';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to 100 and max to 200', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(100);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(200);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is 0 and Y-Max is 0', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '0';
|
||||
// ctrl.panel.yaxes[0].max = '0';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to 0 and max to 0', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(0);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(0);
|
||||
// });
|
||||
// });
|
||||
// describe('and negative values used', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = '-10';
|
||||
// ctrl.panel.yaxes[0].max = '-13.14';
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min and max to negative', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(-10);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(-13.14);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// graphScenario('when using Y-Min and Y-Max settings stored as number', function(ctx) {
|
||||
// describe('and Y-Min is 0 and Y-Max is 100', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = 0;
|
||||
// ctrl.panel.yaxes[0].max = 100;
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to 0 and max to 100', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(0);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(100);
|
||||
// });
|
||||
// });
|
||||
// describe('and Y-Min is -100 and Y-Max is -10.5', function() {
|
||||
// ctx.setup(function(ctrl, data) {
|
||||
// ctrl.panel.yaxes[0].min = -100;
|
||||
// ctrl.panel.yaxes[0].max = -10.5;
|
||||
// data[0] = new TimeSeries({
|
||||
// datapoints: [[120,10],[160,20]],
|
||||
// alias: 'series1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('should set min to -100 and max to -10.5', function() {
|
||||
// expect(ctx.plotOptions.yaxes[0].min).to.be(-100);
|
||||
// expect(ctx.plotOptions.yaxes[0].max).to.be(-10.5);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user