Merge pull request #10751 from backstage/techdocs/addon-integration-mergable
[TechDocs] Techdocs/addon integration mergable
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs-addons': minor
|
||||
'@backstage/techdocs-addons': minor
|
||||
---
|
||||
|
||||
Introducing an addon framework for TechDocs.
|
||||
Introducing `@backstage/techdocs-addons`, a web library you can use to create TechDocs addons.
|
||||
|
||||
Note: this package is not necessarily stable yet. After iteration on this package, its stability will be signaled by a major-version bump.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs-addons': patch
|
||||
---
|
||||
|
||||
Separation between contexts and hooks
|
||||
@@ -2,15 +2,14 @@
|
||||
'@backstage/plugin-techdocs': minor
|
||||
---
|
||||
|
||||
TechDocs now supports a new method of customization: addons!
|
||||
TechDocs supports a new, experimental method of customization: addons!
|
||||
|
||||
To customize the standalone TechDocs reader page experience, update your `/packages/app/src/App.tsx` in the following way:
|
||||
|
||||
```diff
|
||||
import { TechDocsIndexPage, TechDocsReaderPage } from '@backstage/plugin-techdocs';
|
||||
+ import { TechDocsAddons } from '@backstage/plugin-techdocs-addons';
|
||||
+ import { TechDocsAddons } from '@backstage/techdocs-addons';
|
||||
+ import { SomeAddon } from '@backstage/plugin-some-plugin';
|
||||
- import { techDocsPage } from './components/techdocs/TechDocsPage';
|
||||
|
||||
// ...
|
||||
|
||||
@@ -19,7 +18,6 @@ import { TechDocsIndexPage, TechDocsReaderPage } from '@backstage/plugin-techdoc
|
||||
path="/docs/:namespace/:kind/:name/*"
|
||||
element={<TechDocsReaderPage />}
|
||||
>
|
||||
- {techDocsPage}
|
||||
+ <TechDocsAddons>
|
||||
+ <SomeAddon />
|
||||
+ </TechDocsAddons>
|
||||
@@ -32,7 +30,7 @@ To customize the TechDocs reader experience on the Catalog entity page, update y
|
||||
|
||||
```diff
|
||||
import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
|
||||
+ import { TechDocsAddons } from '@backstage/plugin-techdocs-addons';
|
||||
+ import { TechDocsAddons } from '@backstage/techdocs-addons';
|
||||
+ import { SomeAddon } from '@backstage/plugin-some-plugin';
|
||||
|
||||
// ...
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
site_name: e2e Fixture Documentation
|
||||
site_description: Documentation used for end-to-end tests of TechDocs in Backstage.
|
||||
repo_url: https://github.com/backstage/backstage
|
||||
edit_uri: edit/master/cypress/fixtures/docs
|
||||
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Sub-page 1: sub-page-one.md
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
site_name: 'Backstage'
|
||||
site_description: 'Main documentation for Backstage features and platform APIs'
|
||||
repo_url: https://github.com/backstage/backstage
|
||||
edit_uri: edit/master/docs
|
||||
|
||||
plugins:
|
||||
- techdocs-core
|
||||
|
||||
@@ -68,6 +68,7 @@ import {
|
||||
TechDocsIndexPage,
|
||||
TechDocsReaderPage,
|
||||
techdocsPlugin,
|
||||
GiveFeedbackAddon,
|
||||
} from '@backstage/plugin-techdocs';
|
||||
import {
|
||||
UserSettingsPage,
|
||||
@@ -93,13 +94,6 @@ 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,
|
||||
@@ -188,11 +182,7 @@ const routes = (
|
||||
>
|
||||
{techDocsPage}
|
||||
<TechDocsAddons>
|
||||
<ExampleHeader />
|
||||
<ExampleSubHeader />
|
||||
<ExamplePrimarySidebar />
|
||||
<ExampleSecondarySidebar />
|
||||
<ExampleContent />
|
||||
<GiveFeedbackAddon />
|
||||
</TechDocsAddons>
|
||||
</Route>
|
||||
<Route
|
||||
|
||||
@@ -104,7 +104,10 @@ import {
|
||||
isRollbarAvailable,
|
||||
} from '@backstage/plugin-rollbar';
|
||||
import { EntitySentryContent } from '@backstage/plugin-sentry';
|
||||
import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
|
||||
import {
|
||||
EntityTechdocsContent,
|
||||
GiveFeedbackAddon,
|
||||
} from '@backstage/plugin-techdocs';
|
||||
import { EntityTodoContent } from '@backstage/plugin-todo';
|
||||
import { Button, Grid } from '@material-ui/core';
|
||||
import BadgeIcon from '@material-ui/icons/CallToAction';
|
||||
@@ -139,13 +142,6 @@ import { EntityGoCdContent, isGoCdAvailable } from '@backstage/plugin-gocd';
|
||||
|
||||
import React, { ReactNode, useMemo, useState } from 'react';
|
||||
import { TechDocsAddons } from '@backstage/techdocs-addons';
|
||||
import {
|
||||
ExampleContent,
|
||||
ExampleHeader,
|
||||
ExamplePrimarySidebar,
|
||||
ExampleSecondarySidebar,
|
||||
ExampleSubHeader,
|
||||
} from '../techdocs/ExampleAddons';
|
||||
|
||||
const customEntityFilterKind = ['Component', 'API', 'System'];
|
||||
|
||||
@@ -407,11 +403,7 @@ const serviceEntityPage = (
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent>
|
||||
<TechDocsAddons>
|
||||
<ExampleHeader />
|
||||
<ExampleSubHeader />
|
||||
<ExamplePrimarySidebar />
|
||||
<ExampleSecondarySidebar />
|
||||
<ExampleContent />
|
||||
<GiveFeedbackAddon />
|
||||
</TechDocsAddons>
|
||||
</EntityTechdocsContent>
|
||||
</EntityLayout.Route>
|
||||
@@ -482,11 +474,7 @@ const websiteEntityPage = (
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent>
|
||||
<TechDocsAddons>
|
||||
<ExampleHeader />
|
||||
<ExampleSubHeader />
|
||||
<ExamplePrimarySidebar />
|
||||
<ExampleSecondarySidebar />
|
||||
<ExampleContent />
|
||||
<GiveFeedbackAddon />
|
||||
</TechDocsAddons>
|
||||
</EntityTechdocsContent>
|
||||
</EntityLayout.Route>
|
||||
@@ -529,11 +517,7 @@ const defaultEntityPage = (
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent>
|
||||
<TechDocsAddons>
|
||||
<ExampleHeader />
|
||||
<ExampleSubHeader />
|
||||
<ExamplePrimarySidebar />
|
||||
<ExampleSecondarySidebar />
|
||||
<ExampleContent />
|
||||
<GiveFeedbackAddon />
|
||||
</TechDocsAddons>
|
||||
</EntityTechdocsContent>
|
||||
</EntityLayout.Route>
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* 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 React, { useEffect } from 'react';
|
||||
|
||||
import { Card, CardContent } from '@material-ui/core';
|
||||
|
||||
import {
|
||||
techdocsPlugin,
|
||||
useShadowRootElements,
|
||||
} from '@backstage/plugin-techdocs';
|
||||
import {
|
||||
createTechDocsAddon,
|
||||
TechDocsAddonLocations,
|
||||
} from '@backstage/techdocs-addons';
|
||||
import { HeaderLabel } from '@backstage/core-components';
|
||||
|
||||
/**
|
||||
* 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,
|
||||
}),
|
||||
);
|
||||
@@ -17,6 +17,7 @@
|
||||
import {
|
||||
TechDocsReaderPage,
|
||||
TechDocsReaderPageHeader,
|
||||
TechDocsReaderPageSubheader,
|
||||
TechDocsReaderPageContent,
|
||||
} from '@backstage/plugin-techdocs';
|
||||
import React from 'react';
|
||||
@@ -25,6 +26,7 @@ const DefaultTechDocsPage = () => {
|
||||
return (
|
||||
<TechDocsReaderPage>
|
||||
<TechDocsReaderPageHeader />
|
||||
<TechDocsReaderPageSubheader />
|
||||
<TechDocsReaderPageContent />
|
||||
</TechDocsReaderPage>
|
||||
);
|
||||
|
||||
@@ -3,23 +3,19 @@
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { AsyncState } from 'react-use/lib/useAsyncFn';
|
||||
import { ComponentType } from 'react';
|
||||
import { Extension } from '@backstage/core-plugin-api';
|
||||
import { default as React_2 } from 'react';
|
||||
|
||||
// @public
|
||||
// @alpha
|
||||
export function createTechDocsAddon<TComponentProps>(
|
||||
options: TechDocsAddonOptions<TComponentProps>,
|
||||
): Extension<ComponentType<TComponentProps>>;
|
||||
|
||||
// @public
|
||||
// @alpha
|
||||
export const TECHDOCS_ADDONS_WRAPPER_KEY = 'techdocs.addons.wrapper.v1';
|
||||
|
||||
// @public
|
||||
export type TechDocsAddonAsyncMetadata<TValue> = AsyncState<TValue | undefined>;
|
||||
|
||||
// @public
|
||||
// @alpha
|
||||
export enum TechDocsAddonLocations {
|
||||
CONTENT = 'content',
|
||||
HEADER = 'header',
|
||||
@@ -28,17 +24,17 @@ export enum TechDocsAddonLocations {
|
||||
SUBHEADER = 'subheader',
|
||||
}
|
||||
|
||||
// @public
|
||||
// @alpha
|
||||
export type TechDocsAddonOptions<TAddonProps = {}> = {
|
||||
name: string;
|
||||
location: TechDocsAddonLocations;
|
||||
component: ComponentType<TAddonProps>;
|
||||
};
|
||||
|
||||
// @public
|
||||
// @alpha
|
||||
export const TechDocsAddons: React_2.ComponentType;
|
||||
|
||||
// @public
|
||||
// @alpha
|
||||
export const useTechDocsAddons: () => {
|
||||
renderComponentByName: (name: string) => React_2.ReactElement<
|
||||
{
|
||||
|
||||
@@ -42,8 +42,7 @@
|
||||
"@material-ui/styles": "^4.11.0",
|
||||
"jss": "~10.8.2",
|
||||
"react-helmet": "6.1.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^17.2.4"
|
||||
"react-router-dom": "6.0.0-beta.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^16.13.1 || ^17.0.0",
|
||||
|
||||
@@ -31,13 +31,13 @@ export const TECHDOCS_ADDONS_KEY = 'techdocs.addons.addon.v1';
|
||||
|
||||
/**
|
||||
* Marks the <TechDocsAddons> registry component.
|
||||
* @public
|
||||
* @alpha
|
||||
*/
|
||||
export const TECHDOCS_ADDONS_WRAPPER_KEY = 'techdocs.addons.wrapper.v1';
|
||||
|
||||
/**
|
||||
* TechDocs Addon registry.
|
||||
* @public
|
||||
* @alpha
|
||||
*/
|
||||
export const TechDocsAddons: React.ComponentType = () => null;
|
||||
|
||||
@@ -49,7 +49,7 @@ const getDataKeyByName = (name: string) => {
|
||||
|
||||
/**
|
||||
* Create a TechDocs addon.
|
||||
* @public
|
||||
* @alpha
|
||||
*/
|
||||
export function createTechDocsAddon<TComponentProps>(
|
||||
options: TechDocsAddonOptions<TComponentProps>,
|
||||
@@ -93,7 +93,7 @@ const getAllTechDocsAddonsData = (collection: ElementCollection) => {
|
||||
|
||||
/**
|
||||
* hook to use addons in components
|
||||
* @public
|
||||
* @alpha
|
||||
*/
|
||||
export const useTechDocsAddons = () => {
|
||||
const node = useOutlet();
|
||||
|
||||
@@ -27,4 +27,4 @@ export {
|
||||
TECHDOCS_ADDONS_WRAPPER_KEY,
|
||||
} from './addons';
|
||||
export { TechDocsAddonLocations } from './types';
|
||||
export type { TechDocsAddonAsyncMetadata, TechDocsAddonOptions } from './types';
|
||||
export type { TechDocsAddonOptions } from './types';
|
||||
|
||||
@@ -15,11 +15,10 @@
|
||||
*/
|
||||
|
||||
import { ComponentType } from 'react';
|
||||
import { AsyncState } from 'react-use/lib/useAsyncFn';
|
||||
|
||||
/**
|
||||
* Locations for which TechDocs addons may be declared and rendered.
|
||||
* @public
|
||||
* @alpha
|
||||
*/
|
||||
export enum TechDocsAddonLocations {
|
||||
/**
|
||||
@@ -79,16 +78,10 @@ export enum TechDocsAddonLocations {
|
||||
|
||||
/**
|
||||
* Options for creating a TechDocs addon.
|
||||
* @public
|
||||
* @alpha
|
||||
*/
|
||||
export type TechDocsAddonOptions<TAddonProps = {}> = {
|
||||
name: string;
|
||||
location: TechDocsAddonLocations;
|
||||
component: ComponentType<TAddonProps>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Common response envelope for addon-related hooks.
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsAddonAsyncMetadata<TValue> = AsyncState<TValue | undefined>;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
site_name: 'Example Documentation'
|
||||
repo_url: https://github.com/backstage/backstage
|
||||
edit_uri: edit/master/plugins/techdocs-backend/examples/documented-component/docs
|
||||
|
||||
nav:
|
||||
- Home: index.md
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { ApiRef } from '@backstage/core-plugin-api';
|
||||
import { AsyncState } from 'react-use/lib/useAsync';
|
||||
import { BackstagePlugin } from '@backstage/core-plugin-api';
|
||||
import { CommonProps } from '@material-ui/core/OverridableComponent';
|
||||
import { ComponentType } from 'react';
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
@@ -22,8 +23,10 @@ import { default as React_2 } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
import { RouteRef } from '@backstage/core-plugin-api';
|
||||
import { SetStateAction } from 'react';
|
||||
import { StyledComponentProps } from '@material-ui/core';
|
||||
import { TableColumn } from '@backstage/core-components';
|
||||
import { TableProps } from '@backstage/core-components';
|
||||
import { ToolbarTypeMap } from '@material-ui/core';
|
||||
import { UserListFilterKind } from '@backstage/plugin-catalog-react';
|
||||
|
||||
// @public
|
||||
@@ -395,6 +398,545 @@ export type TechDocsReaderPageRenderFunction = ({
|
||||
onReady?: () => void;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export const TechDocsReaderPageSubheader: React_2.ComponentType<
|
||||
Pick<
|
||||
{
|
||||
disableGutters?: boolean | undefined;
|
||||
variant?: 'dense' | 'regular' | undefined;
|
||||
} & CommonProps<ToolbarTypeMap<{}, 'div'>> &
|
||||
Pick<
|
||||
Pick<
|
||||
React_2.DetailedHTMLProps<
|
||||
React_2.HTMLAttributes<HTMLDivElement>,
|
||||
HTMLDivElement
|
||||
>,
|
||||
'key' | keyof React_2.HTMLAttributes<HTMLDivElement>
|
||||
> & {
|
||||
ref?:
|
||||
| ((instance: HTMLDivElement | null) => void)
|
||||
| React_2.RefObject<HTMLDivElement>
|
||||
| null
|
||||
| undefined;
|
||||
},
|
||||
| 'key'
|
||||
| 'id'
|
||||
| 'color'
|
||||
| 'translate'
|
||||
| 'hidden'
|
||||
| 'dir'
|
||||
| 'slot'
|
||||
| 'title'
|
||||
| 'accessKey'
|
||||
| 'draggable'
|
||||
| 'lang'
|
||||
| 'prefix'
|
||||
| 'children'
|
||||
| 'contentEditable'
|
||||
| 'inputMode'
|
||||
| 'tabIndex'
|
||||
| 'ref'
|
||||
| 'defaultChecked'
|
||||
| 'defaultValue'
|
||||
| 'suppressContentEditableWarning'
|
||||
| 'suppressHydrationWarning'
|
||||
| 'contextMenu'
|
||||
| 'placeholder'
|
||||
| 'spellCheck'
|
||||
| 'radioGroup'
|
||||
| 'role'
|
||||
| 'about'
|
||||
| 'datatype'
|
||||
| 'inlist'
|
||||
| 'property'
|
||||
| 'resource'
|
||||
| 'typeof'
|
||||
| 'vocab'
|
||||
| 'autoCapitalize'
|
||||
| 'autoCorrect'
|
||||
| 'autoSave'
|
||||
| 'itemProp'
|
||||
| 'itemScope'
|
||||
| 'itemType'
|
||||
| 'itemID'
|
||||
| 'itemRef'
|
||||
| 'results'
|
||||
| 'security'
|
||||
| 'unselectable'
|
||||
| 'is'
|
||||
| 'aria-activedescendant'
|
||||
| 'aria-atomic'
|
||||
| 'aria-autocomplete'
|
||||
| 'aria-busy'
|
||||
| 'aria-checked'
|
||||
| 'aria-colcount'
|
||||
| 'aria-colindex'
|
||||
| 'aria-colspan'
|
||||
| 'aria-controls'
|
||||
| 'aria-current'
|
||||
| 'aria-describedby'
|
||||
| 'aria-details'
|
||||
| 'aria-disabled'
|
||||
| 'aria-dropeffect'
|
||||
| 'aria-errormessage'
|
||||
| 'aria-expanded'
|
||||
| 'aria-flowto'
|
||||
| 'aria-grabbed'
|
||||
| 'aria-haspopup'
|
||||
| 'aria-hidden'
|
||||
| 'aria-invalid'
|
||||
| 'aria-keyshortcuts'
|
||||
| 'aria-label'
|
||||
| 'aria-labelledby'
|
||||
| 'aria-level'
|
||||
| 'aria-live'
|
||||
| 'aria-modal'
|
||||
| 'aria-multiline'
|
||||
| 'aria-multiselectable'
|
||||
| 'aria-orientation'
|
||||
| 'aria-owns'
|
||||
| 'aria-placeholder'
|
||||
| 'aria-posinset'
|
||||
| 'aria-pressed'
|
||||
| 'aria-readonly'
|
||||
| 'aria-relevant'
|
||||
| 'aria-required'
|
||||
| 'aria-roledescription'
|
||||
| 'aria-rowcount'
|
||||
| 'aria-rowindex'
|
||||
| 'aria-rowspan'
|
||||
| 'aria-selected'
|
||||
| 'aria-setsize'
|
||||
| 'aria-sort'
|
||||
| 'aria-valuemax'
|
||||
| 'aria-valuemin'
|
||||
| 'aria-valuenow'
|
||||
| 'aria-valuetext'
|
||||
| 'dangerouslySetInnerHTML'
|
||||
| 'onCopy'
|
||||
| 'onCopyCapture'
|
||||
| 'onCut'
|
||||
| 'onCutCapture'
|
||||
| 'onPaste'
|
||||
| 'onPasteCapture'
|
||||
| 'onCompositionEnd'
|
||||
| 'onCompositionEndCapture'
|
||||
| 'onCompositionStart'
|
||||
| 'onCompositionStartCapture'
|
||||
| 'onCompositionUpdate'
|
||||
| 'onCompositionUpdateCapture'
|
||||
| 'onFocus'
|
||||
| 'onFocusCapture'
|
||||
| 'onBlur'
|
||||
| 'onBlurCapture'
|
||||
| 'onChange'
|
||||
| 'onChangeCapture'
|
||||
| 'onBeforeInput'
|
||||
| 'onBeforeInputCapture'
|
||||
| 'onInput'
|
||||
| 'onInputCapture'
|
||||
| 'onReset'
|
||||
| 'onResetCapture'
|
||||
| 'onSubmit'
|
||||
| 'onSubmitCapture'
|
||||
| 'onInvalid'
|
||||
| 'onInvalidCapture'
|
||||
| 'onLoad'
|
||||
| 'onLoadCapture'
|
||||
| 'onError'
|
||||
| 'onErrorCapture'
|
||||
| 'onKeyDown'
|
||||
| 'onKeyDownCapture'
|
||||
| 'onKeyPress'
|
||||
| 'onKeyPressCapture'
|
||||
| 'onKeyUp'
|
||||
| 'onKeyUpCapture'
|
||||
| 'onAbort'
|
||||
| 'onAbortCapture'
|
||||
| 'onCanPlay'
|
||||
| 'onCanPlayCapture'
|
||||
| 'onCanPlayThrough'
|
||||
| 'onCanPlayThroughCapture'
|
||||
| 'onDurationChange'
|
||||
| 'onDurationChangeCapture'
|
||||
| 'onEmptied'
|
||||
| 'onEmptiedCapture'
|
||||
| 'onEncrypted'
|
||||
| 'onEncryptedCapture'
|
||||
| 'onEnded'
|
||||
| 'onEndedCapture'
|
||||
| 'onLoadedData'
|
||||
| 'onLoadedDataCapture'
|
||||
| 'onLoadedMetadata'
|
||||
| 'onLoadedMetadataCapture'
|
||||
| 'onLoadStart'
|
||||
| 'onLoadStartCapture'
|
||||
| 'onPause'
|
||||
| 'onPauseCapture'
|
||||
| 'onPlay'
|
||||
| 'onPlayCapture'
|
||||
| 'onPlaying'
|
||||
| 'onPlayingCapture'
|
||||
| 'onProgress'
|
||||
| 'onProgressCapture'
|
||||
| 'onRateChange'
|
||||
| 'onRateChangeCapture'
|
||||
| 'onSeeked'
|
||||
| 'onSeekedCapture'
|
||||
| 'onSeeking'
|
||||
| 'onSeekingCapture'
|
||||
| 'onStalled'
|
||||
| 'onStalledCapture'
|
||||
| 'onSuspend'
|
||||
| 'onSuspendCapture'
|
||||
| 'onTimeUpdate'
|
||||
| 'onTimeUpdateCapture'
|
||||
| 'onVolumeChange'
|
||||
| 'onVolumeChangeCapture'
|
||||
| 'onWaiting'
|
||||
| 'onWaitingCapture'
|
||||
| 'onAuxClick'
|
||||
| 'onAuxClickCapture'
|
||||
| 'onClick'
|
||||
| 'onClickCapture'
|
||||
| 'onContextMenu'
|
||||
| 'onContextMenuCapture'
|
||||
| 'onDoubleClick'
|
||||
| 'onDoubleClickCapture'
|
||||
| 'onDrag'
|
||||
| 'onDragCapture'
|
||||
| 'onDragEnd'
|
||||
| 'onDragEndCapture'
|
||||
| 'onDragEnter'
|
||||
| 'onDragEnterCapture'
|
||||
| 'onDragExit'
|
||||
| 'onDragExitCapture'
|
||||
| 'onDragLeave'
|
||||
| 'onDragLeaveCapture'
|
||||
| 'onDragOver'
|
||||
| 'onDragOverCapture'
|
||||
| 'onDragStart'
|
||||
| 'onDragStartCapture'
|
||||
| 'onDrop'
|
||||
| 'onDropCapture'
|
||||
| 'onMouseDown'
|
||||
| 'onMouseDownCapture'
|
||||
| 'onMouseEnter'
|
||||
| 'onMouseLeave'
|
||||
| 'onMouseMove'
|
||||
| 'onMouseMoveCapture'
|
||||
| 'onMouseOut'
|
||||
| 'onMouseOutCapture'
|
||||
| 'onMouseOver'
|
||||
| 'onMouseOverCapture'
|
||||
| 'onMouseUp'
|
||||
| 'onMouseUpCapture'
|
||||
| 'onSelect'
|
||||
| 'onSelectCapture'
|
||||
| 'onTouchCancel'
|
||||
| 'onTouchCancelCapture'
|
||||
| 'onTouchEnd'
|
||||
| 'onTouchEndCapture'
|
||||
| 'onTouchMove'
|
||||
| 'onTouchMoveCapture'
|
||||
| 'onTouchStart'
|
||||
| 'onTouchStartCapture'
|
||||
| 'onPointerDown'
|
||||
| 'onPointerDownCapture'
|
||||
| 'onPointerMove'
|
||||
| 'onPointerMoveCapture'
|
||||
| 'onPointerUp'
|
||||
| 'onPointerUpCapture'
|
||||
| 'onPointerCancel'
|
||||
| 'onPointerCancelCapture'
|
||||
| 'onPointerEnter'
|
||||
| 'onPointerEnterCapture'
|
||||
| 'onPointerLeave'
|
||||
| 'onPointerLeaveCapture'
|
||||
| 'onPointerOver'
|
||||
| 'onPointerOverCapture'
|
||||
| 'onPointerOut'
|
||||
| 'onPointerOutCapture'
|
||||
| 'onGotPointerCapture'
|
||||
| 'onGotPointerCaptureCapture'
|
||||
| 'onLostPointerCapture'
|
||||
| 'onLostPointerCaptureCapture'
|
||||
| 'onScroll'
|
||||
| 'onScrollCapture'
|
||||
| 'onWheel'
|
||||
| 'onWheelCapture'
|
||||
| 'onAnimationStart'
|
||||
| 'onAnimationStartCapture'
|
||||
| 'onAnimationEnd'
|
||||
| 'onAnimationEndCapture'
|
||||
| 'onAnimationIteration'
|
||||
| 'onAnimationIterationCapture'
|
||||
| 'onTransitionEnd'
|
||||
| 'onTransitionEndCapture'
|
||||
>,
|
||||
| 'key'
|
||||
| 'id'
|
||||
| 'color'
|
||||
| 'translate'
|
||||
| 'hidden'
|
||||
| 'dir'
|
||||
| 'slot'
|
||||
| 'style'
|
||||
| 'title'
|
||||
| 'accessKey'
|
||||
| 'draggable'
|
||||
| 'lang'
|
||||
| 'className'
|
||||
| 'prefix'
|
||||
| 'children'
|
||||
| 'contentEditable'
|
||||
| 'inputMode'
|
||||
| 'tabIndex'
|
||||
| 'ref'
|
||||
| 'defaultChecked'
|
||||
| 'defaultValue'
|
||||
| 'suppressContentEditableWarning'
|
||||
| 'suppressHydrationWarning'
|
||||
| 'contextMenu'
|
||||
| 'placeholder'
|
||||
| 'spellCheck'
|
||||
| 'radioGroup'
|
||||
| 'role'
|
||||
| 'about'
|
||||
| 'datatype'
|
||||
| 'inlist'
|
||||
| 'property'
|
||||
| 'resource'
|
||||
| 'typeof'
|
||||
| 'vocab'
|
||||
| 'autoCapitalize'
|
||||
| 'autoCorrect'
|
||||
| 'autoSave'
|
||||
| 'itemProp'
|
||||
| 'itemScope'
|
||||
| 'itemType'
|
||||
| 'itemID'
|
||||
| 'itemRef'
|
||||
| 'results'
|
||||
| 'security'
|
||||
| 'unselectable'
|
||||
| 'is'
|
||||
| 'aria-activedescendant'
|
||||
| 'aria-atomic'
|
||||
| 'aria-autocomplete'
|
||||
| 'aria-busy'
|
||||
| 'aria-checked'
|
||||
| 'aria-colcount'
|
||||
| 'aria-colindex'
|
||||
| 'aria-colspan'
|
||||
| 'aria-controls'
|
||||
| 'aria-current'
|
||||
| 'aria-describedby'
|
||||
| 'aria-details'
|
||||
| 'aria-disabled'
|
||||
| 'aria-dropeffect'
|
||||
| 'aria-errormessage'
|
||||
| 'aria-expanded'
|
||||
| 'aria-flowto'
|
||||
| 'aria-grabbed'
|
||||
| 'aria-haspopup'
|
||||
| 'aria-hidden'
|
||||
| 'aria-invalid'
|
||||
| 'aria-keyshortcuts'
|
||||
| 'aria-label'
|
||||
| 'aria-labelledby'
|
||||
| 'aria-level'
|
||||
| 'aria-live'
|
||||
| 'aria-modal'
|
||||
| 'aria-multiline'
|
||||
| 'aria-multiselectable'
|
||||
| 'aria-orientation'
|
||||
| 'aria-owns'
|
||||
| 'aria-placeholder'
|
||||
| 'aria-posinset'
|
||||
| 'aria-pressed'
|
||||
| 'aria-readonly'
|
||||
| 'aria-relevant'
|
||||
| 'aria-required'
|
||||
| 'aria-roledescription'
|
||||
| 'aria-rowcount'
|
||||
| 'aria-rowindex'
|
||||
| 'aria-rowspan'
|
||||
| 'aria-selected'
|
||||
| 'aria-setsize'
|
||||
| 'aria-sort'
|
||||
| 'aria-valuemax'
|
||||
| 'aria-valuemin'
|
||||
| 'aria-valuenow'
|
||||
| 'aria-valuetext'
|
||||
| 'dangerouslySetInnerHTML'
|
||||
| 'onCopy'
|
||||
| 'onCopyCapture'
|
||||
| 'onCut'
|
||||
| 'onCutCapture'
|
||||
| 'onPaste'
|
||||
| 'onPasteCapture'
|
||||
| 'onCompositionEnd'
|
||||
| 'onCompositionEndCapture'
|
||||
| 'onCompositionStart'
|
||||
| 'onCompositionStartCapture'
|
||||
| 'onCompositionUpdate'
|
||||
| 'onCompositionUpdateCapture'
|
||||
| 'onFocus'
|
||||
| 'onFocusCapture'
|
||||
| 'onBlur'
|
||||
| 'onBlurCapture'
|
||||
| 'onChange'
|
||||
| 'onChangeCapture'
|
||||
| 'onBeforeInput'
|
||||
| 'onBeforeInputCapture'
|
||||
| 'onInput'
|
||||
| 'onInputCapture'
|
||||
| 'onReset'
|
||||
| 'onResetCapture'
|
||||
| 'onSubmit'
|
||||
| 'onSubmitCapture'
|
||||
| 'onInvalid'
|
||||
| 'onInvalidCapture'
|
||||
| 'onLoad'
|
||||
| 'onLoadCapture'
|
||||
| 'onError'
|
||||
| 'onErrorCapture'
|
||||
| 'onKeyDown'
|
||||
| 'onKeyDownCapture'
|
||||
| 'onKeyPress'
|
||||
| 'onKeyPressCapture'
|
||||
| 'onKeyUp'
|
||||
| 'onKeyUpCapture'
|
||||
| 'onAbort'
|
||||
| 'onAbortCapture'
|
||||
| 'onCanPlay'
|
||||
| 'onCanPlayCapture'
|
||||
| 'onCanPlayThrough'
|
||||
| 'onCanPlayThroughCapture'
|
||||
| 'onDurationChange'
|
||||
| 'onDurationChangeCapture'
|
||||
| 'onEmptied'
|
||||
| 'onEmptiedCapture'
|
||||
| 'onEncrypted'
|
||||
| 'onEncryptedCapture'
|
||||
| 'onEnded'
|
||||
| 'onEndedCapture'
|
||||
| 'onLoadedData'
|
||||
| 'onLoadedDataCapture'
|
||||
| 'onLoadedMetadata'
|
||||
| 'onLoadedMetadataCapture'
|
||||
| 'onLoadStart'
|
||||
| 'onLoadStartCapture'
|
||||
| 'onPause'
|
||||
| 'onPauseCapture'
|
||||
| 'onPlay'
|
||||
| 'onPlayCapture'
|
||||
| 'onPlaying'
|
||||
| 'onPlayingCapture'
|
||||
| 'onProgress'
|
||||
| 'onProgressCapture'
|
||||
| 'onRateChange'
|
||||
| 'onRateChangeCapture'
|
||||
| 'onSeeked'
|
||||
| 'onSeekedCapture'
|
||||
| 'onSeeking'
|
||||
| 'onSeekingCapture'
|
||||
| 'onStalled'
|
||||
| 'onStalledCapture'
|
||||
| 'onSuspend'
|
||||
| 'onSuspendCapture'
|
||||
| 'onTimeUpdate'
|
||||
| 'onTimeUpdateCapture'
|
||||
| 'onVolumeChange'
|
||||
| 'onVolumeChangeCapture'
|
||||
| 'onWaiting'
|
||||
| 'onWaitingCapture'
|
||||
| 'onAuxClick'
|
||||
| 'onAuxClickCapture'
|
||||
| 'onClick'
|
||||
| 'onClickCapture'
|
||||
| 'onContextMenu'
|
||||
| 'onContextMenuCapture'
|
||||
| 'onDoubleClick'
|
||||
| 'onDoubleClickCapture'
|
||||
| 'onDrag'
|
||||
| 'onDragCapture'
|
||||
| 'onDragEnd'
|
||||
| 'onDragEndCapture'
|
||||
| 'onDragEnter'
|
||||
| 'onDragEnterCapture'
|
||||
| 'onDragExit'
|
||||
| 'onDragExitCapture'
|
||||
| 'onDragLeave'
|
||||
| 'onDragLeaveCapture'
|
||||
| 'onDragOver'
|
||||
| 'onDragOverCapture'
|
||||
| 'onDragStart'
|
||||
| 'onDragStartCapture'
|
||||
| 'onDrop'
|
||||
| 'onDropCapture'
|
||||
| 'onMouseDown'
|
||||
| 'onMouseDownCapture'
|
||||
| 'onMouseEnter'
|
||||
| 'onMouseLeave'
|
||||
| 'onMouseMove'
|
||||
| 'onMouseMoveCapture'
|
||||
| 'onMouseOut'
|
||||
| 'onMouseOutCapture'
|
||||
| 'onMouseOver'
|
||||
| 'onMouseOverCapture'
|
||||
| 'onMouseUp'
|
||||
| 'onMouseUpCapture'
|
||||
| 'onSelect'
|
||||
| 'onSelectCapture'
|
||||
| 'onTouchCancel'
|
||||
| 'onTouchCancelCapture'
|
||||
| 'onTouchEnd'
|
||||
| 'onTouchEndCapture'
|
||||
| 'onTouchMove'
|
||||
| 'onTouchMoveCapture'
|
||||
| 'onTouchStart'
|
||||
| 'onTouchStartCapture'
|
||||
| 'onPointerDown'
|
||||
| 'onPointerDownCapture'
|
||||
| 'onPointerMove'
|
||||
| 'onPointerMoveCapture'
|
||||
| 'onPointerUp'
|
||||
| 'onPointerUpCapture'
|
||||
| 'onPointerCancel'
|
||||
| 'onPointerCancelCapture'
|
||||
| 'onPointerEnter'
|
||||
| 'onPointerEnterCapture'
|
||||
| 'onPointerLeave'
|
||||
| 'onPointerLeaveCapture'
|
||||
| 'onPointerOver'
|
||||
| 'onPointerOverCapture'
|
||||
| 'onPointerOut'
|
||||
| 'onPointerOutCapture'
|
||||
| 'onGotPointerCapture'
|
||||
| 'onGotPointerCaptureCapture'
|
||||
| 'onLostPointerCapture'
|
||||
| 'onLostPointerCaptureCapture'
|
||||
| 'onScroll'
|
||||
| 'onScrollCapture'
|
||||
| 'onWheel'
|
||||
| 'onWheelCapture'
|
||||
| 'onAnimationStart'
|
||||
| 'onAnimationStartCapture'
|
||||
| 'onAnimationEnd'
|
||||
| 'onAnimationEndCapture'
|
||||
| 'onAnimationIteration'
|
||||
| 'onAnimationIterationCapture'
|
||||
| 'onTransitionEnd'
|
||||
| 'onTransitionEndCapture'
|
||||
| 'variant'
|
||||
| 'innerRef'
|
||||
| 'disableGutters'
|
||||
> &
|
||||
StyledComponentProps<'root'>
|
||||
>;
|
||||
|
||||
// @public
|
||||
export type TechDocsReaderPageValue = {
|
||||
metadata: AsyncState<TechDocsMetadata>;
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"@backstage/plugin-catalog": "^1.1.0-next.2",
|
||||
"@backstage/plugin-search": "^0.7.5-next.0",
|
||||
"@backstage/techdocs-addons": "^0.0.0",
|
||||
"@backstage/version-bridge": "^1.0.0",
|
||||
"@backstage/theme": "^0.2.15",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
|
||||
@@ -19,7 +19,6 @@ import React, {
|
||||
memo,
|
||||
Dispatch,
|
||||
SetStateAction,
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
} from 'react';
|
||||
@@ -27,6 +26,10 @@ import useAsync, { AsyncState } from 'react-use/lib/useAsync';
|
||||
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import {
|
||||
createVersionedContext,
|
||||
createVersionedValueMap,
|
||||
} from '@backstage/version-bridge';
|
||||
|
||||
import { techdocsApiRef } from '../../../api';
|
||||
import { TechDocsEntityMetadata, TechDocsMetadata } from '../../../types';
|
||||
@@ -78,15 +81,26 @@ export const defaultTechDocsReaderPageValue: TechDocsReaderPageValue = {
|
||||
entityName: { kind: '', name: '', namespace: '' },
|
||||
};
|
||||
|
||||
export const TechDocsReaderPageContext = createContext<TechDocsReaderPageValue>(
|
||||
defaultTechDocsReaderPageValue,
|
||||
);
|
||||
export const TechDocsReaderPageContext = createVersionedContext<{
|
||||
1: TechDocsReaderPageValue;
|
||||
}>('techdocs-reader-page-context');
|
||||
/**
|
||||
* Hook used to get access to shared state between reader page components.
|
||||
* @public
|
||||
*/
|
||||
export const useTechDocsReaderPage = () => {
|
||||
return useContext(TechDocsReaderPageContext);
|
||||
const versionedContext = useContext(TechDocsReaderPageContext);
|
||||
|
||||
if (versionedContext === undefined) {
|
||||
return defaultTechDocsReaderPageValue;
|
||||
}
|
||||
|
||||
const context = versionedContext.atVersion(1);
|
||||
if (context === undefined) {
|
||||
throw new Error('No context found for version 1.');
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -143,9 +157,10 @@ export const TechDocsReaderPageProvider = memo(
|
||||
subtitle,
|
||||
setSubtitle,
|
||||
};
|
||||
const versionedValue = createVersionedValueMap({ 1: value });
|
||||
|
||||
return (
|
||||
<TechDocsReaderPageContext.Provider value={value}>
|
||||
<TechDocsReaderPageContext.Provider value={versionedValue}>
|
||||
{children instanceof Function ? children(value) : children}
|
||||
</TechDocsReaderPageContext.Provider>
|
||||
);
|
||||
|
||||
+5
@@ -23,6 +23,11 @@ import {
|
||||
useTechDocsAddons,
|
||||
} from '@backstage/techdocs-addons';
|
||||
|
||||
/**
|
||||
* Renders the reader page subheader.
|
||||
* Please use the Tech Docs add-ons to customize it
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsReaderPageSubheader = withStyles(theme => ({
|
||||
root: {
|
||||
gridArea: 'pageSubheader',
|
||||
|
||||
@@ -32,5 +32,6 @@ export {
|
||||
} from './TechDocsReaderPage';
|
||||
export * from './TechDocsReaderPageHeader';
|
||||
export * from './TechDocsReaderPageContent';
|
||||
export * from './TechDocsReaderPageSubheader';
|
||||
export * from './TechDocsStateIndicator';
|
||||
export type { ReaderState, ContentStateTypes } from './useReaderState';
|
||||
|
||||
Reference in New Issue
Block a user