diff --git a/public/app/features/canvas/element.ts b/public/app/features/canvas/element.ts index dbb35da18fe..a3653d5ab92 100644 --- a/public/app/features/canvas/element.ts +++ b/public/app/features/canvas/element.ts @@ -5,6 +5,7 @@ import { PanelOptionsSupplier } from '@grafana/data/src/panel/PanelPlugin'; import { ColorDimensionConfig, ScaleDimensionConfig } from '@grafana/schema'; import { config } from 'app/core/config'; +import { LineStyleConfig } from '../../plugins/panel/canvas/editor/LineStyleEditor'; import { DimensionContext } from '../dimensions'; import { BackgroundConfig, Constraint, LineConfig, Placement, StandardEditorConfig } from './types'; @@ -56,7 +57,7 @@ export interface CanvasConnection { path: ConnectionPath; color?: ColorDimensionConfig; size?: ScaleDimensionConfig; - lineStyle?: string; + lineStyle?: LineStyleConfig; vertices?: ConnectionCoordinates[]; radius?: ScaleDimensionConfig; direction?: ConnectionDirection; diff --git a/public/app/plugins/panel/canvas/components/connections/ConnectionSVG.tsx b/public/app/plugins/panel/canvas/components/connections/ConnectionSVG.tsx index e5fde9ef6aa..0c82fc3c578 100644 --- a/public/app/plugins/panel/canvas/components/connections/ConnectionSVG.tsx +++ b/public/app/plugins/panel/canvas/components/connections/ConnectionSVG.tsx @@ -144,12 +144,8 @@ export const ConnectionSVG = ({ const xDist = x2 - x1; const yDist = y2 - y1; - const { strokeColor, strokeWidth, strokeRadius, arrowDirection, lineStyle } = getConnectionStyles( - info, - scene, - defaultArrowSize, - defaultArrowDirection - ); + const { strokeColor, strokeWidth, strokeRadius, arrowDirection, lineStyle, shouldAnimate } = + getConnectionStyles(info, scene, defaultArrowSize, defaultArrowDirection); const isSelected = selectedConnection === v && scene.panel.context.instanceState.selectedConnection; @@ -345,6 +341,16 @@ export const ConnectionSVG = ({ ? `url(#${CONNECTION_HEAD_ID_END})` : undefined; + const getAnimationDirection = () => { + let values = '100;0'; + + if (arrowDirection === ConnectionDirection.Reverse) { + values = '0;100'; + } + + return values; + }; + return ( selectConnection(v)}> @@ -389,10 +395,22 @@ export const ConnectionSVG = ({ stroke={strokeColor} strokeWidth={strokeWidth} strokeDasharray={lineStyle} + strokeDashoffset={1} fill={'none'} markerEnd={markerEnd} markerStart={markerStart} - /> + > + {shouldAnimate && ( + + )} + {isSelected && ( {vertices.map((value, index) => { @@ -455,12 +473,24 @@ export const ConnectionSVG = ({ markerEnd={markerEnd} markerStart={markerStart} strokeDasharray={lineStyle} + strokeDashoffset={1} x1={x1} y1={y1} x2={x2} y2={y2} cursor={connectionCursorStyle} - /> + > + {shouldAnimate && ( + + )} + {isSelected && ( > = [ { value: LineStyle.Solid, label: 'Solid' }, { value: LineStyle.Dashed, label: 'Dashed' }, + { value: LineStyle.Dotted, label: 'Dotted' }, ]; -export const LineStyleEditor = ({ value, onChange }: StandardEditorProps) => { - const lineStyle = value ?? LineStyle.Solid; +export interface LineStyleConfig { + style: LineStyle; + animate?: boolean; +} + +type Props = StandardEditorProps; + +export const defaultLineStyleConfig: LineStyleConfig = { + style: LineStyle.Solid, + animate: false, +}; + +export const LineStyleEditor = ({ value, onChange }: Props) => { + if (!value) { + value = defaultLineStyleConfig; + } else if (typeof value !== 'object') { + value = { + style: value, + animate: false, + }; + } const onLineStyleChange = useCallback( - (lineStyle: string) => { - onChange(lineStyle); + (lineStyle: LineStyle) => { + onChange({ ...value, style: lineStyle }); }, - [onChange] + [onChange, value] ); - return ; + const onAnimateChange = useCallback( + (animate: boolean) => { + onChange({ ...value, animate }); + }, + [onChange, value] + ); + + return ( + <> + + {value.style !== LineStyle.Solid && ( + <> +
+ + onAnimateChange(e.currentTarget.checked)} /> + + + )} + + ); }; diff --git a/public/app/plugins/panel/canvas/types.ts b/public/app/plugins/panel/canvas/types.ts index 0c7dcf123e0..775d059fee4 100644 --- a/public/app/plugins/panel/canvas/types.ts +++ b/public/app/plugins/panel/canvas/types.ts @@ -47,9 +47,11 @@ export interface ConnectionState { export enum LineStyle { Solid = 'solid', Dashed = 'dashed', + Dotted = 'dotted', } export enum StrokeDasharray { Solid = '0', Dashed = '8 8', + Dotted = '3', } diff --git a/public/app/plugins/panel/canvas/utils.ts b/public/app/plugins/panel/canvas/utils.ts index 09adff4aa70..8563acf8b98 100644 --- a/public/app/plugins/panel/canvas/utils.ts +++ b/public/app/plugins/panel/canvas/utils.ts @@ -403,8 +403,21 @@ export const getConnectionStyles = ( const strokeWidth = info.size ? scene.context.getScale(info.size).get(lastRowIndex) : defaultArrowSize; const strokeRadius = info.radius ? scene.context.getScale(info.radius).get(lastRowIndex) : 0; const arrowDirection = info.direction ? info.direction : defaultArrowDirection; - const lineStyle = info.lineStyle === LineStyle.Dashed ? StrokeDasharray.Dashed : StrokeDasharray.Solid; - return { strokeColor, strokeWidth, strokeRadius, arrowDirection, lineStyle }; + const lineStyle = getLineStyle(info.lineStyle?.style); + const shouldAnimate = info.lineStyle?.animate; + + return { strokeColor, strokeWidth, strokeRadius, arrowDirection, lineStyle, shouldAnimate }; +}; + +const getLineStyle = (lineStyle?: LineStyle) => { + switch (lineStyle) { + case LineStyle.Dashed: + return StrokeDasharray.Dashed; + case LineStyle.Dotted: + return StrokeDasharray.Dotted; + default: + return StrokeDasharray.Solid; + } }; export const getParentBoundingClientRect = (scene: Scene) => {