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 aab4af54585b4..c195c5e2214d9 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/controlPanel.tsx
@@ -183,6 +183,18 @@ const config: ControlPanelConfig = {
},
},
],
+ [
+ {
+ name: 'show_total',
+ config: {
+ type: 'CheckboxControl',
+ label: t('Show Total'),
+ default: false,
+ renderTrigger: true,
+ description: t('Whether to display the aggregate count'),
+ },
+ },
+ ],
// eslint-disable-next-line react/jsx-key
[
{t('Pie shape')}
],
[
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 237f4ae001f70..aeeec088b05c4 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts
@@ -25,6 +25,7 @@ import {
getTimeFormatter,
NumberFormats,
NumberFormatter,
+ t,
} from '@superset-ui/core';
import { CallbackDataParams } from 'echarts/types/src/util/types';
import { EChartsCoreOption, PieSeriesOption } from 'echarts';
@@ -45,6 +46,7 @@ import {
} from '../utils/series';
import { defaultGrid, defaultTooltip } from '../defaults';
import { OpacityEnum } from '../constants';
+import { convertInteger } from '../utils/convertInteger';
const percentFormatter = getNumberFormatter(NumberFormats.PERCENT_2_POINT);
@@ -82,6 +84,54 @@ export function formatPieLabel({
}
}
+function getTotalValuePadding({
+ chartPadding,
+ donut,
+ width,
+ height,
+}: {
+ chartPadding: {
+ bottom: number;
+ left: number;
+ right: number;
+ top: number;
+ };
+ donut: boolean;
+ width: number;
+ height: number;
+}) {
+ const padding: {
+ left?: string;
+ top?: string;
+ } = {
+ top: donut ? 'middle' : '0',
+ left: 'center',
+ };
+ const LEGEND_HEIGHT = 15;
+ const LEGEND_WIDTH = 215;
+ if (chartPadding.top) {
+ padding.top = donut
+ ? `${50 + ((chartPadding.top - LEGEND_HEIGHT) / height / 2) * 100}%`
+ : `${((chartPadding.top + LEGEND_HEIGHT) / height) * 100}%`;
+ }
+ if (chartPadding.bottom) {
+ padding.top = donut
+ ? `${50 - ((chartPadding.bottom + LEGEND_HEIGHT) / height / 2) * 100}%`
+ : '0';
+ }
+ if (chartPadding.left) {
+ padding.left = `${
+ 50 + ((chartPadding.left - LEGEND_WIDTH) / width / 2) * 100
+ }%`;
+ }
+ if (chartPadding.right) {
+ padding.left = `${
+ 50 - ((chartPadding.right + LEGEND_WIDTH) / width / 2) * 100
+ }%`;
+ }
+ return padding;
+}
+
export default function transformProps(
chartProps: EchartsPieChartProps,
): PieChartTransformedProps {
@@ -110,6 +160,7 @@ export default function transformProps(
showLabelsThreshold,
emitFilter,
sliceId,
+ showTotal,
}: EchartsPieFormData = {
...DEFAULT_LEGEND_FORM_DATA,
...DEFAULT_PIE_FORM_DATA,
@@ -147,6 +198,7 @@ export default function transformProps(
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
const numberFormatter = getNumberFormatter(numberFormat);
+ let totalValue = 0;
const transformedData: PieSeriesOption[] = data.map(datum => {
const name = extractGroupbyLabel({
@@ -158,9 +210,14 @@ export default function transformProps(
const isFiltered =
filterState.selectedValues && !filterState.selectedValues.includes(name);
+ const value = datum[metricLabel];
+
+ if (typeof value === 'number' || typeof value === 'string') {
+ totalValue += convertInteger(value);
+ }
return {
- value: datum[metricLabel],
+ value,
name,
itemStyle: {
color: colorFn(name, sliceId),
@@ -197,10 +254,16 @@ export default function transformProps(
color: '#000000',
};
+ const chartPadding = getChartPadding(
+ showLegend,
+ legendOrientation,
+ legendMargin,
+ );
+
const series: PieSeriesOption[] = [
{
type: 'pie',
- ...getChartPadding(showLegend, legendOrientation, legendMargin),
+ ...chartPadding,
animation: false,
radius: [`${donut ? innerRadius : 0}%`, `${outerRadius}%`],
center: ['50%', '50%'],
@@ -248,6 +311,18 @@ export default function transformProps(
...getLegendProps(legendType, legendOrientation, showLegend),
data: keys,
},
+ graphic: showTotal
+ ? {
+ type: 'text',
+ ...getTotalValuePadding({ chartPadding, donut, width, height }),
+ style: {
+ text: t(`Total: ${numberFormatter(totalValue)}`),
+ fontSize: 16,
+ fontWeight: 'bold',
+ },
+ z: 10,
+ }
+ : null,
series,
};