Merge pull request #7276 from SDA-SE/feat/graph-scroll
Disable zooming for the CatalogGraphCard
This commit is contained in:
@@ -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.
|
||||
@@ -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.
|
||||
@@ -162,12 +162,36 @@ type DependencyEdge<T = CustomType> = T & {
|
||||
label?: string;
|
||||
};
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "DependencyGraphProps" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "DependencyGraph" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export function DependencyGraph(props: DependencyGraphProps): JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "DependencyGraphProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type DependencyGraphProps = React_2.SVGProps<SVGSVGElement> & {
|
||||
edges: DependencyEdge[];
|
||||
nodes: DependencyNode[];
|
||||
direction?: Direction;
|
||||
align?: Alignment;
|
||||
nodeMargin?: number;
|
||||
edgeMargin?: number;
|
||||
rankMargin?: number;
|
||||
paddingX?: number;
|
||||
paddingY?: number;
|
||||
acyclicer?: 'greedy';
|
||||
ranker?: Ranker;
|
||||
labelPosition?: LabelPosition;
|
||||
labelOffset?: number;
|
||||
edgeRanks?: number;
|
||||
edgeWeight?: number;
|
||||
renderNode?: RenderNodeFunction;
|
||||
renderLabel?: RenderLabelFunction;
|
||||
defs?: SVGDefsElement | SVGDefsElement[];
|
||||
zoom?: 'enabled' | 'disabled' | 'enable-on-click';
|
||||
};
|
||||
|
||||
declare namespace DependencyGraphTypes {
|
||||
export {
|
||||
DependencyEdge,
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -17,4 +17,5 @@
|
||||
import * as DependencyGraphTypes from './types';
|
||||
|
||||
export { DependencyGraph } from './DependencyGraph';
|
||||
export type { DependencyGraphProps } from './DependencyGraph';
|
||||
export { DependencyGraphTypes };
|
||||
|
||||
@@ -77,6 +77,7 @@ export const EntityCatalogGraphCard: ({
|
||||
direction,
|
||||
height,
|
||||
title,
|
||||
zoom,
|
||||
}: {
|
||||
variant?: InfoCardVariants | undefined;
|
||||
relationPairs?: RelationPairs | undefined;
|
||||
@@ -88,6 +89,7 @@ export const EntityCatalogGraphCard: ({
|
||||
direction?: Direction | undefined;
|
||||
height?: number | undefined;
|
||||
title?: string | undefined;
|
||||
zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public
|
||||
@@ -119,6 +121,7 @@ export const EntityRelationsGraph: ({
|
||||
onNodeClick,
|
||||
relationPairs,
|
||||
className,
|
||||
zoom,
|
||||
}: {
|
||||
rootEntityNames: EntityName | EntityName[];
|
||||
maxDepth?: number | undefined;
|
||||
@@ -132,6 +135,7 @@ export const EntityRelationsGraph: ({
|
||||
| undefined;
|
||||
relationPairs?: RelationPairs | undefined;
|
||||
className?: string | undefined;
|
||||
zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user