@grafana/ui
Version:
Grafana Components Library
1 lines • 19.8 kB
Source Map (JSON)
{"version":3,"file":"utils.mjs","sources":["../../../../src/components/uPlot/utils.ts"],"sourcesContent":["import uPlot, { AlignedData, Options, PaddingSide } from 'uplot';\n\nimport {\n DataFrame,\n DisplayProcessor,\n DisplayValue,\n Field,\n fieldReducers,\n getDisplayProcessor,\n GrafanaTheme2,\n reduceField,\n ReducerID,\n} from '@grafana/data';\nimport { BarAlignment, GraphDrawStyle, GraphTransform, LineInterpolation, StackingMode } from '@grafana/schema';\n\nimport { attachDebugger } from '../../utils/debug';\nimport { createLogger } from '../../utils/logger';\n\nimport { buildScaleKey } from './internal';\n\nconst paddingSide: PaddingSide = (u, side, sidesWithAxes) => {\n let hasCrossAxis = side % 2 ? sidesWithAxes[0] || sidesWithAxes[2] : sidesWithAxes[1] || sidesWithAxes[3];\n\n return sidesWithAxes[side] || !hasCrossAxis ? 0 : 8;\n};\n\nexport const DEFAULT_PLOT_CONFIG: Partial<Options> = {\n ms: 1,\n focus: {\n alpha: 1,\n },\n cursor: {\n focus: {\n prox: 30,\n },\n },\n legend: {\n show: false,\n },\n padding: [paddingSide, paddingSide, paddingSide, paddingSide],\n series: [],\n hooks: {},\n};\n\n/** @internal */\ninterface StackMeta {\n totals: AlignedData;\n}\n\n/** @internal */\nexport interface StackingGroup {\n series: number[];\n dir: StackDirection;\n}\n\n/** @internal */\nconst enum StackDirection {\n Pos = 1,\n Neg = -1,\n}\n\n// generates bands between adjacent group series\n/** @internal */\nexport function getStackingBands(group: StackingGroup) {\n let bands: uPlot.Band[] = [];\n let { series, dir } = group;\n let lastIdx = series.length - 1;\n\n let rSeries = series.slice().reverse();\n\n rSeries.forEach((si, i) => {\n if (i !== lastIdx) {\n let nextIdx = rSeries[i + 1];\n bands.push({\n series: [si, nextIdx],\n // fill direction is inverted from stack direction\n dir: (-1 * dir) as 1 | -1,\n });\n }\n });\n\n return bands;\n}\n\n// expects an AlignedFrame\n/** @internal */\nexport function getStackingGroups(frame: DataFrame) {\n let groups: Map<string, StackingGroup> = new Map();\n\n frame.fields.forEach(({ config, values, type }, i) => {\n // skip x or time field\n if (i === 0) {\n return;\n }\n\n let { custom } = config;\n\n if (custom == null) {\n return;\n }\n\n // TODO: currently all AlignedFrame fields end up in uplot series & data, even custom.hideFrom?.viz\n // ideally hideFrom.viz fields would be excluded so we can remove this\n if (custom.hideFrom?.viz) {\n return;\n }\n\n let { stacking } = custom;\n\n if (stacking == null) {\n return;\n }\n\n let { mode: stackingMode, group: stackingGroup } = stacking;\n\n // not stacking\n if (stackingMode === StackingMode.None) {\n return;\n }\n\n // will this be stacked up or down after any transforms applied\n let transform = custom.transform;\n let stackDir = getStackDirection(transform, values);\n\n let drawStyle: GraphDrawStyle = custom.drawStyle;\n let drawStyle2: BarAlignment | LineInterpolation | null =\n drawStyle === GraphDrawStyle.Bars\n ? custom.barAlignment\n : drawStyle === GraphDrawStyle.Line\n ? custom.lineInterpolation\n : null;\n\n let stackKey = `${stackDir}|${stackingMode}|${stackingGroup}|${buildScaleKey(\n config,\n type\n )}|${drawStyle}|${drawStyle2}`;\n\n let group = groups.get(stackKey);\n\n if (group == null) {\n group = {\n series: [],\n dir: stackDir,\n };\n\n groups.set(stackKey, group);\n }\n\n group.series.push(i);\n });\n\n return [...groups.values()];\n}\n\n/** @internal */\nexport function preparePlotData2(\n frame: DataFrame,\n stackingGroups: StackingGroup[],\n onStackMeta?: (meta: StackMeta) => void\n): AlignedData {\n let data = Array(frame.fields.length);\n\n let stacksQty = stackingGroups.length;\n\n let dataLen = frame.length;\n let zeroArr = stacksQty > 0 ? Array(dataLen).fill(0) : [];\n let falseArr = stacksQty > 0 ? Array(dataLen).fill(false) : [];\n let accums = Array.from({ length: stacksQty }, () => zeroArr.slice());\n\n let anyValsAtX = Array.from({ length: stacksQty }, () => falseArr.slice());\n\n // figure out at which time indices each stacking group has any values\n // (needed to avoid absorbing initial accum 0s at unrelated joined timestamps)\n stackingGroups.forEach((group, groupIdx) => {\n let groupValsAtX = anyValsAtX[groupIdx];\n\n group.series.forEach((seriesIdx) => {\n let field = frame.fields[seriesIdx];\n\n if (field.config.custom?.hideFrom?.viz) {\n return;\n }\n\n let vals = field.values;\n\n for (let i = 0; i < dataLen; i++) {\n if (vals[i] != null) {\n groupValsAtX[i] = true;\n }\n }\n });\n });\n\n frame.fields.forEach((field, i) => {\n let vals = field.values;\n\n if (i === 0) {\n data[i] = vals;\n return;\n }\n\n let { custom } = field.config;\n\n if (!custom || custom.hideFrom?.viz) {\n data[i] = vals;\n return;\n }\n\n // apply transforms\n if (custom.transform === GraphTransform.Constant) {\n let firstValIdx = vals.findIndex((v) => v != null);\n let firstVal = vals[firstValIdx];\n vals = Array(vals.length).fill(undefined);\n vals[firstValIdx] = firstVal;\n } else {\n vals = vals.slice();\n\n if (custom.transform === GraphTransform.NegativeY) {\n for (let i = 0; i < vals.length; i++) {\n if (vals[i] != null) {\n vals[i] *= -1;\n }\n }\n }\n }\n\n let stackingMode = custom.stacking?.mode;\n\n if (!stackingMode || stackingMode === StackingMode.None) {\n data[i] = vals;\n } else {\n let stackIdx = stackingGroups.findIndex((group) => group.series.indexOf(i) > -1);\n\n let accum = accums[stackIdx];\n let groupValsAtX = anyValsAtX[stackIdx];\n let stacked = (data[i] = Array(dataLen));\n\n for (let i = 0; i < dataLen; i++) {\n let v = vals[i];\n\n if (v != null) {\n stacked[i] = accum[i] += v;\n } else {\n stacked[i] = groupValsAtX[i] ? accum[i] : v;\n }\n }\n }\n });\n\n if (onStackMeta) {\n let accumsBySeriesIdx = data.map((vals, i) => {\n let stackIdx = stackingGroups.findIndex((group) => group.series.indexOf(i) > -1);\n return stackIdx !== -1 ? accums[stackIdx] : vals;\n });\n\n onStackMeta({\n totals: accumsBySeriesIdx,\n });\n }\n\n // re-compute by percent\n frame.fields.forEach((field, i) => {\n if (i === 0 || field.config.custom?.hideFrom?.viz) {\n return;\n }\n\n let stackingMode = field.config.custom?.stacking?.mode;\n\n if (stackingMode === StackingMode.Percent) {\n let stackIdx = stackingGroups.findIndex((group) => group.series.indexOf(i) > -1);\n let accum = accums[stackIdx];\n let group = stackingGroups[stackIdx];\n\n let stacked = data[i];\n\n for (let i = 0; i < dataLen; i++) {\n let v = stacked[i];\n\n if (v != null) {\n // v / accum will always be pos, so properly (re)sign by group stacking dir\n stacked[i] = accum[i] === 0 ? 0 : group.dir * (v / accum[i]);\n }\n }\n }\n });\n\n return data;\n}\n\n/**\n * Finds y axis midpoint for point at given idx (css pixels relative to uPlot canvas)\n * @internal\n **/\n\nexport function findMidPointYPosition(u: uPlot, idx: number) {\n let y;\n let sMaxIdx = 1;\n let sMinIdx = 1;\n // assume min/max being values of 1st series\n let max = u.data[1][idx];\n let min = u.data[1][idx];\n\n // find min max values AND ids of the corresponding series to get the scales\n for (let i = 1; i < u.data.length; i++) {\n const sData = u.data[i];\n const sVal = sData[idx];\n if (sVal != null) {\n if (max == null) {\n max = sVal;\n } else {\n if (sVal > max) {\n max = u.data[i][idx];\n sMaxIdx = i;\n }\n }\n if (min == null) {\n min = sVal;\n } else {\n if (sVal < min) {\n min = u.data[i][idx];\n sMinIdx = i;\n }\n }\n }\n }\n\n if (min == null && max == null) {\n // no tooltip to show\n y = undefined;\n } else if (min != null && max != null) {\n // find median position\n y = (u.valToPos(min, u.series[sMinIdx].scale!) + u.valToPos(max, u.series[sMaxIdx].scale!)) / 2;\n } else {\n // snap tooltip to min OR max point, one of those is not null :)\n y = u.valToPos((min || max)!, u.series[(sMaxIdx || sMinIdx)!].scale!);\n }\n\n // if y is out of canvas bounds, snap it to the bottom\n if (y !== undefined && y < 0) {\n y = u.bbox.height / devicePixelRatio;\n }\n\n return y;\n}\n\nfunction getStackDirection(transform: GraphTransform, data: unknown[]) {\n const hasNegSamp = hasNegSample(data);\n\n if (transform === GraphTransform.NegativeY) {\n return hasNegSamp ? StackDirection.Pos : StackDirection.Neg;\n }\n return hasNegSamp ? StackDirection.Neg : StackDirection.Pos;\n}\n\n// similar to isLikelyAscendingVector()\nfunction hasNegSample(data: unknown[], samples = 100) {\n const len = data.length;\n\n if (len === 0) {\n return false;\n }\n\n // skip leading & trailing nullish\n let firstIdx = 0;\n let lastIdx = len - 1;\n\n while (firstIdx <= lastIdx && data[firstIdx] == null) {\n firstIdx++;\n }\n\n while (lastIdx >= firstIdx && data[lastIdx] == null) {\n lastIdx--;\n }\n\n let negCount = 0;\n let posCount = 0;\n\n if (lastIdx >= firstIdx) {\n const stride = Math.max(1, Math.floor((lastIdx - firstIdx + 1) / samples));\n\n for (let i = firstIdx; i <= lastIdx; i += stride) {\n const v = data[i];\n\n if (v != null && typeof v === 'number') {\n if (v < 0 || Object.is(v, -0)) {\n negCount++;\n } else if (v > 0) {\n posCount++;\n }\n }\n }\n\n if (negCount > posCount) {\n return true;\n }\n }\n\n return false;\n}\n\nexport const getDisplayValuesForCalcs = (calcs: string[], field: Field, theme: GrafanaTheme2) => {\n if (!calcs?.length) {\n return [];\n }\n\n const defaultFormatter = (v: any) => (v == null ? '-' : v.toFixed(1));\n const fmt = field.display ?? defaultFormatter;\n let countFormatter: DisplayProcessor | null = null;\n\n const fieldCalcs = reduceField({\n field: field,\n reducers: calcs,\n });\n\n return calcs.map<DisplayValue>((reducerId) => {\n const fieldReducer = fieldReducers.get(reducerId);\n let formatter = fmt;\n\n if (fieldReducer.id === ReducerID.diffperc) {\n formatter = getDisplayProcessor({\n field: {\n ...field,\n config: {\n ...field.config,\n unit: 'percent',\n },\n },\n theme,\n });\n }\n\n if (\n fieldReducer.id === ReducerID.count ||\n fieldReducer.id === ReducerID.changeCount ||\n fieldReducer.id === ReducerID.distinctCount\n ) {\n if (!countFormatter) {\n countFormatter = getDisplayProcessor({\n field: {\n ...field,\n config: {\n ...field.config,\n unit: 'none',\n },\n },\n theme,\n });\n }\n formatter = countFormatter;\n }\n\n return {\n ...formatter(fieldCalcs[reducerId]),\n title: fieldReducer.name,\n description: fieldReducer.description,\n };\n });\n};\n\n// Dev helpers\n\n/** @internal */\nexport const pluginLogger = createLogger('uPlot');\nexport const pluginLog = pluginLogger.logger;\n// pluginLogger.enable();\nattachDebugger('graphng', undefined, pluginLogger);\n"],"names":["i","group"],"mappings":"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"}