fix(echarts): rename time series shifted colnames (#33269)

This commit is contained in:
JUST.in DO IT
2025-04-30 10:18:18 -07:00
committed by GitHub
parent 2a97a6ec1f
commit ef14b529b8
2 changed files with 118 additions and 36 deletions

View File

@@ -26,6 +26,7 @@ import {
} from '@superset-ui/core';
import { PostProcessingFactory } from './types';
import { getMetricOffsetsMap, isTimeComparison } from './utils';
import { TIME_COMPARISON_SEPARATOR } from './utils/constants';
export const renameOperator: PostProcessingFactory<PostProcessingRename> = (
formData,
@@ -37,50 +38,60 @@ export const renameOperator: PostProcessingFactory<PostProcessingRename> = (
);
const { truncate_metric } = formData;
const xAxisLabel = getXAxisLabel(formData);
const isTimeComparisonValue = isTimeComparison(formData, queryObject);
// remove or rename top level of column name(metric name) in the MultiIndex when
// 1) only 1 metric
// 1) at least 1 metric
// 2) dimension exist
// 3) xAxis exist
// 4) time comparison exist, and comparison type is "actual values"
// 5) truncate_metric in form_data and truncate_metric is true
// 4) truncate_metric in form_data and truncate_metric is true
if (
metrics.length === 1 &&
metrics.length > 0 &&
columns.length > 0 &&
xAxisLabel &&
!(
// todo: we should provide an approach to handle derived metrics
(
isTimeComparison(formData, queryObject) &&
[
ComparisonType.Difference,
ComparisonType.Ratio,
ComparisonType.Percentage,
].includes(formData.comparison_type)
)
) &&
truncate_metric !== undefined &&
!!truncate_metric
) {
const renamePairs: [string, string | null][] = [];
if (
// "actual values" will add derived metric.
// we will rename the "metric" from the metricWithOffset label
// for example: "count__1 year ago" => "1 year ago"
isTimeComparison(formData, queryObject) &&
formData.comparison_type === ComparisonType.Values
isTimeComparisonValue
) {
const metricOffsetMap = getMetricOffsetsMap(formData, queryObject);
const timeOffsets = ensureIsArray(formData.time_compare);
[...metricOffsetMap.keys()].forEach(metricWithOffset => {
const offsetLabel = timeOffsets.find(offset =>
metricWithOffset.includes(offset),
);
renamePairs.push([metricWithOffset, offsetLabel]);
});
[...metricOffsetMap.entries()].forEach(
([metricWithOffset, metricOnly]) => {
const offsetLabel = timeOffsets.find(offset =>
metricWithOffset.includes(offset),
);
renamePairs.push([
formData.comparison_type === ComparisonType.Values
? metricWithOffset
: [formData.comparison_type, metricOnly, metricWithOffset].join(
TIME_COMPARISON_SEPARATOR,
),
metrics.length > 1 ? `${metricOnly}, ${offsetLabel}` : offsetLabel,
]);
},
);
}
renamePairs.push([getMetricLabel(metrics[0]), null]);
if (
![
ComparisonType.Difference,
ComparisonType.Percentage,
ComparisonType.Ratio,
].includes(formData.comparison_type) &&
metrics.length === 1
) {
renamePairs.push([getMetricLabel(metrics[0]), null]);
}
if (renamePairs.length === 0) {
return undefined;
}
return {
operation: 'rename',

View File

@@ -43,12 +43,12 @@ const queryObject: QueryObject = {
post_processing: [],
};
test('should skip renameOperator if exists multiple metrics', () => {
test('should skip renameOperator for empty metrics', () => {
expect(
renameOperator(formData, {
...queryObject,
...{
metrics: ['count(*)', 'sum(sales)'],
metrics: [],
},
}),
).toEqual(undefined);
@@ -77,7 +77,23 @@ test('should skip renameOperator if does not exist x_axis and is_timeseries', ()
).toEqual(undefined);
});
test('should skip renameOperator if exists derived metrics', () => {
test('should skip renameOperator if not is_timeseries and multi metrics', () => {
expect(
renameOperator(formData, {
...queryObject,
...{ is_timeseries: false, metrics: ['count(*)', 'sum(val)'] },
}),
).toEqual(undefined);
});
test('should add renameOperator', () => {
expect(renameOperator(formData, queryObject)).toEqual({
operation: 'rename',
options: { columns: { 'count(*)': null }, inplace: true, level: 0 },
});
});
test('should add renameOperator if exists derived metrics', () => {
[
ComparisonType.Difference,
ComparisonType.Ratio,
@@ -99,14 +115,14 @@ test('should skip renameOperator if exists derived metrics', () => {
},
},
),
).toEqual(undefined);
});
});
test('should add renameOperator', () => {
expect(renameOperator(formData, queryObject)).toEqual({
operation: 'rename',
options: { columns: { 'count(*)': null }, inplace: true, level: 0 },
).toEqual({
operation: 'rename',
options: {
columns: { [`${type}__count(*)__count(*)__1 year ago`]: '1 year ago' },
inplace: true,
level: 0,
},
});
});
});
@@ -170,6 +186,61 @@ test('should add renameOperator if exist "actual value" time comparison', () =>
});
});
test('should add renameOperator if derived time comparison exists', () => {
expect(
renameOperator(
{
...formData,
...{
comparison_type: ComparisonType.Ratio,
time_compare: ['1 year ago', '1 year later'],
},
},
queryObject,
),
).toEqual({
operation: 'rename',
options: {
columns: {
'ratio__count(*)__count(*)__1 year ago': '1 year ago',
'ratio__count(*)__count(*)__1 year later': '1 year later',
},
inplace: true,
level: 0,
},
});
});
test('should add renameOperator if multiple metrics exist', () => {
expect(
renameOperator(
{
...formData,
...{
comparison_type: ComparisonType.Values,
time_compare: ['1 year ago'],
},
},
{
...queryObject,
...{
metrics: ['count(*)', 'sum(sales)'],
},
},
),
).toEqual({
operation: 'rename',
options: {
columns: {
'count(*)__1 year ago': 'count(*), 1 year ago',
'sum(sales)__1 year ago': 'sum(sales), 1 year ago',
},
inplace: true,
level: 0,
},
});
});
test('should remove renameOperator', () => {
expect(
renameOperator(