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

vavila pushed a commit to branch feat/natural-compare-sorting
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 51ac6c9491f792bd88dad2bd8b3212fc3bc968d0
Author: Vitor Avila <[email protected]>
AuthorDate: Tue Mar 25 10:34:50 2025 -0300

    feat(echarts): Use naturalCompare for series sorting
---
 superset-frontend/package-lock.json                |  5 +-
 superset-frontend/package.json                     |  1 +
 .../plugin-chart-echarts/src/utils/series.ts       |  8 ++-
 .../plugin-chart-echarts/test/utils/series.test.ts | 75 ++++++++++++++++++++++
 .../plugin-chart-echarts/types/external.d.ts       |  5 ++
 5 files changed, 89 insertions(+), 5 deletions(-)

diff --git a/superset-frontend/package-lock.json 
b/superset-frontend/package-lock.json
index 89f7f03163..c234c050a4 100644
--- a/superset-frontend/package-lock.json
+++ b/superset-frontend/package-lock.json
@@ -99,6 +99,7 @@
         "mousetrap": "^1.6.5",
         "mustache": "^4.2.0",
         "nanoid": "^5.0.9",
+        "natural-compare-lite": "^1.4.0",
         "ol": "^7.5.2",
         "polished": "^4.3.1",
         "prop-types": "^15.8.1",
@@ -34042,9 +34043,7 @@
     "node_modules/natural-compare-lite": {
       "version": "1.4.0",
       "resolved": 
"https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz";,
-      "integrity": 
"sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
-      "dev": true,
-      "license": "MIT"
+      "integrity": 
"sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g=="
     },
     "node_modules/nearley": {
       "version": "2.20.1",
diff --git a/superset-frontend/package.json b/superset-frontend/package.json
index 5a1ce072d9..53fd32cc83 100644
--- a/superset-frontend/package.json
+++ b/superset-frontend/package.json
@@ -166,6 +166,7 @@
     "mousetrap": "^1.6.5",
     "mustache": "^4.2.0",
     "nanoid": "^5.0.9",
+    "natural-compare-lite": "^1.4.0",
     "ol": "^7.5.2",
     "polished": "^4.3.1",
     "prop-types": "^15.8.1",
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 ef10fb9d3b..2afc7c5924 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
@@ -38,6 +38,7 @@ import { format } from 'echarts/core';
 import type { LegendComponentOption } from 'echarts/components';
 import type { SeriesOption } from 'echarts';
 import { isEmpty, maxBy, meanBy, minBy, orderBy, sumBy } from 'lodash';
+import naturalCompare from 'natural-compare-lite';
 import {
   NULL_STRING,
   StackControlsValue,
@@ -157,8 +158,11 @@ export function sortAndFilterSeries(
       aggregator = name => ({ name, value: meanBy(rows, name) });
       break;
     default:
-      aggregator = name => ({ name, value: name.toLowerCase() });
-      break;
+      return [...seriesNames].sort((a, b) =>
+        sortSeriesAscending
+          ? naturalCompare(a.toLowerCase(), b.toLowerCase())
+          : naturalCompare(b.toLowerCase(), a.toLowerCase()),
+      );
   }
 
   const sortedValues = seriesNames.map(aggregator);
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 7054f6019a..2bb870ceb4 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
@@ -67,6 +67,27 @@ const sortData: DataRecord[] = [
   { my_x_axis: null, x: 4, y: 3, z: 7 },
 ];
 
+const sortDataWithNumbers: DataRecord[] = [
+  {
+    my_x_axis: 'my_axis',
+    6: 1,
+    8: 2,
+    10: 4,
+    2: 1,
+    12: 3,
+    9: 1,
+    5: 4,
+    3: 1,
+    11: 2,
+    1: 7,
+    4: 5,
+    7: 2,
+    c: 0,
+    d: 0,
+    a: 1,
+  },
+];
+
 const totalStackedValues = [3, 15, 14];
 
 test('sortRows by name ascending', () => {
@@ -288,6 +309,60 @@ test('sortAndFilterSeries by name descending', () => {
     sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Name, false),
   ).toEqual(['z', 'y', 'x']);
 });
+test('sortAndFilterSeries by name with integers asc', () => {
+  expect(
+    sortAndFilterSeries(
+      sortDataWithNumbers,
+      'my_x_axis',
+      [],
+      SortSeriesType.Name,
+      true,
+    ),
+  ).toEqual([
+    '1',
+    '2',
+    '3',
+    '4',
+    '5',
+    '6',
+    '7',
+    '8',
+    '9',
+    '10',
+    '11',
+    '12',
+    'a',
+    'c',
+    'd',
+  ]);
+});
+test('sortAndFilterSeries by name with integers desc', () => {
+  expect(
+    sortAndFilterSeries(
+      sortDataWithNumbers,
+      'my_x_axis',
+      [],
+      SortSeriesType.Name,
+      false,
+    ),
+  ).toEqual([
+    'd',
+    'c',
+    'a',
+    '12',
+    '11',
+    '10',
+    '9',
+    '8',
+    '7',
+    '6',
+    '5',
+    '4',
+    '3',
+    '2',
+    '1',
+  ]);
+});
 
 describe('extractSeries', () => {
   it('should generate a valid ECharts timeseries series object', () => {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/types/external.d.ts 
b/superset-frontend/plugins/plugin-chart-echarts/types/external.d.ts
index ecdf68a745..584b549004 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/types/external.d.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/types/external.d.ts
@@ -23,3 +23,8 @@ declare module '*.png' {
 }
 
 declare module '*.jpg';
+
+declare module 'natural-compare-lite' {
+  function naturalCompare(a: string, b: string): number;
+  export default naturalCompare;
+}

Reply via email to