fix(techdocs): add backwards compatibility

Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
Camila Belo
2022-04-01 00:51:00 +02:00
committed by Emma Indal
parent 6412209815
commit 3fdc1b4f71
8 changed files with 90 additions and 72 deletions
+3 -3
View File
@@ -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 (
<TechDocsReaderPage entityName={entityName}>
<TechDocsReaderLayout hideHeader />
<TechDocsReaderPage entityRef={entityRef}>
<TechDocsReaderLayout withHeader={false} />
</TechDocsReaderPage>
);
};
@@ -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<string, boolean>;
};
};
};
export type TechDocsReaderLayoutProps = {
hideHeader?: boolean;
withHeader?: boolean;
withSearch?: boolean;
};
export const TechDocsReaderLayout = ({
hideHeader = false,
withSearch,
}: TechDocsReaderLayoutProps) => (
<>
{!hideHeader && <TechDocsReaderPageHeader />}
<TechDocsReaderPageSubheader />
<TechDocsReaderPageContent withSearch={withSearch} />
</>
);
withHeader = true,
}: TechDocsReaderLayoutProps) => {
return (
<>
{withHeader && <TechDocsReaderPageHeader />}
<TechDocsReaderPageSubheader />
<TechDocsReaderPageContent withSearch={withSearch} />
</>
);
};
/**
* @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 = <TechDocsReaderLayout />,
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) || (
<TechDocsReaderPageProvider entityName={entityName}>
<Page themeId="documentation">
<TechDocsReaderLayout />
</Page>
</TechDocsReaderPageProvider>
)
);
}
return (
<TechDocsReaderPageProvider entityName={entityName}>
@@ -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;
}) => (
<ThemeProvider theme={lightTheme}>
<TestApiProvider apis={[[techdocsApiRef, techdocsApiMock]]}>
<TechDocsMetadataProvider entityName={entityName}>
<TechDocsEntityProvider entityName={entityName}>
<TechDocsReaderPageProvider path={path} entityName={entityName}>
{children}
</TechDocsReaderPageProvider>
</TechDocsEntityProvider>
</TechDocsMetadataProvider>
<TechDocsReaderPageProvider entityName={entityName}>
{children}
</TechDocsReaderPageProvider>
</TestApiProvider>
</ThemeProvider>
);
@@ -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<HTMLDivElement | null>(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"]',
);
@@ -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;
}) => (
<ThemeProvider theme={lightTheme}>
<TestApiProvider apis={[[techdocsApiRef, techdocsApiMock]]}>
<TechDocsMetadataProvider entityName={entityName}>
<TechDocsEntityProvider entityName={entityName}>
<TechDocsReaderPageProvider path={path} entityName={entityName}>
{children}
</TechDocsReaderPageProvider>
</TechDocsEntityProvider>
</TechDocsMetadataProvider>
<TechDocsReaderPageProvider entityName={entityName}>
{children}
</TechDocsReaderPageProvider>
</TestApiProvider>
</ThemeProvider>
);
@@ -39,7 +39,7 @@ import { rootRouteRef } from '../../../routes';
const skeleton = <Skeleton animation="wave" variant="text" height={40} />;
export const TechDocsReaderPageHeader: FC = ({ children }) => {
export const TechDocsReaderPageHeader = () => {
const addons = useTechDocsAddons();
const configApi = useApi(configApiRef);
@@ -135,7 +135,6 @@ export const TechDocsReaderPageHeader: FC = ({ children }) => {
<title>{tabTitle}</title>
</Helmet>
{labels}
{children}
{addons.renderComponentsByLocation(locations.HEADER)}
</Header>
);