feat: allow to view the raw API definitions, even if a viewer component is available
This commit is contained in:
@@ -39,7 +39,7 @@ export const EntityPageApi: FC<{ entity: Entity }> = ({ entity }) => {
|
||||
<Grid container spacing={3}>
|
||||
{apiNames.map(api => (
|
||||
<Grid item xs={12} key={api}>
|
||||
<ApiDefinitionCard title={api} apiEntity={apiEntities!.get(api)} />
|
||||
<ApiDefinitionCard apiEntity={apiEntities!.get(api)} />
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
@@ -15,31 +15,92 @@
|
||||
*/
|
||||
|
||||
import { ApiEntity } from '@backstage/catalog-model';
|
||||
import { InfoCard } from '@backstage/core';
|
||||
import { TabbedCard, CardTab } from '@backstage/core';
|
||||
import React from 'react';
|
||||
import { ApiDefinitionWidget } from '../ApiDefinitionWidget';
|
||||
import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget';
|
||||
import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget';
|
||||
|
||||
type Props = {
|
||||
title?: string;
|
||||
apiEntity?: ApiEntity;
|
||||
type ApiDefinitionWidget = {
|
||||
type: string;
|
||||
title: string;
|
||||
component: (definition: string) => React.ReactElement;
|
||||
rawLanguage?: string;
|
||||
};
|
||||
|
||||
export const ApiDefinitionCard = ({ title, apiEntity }: Props) => {
|
||||
export function defaultDefinitionWidgets(): ApiDefinitionWidget[] {
|
||||
return [
|
||||
{
|
||||
type: 'openapi',
|
||||
title: 'OpenAPI',
|
||||
rawLanguage: 'yaml',
|
||||
component: definition => (
|
||||
<OpenApiDefinitionWidget definition={definition} />
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'asyncapi',
|
||||
title: 'AsyncAPI',
|
||||
rawLanguage: 'yaml',
|
||||
component: definition => (
|
||||
<AsyncApiDefinitionWidget definition={definition} />
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
type Props = {
|
||||
apiEntity?: ApiEntity;
|
||||
definitionWidgets?: ApiDefinitionWidget[];
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
definitionWidgets: defaultDefinitionWidgets(),
|
||||
};
|
||||
|
||||
export const ApiDefinitionCard = (props: Props) => {
|
||||
const { apiEntity, definitionWidgets } = {
|
||||
...defaultProps,
|
||||
...props,
|
||||
};
|
||||
|
||||
if (!apiEntity) {
|
||||
return <Alert severity="error">Could not fetch the API</Alert>;
|
||||
}
|
||||
|
||||
const definitionWidget = definitionWidgets.find(
|
||||
d => d.type === apiEntity.spec.type,
|
||||
);
|
||||
|
||||
if (definitionWidget) {
|
||||
return (
|
||||
<InfoCard title={title}>
|
||||
<Alert severity="error">Could not fetch the API</Alert>
|
||||
</InfoCard>
|
||||
<TabbedCard title={apiEntity.metadata.name}>
|
||||
<CardTab label={definitionWidget.title}>
|
||||
{definitionWidget.component(apiEntity.spec.definition)}
|
||||
</CardTab>
|
||||
<CardTab label="Raw">
|
||||
<PlainApiDefinitionWidget
|
||||
definition={apiEntity.spec.definition}
|
||||
language={definitionWidget.rawLanguage || apiEntity.spec.type}
|
||||
/>
|
||||
</CardTab>
|
||||
</TabbedCard>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<InfoCard title={title} subheader={apiEntity.spec.type}>
|
||||
<ApiDefinitionWidget
|
||||
type={apiEntity.spec.type}
|
||||
definition={apiEntity.spec.definition}
|
||||
/>
|
||||
</InfoCard>
|
||||
<TabbedCard
|
||||
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}>
|
||||
<PlainApiDefinitionWidget
|
||||
definition={apiEntity.spec.definition}
|
||||
language={apiEntity.spec.type}
|
||||
/>
|
||||
</CardTab>,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget';
|
||||
import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget';
|
||||
import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget';
|
||||
|
||||
type Props = {
|
||||
type: string;
|
||||
definition: string;
|
||||
};
|
||||
|
||||
export const ApiDefinitionWidget = ({ type, definition }: Props) => {
|
||||
switch (type) {
|
||||
case 'openapi':
|
||||
return <OpenApiDefinitionWidget definition={definition} />;
|
||||
|
||||
case 'asyncapi':
|
||||
return <AsyncApiDefinitionWidget definition={definition} />;
|
||||
|
||||
default:
|
||||
return (
|
||||
<PlainApiDefinitionWidget definition={definition} language={type} />
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { ApiDefinitionWidget } from './ApiDefinitionWidget';
|
||||
+1
-1
@@ -136,7 +136,7 @@ const useStyles = makeStyles(theme => ({
|
||||
}));
|
||||
|
||||
type Props = {
|
||||
definition: any;
|
||||
definition: string;
|
||||
};
|
||||
|
||||
export const AsyncApiDefinitionWidget = ({ definition }: Props) => {
|
||||
|
||||
@@ -66,7 +66,7 @@ const useStyles = makeStyles(theme => ({
|
||||
}));
|
||||
|
||||
type Props = {
|
||||
definition: any;
|
||||
definition: string;
|
||||
};
|
||||
|
||||
export const OpenApiDefinitionWidget = ({ definition }: Props) => {
|
||||
|
||||
+3
-1
@@ -23,5 +23,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const PlainApiDefinitionWidget = ({ definition, language }: Props) => {
|
||||
return <CodeSnippet text={definition} language={language} />;
|
||||
return (
|
||||
<CodeSnippet text={definition} language={language} showCopyCodeButton />
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,5 +15,8 @@
|
||||
*/
|
||||
|
||||
export { ApiDefinitionCard } from './ApiDefinitionCard';
|
||||
export { AsyncApiDefinitionWidget } from './AsyncApiDefinitionWidget';
|
||||
export { OpenApiDefinitionWidget } from './OpenApiDefinitionWidget';
|
||||
export { PlainApiDefinitionWidget } from './PlainApiDefinitionWidget';
|
||||
export { useComponentApiNames } from './useComponentApiNames';
|
||||
export { useComponentApiEntities } from './useComponentApiEntities';
|
||||
|
||||
Reference in New Issue
Block a user