feat(catalog-graph): use Catalog Presentation API instead of humanizeEntityRef
Replace humanizeEntityRef with entityPresentationApiRef in CatalogGraphCard and CatalogGraphPage for consistent entity display via the Catalog Presentation API. Contributes to #20955. Signed-off-by: Matt Van Horn <matt@osc.dev> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-graph': patch
|
||||
---
|
||||
|
||||
Replaced `humanizeEntityRef` with the Catalog Presentation API in `CatalogGraphCard` and `CatalogGraphPage` components for consistent entity display.
|
||||
@@ -21,10 +21,21 @@ import {
|
||||
createTestEntityPage,
|
||||
catalogApiMock,
|
||||
} from '@backstage/plugin-catalog-react/testUtils';
|
||||
import {
|
||||
defaultEntityPresentation,
|
||||
entityPresentationApiRef,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import catalogGraphPlugin from './alpha';
|
||||
import { catalogGraphRouteRef } from './routes';
|
||||
import { catalogGraphApiRef, DefaultCatalogGraphApi } from './api';
|
||||
|
||||
const mockEntityPresentationApi = {
|
||||
forEntity(entityOrRef: Parameters<typeof defaultEntityPresentation>[0]) {
|
||||
const snapshot = defaultEntityPresentation(entityOrRef);
|
||||
return { snapshot, promise: Promise.resolve(snapshot) };
|
||||
},
|
||||
};
|
||||
|
||||
const CatalogGraphEntityCard = catalogGraphPlugin.getExtension(
|
||||
'entity-card:catalog-graph/relations',
|
||||
);
|
||||
@@ -59,6 +70,7 @@ describe('catalog-graph alpha plugin', () => {
|
||||
apis: [
|
||||
catalogApiMock({ entities: [entity] }),
|
||||
[catalogGraphApiRef, new DefaultCatalogGraphApi()],
|
||||
[entityPresentationApiRef, mockEntityPresentationApi],
|
||||
],
|
||||
});
|
||||
|
||||
@@ -96,6 +108,7 @@ describe('catalog-graph alpha plugin', () => {
|
||||
apis: [
|
||||
catalogApiMock({ entities: [entity] }),
|
||||
[catalogGraphApiRef, new DefaultCatalogGraphApi()],
|
||||
[entityPresentationApiRef, mockEntityPresentationApi],
|
||||
],
|
||||
});
|
||||
|
||||
@@ -132,6 +145,7 @@ describe('catalog-graph alpha plugin', () => {
|
||||
apis: [
|
||||
catalogApiMock({ entities: [entity] }),
|
||||
[catalogGraphApiRef, new DefaultCatalogGraphApi()],
|
||||
[entityPresentationApiRef, mockEntityPresentationApi],
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import { analyticsApiRef } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
catalogApiRef,
|
||||
EntityProvider,
|
||||
entityPresentationApiRef,
|
||||
entityRouteRef,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { catalogApiMock } from '@backstage/plugin-catalog-react/testUtils';
|
||||
@@ -36,6 +37,14 @@ import { CatalogGraphCard } from './CatalogGraphCard';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import { translationApiRef } from '@backstage/core-plugin-api/alpha';
|
||||
import { catalogGraphApiRef, DefaultCatalogGraphApi } from '../../api';
|
||||
import { defaultEntityPresentation } from '@backstage/plugin-catalog-react';
|
||||
|
||||
const mockEntityPresentationApi = {
|
||||
forEntity(entityOrRef: Parameters<typeof defaultEntityPresentation>[0]) {
|
||||
const snapshot = defaultEntityPresentation(entityOrRef);
|
||||
return { snapshot, promise: Promise.resolve(snapshot) };
|
||||
},
|
||||
};
|
||||
|
||||
describe('<CatalogGraphCard/>', () => {
|
||||
let entity: Entity;
|
||||
@@ -58,6 +67,7 @@ describe('<CatalogGraphCard/>', () => {
|
||||
[catalogApiRef, catalog],
|
||||
[translationApiRef, mockApis.translation()],
|
||||
[catalogGraphApiRef, new DefaultCatalogGraphApi()],
|
||||
[entityPresentationApiRef, mockEntityPresentationApi],
|
||||
);
|
||||
|
||||
wrapper = (
|
||||
@@ -241,7 +251,7 @@ describe('<CatalogGraphCard/>', () => {
|
||||
expect(analyticsApi.captureEvent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
action: 'click',
|
||||
subject: 'b:d/c',
|
||||
subject: 'd/c',
|
||||
attributes: {
|
||||
to: '/entity/{kind}/{namespace}/{name}',
|
||||
},
|
||||
|
||||
@@ -19,10 +19,10 @@ import {
|
||||
parseEntityRef,
|
||||
stringifyEntityRef,
|
||||
} from '@backstage/catalog-model';
|
||||
import { useAnalytics, useRouteRef } from '@backstage/core-plugin-api';
|
||||
import { useAnalytics, useRouteRef, useApi } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
EntityInfoCard,
|
||||
humanizeEntityRef,
|
||||
entityPresentationApiRef,
|
||||
useEntity,
|
||||
entityRouteRef,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
@@ -89,6 +89,7 @@ export const CatalogGraphCard = (
|
||||
const navigate = useNavigate();
|
||||
const classes = useStyles({ height });
|
||||
const analytics = useAnalytics();
|
||||
const entityPresentationApi = useApi(entityPresentationApiRef);
|
||||
|
||||
const defaultOnNodeClick = useCallback(
|
||||
(node: EntityNode, _: MouseEvent<unknown>) => {
|
||||
@@ -100,12 +101,12 @@ export const CatalogGraphCard = (
|
||||
});
|
||||
analytics.captureEvent(
|
||||
'click',
|
||||
node.entity.metadata.title ?? humanizeEntityRef(nodeEntityName),
|
||||
entityPresentationApi.forEntity(node.entity).snapshot.primaryTitle,
|
||||
{ attributes: { to: path } },
|
||||
);
|
||||
navigate(path);
|
||||
},
|
||||
[catalogEntityRoute, navigate, analytics],
|
||||
[catalogEntityRoute, navigate, analytics, entityPresentationApi],
|
||||
);
|
||||
|
||||
const catalogGraphParams = qs.stringify(
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { parseEntityRef } from '@backstage/catalog-model';
|
||||
import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import {
|
||||
Content,
|
||||
ContentHeader,
|
||||
@@ -22,10 +22,10 @@ import {
|
||||
Page,
|
||||
SupportButton,
|
||||
} from '@backstage/core-components';
|
||||
import { useAnalytics, useRouteRef } from '@backstage/core-plugin-api';
|
||||
import { useAnalytics, useRouteRef, useApi } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
entityPresentationApiRef,
|
||||
entityRouteRef,
|
||||
humanizeEntityRef,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
@@ -157,9 +157,12 @@ export const CatalogGraphPage = (
|
||||
toggleShowFilters,
|
||||
} = useCatalogGraphPage({ initialState });
|
||||
const analytics = useAnalytics();
|
||||
const entityPresentationApi = useApi(entityPresentationApiRef);
|
||||
const onNodeClick = useCallback(
|
||||
(node: EntityNode, event: MouseEvent<unknown>) => {
|
||||
const nodeEntityName = parseEntityRef(node.id);
|
||||
const nodeTitle = entityPresentationApi.forEntity(node.entity).snapshot
|
||||
.primaryTitle;
|
||||
|
||||
if (event.shiftKey) {
|
||||
const path = catalogEntityRoute({
|
||||
@@ -168,28 +171,35 @@ export const CatalogGraphPage = (
|
||||
name: nodeEntityName.name,
|
||||
});
|
||||
|
||||
analytics.captureEvent(
|
||||
'click',
|
||||
node.entity.metadata.title ?? humanizeEntityRef(nodeEntityName),
|
||||
{ attributes: { to: path } },
|
||||
);
|
||||
analytics.captureEvent('click', nodeTitle, {
|
||||
attributes: { to: path },
|
||||
});
|
||||
navigate(path);
|
||||
} else {
|
||||
analytics.captureEvent(
|
||||
'click',
|
||||
node.entity.metadata.title ?? humanizeEntityRef(nodeEntityName),
|
||||
);
|
||||
analytics.captureEvent('click', nodeTitle);
|
||||
setRootEntityNames([nodeEntityName]);
|
||||
}
|
||||
},
|
||||
[catalogEntityRoute, navigate, setRootEntityNames, analytics],
|
||||
[
|
||||
catalogEntityRoute,
|
||||
navigate,
|
||||
setRootEntityNames,
|
||||
analytics,
|
||||
entityPresentationApi,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
<Page themeId="home">
|
||||
<Header
|
||||
title={t('catalogGraphPage.title')}
|
||||
subtitle={rootEntityNames.map(e => humanizeEntityRef(e)).join(', ')}
|
||||
subtitle={rootEntityNames
|
||||
.map(
|
||||
e =>
|
||||
entityPresentationApi.forEntity(stringifyEntityRef(e)).snapshot
|
||||
.primaryTitle,
|
||||
)
|
||||
.join(', ')}
|
||||
/>
|
||||
<Content stretch className={classes.content}>
|
||||
<ContentHeader
|
||||
|
||||
Reference in New Issue
Block a user