From 0e147e8e452d3c7c9ba66fa7abfc845aef37901d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 25 Mar 2026 16:50:57 +0100 Subject: [PATCH 01/10] plugin-catalog-graph: nfs page variant and plugin title/icon - Add title, icon, and NfsCatalogGraphPage to the new frontend plugin alpha entry - Refactor catalog graph page with headerVariant for legacy vs Backstage UI header - Export NfsCatalogGraphPage from the CatalogGraphPage module Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/catalog-graph-nfs-page.md | 5 + plugins/catalog-graph/src/alpha.tsx | 5 +- .../CatalogGraphPage/CatalogGraphPage.tsx | 240 ++++++++++-------- .../src/components/CatalogGraphPage/index.ts | 2 +- 4 files changed, 150 insertions(+), 102 deletions(-) create mode 100644 .changeset/catalog-graph-nfs-page.md diff --git a/.changeset/catalog-graph-nfs-page.md b/.changeset/catalog-graph-nfs-page.md new file mode 100644 index 0000000000..ff43ffaf25 --- /dev/null +++ b/.changeset/catalog-graph-nfs-page.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-graph': patch +--- + +The new frontend plugin entry now exposes a display title and icon for navigation, and the catalog graph page uses the Backstage UI header when rendered in the new frontend system. A new `NfsCatalogGraphPage` export is available for the same layout without the legacy `Page` shell. diff --git a/plugins/catalog-graph/src/alpha.tsx b/plugins/catalog-graph/src/alpha.tsx index a0f16cda2a..e1e60f77a0 100644 --- a/plugins/catalog-graph/src/alpha.tsx +++ b/plugins/catalog-graph/src/alpha.tsx @@ -19,6 +19,7 @@ import { createFrontendPlugin, PageBlueprint, } from '@backstage/frontend-plugin-api'; +import { RiMindMap } from '@remixicon/react'; import { EntityCardBlueprint } from '@backstage/plugin-catalog-react/alpha'; import { catalogGraphRouteRef, catalogEntityRouteRef } from './routes'; import { @@ -80,7 +81,7 @@ const CatalogGraphPage = PageBlueprint.makeWithOverrides({ routeRef: catalogGraphRouteRef, loader: () => import('./components/CatalogGraphPage').then(m => ( - + )), }); }, @@ -97,6 +98,8 @@ const CatalogGraphApi = ApiBlueprint.make({ export default createFrontendPlugin({ pluginId: 'catalog-graph', + title: 'Catalog Graph', + icon: , info: { packageJson: () => import('../package.json') }, routes: { catalogGraph: catalogGraphRouteRef, diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx index 7e6420da1f..5fb913d8d7 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx @@ -27,6 +27,7 @@ import { entityRouteRef, humanizeEntityRef, } from '@backstage/plugin-catalog-react'; +import { Header as BuiHeader } from '@backstage/ui'; import Grid from '@material-ui/core/Grid'; import Paper from '@material-ui/core/Paper'; import Typography from '@material-ui/core/Typography'; @@ -116,22 +117,27 @@ const useStyles = makeStyles( { name: 'PluginCatalogGraphCatalogGraphPage' }, ); -export const CatalogGraphPage = ( - props: { - initialState?: { - selectedRelations?: string[]; - selectedKinds?: string[]; - rootEntityRefs?: string[]; - maxDepth?: number; - unidirectional?: boolean; - mergeRelations?: boolean; - direction?: Direction; - showFilters?: boolean; - curve?: 'curveStepBefore' | 'curveMonotoneX'; - }; - } & Partial, -) => { - const { relationPairs, initialState, entityFilter } = props; +type CatalogGraphPageProps = { + initialState?: { + selectedRelations?: string[]; + selectedKinds?: string[]; + rootEntityRefs?: string[]; + maxDepth?: number; + unidirectional?: boolean; + mergeRelations?: boolean; + direction?: Direction; + showFilters?: boolean; + curve?: 'curveStepBefore' | 'curveMonotoneX'; + }; +} & Partial; + +type CatalogGraphPageContentProps = CatalogGraphPageProps & { + headerVariant: 'legacy' | 'bui'; +}; + +function CatalogGraphPageContent(props: CatalogGraphPageContentProps) { + const { headerVariant, ...graphPageProps } = props; + const { relationPairs, initialState, entityFilter } = graphPageProps; const { t } = useTranslationRef(catalogGraphTranslationRef); const navigate = useNavigate(); const classes = useStyles(); @@ -185,93 +191,127 @@ export const CatalogGraphPage = ( [catalogEntityRoute, navigate, setRootEntityNames, analytics], ); + const subtitle = rootEntityNames.map(e => humanizeEntityRef(e)).join(', '); + + const filterToggle = ( + toggleShowFilters()} + > + {t('catalogGraphPage.filterToggleButtonTitle')} + + ); + + const supportButton = ( + + {t('catalogGraphPage.supportButtonDescription')} + + ); + + const graphBody = ( + + {showFilters && ( + + + + + + + + + + )} + + + + {' '} + {t('catalogGraphPage.zoomOutDescription')} + + 0 + ? selectedKinds + : undefined + } + relations={ + selectedRelations && selectedRelations.length > 0 + ? selectedRelations + : undefined + } + mergeRelations={mergeRelations} + unidirectional={unidirectional} + onNodeClick={onNodeClick} + direction={direction} + relationPairs={relationPairs} + entityFilter={entityFilter} + className={classes.graph} + zoom="enabled" + curve={curve} + /> + + + + ); + + if (headerVariant === 'legacy') { + return ( + +
+ + + {supportButton} + + {graphBody} + + + ); + } + return ( - -
humanizeEntityRef(e)).join(', ')} + <> + + {filterToggle} + {supportButton} + + } /> - toggleShowFilters()} - > - {t('catalogGraphPage.filterToggleButtonTitle')} - - } - > - - {t('catalogGraphPage.supportButtonDescription')} - - - - {showFilters && ( - - - - - - - - - - )} - - - - {' '} - {t('catalogGraphPage.zoomOutDescription')} - - 0 - ? selectedKinds - : undefined - } - relations={ - selectedRelations && selectedRelations.length > 0 - ? selectedRelations - : undefined - } - mergeRelations={mergeRelations} - unidirectional={unidirectional} - onNodeClick={onNodeClick} - direction={direction} - relationPairs={relationPairs} - entityFilter={entityFilter} - className={classes.graph} - zoom="enabled" - curve={curve} - /> - - - + {graphBody} - + ); +} + +export const CatalogGraphPage = (props: CatalogGraphPageProps) => { + return ; +}; + +export const NfsCatalogGraphPage = (props: CatalogGraphPageProps) => { + return ; }; diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/index.ts b/plugins/catalog-graph/src/components/CatalogGraphPage/index.ts index 496e79aab4..cdf8bc9430 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/index.ts +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { CatalogGraphPage } from './CatalogGraphPage'; +export { CatalogGraphPage, NfsCatalogGraphPage } from './CatalogGraphPage'; export type { CatalogGraphPageClassKey } from './CatalogGraphPage'; export type { MaxDepthFilterClassKey } from './MaxDepthFilter'; export type { SelectedKindsFilterClassKey } from './SelectedKindsFilter'; From fa0593e6e52e1fdcc383534af63dd56f0c954ab3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 25 Mar 2026 16:52:32 +0100 Subject: [PATCH 02/10] plugin-catalog-import: add NFS page layout and plugin metadata - Register title and icon on the new-frontend createFrontendPlugin export. - Add NfsDefaultImportPage using @backstage/ui Header with shared grid body. - Point the alpha PageBlueprint loader at the NFS variant. - Depend on @backstage/ui and @remixicon/react. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/catalog-import-nfs-page.md | 5 ++ plugins/catalog-import/package.json | 2 + plugins/catalog-import/src/alpha.tsx | 8 ++- .../DefaultImportPage/DefaultImportPage.tsx | 57 +++++++++++++++---- .../src/components/DefaultImportPage/index.ts | 2 +- yarn.lock | 2 + 6 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 .changeset/catalog-import-nfs-page.md diff --git a/.changeset/catalog-import-nfs-page.md b/.changeset/catalog-import-nfs-page.md new file mode 100644 index 0000000000..362f74c12f --- /dev/null +++ b/.changeset/catalog-import-nfs-page.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Updated the catalog import plugin for the new frontend system with plugin title and icon metadata, and a page layout that uses Backstage UI header instead of legacy page chrome. diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index de96cd1f8d..dcac78437c 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -66,10 +66,12 @@ "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", + "@backstage/ui": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@octokit/rest": "^19.0.3", + "@remixicon/react": "^4.6.0", "git-url-parse": "^15.0.0", "js-base64": "^3.6.0", "lodash": "^4.17.21", diff --git a/plugins/catalog-import/src/alpha.tsx b/plugins/catalog-import/src/alpha.tsx index d0c671fe5a..af076e8317 100644 --- a/plugins/catalog-import/src/alpha.tsx +++ b/plugins/catalog-import/src/alpha.tsx @@ -14,6 +14,8 @@ * limitations under the License. */ +import { RiAddCircleLine } from '@remixicon/react'; + import { configApiRef, discoveryApiRef, @@ -49,9 +51,9 @@ const catalogImportPage = PageBlueprint.make({ path: '/catalog-import', routeRef: rootRouteRef, loader: () => - import('./components/ImportPage').then(m => ( + import('./components/DefaultImportPage').then(m => ( - + )), }, @@ -91,6 +93,8 @@ const catalogImportApi = ApiBlueprint.make({ /** @alpha */ export default createFrontendPlugin({ pluginId: 'catalog-import', + title: 'Register Existing Component', + icon: , info: { packageJson: () => import('../package.json') }, extensions: [catalogImportApi, catalogImportPage], routes: { diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx index 24a79866b3..b34ed7d640 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx @@ -23,6 +23,7 @@ import { } from '@backstage/core-components'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { Header as BuiHeader } from '@backstage/ui'; import Grid from '@material-ui/core/Grid'; import { useTheme } from '@material-ui/core/styles'; import useMediaQuery from '@material-ui/core/useMediaQuery'; @@ -31,17 +32,9 @@ import { catalogImportTranslationRef } from '../../translation'; import { ImportInfoCard } from '../ImportInfoCard'; import { ImportStepper } from '../ImportStepper'; -/** - * The default catalog import page. - * - * @public - */ -export const DefaultImportPage = () => { - const { t } = useTranslationRef(catalogImportTranslationRef); +const DefaultImportPageGrid = () => { const theme = useTheme(); - const configApi = useApi(configApiRef); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); - const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; const contentItems = [ @@ -53,6 +46,23 @@ export const DefaultImportPage = () => { , ]; + return ( + + {isMobile ? contentItems : [...contentItems].reverse()} + + ); +}; + +/** + * The default catalog import page. + * + * @public + */ +export const DefaultImportPage = () => { + const { t } = useTranslationRef(catalogImportTranslationRef); + const configApi = useApi(configApiRef); + const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; + return (
@@ -65,10 +75,33 @@ export const DefaultImportPage = () => { - - {isMobile ? contentItems : contentItems.reverse()} - + ); }; + +/** + * @public + */ +export const NfsDefaultImportPage = () => { + const { t } = useTranslationRef(catalogImportTranslationRef); + const configApi = useApi(configApiRef); + const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; + + return ( + <> + + {t('defaultImportPage.supportTitle', { appTitle })} + + } + /> + + + + + ); +}; diff --git a/plugins/catalog-import/src/components/DefaultImportPage/index.ts b/plugins/catalog-import/src/components/DefaultImportPage/index.ts index 5a4d4907e3..590d032c9b 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/index.ts +++ b/plugins/catalog-import/src/components/DefaultImportPage/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { DefaultImportPage } from './DefaultImportPage'; +export { DefaultImportPage, NfsDefaultImportPage } from './DefaultImportPage'; diff --git a/yarn.lock b/yarn.lock index 921a0c575c..cb5f247af1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5245,10 +5245,12 @@ __metadata: "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" "@backstage/test-utils": "workspace:^" + "@backstage/ui": "workspace:^" "@material-ui/core": "npm:^4.12.2" "@material-ui/icons": "npm:^4.9.1" "@material-ui/lab": "npm:4.0.0-alpha.61" "@octokit/rest": "npm:^19.0.3" + "@remixicon/react": "npm:^4.6.0" "@testing-library/dom": "npm:^10.0.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" From d156cf48bb6aeb99aaeb824335950892a436494d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 25 Mar 2026 17:05:23 +0100 Subject: [PATCH 03/10] plugins: add title, icon, and NFS page variants to migrated plugins Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/kubernetes-nfs-metadata.md | 5 +++++ .changeset/notifications-nfs-metadata.md | 5 +++++ .changeset/org-nfs-metadata.md | 5 +++++ .changeset/signals-nfs-metadata.md | 5 +++++ plugins/catalog-import/report.api.md | 3 +++ plugins/kubernetes/package.json | 3 ++- plugins/kubernetes/src/alpha/plugin.tsx | 3 +++ plugins/notifications/package.json | 1 + plugins/notifications/src/alpha.tsx | 3 +++ plugins/org/package.json | 1 + plugins/org/src/alpha.tsx | 3 +++ plugins/signals/package.json | 1 + plugins/signals/src/alpha.tsx | 3 +++ yarn.lock | 4 ++++ 14 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 .changeset/kubernetes-nfs-metadata.md create mode 100644 .changeset/notifications-nfs-metadata.md create mode 100644 .changeset/org-nfs-metadata.md create mode 100644 .changeset/signals-nfs-metadata.md diff --git a/.changeset/kubernetes-nfs-metadata.md b/.changeset/kubernetes-nfs-metadata.md new file mode 100644 index 0000000000..fb80bdb1a1 --- /dev/null +++ b/.changeset/kubernetes-nfs-metadata.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes': patch +--- + +Added `title` and `icon` to the new frontend system plugin definition. diff --git a/.changeset/notifications-nfs-metadata.md b/.changeset/notifications-nfs-metadata.md new file mode 100644 index 0000000000..10ee3bbd8c --- /dev/null +++ b/.changeset/notifications-nfs-metadata.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-notifications': patch +--- + +Added `title` and `icon` to the new frontend system plugin definition. diff --git a/.changeset/org-nfs-metadata.md b/.changeset/org-nfs-metadata.md new file mode 100644 index 0000000000..759cffbd30 --- /dev/null +++ b/.changeset/org-nfs-metadata.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Added `title` and `icon` to the new frontend system plugin definition. diff --git a/.changeset/signals-nfs-metadata.md b/.changeset/signals-nfs-metadata.md new file mode 100644 index 0000000000..de9c09421b --- /dev/null +++ b/.changeset/signals-nfs-metadata.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-signals': patch +--- + +Added `title` and `icon` to the new frontend system plugin definition. diff --git a/plugins/catalog-import/report.api.md b/plugins/catalog-import/report.api.md index 7eff3a7a9c..14c8bbc1f1 100644 --- a/plugins/catalog-import/report.api.md +++ b/plugins/catalog-import/report.api.md @@ -298,6 +298,9 @@ export interface ImportStepperProps { variant?: InfoCardVariants; } +// @public (undocumented) +export const NfsDefaultImportPage: () => JSX_2.Element; + // @public export const PreparePullRequestForm: >( props: PreparePullRequestFormProps, diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index f55a5e9b57..218b38cc85 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -66,7 +66,8 @@ "@backstage/plugin-kubernetes-common": "workspace:^", "@backstage/plugin-kubernetes-react": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", - "@material-ui/core": "^4.12.2" + "@material-ui/core": "^4.12.2", + "@remixicon/react": "^4.6.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/kubernetes/src/alpha/plugin.tsx b/plugins/kubernetes/src/alpha/plugin.tsx index fdca467886..17040b7b76 100644 --- a/plugins/kubernetes/src/alpha/plugin.tsx +++ b/plugins/kubernetes/src/alpha/plugin.tsx @@ -15,6 +15,7 @@ */ import { createFrontendPlugin } from '@backstage/frontend-plugin-api'; +import { RiShipLine } from '@remixicon/react'; import { kubernetesPage } from './pages'; import { entityKubernetesContent } from './entityContents'; import { rootCatalogKubernetesRouteRef } from '../plugin'; @@ -27,6 +28,8 @@ import { export default createFrontendPlugin({ pluginId: 'kubernetes', + title: 'Kubernetes', + icon: , info: { packageJson: () => import('../../package.json') }, extensions: [ kubernetesPage, diff --git a/plugins/notifications/package.json b/plugins/notifications/package.json index 943135a3c0..58ac16a7bf 100644 --- a/plugins/notifications/package.json +++ b/plugins/notifications/package.json @@ -61,6 +61,7 @@ "@backstage/ui": "workspace:^", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", + "@remixicon/react": "^4.6.0", "lodash": "^4.17.21", "material-ui-confirm": "^3.0.12", "notistack": "^3.0.1", diff --git a/plugins/notifications/src/alpha.tsx b/plugins/notifications/src/alpha.tsx index a40bc96b84..aa51d22261 100644 --- a/plugins/notifications/src/alpha.tsx +++ b/plugins/notifications/src/alpha.tsx @@ -21,6 +21,7 @@ import { discoveryApiRef, fetchApiRef, } from '@backstage/frontend-plugin-api'; +import { RiNotification3Line } from '@remixicon/react'; import { rootRouteRef } from './routes'; import { NotificationsClient, notificationsApiRef } from './api'; @@ -48,6 +49,8 @@ const api = ApiBlueprint.make({ /** @alpha */ export default createFrontendPlugin({ pluginId: 'notifications', + title: 'Notifications', + icon: , info: { packageJson: () => import('../package.json') }, routes: { root: rootRouteRef, diff --git a/plugins/org/package.json b/plugins/org/package.json index 694e252535..307b675b35 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -61,6 +61,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", + "@remixicon/react": "^4.6.0", "lodash": "^4.17.21", "p-limit": "^3.1.0", "pluralize": "^8.0.0", diff --git a/plugins/org/src/alpha.tsx b/plugins/org/src/alpha.tsx index 80155c8467..41e8082545 100644 --- a/plugins/org/src/alpha.tsx +++ b/plugins/org/src/alpha.tsx @@ -15,6 +15,7 @@ */ import { createFrontendPlugin } from '@backstage/frontend-plugin-api'; +import { RiTeamLine } from '@remixicon/react'; import { catalogIndexRouteRef } from './routes'; import { EntityCardBlueprint } from '@backstage/plugin-catalog-react/alpha'; @@ -118,6 +119,8 @@ const EntityUserProfileCard = EntityCardBlueprint.makeWithOverrides({ /** @alpha */ export default createFrontendPlugin({ pluginId: 'org', + title: 'Org', + icon: , info: { packageJson: () => import('../package.json') }, extensions: [ EntityGroupProfileCard, diff --git a/plugins/signals/package.json b/plugins/signals/package.json index 6752b09b6c..4e06dd4105 100644 --- a/plugins/signals/package.json +++ b/plugins/signals/package.json @@ -58,6 +58,7 @@ "@backstage/theme": "workspace:^", "@backstage/types": "workspace:^", "@material-ui/core": "^4.12.4", + "@remixicon/react": "^4.6.0", "uuid": "^11.0.0" }, "devDependencies": { diff --git a/plugins/signals/src/alpha.tsx b/plugins/signals/src/alpha.tsx index c32bff140e..3cab21f00c 100644 --- a/plugins/signals/src/alpha.tsx +++ b/plugins/signals/src/alpha.tsx @@ -20,6 +20,7 @@ import { discoveryApiRef, identityApiRef, } from '@backstage/frontend-plugin-api'; +import { RiBroadcastLine } from '@remixicon/react'; import { signalApiRef } from '@backstage/plugin-signals-react'; import { SignalClient } from './api/SignalClient'; @@ -43,6 +44,8 @@ const api = ApiBlueprint.make({ /** @alpha */ export default createFrontendPlugin({ pluginId: 'signals', + title: 'Signals', + icon: , info: { packageJson: () => import('../package.json') }, extensions: [api], }); diff --git a/yarn.lock b/yarn.lock index cb5f247af1..424fa1ef8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6078,6 +6078,7 @@ __metadata: "@backstage/plugin-permission-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@material-ui/core": "npm:^4.12.2" + "@remixicon/react": "npm:^4.6.0" "@testing-library/dom": "npm:^10.0.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" @@ -6279,6 +6280,7 @@ __metadata: "@backstage/ui": "workspace:^" "@material-ui/core": "npm:^4.9.13" "@material-ui/icons": "npm:^4.9.1" + "@remixicon/react": "npm:^4.6.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" "@types/react": "npm:^18.0.0" @@ -6361,6 +6363,7 @@ __metadata: "@material-ui/core": "npm:^4.12.2" "@material-ui/icons": "npm:^4.9.1" "@material-ui/lab": "npm:4.0.0-alpha.61" + "@remixicon/react": "npm:^4.6.0" "@testing-library/dom": "npm:^10.0.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" @@ -7426,6 +7429,7 @@ __metadata: "@backstage/theme": "workspace:^" "@backstage/types": "workspace:^" "@material-ui/core": "npm:^4.12.4" + "@remixicon/react": "npm:^4.6.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" "@types/react": "npm:^18.0.0" From daaaa72ebb477a5e8afbbe50adaf9b145cb6567f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 25 Mar 2026 22:53:03 +0100 Subject: [PATCH 04/10] e2e: use exact name matching for sidebar link assertions New plugin nav items like "Catalog Graph" cause Playwright's substring-based getByRole name matching to find multiple elements when searching for "Catalog". Switch to exact: true. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/app/e2e-tests/app.test.ts | 8 ++++++-- .../templates/next-app/packages/app/e2e-tests/app.test.ts | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/app/e2e-tests/app.test.ts b/packages/app/e2e-tests/app.test.ts index 6d16d134c7..d93b6eed32 100644 --- a/packages/app/e2e-tests/app.test.ts +++ b/packages/app/e2e-tests/app.test.ts @@ -25,7 +25,11 @@ test('App should render the welcome page', async ({ page }) => { // Verify the sidebar navigation is visible after sign-in await expect( - page.getByRole('navigation').getByRole('link', { name: 'Catalog' }), + page + .getByRole('navigation') + .getByRole('link', { name: 'Catalog', exact: true }), + ).toBeVisible(); + await expect( + page.getByRole('link', { name: 'APIs', exact: true }), ).toBeVisible(); - await expect(page.getByRole('link', { name: 'APIs' })).toBeVisible(); }); diff --git a/packages/create-app/templates/next-app/packages/app/e2e-tests/app.test.ts b/packages/create-app/templates/next-app/packages/app/e2e-tests/app.test.ts index 187e124bfa..d8dbc1faa8 100644 --- a/packages/create-app/templates/next-app/packages/app/e2e-tests/app.test.ts +++ b/packages/create-app/templates/next-app/packages/app/e2e-tests/app.test.ts @@ -24,6 +24,10 @@ test('App should render the welcome page', async ({ page }) => { await enterButton.click(); const nav = page.getByRole('navigation'); - await expect(nav.getByRole('link', { name: 'Catalog' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'APIs' })).toBeVisible(); + await expect( + nav.getByRole('link', { name: 'Catalog', exact: true }), + ).toBeVisible(); + await expect( + page.getByRole('link', { name: 'APIs', exact: true }), + ).toBeVisible(); }); From 3cf1950a3f8bdffac6e44cff59636b8145d66871 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 28 Mar 2026 14:03:00 +0100 Subject: [PATCH 05/10] plugin-catalog-import: move NFS page export to alpha entry point Move NfsDefaultImportPage out of the public API and export it as DefaultImportPage from the alpha entry point instead. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- plugins/catalog-import/report-alpha.api.md | 12 ++++++++---- plugins/catalog-import/report.api.md | 3 --- plugins/catalog-import/src/alpha.tsx | 4 +++- .../DefaultImportPage/DefaultImportPage.tsx | 2 +- .../src/components/DefaultImportPage/index.ts | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/plugins/catalog-import/report-alpha.api.md b/plugins/catalog-import/report-alpha.api.md index d00d4634a2..b4847f06f1 100644 --- a/plugins/catalog-import/report-alpha.api.md +++ b/plugins/catalog-import/report-alpha.api.md @@ -11,7 +11,8 @@ import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { IconElement } from '@backstage/frontend-plugin-api'; -import { JSX as JSX_2 } from 'react'; +import { JSX as JSX_2 } from 'react/jsx-runtime'; +import { JSX as JSX_3 } from 'react'; import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -133,7 +134,7 @@ const _default: OverridableFrontendPlugin< optional: true; } > - | ExtensionDataRef + | ExtensionDataRef | ExtensionDataRef< string, 'core.title', @@ -150,7 +151,7 @@ const _default: OverridableFrontendPlugin< >; inputs: { pages: ExtensionInput< - | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef | ConfigurableExtensionDataRef | ConfigurableExtensionDataRef< RouteRef_2, @@ -184,7 +185,7 @@ const _default: OverridableFrontendPlugin< path: string; title?: string; icon?: IconElement; - loader?: () => Promise; + loader?: () => Promise; routeRef?: RouteRef_2; noHeader?: boolean; }; @@ -193,5 +194,8 @@ const _default: OverridableFrontendPlugin< >; export default _default; +// @alpha (undocumented) +export const DefaultImportPage: () => JSX_2.Element; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog-import/report.api.md b/plugins/catalog-import/report.api.md index 14c8bbc1f1..7eff3a7a9c 100644 --- a/plugins/catalog-import/report.api.md +++ b/plugins/catalog-import/report.api.md @@ -298,9 +298,6 @@ export interface ImportStepperProps { variant?: InfoCardVariants; } -// @public (undocumented) -export const NfsDefaultImportPage: () => JSX_2.Element; - // @public export const PreparePullRequestForm: >( props: PreparePullRequestFormProps, diff --git a/plugins/catalog-import/src/alpha.tsx b/plugins/catalog-import/src/alpha.tsx index af076e8317..52b7f9cfe1 100644 --- a/plugins/catalog-import/src/alpha.tsx +++ b/plugins/catalog-import/src/alpha.tsx @@ -44,6 +44,8 @@ import { catalogImportTranslationRef as _catalogImportTranslationRef } from './t */ export const catalogImportTranslationRef = _catalogImportTranslationRef; +export { NfsDefaultImportPage as DefaultImportPage } from './components/DefaultImportPage/DefaultImportPage'; + // TODO: It's currently possible to override the import page with a custom one. We need to decide // whether this type of override is typically done with an input or by overriding the entire extension. const catalogImportPage = PageBlueprint.make({ @@ -51,7 +53,7 @@ const catalogImportPage = PageBlueprint.make({ path: '/catalog-import', routeRef: rootRouteRef, loader: () => - import('./components/DefaultImportPage').then(m => ( + import('./components/DefaultImportPage/DefaultImportPage').then(m => ( diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx index b34ed7d640..5861a141e3 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx @@ -82,7 +82,7 @@ export const DefaultImportPage = () => { }; /** - * @public + * @alpha */ export const NfsDefaultImportPage = () => { const { t } = useTranslationRef(catalogImportTranslationRef); diff --git a/plugins/catalog-import/src/components/DefaultImportPage/index.ts b/plugins/catalog-import/src/components/DefaultImportPage/index.ts index 590d032c9b..5a4d4907e3 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/index.ts +++ b/plugins/catalog-import/src/components/DefaultImportPage/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { DefaultImportPage, NfsDefaultImportPage } from './DefaultImportPage'; +export { DefaultImportPage } from './DefaultImportPage'; From e923ff1485c9c96bb9f7caa379281d6bdb7e6fe6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 28 Mar 2026 14:50:59 +0100 Subject: [PATCH 06/10] Remove unnecessary NFS page component exports Page components without props don't need to be exported from the package API surface. Import directly from the component file in the alpha entry points instead. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/catalog-graph-nfs-page.md | 2 +- plugins/catalog-graph/report-alpha.api.md | 2 +- plugins/catalog-graph/src/alpha.tsx | 2 +- .../src/components/CatalogGraphPage/index.ts | 2 +- plugins/catalog-import/report-alpha.api.md | 12 ++++-------- plugins/catalog-import/src/alpha.tsx | 2 -- .../DefaultImportPage/DefaultImportPage.tsx | 3 --- 7 files changed, 8 insertions(+), 17 deletions(-) diff --git a/.changeset/catalog-graph-nfs-page.md b/.changeset/catalog-graph-nfs-page.md index ff43ffaf25..3b7a999b54 100644 --- a/.changeset/catalog-graph-nfs-page.md +++ b/.changeset/catalog-graph-nfs-page.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-graph': patch --- -The new frontend plugin entry now exposes a display title and icon for navigation, and the catalog graph page uses the Backstage UI header when rendered in the new frontend system. A new `NfsCatalogGraphPage` export is available for the same layout without the legacy `Page` shell. +The new frontend plugin entry now exposes a display title and icon for navigation, and the catalog graph page uses the Backstage UI header when rendered in the new frontend system. diff --git a/plugins/catalog-graph/report-alpha.api.md b/plugins/catalog-graph/report-alpha.api.md index 8bfbe17e9b..e40a82698a 100644 --- a/plugins/catalog-graph/report-alpha.api.md +++ b/plugins/catalog-graph/report-alpha.api.md @@ -167,8 +167,8 @@ const _default: OverridableFrontendPlugin< direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined; zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; relations?: string[] | undefined; - maxDepth?: number | undefined; rootEntityRefs?: string[] | undefined; + maxDepth?: number | undefined; kinds?: string[] | undefined; mergeRelations?: boolean | undefined; relationPairs?: [string, string][] | undefined; diff --git a/plugins/catalog-graph/src/alpha.tsx b/plugins/catalog-graph/src/alpha.tsx index e1e60f77a0..a71189c7ab 100644 --- a/plugins/catalog-graph/src/alpha.tsx +++ b/plugins/catalog-graph/src/alpha.tsx @@ -80,7 +80,7 @@ const CatalogGraphPage = PageBlueprint.makeWithOverrides({ path: '/catalog-graph', routeRef: catalogGraphRouteRef, loader: () => - import('./components/CatalogGraphPage').then(m => ( + import('./components/CatalogGraphPage/CatalogGraphPage').then(m => ( )), }); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/index.ts b/plugins/catalog-graph/src/components/CatalogGraphPage/index.ts index cdf8bc9430..496e79aab4 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/index.ts +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { CatalogGraphPage, NfsCatalogGraphPage } from './CatalogGraphPage'; +export { CatalogGraphPage } from './CatalogGraphPage'; export type { CatalogGraphPageClassKey } from './CatalogGraphPage'; export type { MaxDepthFilterClassKey } from './MaxDepthFilter'; export type { SelectedKindsFilterClassKey } from './SelectedKindsFilter'; diff --git a/plugins/catalog-import/report-alpha.api.md b/plugins/catalog-import/report-alpha.api.md index b4847f06f1..d00d4634a2 100644 --- a/plugins/catalog-import/report-alpha.api.md +++ b/plugins/catalog-import/report-alpha.api.md @@ -11,8 +11,7 @@ import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { IconElement } from '@backstage/frontend-plugin-api'; -import { JSX as JSX_2 } from 'react/jsx-runtime'; -import { JSX as JSX_3 } from 'react'; +import { JSX as JSX_2 } from 'react'; import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -134,7 +133,7 @@ const _default: OverridableFrontendPlugin< optional: true; } > - | ExtensionDataRef + | ExtensionDataRef | ExtensionDataRef< string, 'core.title', @@ -151,7 +150,7 @@ const _default: OverridableFrontendPlugin< >; inputs: { pages: ExtensionInput< - | ConfigurableExtensionDataRef + | ConfigurableExtensionDataRef | ConfigurableExtensionDataRef | ConfigurableExtensionDataRef< RouteRef_2, @@ -185,7 +184,7 @@ const _default: OverridableFrontendPlugin< path: string; title?: string; icon?: IconElement; - loader?: () => Promise; + loader?: () => Promise; routeRef?: RouteRef_2; noHeader?: boolean; }; @@ -194,8 +193,5 @@ const _default: OverridableFrontendPlugin< >; export default _default; -// @alpha (undocumented) -export const DefaultImportPage: () => JSX_2.Element; - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog-import/src/alpha.tsx b/plugins/catalog-import/src/alpha.tsx index 52b7f9cfe1..315bbc36e6 100644 --- a/plugins/catalog-import/src/alpha.tsx +++ b/plugins/catalog-import/src/alpha.tsx @@ -44,8 +44,6 @@ import { catalogImportTranslationRef as _catalogImportTranslationRef } from './t */ export const catalogImportTranslationRef = _catalogImportTranslationRef; -export { NfsDefaultImportPage as DefaultImportPage } from './components/DefaultImportPage/DefaultImportPage'; - // TODO: It's currently possible to override the import page with a custom one. We need to decide // whether this type of override is typically done with an input or by overriding the entire extension. const catalogImportPage = PageBlueprint.make({ diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx index 5861a141e3..9989bbd9b6 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx @@ -81,9 +81,6 @@ export const DefaultImportPage = () => { ); }; -/** - * @alpha - */ export const NfsDefaultImportPage = () => { const { t } = useTranslationRef(catalogImportTranslationRef); const configApi = useApi(configApiRef); From 34f5dc5ae14fcae219545e4c28ee2a2ada7b0f24 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 28 Mar 2026 15:02:28 +0100 Subject: [PATCH 07/10] Update catalog-graph alpha API report Signed-off-by: Patrik Oldsberg Made-with: Cursor --- plugins/catalog-graph/report-alpha.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-graph/report-alpha.api.md b/plugins/catalog-graph/report-alpha.api.md index e40a82698a..8bfbe17e9b 100644 --- a/plugins/catalog-graph/report-alpha.api.md +++ b/plugins/catalog-graph/report-alpha.api.md @@ -167,8 +167,8 @@ const _default: OverridableFrontendPlugin< direction?: 'TB' | 'BT' | 'LR' | 'RL' | undefined; zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; relations?: string[] | undefined; - rootEntityRefs?: string[] | undefined; maxDepth?: number | undefined; + rootEntityRefs?: string[] | undefined; kinds?: string[] | undefined; mergeRelations?: boolean | undefined; relationPairs?: [string, string][] | undefined; From 3c0b453d7e14602e9cd7a9533c43196f3c8ea318 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 30 Mar 2026 00:19:41 +0200 Subject: [PATCH 08/10] Revert NFS page variants, keep only title and icon additions Roll back the NFS page component changes (BuiHeader, headerVariant, NfsCatalogGraphPage, NfsDefaultImportPage) from catalog-graph and catalog-import plugins. Only the title and icon metadata additions to the new frontend system plugin definitions are retained. For the kubernetes plugin, replace the generic RiShipLine icon with a proper Kubernetes helm wheel SVG icon from Simple Icons. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/catalog-graph-nfs-page.md | 2 +- .changeset/catalog-import-nfs-page.md | 2 +- plugins/catalog-graph/src/alpha.tsx | 4 +- .../CatalogGraphPage/CatalogGraphPage.tsx | 240 ++++++++---------- plugins/catalog-import/package.json | 1 - plugins/catalog-import/src/alpha.tsx | 4 +- .../DefaultImportPage/DefaultImportPage.tsx | 54 +--- plugins/kubernetes/package.json | 3 +- plugins/kubernetes/src/alpha/plugin.tsx | 16 +- yarn.lock | 2 - 10 files changed, 133 insertions(+), 195 deletions(-) diff --git a/.changeset/catalog-graph-nfs-page.md b/.changeset/catalog-graph-nfs-page.md index 3b7a999b54..fac437c641 100644 --- a/.changeset/catalog-graph-nfs-page.md +++ b/.changeset/catalog-graph-nfs-page.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-graph': patch --- -The new frontend plugin entry now exposes a display title and icon for navigation, and the catalog graph page uses the Backstage UI header when rendered in the new frontend system. +Added `title` and `icon` to the new frontend system plugin definition. diff --git a/.changeset/catalog-import-nfs-page.md b/.changeset/catalog-import-nfs-page.md index 362f74c12f..2944565205 100644 --- a/.changeset/catalog-import-nfs-page.md +++ b/.changeset/catalog-import-nfs-page.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-import': patch --- -Updated the catalog import plugin for the new frontend system with plugin title and icon metadata, and a page layout that uses Backstage UI header instead of legacy page chrome. +Added `title` and `icon` to the new frontend system plugin definition. diff --git a/plugins/catalog-graph/src/alpha.tsx b/plugins/catalog-graph/src/alpha.tsx index a71189c7ab..f1b4dbc6d0 100644 --- a/plugins/catalog-graph/src/alpha.tsx +++ b/plugins/catalog-graph/src/alpha.tsx @@ -80,8 +80,8 @@ const CatalogGraphPage = PageBlueprint.makeWithOverrides({ path: '/catalog-graph', routeRef: catalogGraphRouteRef, loader: () => - import('./components/CatalogGraphPage/CatalogGraphPage').then(m => ( - + import('./components/CatalogGraphPage').then(m => ( + )), }); }, diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx index 5fb913d8d7..7e6420da1f 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx @@ -27,7 +27,6 @@ import { entityRouteRef, humanizeEntityRef, } from '@backstage/plugin-catalog-react'; -import { Header as BuiHeader } from '@backstage/ui'; import Grid from '@material-ui/core/Grid'; import Paper from '@material-ui/core/Paper'; import Typography from '@material-ui/core/Typography'; @@ -117,27 +116,22 @@ const useStyles = makeStyles( { name: 'PluginCatalogGraphCatalogGraphPage' }, ); -type CatalogGraphPageProps = { - initialState?: { - selectedRelations?: string[]; - selectedKinds?: string[]; - rootEntityRefs?: string[]; - maxDepth?: number; - unidirectional?: boolean; - mergeRelations?: boolean; - direction?: Direction; - showFilters?: boolean; - curve?: 'curveStepBefore' | 'curveMonotoneX'; - }; -} & Partial; - -type CatalogGraphPageContentProps = CatalogGraphPageProps & { - headerVariant: 'legacy' | 'bui'; -}; - -function CatalogGraphPageContent(props: CatalogGraphPageContentProps) { - const { headerVariant, ...graphPageProps } = props; - const { relationPairs, initialState, entityFilter } = graphPageProps; +export const CatalogGraphPage = ( + props: { + initialState?: { + selectedRelations?: string[]; + selectedKinds?: string[]; + rootEntityRefs?: string[]; + maxDepth?: number; + unidirectional?: boolean; + mergeRelations?: boolean; + direction?: Direction; + showFilters?: boolean; + curve?: 'curveStepBefore' | 'curveMonotoneX'; + }; + } & Partial, +) => { + const { relationPairs, initialState, entityFilter } = props; const { t } = useTranslationRef(catalogGraphTranslationRef); const navigate = useNavigate(); const classes = useStyles(); @@ -191,127 +185,93 @@ function CatalogGraphPageContent(props: CatalogGraphPageContentProps) { [catalogEntityRoute, navigate, setRootEntityNames, analytics], ); - const subtitle = rootEntityNames.map(e => humanizeEntityRef(e)).join(', '); - - const filterToggle = ( - toggleShowFilters()} - > - {t('catalogGraphPage.filterToggleButtonTitle')} - - ); - - const supportButton = ( - - {t('catalogGraphPage.supportButtonDescription')} - - ); - - const graphBody = ( - - {showFilters && ( - - - - - - - - - - )} - - - - {' '} - {t('catalogGraphPage.zoomOutDescription')} - - 0 - ? selectedKinds - : undefined - } - relations={ - selectedRelations && selectedRelations.length > 0 - ? selectedRelations - : undefined - } - mergeRelations={mergeRelations} - unidirectional={unidirectional} - onNodeClick={onNodeClick} - direction={direction} - relationPairs={relationPairs} - entityFilter={entityFilter} - className={classes.graph} - zoom="enabled" - curve={curve} - /> - - - - ); - - if (headerVariant === 'legacy') { - return ( - -
- - - {supportButton} - - {graphBody} - - - ); - } - return ( - <> - - {filterToggle} - {supportButton} - - } + +
humanizeEntityRef(e)).join(', ')} /> - {graphBody} + toggleShowFilters()} + > + {t('catalogGraphPage.filterToggleButtonTitle')} + + } + > + + {t('catalogGraphPage.supportButtonDescription')} + + + + {showFilters && ( + + + + + + + + + + )} + + + + {' '} + {t('catalogGraphPage.zoomOutDescription')} + + 0 + ? selectedKinds + : undefined + } + relations={ + selectedRelations && selectedRelations.length > 0 + ? selectedRelations + : undefined + } + mergeRelations={mergeRelations} + unidirectional={unidirectional} + onNodeClick={onNodeClick} + direction={direction} + relationPairs={relationPairs} + entityFilter={entityFilter} + className={classes.graph} + zoom="enabled" + curve={curve} + /> + + + - + ); -} - -export const CatalogGraphPage = (props: CatalogGraphPageProps) => { - return ; -}; - -export const NfsCatalogGraphPage = (props: CatalogGraphPageProps) => { - return ; }; diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index dcac78437c..028c7017e7 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -66,7 +66,6 @@ "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", - "@backstage/ui": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", diff --git a/plugins/catalog-import/src/alpha.tsx b/plugins/catalog-import/src/alpha.tsx index 315bbc36e6..dcbc8886e4 100644 --- a/plugins/catalog-import/src/alpha.tsx +++ b/plugins/catalog-import/src/alpha.tsx @@ -51,9 +51,9 @@ const catalogImportPage = PageBlueprint.make({ path: '/catalog-import', routeRef: rootRouteRef, loader: () => - import('./components/DefaultImportPage/DefaultImportPage').then(m => ( + import('./components/ImportPage').then(m => ( - + )), }, diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx index 9989bbd9b6..24a79866b3 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx @@ -23,7 +23,6 @@ import { } from '@backstage/core-components'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { useTranslationRef } from '@backstage/frontend-plugin-api'; -import { Header as BuiHeader } from '@backstage/ui'; import Grid from '@material-ui/core/Grid'; import { useTheme } from '@material-ui/core/styles'; import useMediaQuery from '@material-ui/core/useMediaQuery'; @@ -32,9 +31,17 @@ import { catalogImportTranslationRef } from '../../translation'; import { ImportInfoCard } from '../ImportInfoCard'; import { ImportStepper } from '../ImportStepper'; -const DefaultImportPageGrid = () => { +/** + * The default catalog import page. + * + * @public + */ +export const DefaultImportPage = () => { + const { t } = useTranslationRef(catalogImportTranslationRef); const theme = useTheme(); + const configApi = useApi(configApiRef); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; const contentItems = [ @@ -46,23 +53,6 @@ const DefaultImportPageGrid = () => { , ]; - return ( - - {isMobile ? contentItems : [...contentItems].reverse()} - - ); -}; - -/** - * The default catalog import page. - * - * @public - */ -export const DefaultImportPage = () => { - const { t } = useTranslationRef(catalogImportTranslationRef); - const configApi = useApi(configApiRef); - const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; - return (
@@ -75,30 +65,10 @@ export const DefaultImportPage = () => { - + + {isMobile ? contentItems : contentItems.reverse()} + ); }; - -export const NfsDefaultImportPage = () => { - const { t } = useTranslationRef(catalogImportTranslationRef); - const configApi = useApi(configApiRef); - const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; - - return ( - <> - - {t('defaultImportPage.supportTitle', { appTitle })} - - } - /> - - - - - ); -}; diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 218b38cc85..f55a5e9b57 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -66,8 +66,7 @@ "@backstage/plugin-kubernetes-common": "workspace:^", "@backstage/plugin-kubernetes-react": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", - "@material-ui/core": "^4.12.2", - "@remixicon/react": "^4.6.0" + "@material-ui/core": "^4.12.2" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/plugins/kubernetes/src/alpha/plugin.tsx b/plugins/kubernetes/src/alpha/plugin.tsx index 17040b7b76..283961b514 100644 --- a/plugins/kubernetes/src/alpha/plugin.tsx +++ b/plugins/kubernetes/src/alpha/plugin.tsx @@ -15,7 +15,6 @@ */ import { createFrontendPlugin } from '@backstage/frontend-plugin-api'; -import { RiShipLine } from '@remixicon/react'; import { kubernetesPage } from './pages'; import { entityKubernetesContent } from './entityContents'; import { rootCatalogKubernetesRouteRef } from '../plugin'; @@ -26,10 +25,23 @@ import { kubernetesProxyApi, } from './apis'; +// Kubernetes helm wheel from Simple Icons (https://simpleicons.org/?q=kubernetes), licensed under CC0 +const KubernetesIcon = () => ( + + + +); + export default createFrontendPlugin({ pluginId: 'kubernetes', title: 'Kubernetes', - icon: , + icon: , info: { packageJson: () => import('../../package.json') }, extensions: [ kubernetesPage, diff --git a/yarn.lock b/yarn.lock index 424fa1ef8b..a1eb767437 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5245,7 +5245,6 @@ __metadata: "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" "@backstage/test-utils": "workspace:^" - "@backstage/ui": "workspace:^" "@material-ui/core": "npm:^4.12.2" "@material-ui/icons": "npm:^4.9.1" "@material-ui/lab": "npm:4.0.0-alpha.61" @@ -6078,7 +6077,6 @@ __metadata: "@backstage/plugin-permission-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@material-ui/core": "npm:^4.12.2" - "@remixicon/react": "npm:^4.6.0" "@testing-library/dom": "npm:^10.0.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" From e1b0ed1cff012a1ed9aa3658fb072f47f755f44a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 30 Mar 2026 12:28:44 +0200 Subject: [PATCH 09/10] Fix changeset to target catalog-import instead of catalog-graph Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/catalog-graph-nfs-page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/catalog-graph-nfs-page.md b/.changeset/catalog-graph-nfs-page.md index fac437c641..2944565205 100644 --- a/.changeset/catalog-graph-nfs-page.md +++ b/.changeset/catalog-graph-nfs-page.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-graph': patch +'@backstage/plugin-catalog-import': patch --- Added `title` and `icon` to the new frontend system plugin definition. From ebc6622ec5574a106fe9f77ed08597ea39e6a34a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 30 Mar 2026 16:43:43 +0200 Subject: [PATCH 10/10] Apply suggestion from @freben MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- .changeset/catalog-graph-nfs-page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/catalog-graph-nfs-page.md b/.changeset/catalog-graph-nfs-page.md index 2944565205..fac437c641 100644 --- a/.changeset/catalog-graph-nfs-page.md +++ b/.changeset/catalog-graph-nfs-page.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-import': patch +'@backstage/plugin-catalog-graph': patch --- Added `title` and `icon` to the new frontend system plugin definition.