From 3fdc1b4f71b7af0d0798ff7560351be78877cfa6 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 1 Apr 2022 00:51:00 +0200 Subject: [PATCH] fix(techdocs): add backwards compatibility Signed-off-by: Camila Belo --- packages/app/src/App.tsx | 3 +- .../src/components/techdocs/TechDocsPage.tsx | 5 +- plugins/techdocs/src/EntityPageDocs.tsx | 6 +- .../TechDocsReaderPage/TechDocsReaderPage.tsx | 60 ++++++++++++++----- .../TechDocsReaderPage/context.test.tsx | 14 +---- .../TechDocsReaderPageContent.tsx | 53 ++++++++-------- .../TechDocsReaderPageHeader.test.tsx | 18 ++---- .../TechDocsReaderPageHeader.tsx | 3 +- 8 files changed, 90 insertions(+), 72 deletions(-) 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)} );