mirror of
https://github.com/grafana/grafana.git
synced 2024-12-01 04:59:15 -06:00
1a0c1a39e4
* added moment timezone package. * added a qnd way of selecting timezone. * added a first draft to display how it can be used. * fixed failing tests. * made moment.local to be in utc when running tests. * added tests to verify that the timeZone support works as expected. * Fixed so we use the formatter in the graph context menu. * changed so we will format d3 according to timeZone. * changed from class base to function based for easier consumption. * fixed so tests got green. * renamed to make it shorter. * fixed formatting in logRow. * removed unused value. * added time formatter to flot. * fixed failing tests. * changed so history will use the formatting with support for timezone. * added todo. * added so we append the correct abbrivation behind time. * added time zone abbrevation in timepicker. * adding timezone in rangeutil tool. * will use timezone when formatting range. * changed so we use new functions to format date so timezone is respected. * wip - dashboard settings. * changed so the time picker settings is in react. * added force update. * wip to get the react graph to work. * fixed formatting and parsing on the timepicker. * updated snap to be correct. * fixed so we format values properly in time picker. * make sure we pass timezone on all the proper places. * fixed so we use correct timeZone in explore. * fixed failing tests. * fixed so we always parse from local to selected timezone. * removed unused variable. * reverted back. * trying to fix issue with directive. * fixed issue. * fixed strict null errors. * fixed so we still can select default. * make sure we reads the time zone from getTimezone
215 lines
5.4 KiB
TypeScript
215 lines
5.4 KiB
TypeScript
/**
|
|
* Calculate tick step.
|
|
* Implementation from d3-array (ticks.js)
|
|
* https://github.com/d3/d3-array/blob/master/src/ticks.js
|
|
* @param start Start value
|
|
* @param stop End value
|
|
* @param count Ticks count
|
|
*/
|
|
export function tickStep(start: number, stop: number, count: number): number {
|
|
const e10 = Math.sqrt(50),
|
|
e5 = Math.sqrt(10),
|
|
e2 = Math.sqrt(2);
|
|
|
|
const step0 = Math.abs(stop - start) / Math.max(0, count);
|
|
let step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10));
|
|
const error = step0 / step1;
|
|
|
|
if (error >= e10) {
|
|
step1 *= 10;
|
|
} else if (error >= e5) {
|
|
step1 *= 5;
|
|
} else if (error >= e2) {
|
|
step1 *= 2;
|
|
}
|
|
|
|
return stop < start ? -step1 : step1;
|
|
}
|
|
|
|
export function getScaledDecimals(decimals: number, tickSize: number) {
|
|
return decimals - Math.floor(Math.log(tickSize) / Math.LN10);
|
|
}
|
|
|
|
/**
|
|
* Calculate tick size based on min and max values, number of ticks and precision.
|
|
* Implementation from Flot.
|
|
* @param min Axis minimum
|
|
* @param max Axis maximum
|
|
* @param noTicks Number of ticks
|
|
* @param tickDecimals Tick decimal precision
|
|
*/
|
|
export function getFlotTickSize(min: number, max: number, noTicks: number, tickDecimals: number) {
|
|
const delta = (max - min) / noTicks;
|
|
let dec = -Math.floor(Math.log(delta) / Math.LN10);
|
|
const maxDec = tickDecimals;
|
|
|
|
const magn = Math.pow(10, -dec);
|
|
const norm = delta / magn; // norm is between 1.0 and 10.0
|
|
let size;
|
|
|
|
if (norm < 1.5) {
|
|
size = 1;
|
|
} else if (norm < 3) {
|
|
size = 2;
|
|
// special case for 2.5, requires an extra decimal
|
|
if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
|
|
size = 2.5;
|
|
++dec;
|
|
}
|
|
} else if (norm < 7.5) {
|
|
size = 5;
|
|
} else {
|
|
size = 10;
|
|
}
|
|
|
|
size *= magn;
|
|
|
|
return size;
|
|
}
|
|
|
|
/**
|
|
* Calculate axis range (min and max).
|
|
* Implementation from Flot.
|
|
*/
|
|
export function getFlotRange(panelMin: any, panelMax: any, datamin: number, datamax: number) {
|
|
const autoscaleMargin = 0.02;
|
|
|
|
let min = +(panelMin != null ? panelMin : datamin);
|
|
let max = +(panelMax != null ? panelMax : datamax);
|
|
const delta = max - min;
|
|
|
|
if (delta === 0.0) {
|
|
// Grafana fix: wide Y min and max using increased wideFactor
|
|
// when all series values are the same
|
|
const wideFactor = 0.25;
|
|
const widen = Math.abs(max === 0 ? 1 : max * wideFactor);
|
|
|
|
if (panelMin === null) {
|
|
min -= widen;
|
|
}
|
|
// always widen max if we couldn't widen min to ensure we
|
|
// don't fall into min == max which doesn't work
|
|
if (panelMax == null || panelMin != null) {
|
|
max += widen;
|
|
}
|
|
} else {
|
|
// consider autoscaling
|
|
const margin = autoscaleMargin;
|
|
if (margin != null) {
|
|
if (panelMin == null) {
|
|
min -= delta * margin;
|
|
// make sure we don't go below zero if all values
|
|
// are positive
|
|
if (min < 0 && datamin != null && datamin >= 0) {
|
|
min = 0;
|
|
}
|
|
}
|
|
if (panelMax == null) {
|
|
max += delta * margin;
|
|
if (max > 0 && datamax != null && datamax <= 0) {
|
|
max = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return { min, max };
|
|
}
|
|
|
|
/**
|
|
* Calculate tick decimals.
|
|
* Implementation from Flot.
|
|
*/
|
|
export function getFlotTickDecimals(datamin: number, datamax: number, axis: { min: any; max: any }, height: number) {
|
|
const { min, max } = getFlotRange(axis.min, axis.max, datamin, datamax);
|
|
const noTicks = 0.3 * Math.sqrt(height);
|
|
const delta = (max - min) / noTicks;
|
|
const dec = -Math.floor(Math.log(delta) / Math.LN10);
|
|
|
|
const magn = Math.pow(10, -dec);
|
|
// norm is between 1.0 and 10.0
|
|
const norm = delta / magn;
|
|
let size;
|
|
|
|
if (norm < 1.5) {
|
|
size = 1;
|
|
} else if (norm < 3) {
|
|
size = 2;
|
|
// special case for 2.5, requires an extra decimal
|
|
if (norm > 2.25) {
|
|
size = 2.5;
|
|
}
|
|
} else if (norm < 7.5) {
|
|
size = 5;
|
|
} else {
|
|
size = 10;
|
|
}
|
|
size *= magn;
|
|
|
|
const tickDecimals = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1);
|
|
// grafana addition
|
|
const scaledDecimals = tickDecimals - Math.floor(Math.log(size) / Math.LN10);
|
|
return { tickDecimals, scaledDecimals };
|
|
}
|
|
|
|
/**
|
|
* Format timestamp similar to Grafana graph panel.
|
|
* @param ticks Number of ticks
|
|
* @param min Time from (in milliseconds)
|
|
* @param max Time to (in milliseconds)
|
|
*/
|
|
export function grafanaTimeFormat(ticks: number, min: number, max: number) {
|
|
if (min && max && ticks) {
|
|
const range = max - min;
|
|
const secPerTick = range / ticks / 1000;
|
|
const oneDay = 86400000;
|
|
const oneYear = 31536000000;
|
|
|
|
if (secPerTick <= 45) {
|
|
return 'HH:mm:ss';
|
|
}
|
|
if (secPerTick <= 7200 || range <= oneDay) {
|
|
return 'HH:mm';
|
|
}
|
|
if (secPerTick <= 80000) {
|
|
return 'MM/DD HH:mm';
|
|
}
|
|
if (secPerTick <= 2419200 || range <= oneYear) {
|
|
return 'MM/DD';
|
|
}
|
|
return 'YYYY-MM';
|
|
}
|
|
|
|
return 'HH:mm';
|
|
}
|
|
|
|
/**
|
|
* Logarithm of value for arbitrary base.
|
|
*/
|
|
export function logp(value: number, base: number) {
|
|
return Math.log(value) / Math.log(base);
|
|
}
|
|
|
|
/**
|
|
* Get decimal precision of number (3.14 => 2)
|
|
*/
|
|
export function getPrecision(num: number): number {
|
|
const str = num.toString();
|
|
return getStringPrecision(str);
|
|
}
|
|
|
|
/**
|
|
* Get decimal precision of number stored as a string ("3.14" => 2)
|
|
*/
|
|
export function getStringPrecision(num: string): number {
|
|
if (isNaN((num as unknown) as number)) {
|
|
return 0;
|
|
}
|
|
|
|
const dotIndex = num.indexOf('.');
|
|
if (dotIndex === -1) {
|
|
return 0;
|
|
} else {
|
|
return num.length - dotIndex - 1;
|
|
}
|
|
}
|