[Lens] improve metric palette behavior (#139596)

* handle single-value case

* match continuity between metric types

* fix collapse-by handling, polish logic

* update snapshot

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Andrew Tate 2022-08-30 08:03:22 -05:00 committed by GitHub
parent 50c0077aba
commit e11e6e6b30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 10 deletions

View file

@ -954,7 +954,7 @@ describe('MetricVisComponent', function () {
"stops": Array [],
},
Object {
"max": 28.984375,
"max": 57.96875,
"min": 0,
},
],

View file

@ -0,0 +1,71 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { Datatable, DatatableRow } from '@kbn/expressions-plugin/common';
import { getDataBoundsForPalette } from './palette_data_bounds';
describe('palette data bounds', () => {
const buildTableWithRows = (rows: DatatableRow[]) => {
const table: Datatable = {
type: 'datatable',
columns: Object.keys(rows).map((key) => ({
id: key,
name: key,
meta: { type: 'number' },
})),
rows,
};
return table;
};
describe('single value scenarios', () => {
it('creates a range with the metric value in the middle', () => {
const accessors = {
metric: 'first',
};
expect(getDataBoundsForPalette(accessors, buildTableWithRows([{ first: 100 }]))).toEqual({
min: 0,
max: 200,
});
expect(getDataBoundsForPalette(accessors, buildTableWithRows([{ first: -100 }]))).toEqual({
min: -200,
max: 0,
});
});
it('uses maximum dimension when available', () => {
expect(
getDataBoundsForPalette(
{ metric: 'metric', max: 'max' },
buildTableWithRows([{ metric: 200, max: 100 }])
)
).toEqual({ min: 0, max: 100 });
expect(
getDataBoundsForPalette(
{ metric: 'metric', max: 'max' },
buildTableWithRows([
{ metric: 200, max: 100 },
{ metric: 400, max: 150 },
]),
1
)
).toEqual({ min: 0, max: 150 });
});
});
it('uses minimum and maximum metric when breakdown but no max', () => {
expect(
getDataBoundsForPalette(
{ metric: 'metric', breakdownBy: 'breakdown' },
buildTableWithRows([{ metric: -100 }, { metric: 100 }, { metric: 200 }, { metric: 300 }])
)
).toEqual({ min: -100, max: 300 });
});
});

View file

@ -19,6 +19,17 @@ export const getDataBoundsForPalette = (
const smallestMetric = Math.min(...data.rows.map((row) => row[accessors.metric]));
const greatestMetric = Math.max(...data.rows.map((row) => row[accessors.metric]));
if (
!accessors.max &&
!accessors.breakdownBy &&
(typeof rowNumber !== 'undefined' || data.rows.length === 1)
) {
// dealing with a single metric and no max
const metricValue = greatestMetric;
return metricValue < 0 ? { min: metricValue * 2, max: 0 } : { min: 0, max: metricValue * 2 };
}
const greatestMaximum = accessors.max
? rowNumber
? data.rows[rowNumber][accessors.max]

View file

@ -15,6 +15,7 @@ export const defaultPaletteParams: RequiredPaletteParamTypes = {
...sharedDefaultParams,
maxSteps: 5,
name: DEFAULT_PALETTE_NAME,
continuity: 'all',
rangeType: 'number',
steps: DEFAULT_COLOR_STEPS,
};

View file

@ -267,14 +267,18 @@ function PrimaryMetricEditor(props: SubProps) {
const hasDynamicColoring = Boolean(state?.palette);
const startWithPercentPalette = Boolean(state.maxAccessor || state.breakdownByAccessor);
const supportsPercentPalette = Boolean(
state.maxAccessor ||
(state.breakdownByAccessor && !state.collapseFn) ||
state?.palette?.params?.rangeType === 'percent'
);
const activePalette = state?.palette || {
type: 'palette',
name: (startWithPercentPalette ? defaultPercentagePaletteParams : defaultNumberPaletteParams)
name: (supportsPercentPalette ? defaultPercentagePaletteParams : defaultNumberPaletteParams)
.name,
params: {
...(startWithPercentPalette ? defaultPercentagePaletteParams : defaultNumberPaletteParams),
...(supportsPercentPalette ? defaultPercentagePaletteParams : defaultNumberPaletteParams),
},
};
@ -282,7 +286,8 @@ function PrimaryMetricEditor(props: SubProps) {
{
metric: state.metricAccessor!,
max: state.maxAccessor,
breakdownBy: state.breakdownByAccessor,
// if we're collapsing, pretend like there's no breakdown to match the activeData
breakdownBy: !state.collapseFn ? state.breakdownByAccessor : undefined,
},
frame.activeData?.[state.layerId]
);
@ -401,11 +406,7 @@ function PrimaryMetricEditor(props: SubProps) {
activePalette={activePalette}
dataBounds={currentMinMax}
displayInfinity={true}
showRangeTypeSelector={Boolean(
state.breakdownByAccessor ||
state.maxAccessor ||
activePalette.params?.rangeType === 'percent'
)}
showRangeTypeSelector={supportsPercentPalette}
setPalette={(newPalette) => {
setState({
...state,