Skip to content

Commit

Permalink
feat(plugin-chart-echarts): add label date format for piechart and bo…
Browse files Browse the repository at this point in the history
…xplot (#973)

* feat(plugin-chart-echarts): add label date format for piechart

* feat(plugin-chart-echarts): add label date format for piechart

* switch to temporal

* Add date format for BoxPlot

* Remove logs

* Revert PERCENTAGE THRESHOLD for pie chart

* type

* add mapping for coltypes & add chart props type for chart

* type

* type

* resolve comments

* Change to formData from rawFormData

Co-authored-by: Victor Malai <victormalai@Victors-MacBook-Pro.local>
  • Loading branch information
2 people authored and zhaoyongjie committed Nov 26, 2021
1 parent 716a962 commit 1c40ac5
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@
* under the License.
*/
import { t } from '@superset-ui/core';
import { D3_FORMAT_OPTIONS, formatSelectOptions, sections } from '@superset-ui/chart-controls';
import {
D3_FORMAT_DOCS,
D3_FORMAT_OPTIONS,
D3_TIME_FORMAT_OPTIONS,
formatSelectOptions,
sections,
} from '@superset-ui/chart-controls';

export default {
controlPanelSections: [
Expand Down Expand Up @@ -86,6 +92,20 @@ export default {
},
},
],
[
{
name: 'date_format',
config: {
type: 'SelectControl',
freeForm: true,
label: t('Date format'),
renderTrigger: true,
choices: D3_TIME_FORMAT_OPTIONS,
default: 'smart_date',
description: D3_FORMAT_DOCS,
},
},
],
],
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ import buildQuery from './buildQuery';
import controlPanel from './controlPanel';
import transformProps from './transformProps';
import thumbnail from './images/thumbnail.png';
import { BoxPlotQueryFormData, EchartsBoxPlotChartProps } from './types';

export default class EchartsBoxPlotChartPlugin extends ChartPlugin {
export default class EchartsBoxPlotChartPlugin extends ChartPlugin<
BoxPlotQueryFormData,
EchartsBoxPlotChartProps
> {
/**
* The constructor is used to pass relevant metadata and callbacks that get
* registered in respective registries that are used throughout the library
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,27 @@
*/
import {
CategoricalColorNamespace,
ChartProps,
DataRecord,
getMetricLabel,
getNumberFormatter,
getTimeFormatter,
} from '@superset-ui/core';
import { EChartsOption, BoxplotSeriesOption } from 'echarts';
import { CallbackDataParams } from 'echarts/types/src/util/types';
import { BoxPlotQueryFormData } from './types';
import { BoxPlotQueryFormData, EchartsBoxPlotChartProps } from './types';
import { EchartsProps } from '../types';
import { extractGroupbyLabel } from '../utils/series';
import { extractGroupbyLabel, getColtypesMapping } from '../utils/series';
import { defaultGrid, defaultTooltip, defaultYAxis } from '../defaults';

export default function transformProps(chartProps: ChartProps): EchartsProps {
export default function transformProps(chartProps: EchartsBoxPlotChartProps): EchartsProps {
const { width, height, formData, queriesData } = chartProps;
const data: DataRecord[] = queriesData[0].data || [];
const { data = [] } = queriesData[0];
const coltypeMapping = getColtypesMapping(queriesData[0]);
const {
colorScheme,
groupby = [],
metrics: formdataMetrics = [],
numberFormat,
dateFormat,
xTicksLayout,
} = formData as BoxPlotQueryFormData;
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
Expand All @@ -46,7 +47,12 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {

const transformedData = data
.map((datum: any) => {
const groupbyLabel = extractGroupbyLabel({ datum, groupby });
const groupbyLabel = extractGroupbyLabel({
datum,
groupby,
coltypeMapping,
timeFormatter: getTimeFormatter(dateFormat),
});
return metricLabels.map(metric => {
const name = metricLabels.length === 1 ? groupbyLabel : `${groupbyLabel}, ${metric}`;
return {
Expand All @@ -70,11 +76,15 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
});
})
.flatMap(row => row);

const outlierData = data
.map(datum =>
metricLabels.map(metric => {
const groupbyLabel = extractGroupbyLabel({ datum, groupby });
const groupbyLabel = extractGroupbyLabel({
datum,
groupby,
coltypeMapping,
timeFormatter: getTimeFormatter(dateFormat),
});
const name = metricLabels.length === 1 ? groupbyLabel : `${groupbyLabel}, ${metric}`;
// Outlier data is a nested array of numbers (uncommon, therefore no need to add to DataRecordValue)
const outlierDatum = (datum[`${metric}__outliers`] || []) as number[];
Expand All @@ -96,7 +106,6 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
}),
)
.flat(2);

let axisLabel;
if (xTicksLayout === '45°') axisLabel = { rotate: -45 };
else if (xTicksLayout === '90°') axisLabel = { rotate: -90 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { QueryFormData } from '@superset-ui/core';
import { ChartDataResponseResult, ChartProps, QueryFormData } from '@superset-ui/core';
import { PostProcessingBoxplot } from '@superset-ui/core/lib/query/types/PostProcessing';

export type BoxPlotQueryFormData = QueryFormData & {
Expand All @@ -33,4 +33,9 @@ export type BoxPlotFormDataWhiskerOptions =

export type BoxPlotFormXTickLayout = '45°' | '90°' | 'auto' | 'flat' | 'staggered';

export interface EchartsBoxPlotChartProps extends ChartProps {
formData: BoxPlotQueryFormData;
queriesData: ChartDataResponseResult[];
}

export type BoxPlotQueryObjectWhiskerType = PostProcessingBoxplot['options']['whisker_type'];
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
*/
import React from 'react';
import { t, validateNonEmpty } from '@superset-ui/core';
import { ControlPanelConfig, D3_FORMAT_OPTIONS, sections } from '@superset-ui/chart-controls';
import {
ControlPanelConfig,
D3_FORMAT_DOCS,
D3_FORMAT_OPTIONS,
D3_TIME_FORMAT_OPTIONS,
sections,
} from '@superset-ui/chart-controls';
import { DEFAULT_FORM_DATA } from './types';
import {
legendMarginControl,
Expand Down Expand Up @@ -66,6 +72,19 @@ const config: ControlPanelConfig = {
expanded: true,
controlSetRows: [
['color_scheme'],
[
{
name: 'show_labels_threshold',
config: {
type: 'TextControl',
label: t('Percentage threshold'),
renderTrigger: true,
isFloat: true,
default: 5,
description: t('Minimum threshold in percentage points for showing labels.'),
},
},
],
// eslint-disable-next-line react/jsx-key
[<h1 className="section-header">{t('Legend')}</h1>],
[showLegendControl],
Expand Down Expand Up @@ -110,6 +129,20 @@ const config: ControlPanelConfig = {
},
},
],
[
{
name: 'date_format',
config: {
type: 'SelectControl',
freeForm: true,
label: t('Date format'),
renderTrigger: true,
choices: D3_TIME_FORMAT_OPTIONS,
default: 'smart_date',
description: D3_FORMAT_DOCS,
},
},
],
[
{
name: 'show_labels',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ import buildQuery from './buildQuery';
import controlPanel from './controlPanel';
import transformProps from './transformProps';
import thumbnail from './images/thumbnail.png';
import { EchartsPieChartProps, EchartsPieFormData } from './types';

export default class EchartsPieChartPlugin extends ChartPlugin {
export default class EchartsPieChartPlugin extends ChartPlugin<
EchartsPieFormData,
EchartsPieChartProps
> {
/**
* The constructor is used to pass relevant metadata and callbacks that get
* registered in respective registries that are used throughout the library
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,27 @@
*/
import {
CategoricalColorNamespace,
ChartProps,
DataRecord,
getMetricLabel,
getNumberFormatter,
getTimeFormatter,
NumberFormats,
NumberFormatter,
} from '@superset-ui/core';
import { CallbackDataParams } from 'echarts/types/src/util/types';
import { EChartsOption, PieSeriesOption } from 'echarts';
import {
DEFAULT_FORM_DATA as DEFAULT_PIE_FORM_DATA,
EchartsPieChartProps,
EchartsPieFormData,
EchartsPieLabelType,
} from './types';
import { DEFAULT_LEGEND_FORM_DATA, EchartsProps } from '../types';
import { extractGroupbyLabel, getChartPadding, getLegendProps } from '../utils/series';
import {
extractGroupbyLabel,
getChartPadding,
getColtypesMapping,
getLegendProps,
} from '../utils/series';
import { defaultGrid, defaultTooltip } from '../defaults';

const percentFormatter = getNumberFormatter(NumberFormats.PERCENT_2_POINT);
Expand All @@ -50,6 +55,7 @@ export function formatPieLabel({
const { name = '', value, percent } = params;
const formattedValue = numberFormatter(value as number);
const formattedPercent = percentFormatter((percent as number) / 100);

switch (labelType) {
case EchartsPieLabelType.Key:
return name;
Expand All @@ -68,9 +74,10 @@ export function formatPieLabel({
}
}

export default function transformProps(chartProps: ChartProps): EchartsProps {
export default function transformProps(chartProps: EchartsPieChartProps): EchartsProps {
const { width, height, formData, queriesData } = chartProps;
const data: DataRecord[] = queriesData[0].data || [];
const { data = [] } = queriesData[0];
const coltypeMapping = getColtypesMapping(queriesData[0]);

const {
colorScheme,
Expand All @@ -85,18 +92,34 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
legendType,
metric = '',
numberFormat,
dateFormat,
outerRadius,
showLabels,
showLegend,
showLabelsThreshold,
}: EchartsPieFormData = { ...DEFAULT_LEGEND_FORM_DATA, ...DEFAULT_PIE_FORM_DATA, ...formData };
const metricLabel = getMetricLabel(metric);

const keys = data.map(datum => extractGroupbyLabel({ datum, groupby }));
const keys = data.map(datum =>
extractGroupbyLabel({
datum,
groupby,
coltypeMapping,
timeFormatter: getTimeFormatter(dateFormat),
}),
);

const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
const numberFormatter = getNumberFormatter(numberFormat);

const transformedData: PieSeriesOption[] = data.map(datum => {
const name = extractGroupbyLabel({ datum, groupby });
const name = extractGroupbyLabel({
datum,
groupby,
coltypeMapping,
timeFormatter: getTimeFormatter(dateFormat),
});

return {
value: datum[metricLabel],
name,
Expand All @@ -106,8 +129,15 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
};
});

const formatter = (params: CallbackDataParams) =>
formatPieLabel({ params, numberFormatter, labelType });
const formatter = (params: CallbackDataParams) => {
if (params.percent && params.percent < showLabelsThreshold) return '';

return formatPieLabel({
params,
numberFormatter,
labelType,
});
};

const defaultLabel = {
formatter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,30 @@
* specific language governing permissions and limitations
* under the License.
*/
import { ChartDataResponseResult, ChartProps, QueryFormData } from '@superset-ui/core';
import {
DEFAULT_LEGEND_FORM_DATA,
EchartsLegendFormData,
LegendOrientation,
LegendType,
} from '../types';

export type EchartsPieFormData = EchartsLegendFormData & {
colorScheme?: string;
donut: boolean;
groupby: string[];
innerRadius: number;
labelLine: boolean;
labelType: EchartsPieLabelType;
labelsOutside: boolean;
metric?: string;
outerRadius: number;
showLabels: boolean;
numberFormat: string;
};
export type EchartsPieFormData = QueryFormData &
EchartsLegendFormData & {
colorScheme?: string;
donut: boolean;
groupby: string[];
innerRadius: number;
labelLine: boolean;
labelType: EchartsPieLabelType;
labelsOutside: boolean;
metric?: string;
outerRadius: number;
showLabels: boolean;
numberFormat: string;
dateFormat: string;
showLabelsThreshold: number;
};

export enum EchartsPieLabelType {
Key = 'key',
Expand All @@ -46,6 +50,12 @@ export enum EchartsPieLabelType {
KeyValuePercent = 'key_value_percent',
}

export interface EchartsPieChartProps extends ChartProps {
formData: EchartsPieFormData;
queriesData: ChartDataResponseResult[];
}

// @ts-ignore
export const DEFAULT_FORM_DATA: EchartsPieFormData = {
...DEFAULT_LEGEND_FORM_DATA,
donut: false,
Expand All @@ -59,4 +69,6 @@ export const DEFAULT_FORM_DATA: EchartsPieFormData = {
outerRadius: 70,
showLabels: true,
labelsOutside: true,
showLabelsThreshold: 5,
dateFormat: 'smart_date',
};
Loading

0 comments on commit 1c40ac5

Please sign in to comment.