Skip to content

Commit

Permalink
feat(plugin-chart-echarts): add legend customization options (apache#833
Browse files Browse the repository at this point in the history
)
  • Loading branch information
villebro authored and zhaoyongjie committed Nov 25, 2021
1 parent b24d8a5 commit 20ee4af
Show file tree
Hide file tree
Showing 13 changed files with 485 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ export const WeekdayPie = ({ width, height }) => {
numberFormat: 'SMART_NUMBER',
donut: boolean('Donut', false),
innerRadius: number('Inner Radius', 30),
outerRadius: number('Outer Radius', 50),
outerRadius: number('Outer Radius', 70),
labelsOutside: boolean('Labels outside', true),
labelLine: boolean('Label line', true),
showLabels: boolean('Show labels', true),
showLegend: boolean('Show legend', false),
pieLabelType: select(
labelType: select(
'Pie label type',
['key', 'value', 'percent', 'key_value', 'key_percent', 'key_value_percent'],
'key_value_percent',
'key',
),
}}
/>
Expand All @@ -58,15 +58,15 @@ export const PopulationPie = ({ width, height }) => {
numberFormat: 'SMART_NUMBER',
donut: boolean('Donut', false),
innerRadius: number('Inner Radius', 30),
outerRadius: number('Outer Radius', 50),
outerRadius: number('Outer Radius', 70),
labelsOutside: boolean('Labels outside', false),
labelLine: boolean('Label line', false),
labelLine: boolean('Label line', true),
showLabels: boolean('Show labels', true),
showLegend: boolean('Show legend', false),
pieLabelType: select(
labelType: select(
'Pie label type',
['key', 'value', 'percent', 'key_value', 'key_percent', 'key_value_percent'],
'key_value_percent',
'key',
),
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,27 @@
* specific language governing permissions and limitations
* under the License.
*/
import React from 'react';
import { t, validateNonEmpty } from '@superset-ui/core';
import { ControlPanelConfig, D3_FORMAT_OPTIONS, sections } from '@superset-ui/chart-controls';
import { DEFAULT_FORM_DATA } from './types';
import {
legendMarginControl,
legendOrientationControl,
legendTypeControl,
showLegendControl,
} from '../controls';

const {
donut,
innerRadius,
labelsOutside,
labelType,
labelLine,
outerRadius,
numberFormat,
showLabels,
} = DEFAULT_FORM_DATA;

const noopControl = { name: 'noop', config: { type: '', renderTrigger: true } };

Expand All @@ -33,13 +52,21 @@ const config: ControlPanelConfig = {
label: t('Chart Options'),
expanded: true,
controlSetRows: [
['color_scheme', noopControl],
// eslint-disable-next-line react/jsx-key
[<h1 className="section-header">{t('Legend')}</h1>],
[showLegendControl],
[legendTypeControl, legendOrientationControl],
[legendMarginControl, noopControl],
// eslint-disable-next-line react/jsx-key
[<h1 className="section-header">{t('Labels')}</h1>],
[
{
name: 'pie_label_type',
config: {
type: 'SelectControl',
label: t('Label Type'),
default: 'key',
default: labelType,
renderTrigger: true,
choices: [
['key', 'Category Name'],
Expand All @@ -59,44 +86,22 @@ const config: ControlPanelConfig = {
freeForm: true,
label: t('Number format'),
renderTrigger: true,
default: 'SMART_NUMBER',
default: numberFormat,
choices: D3_FORMAT_OPTIONS,
description: `${t('D3 format syntax: https://github.com/d3/d3-format')} ${t(
'Only applies when "Label Type" is set to show values.',
)}`,
},
},
],
[
{
name: 'donut',
config: {
type: 'CheckboxControl',
label: t('Donut'),
default: false,
renderTrigger: true,
description: t('Do you want a donut or a pie?'),
},
},
{
name: 'show_legend',
config: {
type: 'CheckboxControl',
label: t('Legend'),
renderTrigger: true,
default: true,
description: t('Whether to display a legend for the chart'),
},
},
],
[
{
name: 'show_labels',
config: {
type: 'CheckboxControl',
label: t('Show Labels'),
renderTrigger: true,
default: true,
default: showLabels,
description: t('Whether to display the labels.'),
},
},
Expand All @@ -107,7 +112,7 @@ const config: ControlPanelConfig = {
config: {
type: 'CheckboxControl',
label: t('Put labels outside'),
default: true,
default: labelsOutside,
renderTrigger: true,
description: t('Put the labels outside of the pie?'),
},
Expand All @@ -117,13 +122,14 @@ const config: ControlPanelConfig = {
config: {
type: 'CheckboxControl',
label: t('Label Line'),
default: false,
default: labelLine,
renderTrigger: true,
description: t('Draw line from Pie to label when labels outside?'),
},
},
],
['color_scheme', noopControl],
// eslint-disable-next-line react/jsx-key
[<h1 className="section-header">{t('Pie shape')}</h1>],
[
{
name: 'outerRadius',
Expand All @@ -134,10 +140,23 @@ const config: ControlPanelConfig = {
min: 10,
max: 100,
step: 1,
default: 80,
default: outerRadius,
description: t('Outer edge of Pie chart'),
},
},
noopControl,
],
[
{
name: 'donut',
config: {
type: 'CheckboxControl',
label: t('Donut'),
default: donut,
renderTrigger: true,
description: t('Do you want a donut or a pie?'),
},
},
],
[
{
Expand All @@ -149,10 +168,11 @@ const config: ControlPanelConfig = {
min: 0,
max: 100,
step: 1,
default: 30,
default: innerRadius,
description: t('Inner radius of donut hole'),
},
},
noopControl,
],
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,51 @@
import {
CategoricalColorNamespace,
ChartProps,
getMetricLabel,
DataRecord,
getMetricLabel,
getNumberFormatter,
NumberFormats,
NumberFormatter,
} from '@superset-ui/core';
import { EchartsPieLabelType, PieChartFormData } from './types';
import { EchartsProps } from '../types';
import { extractGroupbyLabel } from '../utils/series';
import {
DEFAULT_FORM_DATA as DEFAULT_PIE_FORM_DATA,
EchartsPieFormData,
EchartsPieLabelType,
} from './types';
import { DEFAULT_LEGEND_FORM_DATA, EchartsProps } from '../types';
import { extractGroupbyLabel, getChartPadding, getLegendProps } from '../utils/series';
import { defaultGrid, defaultTooltip } from '../defaults';

const percentFormatter = getNumberFormatter(NumberFormats.PERCENT_2_POINT);

export function formatPieLabel({
params,
pieLabelType,
labelType,
numberFormatter,
}: {
params: echarts.EChartOption.Tooltip.Format;
pieLabelType: EchartsPieLabelType;
labelType: EchartsPieLabelType;
numberFormatter: NumberFormatter;
}): string {
const { name = '', value, percent } = params;
const formattedValue = numberFormatter(value as number);
const formattedPercent = percentFormatter((percent as number) / 100);
if (pieLabelType === 'key') return name;
if (pieLabelType === 'value') return formattedValue;
if (pieLabelType === 'percent') return formattedPercent;
if (pieLabelType === 'key_value') return `${name}: ${formattedValue}`;
if (pieLabelType === 'key_value_percent')
return `${name}: ${formattedValue} (${formattedPercent})`;
if (pieLabelType === 'key_percent') return `${name}: ${formattedPercent}`;
return name;
switch (labelType) {
case EchartsPieLabelType.Key:
return name;
case EchartsPieLabelType.Value:
return formattedValue;
case EchartsPieLabelType.Percent:
return formattedPercent;
case EchartsPieLabelType.KeyValue:
return `${name}: ${formattedValue}`;
case EchartsPieLabelType.KeyValuePercent:
return `${name}: ${formattedValue} (${formattedPercent})`;
case EchartsPieLabelType.KeyPercent:
return `${name}: ${formattedPercent}`;
default:
return name;
}
}

export default function transformProps(chartProps: ChartProps): EchartsProps {
Expand All @@ -60,19 +72,23 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {

const {
colorScheme,
donut = false,
donut,
groupby,
innerRadius = 30,
labelsOutside = true,
labelLine = false,
metric,
innerRadius,
labelsOutside,
labelLine,
labelType,
legendMargin,
legendOrientation,
legendType,
metric = '',
numberFormat,
outerRadius = 80,
pieLabelType = 'value',
showLabels = true,
showLegend = false,
} = formData as PieChartFormData;
outerRadius,
showLabels,
showLegend,
}: EchartsPieFormData = { ...DEFAULT_LEGEND_FORM_DATA, ...DEFAULT_PIE_FORM_DATA, ...formData };
const metricLabel = getMetricLabel(metric);

const keys = data.map(datum => extractGroupbyLabel({ datum, groupby }));
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
const numberFormatter = getNumberFormatter(numberFormat);
Expand All @@ -89,7 +105,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
});

const formatter = (params: { name: string; value: number; percent: number }) =>
formatPieLabel({ params, numberFormatter, pieLabelType });
formatPieLabel({ params, numberFormatter, labelType });

const defaultLabel = {
formatter,
Expand All @@ -100,10 +116,6 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
const echartOptions: echarts.EChartOption<echarts.EChartOption.SeriesPie> = {
grid: {
...defaultGrid,
top: 30,
bottom: 30,
left: 30,
right: 30,
},
tooltip: {
...defaultTooltip,
Expand All @@ -112,19 +124,17 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
formatPieLabel({
params: params as echarts.EChartOption.Tooltip.Format,
numberFormatter,
pieLabelType: 'key_value_percent',
labelType: EchartsPieLabelType.KeyValuePercent,
}),
},
legend: showLegend
? {
orient: 'horizontal',
left: 10,
data: keys,
}
: undefined,
legend: {
...getLegendProps(legendType, legendOrientation, showLegend),
data: keys,
},
series: [
{
type: 'pie',
...getChartPadding(showLegend, legendOrientation, legendMargin),
animation: false,
radius: [`${donut ? innerRadius : 0}%`, `${outerRadius}%`],
center: ['50%', '50%'],
Expand All @@ -145,6 +155,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
label: {
show: true,
fontWeight: 'bold',
backgroundColor: 'white',
},
},
// @ts-ignore
Expand Down
Loading

0 comments on commit 20ee4af

Please sign in to comment.