You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by jo...@apache.org on 2023/12/14 18:13:46 UTC
(superset) branch master updated: fix(plugin-chart-echarts): use scale for truncating x-axis (#26269)
This is an automated email from the ASF dual-hosted git repository.
johnbodley pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 67468c46c0 fix(plugin-chart-echarts): use scale for truncating x-axis (#26269)
67468c46c0 is described below
commit 67468c46c0c8c8a03833dd64eb84284890b7091c
Author: Ville Brofeldt <33...@users.noreply.github.com>
AuthorDate: Thu Dec 14 10:13:39 2023 -0800
fix(plugin-chart-echarts): use scale for truncating x-axis (#26269)
---
.../src/MixedTimeseries/controlPanel.tsx | 4 +
.../src/MixedTimeseries/transformProps.ts | 52 +++++++----
.../src/MixedTimeseries/types.ts | 1 +
.../src/Timeseries/transformProps.ts | 8 +-
.../plugin-chart-echarts/src/utils/controls.ts | 1 -
.../plugin-chart-echarts/src/utils/series.ts | 40 ++++++--
.../plugin-chart-echarts/test/utils/series.test.ts | 101 +++++++++++++++++++--
7 files changed, 170 insertions(+), 37 deletions(-)
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
index f54b3d01dc..c5fed29847 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
@@ -35,6 +35,8 @@ import { EchartsTimeseriesSeriesType } from '../Timeseries/types';
import {
legendSection,
richTooltipSection,
+ truncateXAxis,
+ xAxisBounds,
xAxisLabelRotation,
} from '../controls';
@@ -333,6 +335,8 @@ const config: ControlPanelConfig = {
},
},
],
+ [truncateXAxis],
+ [xAxisBounds],
[
{
name: 'truncateYAxis',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
index f924ad6f9b..223083ef0c 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
@@ -20,32 +20,32 @@
import { invert } from 'lodash';
import {
AnnotationLayer,
+ buildCustomFormatters,
CategoricalColorNamespace,
+ CurrencyFormatter,
+ ensureIsArray,
GenericDataType,
+ getCustomFormatter,
getNumberFormatter,
+ getXAxisLabel,
+ isDefined,
isEventAnnotationLayer,
isFormulaAnnotationLayer,
isIntervalAnnotationLayer,
+ isPhysicalColumn,
isTimeseriesAnnotationLayer,
QueryFormData,
+ QueryFormMetric,
TimeseriesChartDataResponseResult,
TimeseriesDataRecord,
- getXAxisLabel,
- isPhysicalColumn,
- isDefined,
- ensureIsArray,
- buildCustomFormatters,
ValueFormatter,
- QueryFormMetric,
- getCustomFormatter,
- CurrencyFormatter,
} from '@superset-ui/core';
import { getOriginalSeries } from '@superset-ui/chart-controls';
import { EChartsCoreOption, SeriesOption } from 'echarts';
import {
DEFAULT_FORM_DATA,
- EchartsMixedTimeseriesFormData,
EchartsMixedTimeseriesChartTransformedProps,
+ EchartsMixedTimeseriesFormData,
EchartsMixedTimeseriesProps,
} from './types';
import {
@@ -55,14 +55,15 @@ import {
} from '../types';
import { parseAxisBound } from '../utils/controls';
import {
- getOverMaxHiddenFormatter,
dedupSeries,
+ extractDataTotalValues,
extractSeries,
+ extractShowValueIndexes,
getAxisType,
getColtypesMapping,
getLegendProps,
- extractDataTotalValues,
- extractShowValueIndexes,
+ getMinAndMaxFromBounds,
+ getOverMaxHiddenFormatter,
} from '../utils/series';
import {
extractAnnotationLabels,
@@ -84,7 +85,7 @@ import {
transformSeries,
transformTimeseriesAnnotation,
} from '../Timeseries/transformers';
-import { TIMESERIES_CONSTANTS, TIMEGRAIN_TO_TIMESTAMP } from '../constants';
+import { TIMEGRAIN_TO_TIMESTAMP, TIMESERIES_CONSTANTS } from '../constants';
import { getDefaultTooltip } from '../utils/tooltip';
import {
getTooltipTimeFormatter,
@@ -166,6 +167,7 @@ export default function transformProps(
showValueB,
stack,
stackB,
+ truncateXAxis,
truncateYAxis,
tooltipTimeFormat,
yAxisFormat,
@@ -181,6 +183,7 @@ export default function transformProps(
zoomable,
richTooltip,
tooltipSortByMetric,
+ xAxisBounds,
xAxisLabelRotation,
groupby,
groupbyB,
@@ -345,7 +348,8 @@ export default function transformProps(
});
// yAxisBounds need to be parsed to replace incompatible values with undefined
- let [min, max] = (yAxisBounds || []).map(parseAxisBound);
+ const [xAxisMin, xAxisMax] = (xAxisBounds || []).map(parseAxisBound);
+ let [yAxisMin, yAxisMax] = (yAxisBounds || []).map(parseAxisBound);
let [minSecondary, maxSecondary] = (yAxisBoundsSecondary || []).map(
parseAxisBound,
);
@@ -386,7 +390,7 @@ export default function transformProps(
formatter:
seriesType === EchartsTimeseriesSeriesType.Bar
? getOverMaxHiddenFormatter({
- max,
+ max: yAxisMax,
formatter: seriesFormatter,
})
: seriesFormatter,
@@ -447,8 +451,8 @@ export default function transformProps(
// default to 0-100% range when doing row-level contribution chart
if (contributionMode === 'row' && stack) {
- if (min === undefined) min = 0;
- if (max === undefined) max = 1;
+ if (yAxisMin === undefined) yAxisMin = 0;
+ if (yAxisMax === undefined) yAxisMax = 1;
if (minSecondary === undefined) minSecondary = 0;
if (maxSecondary === undefined) maxSecondary = 1;
}
@@ -499,13 +503,23 @@ export default function transformProps(
xAxisType === 'time' && timeGrainSqla
? TIMEGRAIN_TO_TIMESTAMP[timeGrainSqla]
: 0,
+ ...getMinAndMaxFromBounds(
+ xAxisType,
+ truncateXAxis,
+ xAxisMin,
+ xAxisMax,
+ seriesType === EchartsTimeseriesSeriesType.Bar ||
+ seriesTypeB === EchartsTimeseriesSeriesType.Bar
+ ? EchartsTimeseriesSeriesType.Bar
+ : undefined,
+ ),
},
yAxis: [
{
...defaultYAxis,
type: logAxis ? 'log' : 'value',
- min,
- max,
+ min: yAxisMin,
+ max: yAxisMax,
minorTick: { show: true },
minorSplitLine: { show: minorSplitLine },
axisLabel: {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts
index 30969ae367..2e9ba641aa 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts
@@ -104,6 +104,7 @@ export const DEFAULT_FORM_DATA: EchartsMixedTimeseriesFormData = {
yAxisFormatSecondary: TIMESERIES_DEFAULTS.yAxisFormat,
yAxisTitleSecondary: DEFAULT_TITLE_FORM_DATA.yAxisTitle,
tooltipTimeFormat: TIMESERIES_DEFAULTS.tooltipTimeFormat,
+ xAxisBounds: TIMESERIES_DEFAULTS.xAxisBounds,
xAxisTimeFormat: TIMESERIES_DEFAULTS.xAxisTimeFormat,
area: TIMESERIES_DEFAULTS.area,
areaB: TIMESERIES_DEFAULTS.area,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
index 8dd9966484..0d54fd114c 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
@@ -460,7 +460,13 @@ export default function transformProps(
xAxisType === AxisType.time && timeGrainSqla
? TIMEGRAIN_TO_TIMESTAMP[timeGrainSqla]
: 0,
- ...getMinAndMaxFromBounds(xAxisType, truncateXAxis, xAxisMin, xAxisMax),
+ ...getMinAndMaxFromBounds(
+ xAxisType,
+ truncateXAxis,
+ xAxisMin,
+ xAxisMax,
+ seriesType,
+ ),
};
let yAxis: any = {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts
index 67a5414112..689a6e99e5 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts
@@ -19,7 +19,6 @@
import { validateNumber } from '@superset-ui/core';
-// eslint-disable-next-line import/prefer-default-export
export function parseAxisBound(
bound?: string | number | null,
): number | undefined {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
index 69c0ccbe1b..a294fa44c3 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
@@ -41,7 +41,12 @@ import {
StackControlsValue,
TIMESERIES_CONSTANTS,
} from '../constants';
-import { LegendOrientation, LegendType, StackType } from '../types';
+import {
+ EchartsTimeseriesSeriesType,
+ LegendOrientation,
+ LegendType,
+ StackType,
+} from '../types';
import { defaultLegendPadding } from '../defaults';
function isDefined<T>(value: T | undefined | null): boolean {
@@ -547,16 +552,35 @@ export function calculateLowerLogTick(minPositiveValue: number) {
return Math.pow(10, logBase10);
}
+type BoundsType = {
+ min?: number | 'dataMin';
+ max?: number | 'dataMax';
+ scale?: true;
+};
+
export function getMinAndMaxFromBounds(
axisType: AxisType,
truncateAxis: boolean,
min?: number,
max?: number,
-): { min: number | 'dataMin'; max: number | 'dataMax' } | {} {
- return truncateAxis && axisType === AxisType.value
- ? {
- min: min === undefined ? 'dataMin' : min,
- max: max === undefined ? 'dataMax' : max,
- }
- : {};
+ seriesType?: EchartsTimeseriesSeriesType,
+): BoundsType | {} {
+ if (axisType === AxisType.value && truncateAxis) {
+ const ret: BoundsType = {};
+ if (seriesType === EchartsTimeseriesSeriesType.Bar) {
+ ret.scale = true;
+ }
+ if (min !== undefined) {
+ ret.min = min;
+ } else if (seriesType !== EchartsTimeseriesSeriesType.Bar) {
+ ret.min = 'dataMin';
+ }
+ if (max !== undefined) {
+ ret.max = max;
+ } else if (seriesType !== EchartsTimeseriesSeriesType.Bar) {
+ ret.max = 'dataMax';
+ }
+ return ret;
+ }
+ return {};
}
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts
index b309bf6f3c..8e55b125b8 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts
@@ -41,7 +41,11 @@ import {
sortAndFilterSeries,
sortRows,
} from '../../src/utils/series';
-import { LegendOrientation, LegendType } from '../../src/types';
+import {
+ EchartsTimeseriesSeriesType,
+ LegendOrientation,
+ LegendType,
+} from '../../src/types';
import { defaultLegendPadding } from '../../src/defaults';
import { NULL_STRING } from '../../src/constants';
@@ -885,28 +889,109 @@ test('getAxisType', () => {
});
test('getMinAndMaxFromBounds returns empty object when not truncating', () => {
- expect(getMinAndMaxFromBounds(AxisType.value, false, 10, 100)).toEqual({});
+ expect(
+ getMinAndMaxFromBounds(
+ AxisType.value,
+ false,
+ 10,
+ 100,
+ EchartsTimeseriesSeriesType.Bar,
+ ),
+ ).toEqual({});
+});
+
+test('getMinAndMaxFromBounds returns empty object for categorical axis', () => {
+ expect(
+ getMinAndMaxFromBounds(
+ AxisType.category,
+ false,
+ 10,
+ 100,
+ EchartsTimeseriesSeriesType.Bar,
+ ),
+ ).toEqual({});
+});
+
+test('getMinAndMaxFromBounds returns empty object for time axis', () => {
+ expect(
+ getMinAndMaxFromBounds(
+ AxisType.time,
+ false,
+ 10,
+ 100,
+ EchartsTimeseriesSeriesType.Bar,
+ ),
+ ).toEqual({});
});
-test('getMinAndMaxFromBounds returns automatic bounds when truncating', () => {
+test('getMinAndMaxFromBounds returns dataMin/dataMax for non-bar charts', () => {
expect(
- getMinAndMaxFromBounds(AxisType.value, true, undefined, undefined),
+ getMinAndMaxFromBounds(
+ AxisType.value,
+ true,
+ undefined,
+ undefined,
+ EchartsTimeseriesSeriesType.Line,
+ ),
).toEqual({
min: 'dataMin',
max: 'dataMax',
});
});
-test('getMinAndMaxFromBounds returns automatic upper bound when truncating', () => {
- expect(getMinAndMaxFromBounds(AxisType.value, true, 10, undefined)).toEqual({
+test('getMinAndMaxFromBounds returns bound without scale for non-bar charts', () => {
+ expect(
+ getMinAndMaxFromBounds(
+ AxisType.value,
+ true,
+ 10,
+ undefined,
+ EchartsTimeseriesSeriesType.Line,
+ ),
+ ).toEqual({
min: 10,
max: 'dataMax',
});
});
+test('getMinAndMaxFromBounds returns scale when truncating without bounds', () => {
+ expect(
+ getMinAndMaxFromBounds(
+ AxisType.value,
+ true,
+ undefined,
+ undefined,
+ EchartsTimeseriesSeriesType.Bar,
+ ),
+ ).toEqual({ scale: true });
+});
+
+test('getMinAndMaxFromBounds returns automatic upper bound when truncating', () => {
+ expect(
+ getMinAndMaxFromBounds(
+ AxisType.value,
+ true,
+ 10,
+ undefined,
+ EchartsTimeseriesSeriesType.Bar,
+ ),
+ ).toEqual({
+ min: 10,
+ scale: true,
+ });
+});
+
test('getMinAndMaxFromBounds returns automatic lower bound when truncating', () => {
- expect(getMinAndMaxFromBounds(AxisType.value, true, undefined, 100)).toEqual({
- min: 'dataMin',
+ expect(
+ getMinAndMaxFromBounds(
+ AxisType.value,
+ true,
+ undefined,
+ 100,
+ EchartsTimeseriesSeriesType.Bar,
+ ),
+ ).toEqual({
max: 100,
+ scale: true,
});
});