Skip to content

Commit cbbcc8d

Browse files
authored
fix(plugin-chart-echarts): reorder totals and support multimetric sort (apache#23675)
1 parent 47fd732 commit cbbcc8d

File tree

6 files changed

+244
-120
lines changed

6 files changed

+244
-120
lines changed

superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/customControls.tsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,27 +54,29 @@ export const contributionModeControl = {
5454
},
5555
};
5656

57+
function isTemporal(controls: ControlStateMapping): boolean {
58+
return !(
59+
isDefined(controls?.x_axis?.value) &&
60+
!isTemporalColumn(
61+
getColumnLabel(controls?.x_axis?.value as QueryFormColumn),
62+
controls?.datasource?.datasource,
63+
)
64+
);
65+
}
66+
5767
const xAxisSortVisibility = ({ controls }: { controls: ControlStateMapping }) =>
58-
isDefined(controls?.x_axis?.value) &&
59-
!isTemporalColumn(
60-
getColumnLabel(controls?.x_axis?.value as QueryFormColumn),
61-
controls?.datasource?.datasource,
62-
) &&
63-
Array.isArray(controls?.groupby?.value) &&
64-
controls.groupby.value.length === 0;
68+
!isTemporal(controls) &&
69+
ensureIsArray(controls?.groupby?.value).length === 0 &&
70+
ensureIsArray(controls?.metrics?.value).length === 1;
6571

6672
const xAxisMultiSortVisibility = ({
6773
controls,
6874
}: {
6975
controls: ControlStateMapping;
7076
}) =>
71-
isDefined(controls?.x_axis?.value) &&
72-
!isTemporalColumn(
73-
getColumnLabel(controls?.x_axis?.value as QueryFormColumn),
74-
controls?.datasource?.datasource,
75-
) &&
76-
Array.isArray(controls?.groupby?.value) &&
77-
!!controls.groupby.value.length;
77+
!isTemporal(controls) &&
78+
(!!ensureIsArray(controls?.groupby?.value).length ||
79+
ensureIsArray(controls?.metrics?.value).length > 1);
7880

7981
export const xAxisSortControl = {
8082
name: 'x_axis_sort',

superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,12 @@ export default function transformProps(
170170
}
171171

172172
const rebasedDataA = rebaseForecastDatum(data1, verboseMap);
173-
const rawSeriesA = extractSeries(rebasedDataA, {
173+
const [rawSeriesA] = extractSeries(rebasedDataA, {
174174
fillNeighborValue: stack ? 0 : undefined,
175175
xAxis: xAxisLabel,
176176
});
177177
const rebasedDataB = rebaseForecastDatum(data2, verboseMap);
178-
const rawSeriesB = extractSeries(rebasedDataB, {
178+
const [rawSeriesB] = extractSeries(rebasedDataB, {
179179
fillNeighborValue: stackB ? 0 : undefined,
180180
xAxis: xAxisLabel,
181181
});

superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ export default function transformProps(
126126
logAxis,
127127
markerEnabled,
128128
markerSize,
129+
metrics,
129130
minorSplitLine,
130131
onlyTotal,
131132
opacity,
@@ -193,7 +194,9 @@ export default function transformProps(
193194
getMetricLabel,
194195
);
195196

196-
const rawSeries = extractSeries(rebasedData, {
197+
const isMultiSeries = groupby.length || metrics.length > 1;
198+
199+
const [rawSeries, sortedTotalValues] = extractSeries(rebasedData, {
197200
fillNeighborValue: stack && !forecastEnabled ? 0 : undefined,
198201
xAxis: xAxisLabel,
199202
extraMetricLabels,
@@ -202,8 +205,8 @@ export default function transformProps(
202205
isHorizontal,
203206
sortSeriesType,
204207
sortSeriesAscending,
205-
xAxisSortSeries: groupby.length ? xAxisSortSeries : undefined,
206-
xAxisSortSeriesAscending: groupby.length
208+
xAxisSortSeries: isMultiSeries ? xAxisSortSeries : undefined,
209+
xAxisSortSeriesAscending: isMultiSeries
207210
? xAxisSortSeriesAscending
208211
: undefined,
209212
});
@@ -240,7 +243,7 @@ export default function transformProps(
240243
formatter,
241244
showValue,
242245
onlyTotal,
243-
totalStackedValues,
246+
totalStackedValues: sortedTotalValues,
244247
showValueIndexes,
245248
thresholdValues,
246249
richTooltip,

superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
ContributionType,
2424
QueryFormColumn,
2525
QueryFormData,
26+
QueryFormMetric,
2627
TimeFormatter,
2728
TimeGranularity,
2829
} from '@superset-ui/core';
@@ -65,6 +66,7 @@ export type EchartsTimeseriesFormData = QueryFormData & {
6566
logAxis: boolean;
6667
markerEnabled: boolean;
6768
markerSize: number;
69+
metrics: QueryFormMetric[];
6870
minorSplitLine: boolean;
6971
opacity: number;
7072
orderDesc: boolean;

superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,12 @@ export function sortAndFilterSeries(
153153

154154
export function sortRows(
155155
rows: DataRecord[],
156+
totalStackedValues: number[],
156157
xAxis: string,
157158
xAxisSortSeries: SortSeriesType,
158159
xAxisSortSeriesAscending: boolean,
159160
) {
160-
const sortedRows = rows.map(row => {
161+
const sortedRows = rows.map((row, idx) => {
161162
let sortKey: DataRecordValue = '';
162163
let aggregate: number | undefined;
163164
let entries = 0;
@@ -219,14 +220,15 @@ export function sortRows(
219220
key: sortKey,
220221
value,
221222
row,
223+
totalStackedValue: totalStackedValues[idx],
222224
};
223225
});
224226

225227
return orderBy(
226228
sortedRows,
227229
['value'],
228230
[xAxisSortSeriesAscending ? 'asc' : 'desc'],
229-
).map(({ row }) => row);
231+
).map(({ row, totalStackedValue }) => ({ row, totalStackedValue }));
230232
}
231233

232234
export function extractSeries(
@@ -244,7 +246,7 @@ export function extractSeries(
244246
xAxisSortSeries?: SortSeriesType;
245247
xAxisSortSeriesAscending?: boolean;
246248
} = {},
247-
): SeriesOption[] {
249+
): [SeriesOption[], number[]] {
248250
const {
249251
fillNeighborValue,
250252
xAxis = DTTM_ALIAS,
@@ -258,7 +260,7 @@ export function extractSeries(
258260
xAxisSortSeries,
259261
xAxisSortSeriesAscending,
260262
} = opts;
261-
if (data.length === 0) return [];
263+
if (data.length === 0) return [[], []];
262264
const rows: DataRecord[] = data.map(datum => ({
263265
...datum,
264266
[xAxis]: datum[xAxis],
@@ -272,14 +274,23 @@ export function extractSeries(
272274
);
273275
const sortedRows =
274276
isDefined(xAxisSortSeries) && isDefined(xAxisSortSeriesAscending)
275-
? sortRows(rows, xAxis, xAxisSortSeries!, xAxisSortSeriesAscending!)
276-
: rows;
277+
? sortRows(
278+
rows,
279+
totalStackedValues,
280+
xAxis,
281+
xAxisSortSeries!,
282+
xAxisSortSeriesAscending!,
283+
)
284+
: rows.map((row, idx) => ({
285+
row,
286+
totalStackedValue: totalStackedValues[idx],
287+
}));
277288

278-
return sortedSeries.map(name => ({
289+
const finalSeries = sortedSeries.map(name => ({
279290
id: name,
280291
name,
281292
data: sortedRows
282-
.map((row, idx) => {
293+
.map(({ row, totalStackedValue }, idx) => {
283294
const isNextToDefinedValue =
284295
isDefined(rows[idx - 1]?.[name]) || isDefined(rows[idx + 1]?.[name]);
285296
const isFillNeighborValue =
@@ -291,15 +302,19 @@ export function extractSeries(
291302
value = fillNeighborValue;
292303
} else if (
293304
stack === StackControlsValue.Expand &&
294-
totalStackedValues.length > 0
305+
totalStackedValue !== undefined
295306
) {
296-
value = ((value || 0) as number) / totalStackedValues[idx];
307+
value = ((value || 0) as number) / totalStackedValue;
297308
}
298309
return [row[xAxis], value];
299310
})
300311
.filter(obs => !removeNulls || (obs[0] !== null && obs[1] !== null))
301312
.map(obs => (isHorizontal ? [obs[1], obs[0]] : obs)),
302313
}));
314+
return [
315+
finalSeries,
316+
sortedRows.map(({ totalStackedValue }) => totalStackedValue),
317+
];
303318
}
304319

305320
export function formatSeriesName(

0 commit comments

Comments
 (0)