Canvas: Add tooltip for data links (#61648)

This commit is contained in:
Adela Almasan
2023-01-20 10:26:51 -06:00
committed by GitHub
parent c1251311d0
commit cef15873d6
11 changed files with 191 additions and 4 deletions

View File

@@ -11,6 +11,7 @@ import { DimensionContext } from 'app/features/dimensions/context';
import { ColorDimensionEditor } from 'app/features/dimensions/editors/ColorDimensionEditor';
import { TextDimensionEditor } from 'app/features/dimensions/editors/TextDimensionEditor';
import { getDataLinks } from '../../../plugins/panel/canvas/utils';
import { CanvasElementItem, CanvasElementProps, defaultBgColor, defaultTextColor } from '../element';
import { ElementState } from '../runtime/element';
import { Align, TextConfig, TextData, VAlign } from '../types';
@@ -159,6 +160,8 @@ export const metricValueItem: CanvasElementItem<TextConfig, TextData> = {
data.color = ctx.getColor(cfg.color).value();
}
data.links = getDataLinks(ctx, cfg, data.text);
return data;
},

View File

@@ -9,6 +9,7 @@ import { DimensionContext } from 'app/features/dimensions/context';
import { ColorDimensionEditor } from 'app/features/dimensions/editors/ColorDimensionEditor';
import { TextDimensionEditor } from 'app/features/dimensions/editors/TextDimensionEditor';
import { getDataLinks } from '../../../plugins/panel/canvas/utils';
import { CanvasElementItem, CanvasElementProps, defaultThemeTextColor } from '../element';
import { ElementState } from '../runtime/element';
import { Align, TextConfig, TextData, VAlign } from '../types';
@@ -158,6 +159,8 @@ export const textItem: CanvasElementItem<TextConfig, TextData> = {
data.color = ctx.getColor(cfg.color).value();
}
data.links = getDataLinks(ctx, cfg, data.text);
return data;
},

View File

@@ -446,6 +446,45 @@ export class ElementState implements LayerElement {
}
};
handleMouseEnter = (event: React.MouseEvent, isSelected: boolean | undefined) => {
const scene = this.getScene();
if (!scene?.isEditingEnabled) {
this.handleTooltip(event);
} else if (!isSelected) {
scene?.connections.handleMouseEnter(event);
}
};
handleTooltip = (event: React.MouseEvent) => {
const scene = this.getScene();
if (scene?.tooltipCallback) {
const rect = this.div?.getBoundingClientRect();
scene.tooltipCallback({
anchorPoint: { x: rect?.right ?? event.pageX, y: rect?.top ?? event.pageY },
element: this,
isOpen: false,
});
}
};
handleMouseLeave = (event: React.MouseEvent) => {
const scene = this.getScene();
if (scene?.tooltipCallback && !scene?.tooltip?.isOpen) {
scene.tooltipCallback(undefined);
}
};
onElementClick = (event: React.MouseEvent) => {
const scene = this.getScene();
if (scene?.tooltipCallback && scene.tooltip?.anchorPoint) {
scene.tooltipCallback({
anchorPoint: { x: scene.tooltip.anchorPoint.x, y: scene.tooltip.anchorPoint.y },
element: this,
isOpen: true,
});
}
};
render() {
const { item, div } = this;
const scene = this.getScene();
@@ -456,7 +495,9 @@ export class ElementState implements LayerElement {
<div
key={this.UID}
ref={this.initElement}
onMouseEnter={!isSelected ? scene?.connections.handleMouseEnter : undefined}
onMouseEnter={(e: React.MouseEvent) => this.handleMouseEnter(e, isSelected)}
onMouseLeave={!scene?.isEditingEnabled ? this.handleMouseLeave : undefined}
onClick={!scene?.isEditingEnabled ? this.onElementClick : undefined}
>
<item.display
key={`${this.UID}/${this.revId}`}

View File

@@ -26,9 +26,10 @@ import {
getTextDimensionFromData,
} from 'app/features/dimensions/utils';
import { CanvasContextMenu } from 'app/plugins/panel/canvas/CanvasContextMenu';
import { CanvasTooltip } from 'app/plugins/panel/canvas/CanvasTooltip';
import { CONNECTION_ANCHOR_DIV_ID } from 'app/plugins/panel/canvas/ConnectionAnchors';
import { Connections } from 'app/plugins/panel/canvas/Connections';
import { AnchorPoint, LayerActionID } from 'app/plugins/panel/canvas/types';
import { AnchorPoint, CanvasTooltipPayload, LayerActionID } from 'app/plugins/panel/canvas/types';
import appEvents from '../../../core/app_events';
import { CanvasPanel } from '../../../plugins/panel/canvas/CanvasPanel';
@@ -74,6 +75,9 @@ export class Scene {
inlineEditingCallback?: () => void;
setBackgroundCallback?: (anchorPoint: AnchorPoint) => void;
tooltipCallback?: (tooltip: CanvasTooltipPayload | undefined) => void;
tooltip?: CanvasTooltipPayload;
readonly editModeEnabled = new BehaviorSubject<boolean>(false);
subscription: Subscription;
@@ -149,6 +153,7 @@ export class Scene {
getScalar: (scalar: ScalarDimensionConfig) => getScalarDimensionFromData(this.data, scalar),
getText: (text: TextDimensionConfig) => getTextDimensionFromData(this.data, text),
getResource: (res: ResourceDimensionConfig) => getResourceDimensionFromData(this.data, res),
getPanelData: () => this.data,
};
updateData(data: PanelData) {
@@ -600,6 +605,8 @@ export class Scene {
render() {
const canShowContextMenu = this.isPanelEditing || (!this.isPanelEditing && this.isEditingEnabled);
const canShowElementTooltip =
!this.isEditingEnabled && this.tooltip?.element && this.tooltip.element.data.links?.length > 0;
return (
<div key={this.revId} className={this.styles.wrap} style={this.style} ref={this.setRef}>
@@ -610,6 +617,11 @@ export class Scene {
<CanvasContextMenu scene={this} panel={this.panel} />
</Portal>
)}
{canShowElementTooltip && (
<Portal>
<CanvasTooltip scene={this} />
</Portal>
)}
</div>
);
}

View File

@@ -1,3 +1,4 @@
import { LinkModel } from '@grafana/data/src';
import { ColorDimensionConfig, ResourceDimensionConfig, TextDimensionConfig } from 'app/features/dimensions/types';
export interface Placement {
@@ -77,6 +78,7 @@ export interface TextData {
size?: number; // 0 or missing will "auto size"
align: Align;
valign: VAlign;
links?: LinkModel[];
}
export interface TextConfig {

View File

@@ -1,3 +1,5 @@
import { PanelData } from '@grafana/data/src';
import {
ColorDimensionConfig,
DimensionSupplier,
@@ -13,4 +15,5 @@ export interface DimensionContext {
getScalar(scalar: ScalarDimensionConfig): DimensionSupplier<number>;
getText(text: TextDimensionConfig): DimensionSupplier<string>;
getResource(resource: ResourceDimensionConfig): DimensionSupplier<string>;
getPanelData(): PanelData | undefined;
}