mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #10994 from ilgizar/1271_share_zero
This commit is contained in:
commit
1ee0d1c296
154
public/app/plugins/panel/graph/align_yaxes.ts
Normal file
154
public/app/plugins/panel/graph/align_yaxes.ts
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To align two Y axes by Y level
|
||||||
|
* @param yAxes data [{min: min_y1, min: max_y1}, {min: min_y2, max: max_y2}]
|
||||||
|
* @param level Y level
|
||||||
|
*/
|
||||||
|
export function alignYLevel(yAxes, level) {
|
||||||
|
if (isNaN(level) || !checkCorrectAxis(yAxes)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var [yLeft, yRight] = yAxes;
|
||||||
|
moveLevelToZero(yLeft, yRight, level);
|
||||||
|
|
||||||
|
expandStuckValues(yLeft, yRight);
|
||||||
|
|
||||||
|
// one of graphs on zero
|
||||||
|
var zero = yLeft.min === 0 || yRight.min === 0 || yLeft.max === 0 || yRight.max === 0;
|
||||||
|
|
||||||
|
var oneSide = checkOneSide(yLeft, yRight);
|
||||||
|
|
||||||
|
if (zero && oneSide) {
|
||||||
|
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 {
|
||||||
|
if (checkOppositeSides(yLeft, yRight)) {
|
||||||
|
if (yLeft.min >= 0) {
|
||||||
|
yLeft.min = -yLeft.max;
|
||||||
|
yRight.max = -yRight.min;
|
||||||
|
} else {
|
||||||
|
yLeft.max = -yLeft.min;
|
||||||
|
yRight.min = -yRight.max;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var rate = getRate(yLeft, yRight);
|
||||||
|
|
||||||
|
if (oneSide) {
|
||||||
|
// all graphs above the Y level
|
||||||
|
if (yLeft.min > 0) {
|
||||||
|
yLeft.min = yLeft.max / rate;
|
||||||
|
yRight.min = yRight.max / rate;
|
||||||
|
} else {
|
||||||
|
yLeft.max = yLeft.min / rate;
|
||||||
|
yRight.max = yRight.min / rate;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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 {
|
||||||
|
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(yLeft, yRight, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
function expandStuckValues(yLeft, yRight) {
|
||||||
|
// wide Y min and max using increased wideFactor
|
||||||
|
var wideFactor = 0.25;
|
||||||
|
if (yLeft.max === yLeft.min) {
|
||||||
|
yLeft.min -= wideFactor;
|
||||||
|
yLeft.max += wideFactor;
|
||||||
|
}
|
||||||
|
if (yRight.max === yRight.min) {
|
||||||
|
yRight.min -= wideFactor;
|
||||||
|
yRight.max += wideFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveLevelToZero(yLeft, yRight, level) {
|
||||||
|
if (level !== 0) {
|
||||||
|
yLeft.min -= level;
|
||||||
|
yLeft.max -= level;
|
||||||
|
yRight.min -= level;
|
||||||
|
yRight.max -= level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreLevelFromZero(yLeft, yRight, level) {
|
||||||
|
if (level !== 0) {
|
||||||
|
yLeft.min += level;
|
||||||
|
yLeft.max += level;
|
||||||
|
yRight.min += level;
|
||||||
|
yRight.max += level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkTwoCross(yLeft, yRight) {
|
||||||
|
// both across zero
|
||||||
|
return yLeft.min <= 0 && yLeft.max >= 0 && yRight.min <= 0 && yRight.max >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(yLeft, yRight)) {
|
||||||
|
rateLeft = yRight.min ? yLeft.min / yRight.min : 0;
|
||||||
|
rateRight = yRight.max ? yLeft.max / yRight.max : 0;
|
||||||
|
} else {
|
||||||
|
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]);
|
||||||
|
var downRight = _.min([absRightMin, absRightMax]);
|
||||||
|
|
||||||
|
rateLeft = downLeft ? upLeft / downLeft : upLeft;
|
||||||
|
rateRight = downRight ? upRight / downRight : upRight;
|
||||||
|
} else {
|
||||||
|
if (yLeft.min > 0 || yRight.min > 0) {
|
||||||
|
rateLeft = yLeft.max / yRight.max;
|
||||||
|
rateRight = 0;
|
||||||
|
} else {
|
||||||
|
rateLeft = 0;
|
||||||
|
rateRight = yLeft.min / yRight.min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rate = rateLeft > rateRight ? rateLeft : rateRight;
|
||||||
|
|
||||||
|
return rate;
|
||||||
|
}
|
@ -11,6 +11,7 @@
|
|||||||
<label class="gf-form-label width-6">Unit</label>
|
<label class="gf-form-label width-6">Unit</label>
|
||||||
<div class="gf-form-dropdown-typeahead max-width-20" ng-model="yaxis.format" dropdown-typeahead2="ctrl.unitFormats" dropdown-typeahead-on-select="ctrl.setUnitFormat(yaxis, $subItem)"></div>
|
<div class="gf-form-dropdown-typeahead max-width-20" ng-model="yaxis.format" dropdown-typeahead2="ctrl.unitFormats" dropdown-typeahead-on-select="ctrl.setUnitFormat(yaxis, $subItem)"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-6">Scale</label>
|
<label class="gf-form-label width-6">Scale</label>
|
||||||
@ -28,8 +29,10 @@
|
|||||||
<label class="gf-form-label width-6">Y-Max</label>
|
<label class="gf-form-label width-6">Y-Max</label>
|
||||||
<input type="text" class="gf-form-input width-5" placeholder="auto" empty-to-null ng-model="yaxis.max" ng-change="ctrl.render()" ng-model-onblur>
|
<input type="text" class="gf-form-input width-5" placeholder="auto" empty-to-null ng-model="yaxis.max" ng-change="ctrl.render()" ng-model-onblur>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
|
||||||
|
<div ng-if="yaxis.show">
|
||||||
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-6">Decimals</label>
|
<label class="gf-form-label width-6">Decimals</label>
|
||||||
<input type="number" class="gf-form-input max-width-20" placeholder="auto" empty-to-null bs-tooltip="'Override automatic decimal precision for y-axis'" data-placement="right" ng-model="yaxis.decimals" ng-change="ctrl.render()" ng-model-onblur>
|
<input type="number" class="gf-form-input max-width-20" placeholder="auto" empty-to-null bs-tooltip="'Override automatic decimal precision for y-axis'" data-placement="right" ng-model="yaxis.decimals" ng-change="ctrl.render()" ng-model-onblur>
|
||||||
</div>
|
</div>
|
||||||
@ -64,6 +67,18 @@
|
|||||||
<input type="number" class="gf-form-input max-width-8" ng-model="ctrl.panel.xaxis.buckets" placeholder="auto" ng-change="ctrl.render()" ng-model-onblur bs-tooltip="'Number of buckets'" data-placement="right">
|
<input type="number" class="gf-form-input max-width-8" ng-model="ctrl.panel.xaxis.buckets" placeholder="auto" ng-change="ctrl.render()" ng-model-onblur bs-tooltip="'Number of buckets'" data-placement="right">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<br/>
|
||||||
|
<h5 class="section-heading">Y-Axes</h5>
|
||||||
|
<gf-form-switch class="gf-form" label="Align" tooltip="Align left and right Y-axes" label-class="width-6" switch-class="width-5" checked="ctrl.panel.yaxis.align" on-change="ctrl.render()"></gf-form-switch>
|
||||||
|
<div class="gf-form" ng-show="ctrl.panel.yaxis.align">
|
||||||
|
<label class="gf-form-label width-6">
|
||||||
|
Level
|
||||||
|
</label>
|
||||||
|
<input type="number" class="gf-form-input width-5" placeholder="0" ng-model="ctrl.panel.yaxis.alignLevel" ng-change="ctrl.render()" ng-model-onblur bs-tooltip="'Alignment of Y-axes are based on this value, starting from Y=0'" data-placement="right">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,6 +18,7 @@ import GraphTooltip from './graph_tooltip';
|
|||||||
import { ThresholdManager } from './threshold_manager';
|
import { ThresholdManager } from './threshold_manager';
|
||||||
import { EventManager } from 'app/features/annotations/all';
|
import { EventManager } from 'app/features/annotations/all';
|
||||||
import { convertToHistogramData } from './histogram';
|
import { convertToHistogramData } from './histogram';
|
||||||
|
import { alignYLevel } from './align_yaxes';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
/** @ngInject **/
|
/** @ngInject **/
|
||||||
@ -155,6 +156,16 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function processRangeHook(plot) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Series could have different timeSteps,
|
// Series could have different timeSteps,
|
||||||
// let's find the smallest one so that bars are correctly rendered.
|
// let's find the smallest one so that bars are correctly rendered.
|
||||||
// In addition, only take series which are rendered as bars for this.
|
// In addition, only take series which are rendered as bars for this.
|
||||||
@ -294,6 +305,7 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) {
|
|||||||
hooks: {
|
hooks: {
|
||||||
draw: [drawHook],
|
draw: [drawHook],
|
||||||
processOffset: [processOffsetHook],
|
processOffset: [processOffsetHook],
|
||||||
|
processRange: [processRangeHook],
|
||||||
},
|
},
|
||||||
legend: { show: false },
|
legend: { show: false },
|
||||||
series: {
|
series: {
|
||||||
|
@ -55,6 +55,10 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
values: [],
|
values: [],
|
||||||
buckets: null,
|
buckets: null,
|
||||||
},
|
},
|
||||||
|
yaxis: {
|
||||||
|
align: false,
|
||||||
|
alignLevel: null,
|
||||||
|
},
|
||||||
// show/hide lines
|
// show/hide lines
|
||||||
lines: true,
|
lines: true,
|
||||||
// fill factor
|
// fill factor
|
||||||
|
210
public/app/plugins/panel/graph/specs/align_yaxes.jest.ts
Normal file
210
public/app/plugins/panel/graph/specs/align_yaxes.jest.ts
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('on level not number value', () => {
|
||||||
|
it('Should ignore without errors', () => {
|
||||||
|
yaxes = [{ min: 5, max: 10 }, { min: 2, max: 4 }];
|
||||||
|
expected = [{ min: 5, max: 10 }, { min: 2, max: 4 }];
|
||||||
|
|
||||||
|
alignYLevel(yaxes, 'q');
|
||||||
|
expect(yaxes).toMatchObject(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
40
public/vendor/flot/jquery.flot.js
vendored
40
public/vendor/flot/jquery.flot.js
vendored
@ -632,6 +632,7 @@ Licensed under the MIT license.
|
|||||||
processRawData: [],
|
processRawData: [],
|
||||||
processDatapoints: [],
|
processDatapoints: [],
|
||||||
processOffset: [],
|
processOffset: [],
|
||||||
|
processRange: [],
|
||||||
drawBackground: [],
|
drawBackground: [],
|
||||||
drawSeries: [],
|
drawSeries: [],
|
||||||
draw: [],
|
draw: [],
|
||||||
@ -1613,20 +1614,32 @@ Licensed under the MIT license.
|
|||||||
setRange(axis);
|
setRange(axis);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
executeHooks(hooks.processRange, []);
|
||||||
|
|
||||||
if (showGrid) {
|
if (showGrid) {
|
||||||
|
|
||||||
var allocatedAxes = $.grep(axes, function (axis) {
|
var allocatedAxes = $.grep(axes, function (axis) {
|
||||||
return axis.show || axis.reserveSpace;
|
return axis.show || axis.reserveSpace;
|
||||||
});
|
});
|
||||||
|
|
||||||
$.each(allocatedAxes, function (_, axis) {
|
var snaped = false;
|
||||||
// make the ticks
|
for (var i = 0; i < 2; i++) {
|
||||||
setupTickGeneration(axis);
|
$.each(allocatedAxes, function (_, axis) {
|
||||||
setTicks(axis);
|
// make the ticks
|
||||||
snapRangeToTicks(axis, axis.ticks);
|
setupTickGeneration(axis);
|
||||||
// find labelWidth/Height for axis
|
setTicks(axis);
|
||||||
measureTickLabels(axis);
|
snaped = snapRangeToTicks(axis, axis.ticks) || snaped;
|
||||||
});
|
// find labelWidth/Height for axis
|
||||||
|
measureTickLabels(axis);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (snaped && hooks.processRange.length > 0) {
|
||||||
|
executeHooks(hooks.processRange, []);
|
||||||
|
snaped = false;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// with all dimensions calculated, we can compute the
|
// with all dimensions calculated, we can compute the
|
||||||
// axis bounding boxes, start from the outside
|
// axis bounding boxes, start from the outside
|
||||||
@ -1643,6 +1656,7 @@ Licensed under the MIT license.
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
plotWidth = surface.width - plotOffset.left - plotOffset.right;
|
plotWidth = surface.width - plotOffset.left - plotOffset.right;
|
||||||
plotHeight = surface.height - plotOffset.bottom - plotOffset.top;
|
plotHeight = surface.height - plotOffset.bottom - plotOffset.top;
|
||||||
|
|
||||||
@ -1876,13 +1890,19 @@ Licensed under the MIT license.
|
|||||||
}
|
}
|
||||||
|
|
||||||
function snapRangeToTicks(axis, ticks) {
|
function snapRangeToTicks(axis, ticks) {
|
||||||
|
var changed = false;
|
||||||
if (axis.options.autoscaleMargin && ticks.length > 0) {
|
if (axis.options.autoscaleMargin && ticks.length > 0) {
|
||||||
// snap to ticks
|
// snap to ticks
|
||||||
if (axis.options.min == null)
|
if (axis.options.min == null) {
|
||||||
axis.min = Math.min(axis.min, ticks[0].v);
|
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);
|
axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
|
Loading…
Reference in New Issue
Block a user