refactor code an structure
This commit is contained in:
@@ -37,7 +37,7 @@ describe('Escalation', () => {
|
||||
expect(getByText('Empty escalation policy')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('render Escalation list', () => {
|
||||
it('render escalation list', () => {
|
||||
const { getByText } = render(
|
||||
wrapInTestApp(<EscalationPolicy users={escalations} />),
|
||||
);
|
||||
|
||||
@@ -29,7 +29,6 @@ export const EscalationPolicy = ({ users }: EscalationPolicyProps) => (
|
||||
{users.length ? (
|
||||
users.map((user, index) => <EscalationUser key={index} user={user} />)
|
||||
) : (
|
||||
// TODO: how does it look if we used an EmptyState component here
|
||||
<EscalationUsersEmptyState />
|
||||
)}
|
||||
</List>
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
} from '@material-ui/core';
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
import EmailIcon from '@material-ui/icons/Email';
|
||||
import PagerdutyIcon from '../Pd';
|
||||
import PagerdutyIcon from '../PagerDutyIcon';
|
||||
import { User } from '../types';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { EscalationPolicy } from './EscalationPolicy';
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
import { StatusError, StatusWarning } from '@backstage/core';
|
||||
import moment from 'moment';
|
||||
import { Incident } from '../types';
|
||||
import PagerdutyIcon from '../Pd';
|
||||
import PagerdutyIcon from '../PagerDutyIcon';
|
||||
|
||||
type IncidentListItemProps = {
|
||||
incident: Incident;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { Incidents } from './Incidents';
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 React from 'react';
|
||||
import { useApi } from '@backstage/core';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { LinearProgress } from '@material-ui/core';
|
||||
import { Incidents } from './Incident/Incidents';
|
||||
import { EscalationPolicy } from './Escalation/EscalationPolicy';
|
||||
import { TriggerButton } from './TriggerButton';
|
||||
import { useAsync } from 'react-use';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { pagerDutyApiRef } from '../api/pagerDutyClient';
|
||||
import { PagerdutyCard } from './PagerdutyCard';
|
||||
|
||||
export const PAGERDUTY_INTEGRATION_KEY = 'pagerduty.com/integration-key';
|
||||
|
||||
export const isPluginApplicableToEntity = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[PAGERDUTY_INTEGRATION_KEY]);
|
||||
|
||||
type Props = {
|
||||
entity: Entity;
|
||||
};
|
||||
|
||||
export const PagerDutyServiceCard = ({ entity }: Props) => {
|
||||
const api = useApi(pagerDutyApiRef);
|
||||
|
||||
const { value, loading, error } = useAsync(async () => {
|
||||
const integrationKey = entity.metadata.annotations![
|
||||
PAGERDUTY_INTEGRATION_KEY
|
||||
];
|
||||
|
||||
const services = await api.getServiceByIntegrationKey(integrationKey);
|
||||
// TODO check services length
|
||||
const service = services[0];
|
||||
const incidents = await api.getIncidentsByServiceId(service.id);
|
||||
const oncalls = await api.getOnCallByPolicyId(service.escalation_policy.id);
|
||||
const users = oncalls.map(item => item.user);
|
||||
|
||||
return {
|
||||
incidents,
|
||||
users,
|
||||
id: service.id,
|
||||
name: service.name,
|
||||
homepageUrl: service.html_url,
|
||||
};
|
||||
});
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div>
|
||||
<Alert severity="error">
|
||||
Error encountered while fetching information. {error.message}
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return <LinearProgress />;
|
||||
}
|
||||
|
||||
const pagerdutyLink = {
|
||||
title: 'View in PagerDuty',
|
||||
href: value!.homepageUrl,
|
||||
};
|
||||
|
||||
const triggerAlarm = {
|
||||
title: 'Trigger Alarm',
|
||||
action: <TriggerButton entity={entity} />,
|
||||
};
|
||||
|
||||
return (
|
||||
<PagerdutyCard
|
||||
title="Pagerduty"
|
||||
subheader={{ ViewPagerduty: pagerdutyLink, TriggerAlarm: triggerAlarm }}
|
||||
content={
|
||||
<>
|
||||
<Incidents incidents={value!.incidents} />
|
||||
<EscalationPolicy users={value!.users} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,18 +1,38 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 React from 'react';
|
||||
import { useApi, EmptyState } from '@backstage/core';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
Divider,
|
||||
Link,
|
||||
LinearProgress,
|
||||
makeStyles,
|
||||
} from '@material-ui/core';
|
||||
import LinkIcon from '@material-ui/icons/Link';
|
||||
import { Incidents } from './Incident';
|
||||
import { EscalationPolicy } from './Escalation';
|
||||
import { TriggerButton } from './TriggerButton';
|
||||
import { useAsync } from 'react-use';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { pagerDutyApiRef, UnauthorizedError } from '../api';
|
||||
import { IconLinkVertical } from '@backstage/plugin-catalog';
|
||||
import PagerDutyIcon from './PagerDutyIcon';
|
||||
import ReportProblemIcon from '@material-ui/icons/ReportProblem';
|
||||
import classnames from 'classnames';
|
||||
import PagerdutyIcon from './Pd';
|
||||
|
||||
// TODO: create a general component to use it in pagerduty and aboutCard
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
links: {
|
||||
@@ -22,102 +42,98 @@ const useStyles = makeStyles(theme => ({
|
||||
gridAutoColumns: 'min-content',
|
||||
gridGap: theme.spacing(3),
|
||||
},
|
||||
link: {
|
||||
display: 'grid',
|
||||
justifyItems: 'center',
|
||||
gridGap: 4,
|
||||
textAlign: 'center',
|
||||
},
|
||||
label: {
|
||||
fontSize: '0.7rem',
|
||||
textTransform: 'uppercase',
|
||||
fontWeight: 600,
|
||||
letterSpacing: 1.2,
|
||||
},
|
||||
trigger: {
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
svgButtonImage: {
|
||||
height: '1.5em',
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
}));
|
||||
|
||||
type SubHeaderProps = {
|
||||
ViewPagerduty: { title: string; href: string };
|
||||
TriggerAlarm: { title: string; action: React.ReactNode };
|
||||
export const PAGERDUTY_INTEGRATION_KEY = 'pagerduty.com/integration-key';
|
||||
|
||||
export const isPluginApplicableToEntity = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[PAGERDUTY_INTEGRATION_KEY]);
|
||||
|
||||
type Props = {
|
||||
entity: Entity;
|
||||
};
|
||||
|
||||
type PagerdutyCardProps = {
|
||||
title: string;
|
||||
subheader: SubHeaderProps;
|
||||
content: React.ReactNode;
|
||||
};
|
||||
|
||||
type VerticalIconProps = {
|
||||
label: string;
|
||||
href?: string;
|
||||
action?: React.ReactNode;
|
||||
icon?: React.ReactNode;
|
||||
};
|
||||
|
||||
const VerticalIcon = ({
|
||||
label,
|
||||
href,
|
||||
icon = <LinkIcon />,
|
||||
action,
|
||||
}: VerticalIconProps) => {
|
||||
export const PagerDutyCard = ({ entity }: Props) => {
|
||||
const classes = useStyles();
|
||||
if (action) {
|
||||
const api = useApi(pagerDutyApiRef);
|
||||
|
||||
const { value, loading, error } = useAsync(async () => {
|
||||
const integrationKey = entity.metadata.annotations![
|
||||
PAGERDUTY_INTEGRATION_KEY
|
||||
];
|
||||
|
||||
const services = await api.getServiceByIntegrationKey(integrationKey);
|
||||
const incidents = await api.getIncidentsByServiceId(services[0].id);
|
||||
const oncalls = await api.getOnCallByPolicyId(
|
||||
services[0].escalation_policy.id,
|
||||
);
|
||||
const users = oncalls.map(oncall => oncall.user);
|
||||
|
||||
return {
|
||||
incidents,
|
||||
users,
|
||||
id: services[0].id,
|
||||
name: services[0].name,
|
||||
homepageUrl: services[0].html_url,
|
||||
};
|
||||
});
|
||||
|
||||
if (error) {
|
||||
if (error instanceof UnauthorizedError) {
|
||||
return (
|
||||
<EmptyState
|
||||
missing="info"
|
||||
title="Missing or invalid PagerDuty Token"
|
||||
description="The request to fetch data need a valid token. See README for more details."
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Link className={classnames(classes.link, classes.trigger)} href={href}>
|
||||
{icon}
|
||||
{action}
|
||||
</Link>
|
||||
</>
|
||||
<Alert severity="error">
|
||||
Error encountered while fetching information. {error.message}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Link className={classes.link} href={href}>
|
||||
{icon}
|
||||
<span className={classes.label}>{label}</span>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export const PagerdutyCard = ({
|
||||
title,
|
||||
subheader,
|
||||
content,
|
||||
}: PagerdutyCardProps) => {
|
||||
const classes = useStyles();
|
||||
const getSubheader = ({ ViewPagerduty, TriggerAlarm }: SubHeaderProps) => {
|
||||
return (
|
||||
<nav className={classes.links}>
|
||||
<VerticalIcon
|
||||
label={ViewPagerduty.title}
|
||||
href={ViewPagerduty.href}
|
||||
icon={<PagerdutyIcon viewBox="0 0 100 100" />}
|
||||
></VerticalIcon>
|
||||
<VerticalIcon
|
||||
label={TriggerAlarm.title}
|
||||
icon={<ReportProblemIcon />}
|
||||
action={TriggerAlarm.action}
|
||||
></VerticalIcon>
|
||||
</nav>
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return <LinearProgress />;
|
||||
}
|
||||
|
||||
const pagerdutyLink = {
|
||||
title: 'View in PagerDuty',
|
||||
href: value!.homepageUrl,
|
||||
};
|
||||
|
||||
const triggerAlarm = {
|
||||
title: 'Trigger Alarm',
|
||||
action: <TriggerButton entity={entity} />,
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title={title}
|
||||
subheader={getSubheader(subheader)}
|
||||
></CardHeader>
|
||||
title="PagerDuty"
|
||||
subheader={
|
||||
<nav className={classes.links}>
|
||||
<IconLinkVertical
|
||||
label={pagerdutyLink.title}
|
||||
href={pagerdutyLink.href}
|
||||
icon={<PagerDutyIcon viewBox="0 0 100 100" />}
|
||||
/>
|
||||
<IconLinkVertical
|
||||
label={triggerAlarm.title}
|
||||
icon={<ReportProblemIcon />}
|
||||
action={triggerAlarm.action}
|
||||
/>
|
||||
</nav>
|
||||
}
|
||||
/>
|
||||
<Divider />
|
||||
<CardContent>{content}</CardContent>
|
||||
<CardContent>
|
||||
<Incidents incidents={value!.incidents} />
|
||||
<EscalationPolicy users={value!.users} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
+2
-2
@@ -16,9 +16,9 @@
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { Button, makeStyles } from '@material-ui/core';
|
||||
import { TriggerDialog } from './TriggerDialog';
|
||||
import { TriggerDialog } from '../TriggerDialog';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { PAGERDUTY_INTEGRATION_KEY } from './PagerDutyServiceCard';
|
||||
import { PAGERDUTY_INTEGRATION_KEY } from '../PagerDutyCard';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
triggerAlarm: {
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { TriggerButton } from './TriggerButton';
|
||||
+2
-2
@@ -24,8 +24,8 @@ import {
|
||||
IdentityApi,
|
||||
identityApiRef,
|
||||
} from '@backstage/core';
|
||||
import { pagerDutyApiRef } from '../api/pagerDutyClient';
|
||||
import { TriggerButton } from './TriggerButton';
|
||||
import { pagerDutyApiRef } from '../../api';
|
||||
import { TriggerButton } from '../TriggerButton';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import {
|
||||
} from '@material-ui/core';
|
||||
import { Progress, useApi, alertApiRef, identityApiRef } from '@backstage/core';
|
||||
import { useAsyncFn } from 'react-use';
|
||||
import { pagerDutyApiRef } from '../api/pagerDutyClient';
|
||||
import { pagerDutyApiRef } from '../../api';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
warningText: {
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { TriggerDialog } from './TriggerDialog';
|
||||
@@ -51,10 +51,6 @@ export type User = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type ClientApiConfig = {
|
||||
token?: string;
|
||||
};
|
||||
|
||||
export type ServicesResponse = {
|
||||
services: Service[];
|
||||
};
|
||||
@@ -72,3 +68,8 @@ export type RequestOptions = {
|
||||
headers: HeadersInit;
|
||||
body?: BodyInit;
|
||||
};
|
||||
|
||||
export type ClientApiConfig = {
|
||||
api_url: string;
|
||||
events_url: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user