diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx
index d792f2ed44..51012b042a 100644
--- a/packages/app/src/App.tsx
+++ b/packages/app/src/App.tsx
@@ -184,8 +184,9 @@ const routes = (
} />
{techDocsPage}}
+ element={}
>
+ {techDocsPage}
diff --git a/packages/app/src/components/techdocs/TechDocsPage.tsx b/packages/app/src/components/techdocs/TechDocsPage.tsx
index 170d4f8f77..89d0c74ad5 100644
--- a/packages/app/src/components/techdocs/TechDocsPage.tsx
+++ b/packages/app/src/components/techdocs/TechDocsPage.tsx
@@ -15,6 +15,7 @@
*/
import {
+ TechDocsReaderPage,
TechDocsReaderPageHeader,
TechDocsReaderPageContent,
} from '@backstage/plugin-techdocs';
@@ -22,10 +23,10 @@ import React from 'react';
const DefaultTechDocsPage = () => {
return (
- <>
+
- >
+
);
};
diff --git a/plugins/techdocs/src/EntityPageDocs.tsx b/plugins/techdocs/src/EntityPageDocs.tsx
index 6cb11a7b25..29f44f2931 100644
--- a/plugins/techdocs/src/EntityPageDocs.tsx
+++ b/plugins/techdocs/src/EntityPageDocs.tsx
@@ -24,11 +24,11 @@ import { TechDocsReaderLayout } from './reader';
type EntityPageDocsProps = { entity: Entity };
export const EntityPageDocs = ({ entity }: EntityPageDocsProps) => {
- const entityName = getCompoundEntityRef(entity);
+ const entityRef = getCompoundEntityRef(entity);
return (
-
-
+
+
);
};
diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx
index b55f42e984..f58fb610b4 100644
--- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx
+++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-import React, { ReactNode } from 'react';
-import { useParams } from 'react-router-dom';
+import React, { ReactNode, ReactChild, Children } from 'react';
+import { useOutlet, useParams } from 'react-router-dom';
import { Page } from '@backstage/core-components';
import { CompoundEntityRef } from '@backstage/catalog-model';
+import { TECHDOCS_ADDONS_WRAPPER_KEY } from '@backstage/techdocs-addons';
import { TechDocsReaderPageRenderFunction } from '../../../types';
@@ -28,27 +29,37 @@ import { TechDocsReaderPageSubheader } from '../TechDocsReaderPageSubheader';
import { TechDocsReaderPageProvider } from './context';
+type Extension = ReactChild & {
+ type: {
+ __backstage_data: {
+ map: Map;
+ };
+ };
+};
+
export type TechDocsReaderLayoutProps = {
- hideHeader?: boolean;
+ withHeader?: boolean;
withSearch?: boolean;
};
export const TechDocsReaderLayout = ({
- hideHeader = false,
withSearch,
-}: TechDocsReaderLayoutProps) => (
- <>
- {!hideHeader && }
-
-
- >
-);
+ withHeader = true,
+}: TechDocsReaderLayoutProps) => {
+ return (
+ <>
+ {withHeader && }
+
+
+ >
+ );
+};
/**
* @public
*/
export type TechDocsReaderPageProps = {
- entityName?: CompoundEntityRef;
+ entityRef?: CompoundEntityRef;
children?: TechDocsReaderPageRenderFunction | ReactNode;
};
@@ -57,12 +68,31 @@ export type TechDocsReaderPageProps = {
* @public
*/
export const TechDocsReaderPage = ({
- entityName: defaultEntityName,
- children = ,
+ entityRef,
+ children,
}: TechDocsReaderPageProps) => {
const { kind, name, namespace } = useParams();
+ const route = useOutlet() || { props: { children: [] } };
+ const entityName = entityRef ?? { kind, name, namespace };
- const entityName = defaultEntityName || { kind, name, namespace };
+ if (!children) {
+ const outlet = Children.toArray(route.props.children);
+
+ const page = outlet.find(child => {
+ const { type } = child as Extension;
+ return !type?.__backstage_data?.map?.get(TECHDOCS_ADDONS_WRAPPER_KEY);
+ });
+
+ return (
+ (page as JSX.Element) || (
+
+
+
+
+
+ )
+ );
+ }
return (
diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx
index f27e5aeb58..8ec0f9fd55 100644
--- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx
+++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx
@@ -30,8 +30,6 @@ import {
useEntityMetadata,
useTechDocsMetadata,
useTechDocsReaderPage,
- TechDocsEntityProvider,
- TechDocsMetadataProvider,
TechDocsReaderPageProvider,
} from './context';
@@ -65,7 +63,6 @@ const techdocsApiMock = {
};
const wrapper = ({
- path = '',
entityName = {
kind: mockEntityMetadata.kind,
name: mockEntityMetadata.metadata.name,
@@ -73,19 +70,14 @@ const wrapper = ({
},
children,
}: {
- path?: string;
entityName?: CompoundEntityRef;
children: React.ReactNode;
}) => (
-
-
-
- {children}
-
-
-
+
+ {children}
+
);
diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx
index 4a823a9e7c..b5cfd38e3c 100644
--- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx
+++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import React, { useRef, useState, useEffect, useCallback } from 'react';
+import React, { useState, useCallback } from 'react';
import { create } from 'jss';
import { makeStyles, Grid, Portal } from '@material-ui/core';
@@ -45,16 +45,16 @@ const useStyles = makeStyles({
export type TechDocsReaderPageContentProps = {
withSearch?: boolean;
+ onReady?: () => void;
};
export const TechDocsReaderPageContent = withTechDocsReaderProvider(
- ({ withSearch = true }: TechDocsReaderPageContentProps) => {
+ ({ withSearch = true, onReady }: TechDocsReaderPageContentProps) => {
const classes = useStyles();
const addons = useTechDocsAddons();
- const { entityName, setShadowRoot } = useTechDocsReaderPage();
+ const { entityName, shadowRoot, setShadowRoot } = useTechDocsReaderPage();
const dom = useTechDocsReaderDom(entityName);
- const ref = useRef(null);
const [jss, setJss] = useState(
create({
...jssPreset(),
@@ -62,31 +62,36 @@ export const TechDocsReaderPageContent = withTechDocsReaderProvider(
}),
);
- useEffect(() => {
- const shadowHost = ref.current;
- if (!dom || !shadowHost) return;
+ const ref = useCallback(
+ (shadowHost: HTMLDivElement) => {
+ if (!dom || !shadowHost) return;
- setJss(
- create({
- ...jssPreset(),
- insertionPoint: dom.querySelector('head') || undefined,
- }),
- );
+ setJss(
+ create({
+ ...jssPreset(),
+ insertionPoint: dom.querySelector('head') || undefined,
+ }),
+ );
- const shadowRoot =
- shadowHost.shadowRoot ?? shadowHost.attachShadow({ mode: 'open' });
- shadowRoot.innerHTML = '';
- shadowRoot.appendChild(dom);
- setShadowRoot(shadowRoot);
- }, [dom, setShadowRoot]);
-
- const contentElement = ref.current?.querySelector(
- '[data-md-component="container"]',
+ const newShadowRoot =
+ shadowHost.shadowRoot ?? shadowHost.attachShadow({ mode: 'open' });
+ newShadowRoot.innerHTML = '';
+ newShadowRoot.appendChild(dom);
+ setShadowRoot(newShadowRoot);
+ if (onReady instanceof Function) {
+ onReady();
+ }
+ },
+ [dom, setShadowRoot, onReady],
);
- const primarySidebarElement = ref.current?.querySelector(
+
+ const contentElement = shadowRoot?.querySelector(
+ '[data-md-component="content"]',
+ );
+ const primarySidebarElement = shadowRoot?.querySelector(
'div[data-md-component="sidebar"][data-md-type="navigation"], div[data-md-component="navigation"]',
);
- const secondarySidebarElement = ref.current?.querySelector(
+ const secondarySidebarElement = shadowRoot?.querySelector(
'div[data-md-component="sidebar"][data-md-type="toc"], div[data-md-component="toc"]',
);
diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx
index 3fb05a400e..0ace77c2ed 100644
--- a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx
+++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx
@@ -26,11 +26,7 @@ import { renderInTestApp, TestApiProvider } from '@backstage/test-utils';
import { techdocsApiRef } from '../../../api';
import { rootRouteRef } from '../../../routes';
-import {
- TechDocsEntityProvider,
- TechDocsMetadataProvider,
- TechDocsReaderPageProvider,
-} from '../TechDocsReaderPage';
+import { TechDocsReaderPageProvider } from '../TechDocsReaderPage';
import { TechDocsReaderPageHeader } from './TechDocsReaderPageHeader';
@@ -64,7 +60,6 @@ const techdocsApiMock = {
};
const Wrapper = ({
- path = '',
entityName = {
kind: mockEntityMetadata.kind,
name: mockEntityMetadata.metadata.name,
@@ -72,19 +67,14 @@ const Wrapper = ({
},
children,
}: {
- path?: string;
entityName?: CompoundEntityRef;
children: React.ReactNode;
}) => (
-
-
-
- {children}
-
-
-
+
+ {children}
+
);
diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx
index 3f9a5b9e1f..8875581473 100644
--- a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx
+++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx
@@ -39,7 +39,7 @@ import { rootRouteRef } from '../../../routes';
const skeleton = ;
-export const TechDocsReaderPageHeader: FC = ({ children }) => {
+export const TechDocsReaderPageHeader = () => {
const addons = useTechDocsAddons();
const configApi = useApi(configApiRef);
@@ -135,7 +135,6 @@ export const TechDocsReaderPageHeader: FC = ({ children }) => {
{tabTitle}
{labels}
- {children}
{addons.renderComponentsByLocation(locations.HEADER)}
);