Connect the API code to the components

Signed-off-by: Karan Shah <karan.shah@simplybusiness.co.uk>
This commit is contained in:
Karan Shah
2022-01-10 11:49:23 +00:00
parent b1afac9d09
commit f3d7baaefa
5 changed files with 87 additions and 99 deletions
+1
View File
@@ -20,6 +20,7 @@
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/catalog-model": "^0.9.7",
"@backstage/core-components": "^0.8.3",
"@backstage/core-plugin-api": "^0.4.1",
"@backstage/theme": "^0.2.14",
+6 -6
View File
@@ -29,12 +29,12 @@ export interface Group {
resolved: boolean;
muted: boolean;
mutedBy: number;
mutedAt?: null;
errors?: Error[] | null;
attributes?: null;
mutedAt?: string | null;
errors?: Error[];
attributes?: string | null;
context: Context;
lastDeployId: string;
lastDeployAt?: null;
lastDeployAt?: string | null;
lastNoticeId: string;
lastNoticeAt: string;
noticeCount: number;
@@ -46,7 +46,7 @@ export interface Group {
export interface Error {
type: string;
message: string;
backtrace?: Backtrace[] | null;
backtrace?: Backtrace[];
}
export interface Backtrace {
@@ -54,7 +54,7 @@ export interface Backtrace {
function: string;
line: number;
column: number;
code?: null;
code?: string | null;
}
export interface Context {
@@ -13,13 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { Entity } from '@backstage/catalog-model';
import React, { useEffect } from 'react';
import { Grid, Typography } from '@material-ui/core';
import { InfoCard } from '@backstage/core-components';
import exampleData from './example-data.json';
import {
EmptyState,
InfoCard,
MissingAnnotationEmptyState,
Progress,
} from '@backstage/core-components';
import hash from 'object-hash';
import { makeStyles } from '@material-ui/core/styles';
import { BackstageTheme } from '@backstage/theme';
import { ErrorApi, errorApiRef, useApi } from '@backstage/core-plugin-api';
import { airbrakeApiRef } from '../../api';
import useAsync from 'react-use/lib/useAsync';
import {
AIRBRAKE_PROJECT_SLUG_ANNOTATION,
useProjectSlug,
} from '../useProjectSlug';
const useStyles = makeStyles<BackstageTheme>(() => ({
multilineText: {
@@ -27,17 +39,54 @@ const useStyles = makeStyles<BackstageTheme>(() => ({
},
}));
export const EntityAirbrakeContent = () => {
export const EntityAirbrakeContent = ({ entity }: { entity: Entity }) => {
const classes = useStyles();
const projectId = useProjectSlug(entity);
const errorApi = useApi<ErrorApi>(errorApiRef);
const airbrakeApi = useApi(airbrakeApiRef);
const { loading, value, error } = useAsync(
() => airbrakeApi.fetchGroups(projectId),
[projectId],
);
useEffect(() => {
if (error) {
errorApi.post(error);
}
}, [error, errorApi]);
if (loading || !projectId || error) {
return (
<InfoCard title="Airbrake groups" variant="gridItem">
{loading && <Progress />}
{!loading && !projectId && (
<MissingAnnotationEmptyState
annotation={AIRBRAKE_PROJECT_SLUG_ANNOTATION}
/>
)}
{!loading && error && (
<EmptyState
missing="info"
title="No information to display"
description={`There is no Sentry project with id '${projectId}'.`}
/>
)}
</InfoCard>
);
}
return (
<Grid container spacing={3} direction="column">
{exampleData.groups.map(group => (
{value?.groups?.map(group => (
<Grid item key={group.id}>
{group.errors.map(error => (
<InfoCard title={error.type} key={hash(error)}>
{group.errors?.map(groupError => (
<InfoCard title={groupError.type} key={hash(groupError)}>
<Typography variant="body1" className={classes.multilineText}>
{error.message}
{groupError.message}
</Typography>
</InfoCard>
))}
@@ -1,85 +0,0 @@
{
"count": 2,
"end": "",
"groups": [
{
"id": "1",
"projectId": 123,
"resolved": false,
"muted": false,
"mutedBy": 0,
"mutedAt": null,
"errors": [
{
"type": "Error",
"message": "useSearch must be used within a SearchContextProvider",
"backtrace": [
{
"file": "webpack-internal:///../../node_modules/@backstage/plugin-search/dist/esm/index-893ec2f5.esm.js",
"function": "useSearch",
"line": 303,
"column": 11,
"code": null
}
]
}
],
"attributes": null,
"context": {
"action": "",
"component": "",
"environment": "local",
"severity": "error"
},
"lastDeployId": "0",
"lastDeployAt": null,
"lastNoticeId": "234",
"lastNoticeAt": "2021-12-19T09:59:00.124Z",
"noticeCount": 5,
"noticeTotalCount": 5,
"commentCount": 0,
"createdAt": "2021-12-19T09:44:30.067447Z"
},
{
"id": "2",
"projectId": 123,
"resolved": true,
"muted": false,
"mutedBy": 0,
"mutedAt": null,
"errors": [
{
"type": "ChunkLoadError",
"message": "Loading chunk 7764 failed.",
"backtrace": [
{
"file": "/PROJECT_ROOT/static/runtime.069c874d.js",
"function": "Object._.f.j",
"line": 1,
"column": 19465,
"code": null
}
]
}
],
"attributes": null,
"context": {
"action": "",
"component": "",
"environment": "local",
"severity": "error"
},
"lastDeployId": "0",
"lastDeployAt": null,
"lastNoticeId": "345",
"lastNoticeAt": "2021-12-15T17:16:38.419Z",
"noticeCount": 1,
"noticeTotalCount": 1,
"commentCount": 0,
"createdAt": "2021-12-15T17:16:38.41983Z"
}
],
"page": 1,
"resolvedCount": 1,
"unresolvedCount": 1
}
@@ -0,0 +1,23 @@
/*
* Copyright 2020 The Backstage Authors
*
* 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 { Entity } from '@backstage/catalog-model';
export const AIRBRAKE_PROJECT_SLUG_ANNOTATION = 'airbrake.io/project-slug';
export const useProjectSlug = (entity: Entity) => {
return entity?.metadata.annotations?.[AIRBRAKE_PROJECT_SLUG_ANNOTATION] ?? '';
};