NodeGraph: Fix invisible arrow tips in Editor (#86517)

NodeGraphPanel: Namespace marker IDs to fix invisible arrow tips in editor

Co-authored-by: Andrej Ocenas <mr.ocenas@gmail.com>
This commit is contained in:
timo 2024-04-18 18:39:16 +02:00 committed by GitHub
parent 1d1ebee36b
commit f3fcfad2c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 24 additions and 6 deletions

View File

@ -11,13 +11,14 @@ export const defaultEdgeColor = '#999';
interface Props {
edge: EdgeDatum;
hovering: boolean;
svgIdNamespace: string;
onClick: (event: MouseEvent<SVGElement>, link: EdgeDatum) => void;
onMouseEnter: (id: string) => void;
onMouseLeave: (id: string) => void;
}
export const Edge = memo(function Edge(props: Props) {
const { edge, onClick, onMouseEnter, onMouseLeave, hovering } = props;
const { edge, onClick, onMouseEnter, onMouseLeave, hovering, svgIdNamespace } = props;
// Not great typing but after we do layout these properties are full objects not just references
const { source, target, sourceNodeRadius, targetNodeRadius } = edge as {
@ -47,8 +48,8 @@ export const Edge = memo(function Edge(props: Props) {
// in case both are provided
const highlightedEdgeColor = edge.color || defaultHighlightedEdgeColor;
const markerId = `triangle-${edge.id}`;
const coloredMarkerId = `triangle-colored-${edge.id}`;
const markerId = `triangle-${svgIdNamespace}-${edge.id}`;
const coloredMarkerId = `triangle-colored-${svgIdNamespace}-${edge.id}`;
return (
<>

View File

@ -111,8 +111,9 @@ interface Props {
dataFrames: DataFrame[];
getLinks: (dataFrame: DataFrame, rowIndex: number) => LinkModel[];
nodeLimit?: number;
panelId?: string;
}
export function NodeGraph({ getLinks, dataFrames, nodeLimit }: Props) {
export function NodeGraph({ getLinks, dataFrames, nodeLimit, panelId }: Props) {
const nodeCountLimit = nodeLimit || defaultNodeCountLimit;
const { edges: edgesDataFrames, nodes: nodesDataFrames } = useCategorizeFrames(dataFrames);
@ -122,6 +123,13 @@ export function NodeGraph({ getLinks, dataFrames, nodeLimit }: Props) {
const firstNodesDataFrame = nodesDataFrames[0];
const firstEdgesDataFrame = edgesDataFrames[0];
// Ensure we use unique IDs for the marker tip elements, since IDs are global
// in the entire HTML document. This prevents hidden tips when an earlier
// occurence is hidden (editor is open in front of an existing node graph
// panel) or when the earlier tips have different properties (color, size, or
// shape for example).
const svgIdNamespace = panelId || 'nodegraphpanel';
// TODO we should be able to allow multiple dataframes for both edges and nodes, could be issue with node ids which in
// that case should be unique or figure a way to link edges and nodes dataframes together.
const processed = useMemo(
@ -215,6 +223,7 @@ export function NodeGraph({ getLinks, dataFrames, nodeLimit }: Props) {
onClick={onEdgeOpen}
onMouseEnter={setEdgeHover}
onMouseLeave={clearEdgeHover}
svgIdNamespace={svgIdNamespace}
/>
)}
<Nodes
@ -332,6 +341,7 @@ interface EdgesProps {
edges: EdgeDatum[];
nodeHoveringId?: string;
edgeHoveringId?: string;
svgIdNamespace: string;
onClick: (event: MouseEvent<SVGElement>, link: EdgeDatum) => void;
onMouseEnter: (id: string) => void;
onMouseLeave: (id: string) => void;
@ -351,6 +361,7 @@ const Edges = memo(function Edges(props: EdgesProps) {
onClick={props.onClick}
onMouseEnter={props.onMouseEnter}
onMouseLeave={props.onMouseLeave}
svgIdNamespace={props.svgIdNamespace}
/>
))}
</>

View File

@ -1,5 +1,5 @@
import memoizeOne from 'memoize-one';
import React from 'react';
import React, { useId } from 'react';
import { PanelProps } from '@grafana/data';
@ -11,6 +11,8 @@ import { getNodeGraphDataFrames } from './utils';
export const NodeGraphPanel = ({ width, height, data, options }: PanelProps<NodeGraphOptions>) => {
const getLinks = useLinks(data.timeRange);
const panelId = useId();
if (!data || !data.series.length) {
return (
<div className="panel-empty">
@ -22,7 +24,11 @@ export const NodeGraphPanel = ({ width, height, data, options }: PanelProps<Node
const memoizedGetNodeGraphDataFrames = memoizeOne(getNodeGraphDataFrames);
return (
<div style={{ width, height }}>
<NodeGraph dataFrames={memoizedGetNodeGraphDataFrames(data.series, options)} getLinks={getLinks} />
<NodeGraph
dataFrames={memoizedGetNodeGraphDataFrames(data.series, options)}
getLinks={getLinks}
panelId={panelId}
/>
</div>
);
};