feat(plugin): resolve remarks of review

Signed-off-by: MitchWijt <mitchel@wijt.net>
This commit is contained in:
MitchWijt
2023-01-31 16:15:44 +01:00
parent 3b5990bca1
commit d1fb4b7bf1
6 changed files with 75 additions and 99 deletions
+5 -5
View File
@@ -22,11 +22,11 @@ In order to be able to navigate to the graphQL voyager page, a new route needs t
```tsx
// packages/app/App.tsx
import { GraphQLVoyagerPage } from "@backstage/plugin-graphql-voyager";
import { GraphQLVoyagerPage } from '@backstage/plugin-graphql-voyager';
const routes = (
<FlatRoutes>
<Route path="/graphql-voyager" element={<GraphqlVoyagerPage/>}/>
<Route path="/graphql-voyager" element={<GraphqlVoyagerPage title="This is Voyager!"/>}/>
```
### Configuration
@@ -36,15 +36,15 @@ In order for the plugin to function correctly. GraphQL endpoints need to be adde
Add your own configuration to the `packages/app/src/apis.ts` file the following way:
```ts
import { identityApiRef } from './IdentityApi';
import { GraphQLVoyagerEndpoints } from './GraphQLVoyagerEndpoints';
import { identityApiRef } from '@backstage/core-plugin-api';
import { GraphQLVoyagerEndpoints } from '@backstage/plugin-graphql-voyager';
export const apis: AnyApiFactory[] = [
createApiFactory({
api: graphQlVoyagerApiRef,
deps: { identityApi: identityApiRef },
factory: ({ identityApiRef }) => {
GraphQLVoyagerEndpoints.from([
return GraphQLVoyagerEndpoints.from([
{
id: `graphql-voyager-endpoint-id`,
title: 'endpoint-title',
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/plugin-graphql-voyager",
"description": "Backstage plugin for GraphQL Voyager",
"version": "0.1.0",
"version": "0.0.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -26,7 +26,7 @@
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/theme": "workspace:^",
"@material-ui/core": "^4.9.13",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
"graphql-voyager": "^1.0.0-rc.31",
@@ -45,7 +45,7 @@
"@testing-library/user-event": "^14.0.0",
"@types/node": "*",
"cross-fetch": "^3.1.5",
"msw": "^0.47.0"
"msw": "^0.49.0"
},
"files": [
"dist"
@@ -17,100 +17,76 @@ import {
GraphQLVoyagerEndpoint,
introspectionQuery,
} from '../../lib/api/types';
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
import { Divider, makeStyles, Tab, Tabs, Typography } from '@material-ui/core';
import { useState } from 'react';
import { makeStyles, Tab, Tabs, Typography } from '@material-ui/core';
import React, { Suspense } from 'react';
import { BackstageTheme } from '@backstage/theme';
import { Content, Progress } from '@backstage/core-components';
import { Content, ErrorPanel, Progress } from '@backstage/core-components';
import { Voyager } from 'graphql-voyager';
import useAsync from 'react-use/lib/useAsync';
const useStyles = makeStyles<BackstageTheme>(theme => ({
const useStyles = makeStyles<BackstageTheme>(() => ({
root: {
height: '100%',
display: 'flex',
flexFlow: 'column nowrap',
},
tabs: {
background: theme.palette.background.paper,
},
}));
type GraphQLVoyagerBrowserProps = {
endpoints: GraphQLVoyagerEndpoint[];
};
type IntrospectionResult = {
data?: Object;
};
const NoEndpoints = () => {
return <Typography variant="h4">No endpoints available</Typography>;
};
const VoyagerBrowserContent = ({
endpoint,
}: {
endpoint: GraphQLVoyagerEndpoint;
}) => {
const { id, introspection, introspectionErrorMessage, voyagerProps } =
endpoint;
const { value, loading, error } = useAsync(
() => introspection(introspectionQuery),
[endpoint],
);
if (loading) {
return <Progress />;
} else if (error) {
return <ErrorPanel error={error} />;
}
return value.data ? (
<Voyager key={id} introspection={value} {...voyagerProps} />
) : (
<Typography variant="h4" color="error">
{introspectionErrorMessage}
</Typography>
);
};
const VoyagerBrowser = (props: GraphQLVoyagerBrowserProps) => {
const { endpoints } = props;
const [tabIndex, setTabIndex] = useState(0);
const [isLoading, setIsLoading] = useState(true);
const [introspectionResult, setIntrospectionResult]: [
IntrospectionResult,
Dispatch<SetStateAction<IntrospectionResult>>,
] = useState({});
const classes = useStyles();
const {
voyagerProps = {},
introspectionErrorMessage,
introspection,
} = endpoints[tabIndex];
useEffect(() => {
const fetchIntrospection = async () => {
setIsLoading(true);
const data = await introspection(introspectionQuery);
setIntrospectionResult(data);
setIsLoading(false);
};
fetchIntrospection();
}, [tabIndex, introspection]);
let voyagerContent: JSX.Element;
if (isLoading) {
voyagerContent = <Typography variant="body1">Loading...</Typography>;
} else if (!introspectionResult.data) {
voyagerContent = (
<Typography variant="h4" color="error">
{introspectionErrorMessage}
</Typography>
);
} else {
voyagerContent = (
<Voyager
key={tabIndex}
introspection={introspectionResult}
{...voyagerProps}
/>
);
}
return (
<div className={classes.root}>
<Suspense fallback={<Progress />}>
<Tabs
classes={{ root: classes.tabs }}
value={tabIndex}
onChange={(_, value) => setTabIndex(value)}
indicatorColor="primary"
>
{endpoints.map(({ title }, index) => (
<Tab key={index} label={title} value={index} />
{endpoints.map(({ title, id }, index) => (
<Tab key={id} label={title} value={index} />
))}
</Tabs>
<Divider />
<Content>{voyagerContent}</Content>
<Content>
<VoyagerBrowserContent endpoint={endpoints[tabIndex]} />
</Content>
</Suspense>
</div>
);
@@ -38,11 +38,7 @@ describe('GraphQLVoyagerPage', () => {
);
expect(rendered.getByText('Welcome to Voyager!')).toBeInTheDocument();
expect(
rendered.getByText(
'Failed to load GraphQL endpoints, Error: No endpoints',
),
).toBeInTheDocument();
expect(rendered.getByText('Error: No endpoints')).toBeInTheDocument();
});
it('should show GraphQLVoyagerBrowser', async () => {
@@ -14,49 +14,48 @@
* limitations under the License.
*/
import React from 'react';
import { Header, Page, Content, Progress } from '@backstage/core-components';
import {
Header,
Page,
Content,
Progress,
ErrorPanel,
} from '@backstage/core-components';
import { useApi } from '@backstage/core-plugin-api';
import 'graphql-voyager/dist/voyager.css';
import { graphQlVoyagerApiRef } from '../../lib/api';
import useAsync from 'react-use/lib/useAsync';
import { Typography } from '@material-ui/core';
import { GraphQLVoyagerBrowser } from '../GraphQLVoyagerBrowser';
/** @public */
export const GraphQLVoyagerPage = () => {
type GraphQLVoyagerPageProps = {
title?: string;
};
const VoyagerContent = () => {
const graphQLVoyagerApi = useApi(graphQlVoyagerApiRef);
const { value, loading, error } = useAsync(() =>
graphQLVoyagerApi.getEndpoints(),
);
let content: JSX.Element;
if (loading) {
content = (
<Content>
<Progress />
</Content>
);
return <Progress />;
} else if (error) {
content = (
<Content>
<Typography variant="h4" color="error">
Failed to load GraphQL endpoints, {String(error)}
</Typography>
</Content>
);
} else {
content = (
<Content noPadding>
<GraphQLVoyagerBrowser endpoints={value!} />
</Content>
);
return <ErrorPanel error={error} />;
}
return <GraphQLVoyagerBrowser endpoints={value!} />;
};
/** @public */
export const GraphQLVoyagerPage = (props: GraphQLVoyagerPageProps) => {
const { title = 'Welcome to Voyager!' } = props;
return (
<Page themeId="tool">
<Header title="Welcome to Voyager!" />
{content}
<Header title={title} />
<Content>
<VoyagerContent />
</Content>
</Page>
);
};