diff --git a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts index 829440133a3..f953e498588 100644 --- a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts +++ b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts @@ -67,6 +67,8 @@ type Hooks = { setDataMask?: SetDataMaskHook; /** handle tooltip */ setTooltip?: HandlerFunction; + /* handle legend scroll changes */ + onLegendScroll?: HandlerFunction; } & PlainObject; /** @@ -105,6 +107,8 @@ export interface ChartPropsConfig { inputRef?: RefObject; /** Theme object */ theme: SupersetTheme; + /* legend index */ + legendIndex?: number; } const DEFAULT_WIDTH = 800; @@ -135,6 +139,8 @@ export default class ChartProps { legendState?: LegendState; + legendIndex?: number; + queriesData: QueryData[]; width: number; @@ -164,6 +170,7 @@ export default class ChartProps { ownState = {}, filterState = {}, legendState, + legendIndex, initialValues = {}, queriesData = [], behaviors = [], @@ -190,6 +197,7 @@ export default class ChartProps { this.ownState = ownState; this.filterState = filterState; this.legendState = legendState; + this.legendIndex = legendIndex; this.behaviors = behaviors; this.displaySettings = displaySettings; this.appSection = appSection; @@ -215,6 +223,7 @@ ChartProps.createSelector = function create(): ChartPropsSelector { input => input.ownState, input => input.filterState, input => input.legendState, + input => input.legendIndex, input => input.behaviors, input => input.displaySettings, input => input.appSection, @@ -235,6 +244,7 @@ ChartProps.createSelector = function create(): ChartPropsSelector { ownState, filterState, legendState, + legendIndex, behaviors, displaySettings, appSection, @@ -255,6 +265,7 @@ ChartProps.createSelector = function create(): ChartPropsSelector { ownState, filterState, legendState, + legendIndex, width, behaviors, displaySettings, diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx index b91db0b4c1b..7bfab8e3ef8 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx @@ -57,6 +57,7 @@ export default function EchartsTimeseries({ refs, emitCrossFilters, coltypeMapping, + onLegendScroll, }: TimeseriesChartTransformedProps) { const { stack } = formData; const echartRef = useRef(null); @@ -159,6 +160,9 @@ export default function EchartsTimeseries({ mouseover: params => { onFocusedSeries(params.seriesName); }, + legendscroll: payload => { + onLegendScroll?.(payload.scrollDataIndex); + }, legendselectchanged: payload => { onLegendStateChanged?.(payload.selected); }, diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts index 6a7119a33c6..e5349ae0ae0 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts @@ -122,6 +122,7 @@ export default function transformProps( theme, inContextMenu, emitCrossFilters, + legendIndex, } = chartProps; let focusedSeries: string | null = null; @@ -467,6 +468,7 @@ export default function transformProps( setControlValue = () => {}, onContextMenu, onLegendStateChanged, + onLegendScroll, } = hooks; const addYAxisLabelOffset = !!yAxisTitle; @@ -642,6 +644,7 @@ export default function transformProps( legendState, padding, ), + scrollDataIndex: legendIndex || 0, data: legendData as string[], }, series: dedupSeries(reorderForecastSeries(series) as SeriesOption[]), @@ -710,5 +713,6 @@ export default function transformProps( }, refs, coltypeMapping: dataTypes, + onLegendScroll, }; } diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/types.ts index 294437c7454..1a45714b3c8 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/types.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/types.ts @@ -138,6 +138,7 @@ export interface BaseTransformedProps { width: number; emitCrossFilters?: boolean; coltypeMapping?: Record; + onLegendScroll?: (currentIndex: number) => void; } export type CrossFilterTransformedProps = { diff --git a/superset-frontend/src/components/Chart/ChartRenderer.jsx b/superset-frontend/src/components/Chart/ChartRenderer.jsx index 7b641d0eaec..22e7915414d 100644 --- a/superset-frontend/src/components/Chart/ChartRenderer.jsx +++ b/superset-frontend/src/components/Chart/ChartRenderer.jsx @@ -95,6 +95,7 @@ class ChartRenderer extends Component { isFeatureEnabled(FeatureFlag.DrillToDetail), inContextMenu: false, legendState: undefined, + legendIndex: 0, }; this.hasQueryResponseChange = false; @@ -109,6 +110,7 @@ class ChartRenderer extends Component { this.handleContextMenuClosed = this.handleContextMenuClosed.bind(this); this.handleLegendStateChanged = this.handleLegendStateChanged.bind(this); this.onContextMenuFallback = this.onContextMenuFallback.bind(this); + this.handleLegendScroll = this.handleLegendScroll.bind(this); this.hooks = { onAddFilter: this.handleAddFilter, @@ -123,6 +125,7 @@ class ChartRenderer extends Component { setDataMask: dataMask => { this.props.actions?.updateDataMask(this.props.chartId, dataMask); }, + onLegendScroll: this.handleLegendScroll, }; // TODO: queriesResponse comes from Redux store but it's being edited by @@ -246,6 +249,10 @@ class ChartRenderer extends Component { } } + handleLegendScroll(legendIndex) { + this.setState({ legendIndex }); + } + render() { const { chartAlert, chartStatus, chartId, emitCrossFilters } = this.props; @@ -372,6 +379,7 @@ class ChartRenderer extends Component { emitCrossFilters={emitCrossFilters} legendState={this.state.legendState} enableNoResults={bypassNoResult} + legendIndex={this.state.legendIndex} {...drillToDetailProps} />