From c0eb1fb9df2bfcec7e7407bbfd45f6f5c1b2f532 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Wed, 22 Sep 2021 10:35:41 +0200 Subject: [PATCH 1/3] Disable zooming for the CatalogGraphCard Signed-off-by: Oliver Sand --- .changeset/clean-hotels-tan.md | 7 +++ .changeset/five-phones-exist.md | 7 +++ .../DependencyGraph.stories.tsx | 26 +++++++++ .../DependencyGraph/DependencyGraph.tsx | 55 +++++++++++-------- .../CatalogGraphCard/CatalogGraphCard.tsx | 5 +- .../CatalogGraphPage/CatalogGraphPage.tsx | 1 + .../EntityRelationsGraph.tsx | 5 +- 7 files changed, 82 insertions(+), 24 deletions(-) create mode 100644 .changeset/clean-hotels-tan.md create mode 100644 .changeset/five-phones-exist.md diff --git a/.changeset/clean-hotels-tan.md b/.changeset/clean-hotels-tan.md new file mode 100644 index 0000000000..b3ac0ead54 --- /dev/null +++ b/.changeset/clean-hotels-tan.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-components': patch +--- + +Allow to configure zooming for ``. `zoom` can either be +`enabled`, `disabled`, or `enable-on-click`. The latter requires the user to +click into the diagram to enable zooming. diff --git a/.changeset/five-phones-exist.md b/.changeset/five-phones-exist.md new file mode 100644 index 0000000000..1812769a7a --- /dev/null +++ b/.changeset/five-phones-exist.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog-graph': patch +--- + +Make zooming configurable for `` 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. diff --git a/packages/core-components/src/components/DependencyGraph/DependencyGraph.stories.tsx b/packages/core-components/src/components/DependencyGraph/DependencyGraph.stories.tsx index 0b97059754..e81988976c 100644 --- a/packages/core-components/src/components/DependencyGraph/DependencyGraph.stories.tsx +++ b/packages/core-components/src/components/DependencyGraph/DependencyGraph.stories.tsx @@ -51,6 +51,32 @@ export const Default = () => ( ); +export const ZoomDisabled = () => ( +
+ +
+); + +export const ZoomEnableOnClick = () => ( +
+ +
+); + export const BottomToTop = () => (
& { 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(node); const workspace = d3Selection.select(node.getElementById(WORKSPACE_ID)); - const zoom = d3Zoom - .zoom() - .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() + .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(() => { diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index abb10d4008..5ac8a89539 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -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({ @@ -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} /> ); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx index 0ad50a8174..f5f1ced541 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx @@ -231,6 +231,7 @@ export const CatalogGraphPage = ({ direction={direction} relationPairs={relationPairs} className={classes.graph} + zoom="enabled" /> diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx index 0f1e72d8b2..76cd44394a 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx @@ -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) => 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} /> )}
From 7361f02da04ed91fbbb2a2c51891d456811c8803 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Wed, 22 Sep 2021 10:53:40 +0200 Subject: [PATCH 2/3] Update API report Signed-off-by: Oliver Sand --- plugins/catalog-graph/api-report.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/catalog-graph/api-report.md b/plugins/catalog-graph/api-report.md index fd9999dc4a..b3694b9fe8 100644 --- a/plugins/catalog-graph/api-report.md +++ b/plugins/catalog-graph/api-report.md @@ -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 From b00510bac55b029ad5dfcf32dbb8f89b540cc17b Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Wed, 22 Sep 2021 16:32:58 +0200 Subject: [PATCH 3/3] Export missing DependencyGraphProps Signed-off-by: Oliver Sand --- packages/core-components/api-report.md | 26 ++++++++++++++++++- .../src/components/DependencyGraph/index.ts | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index b5c98add13..72ce416549 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -162,12 +162,36 @@ type DependencyEdge = 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 & { + 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, diff --git a/packages/core-components/src/components/DependencyGraph/index.ts b/packages/core-components/src/components/DependencyGraph/index.ts index 5f5e7a5439..03a5bfd584 100644 --- a/packages/core-components/src/components/DependencyGraph/index.ts +++ b/packages/core-components/src/components/DependencyGraph/index.ts @@ -17,4 +17,5 @@ import * as DependencyGraphTypes from './types'; export { DependencyGraph } from './DependencyGraph'; +export type { DependencyGraphProps } from './DependencyGraph'; export { DependencyGraphTypes };