Merge pull request #2451 from andrewthauer/api-docs-definitions

Add apiDocsConfigRef to configure ApiDefinitionWidgets
This commit is contained in:
Andrew Thauer
2020-09-17 09:14:43 -04:00
committed by GitHub
7 changed files with 71 additions and 22 deletions
@@ -16,8 +16,8 @@
import { ComponentEntity, Entity } from '@backstage/catalog-model';
import { Progress } from '@backstage/core';
import React from 'react';
import { Grid } from '@material-ui/core';
import React from 'react';
import {
ApiDefinitionCard,
useComponentApiEntities,
@@ -15,15 +15,16 @@
*/
import { ApiEntity } from '@backstage/catalog-model';
import { CardTab, TabbedCard } from '@backstage/core';
import { CardTab, useApi, TabbedCard } from '@backstage/core';
import { Alert } from '@material-ui/lab';
import React from 'react';
import { apiDocsConfigRef } from '../../config';
import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget';
import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget';
import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget';
import { GraphQlDefinitionWidget } from '../GraphQlDefinitionWidget';
type ApiDefinitionWidget = {
export type ApiDefinitionWidget = {
type: string;
title: string;
component: (definition: string) => React.ReactElement;
@@ -61,34 +62,25 @@ export function defaultDefinitionWidgets(): ApiDefinitionWidget[] {
type Props = {
apiEntity?: ApiEntity;
definitionWidgets?: ApiDefinitionWidget[];
};
const defaultProps = {
definitionWidgets: defaultDefinitionWidgets(),
};
export const ApiDefinitionCard = (props: Props) => {
const { apiEntity, definitionWidgets } = {
...defaultProps,
...props,
};
export const ApiDefinitionCard = ({ apiEntity }: Props) => {
const config = useApi(apiDocsConfigRef);
const { getApiDefinitionWidget } = config;
if (!apiEntity) {
return <Alert severity="error">Could not fetch the API</Alert>;
}
const definitionWidget = definitionWidgets.find(
d => d.type === apiEntity.spec.type,
);
const definitionWidget = getApiDefinitionWidget(apiEntity);
if (definitionWidget) {
return (
<TabbedCard title={apiEntity.metadata.name}>
<CardTab label={definitionWidget.title}>
<CardTab label={definitionWidget.title} key="widget">
{definitionWidget.component(apiEntity.spec.definition)}
</CardTab>
<CardTab label="Raw">
<CardTab label="Raw" key="raw">
<PlainApiDefinitionWidget
definition={apiEntity.spec.definition}
language={definitionWidget.rawLanguage || apiEntity.spec.type}
@@ -103,7 +95,7 @@ export const ApiDefinitionCard = (props: Props) => {
title={apiEntity.metadata.name}
children={[
// Has to be an array, otherwise typescript doesn't like that this has only a single child
<CardTab label={apiEntity.spec.type}>
<CardTab label={apiEntity.spec.type} key="raw">
<PlainApiDefinitionWidget
definition={apiEntity.spec.definition}
language={apiEntity.spec.type}
@@ -14,4 +14,8 @@
* limitations under the License.
*/
export { ApiDefinitionCard } from './ApiDefinitionCard';
export type { ApiDefinitionWidget } from './ApiDefinitionCard';
export {
ApiDefinitionCard,
defaultDefinitionWidgets,
} from './ApiDefinitionCard';
+5 -1
View File
@@ -14,7 +14,11 @@
* limitations under the License.
*/
export { ApiDefinitionCard } from './ApiDefinitionCard';
export type { ApiDefinitionWidget } from './ApiDefinitionCard';
export {
ApiDefinitionCard,
defaultDefinitionWidgets,
} from './ApiDefinitionCard';
export { AsyncApiDefinitionWidget } from './AsyncApiDefinitionWidget';
export { OpenApiDefinitionWidget } from './OpenApiDefinitionWidget';
export { PlainApiDefinitionWidget } from './PlainApiDefinitionWidget';
+30
View File
@@ -0,0 +1,30 @@
/*
* Copyright 2020 Spotify AB
*
* 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 { ApiEntity } from '@backstage/catalog-model';
import { createApiRef } from '@backstage/core';
import { ApiDefinitionWidget } from './components';
export const apiDocsConfigRef = createApiRef<ApiDocsConfig>({
id: 'plugin.api-docs.config',
description: 'Used to configure api-docs widgets',
});
export interface ApiDocsConfig {
getApiDefinitionWidget: (
apiEntity: ApiEntity,
) => ApiDefinitionWidget | undefined;
}
+18 -1
View File
@@ -14,13 +14,30 @@
* limitations under the License.
*/
import { createPlugin } from '@backstage/core';
import { ApiEntity } from '@backstage/catalog-model';
import { createApiFactory, createPlugin } from '@backstage/core';
import { ApiExplorerPage } from './components/ApiExplorerPage/ApiExplorerPage';
import { defaultDefinitionWidgets } from './components/ApiDefinitionCard';
import { ApiEntityPage } from './components/ApiEntityPage/ApiEntityPage';
import { entityRoute, rootRoute } from './routes';
import { apiDocsConfigRef } from './config';
export const plugin = createPlugin({
id: 'api-docs',
apis: [
createApiFactory({
api: apiDocsConfigRef,
deps: {},
factory: () => {
const definitionWidgets = defaultDefinitionWidgets();
return {
getApiDefinitionWidget: (apiEntity: ApiEntity) => {
return definitionWidgets.find(d => d.type === apiEntity.spec.type);
},
};
},
}),
],
register({ router }) {
router.addRoute(rootRoute, ApiExplorerPage);
router.addRoute(entityRoute, ApiEntityPage);
+2
View File
@@ -23,11 +23,13 @@ export const rootRoute = createRouteRef({
path: '/api-docs',
title: 'APIs',
});
export const entityRoute = createRouteRef({
icon: NoIcon,
path: '/api-docs/:optionalNamespaceAndName/',
title: 'API',
});
export const catalogRoute = createRouteRef({
icon: NoIcon,
path: '',