UNPKG

@pagerduty/backstage-plugin

Version:

A Backstage plugin that integrates towards PagerDuty

213 lines (210 loc) 9.75 kB
import React, { useState, useCallback } from 'react'; import { Card, CardHeader, Grid, Typography, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core'; 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 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, createStyles, useTheme } from '@material-ui/core/styles'; import { EscalationPolicy } from '../Escalation/EscalationPolicy.esm.js'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; const useStyles = makeStyles( (theme) => createStyles({ overviewHeaderTextStyle: { fontSize: "14px", fontWeight: 500, color: theme.palette.type === "light" ? "rgba(0, 0, 0, 0.54)" : "rgba(255, 255, 255, 0.7)" }, headerStyle: { marginBottom: "0px", fontSize: "0px" }, overviewHeaderContainerStyle: { display: "flex", margin: "0px", padding: "15px", marginBottom: "5px" }, headerWithSubheaderContainerStyle: { display: "flex", alignItems: "center" }, subheaderTextStyle: { fontSize: "10px", marginLeft: "5px" }, overviewCardsContainerStyle: { display: "flex", margin: "15px", marginTop: "-15px" }, onCallAccordionDetails: { display: "flex", width: "100%", marginTop: "-25px", marginBottom: "-15px" }, incidentMetricsContainerStyle: { display: "flex", height: "100%", justifyContent: "center", columnSpan: "all", margin: "15px", marginTop: "-15px" } }) ); const BasicCard = ({ children }) => /* @__PURE__ */ React.createElement(InfoCard, { title: "PagerDuty" }, children); const PagerDutySmallCard = (props) => { const classes = useStyles(); const theme = useTheme(); const { readOnly, disableInsights, disableOnCall } = props; const api = useApi(pagerDutyApiRef); const [refreshStatus, setRefreshStatus] = useState(false); const handleRefresh = useCallback(() => { setRefreshStatus((x) => !x); }, []); 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, name: foundService.name, account: props.account, 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__ */ React.createElement(MissingTokenError, null); break; case NotFoundError: errorNode = /* @__PURE__ */ React.createElement(ServiceNotFoundError, null); break; default: errorNode = /* @__PURE__ */ React.createElement(ForbiddenError, null); } return /* @__PURE__ */ React.createElement(BasicCard, null, errorNode); } if (loading) { return /* @__PURE__ */ React.createElement(BasicCard, null, /* @__PURE__ */ React.createElement(Progress, null)); } return /* @__PURE__ */ React.createElement(Card, { "data-testid": "pagerduty-card" }, /* @__PURE__ */ React.createElement( CardHeader, { className: classes.headerStyle, title: theme.palette.type === "dark" ? /* @__PURE__ */ React.createElement("img", { src: PDWhiteImage, alt: "PagerDuty", height: "25" }) : /* @__PURE__ */ React.createElement("img", { src: PDGreenImage, alt: "PagerDuty", height: "25" }), action: !readOnly && props.integrationKey ? /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement( TriggerIncidentButton, { compact: true, "data-testid": "trigger-incident-button", integrationKey: props.integrationKey, entityName: props.name, handleRefresh } ), /* @__PURE__ */ React.createElement(OpenServiceButton, { compact: true, serviceUrl: service.url })) : /* @__PURE__ */ React.createElement(OpenServiceButton, { compact: true, serviceUrl: service.url }) } ), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 12, className: classes.overviewHeaderContainerStyle }, /* @__PURE__ */ React.createElement(Grid, { item: true, md: 6 }, /* @__PURE__ */ React.createElement(Typography, { className: classes.overviewHeaderTextStyle }, "STATUS")), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 6 }, /* @__PURE__ */ React.createElement(Typography, { className: classes.overviewHeaderTextStyle }, "STANDARDS"))), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 12, className: classes.overviewCardsContainerStyle }, /* @__PURE__ */ React.createElement(Grid, { item: true, md: 6 }, /* @__PURE__ */ React.createElement(StatusCard, { compact: true, serviceId: service.id, refreshStatus, account: service.account })), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 6 }, /* @__PURE__ */ React.createElement( ServiceStandardsCard, { compact: true, 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 } ))), disableInsights !== true ? /* @__PURE__ */ React.createElement(Accordion, null, /* @__PURE__ */ React.createElement( AccordionSummary, { expandIcon: /* @__PURE__ */ React.createElement(ExpandMoreIcon, null), "aria-controls": "panel1a-content", id: "panel1a-header" }, /* @__PURE__ */ React.createElement("span", { className: classes.headerWithSubheaderContainerStyle }, /* @__PURE__ */ React.createElement(Typography, { className: classes.overviewHeaderTextStyle }, "INSIGHTS"), /* @__PURE__ */ React.createElement(Typography, { className: classes.subheaderTextStyle }, "(last 30 days)")) ), /* @__PURE__ */ React.createElement(AccordionDetails, null, /* @__PURE__ */ React.createElement( Grid, { item: true, md: 12, className: classes.incidentMetricsContainerStyle }, /* @__PURE__ */ React.createElement(Grid, { item: true, md: 4 }, /* @__PURE__ */ React.createElement( IncidentCounterCard, { compact: true, count: service?.metrics !== void 0 && service.metrics.length > 0 ? service?.metrics[0].total_interruptions : void 0, label: "interruptions", color: theme.palette.textSubtle } )), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 4 }, /* @__PURE__ */ React.createElement( IncidentCounterCard, { compact: true, 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__ */ React.createElement(Grid, { item: true, md: 4 }, /* @__PURE__ */ React.createElement( IncidentCounterCard, { compact: true, 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__ */ React.createElement(React.Fragment, null), disableOnCall !== true ? /* @__PURE__ */ React.createElement(Accordion, null, /* @__PURE__ */ React.createElement( AccordionSummary, { expandIcon: /* @__PURE__ */ React.createElement(ExpandMoreIcon, null), "aria-controls": "panel1a-content", id: "panel1a-header" }, /* @__PURE__ */ React.createElement(Typography, { className: classes.overviewHeaderTextStyle }, "ON CALL") ), /* @__PURE__ */ React.createElement(AccordionDetails, { className: classes.onCallAccordionDetails }, /* @__PURE__ */ React.createElement( EscalationPolicy, { "data-testid": "oncall-card", policyId: service.policyId, policyUrl: service.policyLink, policyName: service.policyName, account: service.account } ))) : /* @__PURE__ */ React.createElement(React.Fragment, null)); }; export { PagerDutySmallCard }; //# sourceMappingURL=index.esm.js.map