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:
+3
-5
@@ -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;
|
||||
+2
-2
@@ -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();
|
||||
});
|
||||
});
|
||||
+20
-9
@@ -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 />;
|
||||
+1
-1
@@ -14,4 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { ApiCatalogTable } from './ApiCatalogTable';
|
||||
export { ApiExplorerPage } from './ApiExplorerPage';
|
||||
+3
-3
@@ -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}
|
||||
+31
-4
@@ -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>
|
||||
+1
-1
@@ -14,4 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { ApiCatalogPage } from './ApiCatalogPage';
|
||||
export { ApiExplorerTable } from './ApiExplorerTable';
|
||||
@@ -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);
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user