implement suggestions

Signed-off-by: secustor <sebastian@poxhofer.at>
This commit is contained in:
secustor
2025-09-16 22:22:58 +02:00
parent 579f2ad003
commit eda37c161d
9 changed files with 83 additions and 86 deletions
+2 -2
View File
@@ -46,7 +46,7 @@ import { convertLegacyEntityContentExtension } from '@backstage/plugin-catalog-r
import { pluginInfoResolver } from './pluginInfoResolver';
import { appModuleNav } from './modules/appModuleNav';
import devtoolsPlugin from '@backstage/plugin-devtools/alpha';
import { unprocessedEntitiesDevToolsRoute } from '@backstage/plugin-catalog-unprocessed-entities/alpha';
import { unprocessedEntitiesDevToolsContent } from '@backstage/plugin-catalog-unprocessed-entities/alpha';
/*
@@ -115,7 +115,7 @@ const customHomePageModule = createFrontendModule({
const notFoundErrorPageModule = createFrontendModule({
pluginId: 'app',
extensions: [notFoundErrorPage, unprocessedEntitiesDevToolsRoute],
extensions: [notFoundErrorPage, unprocessedEntitiesDevToolsContent],
});
const collectedLegacyPlugins = convertLegacyAppRoot(
@@ -14,23 +14,23 @@
* limitations under the License.
*/
import { createElement } from 'react';
import { DevToolsRouteBlueprint } from '@backstage/plugin-devtools-react';
import { DevToolsContentBlueprint } from '@backstage/plugin-devtools-react';
import { compatWrapper } from '@backstage/core-compat-api';
/**
* DevTools route extension for catalog unprocessed entities
* This demonstrates how to create extensions at the app level using the new DevTools extension system
* DevTools content for catalog unprocessed entities.
*
* @alpha
*/
export const unprocessedEntitiesDevToolsRoute = DevToolsRouteBlueprint.make({
params: {
path: 'unprocessed-entities',
title: 'Unprocessed Entities',
loader: () =>
import('../components/UnprocessedEntities').then(
({ UnprocessedEntitiesContent }) =>
createElement(UnprocessedEntitiesContent),
),
export const unprocessedEntitiesDevToolsContent = DevToolsContentBlueprint.make(
{
params: {
path: 'unprocessed-entities',
title: 'Unprocessed Entities',
loader: () =>
import('../components/UnprocessedEntities').then(m =>
compatWrapper(<m.UnprocessedEntitiesContent />),
),
},
},
});
);
@@ -15,4 +15,4 @@
*/
export { default } from './plugin';
export { unprocessedEntitiesDevToolsRoute } from './devToolsRoute';
export { unprocessedEntitiesDevToolsContent } from './devToolsRoute';
@@ -15,11 +15,13 @@
*/
import {
coreExtensionData,
createExtensionBlueprint,
ExtensionBoundary,
RouteRef,
} from '@backstage/frontend-plugin-api';
import { devToolsRouteDataRef } from './devToolsRouteDataRef';
import { JSX } from 'react';
import { contentTitleDataRef } from './extensionData';
/**
* Parameters for creating a DevTools route extension
@@ -29,6 +31,7 @@ export interface DevToolsRouteBlueprintParams {
path: string;
title: string;
loader: () => Promise<JSX.Element>;
routeRef?: RouteRef;
}
/**
@@ -46,22 +49,38 @@ export interface DevToolsRouteBlueprintParams {
* ```
* @public
*/
export const DevToolsRouteBlueprint = createExtensionBlueprint({
kind: 'devtools-route',
attachTo: { id: 'page:devtools', input: 'routes' },
output: [devToolsRouteDataRef],
factory(params: DevToolsRouteBlueprintParams, { node }) {
const children = ExtensionBoundary.lazy(node, params.loader);
return [
devToolsRouteDataRef({
path: params.path,
title: params.title,
children,
}),
];
},
export const DevToolsContentBlueprint = createExtensionBlueprint({
kind: 'devtools-content',
attachTo: { id: 'page:devtools', input: 'contents' },
output: [
coreExtensionData.reactElement,
coreExtensionData.routePath,
coreExtensionData.routeRef.optional(),
contentTitleDataRef,
],
dataRefs: {
route: devToolsRouteDataRef,
title: contentTitleDataRef,
},
config: {
schema: {
path: z => z.string().optional(),
title: z => z.string().optional(),
},
},
*factory(params: DevToolsRouteBlueprintParams, { node, config }) {
const path = config.path ?? params.path;
const title = config.title ?? params.title;
yield coreExtensionData.reactElement(
ExtensionBoundary.lazy(node, params.loader),
);
yield coreExtensionData.routePath(path);
yield contentTitleDataRef(title);
if (params.routeRef) {
yield coreExtensionData.routeRef(params.routeRef);
}
},
});
@@ -1,5 +1,5 @@
/*
* Copyright 2024 The Backstage Authors
* Copyright 2025 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,25 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createExtensionDataRef } from '@backstage/frontend-plugin-api';
import { JSX } from 'react';
/**
* Represents a DevTools route that can be contributed by extensions
* @public
*/
export interface DevToolsRouteData {
path: string;
title: string;
children: JSX.Element;
}
/**
* Extension data reference for DevTools routes
* @public
*/
export const devToolsRouteDataRef =
createExtensionDataRef<DevToolsRouteData>().with({
id: 'devtools.route',
});
/** @internal */
export const contentTitleDataRef = createExtensionDataRef<string>().with({
id: 'devtools.content-title',
});
+2 -6
View File
@@ -19,11 +19,7 @@
*
* @packageDocumentation
*/
export {
type DevToolsRouteData,
devToolsRouteDataRef,
} from './devToolsRouteDataRef';
export {
type DevToolsRouteBlueprintParams,
DevToolsRouteBlueprint,
} from './devToolsRouteBlueprint.tsx';
DevToolsContentBlueprint,
} from './devToolsContentBlueprint.tsx';
+12 -11
View File
@@ -22,6 +22,7 @@ import {
PageBlueprint,
NavItemBlueprint,
createExtensionInput,
coreExtensionData,
} from '@backstage/frontend-plugin-api';
import { devToolsApiRef, DevToolsClient } from '../api';
@@ -31,7 +32,6 @@ import {
} from '@backstage/core-compat-api';
import BuildIcon from '@material-ui/icons/Build';
import { rootRouteRef } from '../routes';
import { devToolsRouteDataRef } from '@backstage/plugin-devtools-react';
/** @alpha */
export const devToolsApi = ApiBlueprint.make({
@@ -50,9 +50,16 @@ export const devToolsApi = ApiBlueprint.make({
/** @alpha */
export const devToolsPage = PageBlueprint.makeWithOverrides({
inputs: {
routes: createExtensionInput([devToolsRouteDataRef], {
optional: true,
}),
contents: createExtensionInput(
[
coreExtensionData.reactElement,
coreExtensionData.routePath,
coreExtensionData.routeRef.optional(),
],
{
optional: true,
},
),
},
factory(originalFactory, { inputs }) {
return originalFactory({
@@ -60,13 +67,7 @@ export const devToolsPage = PageBlueprint.makeWithOverrides({
routeRef: convertLegacyRouteRef(rootRouteRef),
loader: () =>
import('../components/DevToolsPage').then(m =>
compatWrapper(
<m.DevToolsPage
extensionRoutes={inputs.routes?.map(route =>
route.get(devToolsRouteDataRef),
)}
/>,
),
compatWrapper(<m.DevToolsPage extensions={inputs.contents} />),
),
});
},
@@ -19,14 +19,14 @@ import {
devToolsInfoReadPermission,
} from '@backstage/plugin-devtools-common';
import { ConfigContent } from '../Content/ConfigContent';
import { ConfigContent } from '../Content';
import { DevToolsLayout } from '../DevToolsLayout';
import { InfoContent } from '../Content/InfoContent';
import { InfoContent } from '../Content';
import { RequirePermission } from '@backstage/plugin-permission-react';
import { DevToolsPageProps } from '../DevToolsPage';
/** @public */
export const DefaultDevToolsPage = ({ extensionRoutes }: DevToolsPageProps) => (
export const DefaultDevToolsPage = ({ extensions }: DevToolsPageProps) => (
<DevToolsLayout>
<DevToolsLayout.Route path="info" title="Info">
<RequirePermission permission={devToolsInfoReadPermission}>
@@ -38,13 +38,13 @@ export const DefaultDevToolsPage = ({ extensionRoutes }: DevToolsPageProps) => (
<ConfigContent />
</RequirePermission>
</DevToolsLayout.Route>
{extensionRoutes?.map((route, index) => (
{extensions?.map((extension, index) => (
<DevToolsLayout.Route
key={`extension-${route.path}-${index}`}
path={route.path}
title={route.title}
key={`extension-${extension.path}-${index}`}
path={extension.path}
title={extension.title}
>
{route.children}
{extension.children}
</DevToolsLayout.Route>
))}
</DevToolsLayout>
@@ -16,19 +16,16 @@
import { useOutlet } from 'react-router-dom';
import { DefaultDevToolsPage } from '../DefaultDevToolsPage';
import { DevToolsRouteData } from '@backstage/plugin-devtools-react';
/**
@public
*/
export interface DevToolsPageProps {
extensionRoutes?: DevToolsRouteData[];
extensions?: any[];
}
export const DevToolsPage = ({ extensionRoutes }: DevToolsPageProps) => {
export const DevToolsPage = ({ extensions }: DevToolsPageProps) => {
const outlet = useOutlet();
return (
<>{outlet || <DefaultDevToolsPage extensionRoutes={extensionRoutes} />}</>
);
return <>{outlet || <DefaultDevToolsPage extensions={extensions} />}</>;
};