Disable zooming for the CatalogGraphCard

Signed-off-by: Oliver Sand <oliver.sand@sda-se.com>
This commit is contained in:
Oliver Sand
2021-09-22 10:35:41 +02:00
parent d938f6cda8
commit c0eb1fb9df
7 changed files with 82 additions and 24 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/core-components': patch
---
Allow to configure zooming for `<DependencyGraph>`. `zoom` can either be
`enabled`, `disabled`, or `enable-on-click`. The latter requires the user to
click into the diagram to enable zooming.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-catalog-graph': patch
---
Make zooming configurable for `<CatalogGraphCard>` and disable it by default.
This resolves an issue that scrolling on the entity page is sometimes captured
by the graph making the page hard to use.
@@ -51,6 +51,32 @@ export const Default = () => (
</div>
);
export const ZoomDisabled = () => (
<div style={containerStyle}>
<DependencyGraph
nodes={exampleNodes}
edges={exampleEdges}
style={graphStyle}
paddingX={50}
paddingY={50}
zoom="disabled"
/>
</div>
);
export const ZoomEnableOnClick = () => (
<div style={containerStyle}>
<DependencyGraph
nodes={exampleNodes}
edges={exampleEdges}
style={graphStyle}
paddingX={50}
paddingY={50}
zoom="enable-on-click"
/>
</div>
);
export const BottomToTop = () => (
<div style={containerStyle}>
<DependencyGraph
@@ -56,6 +56,7 @@ export type DependencyGraphProps = React.SVGProps<SVGSVGElement> & {
renderNode?: RenderNodeFunction;
renderLabel?: RenderLabelFunction;
defs?: SVGDefsElement | SVGDefsElement[];
zoom?: 'enabled' | 'disabled' | 'enable-on-click';
};
const WORKSPACE_ID = 'workspace';
@@ -80,6 +81,7 @@ export function DependencyGraph(props: DependencyGraphProps) {
edgeWeight = 1,
renderLabel,
defs,
zoom = 'enabled',
...svgProps
} = props;
const theme: BackstageTheme = useTheme();
@@ -110,28 +112,37 @@ export function DependencyGraph(props: DependencyGraphProps) {
// Set up zooming + panning
const container = d3Selection.select<SVGSVGElement, null>(node);
const workspace = d3Selection.select(node.getElementById(WORKSPACE_ID));
const zoom = d3Zoom
.zoom<SVGSVGElement, null>()
.scaleExtent([1, 10])
.on('zoom', event => {
event.transform.x = Math.min(
0,
Math.max(
event.transform.x,
maxWidth - maxWidth * event.transform.k,
),
);
event.transform.y = Math.min(
0,
Math.max(
event.transform.y,
maxHeight - maxHeight * event.transform.k,
),
);
workspace.attr('transform', event.transform);
});
container.call(zoom);
function enableZoom() {
container.call(
d3Zoom
.zoom<SVGSVGElement, null>()
.scaleExtent([1, 10])
.on('zoom', event => {
event.transform.x = Math.min(
0,
Math.max(
event.transform.x,
maxWidth - maxWidth * event.transform.k,
),
);
event.transform.y = Math.min(
0,
Math.max(
event.transform.y,
maxHeight - maxHeight * event.transform.k,
),
);
workspace.attr('transform', event.transform);
}),
);
}
if (zoom === 'enabled') {
enableZoom();
} else if (zoom === 'enable-on-click') {
container.on('click', () => enableZoom());
}
const { width: newContainerWidth, height: newContainerHeight } =
node.getBoundingClientRect();
@@ -142,7 +153,7 @@ export function DependencyGraph(props: DependencyGraphProps) {
setContainerHeight(newContainerHeight);
}
}, 100),
[containerHeight, containerWidth, maxWidth, maxHeight],
[containerHeight, containerWidth, maxWidth, maxHeight, zoom],
);
const setNodesAndEdges = React.useCallback(() => {
@@ -27,11 +27,11 @@ import React, { MouseEvent, useCallback } from 'react';
import { useNavigate } from 'react-router';
import { catalogEntityRouteRef, catalogGraphRouteRef } from '../../routes';
import {
ALL_RELATION_PAIRS,
Direction,
EntityNode,
EntityRelationsGraph,
RelationPairs,
ALL_RELATION_PAIRS,
} from '../EntityRelationsGraph';
const useStyles = makeStyles<Theme, { height: number | undefined }>({
@@ -58,6 +58,7 @@ export const CatalogGraphCard = ({
direction = Direction.LEFT_RIGHT,
height,
title = 'Relations',
zoom = 'enable-on-click',
}: {
variant?: InfoCardVariants;
relationPairs?: RelationPairs;
@@ -69,6 +70,7 @@ export const CatalogGraphCard = ({
direction?: Direction;
height?: number;
title?: string;
zoom?: 'enabled' | 'disabled' | 'enable-on-click';
}) => {
const { entity } = useEntity();
const entityName = getEntityName(entity);
@@ -118,6 +120,7 @@ export const CatalogGraphCard = ({
onNodeClick={onNodeClick}
className={classes.graph}
relationPairs={relationPairs}
zoom={zoom}
/>
</InfoCard>
);
@@ -231,6 +231,7 @@ export const CatalogGraphPage = ({
direction={direction}
relationPairs={relationPairs}
className={classes.graph}
zoom="enabled"
/>
</Paper>
</Grid>
@@ -24,7 +24,7 @@ import classNames from 'classnames';
import React, { MouseEvent, useEffect, useMemo } from 'react';
import { CustomLabel } from './CustomLabel';
import { CustomNode } from './CustomNode';
import { RelationPairs, ALL_RELATION_PAIRS } from './relations';
import { ALL_RELATION_PAIRS, RelationPairs } from './relations';
import { Direction, EntityNode } from './types';
import { useEntityRelationNodesAndEdges } from './useEntityRelationNodesAndEdges';
@@ -75,6 +75,7 @@ export const EntityRelationsGraph = ({
onNodeClick,
relationPairs = ALL_RELATION_PAIRS,
className,
zoom = 'enabled',
}: {
rootEntityNames: EntityName | EntityName[];
maxDepth?: number;
@@ -86,6 +87,7 @@ export const EntityRelationsGraph = ({
onNodeClick?: (value: EntityNode, event: MouseEvent<unknown>) => void;
relationPairs?: RelationPairs;
className?: string;
zoom?: 'enabled' | 'disabled' | 'enable-on-click';
}) => {
const theme = useTheme();
const classes = useStyles();
@@ -130,6 +132,7 @@ export const EntityRelationsGraph = ({
paddingY={theme.spacing(4)}
labelPosition={DependencyGraphTypes.LabelPosition.RIGHT}
labelOffset={theme.spacing(1)}
zoom={zoom}
/>
)}
</div>