Graph panel: listen to events from timeseries panel (#41033)
* TimeSeries: share cursor with old graph * Typo fix * Fix typecheck errors * Revert "TimeSeries: share cursor with old graph" This reverts commit1e7dd4f627. * Graph: subscribe to DataHoverEvent * Revert "Fix typecheck errors" This reverts commit737c8ea8c1.
This commit is contained in:
@@ -355,6 +355,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor
|
|||||||
// convert the points
|
// convert the points
|
||||||
payload.point[xScaleUnit] = src.posToVal(x, xScaleKey);
|
payload.point[xScaleUnit] = src.posToVal(x, xScaleKey);
|
||||||
payload.point[yScaleKey] = src.posToVal(y, yScaleKey);
|
payload.point[yScaleKey] = src.posToVal(y, yScaleKey);
|
||||||
|
payload.point.panelRelY = y > 0 ? y / h : 1; // used by old graph panel to position tooltip
|
||||||
eventBus.publish(hoverEvent);
|
eventBus.publish(hoverEvent);
|
||||||
hoverEvent.payload.down = undefined;
|
hoverEvent.payload.down = undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export function collectStackingGroups(f: Field, groups: Map<string, number[]>, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds y axis midpoind for point at given idx (css pixels relative to uPlot canvas)
|
* Finds y axis midpoint for point at given idx (css pixels relative to uPlot canvas)
|
||||||
* @internal
|
* @internal
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ export function findMidPointYPosition(u: uPlot, idx: number) {
|
|||||||
// find median position
|
// find median position
|
||||||
y = (u.valToPos(min, u.series[sMinIdx].scale!) + u.valToPos(max, u.series[sMaxIdx].scale!)) / 2;
|
y = (u.valToPos(min, u.series[sMinIdx].scale!) + u.valToPos(max, u.series[sMaxIdx].scale!)) / 2;
|
||||||
} else {
|
} else {
|
||||||
// snap tooltip to min OR max point, one of thos is not null :)
|
// snap tooltip to min OR max point, one of those is not null :)
|
||||||
y = u.valToPos((min || max)!, u.series[(sMaxIdx || sMinIdx)!].scale!);
|
y = u.valToPos((min || max)!, u.series[(sMaxIdx || sMinIdx)!].scale!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ import { provideTheme } from 'app/core/utils/ConfigProvider';
|
|||||||
import {
|
import {
|
||||||
DataFrame,
|
DataFrame,
|
||||||
DataFrameView,
|
DataFrameView,
|
||||||
|
DataHoverClearEvent,
|
||||||
|
DataHoverEvent,
|
||||||
|
DataHoverPayload,
|
||||||
FieldDisplay,
|
FieldDisplay,
|
||||||
FieldType,
|
FieldType,
|
||||||
formattedValueToString,
|
formattedValueToString,
|
||||||
@@ -40,6 +43,7 @@ import {
|
|||||||
LegacyEventHandler,
|
LegacyEventHandler,
|
||||||
LegacyGraphHoverClearEvent,
|
LegacyGraphHoverClearEvent,
|
||||||
LegacyGraphHoverEvent,
|
LegacyGraphHoverEvent,
|
||||||
|
LegacyGraphHoverEventPayload,
|
||||||
LinkModelSupplier,
|
LinkModelSupplier,
|
||||||
PanelEvents,
|
PanelEvents,
|
||||||
toUtc,
|
toUtc,
|
||||||
@@ -49,6 +53,7 @@ import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
|||||||
import { ContextSrv } from 'app/core/services/context_srv';
|
import { ContextSrv } from 'app/core/services/context_srv';
|
||||||
import { getFieldLinksSupplier } from 'app/angular/panel/panellinks/linkSuppliers';
|
import { getFieldLinksSupplier } from 'app/angular/panel/panellinks/linkSuppliers';
|
||||||
import { DashboardModel } from '../../../features/dashboard/state';
|
import { DashboardModel } from '../../../features/dashboard/state';
|
||||||
|
import { isLegacyGraphHoverEvent } from './utils';
|
||||||
|
|
||||||
const LegendWithThemeProvider = provideTheme(Legend);
|
const LegendWithThemeProvider = provideTheme(Legend);
|
||||||
|
|
||||||
@@ -99,6 +104,9 @@ class GraphElement {
|
|||||||
this.ctrl.dashboard.events.on(LegacyGraphHoverEvent.type, this.onGraphHover.bind(this), this.scope);
|
this.ctrl.dashboard.events.on(LegacyGraphHoverEvent.type, this.onGraphHover.bind(this), this.scope);
|
||||||
this.ctrl.dashboard.events.on(LegacyGraphHoverClearEvent.type, this.onGraphHoverClear.bind(this), this.scope);
|
this.ctrl.dashboard.events.on(LegacyGraphHoverClearEvent.type, this.onGraphHoverClear.bind(this), this.scope);
|
||||||
|
|
||||||
|
this.ctrl.dashboard.events.on(DataHoverEvent.type, this.onGraphHover.bind(this), this.scope);
|
||||||
|
this.ctrl.dashboard.events.on(DataHoverClearEvent.type, this.onGraphHoverClear.bind(this), this.scope);
|
||||||
|
|
||||||
// plot events
|
// plot events
|
||||||
this.elem.bind('plotselected', this.onPlotSelected.bind(this));
|
this.elem.bind('plotselected', this.onPlotSelected.bind(this));
|
||||||
this.elem.bind('plotclick', this.onPlotClick.bind(this));
|
this.elem.bind('plotclick', this.onPlotClick.bind(this));
|
||||||
@@ -147,18 +155,27 @@ class GraphElement {
|
|||||||
ReactDOM.render(legendReactElem, this.legendElem, () => this.renderPanel());
|
ReactDOM.render(legendReactElem, this.legendElem, () => this.renderPanel());
|
||||||
}
|
}
|
||||||
|
|
||||||
onGraphHover(evt: any) {
|
onGraphHover(evt: LegacyGraphHoverEventPayload | DataHoverPayload) {
|
||||||
// ignore other graph hover events if shared tooltip is disabled
|
// ignore other graph hover events if shared tooltip is disabled
|
||||||
if (!this.dashboard.sharedTooltipModeEnabled()) {
|
if (!this.dashboard.sharedTooltipModeEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore if we are the emitter
|
if (isLegacyGraphHoverEvent(evt)) {
|
||||||
if (!this.plot || evt.panel.id === this.panel.id || this.ctrl.otherPanelInFullscreenMode()) {
|
// ignore if we are the emitter
|
||||||
|
if (!this.plot || evt.panel?.id === this.panel.id || this.ctrl.otherPanelInFullscreenMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tooltip.show(evt.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataHoverEvent can come from multiple panels that doesn't include x position
|
||||||
|
if (!evt.point?.time) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tooltip.show(evt.pos);
|
this.tooltip.show({ x: evt.point.time, panelRelY: evt.point.panelRelY ?? 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
onPanelTeardown() {
|
onPanelTeardown() {
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
import { DataFrame, ReducerID, reduceField, AbsoluteTimeRange, FieldType } from '@grafana/data';
|
import {
|
||||||
|
AbsoluteTimeRange,
|
||||||
|
DataFrame,
|
||||||
|
FieldType,
|
||||||
|
LegacyGraphHoverEventPayload,
|
||||||
|
reduceField,
|
||||||
|
ReducerID,
|
||||||
|
} from '@grafana/data';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the min and max time that covers all data
|
* Find the min and max time that covers all data
|
||||||
@@ -22,3 +29,8 @@ export function getDataTimeRange(frames: DataFrame[]): AbsoluteTimeRange | undef
|
|||||||
}
|
}
|
||||||
return found ? range : undefined;
|
return found ? range : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check wether event is LegacyGraphHoverEvent
|
||||||
|
export function isLegacyGraphHoverEvent(event: any): event is LegacyGraphHoverEventPayload {
|
||||||
|
return event.hasOwnProperty('pos');
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user