diff --git a/.changeset/replace-humanize-entity-ref-catalog-import.md b/.changeset/replace-humanize-entity-ref-catalog-import.md new file mode 100644 index 0000000000..544e91bac3 --- /dev/null +++ b/.changeset/replace-humanize-entity-ref-catalog-import.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Replaced `humanizeEntityRef` with `defaultEntityPresentation` from the Catalog Presentation API in `StepPrepareCreatePullRequest`. diff --git a/.changeset/replace-humanize-entity-ref-catalog-react.md b/.changeset/replace-humanize-entity-ref-catalog-react.md new file mode 100644 index 0000000000..b44e796624 --- /dev/null +++ b/.changeset/replace-humanize-entity-ref-catalog-react.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Replaced `humanizeEntityRef` with `defaultEntityPresentation` and `useEntityPresentation` from the Catalog Presentation API in `EntityOwnerPicker`, `EntityTable`, `EntityDataTable`, and `AncestryPage` components. diff --git a/.changeset/replace-humanize-entity-ref-catalog.md b/.changeset/replace-humanize-entity-ref-catalog.md new file mode 100644 index 0000000000..2a27c87f47 --- /dev/null +++ b/.changeset/replace-humanize-entity-ref-catalog.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Replaced `humanizeEntityRef` with `defaultEntityPresentation` from the Catalog Presentation API in `CatalogTable` and its column factories. diff --git a/.changeset/replace-humanize-entity-ref-org-react.md b/.changeset/replace-humanize-entity-ref-org-react.md new file mode 100644 index 0000000000..afb04d3348 --- /dev/null +++ b/.changeset/replace-humanize-entity-ref-org-react.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org-react': patch +--- + +Replaced `humanizeEntityRef` with `defaultEntityPresentation` from the Catalog Presentation API in `GroupListPicker`. diff --git a/.changeset/replace-humanize-entity-ref-scaffolder.md b/.changeset/replace-humanize-entity-ref-scaffolder.md new file mode 100644 index 0000000000..5064875451 --- /dev/null +++ b/.changeset/replace-humanize-entity-ref-scaffolder.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Replaced `humanizeEntityRef` with `defaultEntityPresentation` from the Catalog Presentation API in `TemplateFormPreviewer`. diff --git a/.changeset/replace-humanize-entity-ref-techdocs.md b/.changeset/replace-humanize-entity-ref-techdocs.md new file mode 100644 index 0000000000..374a0c2e8e --- /dev/null +++ b/.changeset/replace-humanize-entity-ref-techdocs.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Replaced `humanizeEntityRef` with `defaultEntityPresentation` from the Catalog Presentation API in TechDocs table helpers. diff --git a/docs/features/software-catalog/entity-presentation.md b/docs/features/software-catalog/entity-presentation.md new file mode 100644 index 0000000000..5d65baac07 --- /dev/null +++ b/docs/features/software-catalog/entity-presentation.md @@ -0,0 +1,117 @@ +--- +id: entity-presentation +title: Entity Presentation +description: How to display entity names and control how entities are represented in the Backstage interface +--- + +The _Entity Presentation API_ controls how catalog entities are displayed +throughout the Backstage interface. Instead of rendering raw entity refs like +`component:default/my-service`, the API resolves a human-friendly display +name from fields such as `metadata.title` and `spec.profile.displayName`. + +## Displaying entity names + +There are three ways to display entity names, depending on context: + +### `EntityDisplayName` component + +The simplest option for React components. Renders a styled entity name with +an optional icon and tooltip: + +```tsx +import { EntityDisplayName } from '@backstage/plugin-catalog-react'; + +; +``` + +You can pass an entity ref string, an `Entity` object, or a +`CompoundEntityRef`. The component supports optional `hideIcon` and +`disableTooltip` props. + +### `useEntityPresentation` hook + +Use this hook when you need access to the raw presentation data in a React +component, for example to render the title in a custom layout: + +```tsx +import { useEntityPresentation } from '@backstage/plugin-catalog-react'; + +function MyComponent({ entityRef }: { entityRef: string }) { + const { primaryTitle, secondaryTitle, Icon } = + useEntityPresentation(entityRef); + + return ( + + {Icon && } + {primaryTitle} + + ); +} +``` + +The hook subscribes to the `EntityPresentationApi` and returns a snapshot +that may update over time as additional data is fetched in the background. +If no presentation API is registered, it falls back to +`defaultEntityPresentation`. + +### `defaultEntityPresentation` function + +A synchronous helper for non-React contexts where hooks are not available. +Use it in sort comparators, filter functions, table column factories, and +data mappers: + +```ts +import { defaultEntityPresentation } from '@backstage/plugin-catalog-react'; + +const title = defaultEntityPresentation(entity, { + defaultKind: 'Component', +}).primaryTitle; +``` + +This resolves `primaryTitle` as the first available value among +`spec.profile.displayName`, `metadata.title`, and a shortened entity ref. + +## Customizing entity presentation + +To customize how entities are rendered, provide your own implementation of +the `EntityPresentationApi` interface and register it with the app's API +factory: + +```ts +import { + entityPresentationApiRef, + type EntityPresentationApi, +} from '@backstage/plugin-catalog-react'; +import { createApiFactory } from '@backstage/core-plugin-api'; + +const myPresentationApi: EntityPresentationApi = { + forEntity(entityOrRef, context) { + // Return an EntityRefPresentation with snapshot, update$, and promise + }, +}; + +createApiFactory({ + api: entityPresentationApiRef, + deps: {}, + factory: () => myPresentationApi, +}); +``` + +The presentation snapshot includes `primaryTitle`, an optional +`secondaryTitle` for tooltips, and an optional `Icon` component. You can +also emit updated snapshots over time via the `update$` observable. + +## Migrating from `humanizeEntityRef` + +The `humanizeEntityRef` and `humanizeEntity` functions are deprecated. They +only produce a shortened entity ref string and do not resolve display names +from `metadata.title` or `spec.profile.displayName`. + +Replace them as follows: + +| Old code | Replacement | +| :------------------------------------------------------------------ | :---------------------------------------------------------------- | +| `humanizeEntityRef(entity)` in JSX | `` | +| `humanizeEntityRef(entity)` in a hook-accessible context | `useEntityPresentation(entity).primaryTitle` | +| `humanizeEntityRef(entity, { defaultKind })` in a sort/filter/label | `defaultEntityPresentation(entity, { defaultKind }).primaryTitle` | +| `humanizeEntity(entity, fallback)` | `defaultEntityPresentation(entity).primaryTitle` | diff --git a/mkdocs.yml b/mkdocs.yml index e01ab2a431..ef0b2bae91 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -62,6 +62,7 @@ nav: - Extending the model: 'features/software-catalog/extending-the-model.md' - External integrations: 'features/software-catalog/external-integrations.md' - Catalog Customization: 'features/software-catalog/catalog-customization.md' + - Entity Presentation: 'features/software-catalog/entity-presentation.md' - API: 'features/software-catalog/api.md' - FAQ: 'features/software-catalog/faq.md' - Kubernetes: diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx index e42de5257e..3cb9fbbd39 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx @@ -20,7 +20,7 @@ import { assertError } from '@backstage/errors'; import { useTranslationRef } from '@backstage/frontend-plugin-api'; import { catalogApiRef, - humanizeEntityRef, + defaultEntityPresentation, } from '@backstage/plugin-catalog-react'; import Box from '@material-ui/core/Box'; import FormHelperText from '@material-ui/core/FormHelperText'; @@ -162,7 +162,10 @@ export const StepPrepareCreatePullRequest = ( }); return groupEntities.items - .map(e => humanizeEntityRef(e, { defaultKind: 'group' })) + .map( + e => + defaultEntityPresentation(e, { defaultKind: 'group' }).primaryTitle, + ) .sort(); }); diff --git a/plugins/catalog-react/report.api.md b/plugins/catalog-react/report.api.md index f7f195c226..bb9d43edb0 100644 --- a/plugins/catalog-react/report.api.md +++ b/plugins/catalog-react/report.api.md @@ -834,7 +834,7 @@ export function getEntitySourceLocation( scmIntegrationsApi: typeof scmIntegrationsApiRef.T, ): EntitySourceLocation | undefined; -// @public (undocumented) +// @public @deprecated (undocumented) export function humanizeEntityRef( entityRef: Entity | CompoundEntityRef, opts?: { diff --git a/plugins/catalog-react/src/apis/EntityPresentationApi/EntityPresentationApi.ts b/plugins/catalog-react/src/apis/EntityPresentationApi/EntityPresentationApi.ts index 642dd6dbac..e293d1e0ab 100644 --- a/plugins/catalog-react/src/apis/EntityPresentationApi/EntityPresentationApi.ts +++ b/plugins/catalog-react/src/apis/EntityPresentationApi/EntityPresentationApi.ts @@ -25,6 +25,21 @@ import { Observable } from '@backstage/types'; /** * An API that handles how to represent entities in the interface. * + * @remarks + * + * There are several ways to consume this API depending on context: + * + * - In React components, use the {@link useEntityPresentation} hook to get a + * reactive presentation snapshot that updates over time. + * + * - For simple inline rendering, use the {@link EntityDisplayName} component + * which wraps the hook and renders a styled entity name with optional icon + * and tooltip. + * + * - In non-React contexts such as sort comparators, filter functions, or data + * mappers, use the {@link defaultEntityPresentation} function which + * synchronously extracts a display name from an already-loaded entity. + * * @public */ export const entityPresentationApiRef: ApiRef = @@ -120,8 +135,19 @@ export interface EntityRefPresentation { * * @remarks * - * Most consumers will want to use the {@link useEntityPresentation} hook - * instead of this interface directly. + * Most consumers will not need to interact with this interface directly. + * Instead, use one of the following: + * + * - {@link useEntityPresentation} — React hook for reactive presentation data. + * + * - {@link EntityDisplayName} — React component that renders an entity name + * with optional icon and tooltip. + * + * - {@link defaultEntityPresentation} — synchronous helper for non-React + * contexts where you already have the entity object. + * + * Implement this interface to customize how entities are displayed throughout + * the Backstage interface. * * @public */ diff --git a/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.ts b/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.ts index b546f9aa93..9c1cbd5325 100644 --- a/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.ts +++ b/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.ts @@ -24,7 +24,20 @@ import get from 'lodash/get'; import { EntityRefPresentationSnapshot } from './EntityPresentationApi'; /** - * This returns the default representation of an entity. + * Returns the default representation of an entity. + * + * @remarks + * + * This is a synchronous helper that extracts a display name from an + * already-loaded entity or entity ref. It resolves `primaryTitle` as the + * first available value among `spec.profile.displayName`, `metadata.title`, + * and a shortened entity ref string. + * + * Use this in non-React contexts where hooks are not available, such as sort + * comparators, filter functions, table column factories, and data mappers. + * In React components, prefer the {@link useEntityPresentation} hook or the + * {@link EntityDisplayName} component, which support async enrichment via + * the {@link EntityPresentationApi}. * * @public * @param entityOrRef - Either an entity, or a ref to it. diff --git a/plugins/catalog-react/src/apis/EntityPresentationApi/useEntityPresentation.ts b/plugins/catalog-react/src/apis/EntityPresentationApi/useEntityPresentation.ts index e397558ed0..2e01485dcc 100644 --- a/plugins/catalog-react/src/apis/EntityPresentationApi/useEntityPresentation.ts +++ b/plugins/catalog-react/src/apis/EntityPresentationApi/useEntityPresentation.ts @@ -32,6 +32,19 @@ import { useUpdatingObservable } from './useUpdatingObservable'; /** * Returns information about how to represent an entity in the interface. * + * @remarks + * + * This hook subscribes to the {@link EntityPresentationApi} and returns a + * snapshot that may update over time as richer data is fetched (for example, + * resolving `metadata.title` from a string entity ref). If no presentation + * API is registered, it falls back to {@link defaultEntityPresentation}. + * + * For simple inline rendering, consider using the {@link EntityDisplayName} + * component instead, which wraps this hook with icon and tooltip support. + * + * For non-React contexts such as sort comparators or data mappers, use + * {@link defaultEntityPresentation} directly. + * * @public * @param entityOrRef - The entity to represent, or an entity ref to it. If you * pass in an entity, it is assumed that it is NOT a partial one - i.e. only diff --git a/plugins/catalog-react/src/components/EntityDataTable/columnFactories.tsx b/plugins/catalog-react/src/components/EntityDataTable/columnFactories.tsx index 49fb64caa8..647e7c7f3b 100644 --- a/plugins/catalog-react/src/components/EntityDataTable/columnFactories.tsx +++ b/plugins/catalog-react/src/components/EntityDataTable/columnFactories.tsx @@ -20,11 +20,8 @@ import { RELATION_PART_OF, } from '@backstage/catalog-model'; import { Cell, CellText, Column, ColumnConfig, TableItem } from '@backstage/ui'; -import { - EntityRefLink, - EntityRefLinks, - humanizeEntityRef, -} from '../EntityRefLink'; +import { EntityRefLink, EntityRefLinks } from '../EntityRefLink'; +import { defaultEntityPresentation } from '../../apis'; import { EntityTableColumnTitle } from '../EntityTable/TitleColumn'; import { getEntityRelations } from '../../utils'; @@ -63,8 +60,8 @@ export const columnFactories = Object.freeze({ ), sortValue: entity => - entity.metadata?.title || - humanizeEntityRef(entity, { defaultKind: options.defaultKind }), + defaultEntityPresentation(entity, { defaultKind: options.defaultKind }) + .primaryTitle, }; }, @@ -98,7 +95,12 @@ export const columnFactories = Object.freeze({ ), sortValue: entity => getEntityRelations(entity, options.relation, options.filter) - .map(r => humanizeEntityRef(r, { defaultKind: options.defaultKind })) + .map( + r => + defaultEntityPresentation(r, { + defaultKind: options.defaultKind, + }).primaryTitle, + ) .join(', '), }; }, diff --git a/plugins/catalog-react/src/components/EntityDisplayName/EntityDisplayName.tsx b/plugins/catalog-react/src/components/EntityDisplayName/EntityDisplayName.tsx index a4134df465..6ed863f180 100644 --- a/plugins/catalog-react/src/components/EntityDisplayName/EntityDisplayName.tsx +++ b/plugins/catalog-react/src/components/EntityDisplayName/EntityDisplayName.tsx @@ -62,6 +62,16 @@ export type EntityDisplayNameProps = { /** * Shows a nice representation of a reference to an entity. * + * @remarks + * + * This component uses the {@link useEntityPresentation} hook internally and + * renders the entity's primary title with optional icon and tooltip. It is + * the simplest way to display an entity name in JSX. + * + * For more control over the presentation data, use the + * {@link useEntityPresentation} hook directly. For non-React contexts, use + * {@link defaultEntityPresentation}. + * * @public */ export const EntityDisplayName = ( diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx index ed200c77c4..16e00e5ccd 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx @@ -33,7 +33,7 @@ import { EntityOwnerFilter } from '../../filters'; import { useDebouncedEffect } from '@react-hookz/web'; import PersonIcon from '@material-ui/icons/Person'; import GroupIcon from '@material-ui/icons/Group'; -import { humanizeEntity, humanizeEntityRef } from '../EntityRefLink/humanize'; +import { defaultEntityPresentation } from '../../apis'; import { useFetchEntities } from './useFetchEntities'; import { withStyles } from '@material-ui/core/styles'; import { useEntityPresentation } from '../../apis'; @@ -203,7 +203,7 @@ export const EntityOwnerPicker = (props?: EntityOwnerPickerProps) => { defaultNamespace: 'default', }) : o; - return humanizeEntity(entity, humanizeEntityRef(entity)); + return defaultEntityPresentation(entity).primaryTitle; }} onChange={(_: object, owners) => { setText(''); diff --git a/plugins/catalog-react/src/components/EntityRefLink/humanize.ts b/plugins/catalog-react/src/components/EntityRefLink/humanize.ts index 478f0dce9d..ae1fb5e685 100644 --- a/plugins/catalog-react/src/components/EntityRefLink/humanize.ts +++ b/plugins/catalog-react/src/components/EntityRefLink/humanize.ts @@ -25,6 +25,11 @@ import get from 'lodash/get'; * @param defaultNamespace - if set to false then namespace is never omitted, * if set to string which matches namespace of entity then omitted * + * @deprecated Use {@link defaultEntityPresentation} for non-React contexts, + * or {@link useEntityPresentation} / {@link EntityDisplayName} in React + * components. These provide richer display names using `metadata.title` and + * `spec.profile.displayName` in addition to the entity ref. + * * @public **/ export function humanizeEntityRef( @@ -76,6 +81,9 @@ export function humanizeEntityRef( * * If neither of those are found or populated, fallback to `defaultName`. * + * @deprecated Use {@link defaultEntityPresentation} instead, which provides + * the same resolution logic via `primaryTitle`. + * * @param entity - Entity to convert. * @param defaultName - If entity readable name is not available, `defaultName` will be returned. * @returns Readable name, defaults to `defaultName`. diff --git a/plugins/catalog-react/src/components/EntityTable/columns.tsx b/plugins/catalog-react/src/components/EntityTable/columns.tsx index 1bea56dc27..6b47fa02ff 100644 --- a/plugins/catalog-react/src/components/EntityTable/columns.tsx +++ b/plugins/catalog-react/src/components/EntityTable/columns.tsx @@ -22,11 +22,8 @@ import { } from '@backstage/catalog-model'; import { OverflowTooltip, TableColumn } from '@backstage/core-components'; import { getEntityRelations } from '../../utils'; -import { - EntityRefLink, - EntityRefLinks, - humanizeEntityRef, -} from '../EntityRefLink'; +import { EntityRefLink, EntityRefLinks } from '../EntityRefLink'; +import { defaultEntityPresentation } from '../../apis'; import { EntityTableColumnTitle } from './TitleColumn'; /** @public */ @@ -36,12 +33,7 @@ export const columnFactories = Object.freeze({ }): TableColumn { const { defaultKind } = options; function formatContent(entity: T): string { - return ( - entity.metadata?.title || - humanizeEntityRef(entity, { - defaultKind, - }) - ); + return defaultEntityPresentation(entity, { defaultKind }).primaryTitle; } return { @@ -84,7 +76,7 @@ export const columnFactories = Object.freeze({ function formatContent(entity: T): string { return getRelations(entity) - .map(r => humanizeEntityRef(r, { defaultKind })) + .map(r => defaultEntityPresentation(r, { defaultKind }).primaryTitle) .join(', '); } diff --git a/plugins/catalog-react/src/components/InspectEntityDialog/components/AncestryPage.tsx b/plugins/catalog-react/src/components/InspectEntityDialog/components/AncestryPage.tsx index 771eb7b279..ec7c0dd54f 100644 --- a/plugins/catalog-react/src/components/InspectEntityDialog/components/AncestryPage.tsx +++ b/plugins/catalog-react/src/components/InspectEntityDialog/components/AncestryPage.tsx @@ -35,8 +35,8 @@ import { useLayoutEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import useAsync from 'react-use/esm/useAsync'; import { catalogApiRef } from '../../../api'; -import { humanizeEntityRef } from '../../EntityRefLink'; import { entityRouteRef } from '../../../routes'; +import { useEntityPresentation } from '../../../apis'; import { EntityKindIcon } from './EntityKindIcon'; import { catalogReactTranslationRef } from '../../../translation'; import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; @@ -137,15 +137,7 @@ function CustomNode({ node }: DependencyGraphTypes.RenderNodeProps) { const paddedWidth = paddedIconWidth + width + padding * 2; const paddedHeight = height + padding * 2; - const displayTitle = - node.metadata.title || - (node.kind && node.metadata.name && node.metadata.namespace - ? humanizeEntityRef({ - kind: node.kind, - name: node.metadata.name, - namespace: node.metadata.namespace || '', - }) - : node.id); + const { primaryTitle: displayTitle } = useEntityPresentation(node); const onClick = () => { navigate( diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index 80b37002c5..200505f5be 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -29,8 +29,8 @@ import { WarningPanel, } from '@backstage/core-components'; import { + defaultEntityPresentation, getEntityRelations, - humanizeEntityRef, useEntityList, useStarredEntities, } from '@backstage/plugin-catalog-react'; @@ -71,10 +71,8 @@ export interface CatalogTableProps { const refCompare = (a: Entity, b: Entity) => { const toRef = (entity: Entity) => - entity.metadata.title || - humanizeEntityRef(entity, { - defaultKind: 'Component', - }); + defaultEntityPresentation(entity, { defaultKind: 'Component' }) + .primaryTitle; return toRef(a).localeCompare(toRef(b)); }; @@ -292,19 +290,21 @@ function toEntityRow(entity: Entity) { // This name is here for backwards compatibility mostly; the // presentation of refs in the table should in general be handled with // EntityRefLink / EntityName components - name: humanizeEntityRef(entity, { - defaultKind: 'Component', - }), + name: defaultEntityPresentation(entity, { defaultKind: 'Component' }) + .primaryTitle, entityRef: stringifyEntityRef(entity), ownedByRelationsTitle: ownedByRelations - .map(r => humanizeEntityRef(r, { defaultKind: 'group' })) + .map( + r => + defaultEntityPresentation(r, { defaultKind: 'group' }).primaryTitle, + ) .join(', '), ownedByRelations, partOfSystemRelationTitle: partOfSystemRelations - .map(r => - humanizeEntityRef(r, { - defaultKind: 'system', - }), + .map( + r => + defaultEntityPresentation(r, { defaultKind: 'system' }) + .primaryTitle, ) .join(', '), partOfSystemRelations, diff --git a/plugins/catalog/src/components/CatalogTable/columns.tsx b/plugins/catalog/src/components/CatalogTable/columns.tsx index d2216149cd..8a18b301e6 100644 --- a/plugins/catalog/src/components/CatalogTable/columns.tsx +++ b/plugins/catalog/src/components/CatalogTable/columns.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import { - humanizeEntityRef, + defaultEntityPresentation, EntityRefLink, EntityRefLinks, } from '@backstage/plugin-catalog-react'; @@ -33,12 +33,9 @@ export const columnFactories = Object.freeze({ defaultKind?: string; }): TableColumn { function formatContent(entity: Entity): string { - return ( - entity.metadata?.title || - humanizeEntityRef(entity, { - defaultKind: options?.defaultKind, - }) - ); + return defaultEntityPresentation(entity, { + defaultKind: options?.defaultKind, + }).primaryTitle; } return { diff --git a/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx b/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx index 12dc69073b..b836d30aff 100644 --- a/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx +++ b/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx @@ -17,7 +17,7 @@ import { MouseEvent, useState, useCallback } from 'react'; import { catalogApiRef, - humanizeEntityRef, + defaultEntityPresentation, } from '@backstage/plugin-catalog-react'; import TextField from '@material-ui/core/TextField'; import Autocomplete from '@material-ui/lab/Autocomplete'; @@ -25,7 +25,7 @@ import useAsync from 'react-use/esm/useAsync'; import Popover from '@material-ui/core/Popover'; import { useApi } from '@backstage/core-plugin-api'; import { ResponseErrorPanel } from '@backstage/core-components'; -import { Entity, GroupEntity } from '@backstage/catalog-model'; +import { GroupEntity } from '@backstage/catalog-model'; import { GroupListPickerButton } from './GroupListPickerButton'; /** @@ -85,8 +85,6 @@ export const GroupListPicker = (props: GroupListPickerProps) => { return ; } - const getHumanEntityRef = (entity: Entity) => humanizeEntityRef(entity); - return ( <> { options={groups ?? []} groupBy={option => option.spec.type} getOptionLabel={option => - option.spec.profile?.displayName ?? getHumanEntityRef(option) + defaultEntityPresentation(option).primaryTitle } inputValue={inputValue} onInputChange={(_, value) => setInputValue(value)} diff --git a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateFormPreviewer.tsx index cb40ff2766..d2db8c4a62 100644 --- a/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/alpha/components/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -24,7 +24,7 @@ import { makeStyles } from '@material-ui/core/styles'; import { alertApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; import { catalogApiRef, - humanizeEntityRef, + defaultEntityPresentation, } from '@backstage/plugin-catalog-react'; import { LayoutOptions, @@ -169,9 +169,9 @@ export const TemplateFormPreviewer = ({ .then(({ items }) => setTemplateOptions( items.map(template => ({ - label: - template.metadata.title ?? - humanizeEntityRef(template, { defaultKind: 'template' }), + label: defaultEntityPresentation(template, { + defaultKind: 'template', + }).primaryTitle, value: template, })), ), diff --git a/plugins/techdocs/src/home/components/Tables/helpers.ts b/plugins/techdocs/src/home/components/Tables/helpers.ts index 4c6383c35e..5c972b0233 100644 --- a/plugins/techdocs/src/home/components/Tables/helpers.ts +++ b/plugins/techdocs/src/home/components/Tables/helpers.ts @@ -16,8 +16,8 @@ import { RELATION_OWNED_BY, Entity } from '@backstage/catalog-model'; import { + defaultEntityPresentation, getEntityRelations, - humanizeEntityRef, } from '@backstage/plugin-catalog-react'; import { toLowerMaybe } from '../../../helpers'; import { ConfigApi, RouteFunc } from '@backstage/core-plugin-api'; @@ -48,7 +48,11 @@ export function entitiesToDocsMapper( }), ownedByRelations, ownedByRelationsTitle: ownedByRelations - .map(r => humanizeEntityRef(r, { defaultKind: 'group' })) + .map( + r => + defaultEntityPresentation(r, { defaultKind: 'group' }) + .primaryTitle, + ) .join(', '), }, };