Merge pull request #9730 from backstage/emmaindal/techdocs-api-report
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Update the template to reflect the renaming of `DocsResultListItem` to `TechDocsSearchResultListItem` from `@backstage/plugin-techdocs`.
|
||||
|
||||
To apply this change to an existing app, make the following change to `packages/app/src/components/search/SearchPage.tsx`:
|
||||
|
||||
```diff
|
||||
-import { DocsResultListItem } from '@backstage/plugin-techdocs';
|
||||
+import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
|
||||
```
|
||||
|
||||
```diff
|
||||
case 'techdocs':
|
||||
return (
|
||||
- <DocsResultListItem
|
||||
+ <TechDocsSearchResultListItem
|
||||
key={document.location}
|
||||
result={document}
|
||||
/>
|
||||
```
|
||||
|
||||
The `TechDocsIndexPage` now uses `DefaultTechDocsHome` as fall back if no children is provided as `LegacyTechDocsHome` is marked as deprecated. If you do not use a custom techdocs homepage, you can therefore update your app to the following:
|
||||
|
||||
```diff
|
||||
- <Route path="/docs" element={<TechDocsIndexPage />}>
|
||||
- <DefaultTechDocsHome />
|
||||
- </Route>
|
||||
+ <Route path="/docs" element={<TechDocsIndexPage />} />
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': minor
|
||||
---
|
||||
|
||||
**BREAKING:**
|
||||
Table column utilities `createNameColumn`, `createOwnerColumn`, `createTypeColumn` as well as actions utilities `createCopyDocsUrlAction` and `createStarEntityAction` are no longer directly exported. Instead accessible through DocsTable and EntityListDocsTable.
|
||||
|
||||
Use as following:
|
||||
|
||||
```tsx
|
||||
DocsTable.columns.createNameColumn();
|
||||
DocsTable.columns.createOwnerColumn();
|
||||
DocsTable.columns.createTypeColumn();
|
||||
|
||||
DocsTable.actions.createCopyDocsUrlAction();
|
||||
DocsTable.actions.createStarEntityAction();
|
||||
```
|
||||
|
||||
- Renamed `DocsResultListItem` to `TechDocsSearchResultListItem`, leaving the old name in place as a deprecations.
|
||||
|
||||
- Renamed `TechDocsPage` to `TechDocsReaderPage`, leaving the old name in place as a deprecations.
|
||||
|
||||
- Renamed `TechDocsPageRenderFunction` to `TechDocsPageRenderFunction`, leaving the old name in place as a deprecations.
|
||||
|
||||
- Renamed `TechDocsPageHeader` to `TechDocsReaderPageHeader`, leaving the old name in place as a deprecations.
|
||||
|
||||
- `LegacyTechDocsHome` marked as deprecated and will be deleted in next release, use `TechDocsCustomHome` instead.
|
||||
|
||||
- `LegacyTechDocsPage` marked as deprecated and will be deleted in next release, use `TechDocsReaderPage` instead.
|
||||
@@ -65,7 +65,6 @@ import {
|
||||
import { SearchPage } from '@backstage/plugin-search';
|
||||
import { TechRadarPage } from '@backstage/plugin-tech-radar';
|
||||
import {
|
||||
DefaultTechDocsHome,
|
||||
TechDocsIndexPage,
|
||||
techdocsPlugin,
|
||||
TechDocsReaderPage,
|
||||
@@ -169,9 +168,7 @@ const routes = (
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route path="/docs" element={<TechDocsIndexPage />}>
|
||||
<DefaultTechDocsHome />
|
||||
</Route>
|
||||
<Route path="/docs" element={<TechDocsIndexPage />} />
|
||||
<Route
|
||||
path="/docs/:namespace/:kind/:name/*"
|
||||
element={<TechDocsReaderPage />}
|
||||
|
||||
@@ -38,7 +38,7 @@ import {
|
||||
SearchType,
|
||||
useSearch,
|
||||
} from '@backstage/plugin-search';
|
||||
import { DocsResultListItem } from '@backstage/plugin-techdocs';
|
||||
import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
|
||||
import { Grid, List, makeStyles, Paper, Theme } from '@material-ui/core';
|
||||
import React, { useContext } from 'react';
|
||||
|
||||
@@ -143,7 +143,7 @@ const SearchPage = () => {
|
||||
);
|
||||
case 'techdocs':
|
||||
return (
|
||||
<DocsResultListItem
|
||||
<TechDocsSearchResultListItem
|
||||
key={document.location}
|
||||
result={document}
|
||||
/>
|
||||
|
||||
@@ -16,18 +16,18 @@
|
||||
|
||||
import { Content } from '@backstage/core-components';
|
||||
import {
|
||||
TechDocsPageHeader,
|
||||
TechDocsPage,
|
||||
TechDocsReaderPageHeader,
|
||||
TechDocsReaderPage,
|
||||
Reader,
|
||||
} from '@backstage/plugin-techdocs';
|
||||
import React from 'react';
|
||||
|
||||
const DefaultTechDocsPage = () => {
|
||||
return (
|
||||
<TechDocsPage>
|
||||
<TechDocsReaderPage>
|
||||
{({ techdocsMetadataValue, entityMetadataValue, entityRef, onReady }) => (
|
||||
<>
|
||||
<TechDocsPageHeader
|
||||
<TechDocsReaderPageHeader
|
||||
techDocsMetadata={techdocsMetadataValue}
|
||||
entityMetadata={entityMetadataValue}
|
||||
entityRef={entityRef}
|
||||
@@ -37,7 +37,7 @@ const DefaultTechDocsPage = () => {
|
||||
</Content>
|
||||
</>
|
||||
)}
|
||||
</TechDocsPage>
|
||||
</TechDocsReaderPage>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import { orgPlugin } from '@backstage/plugin-org';
|
||||
import { SearchPage } from '@backstage/plugin-search';
|
||||
import { TechRadarPage } from '@backstage/plugin-tech-radar';
|
||||
import {
|
||||
DefaultTechDocsHome,
|
||||
TechDocsIndexPage,
|
||||
techdocsPlugin,
|
||||
TechDocsReaderPage,
|
||||
@@ -65,9 +64,7 @@ const routes = (
|
||||
>
|
||||
{entityPage}
|
||||
</Route>
|
||||
<Route path="/docs" element={<TechDocsIndexPage />}>
|
||||
<DefaultTechDocsHome />
|
||||
</Route>
|
||||
<Route path="/docs" element={<TechDocsIndexPage />} />
|
||||
<Route
|
||||
path="/docs/:namespace/:kind/:name/*"
|
||||
element={<TechDocsReaderPage />}
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import {
|
||||
catalogApiRef,
|
||||
CATALOG_FILTER_EXISTS,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { DocsResultListItem } from '@backstage/plugin-techdocs';
|
||||
import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
|
||||
|
||||
import {
|
||||
SearchBar,
|
||||
@@ -123,7 +123,7 @@ const SearchPage = () => {
|
||||
);
|
||||
case 'techdocs':
|
||||
return (
|
||||
<DocsResultListItem
|
||||
<TechDocsSearchResultListItem
|
||||
key={document.location}
|
||||
result={document}
|
||||
/>
|
||||
|
||||
+233
-229
@@ -5,7 +5,6 @@
|
||||
```ts
|
||||
/// <reference types="react" />
|
||||
|
||||
import { Action } from '@material-table/core';
|
||||
import { ApiRef } from '@backstage/core-plugin-api';
|
||||
import { BackstagePlugin } from '@backstage/core-plugin-api';
|
||||
import { Config } from '@backstage/config';
|
||||
@@ -22,115 +21,69 @@ import { TableColumn } from '@backstage/core-components';
|
||||
import { TableProps } from '@backstage/core-components';
|
||||
import { UserListFilterKind } from '@backstage/plugin-catalog-react';
|
||||
|
||||
// Warning: (ae-missing-release-tag) "createCopyDocsUrlAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
function createCopyDocsUrlAction(copyToClipboard: Function): (
|
||||
row: DocsTableRow,
|
||||
) => {
|
||||
icon: () => JSX.Element;
|
||||
tooltip: string;
|
||||
onClick: () => any;
|
||||
};
|
||||
// @public
|
||||
export const DefaultTechDocsHome: (
|
||||
props: DefaultTechDocsHomeProps,
|
||||
) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "createNameColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
function createNameColumn(): TableColumn<DocsTableRow>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "createOwnerColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
function createOwnerColumn(): TableColumn<DocsTableRow>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "createStarEntityAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
function createStarEntityAction(
|
||||
isStarredEntity: Function,
|
||||
toggleStarredEntity: Function,
|
||||
): ({ entity }: DocsTableRow) => {
|
||||
cellStyle: {
|
||||
paddingLeft: string;
|
||||
};
|
||||
icon: () => JSX.Element;
|
||||
tooltip: string;
|
||||
onClick: () => any;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "createTypeColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
function createTypeColumn(): TableColumn<DocsTableRow>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "DefaultTechDocsHome" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const DefaultTechDocsHome: ({
|
||||
initialFilter,
|
||||
columns,
|
||||
actions,
|
||||
}: {
|
||||
initialFilter?: UserListFilterKind | undefined;
|
||||
columns?: TableColumn<DocsTableRow>[] | undefined;
|
||||
// @public
|
||||
export type DefaultTechDocsHomeProps = {
|
||||
initialFilter?: UserListFilterKind;
|
||||
columns?: TableColumn<DocsTableRow>[];
|
||||
actions?: TableProps<DocsTableRow>['actions'];
|
||||
}) => JSX.Element;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "DocsCardGrid" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const DocsCardGrid: ({
|
||||
entities,
|
||||
}: {
|
||||
// @public
|
||||
export const DocsCardGrid: (props: DocsCardGridProps) => JSX.Element | null;
|
||||
|
||||
// @public
|
||||
export type DocsCardGridProps = {
|
||||
entities: Entity[] | undefined;
|
||||
}) => JSX.Element | null;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "DocsResultListItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const DocsResultListItem: ({
|
||||
result,
|
||||
lineClamp,
|
||||
asListItem,
|
||||
asLink,
|
||||
title,
|
||||
}: {
|
||||
result: any;
|
||||
lineClamp?: number | undefined;
|
||||
asListItem?: boolean | undefined;
|
||||
asLink?: boolean | undefined;
|
||||
title?: string | undefined;
|
||||
}) => JSX.Element;
|
||||
// @public @deprecated (undocumented)
|
||||
export const DocsResultListItem: (
|
||||
props: TechDocsSearchResultListItemProps,
|
||||
) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "DocsTable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const DocsTable: ({
|
||||
entities,
|
||||
title,
|
||||
loading,
|
||||
columns,
|
||||
actions,
|
||||
}: {
|
||||
// @public
|
||||
export const DocsTable: {
|
||||
(props: DocsTableProps): JSX.Element | null;
|
||||
columns: {
|
||||
createNameColumn(): TableColumn<DocsTableRow>;
|
||||
createOwnerColumn(): TableColumn<DocsTableRow>;
|
||||
createTypeColumn(): TableColumn<DocsTableRow>;
|
||||
};
|
||||
actions: {
|
||||
createCopyDocsUrlAction(copyToClipboard: Function): (row: DocsTableRow) => {
|
||||
icon: () => JSX.Element;
|
||||
tooltip: string;
|
||||
onClick: () => any;
|
||||
};
|
||||
createStarEntityAction(
|
||||
isStarredEntity: Function,
|
||||
toggleStarredEntity: Function,
|
||||
): ({ entity }: DocsTableRow) => {
|
||||
cellStyle: {
|
||||
paddingLeft: string;
|
||||
};
|
||||
icon: () => JSX.Element;
|
||||
tooltip: string;
|
||||
onClick: () => any;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// @public
|
||||
export type DocsTableProps = {
|
||||
entities: Entity[] | undefined;
|
||||
title?: string | undefined;
|
||||
loading?: boolean | undefined;
|
||||
columns?: TableColumn<DocsTableRow>[] | undefined;
|
||||
actions?:
|
||||
| (
|
||||
| Action<DocsTableRow>
|
||||
| {
|
||||
action: (rowData: DocsTableRow) => Action<DocsTableRow>;
|
||||
position: string;
|
||||
}
|
||||
| ((rowData: DocsTableRow) => Action<DocsTableRow>)
|
||||
)[]
|
||||
| undefined;
|
||||
}) => JSX.Element | null;
|
||||
columns?: TableColumn<DocsTableRow>[];
|
||||
actions?: TableProps<DocsTableRow>['actions'];
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "DocsTableRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type DocsTableRow = {
|
||||
entity: Entity;
|
||||
resolved: {
|
||||
@@ -140,74 +93,101 @@ export type DocsTableRow = {
|
||||
};
|
||||
};
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "EmbeddedDocsRouter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const EmbeddedDocsRouter: (_props: Props_2) => JSX.Element;
|
||||
// @public
|
||||
export const EmbeddedDocsRouter: () => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "EntityListDocsGrid" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const EntityListDocsGrid: () => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "EntityListDocsTable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const EntityListDocsTable: {
|
||||
({
|
||||
columns,
|
||||
actions,
|
||||
}: {
|
||||
columns?: TableColumn<DocsTableRow>[] | undefined;
|
||||
actions?: TableProps<DocsTableRow>['actions'];
|
||||
}): JSX.Element;
|
||||
columns: typeof columnFactories;
|
||||
actions: typeof actionFactories;
|
||||
(props: EntityListDocsTableProps): JSX.Element;
|
||||
columns: {
|
||||
createNameColumn(): TableColumn<DocsTableRow>;
|
||||
createOwnerColumn(): TableColumn<DocsTableRow>;
|
||||
createTypeColumn(): TableColumn<DocsTableRow>;
|
||||
};
|
||||
actions: {
|
||||
createCopyDocsUrlAction(copyToClipboard: Function): (row: DocsTableRow) => {
|
||||
icon: () => JSX.Element;
|
||||
tooltip: string;
|
||||
onClick: () => any;
|
||||
};
|
||||
createStarEntityAction(
|
||||
isStarredEntity: Function,
|
||||
toggleStarredEntity: Function,
|
||||
): ({ entity }: DocsTableRow) => {
|
||||
cellStyle: {
|
||||
paddingLeft: string;
|
||||
};
|
||||
icon: () => JSX.Element;
|
||||
tooltip: string;
|
||||
onClick: () => any;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "EntityTechdocsContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const EntityTechdocsContent: (_props: {}) => JSX.Element;
|
||||
// @public
|
||||
export type EntityListDocsTableProps = {
|
||||
columns?: TableColumn<DocsTableRow>[];
|
||||
actions?: TableProps<DocsTableRow>['actions'];
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "isTechDocsAvailable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export const EntityTechdocsContent: () => JSX.Element;
|
||||
|
||||
// @public
|
||||
export const isTechDocsAvailable: (entity: Entity) => boolean;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "PanelType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export interface PanelConfig {
|
||||
// (undocumented)
|
||||
description: string;
|
||||
// (undocumented)
|
||||
filterPredicate: ((entity: Entity) => boolean) | string;
|
||||
// (undocumented)
|
||||
panelCSS?: CSSProperties;
|
||||
// (undocumented)
|
||||
panelType: PanelType;
|
||||
// (undocumented)
|
||||
title: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type PanelType = 'DocsCardGrid' | 'DocsTable';
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "Reader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const Reader: ({
|
||||
entityRef,
|
||||
onReady,
|
||||
withSearch,
|
||||
}: Props_3) => JSX.Element;
|
||||
// @public
|
||||
export const Reader: (props: ReaderProps) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type ReaderProps = {
|
||||
entityRef: EntityName;
|
||||
withSearch?: boolean;
|
||||
onReady?: () => void;
|
||||
};
|
||||
|
||||
// @public
|
||||
export const Router: () => JSX.Element;
|
||||
|
||||
// @public
|
||||
export type SyncResult = 'cached' | 'updated';
|
||||
|
||||
// @public
|
||||
export interface TabConfig {
|
||||
// (undocumented)
|
||||
label: string;
|
||||
// (undocumented)
|
||||
panels: PanelConfig[];
|
||||
}
|
||||
|
||||
// @public
|
||||
export type TabsConfig = TabConfig[];
|
||||
|
||||
// @public
|
||||
export interface TechDocsApi {
|
||||
getApiOrigin(): Promise<string>;
|
||||
// Warning: (ae-forgotten-export) The symbol "TechDocsEntityMetadata" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
getEntityMetadata(entityId: EntityName): Promise<TechDocsEntityMetadata>;
|
||||
// Warning: (ae-forgotten-export) The symbol "TechDocsMetadata" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
getTechDocsMetadata(entityId: EntityName): Promise<TechDocsMetadata>;
|
||||
}
|
||||
@@ -232,84 +212,64 @@ export class TechDocsClient implements TechDocsApi {
|
||||
getTechDocsMetadata(entityId: EntityName): Promise<TechDocsMetadata>;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechDocsCustomHome" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const TechDocsCustomHome: ({
|
||||
tabsConfig,
|
||||
}: {
|
||||
// @public
|
||||
export const TechDocsCustomHome: (
|
||||
props: TechDocsCustomHomeProps,
|
||||
) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export type TechDocsCustomHomeProps = {
|
||||
tabsConfig: TabsConfig;
|
||||
}) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechDocsIndexPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const TechDocsIndexPage: () => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechDocsPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const TechDocsPage: ({ children }: TechDocsPageProps) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechdocsPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const TechdocsPage: () => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechDocsPageHeader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const TechDocsPageHeader: ({
|
||||
entityRef,
|
||||
entityMetadata,
|
||||
techDocsMetadata,
|
||||
children,
|
||||
}: TechDocsPageHeaderProps) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechDocsPageHeaderProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type TechDocsPageHeaderProps = PropsWithChildren<{
|
||||
entityRef: EntityName;
|
||||
entityMetadata?: TechDocsEntityMetadata;
|
||||
techDocsMetadata?: TechDocsMetadata;
|
||||
}>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechDocsPageProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type TechDocsPageProps = {
|
||||
children?: TechDocsPageRenderFunction | React_2.ReactNode;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechDocsPageRenderFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type TechDocsPageRenderFunction = ({
|
||||
techdocsMetadataValue,
|
||||
entityMetadataValue,
|
||||
entityRef,
|
||||
}: {
|
||||
techdocsMetadataValue?: TechDocsMetadata | undefined;
|
||||
entityMetadataValue?: TechDocsEntityMetadata | undefined;
|
||||
entityRef: EntityName;
|
||||
onReady: () => void;
|
||||
}) => JSX.Element;
|
||||
// @public
|
||||
export type TechDocsEntityMetadata = Entity & {
|
||||
locationMetadata?: {
|
||||
type: string;
|
||||
target: string;
|
||||
};
|
||||
};
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "TechDocsPageWrapper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const TechDocsPageWrapper: ({ children }: Props) => JSX.Element;
|
||||
// @public
|
||||
export const TechDocsIndexPage: () => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechDocsPicker" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type TechDocsMetadata = {
|
||||
site_name: string;
|
||||
site_description: string;
|
||||
};
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export const TechDocsPage: (props: TechDocsReaderPageProps) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export const TechdocsPage: () => JSX.Element;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export const TechDocsPageHeader: (
|
||||
props: TechDocsReaderPageHeaderProps,
|
||||
) => JSX.Element;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export type TechDocsPageHeaderProps = TechDocsReaderPageHeaderProps;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export type TechDocsPageRenderFunction = TechDocsReaderPageRenderFunction;
|
||||
|
||||
// @public
|
||||
export const TechDocsPageWrapper: (
|
||||
props: TechDocsPageWrapperProps,
|
||||
) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export type TechDocsPageWrapperProps = {
|
||||
children?: React_2.ReactNode;
|
||||
};
|
||||
|
||||
// @public
|
||||
export const TechDocsPicker: () => null;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "techdocsPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
const techdocsPlugin: BackstagePlugin<
|
||||
{
|
||||
root: RouteRef<undefined>;
|
||||
@@ -325,12 +285,62 @@ const techdocsPlugin: BackstagePlugin<
|
||||
export { techdocsPlugin as plugin };
|
||||
export { techdocsPlugin };
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TechDocsReaderPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const TechDocsReaderPage: ({
|
||||
children,
|
||||
}: TechDocsPageProps) => JSX.Element;
|
||||
// @public
|
||||
export const TechDocsReaderPage: (
|
||||
props: TechDocsReaderPageProps,
|
||||
) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export const TechDocsReaderPageHeader: (
|
||||
props: TechDocsReaderPageHeaderProps,
|
||||
) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export type TechDocsReaderPageHeaderProps = PropsWithChildren<{
|
||||
entityRef: EntityName;
|
||||
entityMetadata?: TechDocsEntityMetadata;
|
||||
techDocsMetadata?: TechDocsMetadata;
|
||||
}>;
|
||||
|
||||
// @public
|
||||
export type TechDocsReaderPageProps = {
|
||||
children?: TechDocsReaderPageRenderFunction | React_2.ReactNode;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type TechDocsReaderPageRenderFunction = ({
|
||||
techdocsMetadataValue,
|
||||
entityMetadataValue,
|
||||
entityRef,
|
||||
}: {
|
||||
techdocsMetadataValue?: TechDocsMetadata | undefined;
|
||||
entityMetadataValue?: TechDocsEntityMetadata | undefined;
|
||||
entityRef: EntityName;
|
||||
onReady: () => void;
|
||||
}) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export const TechDocsSearch: (props: TechDocsSearchProps) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export type TechDocsSearchProps = {
|
||||
entityId: EntityName;
|
||||
debounceTime?: number;
|
||||
};
|
||||
|
||||
// @public
|
||||
export const TechDocsSearchResultListItem: (
|
||||
props: TechDocsSearchResultListItemProps,
|
||||
) => JSX.Element;
|
||||
|
||||
// @public
|
||||
export type TechDocsSearchResultListItemProps = {
|
||||
result: any;
|
||||
lineClamp?: number;
|
||||
asListItem?: boolean;
|
||||
asLink?: boolean;
|
||||
title?: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export interface TechDocsStorageApi {
|
||||
@@ -389,10 +399,4 @@ export class TechDocsStorageClient implements TechDocsStorageApi {
|
||||
logHandler?: (line: string) => void,
|
||||
): Promise<SyncResult>;
|
||||
}
|
||||
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/home/components/EntityListDocsTable.d.ts:11:5 - (ae-forgotten-export) The symbol "columnFactories" needs to be exported by the entry point index.d.ts
|
||||
// src/home/components/EntityListDocsTable.d.ts:12:5 - (ae-forgotten-export) The symbol "actionFactories" needs to be exported by the entry point index.d.ts
|
||||
// src/plugin.d.ts:27:5 - (ae-forgotten-export) The symbol "TabsConfig" needs to be exported by the entry point index.d.ts
|
||||
```
|
||||
|
||||
@@ -19,15 +19,25 @@ import { Entity } from '@backstage/catalog-model';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import { TechDocsIndexPage } from './home/components/TechDocsIndexPage';
|
||||
import { TechDocsPage as TechDocsReaderPage } from './reader/components/TechDocsPage';
|
||||
import { TechDocsReaderPage } from './reader/components/TechDocsReaderPage';
|
||||
import { EntityPageDocs } from './EntityPageDocs';
|
||||
import { MissingAnnotationEmptyState } from '@backstage/core-components';
|
||||
|
||||
const TECHDOCS_ANNOTATION = 'backstage.io/techdocs-ref';
|
||||
|
||||
/**
|
||||
* Helper that takes in entity and returns true/false if TechDocs is available for the entity
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const isTechDocsAvailable = (entity: Entity) =>
|
||||
Boolean(entity?.metadata?.annotations?.[TECHDOCS_ANNOTATION]);
|
||||
|
||||
/**
|
||||
* Responsible for registering routes for TechDocs, TechDocs Homepage and separate TechDocs page
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Router = () => {
|
||||
return (
|
||||
<Routes>
|
||||
@@ -40,9 +50,12 @@ export const Router = () => {
|
||||
);
|
||||
};
|
||||
|
||||
type Props = {};
|
||||
|
||||
export const EmbeddedDocsRouter = (_props: Props) => {
|
||||
/**
|
||||
* Responsible for registering route to view docs on Entity page
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const EmbeddedDocsRouter = () => {
|
||||
const { entity } = useEntity();
|
||||
|
||||
const projectId = entity.metadata.annotations?.[TECHDOCS_ANNOTATION];
|
||||
|
||||
@@ -34,20 +34,28 @@ import {
|
||||
UserListFilterKind,
|
||||
UserListPicker,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { EntityListDocsTable } from './EntityListDocsTable';
|
||||
import { TechDocsPageWrapper } from './TechDocsPageWrapper';
|
||||
import { TechDocsPicker } from './TechDocsPicker';
|
||||
import { DocsTableRow } from './types';
|
||||
import { DocsTableRow, EntityListDocsTable } from './Tables';
|
||||
|
||||
export const DefaultTechDocsHome = ({
|
||||
initialFilter = 'all',
|
||||
columns,
|
||||
actions,
|
||||
}: {
|
||||
/**
|
||||
* Props for {@link DefaultTechDocsHome}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type DefaultTechDocsHomeProps = {
|
||||
initialFilter?: UserListFilterKind;
|
||||
columns?: TableColumn<DocsTableRow>[];
|
||||
actions?: TableProps<DocsTableRow>['actions'];
|
||||
}) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Component which renders a default documentation landing page.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const DefaultTechDocsHome = (props: DefaultTechDocsHomeProps) => {
|
||||
const { initialFilter = 'all', columns, actions } = props;
|
||||
return (
|
||||
<TechDocsPageWrapper>
|
||||
<Content>
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import { configApiRef } from '@backstage/core-plugin-api';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { rootDocsRouteRef } from '../../routes';
|
||||
import { rootDocsRouteRef } from '../../../routes';
|
||||
import { DocsCardGrid } from './DocsCardGrid';
|
||||
|
||||
// Hacky way to mock a specific boolean config value.
|
||||
+19
-10
@@ -14,25 +14,34 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { rootDocsRouteRef } from '../../../routes';
|
||||
import { toLowerMaybe } from '../../../helpers';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { useApi, useRouteRef, configApiRef } from '@backstage/core-plugin-api';
|
||||
import { Card, CardActions, CardContent, CardMedia } from '@material-ui/core';
|
||||
import { rootDocsRouteRef } from '../../routes';
|
||||
|
||||
import {
|
||||
Button,
|
||||
ItemCardGrid,
|
||||
ItemCardHeader,
|
||||
} from '@backstage/core-components';
|
||||
import { toLowerMaybe } from '../../helpers';
|
||||
import { Card, CardActions, CardContent, CardMedia } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
|
||||
export const DocsCardGrid = ({
|
||||
entities,
|
||||
}: {
|
||||
/**
|
||||
* Props for {@link DocsCardGrid}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type DocsCardGridProps = {
|
||||
entities: Entity[] | undefined;
|
||||
}) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Component which accepts a list of entities and renders a item card for each entity
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const DocsCardGrid = (props: DocsCardGridProps) => {
|
||||
const { entities } = props;
|
||||
const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);
|
||||
const config = useApi(configApiRef);
|
||||
if (!entities) return null;
|
||||
+7
-1
@@ -13,6 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DocsCardGrid } from './DocsCardGrid';
|
||||
import {
|
||||
CodeSnippet,
|
||||
Progress,
|
||||
@@ -20,8 +22,12 @@ import {
|
||||
} from '@backstage/core-components';
|
||||
import { useEntityList } from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import { DocsCardGrid } from './DocsCardGrid';
|
||||
|
||||
/**
|
||||
* Component responsible to get entities from entity list context and pass down to DocsCardGrid
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const EntityListDocsGrid = () => {
|
||||
const { loading, error, entities } = useEntityList();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './EntityListDocsGrid';
|
||||
export * from './DocsCardGrid';
|
||||
@@ -17,6 +17,9 @@
|
||||
import React from 'react';
|
||||
import { PanelType, TechDocsCustomHome } from './TechDocsCustomHome';
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link TechDocsCustomHome} instead.
|
||||
*/
|
||||
export const LegacyTechDocsHome = () => {
|
||||
const tabsConfig = [
|
||||
{
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import { render } from '@testing-library/react';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import { configApiRef } from '@backstage/core-plugin-api';
|
||||
import { DocsTable } from './DocsTable';
|
||||
import { rootDocsRouteRef } from '../../routes';
|
||||
import { rootDocsRouteRef } from '../../../routes';
|
||||
import { entityRouteRef } from '@backstage/plugin-catalog-react';
|
||||
|
||||
// Hacky way to mock a specific boolean config value.
|
||||
+22
-12
@@ -23,7 +23,7 @@ import {
|
||||
formatEntityRefTitle,
|
||||
getEntityRelations,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { rootDocsRouteRef } from '../../routes';
|
||||
import { rootDocsRouteRef } from '../../../routes';
|
||||
import {
|
||||
Button,
|
||||
EmptyState,
|
||||
@@ -31,24 +31,31 @@ import {
|
||||
TableColumn,
|
||||
TableProps,
|
||||
} from '@backstage/core-components';
|
||||
import * as actionFactories from './actions';
|
||||
import * as columnFactories from './columns';
|
||||
import { actionFactories } from './actions';
|
||||
import { columnFactories } from './columns';
|
||||
import { toLowerMaybe } from '../../../helpers';
|
||||
import { DocsTableRow } from './types';
|
||||
import { toLowerMaybe } from '../../helpers';
|
||||
|
||||
export const DocsTable = ({
|
||||
entities,
|
||||
title,
|
||||
loading,
|
||||
columns,
|
||||
actions,
|
||||
}: {
|
||||
/**
|
||||
* Props for {@link DocsTable}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type DocsTableProps = {
|
||||
entities: Entity[] | undefined;
|
||||
title?: string | undefined;
|
||||
loading?: boolean | undefined;
|
||||
columns?: TableColumn<DocsTableRow>[];
|
||||
actions?: TableProps<DocsTableRow>['actions'];
|
||||
}) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Component which renders a table documents
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const DocsTable = (props: DocsTableProps) => {
|
||||
const { entities, title, loading, columns, actions } = props;
|
||||
const [, copyToClipboard] = useCopyToClipboard();
|
||||
const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);
|
||||
const config = useApi(configApiRef);
|
||||
@@ -124,3 +131,6 @@ export const DocsTable = ({
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
DocsTable.columns = columnFactories;
|
||||
DocsTable.actions = actionFactories;
|
||||
+17
-7
@@ -28,17 +28,27 @@ import {
|
||||
useStarredEntities,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { DocsTable } from './DocsTable';
|
||||
import * as actionFactories from './actions';
|
||||
import * as columnFactories from './columns';
|
||||
import { actionFactories } from './actions';
|
||||
import { columnFactories } from './columns';
|
||||
import { DocsTableRow } from './types';
|
||||
|
||||
export const EntityListDocsTable = ({
|
||||
columns,
|
||||
actions,
|
||||
}: {
|
||||
/**
|
||||
* Props for {@link EntityListDocsTable}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type EntityListDocsTableProps = {
|
||||
columns?: TableColumn<DocsTableRow>[];
|
||||
actions?: TableProps<DocsTableRow>['actions'];
|
||||
}) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Component which renders a table with entities from catalog.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const EntityListDocsTable = (props: EntityListDocsTableProps) => {
|
||||
const { columns, actions } = props;
|
||||
const { loading, error, entities, filters } = useEntityList();
|
||||
const { isStarredEntity, toggleStarredEntity } = useStarredEntities();
|
||||
const [, copyToClipboard] = useCopyToClipboard();
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2021 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 from 'react';
|
||||
import ShareIcon from '@material-ui/icons/Share';
|
||||
import {
|
||||
favoriteEntityIcon,
|
||||
favoriteEntityTooltip,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { DocsTableRow } from './types';
|
||||
|
||||
/**
|
||||
* Not directly exported, but through DocsTable.actions and EntityListDocsTable.actions
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const actionFactories = {
|
||||
createCopyDocsUrlAction(copyToClipboard: Function) {
|
||||
return (row: DocsTableRow) => {
|
||||
return {
|
||||
icon: () => <ShareIcon fontSize="small" />,
|
||||
tooltip: 'Click to copy documentation link to clipboard',
|
||||
onClick: () =>
|
||||
copyToClipboard(`${window.location.origin}${row.resolved.docsUrl}`),
|
||||
};
|
||||
};
|
||||
},
|
||||
createStarEntityAction(
|
||||
isStarredEntity: Function,
|
||||
toggleStarredEntity: Function,
|
||||
) {
|
||||
return ({ entity }: DocsTableRow) => {
|
||||
const isStarred = isStarredEntity(entity);
|
||||
return {
|
||||
cellStyle: { paddingLeft: '1em' },
|
||||
icon: () => favoriteEntityIcon(isStarred),
|
||||
tooltip: favoriteEntityTooltip(isStarred),
|
||||
onClick: () => toggleStarredEntity(entity),
|
||||
};
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2021 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 from 'react';
|
||||
import { Link, SubvalueCell, TableColumn } from '@backstage/core-components';
|
||||
import { EntityRefLinks } from '@backstage/plugin-catalog-react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { DocsTableRow } from './types';
|
||||
|
||||
function customTitle(entity: Entity): string {
|
||||
return entity.metadata.title || entity.metadata.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not directly exported, but through DocsTable.columns and EntityListDocsTable.columns
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const columnFactories = {
|
||||
createNameColumn(): TableColumn<DocsTableRow> {
|
||||
return {
|
||||
title: 'Document',
|
||||
field: 'entity.metadata.name',
|
||||
highlight: true,
|
||||
render: (row: DocsTableRow) => (
|
||||
<SubvalueCell
|
||||
value={
|
||||
<Link to={row.resolved.docsUrl}>{customTitle(row.entity)}</Link>
|
||||
}
|
||||
subvalue={row.entity.metadata.description}
|
||||
/>
|
||||
),
|
||||
};
|
||||
},
|
||||
createOwnerColumn(): TableColumn<DocsTableRow> {
|
||||
return {
|
||||
title: 'Owner',
|
||||
field: 'resolved.ownedByRelationsTitle',
|
||||
render: ({ resolved }) => (
|
||||
<EntityRefLinks
|
||||
entityRefs={resolved.ownedByRelations}
|
||||
defaultKind="group"
|
||||
/>
|
||||
),
|
||||
};
|
||||
},
|
||||
createTypeColumn(): TableColumn<DocsTableRow> {
|
||||
return {
|
||||
title: 'Type',
|
||||
field: 'entity.spec.type',
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './EntityListDocsTable';
|
||||
export * from './DocsTable';
|
||||
export * from './types';
|
||||
+5
@@ -16,6 +16,11 @@
|
||||
|
||||
import { Entity, EntityName } from '@backstage/catalog-model';
|
||||
|
||||
/**
|
||||
* Generic representing the metadata structure for a docs table row.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type DocsTableRow = {
|
||||
entity: Entity;
|
||||
resolved: {
|
||||
@@ -30,8 +30,8 @@ import {
|
||||
parseEntityRef,
|
||||
UserEntity,
|
||||
} from '@backstage/catalog-model';
|
||||
import { DocsTable } from './DocsTable';
|
||||
import { DocsCardGrid } from './DocsCardGrid';
|
||||
import { DocsTable } from './Tables';
|
||||
import { DocsCardGrid } from './Grids';
|
||||
import { TechDocsPageWrapper } from './TechDocsPageWrapper';
|
||||
|
||||
import {
|
||||
@@ -51,8 +51,18 @@ const panels = {
|
||||
DocsCardGrid: DocsCardGrid,
|
||||
};
|
||||
|
||||
/**
|
||||
* Available panel types
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type PanelType = 'DocsCardGrid' | 'DocsTable';
|
||||
|
||||
/**
|
||||
* Type representing a TechDocsCustomHome panel.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface PanelConfig {
|
||||
title: string;
|
||||
description: string;
|
||||
@@ -61,11 +71,21 @@ export interface PanelConfig {
|
||||
filterPredicate: ((entity: Entity) => boolean) | string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type representing a TechDocsCustomHome tab.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface TabConfig {
|
||||
label: string;
|
||||
panels: PanelConfig[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Type representing a list of TechDocsCustomHome tabs.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TabsConfig = TabConfig[];
|
||||
|
||||
const CustomPanel = ({
|
||||
@@ -118,11 +138,17 @@ const CustomPanel = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const TechDocsCustomHome = ({
|
||||
tabsConfig,
|
||||
}: {
|
||||
/**
|
||||
* Props for {@link TechDocsCustomHome}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsCustomHomeProps = {
|
||||
tabsConfig: TabsConfig;
|
||||
}) => {
|
||||
};
|
||||
|
||||
export const TechDocsCustomHome = (props: TechDocsCustomHomeProps) => {
|
||||
const { tabsConfig } = props;
|
||||
const [selectedTab, setSelectedTab] = useState<number>(0);
|
||||
const catalogApi: CatalogApi = useApi(catalogApiRef);
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ jest.mock('react-router', () => ({
|
||||
useOutlet: jest.fn().mockReturnValue('Route Children'),
|
||||
}));
|
||||
|
||||
jest.mock('./LegacyTechDocsHome', () => ({
|
||||
LegacyTechDocsHome: jest.fn().mockReturnValue('LegacyTechDocsHomeMock'),
|
||||
jest.mock('./DefaultTechDocsHome', () => ({
|
||||
DefaultTechDocsHome: jest.fn().mockReturnValue('DefaultTechDocsHomeMock'),
|
||||
}));
|
||||
|
||||
describe('TechDocsIndexPage', () => {
|
||||
@@ -35,10 +35,10 @@ describe('TechDocsIndexPage', () => {
|
||||
expect(getByText('Route Children')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders legacy TechDocs home when no router children are provided', async () => {
|
||||
it('renders DefaultTechDocsHome when no router children are provided', async () => {
|
||||
(useOutlet as jest.Mock).mockReturnValueOnce(null);
|
||||
const { getByText } = await renderInTestApp(<TechDocsIndexPage />);
|
||||
|
||||
expect(getByText('LegacyTechDocsHomeMock')).toBeInTheDocument();
|
||||
expect(getByText('DefaultTechDocsHomeMock')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
import React from 'react';
|
||||
import { useOutlet } from 'react-router';
|
||||
import { LegacyTechDocsHome } from './LegacyTechDocsHome';
|
||||
import { DefaultTechDocsHome } from './DefaultTechDocsHome';
|
||||
|
||||
export const TechDocsIndexPage = () => {
|
||||
const outlet = useOutlet();
|
||||
|
||||
return outlet || <LegacyTechDocsHome />;
|
||||
return outlet || <DefaultTechDocsHome />;
|
||||
};
|
||||
|
||||
@@ -19,11 +19,22 @@ import React from 'react';
|
||||
import { PageWithHeader } from '@backstage/core-components';
|
||||
import { useApi, configApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
type Props = {
|
||||
/**
|
||||
* Props for {@link TechDocsPageWrapper}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsPageWrapperProps = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export const TechDocsPageWrapper = ({ children }: Props) => {
|
||||
/**
|
||||
* Component wrapping a techdocs page with Page and Header components
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsPageWrapper = (props: TechDocsPageWrapperProps) => {
|
||||
const { children } = props;
|
||||
const configApi = useApi(configApiRef);
|
||||
const generatedSubtitle = `Documentation available in ${
|
||||
configApi.getOptionalString('organization.name') ?? 'Backstage'
|
||||
|
||||
@@ -34,6 +34,11 @@ type CustomFilters = DefaultEntityFilters & {
|
||||
techdocs?: TechDocsFilter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Component responsible for updating TechDocs filters
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsPicker = () => {
|
||||
const { updateFilters } = useEntityList<CustomFilters>();
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 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 from 'react';
|
||||
import ShareIcon from '@material-ui/icons/Share';
|
||||
import {
|
||||
favoriteEntityIcon,
|
||||
favoriteEntityTooltip,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { DocsTableRow } from './types';
|
||||
|
||||
export function createCopyDocsUrlAction(copyToClipboard: Function) {
|
||||
return (row: DocsTableRow) => {
|
||||
return {
|
||||
icon: () => <ShareIcon fontSize="small" />,
|
||||
tooltip: 'Click to copy documentation link to clipboard',
|
||||
onClick: () =>
|
||||
copyToClipboard(`${window.location.origin}${row.resolved.docsUrl}`),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function createStarEntityAction(
|
||||
isStarredEntity: Function,
|
||||
toggleStarredEntity: Function,
|
||||
) {
|
||||
return ({ entity }: DocsTableRow) => {
|
||||
const isStarred = isStarredEntity(entity);
|
||||
return {
|
||||
cellStyle: { paddingLeft: '1em' },
|
||||
icon: () => favoriteEntityIcon(isStarred),
|
||||
tooltip: favoriteEntityTooltip(isStarred),
|
||||
onClick: () => toggleStarredEntity(entity),
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 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 from 'react';
|
||||
import { Link, SubvalueCell, TableColumn } from '@backstage/core-components';
|
||||
import { EntityRefLinks } from '@backstage/plugin-catalog-react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { DocsTableRow } from './types';
|
||||
|
||||
function customTitle(entity: Entity): string {
|
||||
return entity.metadata.title || entity.metadata.name;
|
||||
}
|
||||
|
||||
export function createNameColumn(): TableColumn<DocsTableRow> {
|
||||
return {
|
||||
title: 'Document',
|
||||
field: 'entity.metadata.name',
|
||||
highlight: true,
|
||||
render: (row: DocsTableRow) => (
|
||||
<SubvalueCell
|
||||
value={<Link to={row.resolved.docsUrl}>{customTitle(row.entity)}</Link>}
|
||||
subvalue={row.entity.metadata.description}
|
||||
/>
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export function createOwnerColumn(): TableColumn<DocsTableRow> {
|
||||
return {
|
||||
title: 'Owner',
|
||||
field: 'resolved.ownedByRelationsTitle',
|
||||
render: ({ resolved }) => (
|
||||
<EntityRefLinks
|
||||
entityRefs={resolved.ownedByRelations}
|
||||
defaultKind="group"
|
||||
/>
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export function createTypeColumn(): TableColumn<DocsTableRow> {
|
||||
return {
|
||||
title: 'Type',
|
||||
field: 'entity.spec.type',
|
||||
};
|
||||
}
|
||||
@@ -14,10 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { DefaultTechDocsHome } from './DefaultTechDocsHome';
|
||||
export { EntityListDocsGrid } from './EntityListDocsGrid';
|
||||
export { EntityListDocsTable } from './EntityListDocsTable';
|
||||
export type { PanelType } from './TechDocsCustomHome';
|
||||
export { TechDocsPageWrapper } from './TechDocsPageWrapper';
|
||||
export { TechDocsPicker } from './TechDocsPicker';
|
||||
export type { DocsTableRow } from './types';
|
||||
export * from './Grids';
|
||||
export * from './Tables';
|
||||
export * from './DefaultTechDocsHome';
|
||||
export type {
|
||||
PanelType,
|
||||
PanelConfig,
|
||||
TabConfig,
|
||||
TabsConfig,
|
||||
TechDocsCustomHomeProps,
|
||||
} from './TechDocsCustomHome';
|
||||
export * from './TechDocsPageWrapper';
|
||||
export * from './TechDocsPicker';
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './components';
|
||||
@@ -20,29 +20,19 @@
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './types';
|
||||
export * from './api';
|
||||
export { techdocsApiRef, techdocsStorageApiRef } from './api';
|
||||
export type { TechDocsApi, TechDocsStorageApi } from './api';
|
||||
export { TechDocsClient, TechDocsStorageClient } from './client';
|
||||
export * from './components/DocsResultListItem';
|
||||
export * from './client';
|
||||
export * from './reader';
|
||||
export * from './search';
|
||||
export * from './home';
|
||||
export {
|
||||
DefaultTechDocsHome,
|
||||
EntityListDocsGrid,
|
||||
EntityListDocsTable,
|
||||
TechDocsPageWrapper,
|
||||
TechDocsPicker,
|
||||
} from './home/components';
|
||||
export type { DocsTableRow, PanelType } from './home/components';
|
||||
export {
|
||||
DocsCardGrid,
|
||||
DocsTable,
|
||||
EntityTechdocsContent,
|
||||
TechDocsCustomHome,
|
||||
TechDocsIndexPage,
|
||||
TechdocsPage,
|
||||
TechDocsReaderPage,
|
||||
techdocsPlugin as plugin,
|
||||
techdocsPlugin,
|
||||
TechDocsReaderPage,
|
||||
} from './plugin';
|
||||
export * from './reader';
|
||||
export { EmbeddedDocsRouter, isTechDocsAvailable, Router } from './Router';
|
||||
export * from './Router';
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
import {
|
||||
configApiRef,
|
||||
createApiFactory,
|
||||
createComponentExtension,
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
discoveryApiRef,
|
||||
@@ -32,6 +31,11 @@ import {
|
||||
identityApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
/**
|
||||
* The Backstage plugin that renders technical documentation for your components
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const techdocsPlugin = createPlugin({
|
||||
id: 'techdocs',
|
||||
apis: [
|
||||
@@ -73,6 +77,11 @@ export const techdocsPlugin = createPlugin({
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Routable extension used to render docs
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TechdocsPage = techdocsPlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: 'TechdocsPage',
|
||||
@@ -81,6 +90,11 @@ export const TechdocsPage = techdocsPlugin.provide(
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* Routable extension used to render docs on Entity page
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const EntityTechdocsContent = techdocsPlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: 'EntityTechdocsContent',
|
||||
@@ -89,28 +103,11 @@ export const EntityTechdocsContent = techdocsPlugin.provide(
|
||||
}),
|
||||
);
|
||||
|
||||
// takes a list of entities and renders documentation cards
|
||||
export const DocsCardGrid = techdocsPlugin.provide(
|
||||
createComponentExtension({
|
||||
name: 'DocsCardGrid',
|
||||
component: {
|
||||
lazy: () =>
|
||||
import('./home/components/DocsCardGrid').then(m => m.DocsCardGrid),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// takes a list of entities and renders table listing documentation
|
||||
export const DocsTable = techdocsPlugin.provide(
|
||||
createComponentExtension({
|
||||
name: 'DocsTable',
|
||||
component: {
|
||||
lazy: () => import('./home/components/DocsTable').then(m => m.DocsTable),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// takes a custom tabs config object and renders a documentation landing page
|
||||
/**
|
||||
* Component which takes a custom tabs config object and renders a documentation landing page.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsCustomHome = techdocsPlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: 'TechDocsCustomHome',
|
||||
@@ -122,6 +119,11 @@ export const TechDocsCustomHome = techdocsPlugin.provide(
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* Responsible for rendering the provided router element
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsIndexPage = techdocsPlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: 'TechDocsIndexPage',
|
||||
@@ -133,11 +135,18 @@ export const TechDocsIndexPage = techdocsPlugin.provide(
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* Component responsible for composing a TechDocs reader page experience
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsReaderPage = techdocsPlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: 'TechDocsReaderPage',
|
||||
component: () =>
|
||||
import('./reader/components/TechDocsPage').then(m => m.TechDocsPage),
|
||||
import('./reader/components/TechDocsReaderPage').then(
|
||||
m => m.TechDocsReaderPage,
|
||||
),
|
||||
mountPoint: rootDocsRouteRef,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -22,8 +22,11 @@ import { TechDocsNotFound } from './TechDocsNotFound';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import { Page, Content } from '@backstage/core-components';
|
||||
import { Reader } from './Reader';
|
||||
import { TechDocsPageHeader } from './TechDocsPageHeader';
|
||||
import { TechDocsReaderPageHeader } from './TechDocsReaderPageHeader';
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link TechDocsReaderPage} instead.
|
||||
*/
|
||||
export const LegacyTechDocsPage = () => {
|
||||
const [documentReady, setDocumentReady] = useState<boolean>(false);
|
||||
const { namespace, kind, name } = useParams();
|
||||
@@ -53,7 +56,7 @@ export const LegacyTechDocsPage = () => {
|
||||
|
||||
return (
|
||||
<Page themeId="documentation">
|
||||
<TechDocsPageHeader
|
||||
<TechDocsReaderPageHeader
|
||||
techDocsMetadata={techdocsMetadataValue}
|
||||
entityMetadata={entityMetadataValue}
|
||||
entityRef={{
|
||||
|
||||
@@ -58,11 +58,16 @@ import {
|
||||
copyToClipboard,
|
||||
} from '../transformers';
|
||||
|
||||
import { TechDocsSearch } from './TechDocsSearch';
|
||||
import { TechDocsSearch } from '../../search';
|
||||
import { TechDocsStateIndicator } from './TechDocsStateIndicator';
|
||||
import { useReaderState } from './useReaderState';
|
||||
|
||||
type Props = {
|
||||
/**
|
||||
* Props for {@link Reader}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type ReaderProps = {
|
||||
entityRef: EntityName;
|
||||
withSearch?: boolean;
|
||||
onReady?: () => void;
|
||||
@@ -840,7 +845,7 @@ const TheReader = ({
|
||||
entityRef,
|
||||
onReady = () => {},
|
||||
withSearch = true,
|
||||
}: Props) => {
|
||||
}: ReaderProps) => {
|
||||
const classes = useStyles();
|
||||
const dom = useTechDocsReaderDom(entityRef);
|
||||
const shadowDomRef = useRef<HTMLDivElement>(null);
|
||||
@@ -877,16 +882,20 @@ const TheReader = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const Reader = ({
|
||||
entityRef,
|
||||
onReady = () => {},
|
||||
withSearch = true,
|
||||
}: Props) => (
|
||||
<TechDocsReaderProvider entityRef={entityRef}>
|
||||
<TheReader
|
||||
entityRef={entityRef}
|
||||
onReady={onReady}
|
||||
withSearch={withSearch}
|
||||
/>
|
||||
</TechDocsReaderProvider>
|
||||
);
|
||||
/**
|
||||
* Component responsible for rendering TechDocs documentation
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Reader = (props: ReaderProps) => {
|
||||
const { entityRef, onReady = () => {}, withSearch = true } = props;
|
||||
return (
|
||||
<TechDocsReaderProvider entityRef={entityRef}>
|
||||
<TheReader
|
||||
entityRef={entityRef}
|
||||
onReady={onReady}
|
||||
withSearch={withSearch}
|
||||
/>
|
||||
</TechDocsReaderProvider>
|
||||
);
|
||||
};
|
||||
|
||||
+7
-7
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { TechDocsPage } from './TechDocsPage';
|
||||
import { TechDocsReaderPage } from './TechDocsReaderPage';
|
||||
import { render, act } from '@testing-library/react';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import {
|
||||
@@ -40,10 +40,10 @@ jest.mock('react-router-dom', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('./TechDocsPageHeader', () => {
|
||||
jest.mock('./TechDocsReaderPageHeader', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
TechDocsPageHeader: () => <div />,
|
||||
TechDocsReaderPageHeader: () => <div />,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -51,7 +51,7 @@ const { useParams }: { useParams: jest.Mock } =
|
||||
jest.requireMock('react-router-dom');
|
||||
global.scroll = jest.fn();
|
||||
|
||||
describe('<TechDocsPage />', () => {
|
||||
describe('<TechDocsReaderPage />', () => {
|
||||
it('should render techdocs page', async () => {
|
||||
useParams.mockReturnValue({
|
||||
entityRef: 'Component::backstage',
|
||||
@@ -101,7 +101,7 @@ describe('<TechDocsPage />', () => {
|
||||
const rendered = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apiRegistry}>
|
||||
<TechDocsPage />
|
||||
<TechDocsReaderPage />
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
@@ -158,7 +158,7 @@ describe('<TechDocsPage />', () => {
|
||||
const rendered = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apiRegistry}>
|
||||
<TechDocsPage>
|
||||
<TechDocsReaderPage>
|
||||
{({ techdocsMetadataValue }) => (
|
||||
<Header
|
||||
type="documentation"
|
||||
@@ -166,7 +166,7 @@ describe('<TechDocsPage />', () => {
|
||||
subtitle={techdocsMetadataValue?.site_name}
|
||||
/>
|
||||
)}
|
||||
</TechDocsPage>
|
||||
</TechDocsReaderPage>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
+28
-4
@@ -25,7 +25,12 @@ import { EntityName } from '@backstage/catalog-model';
|
||||
import { useApi, useApp } from '@backstage/core-plugin-api';
|
||||
import { Page } from '@backstage/core-components';
|
||||
|
||||
export type TechDocsPageRenderFunction = ({
|
||||
/**
|
||||
* Helper function that gives the children of {@link TechDocsReaderPage} acccess to techdocs and entity metadata
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsReaderPageRenderFunction = ({
|
||||
techdocsMetadataValue,
|
||||
entityMetadataValue,
|
||||
entityRef,
|
||||
@@ -36,11 +41,17 @@ export type TechDocsPageRenderFunction = ({
|
||||
onReady: () => void;
|
||||
}) => JSX.Element;
|
||||
|
||||
export type TechDocsPageProps = {
|
||||
children?: TechDocsPageRenderFunction | React.ReactNode;
|
||||
/**
|
||||
* Props for {@link TechDocsReaderPage}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsReaderPageProps = {
|
||||
children?: TechDocsReaderPageRenderFunction | React.ReactNode;
|
||||
};
|
||||
|
||||
export const TechDocsPage = ({ children }: TechDocsPageProps) => {
|
||||
export const TechDocsReaderPage = (props: TechDocsReaderPageProps) => {
|
||||
const { children } = props;
|
||||
const { NotFoundErrorPage } = useApp().getComponents();
|
||||
const outlet = useOutlet();
|
||||
|
||||
@@ -83,3 +94,16 @@ export const TechDocsPage = ({ children }: TechDocsPageProps) => {
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use {@link TechDocsReaderPage} instead
|
||||
*/
|
||||
export const TechDocsPage = TechDocsReaderPage;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use {@link TechDocsReaderPageRenderFunction} instead
|
||||
*/
|
||||
|
||||
export type TechDocsPageRenderFunction = TechDocsReaderPageRenderFunction;
|
||||
+5
-5
@@ -14,17 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { TechDocsPageHeader } from './TechDocsPageHeader';
|
||||
import { TechDocsReaderPageHeader } from './TechDocsReaderPageHeader';
|
||||
import { act } from '@testing-library/react';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { entityRouteRef } from '@backstage/plugin-catalog-react';
|
||||
import { rootRouteRef } from '../../routes';
|
||||
|
||||
describe('<TechDocsPageHeader />', () => {
|
||||
describe('<TechDocsReaderPageHeader />', () => {
|
||||
it('should render a techdocs page header', async () => {
|
||||
await act(async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<TechDocsPageHeader
|
||||
<TechDocsReaderPageHeader
|
||||
entityRef={{
|
||||
kind: 'test',
|
||||
name: 'test-name',
|
||||
@@ -66,7 +66,7 @@ describe('<TechDocsPageHeader />', () => {
|
||||
it('should render a techdocs page header even if metadata is missing', async () => {
|
||||
await act(async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<TechDocsPageHeader
|
||||
<TechDocsReaderPageHeader
|
||||
entityRef={{
|
||||
kind: 'test',
|
||||
name: 'test-name',
|
||||
@@ -88,7 +88,7 @@ describe('<TechDocsPageHeader />', () => {
|
||||
it('should render a link back to the component page', async () => {
|
||||
await act(async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<TechDocsPageHeader
|
||||
<TechDocsReaderPageHeader
|
||||
entityRef={{
|
||||
kind: 'test',
|
||||
name: 'test-name',
|
||||
+28
-7
@@ -29,18 +29,26 @@ import {
|
||||
import { rootRouteRef } from '../../routes';
|
||||
import { TechDocsEntityMetadata, TechDocsMetadata } from '../../types';
|
||||
|
||||
export type TechDocsPageHeaderProps = PropsWithChildren<{
|
||||
/**
|
||||
* Props for {@link TechDocsReaderPageHeader}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsReaderPageHeaderProps = PropsWithChildren<{
|
||||
entityRef: EntityName;
|
||||
entityMetadata?: TechDocsEntityMetadata;
|
||||
techDocsMetadata?: TechDocsMetadata;
|
||||
}>;
|
||||
|
||||
export const TechDocsPageHeader = ({
|
||||
entityRef,
|
||||
entityMetadata,
|
||||
techDocsMetadata,
|
||||
children,
|
||||
}: TechDocsPageHeaderProps) => {
|
||||
/**
|
||||
* Component responsible for rendering a Header with metadata on TechDocs reader page.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsReaderPageHeader = (
|
||||
props: TechDocsReaderPageHeaderProps,
|
||||
) => {
|
||||
const { entityRef, entityMetadata, techDocsMetadata, children } = props;
|
||||
const { name } = entityRef;
|
||||
|
||||
const { site_name: siteName, site_description: siteDescription } =
|
||||
@@ -114,3 +122,16 @@ export const TechDocsPageHeader = ({
|
||||
</Header>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use {@link TechDocsReaderPageHeader} instead
|
||||
*/
|
||||
export const TechDocsPageHeader = TechDocsReaderPageHeader;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use {@link TechDocsReaderPageHeader} instead
|
||||
*/
|
||||
|
||||
export type TechDocsPageHeaderProps = TechDocsReaderPageHeaderProps;
|
||||
@@ -15,8 +15,13 @@
|
||||
*/
|
||||
|
||||
export * from './Reader';
|
||||
export * from './TechDocsPage';
|
||||
export * from './TechDocsPageHeader';
|
||||
export type {
|
||||
TechDocsReaderPageProps,
|
||||
TechDocsPageRenderFunction,
|
||||
TechDocsReaderPageRenderFunction,
|
||||
} from './TechDocsReaderPage';
|
||||
export { TechDocsPage } from './TechDocsReaderPage';
|
||||
export * from './TechDocsReaderPageHeader';
|
||||
export * from './TechDocsStateIndicator';
|
||||
|
||||
/**
|
||||
@@ -31,4 +36,3 @@ export * from './TechDocsStateIndicator';
|
||||
* todo: Make public or stop exporting (ctrl+f "altReaderExperiments")
|
||||
* @internal
|
||||
*/
|
||||
export { TechDocsSearch } from './TechDocsSearch';
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ const singleResult = Promise.resolve({
|
||||
],
|
||||
});
|
||||
|
||||
describe('<TechDocsPage />', () => {
|
||||
describe('<TechDocsSearch />', () => {
|
||||
it('should render techdocs search bar', async () => {
|
||||
const query = () => emptyResults;
|
||||
const querySpy = jest.fn(query);
|
||||
+15
-7
@@ -28,7 +28,7 @@ import Autocomplete from '@material-ui/lab/Autocomplete';
|
||||
import React, { ChangeEvent, useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import useDebounce from 'react-use/lib/useDebounce';
|
||||
import { DocsResultListItem } from '../../components/DocsResultListItem';
|
||||
import { TechDocsSearchResultListItem } from './TechDocsSearchResultListItem';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
root: {
|
||||
@@ -36,7 +36,12 @@ const useStyles = makeStyles({
|
||||
},
|
||||
});
|
||||
|
||||
type TechDocsSearchProps = {
|
||||
/**
|
||||
* Props for {@link TechDocsSearch}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsSearchProps = {
|
||||
entityId: EntityName;
|
||||
debounceTime?: number;
|
||||
};
|
||||
@@ -55,10 +60,8 @@ type TechDocsSearchResult = {
|
||||
document: TechDocsDoc;
|
||||
};
|
||||
|
||||
const TechDocsSearchBar = ({
|
||||
entityId,
|
||||
debounceTime = 150,
|
||||
}: TechDocsSearchProps) => {
|
||||
const TechDocsSearchBar = (props: TechDocsSearchProps) => {
|
||||
const { entityId, debounceTime = 150 } = props;
|
||||
const [open, setOpen] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
@@ -138,7 +141,7 @@ const TechDocsSearchBar = ({
|
||||
value={null}
|
||||
options={options}
|
||||
renderOption={({ document }) => (
|
||||
<DocsResultListItem
|
||||
<TechDocsSearchResultListItem
|
||||
result={document}
|
||||
lineClamp={3}
|
||||
asListItem={false}
|
||||
@@ -180,6 +183,11 @@ const TechDocsSearchBar = ({
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Component used to render search bar on TechDocs page, scoped to
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsSearch = (props: TechDocsSearchProps) => {
|
||||
const initialState = {
|
||||
term: '',
|
||||
+10
-5
@@ -16,7 +16,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { DocsResultListItem } from './DocsResultListItem';
|
||||
import { TechDocsSearchResultListItem } from './TechDocsSearchResultListItem';
|
||||
|
||||
// Using canvas to render text..
|
||||
jest.mock('react-text-truncate', () => {
|
||||
@@ -44,9 +44,11 @@ const validResultWithTitle = {
|
||||
lifecycle: 'production',
|
||||
};
|
||||
|
||||
describe('DocsResultListItem test', () => {
|
||||
describe('TechDocsSearchResultListItem test', () => {
|
||||
it('should render search doc passed in', async () => {
|
||||
const { findByText } = render(<DocsResultListItem result={validResult} />);
|
||||
const { findByText } = render(
|
||||
<TechDocsSearchResultListItem result={validResult} />,
|
||||
);
|
||||
|
||||
expect(
|
||||
await findByText('Documentation | Backstage docs'),
|
||||
@@ -60,7 +62,10 @@ describe('DocsResultListItem test', () => {
|
||||
|
||||
it('should use title if defined', async () => {
|
||||
const { findByText } = render(
|
||||
<DocsResultListItem result={validResult} title="Count Dookumentation" />,
|
||||
<TechDocsSearchResultListItem
|
||||
result={validResult}
|
||||
title="Count Dookumentation"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(await findByText('Count Dookumentation')).toBeInTheDocument();
|
||||
@@ -73,7 +78,7 @@ describe('DocsResultListItem test', () => {
|
||||
|
||||
it('should use entity title if defined', async () => {
|
||||
const { findByText } = render(
|
||||
<DocsResultListItem result={validResultWithTitle} />,
|
||||
<TechDocsSearchResultListItem result={validResultWithTitle} />,
|
||||
);
|
||||
|
||||
expect(
|
||||
+29
-8
@@ -29,19 +29,34 @@ const useStyles = makeStyles({
|
||||
},
|
||||
});
|
||||
|
||||
export const DocsResultListItem = ({
|
||||
result,
|
||||
lineClamp = 5,
|
||||
asListItem = true,
|
||||
asLink = true,
|
||||
title,
|
||||
}: {
|
||||
/**
|
||||
* Props for {@link TechDocsSearchResultListItem}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TechDocsSearchResultListItemProps = {
|
||||
result: any;
|
||||
lineClamp?: number;
|
||||
asListItem?: boolean;
|
||||
asLink?: boolean;
|
||||
title?: string;
|
||||
}) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Component which renders documentation and related metadata.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TechDocsSearchResultListItem = (
|
||||
props: TechDocsSearchResultListItemProps,
|
||||
) => {
|
||||
const {
|
||||
result,
|
||||
lineClamp = 5,
|
||||
asListItem = true,
|
||||
asLink = true,
|
||||
title,
|
||||
} = props;
|
||||
const classes = useStyles();
|
||||
const TextItem = () => (
|
||||
<ListItemText
|
||||
@@ -86,3 +101,9 @@ export const DocsResultListItem = ({
|
||||
</LinkWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use {@link TechDocsSearchResultListItem} instead
|
||||
*/
|
||||
export const DocsResultListItem = TechDocsSearchResultListItem;
|
||||
+2
-1
@@ -14,4 +14,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { DocsResultListItem } from './DocsResultListItem';
|
||||
export * from './TechDocsSearchResultListItem';
|
||||
export * from './TechDocsSearch';
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
|
||||
export * from './components';
|
||||
@@ -16,11 +16,21 @@
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
/**
|
||||
* 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 };
|
||||
};
|
||||
|
||||
@@ -241,6 +241,7 @@ const NO_WARNING_PACKAGES = [
|
||||
'plugins/tech-insights-backend-module-jsonfc',
|
||||
'plugins/tech-insights-common',
|
||||
'plugins/tech-insights-node',
|
||||
'plugins/techdocs',
|
||||
'plugins/todo',
|
||||
'plugins/todo-backend',
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user