feat: add rollbar links

This commit is contained in:
Andrew Thauer
2020-08-12 07:10:44 -04:00
parent 2577c730e7
commit aedcad72a5
15 changed files with 207 additions and 38 deletions
@@ -17,6 +17,7 @@
import React, { ReactNode } from 'react';
import {
Header,
HeaderLabel,
Page,
pageTheme,
Content,
@@ -36,7 +37,10 @@ export const RollbarLayout = ({ title = 'Dashboard', children }: Props) => {
<Header
title="Rollbar"
subtitle="Real-time error tracking & debugging tools for developers"
/>
>
<HeaderLabel label="Owner" value="Spotify" />
<HeaderLabel label="Lifecycle" value="Alpha" />
</Header>
<Content>
<ContentHeader title={title}>
<SupportButton>
@@ -15,7 +15,12 @@
*/
import * as React from 'react';
import { ApiProvider, ApiRegistry } from '@backstage/core';
import {
ApiProvider,
ApiRegistry,
ConfigApi,
configApiRef,
} from '@backstage/core';
import { wrapInTestApp } from '@backstage/test-utils';
import { render } from '@testing-library/react';
import { RollbarApi, rollbarApiRef } from '../../api/RollbarApi';
@@ -30,11 +35,20 @@ describe('RollbarPage component', () => {
const rollbarApi: Partial<RollbarApi> = {
getAllProjects: () => Promise.resolve(projects),
};
const config: Partial<ConfigApi> = {
getString: () => 'foo',
getOptionalString: () => 'foo',
};
const renderWrapped = (children: React.ReactNode) =>
render(
wrapInTestApp(
<ApiProvider apis={ApiRegistry.from([[rollbarApiRef, rollbarApi]])}>
<ApiProvider
apis={ApiRegistry.from([
[rollbarApiRef, rollbarApi],
[configApiRef, config],
])}
>
{children}
</ApiProvider>,
),
@@ -16,18 +16,27 @@
import React from 'react';
import { useAsync } from 'react-use';
import { useApi } from '@backstage/core';
import { configApiRef, useApi } from '@backstage/core';
import { rollbarApiRef } from '../../api/RollbarApi';
import { RollbarLayout } from '../RollbarLayout/RollbarLayout';
import { RollbarProjectTable } from './RollbarProjectTable';
export const RollbarPage = () => {
const configApi = useApi(configApiRef);
const rollbarApi = useApi(rollbarApiRef);
const { value, loading } = useAsync(() => rollbarApi.getAllProjects());
const org =
configApi.getOptionalString('rollbar.organization') ??
configApi.getString('organization.name');
const { value, loading, error } = useAsync(() => rollbarApi.getAllProjects());
return (
<RollbarLayout>
<RollbarProjectTable loading={loading} projects={value || []} />
<RollbarProjectTable
projects={value || []}
organization={org}
loading={loading}
error={error}
/>
</RollbarLayout>
);
};
@@ -17,9 +17,14 @@
import React from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { Link } from '@material-ui/core';
import { Alert } from '@material-ui/lab';
import OpenInNewIcon from '@material-ui/icons/OpenInNew';
import { Table, TableColumn } from '@backstage/core';
import { RollbarProject } from '../../api/types';
const projectUrl = (org: string, id: number) =>
`https://rollbar.com/${org}/all/items/?projects=${id}`;
const columns: TableColumn[] = [
{
title: 'ID',
@@ -32,7 +37,6 @@ const columns: TableColumn[] = [
title: 'Name',
field: 'name',
type: 'string',
align: 'left',
highlight: true,
render: (row: Partial<RollbarProject>) => (
<Link component={RouterLink} to={`/rollbar/${row.name}`}>
@@ -44,29 +48,58 @@ const columns: TableColumn[] = [
title: 'Status',
field: 'status',
type: 'string',
align: 'left',
},
{
title: 'Open',
width: '10%',
render: (row: any) => (
<Link
href={projectUrl(row.organization, row.id)}
target="_blank"
rel="noreferrer"
>
<OpenInNewIcon />
</Link>
),
},
];
type Props = {
projects: RollbarProject[];
loading: boolean;
organization: string;
error?: any;
};
export const RollbarProjectTable = ({ projects, loading }: Props) => {
export const RollbarProjectTable = ({
projects,
organization,
loading,
error,
}: Props) => {
if (error) {
return (
<div>
<Alert severity="error">
Error encountered while fetching rollbar projects. {error.toString()}
</Alert>
</div>
);
}
return (
<Table
isLoading={loading}
columns={columns}
options={{
padding: 'dense',
paging: true,
search: true,
paging: true,
pageSize: 10,
showEmptyDataSourceMessage: !loading,
}}
title="Projects"
data={projects}
data={projects.map(p => ({ organization, ...p }))}
/>
);
};
@@ -15,7 +15,12 @@
*/
import * as React from 'react';
import { ApiProvider, ApiRegistry } from '@backstage/core';
import {
ApiProvider,
ApiRegistry,
ConfigApi,
configApiRef,
} from '@backstage/core';
import { wrapInTestApp } from '@backstage/test-utils';
import { render } from '@testing-library/react';
import { RollbarApi, rollbarApiRef } from '../../api/RollbarApi';
@@ -43,11 +48,20 @@ describe('RollbarProjectPage component', () => {
const rollbarApi: Partial<RollbarApi> = {
getTopActiveItems: () => Promise.resolve(items),
};
const config: Partial<ConfigApi> = {
getString: () => 'foo',
getOptionalString: () => 'foo',
};
const renderWrapped = (children: React.ReactNode) =>
render(
wrapInTestApp(
<ApiProvider apis={ApiRegistry.from([[rollbarApiRef, rollbarApi]])}>
<ApiProvider
apis={ApiRegistry.from([
[rollbarApiRef, rollbarApi],
[configApiRef, config],
])}
>
{children}
</ApiProvider>,
),
@@ -17,17 +17,21 @@
import React from 'react';
import { useParams } from 'react-router-dom';
import { useAsync } from 'react-use';
import { useApi } from '@backstage/core';
import { configApiRef, useApi } from '@backstage/core';
import { rollbarApiRef } from '../../api/RollbarApi';
import { RollbarLayout } from '../RollbarLayout/RollbarLayout';
import { RollbarTopItemsTable } from '../RollbarTopItemsTable/RollbarTopItemsTable';
export const RollbarProjectPage = () => {
const configApi = useApi(configApiRef);
const rollbarApi = useApi(rollbarApiRef);
const org =
configApi.getOptionalString('rollbar.organization') ??
configApi.getString('organization.name');
const { componentId } = useParams() as {
componentId: string;
};
const { value, loading } = useAsync(() =>
const { value, loading, error } = useAsync(() =>
rollbarApi
.getTopActiveItems(componentId, 168)
.then(data =>
@@ -37,7 +41,13 @@ export const RollbarProjectPage = () => {
return (
<RollbarLayout>
<RollbarTopItemsTable loading={loading} items={value || []} />
<RollbarTopItemsTable
items={value || []}
organization={org}
project={componentId}
loading={loading}
error={error}
/>
</RollbarLayout>
);
};
@@ -41,14 +41,28 @@ const items: RollbarTopActiveItem[] = [
describe('RollbarTopItemsTable component', () => {
it('should render empty data message when loaded and no data', async () => {
const rendered = render(
wrapInTestApp(<RollbarTopItemsTable items={[]} loading={false} />),
wrapInTestApp(
<RollbarTopItemsTable
items={[]}
organization="foo"
project="bar"
loading={false}
/>,
),
);
expect(rendered.getByText(/No records to display/)).toBeInTheDocument();
});
it('should display item attributes when loading has finished', async () => {
const rendered = render(
wrapInTestApp(<RollbarTopItemsTable items={items} loading={false} />),
wrapInTestApp(
<RollbarTopItemsTable
items={items}
organization="foo"
project="bar"
loading={false}
/>,
),
);
expect(rendered.getByText(/1234/)).toBeInTheDocument();
expect(rendered.getByText(/Error in foo/)).toBeInTheDocument();
@@ -16,6 +16,8 @@
import React from 'react';
import { Table, TableColumn } from '@backstage/core';
import { Link } from '@material-ui/core';
import { Alert } from '@material-ui/lab';
import {
RollbarFrameworkId,
RollbarLevel,
@@ -23,6 +25,9 @@ import {
} from '../../api/types';
import { RollbarTrendGraph } from '../RollbarTrendGraph/RollbarTrendGraph';
const itemUrl = (org: string, project: string, id: number) =>
`https://rollbar.com/${org}/${project}/items/${id}`;
const columns: TableColumn[] = [
{
title: 'ID',
@@ -30,6 +35,15 @@ const columns: TableColumn[] = [
type: 'string',
align: 'left',
width: '70px',
render: (data: any) => (
<Link
href={itemUrl(data.org, data.project, data.item.counter)}
target="_blank"
rel="noreferrer"
>
{data.item.counter}
</Link>
),
},
{
title: 'Title',
@@ -40,9 +54,7 @@ const columns: TableColumn[] = [
{
title: 'Trend',
sorting: false,
render: data => (
<RollbarTrendGraph counts={(data as RollbarTopActiveItem).counts} />
),
render: (data: any) => <RollbarTrendGraph counts={data.counts} />,
},
{
title: 'Occurrences',
@@ -81,22 +93,42 @@ const columns: TableColumn[] = [
type Props = {
items: RollbarTopActiveItem[];
organization: string;
project: string;
loading: boolean;
error?: any;
};
export const RollbarTopItemsTable = ({ items, loading }: Props) => {
export const RollbarTopItemsTable = ({
items,
organization,
project,
loading,
error,
}: Props) => {
if (error) {
return (
<div>
<Alert severity="error">
Error encountered while fetching rollbar top items. {error.toString()}
</Alert>
</div>
);
}
return (
<Table
isLoading={loading}
columns={columns}
options={{
padding: 'dense',
paging: false,
search: true,
paging: true,
pageSize: 5,
showEmptyDataSourceMessage: !loading,
}}
title="Top Active Items"
data={items}
data={items.map(i => ({ org: organization, project, ...i }))}
/>
);
};