mirror of
https://github.com/apache/superset.git
synced 2026-04-21 17:14:57 +00:00
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:
@@ -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',
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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 '';
|
||||
},
|
||||
|
||||
@@ -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 &
|
||||
|
||||
Reference in New Issue
Block a user