diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/controlPanel.tsx index 4f93c0ed2cb..7695272b68e 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/controlPanel.tsx @@ -29,7 +29,7 @@ import { sharedControls, } from '@superset-ui/chart-controls'; import { DEFAULT_FORM_DATA } from './types'; -import { legendSection } from '../controls'; +import { legendSection, legendSortControl } from '../controls'; const { donut, @@ -119,6 +119,7 @@ const config: ControlPanelConfig = { }, ], ...legendSection, + [legendSortControl], // eslint-disable-next-line react/jsx-key [{t('Labels')}], [ diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts index e3980a02b30..e6fee12248e 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts @@ -151,6 +151,7 @@ export default function transformProps( legendMargin, legendOrientation, legendType, + legendSort, metric = '', numberFormat, currencyFormat, @@ -435,7 +436,12 @@ export default function transformProps( }, legend: { ...getLegendProps(legendType, legendOrientation, showLegend, theme), - data: transformedData.map(datum => datum.name), + data: transformedData + .map(datum => datum.name) + .sort((a: string, b: string) => { + if (!legendSort) return 0; + return legendSort === 'asc' ? a.localeCompare(b) : b.localeCompare(a); + }), }, graphic: showTotal ? { diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/types.ts index c684dcf4579..a72a43906d6 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/types.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/types.ts @@ -40,6 +40,7 @@ export type EchartsPieFormData = QueryFormData & labelType: EchartsPieLabelType; labelTemplate: string | null; labelsOutside: boolean; + legendSort: 'asc' | 'desc' | null; metric?: string; outerRadius: number; showLabels: boolean; diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx index 088d5b7ba06..ac8ba387f5d 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx @@ -97,6 +97,24 @@ const legendOrientationControl: ControlSetItem = { }, }; +export const legendSortControl: ControlSetItem = { + name: 'legendSort', + config: { + type: 'SelectControl', + label: t('Sort legend'), + default: null, + renderTrigger: true, + choices: [ + ['asc', t('Label ascending')], + ['desc', t('Label descending')], + [null, t('Sort by data')], + ], + description: t('Changes the sort value of the items in the legend only'), + visibility: ({ controls }: ControlPanelsContainerProps) => + Boolean(controls?.show_legend?.value), + }, +}; + export const legendSection: ControlSetRow[] = [ [{t('Legend')}], [showLegendControl], diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/Pie/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/Pie/transformProps.test.ts index 087f1f49292..00c883d91d9 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/Pie/transformProps.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/Pie/transformProps.test.ts @@ -445,3 +445,103 @@ describe('Other category', () => { expect(data[3].isOther).toBe(true); }); }); + +describe('Sort Legend', () => { + const defaultFormData: SqlaFormData = { + colorScheme: 'bnbColors', + datasource: '3__table', + granularity_sqla: 'ds', + metric: 'metric', + groupby: ['foo', 'bar'], + viz_type: 'my_viz', + }; + + const getChartProps = (formData: Partial) => + new ChartProps({ + formData: { + ...defaultFormData, + ...formData, + }, + width: 800, + height: 600, + queriesData: [ + { + data: [ + { + foo: 'A foo', + bar: 'A bar', + metric: 1, + }, + { + foo: 'D foo', + bar: 'D bar', + metric: 2, + }, + + { + foo: 'C foo', + bar: 'C bar', + metric: 3, + }, + { + foo: 'B foo', + bar: 'B bar', + metric: 4, + }, + + { + foo: 'E foo', + bar: 'E bar', + metric: 5, + }, + ], + }, + ], + theme: supersetTheme, + }); + + it('sort legend by data', () => { + const chartProps = getChartProps({ + legendSort: null, + }); + const transformed = transformProps(chartProps as EchartsPieChartProps); + + expect((transformed.echartOptions.legend as any).data).toEqual([ + 'A foo, A bar', + 'D foo, D bar', + 'C foo, C bar', + 'B foo, B bar', + 'E foo, E bar', + ]); + }); + + it('sort legend by label ascending', () => { + const chartProps = getChartProps({ + legendSort: 'asc', + }); + const transformed = transformProps(chartProps as EchartsPieChartProps); + + expect((transformed.echartOptions.legend as any).data).toEqual([ + 'A foo, A bar', + 'B foo, B bar', + 'C foo, C bar', + 'D foo, D bar', + 'E foo, E bar', + ]); + }); + + it('sort legend by label descending', () => { + const chartProps = getChartProps({ + legendSort: 'desc', + }); + const transformed = transformProps(chartProps as EchartsPieChartProps); + + expect((transformed.echartOptions.legend as any).data).toEqual([ + 'E foo, E bar', + 'D foo, D bar', + 'C foo, C bar', + 'B foo, B bar', + 'A foo, A bar', + ]); + }); +});