mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Canvas: Add direction options for connections (#84620)
* Canvas: Add direction options for connections * Fix radio control to handle default * Fix broken options from merge * Remove unused comment * Change category and capitalize options for arrow * Consolidate marker start and end for connections * Fix linter issue
This commit is contained in:
parent
c4645c81da
commit
c1065e6e68
@ -42,6 +42,13 @@ export enum ConnectionPath {
|
||||
Straight = 'straight',
|
||||
}
|
||||
|
||||
export enum ConnectionDirection {
|
||||
Forward = 'forward',
|
||||
Reverse = 'reverse',
|
||||
Both = 'both',
|
||||
None = 'none',
|
||||
}
|
||||
|
||||
export interface CanvasConnection {
|
||||
source: ConnectionCoordinates;
|
||||
target: ConnectionCoordinates;
|
||||
@ -51,6 +58,7 @@ export interface CanvasConnection {
|
||||
size?: ScaleDimensionConfig;
|
||||
lineStyle?: string;
|
||||
vertices?: ConnectionCoordinates[];
|
||||
direction?: ConnectionDirection;
|
||||
// See https://github.com/anseki/leader-line#options for more examples of more properties
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { config } from 'app/core/config';
|
||||
import { ConnectionDirection } from 'app/features/canvas';
|
||||
import { Scene } from 'app/features/canvas/runtime/scene';
|
||||
|
||||
import { ConnectionCoordinates } from '../../panelcfg.gen';
|
||||
@ -45,6 +46,7 @@ export const ConnectionSVG = ({
|
||||
const EDITOR_HEAD_ID = useMemo(() => `editorHead-${headId}`, [headId]);
|
||||
const defaultArrowColor = config.theme2.colors.text.primary;
|
||||
const defaultArrowSize = 2;
|
||||
const defaultArrowDirection = ConnectionDirection.Forward;
|
||||
const maximumVertices = 10;
|
||||
|
||||
const [selectedConnection, setSelectedConnection] = useState<ConnectionState | undefined>(undefined);
|
||||
@ -134,14 +136,20 @@ export const ConnectionSVG = ({
|
||||
const { x1, y1, x2, y2 } = calculateCoordinates(sourceRect, parentRect, info, target, transformScale);
|
||||
const midpoint = calculateMidpoint(x1, y1, x2, y2);
|
||||
|
||||
const { strokeColor, strokeWidth, lineStyle } = getConnectionStyles(info, scene, defaultArrowSize);
|
||||
const { strokeColor, strokeWidth, arrowDirection, lineStyle } = getConnectionStyles(
|
||||
info,
|
||||
scene,
|
||||
defaultArrowSize,
|
||||
defaultArrowDirection
|
||||
);
|
||||
|
||||
const isSelected = selectedConnection === v && scene.panel.context.instanceState.selectedConnection;
|
||||
|
||||
const connectionCursorStyle = scene.isEditingEnabled ? 'grab' : '';
|
||||
const selectedStyles = { stroke: '#44aaff', strokeOpacity: 0.6, strokeWidth: strokeWidth + 5 };
|
||||
|
||||
const CONNECTION_HEAD_ID = `connectionHead-${headId + Math.random()}`;
|
||||
const CONNECTION_HEAD_ID_START = `connectionHeadStart-${headId + Math.random()}`;
|
||||
const CONNECTION_HEAD_ID_END = `connectionHeadEnd-${headId + Math.random()}`;
|
||||
|
||||
// Create vertex path and populate array of add vertex controls
|
||||
const addVertices: ConnectionCoordinates[] = [];
|
||||
@ -167,12 +175,33 @@ export const ConnectionSVG = ({
|
||||
pathString += `L${x2} ${y2}`;
|
||||
}
|
||||
|
||||
const markerStart =
|
||||
arrowDirection === ConnectionDirection.Reverse || arrowDirection === ConnectionDirection.Both
|
||||
? `url(#${CONNECTION_HEAD_ID_START})`
|
||||
: undefined;
|
||||
|
||||
const markerEnd =
|
||||
arrowDirection === ConnectionDirection.Forward || arrowDirection === ConnectionDirection.Both
|
||||
? `url(#${CONNECTION_HEAD_ID_END})`
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<svg className={styles.connection} key={idx}>
|
||||
<g onClick={() => selectConnection(v)}>
|
||||
<defs>
|
||||
<marker
|
||||
id={CONNECTION_HEAD_ID}
|
||||
id={CONNECTION_HEAD_ID_START}
|
||||
markerWidth="10"
|
||||
markerHeight="7"
|
||||
refX="0"
|
||||
refY="3.5"
|
||||
orient="auto"
|
||||
stroke={strokeColor}
|
||||
>
|
||||
<polygon points="10 0, 0 3.5, 10 7" fill={strokeColor} />
|
||||
</marker>
|
||||
<marker
|
||||
id={CONNECTION_HEAD_ID_END}
|
||||
markerWidth="10"
|
||||
markerHeight="7"
|
||||
refX="10"
|
||||
@ -201,7 +230,8 @@ export const ConnectionSVG = ({
|
||||
strokeWidth={strokeWidth}
|
||||
strokeDasharray={lineStyle}
|
||||
fill={'none'}
|
||||
markerEnd={`url(#${CONNECTION_HEAD_ID})`}
|
||||
markerEnd={markerEnd}
|
||||
markerStart={markerStart}
|
||||
/>
|
||||
{isSelected && (
|
||||
<g>
|
||||
@ -262,8 +292,9 @@ export const ConnectionSVG = ({
|
||||
stroke={strokeColor}
|
||||
pointerEvents="auto"
|
||||
strokeWidth={strokeWidth}
|
||||
markerEnd={markerEnd}
|
||||
markerStart={markerStart}
|
||||
strokeDasharray={lineStyle}
|
||||
markerEnd={`url(#${CONNECTION_HEAD_ID})`}
|
||||
x1={x1}
|
||||
y1={y1}
|
||||
x2={x2}
|
||||
|
@ -36,6 +36,7 @@ export function getConnectionEditor(opts: CanvasConnectionEditorOptions): Nested
|
||||
const ctx = { ...context, options: opts.connection.info };
|
||||
optionBuilder.addColor(builder, ctx);
|
||||
optionBuilder.addSize(builder, ctx);
|
||||
optionBuilder.addDirection(builder, ctx);
|
||||
optionBuilder.addLineStyle(builder, ctx);
|
||||
},
|
||||
};
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { capitalize } from 'lodash';
|
||||
|
||||
import { PanelOptionsSupplier } from '@grafana/data/src/panel/PanelPlugin';
|
||||
import { CanvasConnection, CanvasElementOptions } from 'app/features/canvas';
|
||||
import { CanvasConnection, CanvasElementOptions, ConnectionDirection } from 'app/features/canvas';
|
||||
import { ColorDimensionEditor, ResourceDimensionEditor, ScaleDimensionEditor } from 'app/features/dimensions/editors';
|
||||
import { BackgroundSizeEditor } from 'app/features/dimensions/editors/BackgroundSizeEditor';
|
||||
|
||||
@ -12,6 +14,7 @@ interface OptionSuppliers {
|
||||
addBorder: PanelOptionsSupplier<CanvasElementOptions>;
|
||||
addColor: PanelOptionsSupplier<CanvasConnection>;
|
||||
addSize: PanelOptionsSupplier<CanvasConnection>;
|
||||
addDirection: PanelOptionsSupplier<CanvasConnection>;
|
||||
addLineStyle: PanelOptionsSupplier<CanvasConnection>;
|
||||
}
|
||||
|
||||
@ -126,6 +129,24 @@ export const optionBuilder: OptionSuppliers = {
|
||||
});
|
||||
},
|
||||
|
||||
addDirection: (builder, context) => {
|
||||
const category = ['Arrow Direction'];
|
||||
builder.addRadio({
|
||||
category,
|
||||
path: 'direction',
|
||||
name: 'Direction',
|
||||
settings: {
|
||||
options: [
|
||||
{ value: undefined, label: capitalize(ConnectionDirection.Forward) },
|
||||
{ value: ConnectionDirection.Reverse, label: capitalize(ConnectionDirection.Reverse) },
|
||||
{ value: ConnectionDirection.Both, label: capitalize(ConnectionDirection.Both) },
|
||||
{ value: ConnectionDirection.None, label: capitalize(ConnectionDirection.None) },
|
||||
],
|
||||
},
|
||||
defaultValue: ConnectionDirection.Forward,
|
||||
});
|
||||
},
|
||||
|
||||
addLineStyle: (builder, context) => {
|
||||
const category = ['Line style'];
|
||||
builder.addCustomEditor({
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
canvasElementRegistry,
|
||||
CanvasElementOptions,
|
||||
CanvasConnection,
|
||||
ConnectionDirection,
|
||||
} from 'app/features/canvas';
|
||||
import { notFoundItem } from 'app/features/canvas/elements/notFound';
|
||||
import { ElementState } from 'app/features/canvas/runtime/element';
|
||||
@ -378,13 +379,19 @@ export const getRowIndex = (fieldName: string | undefined, scene: Scene) => {
|
||||
return 0;
|
||||
};
|
||||
|
||||
export const getConnectionStyles = (info: CanvasConnection, scene: Scene, defaultArrowSize: number) => {
|
||||
export const getConnectionStyles = (
|
||||
info: CanvasConnection,
|
||||
scene: Scene,
|
||||
defaultArrowSize: number,
|
||||
defaultArrowDirection: ConnectionDirection
|
||||
) => {
|
||||
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;
|
||||
const arrowDirection = info.direction ? info.direction : defaultArrowDirection;
|
||||
const lineStyle = info.lineStyle === LineStyle.Dashed ? StrokeDasharray.Dashed : StrokeDasharray.Solid;
|
||||
return { strokeColor, strokeWidth, lineStyle };
|
||||
return { strokeColor, strokeWidth, arrowDirection, lineStyle };
|
||||
};
|
||||
|
||||
export const getParentBoundingClientRect = (scene: Scene) => {
|
||||
|
Loading…
Reference in New Issue
Block a user