Connect the API code to the components
Signed-off-by: Karan Shah <karan.shah@simplybusiness.co.uk>
This commit is contained in:
@@ -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
@@ -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] ?? '';
|
||||
};
|
||||
Reference in New Issue
Block a user