Add support for Pages and Sidebar items in existing app

Co-authored-by: Fredrik Adelöw <freben@gmail.com>
Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Camila Belo <camilaibs@gmail.com>
Co-authored-by: Philipp Hugenroth <philipph@spotify.com>
Signed-off-by: Johan Haals <johan.haals@gmail.com>
This commit is contained in:
Johan Haals
2023-09-13 14:55:51 +02:00
parent 474cd71ab8
commit 1807df9dbd
13 changed files with 180 additions and 13 deletions
@@ -65,7 +65,13 @@ const SidebarLogo = () => {
export const CoreNav = createExtension({
id: 'core.nav',
at: 'core.layout/nav',
inputs: {},
inputs: {
targets: {
extensionData: {
path: coreExtensionData.navTarget,
},
},
},
output: {
element: coreExtensionData.reactElement,
},
@@ -47,6 +47,8 @@ import {
RouteRef,
BackstagePlugin as LegacyBackstagePlugin,
featureFlagsApiRef,
attachComponentData,
useRouteRef,
} from '@backstage/core-plugin-api';
import { getAvailablePlugins } from './discovery';
import {
@@ -74,7 +76,8 @@ import {
icons as defaultIcons,
themes as defaultThemes,
} from '../../../app-defaults/src/defaults';
import { BrowserRouter } from 'react-router-dom';
import { BrowserRouter, Route } from 'react-router-dom';
import { SidebarItem } from '@backstage/core-components';
/** @public */
export interface ExtensionTreeNode {
@@ -86,6 +89,8 @@ export interface ExtensionTreeNode {
export interface ExtensionTree {
getExtension(id: string): ExtensionTreeNode | undefined;
getExtensionAttachments(id: string, inputName: string): ExtensionTreeNode[];
getRootRoutes(): JSX.Element[];
getSidebarItems(): JSX.Element[];
}
/** @public */
@@ -108,6 +113,51 @@ export function createExtensionTree(options: {
): ExtensionTreeNode[] {
return instances.get(id)?.attachments.get(inputName) ?? [];
},
getRootRoutes(): JSX.Element[] {
return this.getExtensionAttachments('core.routes', 'routes').map(node => {
const path = node.getData(coreExtensionData.routePath);
const element = node.getData(coreExtensionData.reactElement);
const routeRef = node.getData(coreExtensionData.routeRef);
if (!path || !element) {
throw new Error(`Invalid route extension: ${node.id}`);
}
const Component = () => {
return element;
};
attachComponentData(Component, 'core.mountPoint', routeRef);
return <Route path={path} element={<Component />} />;
});
},
getSidebarItems(): JSX.Element[] {
const RoutedSidebarItem = (props: {
title: string;
routeRef: RouteRef;
icon: IconComponent;
}): React.JSX.Element => {
const location = useRouteRef(props.routeRef);
return (
<SidebarItem icon={props.icon} to={location()} text={props.title} />
);
};
return this.getExtensionAttachments('core.nav', 'items')
.map((node, index) => {
const target = node.getData(coreExtensionData.navTarget);
if (!target) {
return null;
}
return (
<RoutedSidebarItem
key={index}
title={target.title}
icon={target.icon}
routeRef={target.routeRef}
/>
);
})
.filter((x): x is JSX.Element => !!x);
},
};
}