From 7ee7dfda2bfc21a025391c889ce5f3ff9cc51867 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Mon, 24 Jan 2022 01:49:47 -0800 Subject: [PATCH] Stacking: Ignore null/undefined-only stacks instead of assuming 0 value (#44359) --- .../src/components/uPlot/utils.test.ts | 218 ++++++++++++++---- .../grafana-ui/src/components/uPlot/utils.ts | 7 +- 2 files changed, 177 insertions(+), 48 deletions(-) diff --git a/packages/grafana-ui/src/components/uPlot/utils.test.ts b/packages/grafana-ui/src/components/uPlot/utils.test.ts index 3897377bba5..47060f9ddc0 100644 --- a/packages/grafana-ui/src/components/uPlot/utils.test.ts +++ b/packages/grafana-ui/src/components/uPlot/utils.test.ts @@ -296,6 +296,132 @@ describe('preparePlotData', () => { `); }); + describe('ignores nullish-only stacks', () => { + test('single stacking group', () => { + const df = new MutableDataFrame({ + fields: [ + { name: 'time', type: FieldType.time, values: [9997, 9998, 9999] }, + { + name: 'a', + values: [-10, null, 10], + config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' } } }, + }, + { + name: 'b', + values: [10, null, null], + config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' } } }, + }, + { + name: 'c', + values: [20, undefined, 20], + config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' } } }, + }, + ], + }); + + expect(preparePlotData([df])).toMatchInlineSnapshot(` + Array [ + Array [ + 9997, + 9998, + 9999, + ], + Array [ + -10, + null, + 10, + ], + Array [ + 0, + null, + 10, + ], + Array [ + 20, + null, + 30, + ], + ] + `); + }); + test('multiple stacking groups', () => { + const df = new MutableDataFrame({ + fields: [ + { name: 'time', type: FieldType.time, values: [9997, 9998, 9999] }, + { + name: 'a', + values: [-10, undefined, 10], + config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' } } }, + }, + { + name: 'b', + values: [10, undefined, 10], + config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' } } }, + }, + { + name: 'c', + values: [20, undefined, 20], + config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' } } }, + }, + { + name: 'd', + values: [1, 2, null], + config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackB' } } }, + }, + { + name: 'e', + values: [1, 2, null], + config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackB' } } }, + }, + { + name: 'f', + values: [1, 2, null], + config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackB' } } }, + }, + ], + }); + + expect(preparePlotData([df])).toMatchInlineSnapshot(` + Array [ + Array [ + 9997, + 9998, + 9999, + ], + Array [ + -10, + null, + 10, + ], + Array [ + 0, + null, + 20, + ], + Array [ + 20, + null, + 40, + ], + Array [ + 1, + 2, + null, + ], + Array [ + 2, + 4, + null, + ], + Array [ + 3, + 6, + null, + ], + ] + `); + }); + }); describe('with legend sorted', () => { it('should affect when single group', () => { const df = new MutableDataFrame({ @@ -323,53 +449,53 @@ describe('preparePlotData', () => { }); expect(preparePlotData([df], undefined, { sortBy: 'Max', sortDesc: false } as any)).toMatchInlineSnapshot(` - Array [ - Array [ - 9997, - 9998, - 9999, - ], - Array [ - 0, - 30, - 20, - ], - Array [ - 10, - 10, - 10, - ], - Array [ - 20, - 50, - 40, - ], - ] - `); + Array [ + Array [ + 9997, + 9998, + 9999, + ], + Array [ + 0, + 30, + 20, + ], + Array [ + 10, + 10, + 10, + ], + Array [ + 20, + 50, + 40, + ], + ] + `); expect(preparePlotData([df], undefined, { sortBy: 'Max', sortDesc: true } as any)).toMatchInlineSnapshot(` - Array [ - Array [ - 9997, - 9998, - 9999, - ], - Array [ - -10, - 20, - 10, - ], - Array [ - 20, - 50, - 40, - ], - Array [ - 10, - 40, - 30, - ], - ] - `); + Array [ + Array [ + 9997, + 9998, + 9999, + ], + Array [ + -10, + 20, + 10, + ], + Array [ + 20, + 50, + 40, + ], + Array [ + 10, + 40, + 30, + ], + ] + `); }); }); }); diff --git a/packages/grafana-ui/src/components/uPlot/utils.ts b/packages/grafana-ui/src/components/uPlot/utils.ts index 426d14b024a..0a0288ddade 100755 --- a/packages/grafana-ui/src/components/uPlot/utils.ts +++ b/packages/grafana-ui/src/components/uPlot/utils.ts @@ -74,7 +74,7 @@ export function preparePlotData( // array or stacking groups for (const [_, seriesIds] of stackingGroups.entries()) { const seriesIdxs = orderIdsByCalcs({ ids: seriesIds, legend, frame }); - + const noValueStack = Array(dataLength).fill(true); const groupTotals = byPct ? Array(dataLength).fill(0) : null; if (byPct) { @@ -99,10 +99,13 @@ export function preparePlotData( for (let k = 0; k < dataLength; k++) { const v = currentlyStacking[k]; + if (v != null && noValueStack[k]) { + noValueStack[k] = false; + } acc[k] += v == null ? 0 : v / (byPct ? groupTotals![k] : 1); } - result[seriesIdx] = acc.slice(); + result[seriesIdx] = acc.slice().map((v, i) => (noValueStack[i] ? null : v)); } }