From 258a0d276cc61c5a391a1fe3e037ad5c7db66458 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Sun, 18 Feb 2018 00:51:32 +0500 Subject: [PATCH 01/17] Add hook processRange to flot plugin. --- public/vendor/flot/jquery.flot.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/vendor/flot/jquery.flot.js b/public/vendor/flot/jquery.flot.js index ec35fb87bd8..040eb808f48 100644 --- a/public/vendor/flot/jquery.flot.js +++ b/public/vendor/flot/jquery.flot.js @@ -632,6 +632,7 @@ Licensed under the MIT license. processRawData: [], processDatapoints: [], processOffset: [], + processRange: [], drawBackground: [], drawSeries: [], draw: [], @@ -1613,6 +1614,8 @@ Licensed under the MIT license. setRange(axis); }); + executeHooks(hooks.processRange, []); + if (showGrid) { var allocatedAxes = $.grep(axes, function (axis) { From 57013d2228cd2421ca819fbe22d307046158077b Mon Sep 17 00:00:00 2001 From: ilgizar Date: Sun, 18 Feb 2018 00:54:35 +0500 Subject: [PATCH 02/17] Share zero between Y axis. --- .../app/plugins/panel/graph/axes_editor.html | 1 + public/app/plugins/panel/graph/graph.ts | 111 ++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/public/app/plugins/panel/graph/axes_editor.html b/public/app/plugins/panel/graph/axes_editor.html index 6160ef01fec..ee3654a9bbd 100644 --- a/public/app/plugins/panel/graph/axes_editor.html +++ b/public/app/plugins/panel/graph/axes_editor.html @@ -29,6 +29,7 @@ +
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 3ed8cbc1836..ade2fb80960 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -155,6 +155,116 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { } } + function processRangeHook(plot) { + var yaxis = plot.getYAxes(); + if (yaxis.length > 1 && panel.yaxes[1].shareZero) { + shareYLevel(yaxis[0].min, yaxis[0].max, yaxis[1].min, yaxis[1].max, 0); + } + } + + function shareYLevel(minLeft, maxLeft, minRight, maxRight, shareLevel) { + if (shareLevel !== 0) { + minLeft -= shareLevel; + maxLeft -= shareLevel; + minRight -= shareLevel; + maxRight -= shareLevel; + } + + // wide Y min and max using increased wideFactor + var deltaLeft = maxLeft - minLeft; + var deltaRight = maxRight - minRight; + var wideFactor = 0.25; + if (deltaLeft === 0) { + minLeft -= wideFactor; + maxLeft += wideFactor; + } + if (deltaRight === 0) { + minRight -= wideFactor; + maxRight += wideFactor; + } + + // on the opposite sides with respect to zero + if ((minLeft >= 0 && maxRight <= 0) || (maxLeft <= 0 && minRight >= 0)) { + if (minLeft >= 0) { + minLeft = -maxLeft; + maxRight = -minRight; + } else { + maxLeft = -minLeft; + minRight = -maxRight; + } + } else { + var limitTop = Infinity; + var limitBottom = -Infinity; + var absLeftMin = Math.abs(minLeft); + var absLeftMax = Math.abs(maxLeft); + var absRightMin = Math.abs(minRight); + var absRightMax = Math.abs(maxRight); + var upLeft = _.max([absLeftMin, absLeftMax]); + var downLeft = _.min([absLeftMin, absLeftMax]); + var upRight = _.max([absRightMin, absRightMax]); + var downRight = _.min([absRightMin, absRightMax]); + var oneSide = (minLeft >= 0 && minRight >= 0) || (maxLeft <= 0 && maxRight <= 0); + var rateLeft, rateRight, rate; + + // on the one hand with respect to zero + if (oneSide) { + rateLeft = downLeft ? upLeft / downLeft : downLeft >= 0 ? limitTop : limitBottom; + rateRight = downRight ? upRight / downRight : downRight >= 0 ? limitTop : limitBottom; + rate = _.max([rateLeft, rateRight]); + + if (rate === limitTop) { + if (maxLeft > 0) { + minLeft = 0; + minRight = 0; + } else { + maxLeft = 0; + maxRight = 0; + } + } else { + var coef = deltaLeft / deltaRight; + if ((rate === rateLeft && minLeft > 0) || (rate === rateRight && maxRight < 0)) { + maxLeft = maxRight * coef; + minRight = minLeft / coef; + } else { + minLeft = minRight * coef; + maxRight = maxLeft / coef; + } + } + } else { + rateLeft = + minLeft && maxLeft + ? minLeft < 0 ? maxLeft / minLeft : limitBottom + : minLeft < 0 || maxRight >= 0 ? limitBottom : limitTop; + rateRight = + minRight && maxRight + ? minRight < 0 ? maxRight / minRight : limitBottom + : minRight < 0 || maxLeft >= 0 ? limitBottom : limitTop; + rate = _.max([rateLeft, rateRight]); + + if (rate === rateLeft) { + minRight = + upRight === absRightMin && (absRightMin !== absRightMax || upLeft !== absLeftMin) + ? -upRight + : upRight / rate; + maxRight = upRight === absRightMax ? upRight : -upRight * rate; + } else { + minLeft = + upLeft === absLeftMin && (absLeftMin !== absLeftMax || upRight !== absRightMin) + ? -upLeft + : upLeft / rate; + maxLeft = upLeft === absLeftMax ? upLeft : -upLeft * rate; + } + } + } + + if (shareLevel !== 0) { + minLeft += shareLevel; + maxLeft += shareLevel; + minRight += shareLevel; + maxRight += shareLevel; + } + } + // Series could have different timeSteps, // let's find the smallest one so that bars are correctly rendered. // In addition, only take series which are rendered as bars for this. @@ -296,6 +406,7 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { hooks: { draw: [drawHook], processOffset: [processOffsetHook], + processRange: [processRangeHook], }, legend: { show: false }, series: { From 7eeb68b59088686ad3b350d0a8e839d3f41d3116 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Tue, 20 Feb 2018 16:58:49 +0500 Subject: [PATCH 03/17] Refactoring code. Change Y-Zero to Y-Level. --- .../app/plugins/panel/graph/axes_editor.html | 8 +- public/app/plugins/panel/graph/graph.ts | 148 ++++++++++-------- public/app/plugins/panel/graph/module.ts | 2 + public/vendor/flot/jquery.flot.js | 37 +++-- 4 files changed, 117 insertions(+), 78 deletions(-) diff --git a/public/app/plugins/panel/graph/axes_editor.html b/public/app/plugins/panel/graph/axes_editor.html index ee3654a9bbd..a80ebd3036c 100644 --- a/public/app/plugins/panel/graph/axes_editor.html +++ b/public/app/plugins/panel/graph/axes_editor.html @@ -29,7 +29,6 @@
-
@@ -40,6 +39,13 @@
+
+ +
+ + +
+
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index ade2fb80960..95790222cac 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -157,12 +157,17 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { function processRangeHook(plot) { var yaxis = plot.getYAxes(); - if (yaxis.length > 1 && panel.yaxes[1].shareZero) { - shareYLevel(yaxis[0].min, yaxis[0].max, yaxis[1].min, yaxis[1].max, 0); + if (yaxis.length > 1 && panel.yaxes[1].shareLevel) { + shareYLevel(yaxis, parseFloat(panel.yaxes[1].shareY || 0)); } } - function shareYLevel(minLeft, maxLeft, minRight, maxRight, shareLevel) { + function shareYLevel(yaxis, shareLevel) { + var minLeft = yaxis[0].min; + var maxLeft = yaxis[0].max; + var minRight = yaxis[1].min; + var maxRight = yaxis[1].max; + if (shareLevel !== 0) { minLeft -= shareLevel; maxLeft -= shareLevel; @@ -183,76 +188,80 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { maxRight += wideFactor; } - // on the opposite sides with respect to zero - if ((minLeft >= 0 && maxRight <= 0) || (maxLeft <= 0 && minRight >= 0)) { - if (minLeft >= 0) { - minLeft = -maxLeft; - maxRight = -minRight; - } else { - maxLeft = -minLeft; - minRight = -maxRight; - } + // one of graphs on zero + var zero = minLeft === 0 || minRight === 0 || maxLeft === 0 || maxRight === 0; + + // on the one hand with respect to zero + var oneSide = (minLeft >= 0 && minRight >= 0) || (maxLeft <= 0 && maxRight <= 0); + + if (zero && oneSide) { + minLeft = maxLeft > 0 ? 0 : minLeft; + maxLeft = maxLeft > 0 ? maxLeft : 0; + minRight = maxRight > 0 ? 0 : minRight; + maxRight = maxRight > 0 ? maxRight : 0; } else { - var limitTop = Infinity; - var limitBottom = -Infinity; - var absLeftMin = Math.abs(minLeft); - var absLeftMax = Math.abs(maxLeft); - var absRightMin = Math.abs(minRight); - var absRightMax = Math.abs(maxRight); - var upLeft = _.max([absLeftMin, absLeftMax]); - var downLeft = _.min([absLeftMin, absLeftMax]); - var upRight = _.max([absRightMin, absRightMax]); - var downRight = _.min([absRightMin, absRightMax]); - var oneSide = (minLeft >= 0 && minRight >= 0) || (maxLeft <= 0 && maxRight <= 0); - var rateLeft, rateRight, rate; - - // on the one hand with respect to zero - if (oneSide) { - rateLeft = downLeft ? upLeft / downLeft : downLeft >= 0 ? limitTop : limitBottom; - rateRight = downRight ? upRight / downRight : downRight >= 0 ? limitTop : limitBottom; - rate = _.max([rateLeft, rateRight]); - - if (rate === limitTop) { - if (maxLeft > 0) { - minLeft = 0; - minRight = 0; - } else { - maxLeft = 0; - maxRight = 0; - } + // on the opposite sides with respect to zero + if ((minLeft >= 0 && maxRight <= 0) || (maxLeft <= 0 && minRight >= 0)) { + if (minLeft >= 0) { + minLeft = -maxLeft; + maxRight = -minRight; + } else { + maxLeft = -minLeft; + minRight = -maxRight; + } + } else { + // both across zero + var twoCross = minLeft <= 0 && maxLeft >= 0 && minRight <= 0 && maxRight >= 0; + + var rateLeft, rateRight, rate; + if (twoCross) { + rateLeft = minRight ? minLeft / minRight : 0; + rateRight = maxRight ? maxLeft / maxRight : 0; } else { - var coef = deltaLeft / deltaRight; - if ((rate === rateLeft && minLeft > 0) || (rate === rateRight && maxRight < 0)) { - maxLeft = maxRight * coef; - minRight = minLeft / coef; + if (oneSide) { + var absLeftMin = Math.abs(minLeft); + var absLeftMax = Math.abs(maxLeft); + var absRightMin = Math.abs(minRight); + var absRightMax = Math.abs(maxRight); + var upLeft = _.max([absLeftMin, absLeftMax]); + var downLeft = _.min([absLeftMin, absLeftMax]); + var upRight = _.max([absRightMin, absRightMax]); + var downRight = _.min([absRightMin, absRightMax]); + + rateLeft = downLeft ? upLeft / downLeft : upLeft; + rateRight = downRight ? upRight / downRight : upRight; } else { - minLeft = minRight * coef; - maxRight = maxLeft / coef; + if (minLeft > 0 || minRight > 0) { + rateLeft = maxLeft / maxRight; + rateRight = 0; + } else { + rateLeft = 0; + rateRight = minLeft / minRight; + } } } - } else { - rateLeft = - minLeft && maxLeft - ? minLeft < 0 ? maxLeft / minLeft : limitBottom - : minLeft < 0 || maxRight >= 0 ? limitBottom : limitTop; - rateRight = - minRight && maxRight - ? minRight < 0 ? maxRight / minRight : limitBottom - : minRight < 0 || maxLeft >= 0 ? limitBottom : limitTop; - rate = _.max([rateLeft, rateRight]); - - if (rate === rateLeft) { - minRight = - upRight === absRightMin && (absRightMin !== absRightMax || upLeft !== absLeftMin) - ? -upRight - : upRight / rate; - maxRight = upRight === absRightMax ? upRight : -upRight * rate; + rate = rateLeft > rateRight ? rateLeft : rateRight; + + if (oneSide) { + if (minLeft > 0) { + minLeft = maxLeft / rate; + minRight = maxRight / rate; + } else { + maxLeft = minLeft / rate; + maxRight = minRight / rate; + } } else { - minLeft = - upLeft === absLeftMin && (absLeftMin !== absLeftMax || upRight !== absRightMin) - ? -upLeft - : upLeft / rate; - maxLeft = upLeft === absLeftMax ? upLeft : -upLeft * rate; + if (twoCross) { + minLeft = minRight ? minRight * rate : minLeft; + minRight = minLeft ? minLeft / rate : minRight; + maxLeft = maxRight ? maxRight * rate : maxLeft; + maxRight = maxLeft ? maxLeft / rate : maxRight; + } else { + minLeft = minLeft > 0 ? minRight * rate : minLeft; + minRight = minRight > 0 ? minLeft / rate : minRight; + maxLeft = maxLeft < 0 ? maxRight * rate : maxLeft; + maxRight = maxRight < 0 ? maxLeft / rate : maxRight; + } } } } @@ -263,6 +272,11 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { minRight += shareLevel; maxRight += shareLevel; } + + yaxis[0].min = minLeft; + yaxis[0].max = maxLeft; + yaxis[1].min = minRight; + yaxis[1].max = maxRight; } // Series could have different timeSteps, diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index 59e72124c74..67b59997278 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -46,6 +46,8 @@ class GraphCtrl extends MetricsPanelCtrl { min: null, max: null, format: 'short', + shareLevel: false, + shareY: 0, }, ], xaxis: { diff --git a/public/vendor/flot/jquery.flot.js b/public/vendor/flot/jquery.flot.js index 040eb808f48..401198b712d 100644 --- a/public/vendor/flot/jquery.flot.js +++ b/public/vendor/flot/jquery.flot.js @@ -1622,14 +1622,24 @@ Licensed under the MIT license. return axis.show || axis.reserveSpace; }); - $.each(allocatedAxes, function (_, axis) { - // make the ticks - setupTickGeneration(axis); - setTicks(axis); - snapRangeToTicks(axis, axis.ticks); - // find labelWidth/Height for axis - measureTickLabels(axis); - }); + var snaped = false; + for (var i = 0; i < 2; i++) { + $.each(allocatedAxes, function (_, axis) { + // make the ticks + setupTickGeneration(axis); + setTicks(axis); + snaped = snapRangeToTicks(axis, axis.ticks) || snaped; + // find labelWidth/Height for axis + measureTickLabels(axis); + }); + + if (snaped) { + executeHooks(hooks.processRange, []); + snaped = false; + } else { + break; + } + } // with all dimensions calculated, we can compute the // axis bounding boxes, start from the outside @@ -1646,6 +1656,7 @@ Licensed under the MIT license. }); } + plotWidth = surface.width - plotOffset.left - plotOffset.right; plotHeight = surface.height - plotOffset.bottom - plotOffset.top; @@ -1879,13 +1890,19 @@ Licensed under the MIT license. } function snapRangeToTicks(axis, ticks) { + var changed = false; if (axis.options.autoscaleMargin && ticks.length > 0) { // snap to ticks - if (axis.options.min == null) + if (axis.options.min == null) { axis.min = Math.min(axis.min, ticks[0].v); - if (axis.options.max == null && ticks.length > 1) + changed = true; + } + if (axis.options.max == null && ticks.length > 1) { axis.max = Math.max(axis.max, ticks[ticks.length - 1].v); + changed = true; + } } + return changed; } function draw() { From 9e68cbea514380998d4ab5d4b9efe7926935cb05 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Thu, 22 Feb 2018 15:38:32 +0500 Subject: [PATCH 04/17] Refactoring code --- public/app/plugins/panel/graph/align_yaxes.ts | 123 ++++++++++++++++++ .../app/plugins/panel/graph/axes_editor.html | 19 +-- public/app/plugins/panel/graph/graph.ts | 122 +---------------- public/app/plugins/panel/graph/module.ts | 3 +- 4 files changed, 137 insertions(+), 130 deletions(-) create mode 100644 public/app/plugins/panel/graph/align_yaxes.ts diff --git a/public/app/plugins/panel/graph/align_yaxes.ts b/public/app/plugins/panel/graph/align_yaxes.ts new file mode 100644 index 00000000000..74fc9a063c7 --- /dev/null +++ b/public/app/plugins/panel/graph/align_yaxes.ts @@ -0,0 +1,123 @@ +import _ from 'lodash'; + +/** + * To align two Y axes by Y level + * @param yaxis data [{min: min_y1, min: max_y1}, {min: min_y2, max: max_y2}] + * @param align Y level + */ +export function alignYLevel(yaxis, alignLevel) { + var minLeft = yaxis[0].min; + var maxLeft = yaxis[0].max; + var minRight = yaxis[1].min; + var maxRight = yaxis[1].max; + + if (alignLevel !== 0) { + minLeft -= alignLevel; + maxLeft -= alignLevel; + minRight -= alignLevel; + maxRight -= alignLevel; + } + + // wide Y min and max using increased wideFactor + var deltaLeft = maxLeft - minLeft; + var deltaRight = maxRight - minRight; + var wideFactor = 0.25; + if (deltaLeft === 0) { + minLeft -= wideFactor; + maxLeft += wideFactor; + } + if (deltaRight === 0) { + minRight -= wideFactor; + maxRight += wideFactor; + } + + // one of graphs on zero + var zero = minLeft === 0 || minRight === 0 || maxLeft === 0 || maxRight === 0; + + // on the one hand with respect to zero + var oneSide = (minLeft >= 0 && minRight >= 0) || (maxLeft <= 0 && maxRight <= 0); + + if (zero && oneSide) { + minLeft = maxLeft > 0 ? 0 : minLeft; + maxLeft = maxLeft > 0 ? maxLeft : 0; + minRight = maxRight > 0 ? 0 : minRight; + maxRight = maxRight > 0 ? maxRight : 0; + } else { + // on the opposite sides with respect to zero + if ((minLeft >= 0 && maxRight <= 0) || (maxLeft <= 0 && minRight >= 0)) { + if (minLeft >= 0) { + minLeft = -maxLeft; + maxRight = -minRight; + } else { + maxLeft = -minLeft; + minRight = -maxRight; + } + } else { + // both across zero + var twoCross = minLeft <= 0 && maxLeft >= 0 && minRight <= 0 && maxRight >= 0; + + var rateLeft, rateRight, rate; + if (twoCross) { + rateLeft = minRight ? minLeft / minRight : 0; + rateRight = maxRight ? maxLeft / maxRight : 0; + } else { + if (oneSide) { + var absLeftMin = Math.abs(minLeft); + var absLeftMax = Math.abs(maxLeft); + var absRightMin = Math.abs(minRight); + var absRightMax = Math.abs(maxRight); + var upLeft = _.max([absLeftMin, absLeftMax]); + var downLeft = _.min([absLeftMin, absLeftMax]); + var upRight = _.max([absRightMin, absRightMax]); + var downRight = _.min([absRightMin, absRightMax]); + + rateLeft = downLeft ? upLeft / downLeft : upLeft; + rateRight = downRight ? upRight / downRight : upRight; + } else { + if (minLeft > 0 || minRight > 0) { + rateLeft = maxLeft / maxRight; + rateRight = 0; + } else { + rateLeft = 0; + rateRight = minLeft / minRight; + } + } + } + rate = rateLeft > rateRight ? rateLeft : rateRight; + + if (oneSide) { + if (minLeft > 0) { + minLeft = maxLeft / rate; + minRight = maxRight / rate; + } else { + maxLeft = minLeft / rate; + maxRight = minRight / rate; + } + } else { + if (twoCross) { + minLeft = minRight ? minRight * rate : minLeft; + minRight = minLeft ? minLeft / rate : minRight; + maxLeft = maxRight ? maxRight * rate : maxLeft; + maxRight = maxLeft ? maxLeft / rate : maxRight; + } else { + minLeft = minLeft > 0 ? minRight * rate : minLeft; + minRight = minRight > 0 ? minLeft / rate : minRight; + maxLeft = maxLeft < 0 ? maxRight * rate : maxLeft; + maxRight = maxRight < 0 ? maxLeft / rate : maxRight; + } + } + } + } + + if (alignLevel !== 0) { + minLeft += alignLevel; + maxLeft += alignLevel; + minRight += alignLevel; + maxRight += alignLevel; + } + + yaxis[0].min = minLeft; + yaxis[0].max = maxLeft; + yaxis[1].min = minRight; + yaxis[1].max = maxRight; +} diff --git a/public/app/plugins/panel/graph/axes_editor.html b/public/app/plugins/panel/graph/axes_editor.html index a80ebd3036c..7bf6756a7df 100644 --- a/public/app/plugins/panel/graph/axes_editor.html +++ b/public/app/plugins/panel/graph/axes_editor.html @@ -11,6 +11,7 @@
+
@@ -28,8 +29,15 @@
- -
+
+ +
+ + +
+ +
+
@@ -39,13 +47,6 @@
-
- -
- - -
-
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 95790222cac..3f7d1bee33c 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -18,6 +18,7 @@ import GraphTooltip from './graph_tooltip'; import { ThresholdManager } from './threshold_manager'; import { EventManager } from 'app/features/annotations/all'; import { convertValuesToHistogram, getSeriesValues } from './histogram'; +import { alignYLevel } from './align_yaxes'; import config from 'app/core/config'; /** @ngInject **/ @@ -157,128 +158,11 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { function processRangeHook(plot) { var yaxis = plot.getYAxes(); - if (yaxis.length > 1 && panel.yaxes[1].shareLevel) { - shareYLevel(yaxis, parseFloat(panel.yaxes[1].shareY || 0)); + if (yaxis.length > 1 && panel.yaxes[1].align !== null) { + alignYLevel(yaxis, parseFloat(panel.yaxes[1].align)); } } - function shareYLevel(yaxis, shareLevel) { - var minLeft = yaxis[0].min; - var maxLeft = yaxis[0].max; - var minRight = yaxis[1].min; - var maxRight = yaxis[1].max; - - if (shareLevel !== 0) { - minLeft -= shareLevel; - maxLeft -= shareLevel; - minRight -= shareLevel; - maxRight -= shareLevel; - } - - // wide Y min and max using increased wideFactor - var deltaLeft = maxLeft - minLeft; - var deltaRight = maxRight - minRight; - var wideFactor = 0.25; - if (deltaLeft === 0) { - minLeft -= wideFactor; - maxLeft += wideFactor; - } - if (deltaRight === 0) { - minRight -= wideFactor; - maxRight += wideFactor; - } - - // one of graphs on zero - var zero = minLeft === 0 || minRight === 0 || maxLeft === 0 || maxRight === 0; - - // on the one hand with respect to zero - var oneSide = (minLeft >= 0 && minRight >= 0) || (maxLeft <= 0 && maxRight <= 0); - - if (zero && oneSide) { - minLeft = maxLeft > 0 ? 0 : minLeft; - maxLeft = maxLeft > 0 ? maxLeft : 0; - minRight = maxRight > 0 ? 0 : minRight; - maxRight = maxRight > 0 ? maxRight : 0; - } else { - // on the opposite sides with respect to zero - if ((minLeft >= 0 && maxRight <= 0) || (maxLeft <= 0 && minRight >= 0)) { - if (minLeft >= 0) { - minLeft = -maxLeft; - maxRight = -minRight; - } else { - maxLeft = -minLeft; - minRight = -maxRight; - } - } else { - // both across zero - var twoCross = minLeft <= 0 && maxLeft >= 0 && minRight <= 0 && maxRight >= 0; - - var rateLeft, rateRight, rate; - if (twoCross) { - rateLeft = minRight ? minLeft / minRight : 0; - rateRight = maxRight ? maxLeft / maxRight : 0; - } else { - if (oneSide) { - var absLeftMin = Math.abs(minLeft); - var absLeftMax = Math.abs(maxLeft); - var absRightMin = Math.abs(minRight); - var absRightMax = Math.abs(maxRight); - var upLeft = _.max([absLeftMin, absLeftMax]); - var downLeft = _.min([absLeftMin, absLeftMax]); - var upRight = _.max([absRightMin, absRightMax]); - var downRight = _.min([absRightMin, absRightMax]); - - rateLeft = downLeft ? upLeft / downLeft : upLeft; - rateRight = downRight ? upRight / downRight : upRight; - } else { - if (minLeft > 0 || minRight > 0) { - rateLeft = maxLeft / maxRight; - rateRight = 0; - } else { - rateLeft = 0; - rateRight = minLeft / minRight; - } - } - } - rate = rateLeft > rateRight ? rateLeft : rateRight; - - if (oneSide) { - if (minLeft > 0) { - minLeft = maxLeft / rate; - minRight = maxRight / rate; - } else { - maxLeft = minLeft / rate; - maxRight = minRight / rate; - } - } else { - if (twoCross) { - minLeft = minRight ? minRight * rate : minLeft; - minRight = minLeft ? minLeft / rate : minRight; - maxLeft = maxRight ? maxRight * rate : maxLeft; - maxRight = maxLeft ? maxLeft / rate : maxRight; - } else { - minLeft = minLeft > 0 ? minRight * rate : minLeft; - minRight = minRight > 0 ? minLeft / rate : minRight; - maxLeft = maxLeft < 0 ? maxRight * rate : maxLeft; - maxRight = maxRight < 0 ? maxLeft / rate : maxRight; - } - } - } - } - - if (shareLevel !== 0) { - minLeft += shareLevel; - maxLeft += shareLevel; - minRight += shareLevel; - maxRight += shareLevel; - } - - yaxis[0].min = minLeft; - yaxis[0].max = maxLeft; - yaxis[1].min = minRight; - yaxis[1].max = maxRight; - } - // Series could have different timeSteps, // let's find the smallest one so that bars are correctly rendered. // In addition, only take series which are rendered as bars for this. diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index 67b59997278..c198d118115 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -46,8 +46,7 @@ class GraphCtrl extends MetricsPanelCtrl { min: null, max: null, format: 'short', - shareLevel: false, - shareY: 0, + align: null, }, ], xaxis: { From 66590042a6b91dc3ce4e197724d0c1ef96b1bfea Mon Sep 17 00:00:00 2001 From: ilgizar Date: Thu, 22 Feb 2018 15:41:11 +0500 Subject: [PATCH 05/17] Add unit tests. --- .../plugins/panel/graph/specs/align_y.jest.ts | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 public/app/plugins/panel/graph/specs/align_y.jest.ts diff --git a/public/app/plugins/panel/graph/specs/align_y.jest.ts b/public/app/plugins/panel/graph/specs/align_y.jest.ts new file mode 100644 index 00000000000..046d02ee787 --- /dev/null +++ b/public/app/plugins/panel/graph/specs/align_y.jest.ts @@ -0,0 +1,167 @@ +import { alignYLevel } from '../align_yaxes'; + +describe('Graph Y axes aligner', function() { + let yaxes, expected; + let alignY = 0; + + describe('on the one hand with respect to zero', () => { + it('Should shrink Y axis', () => { + yaxes = [{ min: 5, max: 10 }, { min: 2, max: 3 }]; + expected = [{ min: 5, max: 10 }, { min: 1.5, max: 3 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axis', () => { + yaxes = [{ min: 2, max: 3 }, { min: 5, max: 10 }]; + expected = [{ min: 1.5, max: 3 }, { min: 5, max: 10 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axis', () => { + yaxes = [{ min: -10, max: -5 }, { min: -3, max: -2 }]; + expected = [{ min: -10, max: -5 }, { min: -3, max: -1.5 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axis', () => { + yaxes = [{ min: -3, max: -2 }, { min: -10, max: -5 }]; + expected = [{ min: -3, max: -1.5 }, { min: -10, max: -5 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + }); + + describe('on the opposite sides with respect to zero', () => { + it('Should shrink Y axes', () => { + yaxes = [{ min: -3, max: -1 }, { min: 5, max: 10 }]; + expected = [{ min: -3, max: 3 }, { min: -10, max: 10 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + yaxes = [{ min: 1, max: 3 }, { min: -10, max: -5 }]; + expected = [{ min: -3, max: 3 }, { min: -10, max: 10 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + }); + + describe('both across zero', () => { + it('Should shrink Y axes', () => { + yaxes = [{ min: -10, max: 5 }, { min: -2, max: 3 }]; + expected = [{ min: -10, max: 15 }, { min: -2, max: 3 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + yaxes = [{ min: -5, max: 10 }, { min: -3, max: 2 }]; + expected = [{ min: -15, max: 10 }, { min: -3, max: 2 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + }); + + describe('one of graphs on zero', () => { + it('Should shrink Y axes', () => { + yaxes = [{ min: 0, max: 3 }, { min: 5, max: 10 }]; + expected = [{ min: 0, max: 3 }, { min: 0, max: 10 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + yaxes = [{ min: 5, max: 10 }, { min: 0, max: 3 }]; + expected = [{ min: 0, max: 10 }, { min: 0, max: 3 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + yaxes = [{ min: -3, max: 0 }, { min: -10, max: -5 }]; + expected = [{ min: -3, max: 0 }, { min: -10, max: 0 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + yaxes = [{ min: -10, max: -5 }, { min: -3, max: 0 }]; + expected = [{ min: -10, max: 0 }, { min: -3, max: 0 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + }); + + describe('both graphs on zero', () => { + it('Should shrink Y axes', () => { + yaxes = [{ min: 0, max: 3 }, { min: -10, max: 0 }]; + expected = [{ min: -3, max: 3 }, { min: -10, max: 10 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + yaxes = [{ min: -3, max: 0 }, { min: 0, max: 10 }]; + expected = [{ min: -3, max: 3 }, { min: -10, max: 10 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + }); + + describe('mixed placement of graphs relative to zero', () => { + it('Should shrink Y axes', () => { + yaxes = [{ min: -10, max: 5 }, { min: 1, max: 3 }]; + expected = [{ min: -10, max: 5 }, { min: -6, max: 3 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + yaxes = [{ min: 1, max: 3 }, { min: -10, max: 5 }]; + expected = [{ min: -6, max: 3 }, { min: -10, max: 5 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + yaxes = [{ min: -10, max: 5 }, { min: -3, max: -1 }]; + expected = [{ min: -10, max: 5 }, { min: -3, max: 1.5 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + yaxes = [{ min: -3, max: -1 }, { min: -10, max: 5 }]; + expected = [{ min: -3, max: 1.5 }, { min: -10, max: 5 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + }); +}); From 7cddc543068c954124201f1906d0dc576a891499 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Wed, 7 Mar 2018 12:12:39 +0500 Subject: [PATCH 06/17] Add bs-tooltip to Y-Align element. --- public/app/plugins/panel/graph/axes_editor.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/plugins/panel/graph/axes_editor.html b/public/app/plugins/panel/graph/axes_editor.html index 7bf6756a7df..2c08755c17a 100644 --- a/public/app/plugins/panel/graph/axes_editor.html +++ b/public/app/plugins/panel/graph/axes_editor.html @@ -33,7 +33,7 @@
- +
From 916539fad9ebd9cb5a278796a2c54e2310efd755 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Wed, 7 Mar 2018 14:21:10 +0500 Subject: [PATCH 07/17] Append test to check not zero level. --- .../plugins/panel/graph/specs/align_y.jest.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/public/app/plugins/panel/graph/specs/align_y.jest.ts b/public/app/plugins/panel/graph/specs/align_y.jest.ts index 046d02ee787..ff540fd223f 100644 --- a/public/app/plugins/panel/graph/specs/align_y.jest.ts +++ b/public/app/plugins/panel/graph/specs/align_y.jest.ts @@ -158,8 +158,41 @@ describe('Graph Y axes aligner', function() { alignYLevel(yaxes, alignY); expect(yaxes).toMatchObject(expected); }); + }); + + describe('on level not zero', () => { + it('Should shrink Y axis', () => { + alignY = 1; + yaxes = [{ min: 5, max: 10 }, { min: 2, max: 4 }]; + expected = [{ min: 4, max: 10 }, { min: 2, max: 4 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + alignY = 2; + yaxes = [{ min: -3, max: 1 }, { min: 5, max: 10 }]; + expected = [{ min: -3, max: 7 }, { min: -6, max: 10 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + + it('Should shrink Y axes', () => { + alignY = -1; + yaxes = [{ min: -5, max: 5 }, { min: -2, max: 3 }]; + expected = [{ min: -5, max: 15 }, { min: -2, max: 3 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); it('Should shrink Y axes', () => { + alignY = -2; + yaxes = [{ min: -2, max: 3 }, { min: 5, max: 10 }]; + expected = [{ min: -2, max: 3 }, { min: -2, max: 10 }]; + alignYLevel(yaxes, alignY); expect(yaxes).toMatchObject(expected); }); From 8152b9d6fe750a3f662130973141a6a71a752694 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Mon, 12 Mar 2018 10:54:03 +0500 Subject: [PATCH 08/17] Refactoring --- public/app/plugins/panel/graph/align_yaxes.ts | 191 ++++++++++-------- 1 file changed, 102 insertions(+), 89 deletions(-) diff --git a/public/app/plugins/panel/graph/align_yaxes.ts b/public/app/plugins/panel/graph/align_yaxes.ts index 74fc9a063c7..4884cd12441 100644 --- a/public/app/plugins/panel/graph/align_yaxes.ts +++ b/public/app/plugins/panel/graph/align_yaxes.ts @@ -6,118 +6,131 @@ import _ from 'lodash'; * @param align Y level */ export function alignYLevel(yaxis, alignLevel) { - var minLeft = yaxis[0].min; - var maxLeft = yaxis[0].max; - var minRight = yaxis[1].min; - var maxRight = yaxis[1].max; + moveLevelToZero(yaxis, alignLevel); - if (alignLevel !== 0) { - minLeft -= alignLevel; - maxLeft -= alignLevel; - minRight -= alignLevel; - maxRight -= alignLevel; - } - - // wide Y min and max using increased wideFactor - var deltaLeft = maxLeft - minLeft; - var deltaRight = maxRight - minRight; - var wideFactor = 0.25; - if (deltaLeft === 0) { - minLeft -= wideFactor; - maxLeft += wideFactor; - } - if (deltaRight === 0) { - minRight -= wideFactor; - maxRight += wideFactor; - } + expandStuckValues(yaxis); // one of graphs on zero - var zero = minLeft === 0 || minRight === 0 || maxLeft === 0 || maxRight === 0; + var zero = yaxis[0].min === 0 || yaxis[1].min === 0 || yaxis[0].max === 0 || yaxis[1].max === 0; - // on the one hand with respect to zero - var oneSide = (minLeft >= 0 && minRight >= 0) || (maxLeft <= 0 && maxRight <= 0); + var oneSide = checkOneSide(yaxis); if (zero && oneSide) { - minLeft = maxLeft > 0 ? 0 : minLeft; - maxLeft = maxLeft > 0 ? maxLeft : 0; - minRight = maxRight > 0 ? 0 : minRight; - maxRight = maxRight > 0 ? maxRight : 0; + yaxis[0].min = yaxis[0].max > 0 ? 0 : yaxis[0].min; + yaxis[0].max = yaxis[0].max > 0 ? yaxis[0].max : 0; + yaxis[1].min = yaxis[1].max > 0 ? 0 : yaxis[1].min; + yaxis[1].max = yaxis[1].max > 0 ? yaxis[1].max : 0; } else { // on the opposite sides with respect to zero - if ((minLeft >= 0 && maxRight <= 0) || (maxLeft <= 0 && minRight >= 0)) { - if (minLeft >= 0) { - minLeft = -maxLeft; - maxRight = -minRight; + if ((yaxis[0].min >= 0 && yaxis[1].max <= 0) || (yaxis[0].max <= 0 && yaxis[1].min >= 0)) { + if (yaxis[0].min >= 0) { + yaxis[0].min = -yaxis[0].max; + yaxis[1].max = -yaxis[1].min; } else { - maxLeft = -minLeft; - minRight = -maxRight; + yaxis[0].max = -yaxis[0].min; + yaxis[1].min = -yaxis[1].max; } } else { - // both across zero - var twoCross = minLeft <= 0 && maxLeft >= 0 && minRight <= 0 && maxRight >= 0; - - var rateLeft, rateRight, rate; - if (twoCross) { - rateLeft = minRight ? minLeft / minRight : 0; - rateRight = maxRight ? maxLeft / maxRight : 0; - } else { - if (oneSide) { - var absLeftMin = Math.abs(minLeft); - var absLeftMax = Math.abs(maxLeft); - var absRightMin = Math.abs(minRight); - var absRightMax = Math.abs(maxRight); - var upLeft = _.max([absLeftMin, absLeftMax]); - var downLeft = _.min([absLeftMin, absLeftMax]); - var upRight = _.max([absRightMin, absRightMax]); - var downRight = _.min([absRightMin, absRightMax]); - - rateLeft = downLeft ? upLeft / downLeft : upLeft; - rateRight = downRight ? upRight / downRight : upRight; - } else { - if (minLeft > 0 || minRight > 0) { - rateLeft = maxLeft / maxRight; - rateRight = 0; - } else { - rateLeft = 0; - rateRight = minLeft / minRight; - } - } - } - rate = rateLeft > rateRight ? rateLeft : rateRight; + var rate = getRate(yaxis); if (oneSide) { - if (minLeft > 0) { - minLeft = maxLeft / rate; - minRight = maxRight / rate; + if (yaxis[0].min > 0) { + yaxis[0].min = yaxis[0].max / rate; + yaxis[1].min = yaxis[1].max / rate; } else { - maxLeft = minLeft / rate; - maxRight = minRight / rate; + yaxis[0].max = yaxis[0].min / rate; + yaxis[1].max = yaxis[1].min / rate; } } else { - if (twoCross) { - minLeft = minRight ? minRight * rate : minLeft; - minRight = minLeft ? minLeft / rate : minRight; - maxLeft = maxRight ? maxRight * rate : maxLeft; - maxRight = maxLeft ? maxLeft / rate : maxRight; + if (checkTwoCross(yaxis)) { + yaxis[0].min = yaxis[1].min ? yaxis[1].min * rate : yaxis[0].min; + yaxis[1].min = yaxis[0].min ? yaxis[0].min / rate : yaxis[1].min; + yaxis[0].max = yaxis[1].max ? yaxis[1].max * rate : yaxis[0].max; + yaxis[1].max = yaxis[0].max ? yaxis[0].max / rate : yaxis[1].max; } else { - minLeft = minLeft > 0 ? minRight * rate : minLeft; - minRight = minRight > 0 ? minLeft / rate : minRight; - maxLeft = maxLeft < 0 ? maxRight * rate : maxLeft; - maxRight = maxRight < 0 ? maxLeft / rate : maxRight; + yaxis[0].min = yaxis[0].min > 0 ? yaxis[1].min * rate : yaxis[0].min; + yaxis[1].min = yaxis[1].min > 0 ? yaxis[0].min / rate : yaxis[1].min; + yaxis[0].max = yaxis[0].max < 0 ? yaxis[1].max * rate : yaxis[0].max; + yaxis[1].max = yaxis[1].max < 0 ? yaxis[0].max / rate : yaxis[1].max; } } } } + restoreLevelFromZero(yaxis, alignLevel); +} + +function expandStuckValues(yaxis) { + // wide Y min and max using increased wideFactor + var wideFactor = 0.25; + if (yaxis[0].max === yaxis[0].min) { + yaxis[0].min -= wideFactor; + yaxis[0].max += wideFactor; + } + if (yaxis[1].max === yaxis[1].min) { + yaxis[1].min -= wideFactor; + yaxis[1].max += wideFactor; + } +} + +function moveLevelToZero(yaxis, alignLevel) { + if (alignLevel !== 0) { + yaxis[0].min -= alignLevel; + yaxis[0].max -= alignLevel; + yaxis[1].min -= alignLevel; + yaxis[1].max -= alignLevel; + } +} + +function restoreLevelFromZero(yaxis, alignLevel) { if (alignLevel !== 0) { - minLeft += alignLevel; - maxLeft += alignLevel; - minRight += alignLevel; - maxRight += alignLevel; + yaxis[0].min += alignLevel; + yaxis[0].max += alignLevel; + yaxis[1].min += alignLevel; + yaxis[1].max += alignLevel; + } +} + +function checkOneSide(yaxis) { + // on the one hand with respect to zero + return (yaxis[0].min >= 0 && yaxis[1].min >= 0) || (yaxis[0].max <= 0 && yaxis[1].max <= 0); +} + +function checkTwoCross(yaxis) { + // both across zero + return yaxis[0].min <= 0 && yaxis[0].max >= 0 && yaxis[1].min <= 0 && yaxis[1].max >= 0; +} + +function getRate(yaxis) { + var rateLeft, rateRight, rate; + if (checkTwoCross(yaxis)) { + rateLeft = yaxis[1].min ? yaxis[0].min / yaxis[1].min : 0; + rateRight = yaxis[1].max ? yaxis[0].max / yaxis[1].max : 0; + } else { + if (checkOneSide(yaxis)) { + var absLeftMin = Math.abs(yaxis[0].min); + var absLeftMax = Math.abs(yaxis[0].max); + var absRightMin = Math.abs(yaxis[1].min); + var absRightMax = Math.abs(yaxis[1].max); + var upLeft = _.max([absLeftMin, absLeftMax]); + var downLeft = _.min([absLeftMin, absLeftMax]); + var upRight = _.max([absRightMin, absRightMax]); + var downRight = _.min([absRightMin, absRightMax]); + + rateLeft = downLeft ? upLeft / downLeft : upLeft; + rateRight = downRight ? upRight / downRight : upRight; + } else { + if (yaxis[0].min > 0 || yaxis[1].min > 0) { + rateLeft = yaxis[0].max / yaxis[1].max; + rateRight = 0; + } else { + rateLeft = 0; + rateRight = yaxis[0].min / yaxis[1].min; + } + } } - yaxis[0].min = minLeft; - yaxis[0].max = maxLeft; - yaxis[1].min = minRight; - yaxis[1].max = maxRight; + rate = rateLeft > rateRight ? rateLeft : rateRight; + + return rate; } From 11ae926388ff80e3caefdc6812a7e651ad3b7ed5 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Mon, 12 Mar 2018 23:11:11 +0500 Subject: [PATCH 09/17] Rename test file according module name. --- .../panel/graph/specs/{align_y.jest.ts => align_yaxes.jest.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename public/app/plugins/panel/graph/specs/{align_y.jest.ts => align_yaxes.jest.ts} (100%) diff --git a/public/app/plugins/panel/graph/specs/align_y.jest.ts b/public/app/plugins/panel/graph/specs/align_yaxes.jest.ts similarity index 100% rename from public/app/plugins/panel/graph/specs/align_y.jest.ts rename to public/app/plugins/panel/graph/specs/align_yaxes.jest.ts From 8c82e5701c41f828f7d7770fb8177b258afd231f Mon Sep 17 00:00:00 2001 From: ilgizar Date: Mon, 12 Mar 2018 23:12:45 +0500 Subject: [PATCH 10/17] Replaced array values to variables yLeft and yRight for easy reading code. --- public/app/plugins/panel/graph/align_yaxes.ts | 134 +++++++++--------- 1 file changed, 70 insertions(+), 64 deletions(-) diff --git a/public/app/plugins/panel/graph/align_yaxes.ts b/public/app/plugins/panel/graph/align_yaxes.ts index 4884cd12441..b60d75e7b66 100644 --- a/public/app/plugins/panel/graph/align_yaxes.ts +++ b/public/app/plugins/panel/graph/align_yaxes.ts @@ -6,112 +6,118 @@ import _ from 'lodash'; * @param align Y level */ export function alignYLevel(yaxis, alignLevel) { - moveLevelToZero(yaxis, alignLevel); + var [yLeft, yRight] = yaxis; + moveLevelToZero(yLeft, yRight, alignLevel); - expandStuckValues(yaxis); + expandStuckValues(yLeft, yRight); // one of graphs on zero - var zero = yaxis[0].min === 0 || yaxis[1].min === 0 || yaxis[0].max === 0 || yaxis[1].max === 0; + var zero = yLeft.min === 0 || yRight.min === 0 || yLeft.max === 0 || yRight.max === 0; - var oneSide = checkOneSide(yaxis); + var oneSide = checkOneSide(yLeft, yRight); if (zero && oneSide) { - yaxis[0].min = yaxis[0].max > 0 ? 0 : yaxis[0].min; - yaxis[0].max = yaxis[0].max > 0 ? yaxis[0].max : 0; - yaxis[1].min = yaxis[1].max > 0 ? 0 : yaxis[1].min; - yaxis[1].max = yaxis[1].max > 0 ? yaxis[1].max : 0; + yLeft.min = yLeft.max > 0 ? 0 : yLeft.min; + yLeft.max = yLeft.max > 0 ? yLeft.max : 0; + yRight.min = yRight.max > 0 ? 0 : yRight.min; + yRight.max = yRight.max > 0 ? yRight.max : 0; } else { - // on the opposite sides with respect to zero - if ((yaxis[0].min >= 0 && yaxis[1].max <= 0) || (yaxis[0].max <= 0 && yaxis[1].min >= 0)) { - if (yaxis[0].min >= 0) { - yaxis[0].min = -yaxis[0].max; - yaxis[1].max = -yaxis[1].min; + if (checkOppositeSides(yLeft, yRight)) { + if (yLeft.min >= 0) { + yLeft.min = -yLeft.max; + yRight.max = -yRight.min; } else { - yaxis[0].max = -yaxis[0].min; - yaxis[1].min = -yaxis[1].max; + yLeft.max = -yLeft.min; + yRight.min = -yRight.max; } } else { - var rate = getRate(yaxis); + var rate = getRate(yLeft, yRight); if (oneSide) { - if (yaxis[0].min > 0) { - yaxis[0].min = yaxis[0].max / rate; - yaxis[1].min = yaxis[1].max / rate; + // all graphs above the Y level + if (yLeft.min > 0) { + yLeft.min = yLeft.max / rate; + yRight.min = yRight.max / rate; } else { - yaxis[0].max = yaxis[0].min / rate; - yaxis[1].max = yaxis[1].min / rate; + yLeft.max = yLeft.min / rate; + yRight.max = yRight.min / rate; } } else { - if (checkTwoCross(yaxis)) { - yaxis[0].min = yaxis[1].min ? yaxis[1].min * rate : yaxis[0].min; - yaxis[1].min = yaxis[0].min ? yaxis[0].min / rate : yaxis[1].min; - yaxis[0].max = yaxis[1].max ? yaxis[1].max * rate : yaxis[0].max; - yaxis[1].max = yaxis[0].max ? yaxis[0].max / rate : yaxis[1].max; + if (checkTwoCross(yLeft, yRight)) { + yLeft.min = yRight.min ? yRight.min * rate : yLeft.min; + yRight.min = yLeft.min ? yLeft.min / rate : yRight.min; + yLeft.max = yRight.max ? yRight.max * rate : yLeft.max; + yRight.max = yLeft.max ? yLeft.max / rate : yRight.max; } else { - yaxis[0].min = yaxis[0].min > 0 ? yaxis[1].min * rate : yaxis[0].min; - yaxis[1].min = yaxis[1].min > 0 ? yaxis[0].min / rate : yaxis[1].min; - yaxis[0].max = yaxis[0].max < 0 ? yaxis[1].max * rate : yaxis[0].max; - yaxis[1].max = yaxis[1].max < 0 ? yaxis[0].max / rate : yaxis[1].max; + yLeft.min = yLeft.min > 0 ? yRight.min * rate : yLeft.min; + yRight.min = yRight.min > 0 ? yLeft.min / rate : yRight.min; + yLeft.max = yLeft.max < 0 ? yRight.max * rate : yLeft.max; + yRight.max = yRight.max < 0 ? yLeft.max / rate : yRight.max; } } } } - restoreLevelFromZero(yaxis, alignLevel); + restoreLevelFromZero(yLeft, yRight, alignLevel); } -function expandStuckValues(yaxis) { +function expandStuckValues(yLeft, yRight) { // wide Y min and max using increased wideFactor var wideFactor = 0.25; - if (yaxis[0].max === yaxis[0].min) { - yaxis[0].min -= wideFactor; - yaxis[0].max += wideFactor; + if (yLeft.max === yLeft.min) { + yLeft.min -= wideFactor; + yLeft.max += wideFactor; } - if (yaxis[1].max === yaxis[1].min) { - yaxis[1].min -= wideFactor; - yaxis[1].max += wideFactor; + if (yRight.max === yRight.min) { + yRight.min -= wideFactor; + yRight.max += wideFactor; } } -function moveLevelToZero(yaxis, alignLevel) { +function moveLevelToZero(yLeft, yRight, alignLevel) { if (alignLevel !== 0) { - yaxis[0].min -= alignLevel; - yaxis[0].max -= alignLevel; - yaxis[1].min -= alignLevel; - yaxis[1].max -= alignLevel; + yLeft.min -= alignLevel; + yLeft.max -= alignLevel; + yRight.min -= alignLevel; + yRight.max -= alignLevel; } } -function restoreLevelFromZero(yaxis, alignLevel) { +function restoreLevelFromZero(yLeft, yRight, alignLevel) { if (alignLevel !== 0) { - yaxis[0].min += alignLevel; - yaxis[0].max += alignLevel; - yaxis[1].min += alignLevel; - yaxis[1].max += alignLevel; + yLeft.min += alignLevel; + yLeft.max += alignLevel; + yRight.min += alignLevel; + yRight.max += alignLevel; } } -function checkOneSide(yaxis) { +function checkOneSide(yLeft, yRight) { // on the one hand with respect to zero - return (yaxis[0].min >= 0 && yaxis[1].min >= 0) || (yaxis[0].max <= 0 && yaxis[1].max <= 0); + return (yLeft.min >= 0 && yRight.min >= 0) || (yLeft.max <= 0 && yRight.max <= 0); } -function checkTwoCross(yaxis) { +function checkTwoCross(yLeft, yRight) { // both across zero - return yaxis[0].min <= 0 && yaxis[0].max >= 0 && yaxis[1].min <= 0 && yaxis[1].max >= 0; + return yLeft.min <= 0 && yLeft.max >= 0 && yRight.min <= 0 && yRight.max >= 0; } -function getRate(yaxis) { +function checkOppositeSides(yLeft, yRight) { + // on the opposite sides with respect to zero + return (yLeft.min >= 0 && yRight.max <= 0) || (yLeft.max <= 0 && yRight.min >= 0); +} + +function getRate(yLeft, yRight) { var rateLeft, rateRight, rate; - if (checkTwoCross(yaxis)) { - rateLeft = yaxis[1].min ? yaxis[0].min / yaxis[1].min : 0; - rateRight = yaxis[1].max ? yaxis[0].max / yaxis[1].max : 0; + if (checkTwoCross(yLeft, yRight)) { + rateLeft = yRight.min ? yLeft.min / yRight.min : 0; + rateRight = yRight.max ? yLeft.max / yRight.max : 0; } else { - if (checkOneSide(yaxis)) { - var absLeftMin = Math.abs(yaxis[0].min); - var absLeftMax = Math.abs(yaxis[0].max); - var absRightMin = Math.abs(yaxis[1].min); - var absRightMax = Math.abs(yaxis[1].max); + if (checkOneSide(yLeft, yRight)) { + var absLeftMin = Math.abs(yLeft.min); + var absLeftMax = Math.abs(yLeft.max); + var absRightMin = Math.abs(yRight.min); + var absRightMax = Math.abs(yRight.max); var upLeft = _.max([absLeftMin, absLeftMax]); var downLeft = _.min([absLeftMin, absLeftMax]); var upRight = _.max([absRightMin, absRightMax]); @@ -120,12 +126,12 @@ function getRate(yaxis) { rateLeft = downLeft ? upLeft / downLeft : upLeft; rateRight = downRight ? upRight / downRight : upRight; } else { - if (yaxis[0].min > 0 || yaxis[1].min > 0) { - rateLeft = yaxis[0].max / yaxis[1].max; + if (yLeft.min > 0 || yRight.min > 0) { + rateLeft = yLeft.max / yRight.max; rateRight = 0; } else { rateLeft = 0; - rateRight = yaxis[0].min / yaxis[1].min; + rateRight = yLeft.min / yRight.min; } } } From 7dd66450adc6dea4ac499c1027937160997f64b4 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Mon, 12 Mar 2018 23:43:13 +0500 Subject: [PATCH 11/17] Corrected work for graphs created before this feature. --- public/app/plugins/panel/graph/graph.ts | 2 +- public/vendor/flot/jquery.flot.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 3f7d1bee33c..231b1ecaf42 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -158,7 +158,7 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { function processRangeHook(plot) { var yaxis = plot.getYAxes(); - if (yaxis.length > 1 && panel.yaxes[1].align !== null) { + if (yaxis.length > 1 && 'align' in panel.yaxes[1] && panel.yaxes[1].align !== null) { alignYLevel(yaxis, parseFloat(panel.yaxes[1].align)); } } diff --git a/public/vendor/flot/jquery.flot.js b/public/vendor/flot/jquery.flot.js index 401198b712d..8ee09e25c41 100644 --- a/public/vendor/flot/jquery.flot.js +++ b/public/vendor/flot/jquery.flot.js @@ -1633,7 +1633,7 @@ Licensed under the MIT license. measureTickLabels(axis); }); - if (snaped) { + if (snaped && hooks.processRange.length > 0) { executeHooks(hooks.processRange, []); snaped = false; } else { From 9d7ab78d9f0c38c143f8cdf1fda0644897493e12 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Wed, 14 Mar 2018 23:39:05 +0500 Subject: [PATCH 12/17] Resolved conflict --- public/app/plugins/panel/graph/graph.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 231b1ecaf42..bbfe63a87b2 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -17,7 +17,7 @@ import { appEvents, coreModule, updateLegendValues } from 'app/core/core'; import GraphTooltip from './graph_tooltip'; import { ThresholdManager } from './threshold_manager'; import { EventManager } from 'app/features/annotations/all'; -import { convertValuesToHistogram, getSeriesValues } from './histogram'; +import { convertToHistogramData } from './histogram'; import { alignYLevel } from './align_yaxes'; import config from 'app/core/config'; From 230f018c7820542162e7ae4f9e52bf56fcd7011a Mon Sep 17 00:00:00 2001 From: ilgizar Date: Tue, 20 Mar 2018 15:37:18 +0500 Subject: [PATCH 13/17] Added validation of input parameters. --- public/app/plugins/panel/graph/align_yaxes.ts | 12 ++++++++++++ .../plugins/panel/graph/specs/align_yaxes.jest.ts | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/public/app/plugins/panel/graph/align_yaxes.ts b/public/app/plugins/panel/graph/align_yaxes.ts index b60d75e7b66..71bfcd8423d 100644 --- a/public/app/plugins/panel/graph/align_yaxes.ts +++ b/public/app/plugins/panel/graph/align_yaxes.ts @@ -6,6 +6,10 @@ import _ from 'lodash'; * @param align Y level */ export function alignYLevel(yaxis, alignLevel) { + if (isNaN(alignLevel) || !checkCorrectAxis(yaxis)) { + return; + } + var [yLeft, yRight] = yaxis; moveLevelToZero(yLeft, yRight, alignLevel); @@ -92,6 +96,14 @@ function restoreLevelFromZero(yLeft, yRight, alignLevel) { } } +function checkCorrectAxis(axis) { + return axis.length === 2 && checkCorrectAxes(axis[0]) && checkCorrectAxes(axis[1]); +} + +function checkCorrectAxes(axes) { + return 'min' in axes && 'max' in axes; +} + function checkOneSide(yLeft, yRight) { // on the one hand with respect to zero return (yLeft.min >= 0 && yRight.min >= 0) || (yLeft.max <= 0 && yRight.max <= 0); diff --git a/public/app/plugins/panel/graph/specs/align_yaxes.jest.ts b/public/app/plugins/panel/graph/specs/align_yaxes.jest.ts index ff540fd223f..963ecfbfa1f 100644 --- a/public/app/plugins/panel/graph/specs/align_yaxes.jest.ts +++ b/public/app/plugins/panel/graph/specs/align_yaxes.jest.ts @@ -197,4 +197,15 @@ describe('Graph Y axes aligner', function() { expect(yaxes).toMatchObject(expected); }); }); + + describe('on level not number value', () => { + it('Should ignore without errors', () => { + alignY = 'q'; + yaxes = [{ min: 5, max: 10 }, { min: 2, max: 4 }]; + expected = [{ min: 5, max: 10 }, { min: 2, max: 4 }]; + + alignYLevel(yaxes, alignY); + expect(yaxes).toMatchObject(expected); + }); + }); }); From 1588295375574bfda62d34271707535dfed6c16d Mon Sep 17 00:00:00 2001 From: ilgizar Date: Tue, 20 Mar 2018 15:38:48 +0500 Subject: [PATCH 14/17] Changed the way this feature was activated. And changed tolltip. --- public/app/plugins/panel/graph/axes_editor.html | 11 ++++++++--- public/app/plugins/panel/graph/graph.ts | 5 +++-- public/app/plugins/panel/graph/module.ts | 3 ++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/public/app/plugins/panel/graph/axes_editor.html b/public/app/plugins/panel/graph/axes_editor.html index 2c08755c17a..f17c9ce105f 100644 --- a/public/app/plugins/panel/graph/axes_editor.html +++ b/public/app/plugins/panel/graph/axes_editor.html @@ -31,9 +31,14 @@
-
- - +
+
+ +
+
+ + +
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 73b261fce3a..713d7079152 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -158,8 +158,9 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { function processRangeHook(plot) { var yaxis = plot.getYAxes(); - if (yaxis.length > 1 && 'align' in panel.yaxes[1] && panel.yaxes[1].align !== null) { - alignYLevel(yaxis, parseFloat(panel.yaxes[1].align)); + if (yaxis.length > 1 && panel.yaxes[1].alignment) { + var align = panel.yaxes[1].align || 0; + alignYLevel(yaxis, parseFloat(align)); } } diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index c198d118115..7e7b270bd61 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -46,7 +46,8 @@ class GraphCtrl extends MetricsPanelCtrl { min: null, max: null, format: 'short', - align: null, + alignment: false, + align: 0, }, ], xaxis: { From e015047ed1c234eed8d14c91b3b6eb5f7f5b7612 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Tue, 20 Mar 2018 16:09:52 +0500 Subject: [PATCH 15/17] Fixed unit test. --- public/app/plugins/panel/graph/specs/align_yaxes.jest.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/app/plugins/panel/graph/specs/align_yaxes.jest.ts b/public/app/plugins/panel/graph/specs/align_yaxes.jest.ts index 963ecfbfa1f..da3aff91275 100644 --- a/public/app/plugins/panel/graph/specs/align_yaxes.jest.ts +++ b/public/app/plugins/panel/graph/specs/align_yaxes.jest.ts @@ -200,11 +200,10 @@ describe('Graph Y axes aligner', function() { describe('on level not number value', () => { it('Should ignore without errors', () => { - alignY = 'q'; yaxes = [{ min: 5, max: 10 }, { min: 2, max: 4 }]; expected = [{ min: 5, max: 10 }, { min: 2, max: 4 }]; - alignYLevel(yaxes, alignY); + alignYLevel(yaxes, 'q'); expect(yaxes).toMatchObject(expected); }); }); From 0e159dada1be72b121c93cb2d682b890f44968e9 Mon Sep 17 00:00:00 2001 From: ilgizar Date: Tue, 20 Mar 2018 22:44:48 +0500 Subject: [PATCH 16/17] Allocated to a separate alignment block. Replaced the attribute of the second axis by the attribute of the axes. --- .../app/plugins/panel/graph/axes_editor.html | 20 +++++++++---------- public/app/plugins/panel/graph/graph.ts | 4 ++-- public/app/plugins/panel/graph/module.ts | 6 ++++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/public/app/plugins/panel/graph/axes_editor.html b/public/app/plugins/panel/graph/axes_editor.html index f17c9ce105f..9020bbe4446 100644 --- a/public/app/plugins/panel/graph/axes_editor.html +++ b/public/app/plugins/panel/graph/axes_editor.html @@ -31,16 +31,6 @@
-
-
- -
-
- - -
-
-
@@ -77,6 +67,16 @@
+
+
+
Y-Axes
+ +
+ + +
+
+
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 713d7079152..dc801a1b33f 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -158,8 +158,8 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { function processRangeHook(plot) { var yaxis = plot.getYAxes(); - if (yaxis.length > 1 && panel.yaxes[1].alignment) { - var align = panel.yaxes[1].align || 0; + if (yaxis.length > 1 && panel.yaxis.alignment) { + var align = panel.yaxis.align || 0; alignYLevel(yaxis, parseFloat(align)); } } diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index 7e7b270bd61..2fe1ecc8684 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -46,8 +46,6 @@ class GraphCtrl extends MetricsPanelCtrl { min: null, max: null, format: 'short', - alignment: false, - align: 0, }, ], xaxis: { @@ -57,6 +55,10 @@ class GraphCtrl extends MetricsPanelCtrl { values: [], buckets: null, }, + yaxis: { + alignment: false, + align: 0, + }, // show/hide lines lines: true, // fill factor From c672e44d35c5976df7f00b7acd9b06d829049928 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Thu, 22 Mar 2018 18:30:23 +0100 Subject: [PATCH 17/17] graph: minor fixes to y-axes alignment feature --- public/app/plugins/panel/graph/align_yaxes.ts | 38 +++++++++---------- .../app/plugins/panel/graph/axes_editor.html | 10 +++-- public/app/plugins/panel/graph/graph.ts | 10 +++-- public/app/plugins/panel/graph/module.ts | 4 +- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/public/app/plugins/panel/graph/align_yaxes.ts b/public/app/plugins/panel/graph/align_yaxes.ts index 71bfcd8423d..e0d8794c250 100644 --- a/public/app/plugins/panel/graph/align_yaxes.ts +++ b/public/app/plugins/panel/graph/align_yaxes.ts @@ -2,16 +2,16 @@ import _ from 'lodash'; /** * To align two Y axes by Y level - * @param yaxis data [{min: min_y1, min: max_y1}, {min: min_y2, max: max_y2}] - * @param align Y level + * @param yAxes data [{min: min_y1, min: max_y1}, {min: min_y2, max: max_y2}] + * @param level Y level */ -export function alignYLevel(yaxis, alignLevel) { - if (isNaN(alignLevel) || !checkCorrectAxis(yaxis)) { +export function alignYLevel(yAxes, level) { + if (isNaN(level) || !checkCorrectAxis(yAxes)) { return; } - var [yLeft, yRight] = yaxis; - moveLevelToZero(yLeft, yRight, alignLevel); + var [yLeft, yRight] = yAxes; + moveLevelToZero(yLeft, yRight, level); expandStuckValues(yLeft, yRight); @@ -62,7 +62,7 @@ export function alignYLevel(yaxis, alignLevel) { } } - restoreLevelFromZero(yLeft, yRight, alignLevel); + restoreLevelFromZero(yLeft, yRight, level); } function expandStuckValues(yLeft, yRight) { @@ -78,21 +78,21 @@ function expandStuckValues(yLeft, yRight) { } } -function moveLevelToZero(yLeft, yRight, alignLevel) { - if (alignLevel !== 0) { - yLeft.min -= alignLevel; - yLeft.max -= alignLevel; - yRight.min -= alignLevel; - yRight.max -= alignLevel; +function moveLevelToZero(yLeft, yRight, level) { + if (level !== 0) { + yLeft.min -= level; + yLeft.max -= level; + yRight.min -= level; + yRight.max -= level; } } -function restoreLevelFromZero(yLeft, yRight, alignLevel) { - if (alignLevel !== 0) { - yLeft.min += alignLevel; - yLeft.max += alignLevel; - yRight.min += alignLevel; - yRight.max += alignLevel; +function restoreLevelFromZero(yLeft, yRight, level) { + if (level !== 0) { + yLeft.min += level; + yLeft.max += level; + yRight.min += level; + yRight.max += level; } } diff --git a/public/app/plugins/panel/graph/axes_editor.html b/public/app/plugins/panel/graph/axes_editor.html index 9020bbe4446..6ec64015746 100644 --- a/public/app/plugins/panel/graph/axes_editor.html +++ b/public/app/plugins/panel/graph/axes_editor.html @@ -70,10 +70,12 @@

Y-Axes
- -
- - + +
+ +
diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index dc801a1b33f..8a2aea8c4c2 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -157,10 +157,12 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) { } function processRangeHook(plot) { - var yaxis = plot.getYAxes(); - if (yaxis.length > 1 && panel.yaxis.alignment) { - var align = panel.yaxis.align || 0; - alignYLevel(yaxis, parseFloat(align)); + var yAxes = plot.getYAxes(); + const align = panel.yaxis.align || false; + + if (yAxes.length > 1 && align === true) { + const level = panel.yaxis.alignLevel || 0; + alignYLevel(yAxes, parseFloat(level)); } } diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index 2fe1ecc8684..6cebbe65ab8 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -56,8 +56,8 @@ class GraphCtrl extends MetricsPanelCtrl { buckets: null, }, yaxis: { - alignment: false, - align: 0, + align: false, + alignLevel: null, }, // show/hide lines lines: true,