fix(plugin-chart-echarts): force min y-tick for log axis with zero (#24186)

This commit is contained in:
Ville Brofeldt 2023-05-23 13:25:08 +03:00 committed by GitHub
parent a7f9c66e57
commit bc0079f2fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 20 deletions

View File

@ -53,14 +53,15 @@ import { DEFAULT_FORM_DATA } from './constants';
import { ForecastSeriesEnum, ForecastValue, Refs } from '../types'; import { ForecastSeriesEnum, ForecastValue, Refs } from '../types';
import { parseYAxisBound } from '../utils/controls'; import { parseYAxisBound } from '../utils/controls';
import { import {
calculateLowerLogTick,
currentSeries, currentSeries,
dedupSeries, dedupSeries,
extractDataTotalValues,
extractSeries, extractSeries,
extractShowValueIndexes,
getAxisType, getAxisType,
getColtypesMapping, getColtypesMapping,
getLegendProps, getLegendProps,
extractDataTotalValues,
extractShowValueIndexes,
} from '../utils/series'; } from '../utils/series';
import { import {
extractAnnotationLabels, extractAnnotationLabels,
@ -199,20 +200,23 @@ export default function transformProps(
const isMultiSeries = groupby.length || metrics.length > 1; const isMultiSeries = groupby.length || metrics.length > 1;
const [rawSeries, sortedTotalValues] = extractSeries(rebasedData, { const [rawSeries, sortedTotalValues, minPositiveValue] = extractSeries(
fillNeighborValue: stack && !forecastEnabled ? 0 : undefined, rebasedData,
xAxis: xAxisLabel, {
extraMetricLabels, fillNeighborValue: stack && !forecastEnabled ? 0 : undefined,
stack, xAxis: xAxisLabel,
totalStackedValues, extraMetricLabels,
isHorizontal, stack,
sortSeriesType, totalStackedValues,
sortSeriesAscending, isHorizontal,
xAxisSortSeries: isMultiSeries ? xAxisSortSeries : undefined, sortSeriesType,
xAxisSortSeriesAscending: isMultiSeries sortSeriesAscending,
? xAxisSortSeriesAscending xAxisSortSeries: isMultiSeries ? xAxisSortSeries : undefined,
: undefined, xAxisSortSeriesAscending: isMultiSeries
}); ? xAxisSortSeriesAscending
: undefined,
},
);
const showValueIndexes = extractShowValueIndexes(rawSeries, { const showValueIndexes = extractShowValueIndexes(rawSeries, {
stack, stack,
onlyTotal, onlyTotal,
@ -358,6 +362,8 @@ export default function transformProps(
if ((contributionMode === 'row' || isAreaExpand) && stack) { if ((contributionMode === 'row' || isAreaExpand) && stack) {
if (min === undefined) min = 0; if (min === undefined) min = 0;
if (max === undefined) max = 1; if (max === undefined) max = 1;
} else if (logAxis && min === undefined && minPositiveValue !== undefined) {
min = calculateLowerLogTick(minPositiveValue);
} }
const tooltipFormatter = const tooltipFormatter =

View File

@ -247,7 +247,7 @@ export function extractSeries(
xAxisSortSeries?: SortSeriesType; xAxisSortSeries?: SortSeriesType;
xAxisSortSeriesAscending?: boolean; xAxisSortSeriesAscending?: boolean;
} = {}, } = {},
): [SeriesOption[], number[]] { ): [SeriesOption[], number[], number | undefined] {
const { const {
fillNeighborValue, fillNeighborValue,
xAxis = DTTM_ALIAS, xAxis = DTTM_ALIAS,
@ -261,7 +261,7 @@ export function extractSeries(
xAxisSortSeries, xAxisSortSeries,
xAxisSortSeriesAscending, xAxisSortSeriesAscending,
} = opts; } = opts;
if (data.length === 0) return [[], []]; if (data.length === 0) return [[], [], undefined];
const rows: DataRecord[] = data.map(datum => ({ const rows: DataRecord[] = data.map(datum => ({
...datum, ...datum,
[xAxis]: datum[xAxis], [xAxis]: datum[xAxis],
@ -287,18 +287,27 @@ export function extractSeries(
totalStackedValue: totalStackedValues[idx], totalStackedValue: totalStackedValues[idx],
})); }));
let minPositiveValue: number | undefined;
const finalSeries = sortedSeries.map(name => ({ const finalSeries = sortedSeries.map(name => ({
id: name, id: name,
name, name,
data: sortedRows data: sortedRows
.map(({ row, totalStackedValue }, idx) => { .map(({ row, totalStackedValue }, idx) => {
const currentValue = row[name];
if (
typeof currentValue === 'number' &&
currentValue > 0 &&
(minPositiveValue === undefined || minPositiveValue > currentValue)
) {
minPositiveValue = currentValue;
}
const isNextToDefinedValue = const isNextToDefinedValue =
isDefined(rows[idx - 1]?.[name]) || isDefined(rows[idx + 1]?.[name]); isDefined(rows[idx - 1]?.[name]) || isDefined(rows[idx + 1]?.[name]);
const isFillNeighborValue = const isFillNeighborValue =
!isDefined(row[name]) && !isDefined(currentValue) &&
isNextToDefinedValue && isNextToDefinedValue &&
fillNeighborValue !== undefined; fillNeighborValue !== undefined;
let value: DataRecordValue | undefined = row[name]; let value: DataRecordValue | undefined = currentValue;
if (isFillNeighborValue) { if (isFillNeighborValue) {
value = fillNeighborValue; value = fillNeighborValue;
} else if ( } else if (
@ -315,6 +324,7 @@ export function extractSeries(
return [ return [
finalSeries, finalSeries,
sortedRows.map(({ totalStackedValue }) => totalStackedValue), sortedRows.map(({ totalStackedValue }) => totalStackedValue),
minPositiveValue,
]; ];
} }
@ -518,3 +528,8 @@ export function getOverMaxHiddenFormatter(
id: NumberFormats.OVER_MAX_HIDDEN, id: NumberFormats.OVER_MAX_HIDDEN,
}); });
} }
export function calculateLowerLogTick(minPositiveValue: number) {
const logBase10 = Math.floor(Math.log10(minPositiveValue));
return Math.pow(10, logBase10);
}

View File

@ -25,6 +25,7 @@ import {
supersetTheme as theme, supersetTheme as theme,
} from '@superset-ui/core'; } from '@superset-ui/core';
import { import {
calculateLowerLogTick,
dedupSeries, dedupSeries,
extractGroupbyLabel, extractGroupbyLabel,
extractSeries, extractSeries,
@ -321,6 +322,7 @@ describe('extractSeries', () => {
}, },
], ],
totalStackedValues, totalStackedValues,
1,
]); ]);
}); });
@ -366,6 +368,7 @@ describe('extractSeries', () => {
}, },
], ],
totalStackedValues, totalStackedValues,
1,
]); ]);
}); });
@ -435,6 +438,7 @@ describe('extractSeries', () => {
}, },
], ],
totalStackedValues, totalStackedValues,
1,
]); ]);
}); });
}); });
@ -857,3 +861,12 @@ describe('getOverMaxHiddenFormatter', () => {
expect(formatter.format(50000)).toEqual('50000'); expect(formatter.format(50000)).toEqual('50000');
}); });
}); });
test('calculateLowerLogTick', () => {
expect(calculateLowerLogTick(1000000)).toEqual(1000000);
expect(calculateLowerLogTick(456)).toEqual(100);
expect(calculateLowerLogTick(100)).toEqual(100);
expect(calculateLowerLogTick(99)).toEqual(10);
expect(calculateLowerLogTick(2)).toEqual(1);
expect(calculateLowerLogTick(0.005)).toEqual(0.001);
});