techdocs: add extensions for techdocs addons (#28644)
* techdocs: add extensions for techdocs addons Signed-off-by: Jackson Chen <jacksonc@spotify.com> * techdocs: add blueprint extension for techdocs addons Signed-off-by: Jackson Chen <jacksonc@spotify.com> * techdocs: move addons blueprint to alpha Signed-off-by: Jackson Chen <jacksonc@spotify.com> * techdocs: add addon extensions for new frontend system and add docs Signed-off-by: Jackson Chen <jacksonc@spotify.com> * techdocs: fix addon modules naming patterns Signed-off-by: Jackson Chen <jacksonc@spotify.com> * techdocs: update test utils with entity presentation api Signed-off-by: Jackson Chen <jacksonc@spotify.com> --------- Signed-off-by: Jackson Chen <jacksonc@spotify.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import { RouteRef } from '@backstage/frontend-plugin-api';
|
||||
import { SearchResultItemExtensionComponent } from '@backstage/plugin-search-react/alpha';
|
||||
import { SearchResultItemExtensionPredicate } from '@backstage/plugin-search-react/alpha';
|
||||
import { SearchResultListItemBlueprintParams } from '@backstage/plugin-search-react/alpha';
|
||||
import { TechDocsAddonOptions } from '@backstage/plugin-techdocs-react';
|
||||
|
||||
// @alpha (undocumented)
|
||||
const _default: FrontendPlugin<
|
||||
@@ -151,8 +152,6 @@ const _default: FrontendPlugin<
|
||||
params: SearchResultListItemBlueprintParams;
|
||||
}>;
|
||||
'page:techdocs/reader': ExtensionDefinition<{
|
||||
kind: 'page';
|
||||
name: 'reader';
|
||||
config: {
|
||||
path: string | undefined;
|
||||
};
|
||||
@@ -173,7 +172,21 @@ const _default: FrontendPlugin<
|
||||
optional: true;
|
||||
}
|
||||
>;
|
||||
inputs: {};
|
||||
inputs: {
|
||||
addons: ExtensionInput<
|
||||
ConfigurableExtensionDataRef<
|
||||
TechDocsAddonOptions,
|
||||
'techdocs.addon',
|
||||
{}
|
||||
>,
|
||||
{
|
||||
singleton: false;
|
||||
optional: false;
|
||||
}
|
||||
>;
|
||||
};
|
||||
kind: 'page';
|
||||
name: 'reader';
|
||||
params: {
|
||||
defaultPath: string;
|
||||
loader: () => Promise<JSX.Element>;
|
||||
@@ -234,6 +247,17 @@ const _default: FrontendPlugin<
|
||||
}
|
||||
>;
|
||||
inputs: {
|
||||
addons: ExtensionInput<
|
||||
ConfigurableExtensionDataRef<
|
||||
TechDocsAddonOptions,
|
||||
'techdocs.addon',
|
||||
{}
|
||||
>,
|
||||
{
|
||||
singleton: false;
|
||||
optional: false;
|
||||
}
|
||||
>;
|
||||
emptyState: ExtensionInput<
|
||||
ConfigurableExtensionDataRef<
|
||||
React_2.JSX.Element,
|
||||
|
||||
@@ -56,6 +56,26 @@ export const Router = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const TechDocsReaderRouter = (props: PropsWithChildren) => {
|
||||
const { children } = props;
|
||||
|
||||
// Using objects instead of <Route> elements, otherwise "outlet" will be null on sub-pages and add-ons won't render
|
||||
const element = useRoutes([
|
||||
{
|
||||
path: '*',
|
||||
element: <TechDocsReaderPage />,
|
||||
children: [
|
||||
{
|
||||
path: '*',
|
||||
element: children,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
return element;
|
||||
};
|
||||
|
||||
export const EmbeddedDocsRouter = (
|
||||
props: PropsWithChildren<{
|
||||
emptyState?: React.ReactElement;
|
||||
@@ -90,7 +110,6 @@ export const EmbeddedDocsRouter = (
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return element;
|
||||
};
|
||||
|
||||
|
||||
@@ -38,16 +38,20 @@ import {
|
||||
} from '@backstage/core-compat-api';
|
||||
import { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';
|
||||
import { SearchResultListItemBlueprint } from '@backstage/plugin-search-react/alpha';
|
||||
import {
|
||||
techdocsApiRef,
|
||||
techdocsStorageApiRef,
|
||||
} from '@backstage/plugin-techdocs-react';
|
||||
import { AddonBlueprint } from '@backstage/plugin-techdocs-react/alpha';
|
||||
import { TechDocsClient, TechDocsStorageClient } from './client';
|
||||
import {
|
||||
rootCatalogDocsRouteRef,
|
||||
rootDocsRouteRef,
|
||||
rootRouteRef,
|
||||
} from './routes';
|
||||
import { TechDocsReaderLayout } from './reader';
|
||||
import { attachTechDocsAddonComponentData } from '@backstage/plugin-techdocs-react/alpha';
|
||||
import {
|
||||
TechDocsAddons,
|
||||
techdocsApiRef,
|
||||
techdocsStorageApiRef,
|
||||
} from '@backstage/plugin-techdocs-react';
|
||||
|
||||
/** @alpha */
|
||||
const techDocsStorageApi = ApiBlueprint.make({
|
||||
@@ -138,15 +142,32 @@ const techDocsPage = PageBlueprint.make({
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
const techDocsReaderPage = PageBlueprint.make({
|
||||
const techDocsReaderPage = PageBlueprint.makeWithOverrides({
|
||||
name: 'reader',
|
||||
params: {
|
||||
defaultPath: '/docs/:namespace/:kind/:name',
|
||||
routeRef: convertLegacyRouteRef(rootDocsRouteRef),
|
||||
loader: () =>
|
||||
import('./reader/components/TechDocsReaderPage').then(m =>
|
||||
compatWrapper(<m.TechDocsReaderPage />),
|
||||
),
|
||||
inputs: {
|
||||
addons: createExtensionInput([AddonBlueprint.dataRefs.addon]),
|
||||
},
|
||||
factory(originalFactory, { inputs }) {
|
||||
const addons = inputs.addons.map(output => {
|
||||
const options = output.get(AddonBlueprint.dataRefs.addon);
|
||||
const Addon = options.component;
|
||||
attachTechDocsAddonComponentData(Addon, options);
|
||||
return <Addon key={options.name} />;
|
||||
});
|
||||
|
||||
return originalFactory({
|
||||
defaultPath: '/docs/:namespace/:kind/:name',
|
||||
routeRef: convertLegacyRouteRef(rootDocsRouteRef),
|
||||
loader: async () =>
|
||||
await import('./Router').then(({ TechDocsReaderRouter }) => {
|
||||
return compatWrapper(
|
||||
<TechDocsReaderRouter>
|
||||
<TechDocsReaderLayout />
|
||||
<TechDocsAddons>{addons}</TechDocsAddons>
|
||||
</TechDocsReaderRouter>,
|
||||
);
|
||||
}),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -157,6 +178,7 @@ const techDocsReaderPage = PageBlueprint.make({
|
||||
*/
|
||||
const techDocsEntityContent = EntityContentBlueprint.makeWithOverrides({
|
||||
inputs: {
|
||||
addons: createExtensionInput([AddonBlueprint.dataRefs.addon]),
|
||||
emptyState: createExtensionInput(
|
||||
[coreExtensionData.reactElement.optional()],
|
||||
{
|
||||
@@ -172,15 +194,23 @@ const techDocsEntityContent = EntityContentBlueprint.makeWithOverrides({
|
||||
defaultTitle: 'TechDocs',
|
||||
routeRef: convertLegacyRouteRef(rootCatalogDocsRouteRef),
|
||||
loader: () =>
|
||||
import('./Router').then(({ EmbeddedDocsRouter }) =>
|
||||
compatWrapper(
|
||||
import('./Router').then(({ EmbeddedDocsRouter }) => {
|
||||
const addons = context.inputs.addons.map(output => {
|
||||
const options = output.get(AddonBlueprint.dataRefs.addon);
|
||||
const Addon = options.component;
|
||||
attachTechDocsAddonComponentData(Addon, options);
|
||||
return <Addon key={options.name} />;
|
||||
});
|
||||
return compatWrapper(
|
||||
<EmbeddedDocsRouter
|
||||
emptyState={context.inputs.emptyState?.get(
|
||||
coreExtensionData.reactElement,
|
||||
)}
|
||||
/>,
|
||||
),
|
||||
),
|
||||
>
|
||||
<TechDocsAddons>{addons}</TechDocsAddons>
|
||||
</EmbeddedDocsRouter>,
|
||||
);
|
||||
}),
|
||||
},
|
||||
context,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user