diff --git a/packages/grafana-data/src/events/types.ts b/packages/grafana-data/src/events/types.ts index 5ef531a46f9..f5e111eb2fc 100644 --- a/packages/grafana-data/src/events/types.ts +++ b/packages/grafana-data/src/events/types.ts @@ -19,10 +19,22 @@ export abstract class BusEventBase implements BusEvent { readonly payload?: any; readonly origin?: EventBus; + /** @internal */ + tags?: Set; + constructor() { //@ts-ignore this.type = this.__proto__.constructor.type; } + + /** + * @internal + * Tag event for finer-grained filtering in subscribers + */ + setTags(tags: string[]) { + this.tags = new Set(tags); + return this; + } } /** diff --git a/public/app/core/components/GraphNG/GraphNG.tsx b/public/app/core/components/GraphNG/GraphNG.tsx index 9ebfa499c81..b4b5974d55d 100644 --- a/public/app/core/components/GraphNG/GraphNG.tsx +++ b/public/app/core/components/GraphNG/GraphNG.tsx @@ -139,6 +139,11 @@ export class GraphNG extends Component { } handleCursorUpdate(evt: DataHoverEvent | LegacyGraphHoverEvent) { + // ignore uplot-emitted events, since we already use uPlot's sync + if (evt.tags?.has('uplot')) { + return; + } + const time = evt.payload?.point?.time; const u = this.plotInstance.current; if (u && time) { diff --git a/public/app/core/components/TimeSeries/utils.ts b/public/app/core/components/TimeSeries/utils.ts index 106f2c72b10..d5a1916ae32 100644 --- a/public/app/core/components/TimeSeries/utils.ts +++ b/public/app/core/components/TimeSeries/utils.ts @@ -583,7 +583,9 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ data: frame, }; - const hoverEvent = new DataHoverEvent(payload); + const hoverEvent = new DataHoverEvent(payload).setTags(['uplot']); + const clearEvent = new DataHoverClearEvent().setTags(['uplot']); + cursor.sync = { key: eventsScope, filters: { @@ -594,9 +596,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ payload.rowIndex = dataIdx; if (x < 0 && y < 0) { - payload.point[xScaleUnit] = null; - payload.point[yScaleKey] = null; - eventBus.publish(new DataHoverClearEvent()); + eventBus.publish(clearEvent); } else { // convert the points payload.point[xScaleUnit] = src.posToVal(x, xScaleKey); diff --git a/public/app/core/components/TimelineChart/utils.ts b/public/app/core/components/TimelineChart/utils.ts index 489cd13222d..ef52d51c94a 100644 --- a/public/app/core/components/TimelineChart/utils.ts +++ b/public/app/core/components/TimelineChart/utils.ts @@ -180,6 +180,9 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn = ( data: frame, }; + const hoverEvent = new DataHoverEvent(payload).setTags(['uplot']); + const clearEvent = new DataHoverClearEvent().setTags(['uplot']); + builder.addHook('init', coreConfig.init); builder.addHook('drawClear', coreConfig.drawClear); @@ -293,14 +296,12 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn = ( } payload.rowIndex = dataIdx; if (x < 0 && y < 0) { - payload.point[xScaleUnit] = null; - payload.point[FIXED_UNIT] = null; - eventBus.publish(new DataHoverClearEvent()); + eventBus.publish(clearEvent); } else { payload.point[xScaleUnit] = src.posToVal(x, xScaleKey); payload.point.panelRelY = y > 0 ? y / h : 1; // used for old graph panel to position tooltip payload.down = undefined; - eventBus.publish(new DataHoverEvent(payload)); + eventBus.publish(hoverEvent); } return true; }, diff --git a/public/app/plugins/panel/heatmap/utils.ts b/public/app/plugins/panel/heatmap/utils.ts index 3b54f45e052..79747c7c5cb 100644 --- a/public/app/plugins/panel/heatmap/utils.ts +++ b/public/app/plugins/panel/heatmap/utils.ts @@ -172,7 +172,9 @@ export function prepConfig(opts: PrepConfigOpts) { }, data: dataRef.current?.heatmap, }; - const hoverEvent = new DataHoverEvent(payload); + + const hoverEvent = new DataHoverEvent(payload).setTags(['uplot']); + const clearEvent = new DataHoverClearEvent().setTags(['uplot']); let pendingOnleave: ReturnType | 0; @@ -209,9 +211,7 @@ export function prepConfig(opts: PrepConfigOpts) { if (!pendingOnleave) { pendingOnleave = setTimeout(() => { onhover(null); - payload.rowIndex = undefined; - payload.point[xScaleUnit] = null; - eventBus.publish(hoverEvent); + eventBus.publish(clearEvent); }, 100); } }