diff --git a/.changeset/flat-peas-run.md b/.changeset/flat-peas-run.md new file mode 100644 index 0000000000..116e8eb449 --- /dev/null +++ b/.changeset/flat-peas-run.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-components': minor +'@backstage/plugin-catalog-graph': minor +--- + +Added `renderEdge` prop to component in @backstage/core-components to allow custom rendering of graph edges. Fixed local development for EntityRelationsGraph plugin. diff --git a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx index d690253b06..f4b3d6bd58 100644 --- a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx +++ b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx @@ -138,6 +138,11 @@ export interface DependencyGraphProps * Weight applied to edges in graph */ edgeWeight?: number; + /** + * Custom edge rendering component + */ + renderEdge?: Types.RenderEdgeFunction; + /** * Custom node rendering component */ @@ -210,6 +215,7 @@ export function DependencyGraph( labelOffset = 10, edgeRanks = 1, edgeWeight = 1, + renderEdge, renderLabel, defs, zoom = 'enabled', @@ -442,6 +448,8 @@ export function DependencyGraph( {graphEdges.map(e => { const edge = graph.current.edge(e) as GraphEdge; if (!edge) return null; + if (renderEdge) return renderEdge({ edge, id: e }); + return ( , ) => ReactNode; + /** + * Properties of {@link DependencyGraphTypes.RenderEdgeFunction} for {@link DependencyGraphTypes.DependencyEdge} + * + * @public + */ + export type RenderEdgeProps = { + edge: DependencyEdge; + id: dagre.Edge; + }; + + /** + * Custom React component for graph {@link DependencyGraphTypes.DependencyEdge} + * + * @public + */ + export type RenderEdgeFunction = (props: { + edge: T & { + points: { x: number; y: number }[]; + label?: string; + labeloffset?: number; + labelpos?: string; + width?: number; + height?: number; + weight?: number; + minlen?: number; + showArrowHeads?: boolean; + from?: string; + to?: string; + relations?: string[]; + }; + id: { v: string; w: string }; + }) => ReactNode; + /** * Graph direction * diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index dd3271f468..7cea775bbe 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -61,6 +61,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "classnames": "^2.3.1", + "d3-shape": "^3.0.0", "lodash": "^4.17.15", "p-limit": "^3.1.0", "qs": "^6.9.4", @@ -76,6 +77,7 @@ "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.0.0", + "@types/d3-shape": "^3.0.1", "@types/react": "^18.0.0", "react": "^18.0.2", "react-dom": "^18.0.2", diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx new file mode 100644 index 0000000000..379ce77f52 --- /dev/null +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx @@ -0,0 +1,15 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx index 933aa230be..f08cd7a760 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx @@ -89,6 +89,7 @@ export type EntityRelationsGraphProps = { zoom?: 'enabled' | 'disabled' | 'enable-on-click'; renderNode?: DependencyGraphTypes.RenderNodeFunction; renderLabel?: DependencyGraphTypes.RenderLabelFunction; + renderEdge?: DependencyGraphTypes.RenderEdgeFunction; curve?: 'curveStepBefore' | 'curveMonotoneX'; showArrowHeads?: boolean; }; @@ -114,6 +115,7 @@ export const EntityRelationsGraph = (props: EntityRelationsGraphProps) => { zoom = 'enabled', renderNode, renderLabel, + renderEdge, curve, showArrowHeads, } = props; @@ -156,6 +158,7 @@ export const EntityRelationsGraph = (props: EntityRelationsGraphProps) => { edges={edges} renderNode={renderNode || DefaultRenderNode} renderLabel={renderLabel || DefaultRenderLabel} + renderEdge={renderEdge} direction={direction} className={classes.graph} paddingX={theme.spacing(4)} diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts index c55becdd49..be6ea81f57 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts @@ -64,7 +64,7 @@ export function useEntityStore(): { return; } - const { items } = await catalogClient.getEntitiesByRefs({ entityRefs }); + const { items } = await catalogClient.getEntities(); items.forEach(ent => { if (ent) { const entityRef = stringifyEntityRef(ent); diff --git a/yarn.lock b/yarn.lock index 853749b99e..fde37ae4e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4771,8 +4771,10 @@ __metadata: "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" "@testing-library/user-event": "npm:^14.0.0" + "@types/d3-shape": "npm:^3.0.1" "@types/react": "npm:^18.0.0" classnames: "npm:^2.3.1" + d3-shape: "npm:^3.0.0" lodash: "npm:^4.17.15" p-limit: "npm:^3.1.0" qs: "npm:^6.9.4"