This is an automated email from the ASF dual-hosted git repository.

michaelsmolina 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 ef14b529b8 fix(echarts): rename time series shifted colnames (#33269)
ef14b529b8 is described below

commit ef14b529b82798989b3aa850a5442a5e5b127dd9
Author: JUST.in DO IT <[email protected]>
AuthorDate: Wed Apr 30 10:18:18 2025 -0700

    fix(echarts): rename time series shifted colnames (#33269)
---
 .../src/operators/renameOperator.ts                | 61 ++++++++------
 .../test/operators/renameOperator.test.ts          | 93 +++++++++++++++++++---
 2 files changed, 118 insertions(+), 36 deletions(-)

diff --git 
a/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts
 
b/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts
index 04f3b7ac32..d6f496c599 100644
--- 
a/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts
+++ 
b/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts
@@ -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',
diff --git 
a/superset-frontend/packages/superset-ui-chart-controls/test/operators/renameOperator.test.ts
 
b/superset-frontend/packages/superset-ui-chart-controls/test/operators/renameOperator.test.ts
index c6b899d513..c3a7faacff 100644
--- 
a/superset-frontend/packages/superset-ui-chart-controls/test/operators/renameOperator.test.ts
+++ 
b/superset-frontend/packages/superset-ui-chart-controls/test/operators/renameOperator.test.ts
@@ -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(

Reply via email to