@pagerduty/backstage-plugin
Version:
A Backstage plugin that integrates towards PagerDuty
244 lines (241 loc) • 10.2 kB
JavaScript
import { jsx, jsxs } from 'react/jsx-runtime';
import { useState, useCallback } from 'react';
import { Divider } from '@material-ui/core';
import { Incidents } from '../Incident/Incidents.esm.js';
import { EscalationPolicy } from '../Escalation/EscalationPolicy.esm.js';
import useAsync from 'react-use/lib/useAsync';
import { pagerDutyApiRef, UnauthorizedError } from '../../api/client.esm.js';
import { MissingTokenError } from '../Errors/MissingTokenError.esm.js';
import { ServiceNotFoundError } from '../Errors/ServiceNotFoundError.esm.js';
import { ChangeEvents } from '../ChangeEvents/ChangeEvents.esm.js';
import PDGreenImage from '../../assets/PD-Green.svg';
import PDWhiteImage from '../../assets/PD-White.svg';
import { useApi } from '@backstage/core-plugin-api';
import { NotFoundError } from '@backstage/errors';
import { Progress, InfoCard } from '@backstage/core-components';
import { ForbiddenError } from '../Errors/ForbiddenError.esm.js';
import IncidentCounterCard from '../PagerDutyCardCommon/InsightsCard.esm.js';
import { OpenServiceButton } from '../PagerDutyCardCommon/OpenServiceButton.esm.js';
import ServiceStandardsCard from '../PagerDutyCardCommon/ServiceStandardsCard.esm.js';
import StatusCard from '../PagerDutyCardCommon/StatusCard.esm.js';
import { TriggerIncidentButton } from '../PagerDutyCardCommon/TriggerIncidentButton.esm.js';
import { makeStyles, useTheme, createStyles } from '@material-ui/core/styles';
import { Card, Grid, Flex, Text, Tabs, TabList, Tab, TabPanel } from '@backstage/ui';
const useStyles = makeStyles(
(_) => createStyles({
oncallHeaderTextStyle: {
fontSize: "14px",
fontWeight: 500,
marginTop: "10px",
marginLeft: "10px"
},
subheaderTextStyle: {
fontSize: "10px",
marginLeft: "-10px",
paddingTop: "3px"
},
logoContainerStyles: {
height: "100%"
},
cardStyles: {
paddingLeft: "20px",
paddingRight: "20px"
}
})
);
const BasicCard = ({ children }) => /* @__PURE__ */ jsx(InfoCard, { title: "PagerDuty", children });
const PagerDutyCard = (props) => {
const classes = useStyles();
const theme = useTheme();
const { entity, readOnly, disableChangeEvents, disableOnCall } = props;
const api = useApi(pagerDutyApiRef);
const [refreshIncidents, setRefreshIncidents] = useState(false);
const [refreshChangeEvents, setRefreshChangeEvents] = useState(false);
const [refreshStatus, setRefreshStatus] = useState(false);
const handleRefresh = useCallback(() => {
setRefreshIncidents((x) => !x);
setRefreshChangeEvents((x) => !x);
setRefreshStatus((x) => !x);
}, []);
const handleUnmapService = useCallback(async () => {
const { namespace, name } = entity.metadata;
const kind = entity.kind;
const entityRef = `${kind}:${namespace || "default"}/${name}`;
return await api.removeServiceMapping(entityRef);
}, [entity, api]);
const {
value: service,
loading,
error
} = useAsync(async () => {
const { service: foundService } = await api.getServiceByPagerDutyEntity(
props
);
const serviceStandards = await api.getServiceStandardsByServiceId(
foundService.id,
props.account
);
const serviceMetrics = await api.getServiceMetricsByServiceId(
foundService.id,
props.account
);
const result = {
id: foundService.id,
account: props.account,
name: foundService.name,
url: foundService.html_url,
policyId: foundService.escalation_policy.id,
policyLink: foundService.escalation_policy.html_url,
policyName: foundService.escalation_policy.name,
status: foundService.status,
standards: serviceStandards !== void 0 ? serviceStandards.standards : void 0,
metrics: serviceMetrics !== void 0 ? serviceMetrics.metrics : void 0
};
return result;
}, [props]);
if (error) {
let errorNode;
switch (error.constructor) {
case UnauthorizedError:
errorNode = /* @__PURE__ */ jsx(MissingTokenError, {});
break;
case NotFoundError:
errorNode = /* @__PURE__ */ jsx(
ServiceNotFoundError,
{
entity,
serviceId: props.serviceId,
integrationKey: props.integrationKey,
onUnmap: handleUnmapService
}
);
break;
default:
errorNode = /* @__PURE__ */ jsx(ForbiddenError, {});
}
return /* @__PURE__ */ jsx(BasicCard, { children: errorNode });
}
if (loading) {
return /* @__PURE__ */ jsx(BasicCard, { children: /* @__PURE__ */ jsx(Progress, {}) });
}
return /* @__PURE__ */ jsxs(Card, { "data-testid": "pagerduty-card", className: classes.cardStyles, children: [
/* @__PURE__ */ jsxs(Grid.Root, { columns: "6", children: [
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "4", children: /* @__PURE__ */ jsx(
Flex,
{
pl: "20px",
align: "center",
className: classes.logoContainerStyles,
children: theme.palette.type === "dark" ? /* @__PURE__ */ jsx("img", { src: PDWhiteImage, alt: "PagerDuty", height: "35" }) : /* @__PURE__ */ jsx("img", { src: PDGreenImage, alt: "PagerDuty", height: "35" })
}
) }),
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "2", children: /* @__PURE__ */ jsx(Flex, { justify: "end", children: !readOnly && props.integrationKey ? /* @__PURE__ */ jsxs(Flex, { children: [
/* @__PURE__ */ jsx(
TriggerIncidentButton,
{
"data-testid": "trigger-incident-button",
integrationKey: props.integrationKey,
entityName: props.name,
handleRefresh
}
),
/* @__PURE__ */ jsx(OpenServiceButton, { serviceUrl: service.url })
] }) : /* @__PURE__ */ jsx(OpenServiceButton, { serviceUrl: service.url }) }) })
] }),
/* @__PURE__ */ jsxs(Grid.Root, { columns: "4", gap: "1", pl: "1", pr: "1", children: [
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "1", children: /* @__PURE__ */ jsx(Text, { color: "secondary", weight: "bold", children: "STATUS" }) }),
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "2", children: /* @__PURE__ */ jsxs(Flex, { children: [
/* @__PURE__ */ jsx(Text, { color: "secondary", weight: "bold", children: "INSIGHTS" }),
/* @__PURE__ */ jsx(Text, { color: "secondary", className: classes.subheaderTextStyle, children: "(last 30 days)" })
] }) }),
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "1", children: /* @__PURE__ */ jsx(Text, { color: "secondary", weight: "bold", children: "STANDARDS" }) })
] }),
/* @__PURE__ */ jsxs(Grid.Root, { gap: "1", columns: "4", pl: "1", pr: "1", children: [
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "1", children: /* @__PURE__ */ jsx(
StatusCard,
{
serviceId: service.id,
account: service.account,
refreshStatus
}
) }),
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "2", children: /* @__PURE__ */ jsxs(Grid.Root, { gap: "1", columns: "3", pl: "1", pr: "1", children: [
/* @__PURE__ */ jsx(Grid.Item, { children: /* @__PURE__ */ jsx(
IncidentCounterCard,
{
count: service?.metrics !== void 0 && service.metrics.length > 0 ? service?.metrics[0].total_interruptions : void 0,
label: "interruptions",
color: theme.palette.textSubtle
}
) }),
/* @__PURE__ */ jsx(Grid.Item, { children: /* @__PURE__ */ jsx(
IncidentCounterCard,
{
count: service?.metrics !== void 0 && service.metrics.length > 0 ? service?.metrics[0].total_high_urgency_incidents : void 0,
label: "high urgency",
color: theme.palette.warning.main
}
) }),
/* @__PURE__ */ jsx(Grid.Item, { children: /* @__PURE__ */ jsx(
IncidentCounterCard,
{
count: service?.metrics !== void 0 && service?.metrics?.length > 0 ? service?.metrics[0].total_incident_count : void 0,
label: "incidents",
color: theme.palette.error.main
}
) })
] }) }),
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "1", children: /* @__PURE__ */ jsx(
ServiceStandardsCard,
{
total: service?.standards?.score !== void 0 ? service?.standards?.score?.total : void 0,
completed: service?.standards?.score !== void 0 ? service?.standards?.score?.passing : void 0,
standards: service?.standards !== void 0 ? service?.standards?.standards : void 0
}
) })
] }),
/* @__PURE__ */ jsx(Divider, {}),
/* @__PURE__ */ jsxs(Tabs, { children: [
/* @__PURE__ */ jsxs(TabList, { children: [
/* @__PURE__ */ jsxs(Tab, { id: "tab-1", children: [
"Incidents \xA0",
/* @__PURE__ */ jsx(Text, { variant: "body-x-small", children: "(last 30 days)" })
] }),
disableChangeEvents !== true && /* @__PURE__ */ jsx(Tab, { id: "tab-2", children: "Change Events" })
] }),
/* @__PURE__ */ jsx(TabPanel, { id: "tab-1", children: /* @__PURE__ */ jsx(
Incidents,
{
serviceId: service.id,
refreshIncidents,
account: service.account,
serviceURL: service.url
}
) }),
disableChangeEvents !== true && /* @__PURE__ */ jsx(TabPanel, { id: "tab-2", children: /* @__PURE__ */ jsx(
ChangeEvents,
{
"data-testid": "change-events",
serviceId: service.id,
refreshEvents: refreshChangeEvents,
account: service.account
}
) })
] }),
disableOnCall !== true && /* @__PURE__ */ jsxs(Flex, { mt: "10px", ml: "10px", direction: "column", gap: "0", children: [
/* @__PURE__ */ jsx(Text, { weight: "bold", color: "secondary", children: "ON CALL" }),
/* @__PURE__ */ jsx(
EscalationPolicy,
{
"data-testid": "oncall-card",
policyId: service.policyId,
policyUrl: service.policyLink,
policyName: service.policyName,
account: service.account
}
)
] })
] });
};
export { PagerDutyCard };
//# sourceMappingURL=index.esm.js.map