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',
+ ]);
+ });
+});