feat: rework Api Explorer components

The table in the API explorer now shows details such as tags, owner, and description.
This commit is contained in:
Oliver Sand
2020-09-17 11:18:21 +02:00
parent ed140a0602
commit bcf0f4cc11
8 changed files with 63 additions and 27 deletions
@@ -21,17 +21,15 @@ type Props = {
children?: React.ReactNode;
};
const ApiCatalogLayout = ({ children }: Props) => {
export const ApiExplorerLayout = ({ children }: Props) => {
return (
<Page theme={pageTheme.home}>
<Header
title="APIs"
subtitle="Backstage API Catalog"
pageTitleOverride="Home"
subtitle="Backstage API Explorer"
pageTitleOverride="APIs"
/>
{children}
</Page>
);
};
export default ApiCatalogLayout;
@@ -20,7 +20,7 @@ import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog';
import { MockStorageApi, wrapInTestApp } from '@backstage/test-utils';
import { render } from '@testing-library/react';
import React from 'react';
import { ApiCatalogPage } from './ApiCatalogPage';
import { ApiExplorerPage } from './ApiExplorerPage';
describe('ApiCatalogPage', () => {
const catalogApi: Partial<CatalogApi> = {
@@ -63,7 +63,7 @@ describe('ApiCatalogPage', () => {
// related to some theme issues in mui-table
// https://github.com/mbrn/material-table/issues/1293
it('should render', async () => {
const { findByText } = renderWrapped(<ApiCatalogPage />);
const { findByText } = renderWrapped(<ApiExplorerPage />);
expect(await findByText(/APIs \(2\)/)).toBeInTheDocument();
});
});
@@ -14,31 +14,42 @@
* limitations under the License.
*/
import { Content, useApi } from '@backstage/core';
import { Content, ContentHeader, SupportButton, useApi } from '@backstage/core';
import { catalogApiRef } from '@backstage/plugin-catalog';
import { Button } from '@material-ui/core';
import React from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { useAsync } from 'react-use';
import { ApiCatalogTable } from '../ApiCatalogTable';
import ApiCatalogLayout from './ApiCatalogLayout';
import { ApiExplorerTable } from '../ApiExplorerTable';
import { ApiExplorerLayout } from './ApiExplorerLayout';
const CatalogPageContents = () => {
export const ApiExplorerPage = () => {
const catalogApi = useApi(catalogApiRef);
const { loading, error, value: matchingEntities } = useAsync(() => {
return catalogApi.getEntities({ kind: 'API' });
}, [catalogApi]);
return (
<ApiCatalogLayout>
<ApiExplorerLayout>
<Content>
<ApiCatalogTable
<ContentHeader title="">
<Button
variant="contained"
color="primary"
component={RouterLink}
to="/register-component"
>
Register Existing API
</Button>
<SupportButton>All your APIs</SupportButton>
</ContentHeader>
<ApiExplorerTable
titlePreamble="APIs"
entities={matchingEntities!}
loading={loading}
error={error}
/>
</Content>
</ApiCatalogLayout>
</ApiExplorerLayout>
);
};
export const ApiCatalogPage = () => <CatalogPageContents />;
@@ -14,4 +14,4 @@
* limitations under the License.
*/
export { ApiCatalogTable } from './ApiCatalogTable';
export { ApiExplorerPage } from './ApiExplorerPage';
@@ -18,7 +18,7 @@ import { Entity } from '@backstage/catalog-model';
import { wrapInTestApp } from '@backstage/test-utils';
import { render } from '@testing-library/react';
import * as React from 'react';
import { ApiCatalogTable } from './ApiCatalogTable';
import { ApiExplorerTable } from './ApiExplorerTable';
const entites: Entity[] = [
{
@@ -42,7 +42,7 @@ describe('ApiCatalogTable component', () => {
it('should render error message when error is passed in props', async () => {
const rendered = render(
wrapInTestApp(
<ApiCatalogTable
<ApiExplorerTable
titlePreamble="APIs"
entities={[]}
loading={false}
@@ -59,7 +59,7 @@ describe('ApiCatalogTable component', () => {
it('should display entity names when loading has finished and no error occurred', async () => {
const rendered = render(
wrapInTestApp(
<ApiCatalogTable
<ApiExplorerTable
titlePreamble="APIs"
entities={entites}
loading={false}
@@ -16,7 +16,7 @@
import { Entity } from '@backstage/catalog-model';
import { Table, TableColumn } from '@backstage/core';
import { Link } from '@material-ui/core';
import { Link, Chip } from '@material-ui/core';
import { Alert } from '@material-ui/lab';
import React from 'react';
import { generatePath, Link as RouterLink } from 'react-router-dom';
@@ -45,25 +45,52 @@ const columns: TableColumn<Entity>[] = [
</Link>
),
},
{
title: 'Owner',
field: 'spec.owner',
},
{
title: 'Lifecycle',
field: 'spec.lifecycle',
},
{
title: 'Type', // TODO: Resolve the type display name using the API from https://github.com/spotify/backstage/pull/2451
field: 'spec.type',
},
{
title: 'Description',
field: 'metadata.description',
},
{
title: 'Tags',
field: 'metadata.tags',
cellStyle: {
padding: '0px 16px 0px 20px',
},
render: (entity: Entity) => (
<>
{entity.metadata.tags &&
entity.metadata.tags.map(t => (
<Chip key={t} label={t} style={{ marginBottom: '0px' }} />
))}
</>
),
},
];
type CatalogTableProps = {
type ExplorerTableProps = {
entities: Entity[];
titlePreamble: string;
loading: boolean;
error?: any;
};
export const ApiCatalogTable = ({
export const ApiExplorerTable = ({
entities,
loading,
error,
titlePreamble,
}: CatalogTableProps) => {
}: ExplorerTableProps) => {
if (error) {
return (
<div>
@@ -14,4 +14,4 @@
* limitations under the License.
*/
export { ApiCatalogPage } from './ApiCatalogPage';
export { ApiExplorerTable } from './ApiExplorerTable';
+2 -2
View File
@@ -15,14 +15,14 @@
*/
import { createPlugin } from '@backstage/core';
import { ApiCatalogPage } from './components/ApiCatalogPage/ApiCatalogPage';
import { ApiExplorerPage } from './components/ApiExplorerPage/ApiExplorerPage';
import { ApiEntityPage } from './components/ApiEntityPage/ApiEntityPage';
import { entityRoute, rootRoute } from './routes';
export const plugin = createPlugin({
id: 'api-docs',
register({ router }) {
router.addRoute(rootRoute, ApiCatalogPage);
router.addRoute(rootRoute, ApiExplorerPage);
router.addRoute(entityRoute, ApiEntityPage);
},
});