feat(plugin-chart-echarts): [feature-parity] support extra control for the area chart V2 (#16493)

* feat(echarts): [feature-parity] support extra control

* add extra control for plugin

* refactor: extract ExtraControl

* fix: lint

* fix some problems
This commit is contained in:
Stephen Liu
2022-06-09 00:59:10 +08:00
committed by GitHub
parent 0238492df7
commit eab0009101
19 changed files with 349 additions and 70 deletions

View File

@@ -34,10 +34,12 @@ import {
} from '../types';
import {
legendSection,
onlyTotalControl,
showValueControl,
richTooltipSection,
showValueSection,
xAxisControl,
} from '../../controls';
import { AreaChartExtraControlsOptions } from '../../constants';
const {
contributionMode,
@@ -132,7 +134,37 @@ const config: ControlPanelConfig = {
},
},
],
...showValueSection,
[showValueControl],
[
{
name: 'stack',
config: {
type: 'SelectControl',
label: t('Stacked Style'),
renderTrigger: true,
choices: AreaChartExtraControlsOptions,
default: null,
description: t('Stack series on top of each other'),
},
},
],
[onlyTotalControl],
[
{
name: 'show_extra_controls',
config: {
type: 'CheckboxControl',
label: t('Extra Controls'),
renderTrigger: true,
default: false,
description: t(
'Whether to show extra controls or not. Extra controls ' +
'include things like making mulitBar charts stacked ' +
'or side by side.',
),
},
},
],
[
{
name: 'markerEnabled',

View File

@@ -24,8 +24,10 @@ import { EchartsHandler, EventHandlers } from '../types';
import Echart from '../components/Echart';
import { TimeseriesChartTransformedProps } from './types';
import { currentSeries } from '../utils/series';
import { ExtraControls } from '../components/ExtraControls';
const TIMER_DURATION = 300;
// @ts-ignore
export default function EchartsTimeseries({
formData,
@@ -36,6 +38,7 @@ export default function EchartsTimeseries({
labelMap,
selectedValues,
setDataMask,
setControlValue,
legendData = [],
}: TimeseriesChartTransformedProps) {
const { emitFilter, stack } = formData;
@@ -120,7 +123,7 @@ export default function EchartsTimeseries({
},
});
},
[groupby, labelMap, setDataMask],
[groupby, labelMap, setDataMask, emitFilter],
);
const eventHandlers: EventHandlers = {
@@ -195,14 +198,17 @@ export default function EchartsTimeseries({
};
return (
<Echart
ref={echartRef}
height={height}
width={width}
echartOptions={echartOptions}
eventHandlers={eventHandlers}
zrEventHandlers={zrEventHandlers}
selectedValues={selectedValues}
/>
<>
<ExtraControls formData={formData} setControlValue={setControlValue} />
<Echart
ref={echartRef}
height={height}
width={width}
echartOptions={echartOptions}
eventHandlers={eventHandlers}
zrEventHandlers={zrEventHandlers}
selectedValues={selectedValues}
/>
</>
);
}

View File

@@ -30,6 +30,7 @@ import {
isIntervalAnnotationLayer,
isTimeseriesAnnotationLayer,
TimeseriesChartDataResponseResult,
t,
} from '@superset-ui/core';
import { isDerivedSeries } from '@superset-ui/chart-controls';
import { EChartsCoreOption, SeriesOption } from 'echarts';
@@ -51,6 +52,8 @@ import {
getAxisType,
getColtypesMapping,
getLegendProps,
extractDataTotalValues,
extractShowValueIndexes,
} from '../utils/series';
import { extractAnnotationLabels } from '../utils/annotation';
import {
@@ -72,7 +75,11 @@ import {
transformSeries,
transformTimeseriesAnnotation,
} from './transformers';
import { TIMESERIES_CONSTANTS, TIMEGRAIN_TO_TIMESTAMP } from '../constants';
import {
AreaChartExtraControlsValue,
TIMESERIES_CONSTANTS,
TIMEGRAIN_TO_TIMESTAMP,
} from '../constants';
export default function transformProps(
chartProps: EchartsTimeseriesChartProps,
@@ -140,46 +147,35 @@ export default function transformProps(
const xAxisCol =
verboseMap[xAxisOrig] || getColumnLabel(xAxisOrig || DTTM_ALIAS);
const isHorizontal = orientation === OrientationType.horizontal;
const { totalStackedValues, thresholdValues } = extractDataTotalValues(
rebasedData,
{
stack,
percentageThreshold,
xAxisCol,
},
);
const rawSeries = extractSeries(rebasedData, {
fillNeighborValue: stack && !forecastEnabled ? 0 : undefined,
xAxis: xAxisCol,
removeNulls: seriesType === EchartsTimeseriesSeriesType.Scatter,
stack,
totalStackedValues,
isHorizontal,
});
const showValueIndexes = extractShowValueIndexes(rawSeries, {
stack,
});
const seriesContexts = extractForecastSeriesContexts(
Object.values(rawSeries).map(series => series.name as string),
);
const isAreaExpand = stack === AreaChartExtraControlsValue.Expand;
const xAxisDataType = dataTypes?.[xAxisCol];
const xAxisType = getAxisType(xAxisDataType);
const series: SeriesOption[] = [];
const formatter = getNumberFormatter(contributionMode ? ',.0%' : yAxisFormat);
const totalStackedValues: number[] = [];
const showValueIndexes: number[] = [];
const thresholdValues: number[] = [];
rebasedData.forEach(data => {
const values = Object.keys(data).reduce((prev, curr) => {
if (curr === xAxisCol) {
return prev;
}
const value = data[curr] || 0;
return prev + (value as number);
}, 0);
totalStackedValues.push(values);
thresholdValues.push(((percentageThreshold || 0) / 100) * values);
});
if (stack) {
rawSeries.forEach((entry, seriesIndex) => {
const { data = [] } = entry;
(data as [Date, number][]).forEach((datum, dataIndex) => {
if (datum[1] !== null) {
showValueIndexes[dataIndex] = seriesIndex;
}
});
});
}
const formatter = getNumberFormatter(
contributionMode || isAreaExpand ? ',.0%' : yAxisFormat,
);
rawSeries.forEach(entry => {
const lineStyle = isDerivedSeries(entry, chartProps.rawFormData)
@@ -266,7 +262,7 @@ export default function transformProps(
let [min, max] = (yAxisBounds || []).map(parseYAxisBound);
// default to 0-100% range when doing row-level contribution chart
if (contributionMode === 'row' && stack) {
if ((contributionMode === 'row' || isAreaExpand) && stack) {
if (min === undefined) min = 0;
if (max === undefined) max = 1;
}
@@ -291,7 +287,10 @@ export default function transformProps(
{},
);
const { setDataMask = () => {} } = hooks;
const {
setDataMask = () => {},
setControlValue = (...args: unknown[]) => {},
} = hooks;
const addYAxisLabelOffset = !!yAxisTitle;
const addXAxisLabelOffset = !!xAxisTitle;
@@ -406,8 +405,8 @@ export default function transformProps(
dataZoom: {
yAxisIndex: false,
title: {
zoom: 'zoom area',
back: 'restore zoom',
zoom: t('zoom area'),
back: t('restore zoom'),
},
},
},
@@ -433,6 +432,7 @@ export default function transformProps(
labelMap,
selectedValues,
setDataMask,
setControlValue,
width,
legendData,
};

View File

@@ -52,7 +52,7 @@ import {
import { MarkLine1DDataItemOption } from 'echarts/types/src/component/marker/MarkLineModel';
import { extractForecastSeriesContext } from '../utils/forecast';
import { ForecastSeriesEnum, LegendOrientation } from '../types';
import { ForecastSeriesEnum, LegendOrientation, StackType } from '../types';
import { EchartsTimeseriesSeriesType } from './types';
import {
@@ -62,7 +62,11 @@ import {
parseAnnotationOpacity,
} from '../utils/annotation';
import { currentSeries, getChartPadding } from '../utils/series';
import { OpacityEnum, TIMESERIES_CONSTANTS } from '../constants';
import {
AreaChartExtraControlsValue,
OpacityEnum,
TIMESERIES_CONSTANTS,
} from '../constants';
export function transformSeries(
series: SeriesOption,
@@ -75,7 +79,7 @@ export function transformSeries(
markerSize?: number;
areaOpacity?: number;
seriesType?: EchartsTimeseriesSeriesType;
stack?: boolean;
stack?: StackType;
yAxisIndex?: number;
showValue?: boolean;
onlyTotal?: boolean;
@@ -225,6 +229,7 @@ export function transformSeries(
const { value, dataIndex, seriesIndex, seriesName } = params;
const numericValue = isHorizontal ? value[0] : value[1];
const isSelectedLegend = currentSeries.legend === seriesName;
const isAreaExpand = stack === AreaChartExtraControlsValue.Expand;
if (!formatter) return numericValue;
if (!stack || isSelectedLegend) return formatter(numericValue);
if (!onlyTotal) {
@@ -234,7 +239,7 @@ export function transformSeries(
return '';
}
if (seriesIndex === showValueIndexes[dataIndex]) {
return formatter(totalStackedValues[dataIndex]);
return formatter(isAreaExpand ? 1 : totalStackedValues[dataIndex]);
}
return '';
},

View File

@@ -31,6 +31,7 @@ import {
EChartTransformedProps,
EchartsTitleFormData,
DEFAULT_TITLE_FORM_DATA,
StackType,
} from '../types';
export enum EchartsTimeseriesContributionType {
@@ -72,7 +73,7 @@ export type EchartsTimeseriesFormData = QueryFormData & {
orderDesc: boolean;
rowLimit: number;
seriesType: EchartsTimeseriesSeriesType;
stack: boolean;
stack: StackType;
tooltipTimeFormat?: string;
truncateYAxis: boolean;
yAxisFormat?: string;
@@ -86,6 +87,7 @@ export type EchartsTimeseriesFormData = QueryFormData & {
groupby: QueryFormColumn[];
showValue: boolean;
onlyTotal: boolean;
showExtraControls: boolean;
percentageThreshold: number;
orientation?: OrientationType;
} & EchartsLegendFormData &