@grafana/ui
Version:
Grafana Components Library
327 lines (324 loc) • 9.77 kB
JavaScript
import { reduceField, fieldReducers, ReducerID, getDisplayProcessor } from '@grafana/data';
import { StackingMode, GraphDrawStyle, GraphTransform } from '@grafana/schema';
import { attachDebugger } from '../../utils/debug.mjs';
import { createLogger } from '../../utils/logger.mjs';
import { buildScaleKey } from './internal.mjs';
;
const paddingSide = (u, side, sidesWithAxes) => {
let hasCrossAxis = side % 2 ? sidesWithAxes[0] || sidesWithAxes[2] : sidesWithAxes[1] || sidesWithAxes[3];
return sidesWithAxes[side] || !hasCrossAxis ? 0 : 8;
};
const DEFAULT_PLOT_CONFIG = {
ms: 1,
focus: {
alpha: 1
},
cursor: {
focus: {
prox: 30
}
},
legend: {
show: false
},
padding: [paddingSide, paddingSide, paddingSide, paddingSide],
series: [],
hooks: {}
};
var StackDirection = /* @__PURE__ */ ((StackDirection2) => {
StackDirection2[StackDirection2["Pos"] = 1] = "Pos";
StackDirection2[StackDirection2["Neg"] = -1] = "Neg";
return StackDirection2;
})(StackDirection || {});
function getStackingBands(group) {
let bands = [];
let { series, dir } = group;
let lastIdx = series.length - 1;
let rSeries = series.slice().reverse();
rSeries.forEach((si, i) => {
if (i !== lastIdx) {
let nextIdx = rSeries[i + 1];
bands.push({
series: [si, nextIdx],
// fill direction is inverted from stack direction
dir: -1 * dir
});
}
});
return bands;
}
function getStackingGroups(frame) {
let groups = /* @__PURE__ */ new Map();
frame.fields.forEach(({ config, values, type }, i) => {
var _a;
if (i === 0) {
return;
}
let { custom } = config;
if (custom == null) {
return;
}
if ((_a = custom.hideFrom) == null ? void 0 : _a.viz) {
return;
}
let { stacking } = custom;
if (stacking == null) {
return;
}
let { mode: stackingMode, group: stackingGroup } = stacking;
if (stackingMode === StackingMode.None) {
return;
}
let transform = custom.transform;
let stackDir = getStackDirection(transform, values);
let drawStyle = custom.drawStyle;
let drawStyle2 = drawStyle === GraphDrawStyle.Bars ? custom.barAlignment : drawStyle === GraphDrawStyle.Line ? custom.lineInterpolation : null;
let stackKey = `${stackDir}|${stackingMode}|${stackingGroup}|${buildScaleKey(
config,
type
)}|${drawStyle}|${drawStyle2}`;
let group = groups.get(stackKey);
if (group == null) {
group = {
series: [],
dir: stackDir
};
groups.set(stackKey, group);
}
group.series.push(i);
});
return [...groups.values()];
}
function preparePlotData2(frame, stackingGroups, onStackMeta) {
let data = Array(frame.fields.length);
let stacksQty = stackingGroups.length;
let dataLen = frame.length;
let zeroArr = stacksQty > 0 ? Array(dataLen).fill(0) : [];
let falseArr = stacksQty > 0 ? Array(dataLen).fill(false) : [];
let accums = Array.from({ length: stacksQty }, () => zeroArr.slice());
let anyValsAtX = Array.from({ length: stacksQty }, () => falseArr.slice());
stackingGroups.forEach((group, groupIdx) => {
let groupValsAtX = anyValsAtX[groupIdx];
group.series.forEach((seriesIdx) => {
var _a, _b;
let field = frame.fields[seriesIdx];
if ((_b = (_a = field.config.custom) == null ? void 0 : _a.hideFrom) == null ? void 0 : _b.viz) {
return;
}
let vals = field.values;
for (let i = 0; i < dataLen; i++) {
if (vals[i] != null) {
groupValsAtX[i] = true;
}
}
});
});
frame.fields.forEach((field, i) => {
var _a, _b;
let vals = field.values;
if (i === 0) {
data[i] = vals;
return;
}
let { custom } = field.config;
if (!custom || ((_a = custom.hideFrom) == null ? void 0 : _a.viz)) {
data[i] = vals;
return;
}
if (custom.transform === GraphTransform.Constant) {
let firstValIdx = vals.findIndex((v) => v != null);
let firstVal = vals[firstValIdx];
vals = Array(vals.length).fill(void 0);
vals[firstValIdx] = firstVal;
} else {
vals = vals.slice();
if (custom.transform === GraphTransform.NegativeY) {
for (let i2 = 0; i2 < vals.length; i2++) {
if (vals[i2] != null) {
vals[i2] *= -1;
}
}
}
}
let stackingMode = (_b = custom.stacking) == null ? void 0 : _b.mode;
if (!stackingMode || stackingMode === StackingMode.None) {
data[i] = vals;
} else {
let stackIdx = stackingGroups.findIndex((group) => group.series.indexOf(i) > -1);
let accum = accums[stackIdx];
let groupValsAtX = anyValsAtX[stackIdx];
let stacked = data[i] = Array(dataLen);
for (let i2 = 0; i2 < dataLen; i2++) {
let v = vals[i2];
if (v != null) {
stacked[i2] = accum[i2] += v;
} else {
stacked[i2] = groupValsAtX[i2] ? accum[i2] : v;
}
}
}
});
if (onStackMeta) {
let accumsBySeriesIdx = data.map((vals, i) => {
let stackIdx = stackingGroups.findIndex((group) => group.series.indexOf(i) > -1);
return stackIdx !== -1 ? accums[stackIdx] : vals;
});
onStackMeta({
totals: accumsBySeriesIdx
});
}
frame.fields.forEach((field, i) => {
var _a, _b, _c, _d;
if (i === 0 || ((_b = (_a = field.config.custom) == null ? void 0 : _a.hideFrom) == null ? void 0 : _b.viz)) {
return;
}
let stackingMode = (_d = (_c = field.config.custom) == null ? void 0 : _c.stacking) == null ? void 0 : _d.mode;
if (stackingMode === StackingMode.Percent) {
let stackIdx = stackingGroups.findIndex((group2) => group2.series.indexOf(i) > -1);
let accum = accums[stackIdx];
let group = stackingGroups[stackIdx];
let stacked = data[i];
for (let i2 = 0; i2 < dataLen; i2++) {
let v = stacked[i2];
if (v != null) {
stacked[i2] = accum[i2] === 0 ? 0 : group.dir * (v / accum[i2]);
}
}
}
});
return data;
}
function findMidPointYPosition(u, idx) {
let y;
let sMaxIdx = 1;
let sMinIdx = 1;
let max = u.data[1][idx];
let min = u.data[1][idx];
for (let i = 1; i < u.data.length; i++) {
const sData = u.data[i];
const sVal = sData[idx];
if (sVal != null) {
if (max == null) {
max = sVal;
} else {
if (sVal > max) {
max = u.data[i][idx];
sMaxIdx = i;
}
}
if (min == null) {
min = sVal;
} else {
if (sVal < min) {
min = u.data[i][idx];
sMinIdx = i;
}
}
}
}
if (min == null && max == null) {
y = void 0;
} else if (min != null && max != null) {
y = (u.valToPos(min, u.series[sMinIdx].scale) + u.valToPos(max, u.series[sMaxIdx].scale)) / 2;
} else {
y = u.valToPos(min || max, u.series[sMaxIdx || sMinIdx].scale);
}
if (y !== void 0 && y < 0) {
y = u.bbox.height / devicePixelRatio;
}
return y;
}
function getStackDirection(transform, data) {
const hasNegSamp = hasNegSample(data);
if (transform === GraphTransform.NegativeY) {
return hasNegSamp ? 1 /* Pos */ : -1 /* Neg */;
}
return hasNegSamp ? -1 /* Neg */ : 1 /* Pos */;
}
function hasNegSample(data, samples = 100) {
const len = data.length;
if (len === 0) {
return false;
}
let firstIdx = 0;
let lastIdx = len - 1;
while (firstIdx <= lastIdx && data[firstIdx] == null) {
firstIdx++;
}
while (lastIdx >= firstIdx && data[lastIdx] == null) {
lastIdx--;
}
let negCount = 0;
let posCount = 0;
if (lastIdx >= firstIdx) {
const stride = Math.max(1, Math.floor((lastIdx - firstIdx + 1) / samples));
for (let i = firstIdx; i <= lastIdx; i += stride) {
const v = data[i];
if (v != null && typeof v === "number") {
if (v < 0 || Object.is(v, -0)) {
negCount++;
} else if (v > 0) {
posCount++;
}
}
}
if (negCount > posCount) {
return true;
}
}
return false;
}
const getDisplayValuesForCalcs = (calcs, field, theme) => {
var _a;
if (!(calcs == null ? void 0 : calcs.length)) {
return [];
}
const defaultFormatter = (v) => v == null ? "-" : v.toFixed(1);
const fmt = (_a = field.display) != null ? _a : defaultFormatter;
let countFormatter = null;
const fieldCalcs = reduceField({
field,
reducers: calcs
});
return calcs.map((reducerId) => {
const fieldReducer = fieldReducers.get(reducerId);
let formatter = fmt;
if (fieldReducer.id === ReducerID.diffperc) {
formatter = getDisplayProcessor({
field: {
...field,
config: {
...field.config,
unit: "percent"
}
},
theme
});
}
if (fieldReducer.id === ReducerID.count || fieldReducer.id === ReducerID.changeCount || fieldReducer.id === ReducerID.distinctCount) {
if (!countFormatter) {
countFormatter = getDisplayProcessor({
field: {
...field,
config: {
...field.config,
unit: "none"
}
},
theme
});
}
formatter = countFormatter;
}
return {
...formatter(fieldCalcs[reducerId]),
title: fieldReducer.name,
description: fieldReducer.description
};
});
};
const pluginLogger = createLogger("uPlot");
const pluginLog = pluginLogger.logger;
attachDebugger("graphng", void 0, pluginLogger);
export { DEFAULT_PLOT_CONFIG, findMidPointYPosition, getDisplayValuesForCalcs, getStackingBands, getStackingGroups, pluginLog, pluginLogger, preparePlotData2 };
//# sourceMappingURL=utils.mjs.map