From f3d7baaefa248681c8db3e0829f95cf02af40934 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Mon, 10 Jan 2022 11:49:23 +0000 Subject: [PATCH] Connect the API code to the components Signed-off-by: Karan Shah --- plugins/airbrake/package.json | 1 + plugins/airbrake/src/api/airbrake-groups.d.ts | 12 +-- .../EntityAirbrakeContent.tsx | 65 ++++++++++++-- .../EntityAirbrakeContent/example-data.json | 85 ------------------- .../airbrake/src/components/useProjectSlug.ts | 23 +++++ 5 files changed, 87 insertions(+), 99 deletions(-) delete mode 100644 plugins/airbrake/src/components/EntityAirbrakeContent/example-data.json create mode 100644 plugins/airbrake/src/components/useProjectSlug.ts diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 7294c97413..7f96f0bc61 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -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", diff --git a/plugins/airbrake/src/api/airbrake-groups.d.ts b/plugins/airbrake/src/api/airbrake-groups.d.ts index df4c5de120..e1887eca9b 100644 --- a/plugins/airbrake/src/api/airbrake-groups.d.ts +++ b/plugins/airbrake/src/api/airbrake-groups.d.ts @@ -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 { diff --git a/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.tsx b/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.tsx index 062d9e898a..2bd3917443 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.tsx @@ -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(() => ({ multilineText: { @@ -27,17 +39,54 @@ const useStyles = makeStyles(() => ({ }, })); -export const EntityAirbrakeContent = () => { +export const EntityAirbrakeContent = ({ entity }: { entity: Entity }) => { const classes = useStyles(); + const projectId = useProjectSlug(entity); + const errorApi = useApi(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 ( + + {loading && } + + {!loading && !projectId && ( + + )} + + {!loading && error && ( + + )} + + ); + } + return ( - {exampleData.groups.map(group => ( + {value?.groups?.map(group => ( - {group.errors.map(error => ( - + {group.errors?.map(groupError => ( + - {error.message} + {groupError.message} ))} diff --git a/plugins/airbrake/src/components/EntityAirbrakeContent/example-data.json b/plugins/airbrake/src/components/EntityAirbrakeContent/example-data.json deleted file mode 100644 index fa654ec50b..0000000000 --- a/plugins/airbrake/src/components/EntityAirbrakeContent/example-data.json +++ /dev/null @@ -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 -} diff --git a/plugins/airbrake/src/components/useProjectSlug.ts b/plugins/airbrake/src/components/useProjectSlug.ts new file mode 100644 index 0000000000..4c6337b49e --- /dev/null +++ b/plugins/airbrake/src/components/useProjectSlug.ts @@ -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] ?? ''; +};