From 087e081c5a81b9e0f87481634fa8a4540c7d78cb Mon Sep 17 00:00:00 2001 From: Adela Almasan <88068998+adela-almasan@users.noreply.github.com> Date: Thu, 2 Nov 2023 12:09:07 -0500 Subject: [PATCH] Canvas: Refactor ConnectionSVG utils (#77578) Co-authored-by: Krishna Dhakal <7krishna7dhakal7@gmail.com> --- .../components/connections/ConnectionSVG.tsx | 46 +-------------- public/app/plugins/panel/canvas/utils.ts | 56 ++++++++++++++++++- 2 files changed, 58 insertions(+), 44 deletions(-) diff --git a/public/app/plugins/panel/canvas/components/connections/ConnectionSVG.tsx b/public/app/plugins/panel/canvas/components/connections/ConnectionSVG.tsx index 47a3bde9eb8..f8c5ece15f6 100644 --- a/public/app/plugins/panel/canvas/components/connections/ConnectionSVG.tsx +++ b/public/app/plugins/panel/canvas/components/connections/ConnectionSVG.tsx @@ -7,6 +7,7 @@ import { config } from 'app/core/config'; import { Scene } from 'app/features/canvas/runtime/scene'; import { ConnectionState } from '../../types'; +import { calculateCoordinates, getConnectionStyles } from '../../utils'; type Props = { setSVGRef: (anchorElement: SVGSVGElement) => void; @@ -97,19 +98,6 @@ export const ConnectionSVG = ({ setSVGRef, setLineRef, scene }: Props) => { } }; - // @TODO revisit, currently returning last row index for field - const getRowIndex = (fieldName: string | undefined) => { - if (fieldName) { - const series = scene.context.getPanelData()?.series[0]; - const field = series?.fields.find((f) => (f.name = fieldName)); - const data = field?.values; - - return data ? data.length - 1 : 0; - } - - return 0; - }; - // Figure out target and then target's relative coordinates drawing (if no target do parent) const renderConnections = () => { return scene.connections.state.map((v, idx) => { @@ -122,40 +110,12 @@ export const ConnectionSVG = ({ setSVGRef, setLineRef, scene }: Props) => { return; } - const sourceHorizontalCenter = sourceRect.left - parentRect.left + sourceRect.width / 2; - const sourceVerticalCenter = sourceRect.top - parentRect.top + sourceRect.height / 2; + const { x1, y1, x2, y2 } = calculateCoordinates(sourceRect, parentRect, info, target); - // Convert from connection coords to DOM coords - // TODO: Break this out into util function and add tests - const x1 = sourceHorizontalCenter + (info.source.x * sourceRect.width) / 2; - const y1 = sourceVerticalCenter - (info.source.y * sourceRect.height) / 2; - - let x2; - let y2; - - if (info.targetName) { - const targetRect = target.div?.getBoundingClientRect(); - - const targetHorizontalCenter = targetRect!.left - parentRect.left + targetRect!.width / 2; - const targetVerticalCenter = targetRect!.top - parentRect.top + targetRect!.height / 2; - - x2 = targetHorizontalCenter + (info.target.x * targetRect!.width) / 2; - y2 = targetVerticalCenter - (info.target.y * targetRect!.height) / 2; - } else { - const parentHorizontalCenter = parentRect.width / 2; - const parentVerticalCenter = parentRect.height / 2; - - x2 = parentHorizontalCenter + (info.target.x * parentRect.width) / 2; - y2 = parentVerticalCenter - (info.target.y * parentRect.height) / 2; - } + const { strokeColor, strokeWidth } = getConnectionStyles(info, scene, defaultArrowSize); const isSelected = selectedConnection === v && scene.panel.context.instanceState.selectedConnection; - const strokeColor = info.color ? scene.context.getColor(info.color).value() : defaultArrowColor; - const lastRowIndex = getRowIndex(info.size?.field); - - const strokeWidth = info.size ? scene.context.getScale(info.size).get(lastRowIndex) : defaultArrowSize; - const connectionCursorStyle = scene.isEditingEnabled ? 'grab' : ''; const selectedStyles = { stroke: '#44aaff', strokeOpacity: 0.6, strokeWidth: strokeWidth + 5 }; diff --git a/public/app/plugins/panel/canvas/utils.ts b/public/app/plugins/panel/canvas/utils.ts index 5e4a03eec97..60056dad2c4 100644 --- a/public/app/plugins/panel/canvas/utils.ts +++ b/public/app/plugins/panel/canvas/utils.ts @@ -2,7 +2,7 @@ import { isNumber, isString } from 'lodash'; import { AppEvents, Field, getFieldDisplayName, LinkModel, PluginState, SelectableValue } from '@grafana/data'; import appEvents from 'app/core/app_events'; -import { hasAlphaPanels } from 'app/core/config'; +import { hasAlphaPanels, config } from 'app/core/config'; import { defaultElementItems, advancedElementItems, @@ -10,6 +10,7 @@ import { canvasElementRegistry, CanvasElementOptions, TextConfig, + CanvasConnection, } from 'app/features/canvas'; import { notFoundItem } from 'app/features/canvas/elements/notFound'; import { ElementState } from 'app/features/canvas/runtime/element'; @@ -184,3 +185,56 @@ export function updateConnectionsForSource(element: ElementState, scene: Scene) connection.source.onChange({ ...connection.source.options, connections }); }); } + +export const calculateCoordinates = ( + sourceRect: DOMRect, + parentRect: DOMRect, + info: CanvasConnection, + target: ElementState +) => { + const sourceHorizontalCenter = sourceRect.left - parentRect.left + sourceRect.width / 2; + const sourceVerticalCenter = sourceRect.top - parentRect.top + sourceRect.height / 2; + + // Convert from connection coords to DOM coords + const x1 = sourceHorizontalCenter + (info.source.x * sourceRect.width) / 2; + const y1 = sourceVerticalCenter - (info.source.y * sourceRect.height) / 2; + + let x2; + let y2; + + if (info.targetName) { + const targetRect = target.div?.getBoundingClientRect(); + + const targetHorizontalCenter = targetRect!.left - parentRect.left + targetRect!.width / 2; + const targetVerticalCenter = targetRect!.top - parentRect.top + targetRect!.height / 2; + + x2 = targetHorizontalCenter + (info.target.x * targetRect!.width) / 2; + y2 = targetVerticalCenter - (info.target.y * targetRect!.height) / 2; + } else { + const parentHorizontalCenter = parentRect.width / 2; + const parentVerticalCenter = parentRect.height / 2; + + x2 = parentHorizontalCenter + (info.target.x * parentRect.width) / 2; + y2 = parentVerticalCenter - (info.target.y * parentRect.height) / 2; + } + return { x1, y1, x2, y2 }; +}; + +// @TODO revisit, currently returning last row index for field +export const getRowIndex = (fieldName: string | undefined, scene: Scene) => { + if (fieldName) { + const series = scene.context.getPanelData()?.series[0]; + const field = series?.fields.find((f) => (f.name = fieldName)); + const data = field?.values; + return data ? data.length - 1 : 0; + } + return 0; +}; + +export const getConnectionStyles = (info: CanvasConnection, scene: Scene, defaultArrowSize: number) => { + const defaultArrowColor = config.theme2.colors.text.primary; + const lastRowIndex = getRowIndex(info.size?.field, scene); + const strokeColor = info.color ? scene.context.getColor(info.color).value() : defaultArrowColor; + const strokeWidth = info.size ? scene.context.getScale(info.size).get(lastRowIndex) : defaultArrowSize; + return { strokeColor, strokeWidth }; +};