@pagerduty/backstage-plugin 0.9.4-next.1 → 0.9.4-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/{index-46807363.esm.js → index-05ed342b.esm.js} +453 -383
- package/dist/esm/index-05ed342b.esm.js.map +1 -0
- package/dist/esm/{index-b2ba10a3.esm.js → index-7306b2fe.esm.js} +7 -7
- package/dist/esm/{index-b2ba10a3.esm.js.map → index-7306b2fe.esm.js.map} +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.esm.js +6 -6
- package/package.json +5 -4
- package/dist/esm/index-46807363.esm.js.map +0 -1
|
@@ -3,9 +3,7 @@ import { NotFoundError } from '@backstage/errors';
|
|
|
3
3
|
import { createCardExtension } from '@backstage/plugin-home-react';
|
|
4
4
|
import React, { useEffect, useState, useCallback } from 'react';
|
|
5
5
|
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
6
|
-
import { makeStyles, ListItem, ListItemText, Chip, Typography, ListItemSecondaryAction, Tooltip, IconButton, Grid, List, ListItemIcon, ListSubheader, Button, Dialog, DialogTitle, DialogContent, TextField, DialogActions, CircularProgress, Card, CardHeader, Divider, CardContent } from '@material-ui/core';
|
|
7
|
-
import Done from '@material-ui/icons/Done';
|
|
8
|
-
import Warning from '@material-ui/icons/Warning';
|
|
6
|
+
import { makeStyles, ListItem, ListItemText, Chip, Typography, ListItemSecondaryAction, Tooltip, IconButton, Grid, List, ListItemIcon, ListSubheader, Button, Dialog, DialogTitle, DialogContent, TextField, DialogActions, CircularProgress, Card, withStyles, LinearProgress, CardHeader, Divider, CardContent } from '@material-ui/core';
|
|
9
7
|
import { DateTime, Duration } from 'luxon';
|
|
10
8
|
import OpenInBrowserIcon from '@material-ui/icons/OpenInBrowser';
|
|
11
9
|
import { Link, Progress, StatusWarning, StatusError, EmptyState, TabbedCard, CardTab, InfoCard } from '@backstage/core-components';
|
|
@@ -15,14 +13,16 @@ import { Alert } from '@material-ui/lab';
|
|
|
15
13
|
import ForbiddenStateImage from '../assets/forbiddenstate.svg';
|
|
16
14
|
import Avatar from '@material-ui/core/Avatar';
|
|
17
15
|
import NotificationsIcon from '@material-ui/icons/Notifications';
|
|
18
|
-
import MailOutline from '@material-ui/icons/MailOutline';
|
|
19
16
|
import useAsync from 'react-use/lib/useAsync';
|
|
20
|
-
import
|
|
17
|
+
import LinkIcon from '@material-ui/icons/Link';
|
|
21
18
|
import PDGreenImage from '../assets/PD-Green.svg';
|
|
22
19
|
import PDWhiteImage from '../assets/PD-White.svg';
|
|
20
|
+
import { parseEntityRef, DEFAULT_NAMESPACE } from '@backstage/catalog-model';
|
|
23
21
|
import AddAlert from '@material-ui/icons/AddAlert';
|
|
24
|
-
import { useTheme } from '@material-ui/core/styles';
|
|
25
|
-
import
|
|
22
|
+
import { makeStyles as makeStyles$1, createStyles, useTheme } from '@material-ui/core/styles';
|
|
23
|
+
import { useAsyncFn as useAsyncFn$1 } from 'react-use';
|
|
24
|
+
import Alert$1 from '@material-ui/lab/Alert/Alert';
|
|
25
|
+
import validateColor from 'validate-color';
|
|
26
26
|
|
|
27
27
|
const PAGERDUTY_INTEGRATION_KEY = "pagerduty.com/integration-key";
|
|
28
28
|
const PAGERDUTY_SERVICE_ID = "pagerduty.com/service-id";
|
|
@@ -82,6 +82,12 @@ class PagerDutyClient {
|
|
|
82
82
|
async getServiceByEntity(entity) {
|
|
83
83
|
return await this.getServiceByPagerDutyEntity(getPagerDutyEntity(entity));
|
|
84
84
|
}
|
|
85
|
+
async getServiceById(serviceId) {
|
|
86
|
+
const url = `${await this.config.discoveryApi.getBaseUrl(
|
|
87
|
+
"pagerduty"
|
|
88
|
+
)}/services/${serviceId}`;
|
|
89
|
+
return await this.findByUrl(url);
|
|
90
|
+
}
|
|
85
91
|
async getIncidentsByServiceId(serviceId) {
|
|
86
92
|
const url = `${await this.config.discoveryApi.getBaseUrl(
|
|
87
93
|
"pagerduty"
|
|
@@ -94,6 +100,12 @@ class PagerDutyClient {
|
|
|
94
100
|
)}/services/${serviceId}/change-events`;
|
|
95
101
|
return await this.findByUrl(url);
|
|
96
102
|
}
|
|
103
|
+
async getServiceStandardsByServiceId(serviceId) {
|
|
104
|
+
const url = `${await this.config.discoveryApi.getBaseUrl(
|
|
105
|
+
"pagerduty"
|
|
106
|
+
)}/services/${serviceId}/standards`;
|
|
107
|
+
return await this.findByUrl(url);
|
|
108
|
+
}
|
|
97
109
|
async getOnCallByPolicyId(policyId) {
|
|
98
110
|
const params = `escalation_policy_ids[]=${policyId}`;
|
|
99
111
|
const url = `${await this.config.discoveryApi.getBaseUrl(
|
|
@@ -194,7 +206,7 @@ const HomePagePagerDutyCard = pagerDutyPlugin.provide(
|
|
|
194
206
|
createCardExtension({
|
|
195
207
|
name: "HomePagePagerDutyCard",
|
|
196
208
|
title: "PagerDuty Homepage Card",
|
|
197
|
-
components: () => import('./index-
|
|
209
|
+
components: () => import('./index-7306b2fe.esm.js'),
|
|
198
210
|
settings: {
|
|
199
211
|
schema: {
|
|
200
212
|
title: "PagerDuty",
|
|
@@ -218,7 +230,7 @@ const HomePagePagerDutyCard = pagerDutyPlugin.provide(
|
|
|
218
230
|
})
|
|
219
231
|
);
|
|
220
232
|
|
|
221
|
-
const useStyles$
|
|
233
|
+
const useStyles$8 = makeStyles((theme) => ({
|
|
222
234
|
denseListIcon: {
|
|
223
235
|
marginRight: 0,
|
|
224
236
|
display: "flex",
|
|
@@ -230,39 +242,81 @@ const useStyles$7 = makeStyles((theme) => ({
|
|
|
230
242
|
fontWeight: "bold"
|
|
231
243
|
},
|
|
232
244
|
warning: {
|
|
233
|
-
borderColor: theme.palette.
|
|
234
|
-
color:
|
|
245
|
+
borderColor: theme.palette.warning.main,
|
|
246
|
+
color: "#fff",
|
|
247
|
+
backgroundColor: theme.palette.warning.main,
|
|
248
|
+
boxShadow: "0 4px 4px 0 rgba(0,0,0,0.2)",
|
|
249
|
+
textTransform: "uppercase",
|
|
235
250
|
"& *": {
|
|
236
|
-
color:
|
|
251
|
+
color: "#fff"
|
|
237
252
|
}
|
|
238
253
|
},
|
|
239
254
|
error: {
|
|
240
|
-
borderColor: theme.palette.
|
|
241
|
-
color:
|
|
255
|
+
borderColor: theme.palette.error.main,
|
|
256
|
+
color: "#fff",
|
|
257
|
+
backgroundColor: theme.palette.error.main,
|
|
258
|
+
boxShadow: "0 4px 4px 0 rgba(0,0,0,0.2)",
|
|
259
|
+
textTransform: "uppercase",
|
|
242
260
|
"& *": {
|
|
243
|
-
color:
|
|
261
|
+
color: "#fff"
|
|
244
262
|
}
|
|
263
|
+
},
|
|
264
|
+
lowUrgency: {
|
|
265
|
+
borderColor: theme.palette.warning.main,
|
|
266
|
+
color: theme.palette.warning.main,
|
|
267
|
+
backgroundColor: "#fff",
|
|
268
|
+
boxShadow: "0 4px 4px 0 rgba(0,0,0,0.2)",
|
|
269
|
+
textTransform: "uppercase",
|
|
270
|
+
"& *": {
|
|
271
|
+
color: theme.palette.warning.main
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
highUrgency: {
|
|
275
|
+
borderColor: theme.palette.error.main,
|
|
276
|
+
color: theme.palette.error.main,
|
|
277
|
+
backgroundColor: "#fff",
|
|
278
|
+
boxShadow: "0 4px 4px 0 rgba(0,0,0,0.2)",
|
|
279
|
+
textTransform: "uppercase",
|
|
280
|
+
"& *": {
|
|
281
|
+
color: theme.palette.error.main
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
textContainer: {
|
|
285
|
+
display: "flex",
|
|
286
|
+
alignItems: "baseline"
|
|
287
|
+
},
|
|
288
|
+
smallIconStyle: {
|
|
289
|
+
color: theme.palette.text.primary,
|
|
290
|
+
marginRight: "-20px"
|
|
245
291
|
}
|
|
246
292
|
}));
|
|
247
293
|
const IncidentListItem = ({ incident }) => {
|
|
248
294
|
var _a, _b, _c;
|
|
249
|
-
const classes = useStyles$
|
|
295
|
+
const classes = useStyles$8();
|
|
250
296
|
const duration = (/* @__PURE__ */ new Date()).getTime() - new Date(incident.created_at).getTime();
|
|
251
297
|
const createdAt = DateTime.local().minus(Duration.fromMillis(duration)).toRelative({ locale: "en" });
|
|
252
298
|
const user = (_a = incident.assignments[0]) == null ? void 0 : _a.assignee;
|
|
253
299
|
return /* @__PURE__ */ React.createElement(ListItem, { dense: true, key: incident.id }, /* @__PURE__ */ React.createElement(
|
|
254
300
|
ListItemText,
|
|
255
301
|
{
|
|
256
|
-
primary: /* @__PURE__ */ React.createElement(
|
|
302
|
+
primary: /* @__PURE__ */ React.createElement("div", { className: classes.textContainer }, /* @__PURE__ */ React.createElement(
|
|
257
303
|
Chip,
|
|
258
304
|
{
|
|
259
305
|
"data-testid": `chip-${incident.status}`,
|
|
260
306
|
label: incident.status,
|
|
261
307
|
size: "small",
|
|
262
308
|
variant: "outlined",
|
|
263
|
-
icon: incident.status === "acknowledged" ? /* @__PURE__ */ React.createElement(Done, null) : /* @__PURE__ */ React.createElement(Warning, null),
|
|
264
309
|
className: incident.status === "triggered" ? classes.error : classes.warning
|
|
265
310
|
}
|
|
311
|
+
), /* @__PURE__ */ React.createElement(
|
|
312
|
+
Chip,
|
|
313
|
+
{
|
|
314
|
+
"data-testid": `chip-${incident.urgency}`,
|
|
315
|
+
label: `${incident.urgency} urgency`,
|
|
316
|
+
size: "small",
|
|
317
|
+
variant: "outlined",
|
|
318
|
+
className: incident.urgency === "high" ? classes.highUrgency : classes.lowUrgency
|
|
319
|
+
}
|
|
266
320
|
), incident.title),
|
|
267
321
|
primaryTypographyProps: {
|
|
268
322
|
variant: "body1",
|
|
@@ -276,7 +330,7 @@ const IncidentListItem = ({ incident }) => {
|
|
|
276
330
|
href: incident.html_url,
|
|
277
331
|
target: "_blank",
|
|
278
332
|
rel: "noopener noreferrer",
|
|
279
|
-
|
|
333
|
+
className: classes.smallIconStyle
|
|
280
334
|
},
|
|
281
335
|
/* @__PURE__ */ React.createElement(OpenInBrowserIcon, null)
|
|
282
336
|
))));
|
|
@@ -342,7 +396,7 @@ const Incidents = ({ serviceId, refreshIncidents }) => {
|
|
|
342
396
|
return /* @__PURE__ */ React.createElement(List, { dense: true }, incidents.map((incident, index) => /* @__PURE__ */ React.createElement(IncidentListItem, { key: incident.id + index, incident })));
|
|
343
397
|
};
|
|
344
398
|
|
|
345
|
-
const useStyles$
|
|
399
|
+
const useStyles$7 = makeStyles({
|
|
346
400
|
denseListIcon: {
|
|
347
401
|
marginRight: 0,
|
|
348
402
|
display: "flex",
|
|
@@ -352,11 +406,11 @@ const useStyles$6 = makeStyles({
|
|
|
352
406
|
}
|
|
353
407
|
});
|
|
354
408
|
const EscalationUsersEmptyState = () => {
|
|
355
|
-
const classes = useStyles$
|
|
409
|
+
const classes = useStyles$7();
|
|
356
410
|
return /* @__PURE__ */ React.createElement(ListItem, null, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement("div", { className: classes.denseListIcon }, /* @__PURE__ */ React.createElement(StatusWarning, null))), /* @__PURE__ */ React.createElement(ListItemText, { primary: "No one is on-call. Update the escalation policy." }));
|
|
357
411
|
};
|
|
358
412
|
|
|
359
|
-
const useStyles$
|
|
413
|
+
const useStyles$6 = makeStyles({
|
|
360
414
|
denseListIcon: {
|
|
361
415
|
marginRight: 0,
|
|
362
416
|
display: "flex",
|
|
@@ -366,11 +420,11 @@ const useStyles$5 = makeStyles({
|
|
|
366
420
|
}
|
|
367
421
|
});
|
|
368
422
|
const EscalationUsersForbiddenState = () => {
|
|
369
|
-
const classes = useStyles$
|
|
423
|
+
const classes = useStyles$6();
|
|
370
424
|
return /* @__PURE__ */ React.createElement(ListItem, null, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement("div", { className: classes.denseListIcon }, /* @__PURE__ */ React.createElement(StatusError, null))), /* @__PURE__ */ React.createElement(ListItemText, { primary: "You don't permissions to list on-calls. Check your OAuth token permissions." }));
|
|
371
425
|
};
|
|
372
426
|
|
|
373
|
-
const useStyles$
|
|
427
|
+
const useStyles$5 = makeStyles((theme) => ({
|
|
374
428
|
listItemPrimary: {
|
|
375
429
|
fontWeight: "bold"
|
|
376
430
|
},
|
|
@@ -401,11 +455,17 @@ const useStyles$4 = makeStyles((theme) => ({
|
|
|
401
455
|
},
|
|
402
456
|
smallIconStyle: {
|
|
403
457
|
color: theme.palette.text.primary
|
|
458
|
+
},
|
|
459
|
+
avatarStyle: {
|
|
460
|
+
marginTop: "-20px"
|
|
404
461
|
}
|
|
405
462
|
}));
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
463
|
+
function navigateToEscalationPolicy(url) {
|
|
464
|
+
window.open(url, "_blank");
|
|
465
|
+
}
|
|
466
|
+
const EscalationUser = ({ user, policyUrl, policyName }) => {
|
|
467
|
+
const classes = useStyles$5();
|
|
468
|
+
return /* @__PURE__ */ React.createElement(ListItem, null, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement(Avatar, { alt: user.name, src: user.avatar_url, className: classes.avatarStyle })), /* @__PURE__ */ React.createElement(
|
|
409
469
|
ListItemText,
|
|
410
470
|
{
|
|
411
471
|
primary: /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, { className: classes.listItemPrimary }, user.name), /* @__PURE__ */ React.createElement(
|
|
@@ -420,12 +480,13 @@ const EscalationUser = ({ user }) => {
|
|
|
420
480
|
IconButton,
|
|
421
481
|
{
|
|
422
482
|
"aria-label": "open-service-in-browser",
|
|
483
|
+
onClick: () => navigateToEscalationPolicy(policyUrl),
|
|
423
484
|
className: classes.buttonStyle
|
|
424
485
|
},
|
|
425
|
-
/* @__PURE__ */ React.createElement("span", { className: classes.containerStyle }, /* @__PURE__ */ React.createElement(NotificationsIcon, { className: classes.iconStyle }),
|
|
486
|
+
/* @__PURE__ */ React.createElement("span", { className: classes.containerStyle }, /* @__PURE__ */ React.createElement(NotificationsIcon, { className: classes.iconStyle }), policyName)
|
|
426
487
|
)
|
|
427
488
|
}
|
|
428
|
-
), /* @__PURE__ */ React.createElement(ListItemSecondaryAction, null, /* @__PURE__ */ React.createElement(Tooltip, { title: "
|
|
489
|
+
), /* @__PURE__ */ React.createElement(ListItemSecondaryAction, null, /* @__PURE__ */ React.createElement(Tooltip, { title: "Open user in PagerDuty", placement: "top" }, /* @__PURE__ */ React.createElement(
|
|
429
490
|
IconButton,
|
|
430
491
|
{
|
|
431
492
|
href: user.html_url,
|
|
@@ -437,7 +498,7 @@ const EscalationUser = ({ user }) => {
|
|
|
437
498
|
))));
|
|
438
499
|
};
|
|
439
500
|
|
|
440
|
-
const EscalationPolicy = ({ policyId }) => {
|
|
501
|
+
const EscalationPolicy = ({ policyId, policyUrl, policyName }) => {
|
|
441
502
|
const api = useApi(pagerDutyApiRef);
|
|
442
503
|
const {
|
|
443
504
|
value: users,
|
|
@@ -458,7 +519,7 @@ const EscalationPolicy = ({ policyId }) => {
|
|
|
458
519
|
if (!(users == null ? void 0 : users.length)) {
|
|
459
520
|
return /* @__PURE__ */ React.createElement(EscalationUsersEmptyState, null);
|
|
460
521
|
}
|
|
461
|
-
return /* @__PURE__ */ React.createElement(List, { dense: true, subheader: /* @__PURE__ */ React.createElement(ListSubheader, null, "ON CALL") }, users.map((user, index) => /* @__PURE__ */ React.createElement(EscalationUser, { key: index, user })));
|
|
522
|
+
return /* @__PURE__ */ React.createElement(List, { dense: true, subheader: /* @__PURE__ */ React.createElement(ListSubheader, null, "ON CALL"), style: { marginLeft: "-15px" } }, users.map((user, index) => /* @__PURE__ */ React.createElement(EscalationUser, { key: index, user, policyUrl, policyName })));
|
|
462
523
|
};
|
|
463
524
|
|
|
464
525
|
const MissingTokenError = () => /* @__PURE__ */ React.createElement(
|
|
@@ -497,91 +558,7 @@ const ServiceNotFoundError = () => /* @__PURE__ */ React.createElement(
|
|
|
497
558
|
}
|
|
498
559
|
);
|
|
499
560
|
|
|
500
|
-
const
|
|
501
|
-
showDialog,
|
|
502
|
-
handleDialog,
|
|
503
|
-
onIncidentCreated,
|
|
504
|
-
name,
|
|
505
|
-
integrationKey
|
|
506
|
-
}) => {
|
|
507
|
-
const alertApi = useApi(alertApiRef);
|
|
508
|
-
const identityApi = useApi(identityApiRef);
|
|
509
|
-
const api = useApi(pagerDutyApiRef);
|
|
510
|
-
const [description, setDescription] = useState("");
|
|
511
|
-
const [{ value, loading, error }, handleTriggerAlarm] = useAsyncFn(
|
|
512
|
-
async (descriptions) => {
|
|
513
|
-
const { userEntityRef } = await identityApi.getBackstageIdentity();
|
|
514
|
-
const { name: userName } = parseEntityRef(userEntityRef, {
|
|
515
|
-
defaultKind: "User",
|
|
516
|
-
defaultNamespace: DEFAULT_NAMESPACE
|
|
517
|
-
});
|
|
518
|
-
return await api.triggerAlarm({
|
|
519
|
-
integrationKey,
|
|
520
|
-
source: window.location.toString(),
|
|
521
|
-
description: descriptions,
|
|
522
|
-
userName
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
);
|
|
526
|
-
const descriptionChanged = (event) => {
|
|
527
|
-
setDescription(event.target.value);
|
|
528
|
-
};
|
|
529
|
-
useEffect(() => {
|
|
530
|
-
if (value) {
|
|
531
|
-
(async () => {
|
|
532
|
-
alertApi.post({
|
|
533
|
-
message: `Alarm successfully triggered`
|
|
534
|
-
});
|
|
535
|
-
handleDialog();
|
|
536
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
537
|
-
onIncidentCreated == null ? void 0 : onIncidentCreated();
|
|
538
|
-
})();
|
|
539
|
-
}
|
|
540
|
-
}, [value, alertApi, handleDialog, onIncidentCreated]);
|
|
541
|
-
if (error) {
|
|
542
|
-
alertApi.post({
|
|
543
|
-
message: `Failed to trigger alarm. ${error.message}`,
|
|
544
|
-
severity: "error"
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
return /* @__PURE__ */ React.createElement(Dialog, { maxWidth: "md", open: showDialog, onClose: handleDialog, fullWidth: true }, /* @__PURE__ */ React.createElement(DialogTitle, null, "This action will trigger an incident for ", /* @__PURE__ */ React.createElement("strong", null, '"', name, '"'), "."), /* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(Alert, { severity: "info" }, /* @__PURE__ */ React.createElement(Typography, { variant: "body1", align: "justify" }, `If the issue you are seeing does not need urgent attention, please get in touch with the responsible team using their preferred communications channel. You can find information about the owner of this entity in the "About" card. If the issue is urgent, please don't hesitate to trigger the alert.`)), /* @__PURE__ */ React.createElement(
|
|
548
|
-
Typography,
|
|
549
|
-
{
|
|
550
|
-
variant: "body1",
|
|
551
|
-
style: { marginTop: "1em" },
|
|
552
|
-
gutterBottom: true,
|
|
553
|
-
align: "justify"
|
|
554
|
-
},
|
|
555
|
-
"Please describe the problem you want to report. Be as descriptive as possible. Your signed in user and a reference to the current page will automatically be amended to the alarm so that the receiver can reach out to you if necessary."
|
|
556
|
-
), /* @__PURE__ */ React.createElement(
|
|
557
|
-
TextField,
|
|
558
|
-
{
|
|
559
|
-
inputProps: { "data-testid": "trigger-input" },
|
|
560
|
-
id: "description",
|
|
561
|
-
multiline: true,
|
|
562
|
-
fullWidth: true,
|
|
563
|
-
rows: "4",
|
|
564
|
-
margin: "normal",
|
|
565
|
-
label: "Problem description",
|
|
566
|
-
variant: "outlined",
|
|
567
|
-
onChange: descriptionChanged
|
|
568
|
-
}
|
|
569
|
-
)), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(
|
|
570
|
-
Button,
|
|
571
|
-
{
|
|
572
|
-
"data-testid": "trigger-button",
|
|
573
|
-
id: "trigger",
|
|
574
|
-
color: "secondary",
|
|
575
|
-
disabled: !description || loading,
|
|
576
|
-
variant: "contained",
|
|
577
|
-
onClick: () => handleTriggerAlarm(description),
|
|
578
|
-
endIcon: loading && /* @__PURE__ */ React.createElement(CircularProgress, { size: 16 })
|
|
579
|
-
},
|
|
580
|
-
"Trigger Incident"
|
|
581
|
-
), /* @__PURE__ */ React.createElement(Button, { id: "close", color: "primary", onClick: handleDialog }, "Close")));
|
|
582
|
-
};
|
|
583
|
-
|
|
584
|
-
const useStyles$3 = makeStyles({
|
|
561
|
+
const useStyles$4 = makeStyles((theme) => ({
|
|
585
562
|
denseListIcon: {
|
|
586
563
|
marginRight: 0,
|
|
587
564
|
display: "flex",
|
|
@@ -591,10 +568,17 @@ const useStyles$3 = makeStyles({
|
|
|
591
568
|
},
|
|
592
569
|
listItemPrimary: {
|
|
593
570
|
fontWeight: "bold"
|
|
571
|
+
},
|
|
572
|
+
smallExternalLinkIconStyle: {
|
|
573
|
+
color: theme.palette.text.primary
|
|
574
|
+
},
|
|
575
|
+
smallIconStyle: {
|
|
576
|
+
color: theme.palette.text.primary,
|
|
577
|
+
marginRight: "-20px"
|
|
594
578
|
}
|
|
595
|
-
});
|
|
579
|
+
}));
|
|
596
580
|
const ChangeEventListItem = ({ changeEvent }) => {
|
|
597
|
-
const classes = useStyles$
|
|
581
|
+
const classes = useStyles$4();
|
|
598
582
|
const duration = (/* @__PURE__ */ new Date()).getTime() - new Date(changeEvent.timestamp).getTime();
|
|
599
583
|
const changedAt = DateTime.local().minus(Duration.fromMillis(duration)).toRelative({ locale: "en" });
|
|
600
584
|
let externalLinkElem;
|
|
@@ -605,9 +589,9 @@ const ChangeEventListItem = ({ changeEvent }) => {
|
|
|
605
589
|
{
|
|
606
590
|
component: Link,
|
|
607
591
|
to: changeEvent.links[0].href,
|
|
608
|
-
|
|
592
|
+
className: classes.smallExternalLinkIconStyle
|
|
609
593
|
},
|
|
610
|
-
/* @__PURE__ */ React.createElement(
|
|
594
|
+
/* @__PURE__ */ React.createElement(LinkIcon, null)
|
|
611
595
|
));
|
|
612
596
|
}
|
|
613
597
|
return /* @__PURE__ */ React.createElement(ListItem, { dense: true, key: changeEvent.id }, /* @__PURE__ */ React.createElement(
|
|
@@ -625,7 +609,7 @@ const ChangeEventListItem = ({ changeEvent }) => {
|
|
|
625
609
|
{
|
|
626
610
|
component: Link,
|
|
627
611
|
to: changeEvent.html_url,
|
|
628
|
-
|
|
612
|
+
className: classes.smallIconStyle
|
|
629
613
|
},
|
|
630
614
|
/* @__PURE__ */ React.createElement(OpenInBrowserIcon, null)
|
|
631
615
|
))));
|
|
@@ -708,7 +692,91 @@ function usePagerdutyEntity() {
|
|
|
708
692
|
return getPagerDutyEntity(entity);
|
|
709
693
|
}
|
|
710
694
|
|
|
711
|
-
const
|
|
695
|
+
const TriggerDialog = ({
|
|
696
|
+
showDialog,
|
|
697
|
+
handleDialog,
|
|
698
|
+
onIncidentCreated,
|
|
699
|
+
name,
|
|
700
|
+
integrationKey
|
|
701
|
+
}) => {
|
|
702
|
+
const alertApi = useApi(alertApiRef);
|
|
703
|
+
const identityApi = useApi(identityApiRef);
|
|
704
|
+
const api = useApi(pagerDutyApiRef);
|
|
705
|
+
const [description, setDescription] = useState("");
|
|
706
|
+
const [{ value, loading, error }, handleTriggerAlarm] = useAsyncFn(
|
|
707
|
+
async (descriptions) => {
|
|
708
|
+
const { userEntityRef } = await identityApi.getBackstageIdentity();
|
|
709
|
+
const { name: userName } = parseEntityRef(userEntityRef, {
|
|
710
|
+
defaultKind: "User",
|
|
711
|
+
defaultNamespace: DEFAULT_NAMESPACE
|
|
712
|
+
});
|
|
713
|
+
return await api.triggerAlarm({
|
|
714
|
+
integrationKey,
|
|
715
|
+
source: window.location.toString(),
|
|
716
|
+
description: descriptions,
|
|
717
|
+
userName
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
);
|
|
721
|
+
const descriptionChanged = (event) => {
|
|
722
|
+
setDescription(event.target.value);
|
|
723
|
+
};
|
|
724
|
+
useEffect(() => {
|
|
725
|
+
if (value) {
|
|
726
|
+
(async () => {
|
|
727
|
+
alertApi.post({
|
|
728
|
+
message: `Alarm successfully triggered`
|
|
729
|
+
});
|
|
730
|
+
handleDialog();
|
|
731
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
732
|
+
onIncidentCreated == null ? void 0 : onIncidentCreated();
|
|
733
|
+
})();
|
|
734
|
+
}
|
|
735
|
+
}, [value, alertApi, handleDialog, onIncidentCreated]);
|
|
736
|
+
if (error) {
|
|
737
|
+
alertApi.post({
|
|
738
|
+
message: `Failed to trigger alarm. ${error.message}`,
|
|
739
|
+
severity: "error"
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
return /* @__PURE__ */ React.createElement(Dialog, { maxWidth: "md", open: showDialog, onClose: handleDialog, fullWidth: true }, /* @__PURE__ */ React.createElement(DialogTitle, null, "This action will trigger an incident for ", /* @__PURE__ */ React.createElement("strong", null, '"', name, '"'), "."), /* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(Alert, { severity: "info" }, /* @__PURE__ */ React.createElement(Typography, { variant: "body1", align: "justify" }, `If the issue you are seeing does not need urgent attention, please get in touch with the responsible team using their preferred communications channel. You can find information about the owner of this entity in the "About" card. If the issue is urgent, please don't hesitate to trigger the alert.`)), /* @__PURE__ */ React.createElement(
|
|
743
|
+
Typography,
|
|
744
|
+
{
|
|
745
|
+
variant: "body1",
|
|
746
|
+
style: { marginTop: "1em" },
|
|
747
|
+
gutterBottom: true,
|
|
748
|
+
align: "justify"
|
|
749
|
+
},
|
|
750
|
+
"Please describe the problem you want to report. Be as descriptive as possible. Your signed in user and a reference to the current page will automatically be amended to the alarm so that the receiver can reach out to you if necessary."
|
|
751
|
+
), /* @__PURE__ */ React.createElement(
|
|
752
|
+
TextField,
|
|
753
|
+
{
|
|
754
|
+
inputProps: { "data-testid": "trigger-input" },
|
|
755
|
+
id: "description",
|
|
756
|
+
multiline: true,
|
|
757
|
+
fullWidth: true,
|
|
758
|
+
rows: "4",
|
|
759
|
+
margin: "normal",
|
|
760
|
+
label: "Problem description",
|
|
761
|
+
variant: "outlined",
|
|
762
|
+
onChange: descriptionChanged
|
|
763
|
+
}
|
|
764
|
+
)), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(
|
|
765
|
+
Button,
|
|
766
|
+
{
|
|
767
|
+
"data-testid": "trigger-button",
|
|
768
|
+
id: "trigger",
|
|
769
|
+
color: "secondary",
|
|
770
|
+
disabled: !description || loading,
|
|
771
|
+
variant: "contained",
|
|
772
|
+
onClick: () => handleTriggerAlarm(description),
|
|
773
|
+
endIcon: loading && /* @__PURE__ */ React.createElement(CircularProgress, { size: 16 })
|
|
774
|
+
},
|
|
775
|
+
"Trigger Incident"
|
|
776
|
+
), /* @__PURE__ */ React.createElement(Button, { id: "close", color: "primary", onClick: handleDialog }, "Close")));
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
const useStyles$3 = makeStyles((theme) => ({
|
|
712
780
|
buttonStyle: {
|
|
713
781
|
color: theme.palette.text.primary,
|
|
714
782
|
"&:hover": {
|
|
@@ -727,8 +795,8 @@ const useStyles$2 = makeStyles((theme) => ({
|
|
|
727
795
|
marginBottom: "-10px"
|
|
728
796
|
}
|
|
729
797
|
}));
|
|
730
|
-
function TriggerIncidentButton() {
|
|
731
|
-
const { buttonStyle, containerStyle, iconStyle } = useStyles$
|
|
798
|
+
function TriggerIncidentButton({ handleRefresh }) {
|
|
799
|
+
const { buttonStyle, containerStyle, iconStyle } = useStyles$3();
|
|
732
800
|
const { integrationKey, name } = usePagerdutyEntity();
|
|
733
801
|
const [dialogShown, setDialogShown] = useState(false);
|
|
734
802
|
const showDialog = useCallback(() => {
|
|
@@ -746,19 +814,20 @@ function TriggerIncidentButton() {
|
|
|
746
814
|
className: disabled ? "" : buttonStyle,
|
|
747
815
|
disabled
|
|
748
816
|
},
|
|
749
|
-
/* @__PURE__ */ React.createElement("div", { className: containerStyle }, /* @__PURE__ */ React.createElement(AddAlert, { className: iconStyle }), /* @__PURE__ */ React.createElement("p", null, "Create
|
|
817
|
+
/* @__PURE__ */ React.createElement("div", { className: containerStyle }, /* @__PURE__ */ React.createElement(AddAlert, { className: iconStyle }), /* @__PURE__ */ React.createElement("p", null, "Create new incident"))
|
|
750
818
|
), integrationKey && /* @__PURE__ */ React.createElement(
|
|
751
819
|
TriggerDialog,
|
|
752
820
|
{
|
|
753
821
|
showDialog: dialogShown,
|
|
754
822
|
handleDialog: hideDialog,
|
|
755
823
|
integrationKey,
|
|
756
|
-
name
|
|
824
|
+
name,
|
|
825
|
+
onIncidentCreated: handleRefresh
|
|
757
826
|
}
|
|
758
827
|
));
|
|
759
828
|
}
|
|
760
829
|
|
|
761
|
-
const useStyles$
|
|
830
|
+
const useStyles$2 = makeStyles((theme) => ({
|
|
762
831
|
buttonStyle: {
|
|
763
832
|
color: theme.palette.text.primary,
|
|
764
833
|
"&:hover": {
|
|
@@ -778,7 +847,7 @@ const useStyles$1 = makeStyles((theme) => ({
|
|
|
778
847
|
}
|
|
779
848
|
}));
|
|
780
849
|
function OpenServiceButton(props) {
|
|
781
|
-
const { buttonStyle, containerStyle, iconStyle } = useStyles$
|
|
850
|
+
const { buttonStyle, containerStyle, iconStyle } = useStyles$2();
|
|
782
851
|
function navigateToService() {
|
|
783
852
|
window.open(props.serviceUrl, "_blank");
|
|
784
853
|
}
|
|
@@ -793,20 +862,228 @@ function OpenServiceButton(props) {
|
|
|
793
862
|
));
|
|
794
863
|
}
|
|
795
864
|
|
|
865
|
+
function labelFromStatus(status) {
|
|
866
|
+
let label;
|
|
867
|
+
switch (status) {
|
|
868
|
+
case "active":
|
|
869
|
+
label = "OK";
|
|
870
|
+
break;
|
|
871
|
+
case "warning":
|
|
872
|
+
label = "ACTIVE";
|
|
873
|
+
break;
|
|
874
|
+
case "critical":
|
|
875
|
+
label = "ALARM";
|
|
876
|
+
break;
|
|
877
|
+
case "maintenance":
|
|
878
|
+
label = "MAINTENANCE";
|
|
879
|
+
break;
|
|
880
|
+
case "disabled":
|
|
881
|
+
label = "DISABLED";
|
|
882
|
+
break;
|
|
883
|
+
default:
|
|
884
|
+
label = "OK";
|
|
885
|
+
break;
|
|
886
|
+
}
|
|
887
|
+
return label;
|
|
888
|
+
}
|
|
889
|
+
function colorFromStatus(theme, status) {
|
|
890
|
+
let color;
|
|
891
|
+
switch (status) {
|
|
892
|
+
case "active":
|
|
893
|
+
color = theme.palette.success.main;
|
|
894
|
+
break;
|
|
895
|
+
case "warning":
|
|
896
|
+
color = theme.palette.warningBackground;
|
|
897
|
+
break;
|
|
898
|
+
case "critical":
|
|
899
|
+
color = theme.palette.error.main;
|
|
900
|
+
break;
|
|
901
|
+
case "maintenance":
|
|
902
|
+
color = "#ebdc00";
|
|
903
|
+
break;
|
|
904
|
+
case "disabled":
|
|
905
|
+
color = "#A9A9A9";
|
|
906
|
+
break;
|
|
907
|
+
default:
|
|
908
|
+
color = theme.palette.success.main;
|
|
909
|
+
break;
|
|
910
|
+
}
|
|
911
|
+
return color;
|
|
912
|
+
}
|
|
913
|
+
function StatusCard({ serviceId, refreshStatus }) {
|
|
914
|
+
const api = useApi(pagerDutyApiRef);
|
|
915
|
+
const [{ value: status, loading, error }, getStatus] = useAsyncFn$1(
|
|
916
|
+
async () => {
|
|
917
|
+
const { service: foundService } = await api.getServiceById(serviceId);
|
|
918
|
+
return foundService.status;
|
|
919
|
+
}
|
|
920
|
+
);
|
|
921
|
+
const useStyles = makeStyles$1((theme) => ({
|
|
922
|
+
cardStyle: {
|
|
923
|
+
height: "120px",
|
|
924
|
+
display: "flex",
|
|
925
|
+
alignItems: "center",
|
|
926
|
+
justifyContent: "center",
|
|
927
|
+
backgroundColor: status !== void 0 ? colorFromStatus(theme, status) : colorFromStatus(theme, "active"),
|
|
928
|
+
marginRight: "10px"
|
|
929
|
+
},
|
|
930
|
+
largeTextStyle: {
|
|
931
|
+
color: "white",
|
|
932
|
+
fontWeight: "bold",
|
|
933
|
+
fontSize: "20px",
|
|
934
|
+
wordWrap: "break-word"
|
|
935
|
+
}
|
|
936
|
+
}));
|
|
937
|
+
const { cardStyle, largeTextStyle } = useStyles();
|
|
938
|
+
useEffect(() => {
|
|
939
|
+
getStatus();
|
|
940
|
+
}, [refreshStatus, getStatus]);
|
|
941
|
+
if (error) {
|
|
942
|
+
if (error.message.includes("Forbidden")) {
|
|
943
|
+
return /* @__PURE__ */ React.createElement("p", null, "forbidden");
|
|
944
|
+
}
|
|
945
|
+
return /* @__PURE__ */ React.createElement(Alert$1, { severity: "error" }, "Error encountered while fetching information. ", error.message);
|
|
946
|
+
}
|
|
947
|
+
if (loading) {
|
|
948
|
+
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
949
|
+
}
|
|
950
|
+
if (!status) {
|
|
951
|
+
return /* @__PURE__ */ React.createElement("p", null, "not found");
|
|
952
|
+
}
|
|
953
|
+
return /* @__PURE__ */ React.createElement(Card, { className: cardStyle }, status !== void 0 ? /* @__PURE__ */ React.createElement(Typography, { className: largeTextStyle }, labelFromStatus(status)) : /* @__PURE__ */ React.createElement(Typography, { className: largeTextStyle }, "Unable to get status"));
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
function colorFromPercentage(theme, percentage) {
|
|
957
|
+
if (percentage < 0.5) {
|
|
958
|
+
return theme.palette.error.main;
|
|
959
|
+
} else if (percentage < 0.8) {
|
|
960
|
+
return theme.palette.warning.main;
|
|
961
|
+
}
|
|
962
|
+
return theme.palette.success.main;
|
|
963
|
+
}
|
|
964
|
+
function ServiceStandardsCard({ total, completed }) {
|
|
965
|
+
const useStyles = makeStyles((theme) => ({
|
|
966
|
+
cardStyle: {
|
|
967
|
+
height: "120px",
|
|
968
|
+
display: "grid",
|
|
969
|
+
gridTemplateRows: "1fr auto auto",
|
|
970
|
+
backgroundColor: "rgba(0, 0, 0, 0.03)"
|
|
971
|
+
},
|
|
972
|
+
containerStyle: {
|
|
973
|
+
display: "flex",
|
|
974
|
+
justifyContent: "center"
|
|
975
|
+
},
|
|
976
|
+
largeTextStyle: {
|
|
977
|
+
fontSize: "50px",
|
|
978
|
+
color: completed !== void 0 && total !== void 0 ? colorFromPercentage(theme, completed / total) : colorFromPercentage(theme, 0),
|
|
979
|
+
alignSelf: "center",
|
|
980
|
+
justifyContent: "center"
|
|
981
|
+
},
|
|
982
|
+
smallTextStyle: {
|
|
983
|
+
color: theme.palette.textSubtle,
|
|
984
|
+
fontSize: "14px",
|
|
985
|
+
fontWeight: "bold",
|
|
986
|
+
alignSelf: "center",
|
|
987
|
+
justifyContent: "center",
|
|
988
|
+
marginLeft: "-2px",
|
|
989
|
+
marginTop: "25px"
|
|
990
|
+
}
|
|
991
|
+
}));
|
|
992
|
+
const BorderLinearProgress = withStyles((theme) => ({
|
|
993
|
+
root: {
|
|
994
|
+
height: 10,
|
|
995
|
+
borderRadius: 5,
|
|
996
|
+
margin: 5
|
|
997
|
+
},
|
|
998
|
+
colorPrimary: {
|
|
999
|
+
backgroundColor: theme.palette.grey[theme.palette.type === "light" ? 200 : 700]
|
|
1000
|
+
},
|
|
1001
|
+
bar: {
|
|
1002
|
+
borderRadius: 5,
|
|
1003
|
+
backgroundColor: completed !== void 0 && total !== void 0 ? colorFromPercentage(theme, completed / total) : colorFromPercentage(theme, 0)
|
|
1004
|
+
}
|
|
1005
|
+
}))(LinearProgress);
|
|
1006
|
+
const { cardStyle, containerStyle, largeTextStyle, smallTextStyle } = useStyles();
|
|
1007
|
+
return /* @__PURE__ */ React.createElement(Card, { className: cardStyle }, completed !== void 0 && total !== void 0 ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: containerStyle }, /* @__PURE__ */ React.createElement(Typography, { className: largeTextStyle }, completed), /* @__PURE__ */ React.createElement(Typography, { className: smallTextStyle }, "/", total)), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(
|
|
1008
|
+
BorderLinearProgress,
|
|
1009
|
+
{
|
|
1010
|
+
variant: "determinate",
|
|
1011
|
+
value: completed / total * 100
|
|
1012
|
+
}
|
|
1013
|
+
))) : /* @__PURE__ */ React.createElement("div", { className: containerStyle }, /* @__PURE__ */ React.createElement(Typography, { className: largeTextStyle }, "Unable to retrieve Scores")));
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
function IncidentCounterCard({ count, label, color }) {
|
|
1017
|
+
const textColor = color && validateColor(color) ? color : "black";
|
|
1018
|
+
const useStyles = makeStyles(() => ({
|
|
1019
|
+
cardStyle: {
|
|
1020
|
+
marginRight: "10px",
|
|
1021
|
+
height: "120px",
|
|
1022
|
+
display: "flex",
|
|
1023
|
+
alignItems: "center",
|
|
1024
|
+
justifyContent: "center",
|
|
1025
|
+
backgroundColor: "rgba(0, 0, 0, 0.03)"
|
|
1026
|
+
},
|
|
1027
|
+
largeTextStyle: {
|
|
1028
|
+
color: textColor,
|
|
1029
|
+
fontSize: "30px",
|
|
1030
|
+
marginTop: "-10px"
|
|
1031
|
+
},
|
|
1032
|
+
smallTextStyle: {
|
|
1033
|
+
color: textColor,
|
|
1034
|
+
fontWeight: "bold",
|
|
1035
|
+
fontSize: "10px",
|
|
1036
|
+
marginTop: "-5px",
|
|
1037
|
+
textTransform: "uppercase",
|
|
1038
|
+
flexWrap: "wrap"
|
|
1039
|
+
}
|
|
1040
|
+
}));
|
|
1041
|
+
const { cardStyle, largeTextStyle, smallTextStyle } = useStyles();
|
|
1042
|
+
return /* @__PURE__ */ React.createElement(Card, { className: cardStyle }, /* @__PURE__ */ React.createElement(Typography, { className: largeTextStyle }, count), /* @__PURE__ */ React.createElement(Typography, { className: smallTextStyle }, label));
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
const useStyles$1 = makeStyles$1(
|
|
1046
|
+
(theme) => createStyles({
|
|
1047
|
+
overviewHeaderTextStyle: {
|
|
1048
|
+
fontSize: "14px",
|
|
1049
|
+
fontWeight: 500,
|
|
1050
|
+
color: theme.palette.type === "light" ? "rgba(0, 0, 0, 0.54)" : "rgba(255, 255, 255, 0.7)"
|
|
1051
|
+
},
|
|
1052
|
+
headerStyle: {
|
|
1053
|
+
marginRight: "1em"
|
|
1054
|
+
},
|
|
1055
|
+
overviewHeaderContainerStyle: {
|
|
1056
|
+
display: "flex",
|
|
1057
|
+
margin: "15px",
|
|
1058
|
+
marginBottom: "20px"
|
|
1059
|
+
},
|
|
1060
|
+
overviewCardsContainerStyle: {
|
|
1061
|
+
display: "flex",
|
|
1062
|
+
margin: "15px",
|
|
1063
|
+
marginTop: "-15px"
|
|
1064
|
+
},
|
|
1065
|
+
incidentMetricsContainerStyle: {
|
|
1066
|
+
display: "flex",
|
|
1067
|
+
height: "100%",
|
|
1068
|
+
justifyContent: "center",
|
|
1069
|
+
columnSpan: "all"
|
|
1070
|
+
}
|
|
1071
|
+
})
|
|
1072
|
+
);
|
|
796
1073
|
const BasicCard = ({ children }) => /* @__PURE__ */ React.createElement(InfoCard, { title: "PagerDuty" }, children);
|
|
797
1074
|
const PagerDutyCard$1 = (props) => {
|
|
1075
|
+
var _a, _b;
|
|
1076
|
+
const classes = useStyles$1();
|
|
798
1077
|
const theme = useTheme();
|
|
799
|
-
const { readOnly, disableChangeEvents
|
|
1078
|
+
const { readOnly, disableChangeEvents } = props;
|
|
800
1079
|
const api = useApi(pagerDutyApiRef);
|
|
801
1080
|
const [refreshIncidents, setRefreshIncidents] = useState(false);
|
|
802
1081
|
const [refreshChangeEvents, setRefreshChangeEvents] = useState(false);
|
|
803
|
-
const [
|
|
804
|
-
const hideDialog = useCallback(() => {
|
|
805
|
-
setDialogShown(false);
|
|
806
|
-
}, [setDialogShown]);
|
|
1082
|
+
const [refreshStatus, setRefreshStatus] = useState(false);
|
|
807
1083
|
const handleRefresh = useCallback(() => {
|
|
808
1084
|
setRefreshIncidents((x) => !x);
|
|
809
1085
|
setRefreshChangeEvents((x) => !x);
|
|
1086
|
+
setRefreshStatus((x) => !x);
|
|
810
1087
|
}, []);
|
|
811
1088
|
const {
|
|
812
1089
|
value: service,
|
|
@@ -816,13 +1093,18 @@ const PagerDutyCard$1 = (props) => {
|
|
|
816
1093
|
const { service: foundService } = await api.getServiceByPagerDutyEntity(
|
|
817
1094
|
props
|
|
818
1095
|
);
|
|
819
|
-
|
|
1096
|
+
const { standards: serviceStandards } = await api.getServiceStandardsByServiceId(foundService.id);
|
|
1097
|
+
const result = {
|
|
820
1098
|
id: foundService.id,
|
|
821
1099
|
name: foundService.name,
|
|
822
1100
|
url: foundService.html_url,
|
|
823
1101
|
policyId: foundService.escalation_policy.id,
|
|
824
|
-
policyLink: foundService.escalation_policy.html_url
|
|
1102
|
+
policyLink: foundService.escalation_policy.html_url,
|
|
1103
|
+
policyName: foundService.escalation_policy.name,
|
|
1104
|
+
status: foundService.status,
|
|
1105
|
+
standardsScore: serviceStandards.score
|
|
825
1106
|
};
|
|
1107
|
+
return result;
|
|
826
1108
|
}, [props]);
|
|
827
1109
|
if (error) {
|
|
828
1110
|
let errorNode;
|
|
@@ -841,250 +1123,41 @@ const PagerDutyCard$1 = (props) => {
|
|
|
841
1123
|
if (loading) {
|
|
842
1124
|
return /* @__PURE__ */ React.createElement(BasicCard, null, /* @__PURE__ */ React.createElement(Progress, null));
|
|
843
1125
|
}
|
|
844
|
-
const createIncidentDisabled = !integrationKey;
|
|
845
1126
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Card, { "data-testid": "pagerduty-card" }, /* @__PURE__ */ React.createElement(
|
|
846
1127
|
CardHeader,
|
|
847
1128
|
{
|
|
848
|
-
|
|
1129
|
+
className: classes.headerStyle,
|
|
849
1130
|
title: theme.palette.type === "dark" ? /* @__PURE__ */ React.createElement("img", { src: PDWhiteImage, alt: "PagerDuty", height: "35" }) : /* @__PURE__ */ React.createElement("img", { src: PDGreenImage, alt: "PagerDuty", height: "35" }),
|
|
850
|
-
action: !readOnly ? /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(TriggerIncidentButton,
|
|
1131
|
+
action: !readOnly ? /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(TriggerIncidentButton, { handleRefresh }), /* @__PURE__ */ React.createElement(OpenServiceButton, { serviceUrl: service.url })) : /* @__PURE__ */ React.createElement(OpenServiceButton, { serviceUrl: service.url })
|
|
851
1132
|
}
|
|
852
|
-
), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 12,
|
|
853
|
-
|
|
1133
|
+
), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 12, className: classes.overviewHeaderContainerStyle }, /* @__PURE__ */ React.createElement(Grid, { item: true, md: 3 }, /* @__PURE__ */ React.createElement(Typography, { className: classes.overviewHeaderTextStyle }, "STATUS")), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 6 }, /* @__PURE__ */ React.createElement(Typography, { className: classes.overviewHeaderTextStyle }, "INSIGHTS")), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 3 }, /* @__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: 3 }, /* @__PURE__ */ React.createElement(StatusCard, { serviceId: service.id, refreshStatus })), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 6, className: classes.incidentMetricsContainerStyle }, /* @__PURE__ */ React.createElement(Grid, { md: 4 }, /* @__PURE__ */ React.createElement(
|
|
1134
|
+
IncidentCounterCard,
|
|
854
1135
|
{
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
"SERVICE STANDARDS"
|
|
862
|
-
))), /* @__PURE__ */ React.createElement(
|
|
863
|
-
Grid,
|
|
1136
|
+
count: 29,
|
|
1137
|
+
label: "interruptions",
|
|
1138
|
+
color: theme.palette.textSubtle
|
|
1139
|
+
}
|
|
1140
|
+
)), /* @__PURE__ */ React.createElement(Grid, { md: 4 }, /* @__PURE__ */ React.createElement(
|
|
1141
|
+
IncidentCounterCard,
|
|
864
1142
|
{
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
{
|
|
884
|
-
variant: "h3",
|
|
885
|
-
style: { color: "white", fontWeight: "bold" }
|
|
886
|
-
},
|
|
887
|
-
"ALARM"
|
|
888
|
-
),
|
|
889
|
-
/* @__PURE__ */ React.createElement(
|
|
890
|
-
Typography,
|
|
891
|
-
{
|
|
892
|
-
style: {
|
|
893
|
-
alignSelf: "start",
|
|
894
|
-
position: "absolute",
|
|
895
|
-
verticalAlign: "bottom",
|
|
896
|
-
marginTop: "120px",
|
|
897
|
-
marginLeft: "10px",
|
|
898
|
-
color: "white"
|
|
899
|
-
}
|
|
900
|
-
},
|
|
901
|
-
"Last triggered 8 minutes ago"
|
|
902
|
-
)
|
|
903
|
-
)),
|
|
904
|
-
/* @__PURE__ */ React.createElement(
|
|
905
|
-
Grid,
|
|
906
|
-
{
|
|
907
|
-
item: true,
|
|
908
|
-
md: 6,
|
|
909
|
-
style: {
|
|
910
|
-
display: "flex",
|
|
911
|
-
height: "100%",
|
|
912
|
-
justifyContent: "center",
|
|
913
|
-
columnSpan: "all"
|
|
914
|
-
}
|
|
915
|
-
},
|
|
916
|
-
/* @__PURE__ */ React.createElement(Grid, { md: 4, style: { height: "100%" } }, /* @__PURE__ */ React.createElement(
|
|
917
|
-
Card,
|
|
918
|
-
{
|
|
919
|
-
style: {
|
|
920
|
-
marginRight: "10px",
|
|
921
|
-
height: "150px",
|
|
922
|
-
display: "flex",
|
|
923
|
-
alignItems: "center",
|
|
924
|
-
justifyContent: "center"
|
|
925
|
-
}
|
|
926
|
-
},
|
|
927
|
-
/* @__PURE__ */ React.createElement(
|
|
928
|
-
Typography,
|
|
929
|
-
{
|
|
930
|
-
style: {
|
|
931
|
-
color: "red",
|
|
932
|
-
fontSize: "50px"
|
|
933
|
-
}
|
|
934
|
-
},
|
|
935
|
-
"1"
|
|
936
|
-
),
|
|
937
|
-
/* @__PURE__ */ React.createElement(
|
|
938
|
-
Typography,
|
|
939
|
-
{
|
|
940
|
-
style: {
|
|
941
|
-
color: "red",
|
|
942
|
-
fontWeight: "bold",
|
|
943
|
-
fontSize: "10px"
|
|
944
|
-
}
|
|
945
|
-
},
|
|
946
|
-
"TRIGGERED"
|
|
947
|
-
)
|
|
948
|
-
)),
|
|
949
|
-
/* @__PURE__ */ React.createElement(Grid, { md: 4 }, /* @__PURE__ */ React.createElement(
|
|
950
|
-
Card,
|
|
951
|
-
{
|
|
952
|
-
style: {
|
|
953
|
-
marginRight: "10px",
|
|
954
|
-
height: "150px",
|
|
955
|
-
display: "flex",
|
|
956
|
-
alignItems: "center",
|
|
957
|
-
justifyContent: "center"
|
|
958
|
-
}
|
|
959
|
-
},
|
|
960
|
-
/* @__PURE__ */ React.createElement(
|
|
961
|
-
Typography,
|
|
962
|
-
{
|
|
963
|
-
style: {
|
|
964
|
-
color: "orange",
|
|
965
|
-
fontSize: "50px"
|
|
966
|
-
}
|
|
967
|
-
},
|
|
968
|
-
"1"
|
|
969
|
-
),
|
|
970
|
-
/* @__PURE__ */ React.createElement(
|
|
971
|
-
Typography,
|
|
972
|
-
{
|
|
973
|
-
style: {
|
|
974
|
-
color: "orange",
|
|
975
|
-
fontWeight: "bold",
|
|
976
|
-
fontSize: "10px"
|
|
977
|
-
}
|
|
978
|
-
},
|
|
979
|
-
"ACKNOWLEDGED"
|
|
980
|
-
)
|
|
981
|
-
)),
|
|
982
|
-
/* @__PURE__ */ React.createElement(Grid, { md: 4 }, /* @__PURE__ */ React.createElement(
|
|
983
|
-
Card,
|
|
984
|
-
{
|
|
985
|
-
style: {
|
|
986
|
-
marginRight: "10px",
|
|
987
|
-
height: "150px",
|
|
988
|
-
display: "flex",
|
|
989
|
-
alignItems: "center",
|
|
990
|
-
justifyContent: "center"
|
|
991
|
-
}
|
|
992
|
-
},
|
|
993
|
-
/* @__PURE__ */ React.createElement(
|
|
994
|
-
Typography,
|
|
995
|
-
{
|
|
996
|
-
style: {
|
|
997
|
-
color: "green",
|
|
998
|
-
fontSize: "50px"
|
|
999
|
-
}
|
|
1000
|
-
},
|
|
1001
|
-
"43"
|
|
1002
|
-
),
|
|
1003
|
-
/* @__PURE__ */ React.createElement(
|
|
1004
|
-
Typography,
|
|
1005
|
-
{
|
|
1006
|
-
style: {
|
|
1007
|
-
color: "green",
|
|
1008
|
-
fontWeight: "bold",
|
|
1009
|
-
fontSize: "10px"
|
|
1010
|
-
}
|
|
1011
|
-
},
|
|
1012
|
-
"RESOLVED"
|
|
1013
|
-
)
|
|
1014
|
-
))
|
|
1015
|
-
),
|
|
1016
|
-
/* @__PURE__ */ React.createElement(Grid, { item: true, md: 3 }, /* @__PURE__ */ React.createElement(
|
|
1017
|
-
Card,
|
|
1018
|
-
{
|
|
1019
|
-
style: {
|
|
1020
|
-
height: "150px",
|
|
1021
|
-
display: "grid",
|
|
1022
|
-
gridTemplateRows: "1fr auto auto"
|
|
1023
|
-
}
|
|
1024
|
-
},
|
|
1025
|
-
/* @__PURE__ */ React.createElement(
|
|
1026
|
-
"div",
|
|
1027
|
-
{
|
|
1028
|
-
style: {
|
|
1029
|
-
display: "flex",
|
|
1030
|
-
justifyContent: "center",
|
|
1031
|
-
marginTop: "30px"
|
|
1032
|
-
}
|
|
1033
|
-
},
|
|
1034
|
-
/* @__PURE__ */ React.createElement(
|
|
1035
|
-
Typography,
|
|
1036
|
-
{
|
|
1037
|
-
style: {
|
|
1038
|
-
fontSize: "50px",
|
|
1039
|
-
color: "black",
|
|
1040
|
-
fontWeight: "bold",
|
|
1041
|
-
alignSelf: "center",
|
|
1042
|
-
justifyContent: "center"
|
|
1043
|
-
}
|
|
1044
|
-
},
|
|
1045
|
-
"4"
|
|
1046
|
-
),
|
|
1047
|
-
/* @__PURE__ */ React.createElement(
|
|
1048
|
-
Typography,
|
|
1049
|
-
{
|
|
1050
|
-
variant: "body1",
|
|
1051
|
-
style: {
|
|
1052
|
-
color: "black",
|
|
1053
|
-
alignSelf: "center",
|
|
1054
|
-
justifyContent: "center",
|
|
1055
|
-
marginLeft: "1px",
|
|
1056
|
-
marginTop: "20px"
|
|
1057
|
-
}
|
|
1058
|
-
},
|
|
1059
|
-
"/5"
|
|
1060
|
-
)
|
|
1061
|
-
),
|
|
1062
|
-
/* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "row-reverse" } }, /* @__PURE__ */ React.createElement(
|
|
1063
|
-
Typography,
|
|
1064
|
-
{
|
|
1065
|
-
style: {
|
|
1066
|
-
justifyContent: "end",
|
|
1067
|
-
color: "gray",
|
|
1068
|
-
textDecoration: "underline",
|
|
1069
|
-
marginRight: "5px"
|
|
1070
|
-
}
|
|
1071
|
-
},
|
|
1072
|
-
"See service standards"
|
|
1073
|
-
)),
|
|
1074
|
-
/* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(
|
|
1075
|
-
LinearProgress,
|
|
1076
|
-
{
|
|
1077
|
-
variant: "determinate",
|
|
1078
|
-
value: 80,
|
|
1079
|
-
style: {
|
|
1080
|
-
margin: "5px",
|
|
1081
|
-
borderRadius: "10px",
|
|
1082
|
-
height: "10px"
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
))
|
|
1086
|
-
))
|
|
1087
|
-
), /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(TabbedCard, null, /* @__PURE__ */ React.createElement(CardTab, { label: "Incidents" }, /* @__PURE__ */ React.createElement(
|
|
1143
|
+
count: 29,
|
|
1144
|
+
label: "high urgency",
|
|
1145
|
+
color: theme.palette.warning.main
|
|
1146
|
+
}
|
|
1147
|
+
)), /* @__PURE__ */ React.createElement(Grid, { md: 4 }, /* @__PURE__ */ React.createElement(
|
|
1148
|
+
IncidentCounterCard,
|
|
1149
|
+
{
|
|
1150
|
+
count: 32,
|
|
1151
|
+
label: "incidents",
|
|
1152
|
+
color: theme.palette.error.main
|
|
1153
|
+
}
|
|
1154
|
+
))), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 3 }, /* @__PURE__ */ React.createElement(
|
|
1155
|
+
ServiceStandardsCard,
|
|
1156
|
+
{
|
|
1157
|
+
total: (_a = service == null ? void 0 : service.standardsScore) == null ? void 0 : _a.total,
|
|
1158
|
+
completed: (_b = service == null ? void 0 : service.standardsScore) == null ? void 0 : _b.passing
|
|
1159
|
+
}
|
|
1160
|
+
))), /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(TabbedCard, null, /* @__PURE__ */ React.createElement(CardTab, { label: "Incidents" }, /* @__PURE__ */ React.createElement(
|
|
1088
1161
|
Incidents,
|
|
1089
1162
|
{
|
|
1090
1163
|
serviceId: service.id,
|
|
@@ -1096,17 +1169,14 @@ const PagerDutyCard$1 = (props) => {
|
|
|
1096
1169
|
serviceId: service.id,
|
|
1097
1170
|
refreshEvents: refreshChangeEvents
|
|
1098
1171
|
}
|
|
1099
|
-
)) : /* @__PURE__ */ React.createElement(React.Fragment, null)), /* @__PURE__ */ React.createElement(
|
|
1100
|
-
|
|
1172
|
+
)) : /* @__PURE__ */ React.createElement(React.Fragment, null)), /* @__PURE__ */ React.createElement(
|
|
1173
|
+
EscalationPolicy,
|
|
1101
1174
|
{
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
onIncidentCreated: handleRefresh,
|
|
1106
|
-
name,
|
|
1107
|
-
integrationKey
|
|
1175
|
+
policyId: service.policyId,
|
|
1176
|
+
policyUrl: service.policyLink,
|
|
1177
|
+
policyName: service.policyName
|
|
1108
1178
|
}
|
|
1109
|
-
));
|
|
1179
|
+
))));
|
|
1110
1180
|
};
|
|
1111
1181
|
|
|
1112
1182
|
const isPluginApplicableToEntity = (entity) => {
|
|
@@ -1164,7 +1234,7 @@ function TriggerButton(props) {
|
|
|
1164
1234
|
className: disabled ? "" : buttonStyle,
|
|
1165
1235
|
disabled
|
|
1166
1236
|
},
|
|
1167
|
-
integrationKey ? (_a = props.children) != null ? _a : "Create
|
|
1237
|
+
integrationKey ? (_a = props.children) != null ? _a : "Create new incident" : "Missing integration key"
|
|
1168
1238
|
), integrationKey && /* @__PURE__ */ React.createElement(
|
|
1169
1239
|
TriggerDialog,
|
|
1170
1240
|
{
|
|
@@ -1179,4 +1249,4 @@ function TriggerButton(props) {
|
|
|
1179
1249
|
const PagerDutyCard = EntityPagerDutyCard;
|
|
1180
1250
|
|
|
1181
1251
|
export { EntityPagerDutyCard$1 as E, HomePagePagerDutyCard as H, PagerDutyCard$1 as P, TriggerButton as T, UnauthorizedError as U, PagerDutyClient as a, pagerDutyApiRef as b, PagerDutyCard as c, isPluginApplicableToEntity as i, pagerDutyPlugin as p };
|
|
1182
|
-
//# sourceMappingURL=index-
|
|
1252
|
+
//# sourceMappingURL=index-05ed342b.esm.js.map
|