diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/EchartsMixedTimeseries.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/EchartsMixedTimeseries.tsx
index 71c66d2e5853b..ae1a1f3c70e86 100644
--- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/EchartsMixedTimeseries.tsx
+++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/EchartsMixedTimeseries.tsx
@@ -16,10 +16,92 @@
* specific language governing permissions and limitations
* under the License.
*/
-import React from 'react';
-import { EchartsProps } from '../types';
+import React, { useCallback } from 'react';
+import { EchartsMixedTimeseriesChartTransformedProps } from './types';
import Echart from '../components/Echart';
+import { EventHandlers } from '../types';
-export default function EchartsMixedTimeseries({ height, width, echartOptions }: EchartsProps) {
- return ;
+export default function EchartsMixedTimeseries({
+ height,
+ width,
+ echartOptions,
+ setDataMask,
+ labelMap,
+ labelMapB,
+ groupby,
+ groupbyB,
+ selectedValues,
+ formData,
+ seriesBreakdown,
+}: EchartsMixedTimeseriesChartTransformedProps) {
+ const isFirstQuery = useCallback((seriesIndex: number) => seriesIndex < seriesBreakdown, [
+ seriesBreakdown,
+ ]);
+
+ const handleChange = useCallback(
+ (values: string[], seriesIndex: number) => {
+ const emitFilter = isFirstQuery(seriesIndex) ? formData.emitFilter : formData.emitFilterB;
+ if (!emitFilter) {
+ return;
+ }
+
+ const currentGroupBy = isFirstQuery(seriesIndex) ? groupby : groupbyB;
+ const currentLabelMap = isFirstQuery(seriesIndex) ? labelMap : labelMapB;
+ const groupbyValues = values.map(value => currentLabelMap[value]).filter(value => !!value);
+
+ setDataMask({
+ extraFormData: {
+ // @ts-ignore
+ filters:
+ values.length === 0
+ ? []
+ : [
+ ...currentGroupBy.map((col, idx) => {
+ const val = groupbyValues.map(v => v[idx]);
+ if (val === null || val === undefined)
+ return {
+ col,
+ op: 'IS NULL',
+ };
+ return {
+ col,
+ op: 'IN',
+ val: val as (string | number | boolean)[],
+ };
+ }),
+ ],
+ },
+ filterState: {
+ value: !groupbyValues.length ? null : groupbyValues,
+ selectedValues: values.length ? values : null,
+ },
+ });
+ },
+ [groupby, groupbyB, labelMap, labelMapB, setDataMask, selectedValues],
+ );
+
+ const eventHandlers: EventHandlers = {
+ click: props => {
+ const { seriesName, seriesIndex } = props;
+ const values: string[] = Object.values(selectedValues);
+ if (values.includes(seriesName)) {
+ handleChange(
+ values.filter(v => v !== seriesName),
+ seriesIndex,
+ );
+ } else {
+ handleChange([seriesName], seriesIndex);
+ }
+ },
+ };
+
+ return (
+
+ );
}
diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
index 11d91f862a6ca..7f3f03d88bb61 100644
--- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
+++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
@@ -22,6 +22,7 @@ import {
ControlPanelConfig,
ControlPanelSectionConfig,
ControlSetRow,
+ emitFilterControl,
sections,
sharedControls,
} from '@superset-ui/chart-controls';
@@ -72,6 +73,14 @@ function createQuerySection(label: string, controlSuffix: string): ControlPanelS
config: sharedControls.adhoc_filters,
},
],
+ emitFilterControl.length > 0
+ ? [
+ {
+ ...emitFilterControl[0],
+ name: `emit_filter${controlSuffix}`,
+ },
+ ]
+ : [],
[
{
name: `limit${controlSuffix}`,
diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/index.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/index.ts
index a4158966b113f..a96487c8eec1b 100644
--- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/index.ts
+++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/index.ts
@@ -16,13 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { t, ChartMetadata, ChartPlugin, AnnotationType } from '@superset-ui/core';
+import { t, ChartMetadata, ChartPlugin, AnnotationType, Behavior } from '@superset-ui/core';
import buildQuery from './buildQuery';
import controlPanel from './controlPanel';
import transformProps from './transformProps';
import thumbnail from './images/thumbnail.png';
+import { EchartsMixedTimeseriesProps, EchartsMixedTimeseriesFormData } from './types';
-export default class EchartsTimeseriesChartPlugin extends ChartPlugin {
+export default class EchartsTimeseriesChartPlugin extends ChartPlugin<
+ EchartsMixedTimeseriesFormData,
+ EchartsMixedTimeseriesProps
+> {
/**
* The constructor is used to pass relevant metadata and callbacks that get
* registered in respective registries that are used throughout the library
@@ -39,6 +43,7 @@ export default class EchartsTimeseriesChartPlugin extends ChartPlugin {
controlPanel,
loadChart: () => import('./EchartsMixedTimeseries'),
metadata: new ChartMetadata({
+ behaviors: [Behavior.INTERACTIVE_CHART],
category: t('Evolution'),
credits: ['https://echarts.apache.org'],
description: t(
@@ -64,6 +69,7 @@ export default class EchartsTimeseriesChartPlugin extends ChartPlugin {
t('Transformable'),
],
}),
+ // @ts-ignore
transformProps,
});
}
diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
index 8079b0ddfa2c6..636921ee43571 100644
--- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
+++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
@@ -20,7 +20,8 @@
import {
AnnotationLayer,
CategoricalColorNamespace,
- ChartProps,
+ DataRecordValue,
+ TimeseriesDataRecord,
getNumberFormatter,
isEventAnnotationLayer,
isFormulaAnnotationLayer,
@@ -28,8 +29,12 @@ import {
isTimeseriesAnnotationLayer,
} from '@superset-ui/core';
import { EChartsOption, SeriesOption } from 'echarts';
-import { DEFAULT_FORM_DATA, EchartsMixedTimeseriesFormData } from './types';
-import { EchartsProps, ForecastSeriesEnum, ProphetValue } from '../types';
+import {
+ DEFAULT_FORM_DATA,
+ EchartsMixedTimeseriesFormData,
+ EchartsMixedTimeseriesChartTransformedProps,
+} from './types';
+import { ForecastSeriesEnum, ProphetValue } from '../types';
import { parseYAxisBound } from '../utils/controls';
import { dedupSeries, extractTimeseriesSeries, getLegendProps } from '../utils/series';
import { extractAnnotationLabels } from '../utils/annotation';
@@ -52,11 +57,14 @@ import {
} from '../Timeseries/transformers';
import { TIMESERIES_CONSTANTS } from '../constants';
-export default function transformProps(chartProps: ChartProps): EchartsProps {
- const { width, height, formData, queriesData } = chartProps;
- const { annotation_data: annotationData_, data: data1 = [] } = queriesData[0];
- const { data: data2 = [] } = queriesData[1];
+export default function transformProps(
+ chartProps: EchartsMixedTimeseriesFormData,
+): EchartsMixedTimeseriesChartTransformedProps {
+ const { width, height, formData, queriesData, hooks, filterState } = chartProps;
+ const { annotation_data: annotationData_ } = queriesData[0];
const annotationData = annotationData_ || {};
+ const data1: TimeseriesDataRecord[] = queriesData[0].data || [];
+ const data2: TimeseriesDataRecord[] = queriesData[1].data || [];
const {
area,
@@ -95,6 +103,10 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
zoomable,
richTooltip,
xAxisLabelRotation,
+ groupby,
+ groupbyB,
+ emitFilter,
+ emitFilterB,
}: EchartsMixedTimeseriesFormData = { ...DEFAULT_FORM_DATA, ...formData };
const colorScale = CategoricalColorNamespace.getScale(colorScheme as string);
@@ -130,6 +142,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
seriesType,
stack,
yAxisIndex,
+ filterState,
});
if (transformedSeries) series.push(transformedSeries);
});
@@ -142,6 +155,7 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
seriesType: seriesTypeB,
stack: stackB,
yAxisIndex: yAxisIndexB,
+ filterState,
});
if (transformedSeries) series.push(transformedSeries);
});
@@ -174,6 +188,25 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
const addYAxisLabelOffset = !!(yAxisTitle || yAxisTitleSecondary);
const chartPadding = getPadding(showLegend, legendOrientation, addYAxisLabelOffset, zoomable);
+
+ const labelMap = rawSeriesA.reduce((acc, datum) => {
+ const label = datum.name as string;
+ return {
+ ...acc,
+ [label]: label.split(', '),
+ };
+ }, {}) as Record;
+
+ const labelMapB = rawSeriesB.reduce((acc, datum) => {
+ const label = datum.name as string;
+ return {
+ ...acc,
+ [label]: label.split(', '),
+ };
+ }, {}) as Record;
+
+ const { setDataMask = () => {} } = hooks;
+
const echartOptions: EChartsOption = {
useUTC: true,
grid: {
@@ -280,8 +313,18 @@ export default function transformProps(chartProps: ChartProps): EchartsProps {
};
return {
- echartOptions,
+ formData,
width,
height,
+ echartOptions,
+ setDataMask,
+ emitFilter,
+ emitFilterB,
+ labelMap,
+ labelMapB,
+ groupby,
+ groupbyB,
+ seriesBreakdown: rawSeriesA.length,
+ selectedValues: filterState.selectedValues || [],
};
}
diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts
index 1b30ba185619b..16908835f588c 100644
--- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts
+++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts
@@ -16,7 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { AnnotationLayer, TimeGranularity } from '@superset-ui/core';
+import { EChartsOption } from 'echarts';
+import {
+ AnnotationLayer,
+ TimeGranularity,
+ DataRecordValue,
+ SetDataMaskHook,
+ QueryFormData,
+ ChartProps,
+ ChartDataResponseResult,
+} from '@superset-ui/core';
import { DEFAULT_LEGEND_FORM_DATA, EchartsLegendFormData } from '../types';
import {
DEFAULT_FORM_DATA as TIMESERIES_DEFAULTS,
@@ -24,7 +33,7 @@ import {
EchartsTimeseriesSeriesType,
} from '../Timeseries/types';
-export type EchartsMixedTimeseriesFormData = {
+export type EchartsMixedTimeseriesFormData = QueryFormData & {
annotationLayers: AnnotationLayer[];
// shared properties
minorSplitLine: boolean;
@@ -68,8 +77,12 @@ export type EchartsMixedTimeseriesFormData = {
stackB: boolean;
yAxisIndex?: number;
yAxisIndexB?: number;
+ groupby: string[];
+ groupbyB: string[];
+ emitFilter: boolean;
} & EchartsLegendFormData;
+// @ts-ignore
export const DEFAULT_FORM_DATA: EchartsMixedTimeseriesFormData = {
...DEFAULT_LEGEND_FORM_DATA,
annotationLayers: [],
@@ -104,9 +117,32 @@ export const DEFAULT_FORM_DATA: EchartsMixedTimeseriesFormData = {
stackB: TIMESERIES_DEFAULTS.stack,
yAxisIndex: 0,
yAxisIndexB: 0,
+ groupby: [],
+ groupbyB: [],
xAxisShowMinLabel: TIMESERIES_DEFAULTS.xAxisShowMinLabel,
xAxisShowMaxLabel: TIMESERIES_DEFAULTS.xAxisShowMaxLabel,
zoomable: TIMESERIES_DEFAULTS.zoomable,
richTooltip: TIMESERIES_DEFAULTS.richTooltip,
xAxisLabelRotation: TIMESERIES_DEFAULTS.xAxisLabelRotation,
};
+
+export interface EchartsMixedTimeseriesProps extends ChartProps {
+ formData: EchartsMixedTimeseriesFormData;
+ queriesData: ChartDataResponseResult[];
+}
+
+export type EchartsMixedTimeseriesChartTransformedProps = {
+ formData: EchartsMixedTimeseriesFormData;
+ height: number;
+ width: number;
+ echartOptions: EChartsOption;
+ emitFilter: boolean;
+ emitFilterB: boolean;
+ setDataMask: SetDataMaskHook;
+ groupby: string[];
+ groupbyB: string[];
+ labelMap: Record;
+ labelMapB: Record;
+ selectedValues: Record;
+ seriesBreakdown: number;
+};