From deb4476146018f963c879dfcdaa09de2a76555a0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 26 Feb 2026 00:32:23 +0100 Subject: [PATCH] Address review feedback - Rename 'alpha' to 'title' for content order enum value - Inline EntityContentGroupDefinition type into EntityContentGroupDefinitions - Rename defaultContentOrder prop to contentOrder - Apply content ordering to ungrouped tabs as well - Fix no-nested-ternary lint error Signed-off-by: Patrik Oldsberg --- ...page-group-aliases-and-ordering-catalog.md | 2 +- packages/app/app-config.yaml | 4 +-- plugins/catalog-react/report-alpha.api.md | 15 ++++---- .../src/alpha/blueprints/extensionData.tsx | 19 +++++------ .../src/alpha/blueprints/index.ts | 1 - plugins/catalog/report-alpha.api.md | 8 ++--- .../components/EntityLayout/EntityLayout.tsx | 6 ++-- .../components/EntityTabs/EntityTabs.tsx | 6 ++-- .../components/EntityTabs/EntityTabsList.tsx | 34 +++++++++++++------ plugins/catalog/src/alpha/pages.test.tsx | 4 +-- plugins/catalog/src/alpha/pages.tsx | 6 ++-- 11 files changed, 56 insertions(+), 49 deletions(-) diff --git a/.changeset/entity-page-group-aliases-and-ordering-catalog.md b/.changeset/entity-page-group-aliases-and-ordering-catalog.md index b29bd483bc..c2a17ae773 100644 --- a/.changeset/entity-page-group-aliases-and-ordering-catalog.md +++ b/.changeset/entity-page-group-aliases-and-ordering-catalog.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog': minor --- -Added support for group alias IDs and configurable content ordering on the entity page. Groups can now declare `aliases` so that content targeting an aliased group is included in the group. A new `contentOrder` option (default `alpha`) controls how content items within each group are sorted, with support for both a page-level default and per-group overrides. +Added support for group alias IDs and configurable content ordering on the entity page. Groups can now declare `aliases` so that content targeting an aliased group is included in the group. A new `contentOrder` option (default `title`) controls how content items within each group are sorted, with support for both a page-level default and per-group overrides. diff --git a/packages/app/app-config.yaml b/packages/app/app-config.yaml index d22a7e2fbd..0e49365c08 100644 --- a/packages/app/app-config.yaml +++ b/packages/app/app-config.yaml @@ -48,8 +48,8 @@ app: - page:catalog/entity: config: showNavItemIcons: true - # default content order for all groups, can be 'alpha' or 'natural' - # contentOrder: alpha + # default content order for all groups, can be 'title' or 'natural' + # contentOrder: title groups: # placing a tab at the beginning - overview: diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index a9a054da26..9c76a221dc 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -339,18 +339,15 @@ export const EntityContentBlueprint: ExtensionBlueprint<{ }; }>; -// @alpha (undocumented) -export type EntityContentGroupDefinition = { - title: string; - icon?: string | ReactElement; - aliases?: string[]; - contentOrder?: 'alpha' | 'natural'; -}; - // @alpha (undocumented) export type EntityContentGroupDefinitions = Record< string, - EntityContentGroupDefinition + { + title: string; + icon?: string | ReactElement; + aliases?: string[]; + contentOrder?: 'title' | 'natural'; + } >; // @alpha (undocumented) diff --git a/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx b/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx index 292c9f367a..04c13db484 100644 --- a/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx +++ b/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx @@ -41,20 +41,17 @@ export const entityFilterExpressionDataRef = id: 'catalog.entity-filter-expression', }); -/** @alpha */ -export type EntityContentGroupDefinition = { - title: string; - icon?: string | ReactElement; - /** Other group IDs that should be treated as aliases for this group. */ - aliases?: string[]; - /** How to sort the content items within this group. Overrides the page-level default. */ - contentOrder?: 'alpha' | 'natural'; -}; - /** @alpha */ export type EntityContentGroupDefinitions = Record< string, - EntityContentGroupDefinition + { + title: string; + icon?: string | ReactElement; + /** Other group IDs that should be treated as aliases for this group. */ + aliases?: string[]; + /** How to sort the content items within this group. Overrides the page-level default. */ + contentOrder?: 'title' | 'natural'; + } >; /** diff --git a/plugins/catalog-react/src/alpha/blueprints/index.ts b/plugins/catalog-react/src/alpha/blueprints/index.ts index 507511358e..07401018cb 100644 --- a/plugins/catalog-react/src/alpha/blueprints/index.ts +++ b/plugins/catalog-react/src/alpha/blueprints/index.ts @@ -24,7 +24,6 @@ export { EntityHeaderBlueprint } from './EntityHeaderBlueprint'; export { defaultEntityContentGroups, defaultEntityContentGroupDefinitions, - type EntityContentGroupDefinition, type EntityContentGroupDefinitions, } from './extensionData'; export type { EntityCardType } from './extensionData'; diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index d164c4401f..2c44d0cefc 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -1097,12 +1097,12 @@ const _default: OverridableFrontendPlugin< { title: string; icon?: string | undefined; - contentOrder?: 'alpha' | 'natural' | undefined; + contentOrder?: 'title' | 'natural' | undefined; aliases?: string[] | undefined; } >[] | undefined; - contentOrder: 'alpha' | 'natural'; + contentOrder: 'title' | 'natural'; showNavItemIcons: boolean; path: string | undefined; title: string | undefined; @@ -1114,13 +1114,13 @@ const _default: OverridableFrontendPlugin< { title: string; icon?: string | undefined; - contentOrder?: 'alpha' | 'natural' | undefined; + contentOrder?: 'title' | 'natural' | undefined; aliases?: string[] | undefined; } >[] | undefined; + contentOrder?: 'title' | 'natural' | undefined; showNavItemIcons?: boolean | undefined; - contentOrder?: 'alpha' | 'natural' | undefined; title?: string | undefined; path?: string | undefined; }; diff --git a/plugins/catalog/src/alpha/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/alpha/components/EntityLayout/EntityLayout.tsx index 1e86c92ef8..ecee929cde 100644 --- a/plugins/catalog/src/alpha/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/alpha/components/EntityLayout/EntityLayout.tsx @@ -80,7 +80,7 @@ export interface EntityLayoutProps { */ parentEntityRelations?: string[]; groupDefinitions: EntityContentGroupDefinitions; - defaultContentOrder?: 'alpha' | 'natural'; + contentOrder?: 'title' | 'natural'; showNavItemIcons?: boolean; } @@ -111,7 +111,7 @@ export const EntityLayout = (props: EntityLayoutProps) => { NotFoundComponent, parentEntityRelations, groupDefinitions, - defaultContentOrder, + contentOrder, showNavItemIcons, } = props; const { kind } = useRouteRefParams(entityRouteRef); @@ -166,7 +166,7 @@ export const EntityLayout = (props: EntityLayoutProps) => { )} diff --git a/plugins/catalog/src/alpha/components/EntityTabs/EntityTabs.tsx b/plugins/catalog/src/alpha/components/EntityTabs/EntityTabs.tsx index 14a2e755a6..22ae70d726 100644 --- a/plugins/catalog/src/alpha/components/EntityTabs/EntityTabs.tsx +++ b/plugins/catalog/src/alpha/components/EntityTabs/EntityTabs.tsx @@ -72,12 +72,12 @@ export function useSelectedSubRoute(subRoutes: SubRoute[]): { type EntityTabsProps = { routes: SubRoute[]; groupDefinitions: EntityContentGroupDefinitions; - defaultContentOrder?: 'alpha' | 'natural'; + contentOrder?: 'title' | 'natural'; showIcons?: boolean; }; export function EntityTabs(props: EntityTabsProps) { - const { routes, groupDefinitions, defaultContentOrder, showIcons } = props; + const { routes, groupDefinitions, contentOrder, showIcons } = props; const { index, route, element } = useSelectedSubRoute(routes); @@ -108,7 +108,7 @@ export function EntityTabs(props: EntityTabsProps) { selectedIndex={index} showIcons={showIcons} groupDefinitions={groupDefinitions} - defaultContentOrder={defaultContentOrder} + contentOrder={contentOrder} /> diff --git a/plugins/catalog/src/alpha/components/EntityTabs/EntityTabsList.tsx b/plugins/catalog/src/alpha/components/EntityTabs/EntityTabsList.tsx index 3f5d735e30..e55129c573 100644 --- a/plugins/catalog/src/alpha/components/EntityTabs/EntityTabsList.tsx +++ b/plugins/catalog/src/alpha/components/EntityTabs/EntityTabsList.tsx @@ -78,11 +78,25 @@ type TabGroup = { type EntityTabsListProps = { tabs: Tab[]; groupDefinitions: EntityContentGroupDefinitions; - defaultContentOrder?: 'alpha' | 'natural'; + contentOrder?: 'title' | 'natural'; showIcons?: boolean; selectedIndex?: number; }; +function resolveGroupId( + tabGroup: string | undefined, + groupDefinitions: EntityContentGroupDefinitions, + aliasToGroup: Record, +): string | undefined { + if (!tabGroup) { + return undefined; + } + if (groupDefinitions[tabGroup]) { + return tabGroup; + } + return aliasToGroup[tabGroup]; +} + export function EntityTabsList(props: EntityTabsListProps) { const styles = useStyles(); const { t } = useTranslationRef(catalogTranslationRef); @@ -92,7 +106,7 @@ export function EntityTabsList(props: EntityTabsListProps) { selectedIndex = 0, showIcons, groupDefinitions, - defaultContentOrder = 'alpha', + contentOrder = 'title', } = props; const aliasToGroup = useMemo( @@ -108,11 +122,11 @@ export function EntityTabsList(props: EntityTabsListProps) { const groups = useMemo(() => { const byKey = items.reduce((result, tab) => { - const resolvedGroupId = tab.group - ? groupDefinitions[tab.group] - ? tab.group - : aliasToGroup[tab.group] - : undefined; + const resolvedGroupId = resolveGroupId( + tab.group, + groupDefinitions, + aliasToGroup, + ); const group = resolvedGroupId ? groupDefinitions[resolvedGroupId] : undefined; @@ -143,8 +157,8 @@ export function EntityTabsList(props: EntityTabsListProps) { for (const [id, tabGroup] of sorted) { const groupDef = groupDefinitions[id]; - const order = groupDef?.contentOrder ?? defaultContentOrder; - if (order === 'alpha') { + const order = groupDef?.contentOrder ?? contentOrder; + if (order === 'title') { tabGroup.items.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: 'base' }), ); @@ -152,7 +166,7 @@ export function EntityTabsList(props: EntityTabsListProps) { } return sorted; - }, [items, groupDefinitions, aliasToGroup, defaultContentOrder]); + }, [items, groupDefinitions, aliasToGroup, contentOrder]); const selectedItem = items[selectedIndex]; return ( diff --git a/plugins/catalog/src/alpha/pages.test.tsx b/plugins/catalog/src/alpha/pages.test.tsx index 2c6dfb5c9f..39f96f8d5e 100644 --- a/plugins/catalog/src/alpha/pages.test.tsx +++ b/plugins/catalog/src/alpha/pages.test.tsx @@ -482,7 +482,7 @@ describe('Entity page', () => { ); }); - it('Should sort content alphabetically by default', async () => { + it('Should sort content by title by default', async () => { const tester = createExtensionTester( Object.assign({ namespace: 'catalog' }, catalogEntityPage), ) @@ -564,7 +564,7 @@ describe('Entity page', () => { Object.assign({ namespace: 'catalog' }, catalogEntityPage), { config: { - contentOrder: 'alpha', + contentOrder: 'title', groups: [ { documentation: { diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx index 40aa217442..61801478f7 100644 --- a/plugins/catalog/src/alpha/pages.tsx +++ b/plugins/catalog/src/alpha/pages.tsx @@ -110,13 +110,13 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ title: z.string(), icon: z.string().optional(), aliases: z.array(z.string()).optional(), - contentOrder: z.enum(['alpha', 'natural']).optional(), + contentOrder: z.enum(['title', 'natural']).optional(), }), ), ) .optional(), contentOrder: z => - z.enum(['alpha', 'natural']).optional().default('alpha'), + z.enum(['title', 'natural']).optional().default('title'), showNavItemIcons: z => z.boolean().optional().default(false), }, }, @@ -178,7 +178,7 @@ export const catalogEntityPage = PageBlueprint.makeWithOverrides({ header={header} contextMenuItems={filteredMenuItems} groupDefinitions={groupDefinitions} - defaultContentOrder={config.contentOrder} + contentOrder={config.contentOrder} showNavItemIcons={config.showNavItemIcons} > {inputs.contents.map(output => (