diff --git a/.changeset/smooth-countries-relate.md b/.changeset/smooth-countries-relate.md new file mode 100644 index 0000000000..5e86ee8ab5 --- /dev/null +++ b/.changeset/smooth-countries-relate.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-graph': patch +--- + +Use `entityPresentationApi` for the node title and the icon. diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderNode.test.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderNode.test.tsx index 1f3d77e1ae..10aa62f946 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderNode.test.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderNode.test.tsx @@ -47,6 +47,7 @@ describe('', () => { ); expect(screen.getByText('kind:namespace/name')).toBeInTheDocument(); + expect(screen.getByText('namespace/name')).toBeInTheDocument(); }); test('renders node, skips default namespace', async () => { @@ -73,7 +74,7 @@ describe('', () => { , ); - expect(screen.getByText('kind:name')).toBeInTheDocument(); + expect(screen.getByText('name')).toBeInTheDocument(); }); test('renders node with onClick', async () => { @@ -102,8 +103,8 @@ describe('', () => { , ); - expect(screen.getByText('kind:namespace/name')).toBeInTheDocument(); - await userEvent.click(screen.getByText('kind:namespace/name')); + expect(screen.getByText('namespace/name')).toBeInTheDocument(); + await userEvent.click(screen.getByText('namespace/name')); expect(onClick).toHaveBeenCalledTimes(1); }); @@ -134,5 +135,6 @@ describe('', () => { ); expect(screen.getByText('Custom Title')).toBeInTheDocument(); + expect(screen.getByText('kind:namespace/name')).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderNode.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderNode.tsx index d55f4c015b..bc3311d33f 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderNode.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderNode.tsx @@ -14,12 +14,12 @@ * limitations under the License. */ import { DependencyGraphTypes } from '@backstage/core-components'; -import { useApp } from '@backstage/core-plugin-api'; -import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; +import { IconComponent } from '@backstage/core-plugin-api'; +import { useEntityPresentation } from '@backstage/plugin-catalog-react'; import { makeStyles } from '@material-ui/core/styles'; import classNames from 'classnames'; import React, { useLayoutEffect, useRef, useState } from 'react'; -import { EntityKindIcon } from './EntityKindIcon'; +import { EntityIcon } from './EntityIcon'; import { EntityNodeData } from './types'; import { DEFAULT_NAMESPACE } from '@backstage/catalog-model'; @@ -64,8 +64,10 @@ export function DefaultRenderNode({ const classes = useStyles(); const [width, setWidth] = useState(0); const [height, setHeight] = useState(0); - const app = useApp(); const idRef = useRef(null); + const entityRefPresentationSnapshot = useEntityPresentation(entity, { + defaultNamespace: DEFAULT_NAMESPACE, + }); useLayoutEffect(() => { // set the width to the length of the ID @@ -82,25 +84,14 @@ export function DefaultRenderNode({ } }, [width, height]); - const { - kind, - metadata: { name, namespace = DEFAULT_NAMESPACE, title }, - } = entity; - - const hasKindIcon = app.getSystemIcon( - `kind:${kind.toLocaleLowerCase('en-US')}`, - ); + const hasKindIcon = !!entityRefPresentationSnapshot.Icon; const padding = 10; const iconSize = height; const paddedIconWidth = hasKindIcon ? iconSize + padding : 0; const paddedWidth = paddedIconWidth + width + padding * 2; const paddedHeight = height + padding * 2; - const displayTitle = - title ?? - (kind && name && namespace - ? humanizeEntityRef({ kind, name, namespace }) - : id); + const displayTitle = entityRefPresentationSnapshot.primaryTitle ?? id; return ( @@ -115,8 +106,8 @@ export function DefaultRenderNode({ rx={10} /> {hasKindIcon && ( - {displayTitle} + {entityRefPresentationSnapshot.entityRef} ); } diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityIcon.test.tsx similarity index 81% rename from plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx rename to plugins/catalog-graph/src/components/EntityRelationsGraph/EntityIcon.test.tsx index cc47c8850b..8683af9c1e 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.test.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityIcon.test.tsx @@ -16,12 +16,14 @@ import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; -import { EntityKindIcon } from './EntityKindIcon'; +import { EntityIcon } from './EntityIcon'; +import MuiMemoryIcon from '@material-ui/icons/Memory'; +import { IconComponent } from '@backstage/core-plugin-api'; describe('', () => { it('renders without exploding', async () => { const { baseElement } = await renderInTestApp( - , + , ); expect(baseElement.querySelector('svg')).toBeInTheDocument(); @@ -29,7 +31,7 @@ describe('', () => { it('renders without exploding for unknown kind', async () => { const { baseElement } = await renderInTestApp( - , + , ); expect(baseElement.querySelector('svg')).toBeInTheDocument(); diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityIcon.tsx similarity index 69% rename from plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.tsx rename to plugins/catalog-graph/src/components/EntityRelationsGraph/EntityIcon.tsx index 7263e25eae..a46a8bcc9d 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityKindIcon.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityIcon.tsx @@ -13,23 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { useApp } from '@backstage/core-plugin-api'; import React from 'react'; import SvgIcon from '@material-ui/core/SvgIcon'; +import { OverridableComponent } from '@material-ui/core/OverridableComponent'; +import { SvgIconTypeMap } from '@material-ui/core/SvgIcon/SvgIcon'; +import { IconComponent } from '@backstage/core-plugin-api'; -export function EntityKindIcon({ - kind, +export function EntityIcon({ + icon, ...props }: { - kind: string; + icon: IconComponent | undefined; x?: number; y?: number; width?: number; height?: number; className?: string; }) { - const app = useApp(); - const Icon = - app.getSystemIcon(`kind:${kind.toLocaleLowerCase('en-US')}`) ?? SvgIcon; + const Icon = (icon as OverridableComponent) ?? SvgIcon; return ; }