This is an automated email from the ASF dual-hosted git repository. vavila pushed a commit to branch fix/use-natural-compare-for-series-sorting in repository https://gitbox.apache.org/repos/asf/superset.git
commit ac7c4fd2aeb008596439237786cf9e5b8eddf0f8 Author: Vitor Avila <[email protected]> AuthorDate: Tue Mar 25 15:46:28 2025 -0300 fix(echarts): Sort series by name using naturalCompare --- superset-frontend/package-lock.json | 4 +- .../plugins/plugin-chart-echarts/package.json | 5 +- .../plugin-chart-echarts/src/utils/series.ts | 8 +- .../plugin-chart-echarts/test/utils/series.test.ts | 111 +++++++++++++++++++++ .../plugin-chart-echarts/types/external.d.ts | 5 + 5 files changed, 127 insertions(+), 6 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 89f7f03163..40362d5e1c 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -34043,7 +34043,6 @@ "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" }, "node_modules/nearley": { @@ -50730,7 +50729,8 @@ "@types/react-redux": "^7.1.10", "d3-array": "^1.2.0", "dayjs": "^1.11.13", - "lodash": "^4.17.21" + "lodash": "^4.17.21", + "natural-compare-lite": "^1.4.0" }, "peerDependencies": { "@superset-ui/chart-controls": "*", diff --git a/superset-frontend/plugins/plugin-chart-echarts/package.json b/superset-frontend/plugins/plugin-chart-echarts/package.json index 64da86afdc..5a23f54e43 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/package.json +++ b/superset-frontend/plugins/plugin-chart-echarts/package.json @@ -24,10 +24,11 @@ "lib" ], "dependencies": { + "@types/react-redux": "^7.1.10", "d3-array": "^1.2.0", - "lodash": "^4.17.21", "dayjs": "^1.11.13", - "@types/react-redux": "^7.1.10" + "lodash": "^4.17.21", + "natural-compare-lite": "^1.4.0" }, "peerDependencies": { "@superset-ui/chart-controls": "*", 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..67a0bab9e6 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,39 @@ const sortData: DataRecord[] = [ { my_x_axis: null, x: 4, y: 3, z: 7 }, ]; +const sortDataWithNumbers: DataRecord[] = [ + { + my_x_axis: 'my_axis', + '9. September': 6, + 6: 1, + '11. November': 8, + 8: 2, + '10. October': 1, + 10: 4, + '3. March': 2, + '8. August': 6, + 2: 1, + 12: 3, + 9: 1, + '1. January': 1, + '4. April': 12, + '2. February': 9, + 5: 4, + 3: 1, + 11: 2, + '12. December': 4, + 1: 7, + '6. June': 1, + 4: 5, + 7: 2, + c: 0, + '7. July': 2, + d: 0, + '5. May': 4, + a: 1, + }, +]; + const totalStackedValues = [3, 15, 14]; test('sortRows by name ascending', () => { @@ -288,6 +321,84 @@ test('sortAndFilterSeries by name descending', () => { sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Name, false), ).toEqual(['z', 'y', 'x']); }); +test('sortAndFilterSeries by name with numbers asc', () => { + expect( + sortAndFilterSeries( + sortDataWithNumbers, + 'my_x_axis', + [], + SortSeriesType.Name, + true, + ), + ).toEqual([ + '1', + '1. January', + '2', + '2. February', + '3', + '3. March', + '4', + '4. April', + '5', + '5. May', + '6', + '6. June', + '7', + '7. July', + '8', + '8. August', + '9', + '9. September', + '10', + '10. October', + '11', + '11. November', + '12', + '12. December', + 'a', + 'c', + 'd', + ]); +}); +test('sortAndFilterSeries by name with numbers desc', () => { + expect( + sortAndFilterSeries( + sortDataWithNumbers, + 'my_x_axis', + [], + SortSeriesType.Name, + false, + ), + ).toEqual([ + 'd', + 'c', + 'a', + '12. December', + '12', + '11. November', + '11', + '10. October', + '10', + '9. September', + '9', + '8. August', + '8', + '7. July', + '7', + '6. June', + '6', + '5. May', + '5', + '4. April', + '4', + '3. March', + '3', + '2. February', + '2', + '1. January', + '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; +}
