Testbed to help iterate on addons + correct dependency graph
Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
committed by
Emma Indal
parent
0b67af3485
commit
10a7736ced
@@ -52,6 +52,7 @@
|
||||
"@backstage/plugin-shortcuts": "^0.2.5-next.0",
|
||||
"@backstage/plugin-tech-radar": "^0.5.11-next.1",
|
||||
"@backstage/plugin-techdocs": "^1.0.1-next.1",
|
||||
"@backstage/plugin-techdocs-addons": "^0.0.0",
|
||||
"@backstage/plugin-todo": "^0.2.6-next.0",
|
||||
"@backstage/plugin-user-settings": "^0.4.3-next.0",
|
||||
"@backstage/plugin-tech-insights": "^0.1.14-next.0",
|
||||
|
||||
@@ -66,14 +66,15 @@ import { SearchPage } from '@backstage/plugin-search';
|
||||
import { TechRadarPage } from '@backstage/plugin-tech-radar';
|
||||
import {
|
||||
TechDocsIndexPage,
|
||||
techdocsPlugin,
|
||||
TechDocsReaderPage,
|
||||
techdocsPlugin,
|
||||
} from '@backstage/plugin-techdocs';
|
||||
import {
|
||||
UserSettingsPage,
|
||||
UserSettingsTab,
|
||||
} from '@backstage/plugin-user-settings';
|
||||
import { AdvancedSettings } from './components/advancedSettings';
|
||||
import { TechDocsAddons } from '@backstage/plugin-techdocs-addons';
|
||||
import AlarmIcon from '@material-ui/icons/Alarm';
|
||||
import React from 'react';
|
||||
import { hot } from 'react-hot-loader/root';
|
||||
@@ -87,10 +88,18 @@ import { defaultPreviewTemplate } from './components/scaffolder/defaultPreviewTe
|
||||
import { searchPage } from './components/search/SearchPage';
|
||||
import { providers } from './identityProviders';
|
||||
import * as plugins from './plugins';
|
||||
import { techDocsPage } from './components/techdocs/TechDocsPage';
|
||||
|
||||
// import { techDocsPage } from './components/techdocs/TechDocsPage';
|
||||
import { ApacheAirflowPage } from '@backstage/plugin-apache-airflow';
|
||||
import { PermissionedRoute } from '@backstage/plugin-permission-react';
|
||||
import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common';
|
||||
import {
|
||||
ExampleContent,
|
||||
ExampleHeader,
|
||||
ExamplePrimarySidebar,
|
||||
ExampleSecondarySidebar,
|
||||
ExampleSubHeader,
|
||||
} from './components/techdocs/ExampleAddons';
|
||||
|
||||
const app = createApp({
|
||||
apis,
|
||||
@@ -177,7 +186,13 @@ const routes = (
|
||||
path="/docs/:namespace/:kind/:name/*"
|
||||
element={<TechDocsReaderPage />}
|
||||
>
|
||||
{techDocsPage}
|
||||
<TechDocsAddons>
|
||||
<ExampleHeader />
|
||||
<ExampleSubHeader />
|
||||
<ExamplePrimarySidebar />
|
||||
<ExampleSecondarySidebar />
|
||||
<ExampleContent />
|
||||
</TechDocsAddons>
|
||||
</Route>
|
||||
<Route
|
||||
path="/create"
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { HeaderLabel } from '@backstage/core-components';
|
||||
import { techdocsPlugin } from '@backstage/plugin-techdocs';
|
||||
import {
|
||||
createTechDocsAddon,
|
||||
TechDocsAddonLocations,
|
||||
useShadowRootElements,
|
||||
} from '@backstage/plugin-techdocs-addons';
|
||||
import { Card, CardContent } from '@material-ui/core';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
/**
|
||||
* Note: this is not typically how or where one might define such things. It
|
||||
* would more typically be exported/provided by a plugin!
|
||||
*
|
||||
* In fact, this whole file and usage should be deleted before we merge things
|
||||
* in. This is just a convenient way to test the addon framework in a nice
|
||||
* end-to-end way before releasing anything.
|
||||
*/
|
||||
|
||||
export const ExampleHeader = techdocsPlugin.provide(
|
||||
createTechDocsAddon({
|
||||
name: 'ExampleHeader',
|
||||
location: TechDocsAddonLocations.HEADER,
|
||||
component: () => {
|
||||
return <HeaderLabel label="Label" value="Value" />;
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const ExampleSubHeader = techdocsPlugin.provide(
|
||||
createTechDocsAddon({
|
||||
name: 'ExampleSubHeader',
|
||||
location: TechDocsAddonLocations.SUBHEADER,
|
||||
component: () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardContent>Subheader.</CardContent>
|
||||
</Card>
|
||||
);
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const ExamplePrimarySidebar = techdocsPlugin.provide(
|
||||
createTechDocsAddon({
|
||||
name: 'ExamplePrimarySidebar',
|
||||
location: TechDocsAddonLocations.PRIMARY_SIDEBAR,
|
||||
component: () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardContent>Primary Sidebar.</CardContent>
|
||||
</Card>
|
||||
);
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const ExampleSecondarySidebar = techdocsPlugin.provide(
|
||||
createTechDocsAddon({
|
||||
name: 'ExampleSecondarySidebar',
|
||||
location: TechDocsAddonLocations.SECONDARY_SIDEBAR,
|
||||
component: () => {
|
||||
return (
|
||||
<Card>
|
||||
<CardContent>Secondary Sidebar.</CardContent>
|
||||
</Card>
|
||||
);
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const ExampleContentComponent = () => {
|
||||
const h1 = useShadowRootElements(['h1'])[0];
|
||||
useEffect(() => {
|
||||
if (h1 && !h1.innerText.startsWith('Modified: ')) {
|
||||
h1.innerText = `Modified: ${h1.innerText}`;
|
||||
}
|
||||
}, [h1]);
|
||||
return null;
|
||||
};
|
||||
|
||||
export const ExampleContent = techdocsPlugin.provide(
|
||||
createTechDocsAddon({
|
||||
name: 'ExampleContent',
|
||||
location: TechDocsAddonLocations.CONTENT,
|
||||
component: ExampleContentComponent,
|
||||
}),
|
||||
);
|
||||
@@ -7,17 +7,18 @@
|
||||
|
||||
import { AsyncState } from 'react-use/lib/useAsyncFn';
|
||||
import { ComponentType } from 'react';
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { Extension } from '@backstage/core-plugin-api';
|
||||
import { default as React_2 } from 'react';
|
||||
import { TechDocsEntityMetadata } from '@backstage/plugin-techdocs';
|
||||
import { TechDocsMetadata } from '@backstage/plugin-techdocs';
|
||||
|
||||
// @public
|
||||
export function createTechDocsAddon<TComponentProps>(
|
||||
options: TechDocsAddonOptions<TComponentProps>,
|
||||
): Extension<ComponentType<TComponentProps>>;
|
||||
|
||||
// @public
|
||||
export const TECHDOCS_ADDONS_WRAPPER_KEY = 'techdocs.addons.wrapper.v1';
|
||||
|
||||
// @public
|
||||
export type TechDocsAddonAsyncMetadata<TValue> = AsyncState<TValue | undefined>;
|
||||
|
||||
@@ -41,6 +42,20 @@ export type TechDocsAddonOptions<TAddonProps = {}> = {
|
||||
// @public
|
||||
export const TechDocsAddons: React_2.ComponentType;
|
||||
|
||||
// @public
|
||||
export type TechDocsEntityMetadata = Entity & {
|
||||
locationMetadata?: {
|
||||
type: string;
|
||||
target: string;
|
||||
};
|
||||
};
|
||||
|
||||
// @public
|
||||
export type TechDocsMetadata = {
|
||||
site_name: string;
|
||||
site_description: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export const TechDocsReaderPage: (
|
||||
props: TechDocsReaderPageProps,
|
||||
@@ -48,7 +63,9 @@ export const TechDocsReaderPage: (
|
||||
|
||||
// @public (undocumented)
|
||||
export type TechDocsReaderPageProps = {
|
||||
entityName: CompoundEntityRef;
|
||||
dom: Element | null;
|
||||
asyncEntityMetadata: AsyncState<TechDocsEntityMetadata>;
|
||||
asyncTechDocsMetadata: AsyncState<TechDocsMetadata>;
|
||||
};
|
||||
|
||||
// @public
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
"@backstage/catalog-model": "^0.13.0",
|
||||
"@backstage/core-components": "^0.9.1",
|
||||
"@backstage/core-plugin-api": "^0.8.0",
|
||||
"@backstage/plugin-techdocs": "^0.15.1",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
"@material-ui/styles": "^4.11.0",
|
||||
|
||||
@@ -27,6 +27,11 @@ import { useOutlet } from 'react-router-dom';
|
||||
import { TechDocsAddonLocations, TechDocsAddonOptions } from './types';
|
||||
|
||||
export const TECHDOCS_ADDONS_KEY = 'techdocs.addons.addon.v1';
|
||||
|
||||
/**
|
||||
* Marks the <TechDocsAddons> registry component.
|
||||
* @public
|
||||
*/
|
||||
export const TECHDOCS_ADDONS_WRAPPER_KEY = 'techdocs.addons.wrapper.v1';
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,21 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { Page } from '@backstage/core-components';
|
||||
// todo(backstage/techdocs-core): Export these from @backstage/plugin-techdocs
|
||||
import {
|
||||
withTechDocsReaderProvider,
|
||||
// @ts-ignore
|
||||
TechDocsStateIndicator as TechDocReaderPageIndicator,
|
||||
} from '@backstage/plugin-techdocs';
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { AsyncState } from 'react-use/lib/useAsyncFn';
|
||||
|
||||
import {
|
||||
TechDocsMetadataProvider,
|
||||
TechDocsEntityProvider,
|
||||
TechDocsReaderPageProvider,
|
||||
} from '../../context';
|
||||
import { TechDocsEntityMetadata, TechDocsMetadata } from '../../types';
|
||||
import { TechDocsReaderPageContent } from '../TechDocsReaderPageContent';
|
||||
import { TechDocsReaderPageHeader } from '../TechDocsReaderPageHeader';
|
||||
import { TechDocsReaderPageSubheader } from '../TechDocsReaderPageSubheader';
|
||||
@@ -36,29 +32,33 @@ import { TechDocsReaderPageSubheader } from '../TechDocsReaderPageSubheader';
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsReaderPageProps = { entityName: CompoundEntityRef };
|
||||
export type TechDocsReaderPageProps = {
|
||||
dom: Element | null;
|
||||
asyncEntityMetadata: AsyncState<TechDocsEntityMetadata>;
|
||||
asyncTechDocsMetadata: AsyncState<TechDocsMetadata>;
|
||||
};
|
||||
|
||||
/**
|
||||
* An addon-aware implementation of the TechDocsReaderPage.
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsReaderPage = (props: TechDocsReaderPageProps) => {
|
||||
const { entityName } = props;
|
||||
const Component = withTechDocsReaderProvider(() => {
|
||||
return (
|
||||
<TechDocsMetadataProvider entityName={entityName}>
|
||||
<TechDocsEntityProvider entityName={entityName}>
|
||||
<TechDocsReaderPageProvider entityName={entityName}>
|
||||
<Page themeId="documentation">
|
||||
<TechDocsReaderPageHeader />
|
||||
<TechDocsReaderPageSubheader />
|
||||
<TechDocReaderPageIndicator />
|
||||
<TechDocsReaderPageContent />
|
||||
</Page>
|
||||
</TechDocsReaderPageProvider>
|
||||
</TechDocsEntityProvider>
|
||||
</TechDocsMetadataProvider>
|
||||
);
|
||||
}, entityName);
|
||||
return <Component />;
|
||||
const { asyncEntityMetadata, asyncTechDocsMetadata, dom } = props;
|
||||
const { namespace, kind, name } = useParams();
|
||||
const entityName = { namespace, kind, name };
|
||||
return (
|
||||
<TechDocsMetadataProvider asyncValue={asyncTechDocsMetadata}>
|
||||
<TechDocsEntityProvider asyncValue={asyncEntityMetadata}>
|
||||
<TechDocsReaderPageProvider entityName={entityName}>
|
||||
<Page themeId="documentation">
|
||||
<TechDocsReaderPageHeader />
|
||||
<TechDocsReaderPageSubheader />
|
||||
{/* todo(backstage/techdocs-core): handle state indicator */}
|
||||
{/* <TechDocReaderPageIndicator /> */}
|
||||
<TechDocsReaderPageContent dom={dom} />
|
||||
</Page>
|
||||
</TechDocsReaderPageProvider>
|
||||
</TechDocsEntityProvider>
|
||||
</TechDocsMetadataProvider>
|
||||
);
|
||||
};
|
||||
|
||||
+4
-8
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
|
||||
import { Content, Progress } from '@backstage/core-components';
|
||||
// todo(backstage/techdocs-core): Export these from @backstage/plugin-techdocs
|
||||
// @ts-ignore
|
||||
import { useTechDocsReaderDom } from '@backstage/plugin-techdocs';
|
||||
import { Portal } from '@material-ui/core';
|
||||
import { StylesProvider, jssPreset } from '@material-ui/styles';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
@@ -27,7 +24,7 @@ import { useTechDocsAddons } from '../../addons';
|
||||
import { useTechDocsReaderPage } from '../../context';
|
||||
import { TechDocsAddonLocations as locations } from '../../types';
|
||||
|
||||
export const TechDocsReaderPageContent = () => {
|
||||
export const TechDocsReaderPageContent = ({ dom }: { dom: Element | null }) => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [jss, setJss] = useState(
|
||||
create({
|
||||
@@ -37,8 +34,7 @@ export const TechDocsReaderPageContent = () => {
|
||||
);
|
||||
|
||||
const addons = useTechDocsAddons();
|
||||
const { entityName, setShadowRoot } = useTechDocsReaderPage();
|
||||
const dom = useTechDocsReaderDom(entityName);
|
||||
const { setShadowRoot } = useTechDocsReaderPage();
|
||||
|
||||
useEffect(() => {
|
||||
const shadowHost = ref.current;
|
||||
@@ -61,10 +57,10 @@ export const TechDocsReaderPageContent = () => {
|
||||
'[data-md-component="container"]',
|
||||
);
|
||||
const primarySidebarElement = ref.current?.shadowRoot?.querySelector(
|
||||
'[data-md-component="navigation"]',
|
||||
'div[data-md-component="sidebar"][data-md-type="navigation"], div[data-md-component="navigation"]',
|
||||
);
|
||||
const secondarySidebarElement = ref.current?.shadowRoot?.querySelector(
|
||||
'[data-md-component="toc"]',
|
||||
'div[data-md-component="sidebar"][data-md-type="toc"], div[data-md-component="toc"]',
|
||||
);
|
||||
|
||||
const primarySidebarAddonLocation = document.createElement('div');
|
||||
|
||||
@@ -15,12 +15,6 @@
|
||||
*/
|
||||
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
techdocsApiRef,
|
||||
TechDocsEntityMetadata,
|
||||
TechDocsMetadata,
|
||||
} from '@backstage/plugin-techdocs';
|
||||
import React, {
|
||||
createContext,
|
||||
Dispatch,
|
||||
@@ -29,9 +23,16 @@ import React, {
|
||||
useContext,
|
||||
useState,
|
||||
} from 'react';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { TechDocsAddonAsyncMetadata } from './types';
|
||||
import { AsyncState } from 'react-use/lib/useAsync';
|
||||
import {
|
||||
TechDocsAddonAsyncMetadata,
|
||||
TechDocsEntityMetadata,
|
||||
TechDocsMetadata,
|
||||
} from './types';
|
||||
|
||||
type PropsWithAsyncMetadata<TMetadata> = PropsWithChildren<{
|
||||
asyncValue: AsyncState<TMetadata>;
|
||||
}>;
|
||||
type PropsWithEntityName = PropsWithChildren<{ entityName: CompoundEntityRef }>;
|
||||
|
||||
const initialContextValue = {
|
||||
@@ -46,17 +47,11 @@ const TechDocsMetadataContext =
|
||||
);
|
||||
|
||||
export const TechDocsMetadataProvider = ({
|
||||
entityName,
|
||||
asyncValue,
|
||||
children,
|
||||
}: PropsWithEntityName) => {
|
||||
const techdocsApi = useApi(techdocsApiRef);
|
||||
|
||||
const metadataResponse = useAsync(async () => {
|
||||
return await techdocsApi.getTechDocsMetadata(entityName);
|
||||
}, []);
|
||||
|
||||
}: PropsWithAsyncMetadata<TechDocsMetadata>) => {
|
||||
return (
|
||||
<TechDocsMetadataContext.Provider value={metadataResponse}>
|
||||
<TechDocsMetadataContext.Provider value={asyncValue}>
|
||||
{children}
|
||||
</TechDocsMetadataContext.Provider>
|
||||
);
|
||||
@@ -77,17 +72,11 @@ const TechDocsEntityContext =
|
||||
);
|
||||
|
||||
export const TechDocsEntityProvider = ({
|
||||
entityName,
|
||||
asyncValue,
|
||||
children,
|
||||
}: PropsWithEntityName) => {
|
||||
const techdocsApi = useApi(techdocsApiRef);
|
||||
|
||||
const metadataResponse = useAsync(async () => {
|
||||
return await techdocsApi.getEntityMetadata(entityName);
|
||||
}, []);
|
||||
|
||||
}: PropsWithAsyncMetadata<TechDocsEntityMetadata>) => {
|
||||
return (
|
||||
<TechDocsEntityContext.Provider value={metadataResponse}>
|
||||
<TechDocsEntityContext.Provider value={asyncValue}>
|
||||
{children}
|
||||
</TechDocsEntityContext.Provider>
|
||||
);
|
||||
|
||||
@@ -20,12 +20,17 @@
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export { createTechDocsAddon, TechDocsAddons } from './addons';
|
||||
export {
|
||||
createTechDocsAddon,
|
||||
TechDocsAddons,
|
||||
TECHDOCS_ADDONS_WRAPPER_KEY,
|
||||
} from './addons';
|
||||
export * from './components';
|
||||
export { useEntityMetadata, useTechDocsMetadata } from './context';
|
||||
export { useShadowRoot, useShadowRootElements } from './hooks';
|
||||
export { TechDocsAddonLocations } from './types';
|
||||
export type {
|
||||
TechDocsAddonAsyncMetadata,
|
||||
TechDocsAddonLocations,
|
||||
TechDocsAddonOptions,
|
||||
TechDocsMetadata,
|
||||
TechDocsEntityMetadata,
|
||||
} from './types';
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { ComponentType } from 'react';
|
||||
import { AsyncState } from 'react-use/lib/useAsyncFn';
|
||||
|
||||
@@ -77,3 +78,22 @@ export type TechDocsAddonOptions<TAddonProps = {}> = {
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsAddonAsyncMetadata<TValue> = AsyncState<TValue | undefined>;
|
||||
|
||||
/**
|
||||
* Metadata for TechDocs page
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsMetadata = {
|
||||
site_name: string;
|
||||
site_description: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Metadata for TechDocs Entity
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsEntityMetadata = Entity & {
|
||||
locationMetadata?: { type: string; target: string };
|
||||
};
|
||||
|
||||
@@ -43,7 +43,9 @@
|
||||
"@backstage/integration": "^1.1.0-next.1",
|
||||
"@backstage/integration-react": "^1.0.1-next.1",
|
||||
"@backstage/plugin-catalog-react": "^1.0.1-next.2",
|
||||
"@backstage/plugin-catalog": "^0.10.0",
|
||||
"@backstage/plugin-search": "^0.7.5-next.0",
|
||||
"@backstage/plugin-techdocs-addons": "^0.0.0",
|
||||
"@backstage/theme": "^0.2.15",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
|
||||
@@ -17,14 +17,17 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useOutlet } from 'react-router';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { Reader } from './Reader';
|
||||
import { TechDocsReaderPageHeader } from './TechDocsReaderPageHeader';
|
||||
import useAsync, { AsyncState } from 'react-use/lib/useAsync';
|
||||
import { techdocsApiRef } from '../../api';
|
||||
import { TechDocsEntityMetadata, TechDocsMetadata } from '../../types';
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { useApi, useApp } from '@backstage/core-plugin-api';
|
||||
import { Page, Content } from '@backstage/core-components';
|
||||
import { getComponentData, useApi, useApp } from '@backstage/core-plugin-api';
|
||||
import { Page } from '@backstage/core-components';
|
||||
import {
|
||||
TechDocsReaderPage as AddonAwareReaderPage,
|
||||
TECHDOCS_ADDONS_WRAPPER_KEY,
|
||||
} from '@backstage/plugin-techdocs-addons';
|
||||
import { useTechDocsReaderDom, withTechDocsReaderProvider } from './Reader';
|
||||
|
||||
/**
|
||||
* Helper function that gives the children of {@link TechDocsReaderPage} access to techdocs and entity metadata
|
||||
@@ -42,6 +45,24 @@ export type TechDocsReaderPageRenderFunction = ({
|
||||
onReady: () => void;
|
||||
}) => JSX.Element;
|
||||
|
||||
type SpecialReaderPageProps = {
|
||||
entityName: CompoundEntityRef;
|
||||
asyncEntityMetadata: AsyncState<any>;
|
||||
asyncTechDocsMetadata: AsyncState<any>;
|
||||
};
|
||||
|
||||
const SpecialReaderPage = (props: SpecialReaderPageProps) => {
|
||||
const dom = useTechDocsReaderDom(props.entityName);
|
||||
|
||||
return (
|
||||
<AddonAwareReaderPage
|
||||
asyncEntityMetadata={props.asyncEntityMetadata}
|
||||
asyncTechDocsMetadata={props.asyncTechDocsMetadata}
|
||||
dom={dom}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Props for {@link TechDocsReaderPage}
|
||||
*
|
||||
@@ -61,7 +82,7 @@ export const TechDocsReaderPage = (props: TechDocsReaderPageProps) => {
|
||||
|
||||
const techdocsApi = useApi(techdocsApiRef);
|
||||
|
||||
const { value: techdocsMetadataValue } = useAsync(() => {
|
||||
const asyncTechDocsMetadata = useAsync(() => {
|
||||
if (documentReady) {
|
||||
return techdocsApi.getTechDocsMetadata({ kind, namespace, name });
|
||||
}
|
||||
@@ -69,50 +90,47 @@ export const TechDocsReaderPage = (props: TechDocsReaderPageProps) => {
|
||||
return Promise.resolve(undefined);
|
||||
}, [kind, namespace, name, techdocsApi, documentReady]);
|
||||
|
||||
const { value: entityMetadataValue, error: entityMetadataError } =
|
||||
useAsync(() => {
|
||||
return techdocsApi.getEntityMetadata({ kind, namespace, name });
|
||||
}, [kind, namespace, name, techdocsApi]);
|
||||
const asyncEntityMetadata = useAsync(() => {
|
||||
return techdocsApi.getEntityMetadata({ kind, namespace, name });
|
||||
}, [kind, namespace, name, techdocsApi]);
|
||||
|
||||
const onReady = useCallback(() => {
|
||||
setDocumentReady(true);
|
||||
}, [setDocumentReady]);
|
||||
|
||||
if (entityMetadataError) return <NotFoundErrorPage />;
|
||||
if (asyncEntityMetadata.error) return <NotFoundErrorPage />;
|
||||
|
||||
if (!children)
|
||||
return (
|
||||
outlet || (
|
||||
<Page themeId="documentation">
|
||||
<TechDocsReaderPageHeader
|
||||
techDocsMetadata={techdocsMetadataValue}
|
||||
entityMetadata={entityMetadataValue}
|
||||
entityRef={{
|
||||
kind,
|
||||
namespace,
|
||||
name,
|
||||
}}
|
||||
if (!children) {
|
||||
if (outlet) {
|
||||
// If the outlet is a single child and that child is an instance of the
|
||||
// TechDocsAddons registry, then render it a certain way.
|
||||
if (
|
||||
getComponentData(outlet.props.children, TECHDOCS_ADDONS_WRAPPER_KEY)
|
||||
) {
|
||||
const Component = withTechDocsReaderProvider(SpecialReaderPage, {
|
||||
kind,
|
||||
namespace,
|
||||
name,
|
||||
});
|
||||
return (
|
||||
<Component
|
||||
entityName={{ kind, namespace, name }}
|
||||
asyncEntityMetadata={asyncEntityMetadata}
|
||||
asyncTechDocsMetadata={asyncTechDocsMetadata}
|
||||
/>
|
||||
<Content data-testid="techdocs-content">
|
||||
<Reader
|
||||
onReady={onReady}
|
||||
entityRef={{
|
||||
kind,
|
||||
namespace,
|
||||
name,
|
||||
}}
|
||||
/>
|
||||
</Content>
|
||||
</Page>
|
||||
)
|
||||
);
|
||||
);
|
||||
}
|
||||
// Otherwise, just return the outlet (legacy-style composability).
|
||||
return outlet;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Page themeId="documentation">
|
||||
{children instanceof Function
|
||||
? children({
|
||||
techdocsMetadataValue,
|
||||
entityMetadataValue,
|
||||
techdocsMetadataValue: asyncTechDocsMetadata.value,
|
||||
entityMetadataValue: asyncEntityMetadata.value,
|
||||
entityRef: { kind, namespace, name },
|
||||
onReady,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user