Address further concerns
- Remove custom error - Remove enums - The API no longer checks validity of its input, the calling useAsync call does that Signed-off-by: Karan Shah <karan.shah@simplybusiness.co.uk>
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
|
||||
import { Groups } from './airbrakeGroups';
|
||||
import { createApiRef } from '@backstage/core-plugin-api';
|
||||
import { CustomErrorBase } from '@backstage/errors';
|
||||
|
||||
export const airbrakeApiRef = createApiRef<AirbrakeApi>({
|
||||
id: 'plugin.airbrake.service',
|
||||
@@ -25,9 +24,3 @@ export const airbrakeApiRef = createApiRef<AirbrakeApi>({
|
||||
export interface AirbrakeApi {
|
||||
fetchGroups(projectId: string): Promise<Groups>;
|
||||
}
|
||||
|
||||
export class NoProjectIdError extends CustomErrorBase {
|
||||
constructor() {
|
||||
super('Project ID is not present');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,13 @@
|
||||
*/
|
||||
|
||||
import { Groups } from './airbrakeGroups';
|
||||
import { AirbrakeApi, NoProjectIdError } from './AirbrakeApi';
|
||||
import { AirbrakeApi } from './AirbrakeApi';
|
||||
import { DiscoveryApi } from '@backstage/core-plugin-api';
|
||||
|
||||
export class ProductionAirbrakeApi implements AirbrakeApi {
|
||||
constructor(private readonly discoveryApi: DiscoveryApi) {}
|
||||
|
||||
async fetchGroups(projectId: string): Promise<Groups> {
|
||||
if (!projectId) {
|
||||
throw new NoProjectIdError();
|
||||
}
|
||||
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('airbrake');
|
||||
const apiUrl = `${baseUrl}/api/v4/projects/${projectId}/groups`;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { Groups } from '../airbrakeGroups';
|
||||
import { AirbrakeApi, NoProjectIdError } from '../AirbrakeApi';
|
||||
import { AirbrakeApi } from '../AirbrakeApi';
|
||||
import mockGroupsData from './airbrakeGroupsApiMock.json';
|
||||
|
||||
export class MockAirbrakeApi implements AirbrakeApi {
|
||||
@@ -25,10 +25,7 @@ export class MockAirbrakeApi implements AirbrakeApi {
|
||||
this.waitTimeInMillis = waitTimeInMillis;
|
||||
}
|
||||
|
||||
fetchGroups(projectId: string): Promise<Groups> {
|
||||
if (!projectId) {
|
||||
return Promise.reject(new NoProjectIdError());
|
||||
}
|
||||
fetchGroups(): Promise<Groups> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => resolve(mockGroupsData), this.waitTimeInMillis);
|
||||
});
|
||||
|
||||
@@ -37,70 +37,54 @@ const useStyles = makeStyles<BackstageTheme>(() => ({
|
||||
},
|
||||
}));
|
||||
|
||||
enum ComponentState {
|
||||
Loading,
|
||||
NoProjectId,
|
||||
Error,
|
||||
Loaded,
|
||||
}
|
||||
|
||||
export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => {
|
||||
const classes = useStyles();
|
||||
|
||||
const projectId = useProjectId(entity);
|
||||
const airbrakeApi = useApi(airbrakeApiRef);
|
||||
let componentState = ComponentState.Loading;
|
||||
|
||||
const { loading, value, error } = useAsync(() => {
|
||||
if (!projectId) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
return airbrakeApi.fetchGroups(projectId);
|
||||
}, [airbrakeApi, projectId]);
|
||||
|
||||
if (loading) {
|
||||
componentState = ComponentState.Loading;
|
||||
} else if (!projectId) {
|
||||
componentState = ComponentState.NoProjectId;
|
||||
} else if (error) {
|
||||
componentState = ComponentState.Error;
|
||||
if (!projectId) {
|
||||
return (
|
||||
<MissingAnnotationEmptyState
|
||||
annotation={AIRBRAKE_PROJECT_ID_ANNOTATION}
|
||||
/>
|
||||
);
|
||||
} else if (loading) {
|
||||
return <Progress />;
|
||||
} else if (value) {
|
||||
componentState = ComponentState.Loaded;
|
||||
return (
|
||||
<Grid container spacing={3} direction="column">
|
||||
{value.groups?.map(group => (
|
||||
<Grid item key={group.id}>
|
||||
{group.errors?.map(groupError => (
|
||||
<InfoCard title={groupError.type} key={hash(groupError)}>
|
||||
<Typography variant="body1" className={classes.multilineText}>
|
||||
{groupError.message}
|
||||
</Typography>
|
||||
</InfoCard>
|
||||
))}
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
switch (componentState) {
|
||||
case ComponentState.Loaded:
|
||||
return (
|
||||
<Grid container spacing={3} direction="column">
|
||||
{value?.groups?.map(group => (
|
||||
<Grid item key={group.id}>
|
||||
{group.errors?.map(groupError => (
|
||||
<InfoCard title={groupError.type} key={hash(groupError)}>
|
||||
<Typography variant="body1" className={classes.multilineText}>
|
||||
{groupError.message}
|
||||
</Typography>
|
||||
</InfoCard>
|
||||
))}
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
);
|
||||
case ComponentState.NoProjectId:
|
||||
return (
|
||||
<MissingAnnotationEmptyState
|
||||
annotation={AIRBRAKE_PROJECT_ID_ANNOTATION}
|
||||
/>
|
||||
);
|
||||
case ComponentState.Loading:
|
||||
return <Progress />;
|
||||
case ComponentState.Error:
|
||||
default:
|
||||
return (
|
||||
<>
|
||||
<ErrorPanel error={error as Error} />
|
||||
<EmptyState
|
||||
missing="info"
|
||||
title="No information to display"
|
||||
description={`There is no Airbrake project with id '${projectId}' or there was an issue communicating with Airbrake.`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{error && <ErrorPanel error={error} />}
|
||||
<EmptyState
|
||||
missing="info"
|
||||
title="No information to display"
|
||||
description={`There is no Airbrake project with id '${projectId}' or there was an issue communicating with Airbrake.`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user