feat(plugin): resolve remarks of review
Signed-off-by: MitchWijt <mitchel@wijt.net>
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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"
|
||||
|
||||
+36
-60
@@ -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>
|
||||
);
|
||||
|
||||
+1
-5
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user