This is an automated email from the ASF dual-hosted git repository. sophieyou pushed a commit to branch mixed-chart-tooltip-query-control in repository https://gitbox.apache.org/repos/asf/superset.git
commit 5f390a1d5ea35ba5969d7e792e49afbf36cb1b9b Author: yousoph <[email protected]> AuthorDate: Tue Jul 29 23:50:44 2025 +0000 feat: add optional query identifiers to mixed timeseries charts - Add 'Show query identifiers' checkbox control to MixedTimeseries chart - Control appears above Rich tooltip in the Tooltip section - Default behavior: unchecked (no Query A/B identifiers shown) - When checked: adds (Query A) and (Query B) to legend and series names - Updates legend to use transformed series names instead of raw names - Conditional logic based on show_query_identifiers form data 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> --- .../src/MixedTimeseries/controlPanel.tsx | 17 +++++++++++- .../src/MixedTimeseries/transformProps.ts | 32 +++++++++++++++++----- .../src/MixedTimeseries/types.ts | 2 ++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx index 6bc7643c84..52e7d4233a 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx @@ -358,7 +358,22 @@ const config: ControlPanelConfig = { ['x_axis_time_format'], [xAxisLabelRotation], [xAxisLabelInterval], - ...richTooltipSection, + [<ControlSubSectionHeader>{t('Tooltip')}</ControlSubSectionHeader>], + [ + { + name: 'show_query_identifiers', + config: { + type: 'CheckboxControl', + label: t('Show query identifiers'), + description: t( + 'Add Query A and Query B identifiers to legend and tooltip to help differentiate series', + ), + default: false, + renderTrigger: true, + }, + }, + ], + ...richTooltipSection.slice(1), // Skip the tooltip header since we added our own // eslint-disable-next-line react/jsx-key [<ControlSubSectionHeader>{t('Y Axis')}</ControlSubSectionHeader>], [ diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts index fc2a6fe438..0c2364a12f 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts @@ -212,6 +212,7 @@ export default function transformProps( sortSeriesAscendingB, timeGrainSqla, percentageThreshold, + show_query_identifiers = false, metrics = [], metricsB = [], }: EchartsMixedTimeseriesFormData = { ...DEFAULT_FORM_DATA, ...formData }; @@ -395,10 +396,19 @@ export default function transformProps( const seriesName = inverted[entryName] || entryName; const colorScaleKey = getOriginalSeries(seriesName, array); - let displayName = `${entryName} (Query A)`; + let displayName: string; if (groupby.length > 0) { - displayName = `${MetricDisplayNameA} (Query A), ${entryName}`; + // When we have groupby, format as "metric, dimension" + const metricPart = show_query_identifiers + ? `${MetricDisplayNameA} (Query A)` + : MetricDisplayNameA; + displayName = `${metricPart}, ${entryName}`; + } else { + // When no groupby, format as just the entry name with optional query identifier + displayName = show_query_identifiers + ? `${entryName} (Query A)` + : entryName; } const seriesFormatter = getFormatter( @@ -453,10 +463,19 @@ export default function transformProps( const seriesName = `${seriesEntry} (1)`; const colorScaleKey = getOriginalSeries(seriesEntry, array); - let displayName = `${entryName} (Query B)`; + let displayName: string; if (groupbyB.length > 0) { - displayName = `${MetricDisplayNameB} (Query B), ${entryName}`; + // When we have groupby, format as "metric, dimension" + const metricPart = show_query_identifiers + ? `${MetricDisplayNameB} (Query B)` + : MetricDisplayNameB; + displayName = `${metricPart}, ${entryName}`; + } else { + // When no groupby, format as just the entry name with optional query identifier + displayName = show_query_identifiers + ? `${entryName} (Query B)` + : entryName; } const seriesFormatter = getFormatter( @@ -696,14 +715,13 @@ export default function transformProps( zoomable, ), // @ts-ignore - data: rawSeriesA - .concat(rawSeriesB) + data: series .filter( entry => extractForecastSeriesContext((entry.name || '') as string).type === ForecastSeriesEnum.Observation, ) - .map(entry => entry.name || '') + .map(entry => entry.id || entry.name || '') .concat(extractAnnotationLabels(annotationLayers, annotationData)), }, series: dedupSeries(reorderForecastSeries(series) as SeriesOption[]), diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts index a8a2bac65d..9c5ad1b636 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts @@ -60,6 +60,7 @@ export type EchartsMixedTimeseriesFormData = QueryFormData & { tooltipTimeFormat?: string; zoomable: boolean; richTooltip: boolean; + show_query_identifiers?: boolean; xAxisLabelRotation: number; xAxisLabelInterval?: number | string; colorScheme?: string; @@ -133,6 +134,7 @@ export const DEFAULT_FORM_DATA: EchartsMixedTimeseriesFormData = { groupbyB: [], zoomable: TIMESERIES_DEFAULTS.zoomable, richTooltip: TIMESERIES_DEFAULTS.richTooltip, + show_query_identifiers: false, xAxisLabelRotation: TIMESERIES_DEFAULTS.xAxisLabelRotation, xAxisLabelInterval: TIMESERIES_DEFAULTS.xAxisLabelInterval, ...DEFAULT_TITLE_FORM_DATA,
