@pagerduty/backstage-plugin 0.9.4-next.1 → 0.9.4-next.11
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-b2ba10a3.esm.js → index-6bae2e1b.esm.js} +10 -7
- package/dist/esm/{index-b2ba10a3.esm.js.map → index-6bae2e1b.esm.js.map} +1 -1
- package/dist/esm/{index-46807363.esm.js → index-90a6424d.esm.js} +482 -383
- package/dist/esm/index-90a6424d.esm.js.map +1 -0
- package/dist/index.d.ts +14 -1
- package/dist/index.esm.js +9 -6
- package/dist/index.esm.js.map +1 -1
- 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,19 @@ 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 InfoIcon from '@material-ui/icons/Info';
|
|
26
|
+
import CheckCircle from '@material-ui/icons/CheckCircle';
|
|
27
|
+
import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked';
|
|
28
|
+
import validateColor from 'validate-color';
|
|
26
29
|
|
|
27
30
|
const PAGERDUTY_INTEGRATION_KEY = "pagerduty.com/integration-key";
|
|
28
31
|
const PAGERDUTY_SERVICE_ID = "pagerduty.com/service-id";
|
|
@@ -82,6 +85,12 @@ class PagerDutyClient {
|
|
|
82
85
|
async getServiceByEntity(entity) {
|
|
83
86
|
return await this.getServiceByPagerDutyEntity(getPagerDutyEntity(entity));
|
|
84
87
|
}
|
|
88
|
+
async getServiceById(serviceId) {
|
|
89
|
+
const url = `${await this.config.discoveryApi.getBaseUrl(
|
|
90
|
+
"pagerduty"
|
|
91
|
+
)}/services/${serviceId}`;
|
|
92
|
+
return await this.findByUrl(url);
|
|
93
|
+
}
|
|
85
94
|
async getIncidentsByServiceId(serviceId) {
|
|
86
95
|
const url = `${await this.config.discoveryApi.getBaseUrl(
|
|
87
96
|
"pagerduty"
|
|
@@ -94,6 +103,12 @@ class PagerDutyClient {
|
|
|
94
103
|
)}/services/${serviceId}/change-events`;
|
|
95
104
|
return await this.findByUrl(url);
|
|
96
105
|
}
|
|
106
|
+
async getServiceStandardsByServiceId(serviceId) {
|
|
107
|
+
const url = `${await this.config.discoveryApi.getBaseUrl(
|
|
108
|
+
"pagerduty"
|
|
109
|
+
)}/services/${serviceId}/standards`;
|
|
110
|
+
return await this.findByUrl(url);
|
|
111
|
+
}
|
|
97
112
|
async getOnCallByPolicyId(policyId) {
|
|
98
113
|
const params = `escalation_policy_ids[]=${policyId}`;
|
|
99
114
|
const url = `${await this.config.discoveryApi.getBaseUrl(
|
|
@@ -194,7 +209,7 @@ const HomePagePagerDutyCard = pagerDutyPlugin.provide(
|
|
|
194
209
|
createCardExtension({
|
|
195
210
|
name: "HomePagePagerDutyCard",
|
|
196
211
|
title: "PagerDuty Homepage Card",
|
|
197
|
-
components: () => import('./index-
|
|
212
|
+
components: () => import('./index-6bae2e1b.esm.js'),
|
|
198
213
|
settings: {
|
|
199
214
|
schema: {
|
|
200
215
|
title: "PagerDuty",
|
|
@@ -218,7 +233,7 @@ const HomePagePagerDutyCard = pagerDutyPlugin.provide(
|
|
|
218
233
|
})
|
|
219
234
|
);
|
|
220
235
|
|
|
221
|
-
const useStyles$
|
|
236
|
+
const useStyles$8 = makeStyles((theme) => ({
|
|
222
237
|
denseListIcon: {
|
|
223
238
|
marginRight: 0,
|
|
224
239
|
display: "flex",
|
|
@@ -230,39 +245,81 @@ const useStyles$7 = makeStyles((theme) => ({
|
|
|
230
245
|
fontWeight: "bold"
|
|
231
246
|
},
|
|
232
247
|
warning: {
|
|
233
|
-
borderColor: theme.palette.
|
|
234
|
-
color:
|
|
248
|
+
borderColor: theme.palette.warning.main,
|
|
249
|
+
color: "#fff",
|
|
250
|
+
backgroundColor: theme.palette.warning.main,
|
|
251
|
+
boxShadow: "0 4px 4px 0 rgba(0,0,0,0.2)",
|
|
252
|
+
textTransform: "uppercase",
|
|
235
253
|
"& *": {
|
|
236
|
-
color:
|
|
254
|
+
color: "#fff"
|
|
237
255
|
}
|
|
238
256
|
},
|
|
239
257
|
error: {
|
|
240
|
-
borderColor: theme.palette.
|
|
241
|
-
color:
|
|
258
|
+
borderColor: theme.palette.error.main,
|
|
259
|
+
color: "#fff",
|
|
260
|
+
backgroundColor: theme.palette.error.main,
|
|
261
|
+
boxShadow: "0 4px 4px 0 rgba(0,0,0,0.2)",
|
|
262
|
+
textTransform: "uppercase",
|
|
242
263
|
"& *": {
|
|
243
|
-
color:
|
|
264
|
+
color: "#fff"
|
|
244
265
|
}
|
|
266
|
+
},
|
|
267
|
+
lowUrgency: {
|
|
268
|
+
borderColor: theme.palette.warning.main,
|
|
269
|
+
color: theme.palette.warning.main,
|
|
270
|
+
backgroundColor: "#fff",
|
|
271
|
+
boxShadow: "0 4px 4px 0 rgba(0,0,0,0.2)",
|
|
272
|
+
textTransform: "uppercase",
|
|
273
|
+
"& *": {
|
|
274
|
+
color: theme.palette.warning.main
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
highUrgency: {
|
|
278
|
+
borderColor: theme.palette.error.main,
|
|
279
|
+
color: theme.palette.error.main,
|
|
280
|
+
backgroundColor: "#fff",
|
|
281
|
+
boxShadow: "0 4px 4px 0 rgba(0,0,0,0.2)",
|
|
282
|
+
textTransform: "uppercase",
|
|
283
|
+
"& *": {
|
|
284
|
+
color: theme.palette.error.main
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
textContainer: {
|
|
288
|
+
display: "flex",
|
|
289
|
+
alignItems: "baseline"
|
|
290
|
+
},
|
|
291
|
+
smallIconStyle: {
|
|
292
|
+
color: theme.palette.text.primary,
|
|
293
|
+
marginRight: "-20px"
|
|
245
294
|
}
|
|
246
295
|
}));
|
|
247
296
|
const IncidentListItem = ({ incident }) => {
|
|
248
297
|
var _a, _b, _c;
|
|
249
|
-
const classes = useStyles$
|
|
298
|
+
const classes = useStyles$8();
|
|
250
299
|
const duration = (/* @__PURE__ */ new Date()).getTime() - new Date(incident.created_at).getTime();
|
|
251
300
|
const createdAt = DateTime.local().minus(Duration.fromMillis(duration)).toRelative({ locale: "en" });
|
|
252
301
|
const user = (_a = incident.assignments[0]) == null ? void 0 : _a.assignee;
|
|
253
302
|
return /* @__PURE__ */ React.createElement(ListItem, { dense: true, key: incident.id }, /* @__PURE__ */ React.createElement(
|
|
254
303
|
ListItemText,
|
|
255
304
|
{
|
|
256
|
-
primary: /* @__PURE__ */ React.createElement(
|
|
305
|
+
primary: /* @__PURE__ */ React.createElement("div", { className: classes.textContainer }, /* @__PURE__ */ React.createElement(
|
|
257
306
|
Chip,
|
|
258
307
|
{
|
|
259
308
|
"data-testid": `chip-${incident.status}`,
|
|
260
309
|
label: incident.status,
|
|
261
310
|
size: "small",
|
|
262
311
|
variant: "outlined",
|
|
263
|
-
icon: incident.status === "acknowledged" ? /* @__PURE__ */ React.createElement(Done, null) : /* @__PURE__ */ React.createElement(Warning, null),
|
|
264
312
|
className: incident.status === "triggered" ? classes.error : classes.warning
|
|
265
313
|
}
|
|
314
|
+
), /* @__PURE__ */ React.createElement(
|
|
315
|
+
Chip,
|
|
316
|
+
{
|
|
317
|
+
"data-testid": `chip-${incident.urgency}`,
|
|
318
|
+
label: `${incident.urgency} urgency`,
|
|
319
|
+
size: "small",
|
|
320
|
+
variant: "outlined",
|
|
321
|
+
className: incident.urgency === "high" ? classes.highUrgency : classes.lowUrgency
|
|
322
|
+
}
|
|
266
323
|
), incident.title),
|
|
267
324
|
primaryTypographyProps: {
|
|
268
325
|
variant: "body1",
|
|
@@ -276,7 +333,7 @@ const IncidentListItem = ({ incident }) => {
|
|
|
276
333
|
href: incident.html_url,
|
|
277
334
|
target: "_blank",
|
|
278
335
|
rel: "noopener noreferrer",
|
|
279
|
-
|
|
336
|
+
className: classes.smallIconStyle
|
|
280
337
|
},
|
|
281
338
|
/* @__PURE__ */ React.createElement(OpenInBrowserIcon, null)
|
|
282
339
|
))));
|
|
@@ -342,7 +399,7 @@ const Incidents = ({ serviceId, refreshIncidents }) => {
|
|
|
342
399
|
return /* @__PURE__ */ React.createElement(List, { dense: true }, incidents.map((incident, index) => /* @__PURE__ */ React.createElement(IncidentListItem, { key: incident.id + index, incident })));
|
|
343
400
|
};
|
|
344
401
|
|
|
345
|
-
const useStyles$
|
|
402
|
+
const useStyles$7 = makeStyles({
|
|
346
403
|
denseListIcon: {
|
|
347
404
|
marginRight: 0,
|
|
348
405
|
display: "flex",
|
|
@@ -352,11 +409,11 @@ const useStyles$6 = makeStyles({
|
|
|
352
409
|
}
|
|
353
410
|
});
|
|
354
411
|
const EscalationUsersEmptyState = () => {
|
|
355
|
-
const classes = useStyles$
|
|
412
|
+
const classes = useStyles$7();
|
|
356
413
|
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
414
|
};
|
|
358
415
|
|
|
359
|
-
const useStyles$
|
|
416
|
+
const useStyles$6 = makeStyles({
|
|
360
417
|
denseListIcon: {
|
|
361
418
|
marginRight: 0,
|
|
362
419
|
display: "flex",
|
|
@@ -366,11 +423,11 @@ const useStyles$5 = makeStyles({
|
|
|
366
423
|
}
|
|
367
424
|
});
|
|
368
425
|
const EscalationUsersForbiddenState = () => {
|
|
369
|
-
const classes = useStyles$
|
|
426
|
+
const classes = useStyles$6();
|
|
370
427
|
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
428
|
};
|
|
372
429
|
|
|
373
|
-
const useStyles$
|
|
430
|
+
const useStyles$5 = makeStyles((theme) => ({
|
|
374
431
|
listItemPrimary: {
|
|
375
432
|
fontWeight: "bold"
|
|
376
433
|
},
|
|
@@ -401,11 +458,17 @@ const useStyles$4 = makeStyles((theme) => ({
|
|
|
401
458
|
},
|
|
402
459
|
smallIconStyle: {
|
|
403
460
|
color: theme.palette.text.primary
|
|
461
|
+
},
|
|
462
|
+
avatarStyle: {
|
|
463
|
+
marginTop: "-20px"
|
|
404
464
|
}
|
|
405
465
|
}));
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
466
|
+
function navigateToEscalationPolicy(url) {
|
|
467
|
+
window.open(url, "_blank");
|
|
468
|
+
}
|
|
469
|
+
const EscalationUser = ({ user, policyUrl, policyName }) => {
|
|
470
|
+
const classes = useStyles$5();
|
|
471
|
+
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
472
|
ListItemText,
|
|
410
473
|
{
|
|
411
474
|
primary: /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, { className: classes.listItemPrimary }, user.name), /* @__PURE__ */ React.createElement(
|
|
@@ -420,12 +483,13 @@ const EscalationUser = ({ user }) => {
|
|
|
420
483
|
IconButton,
|
|
421
484
|
{
|
|
422
485
|
"aria-label": "open-service-in-browser",
|
|
486
|
+
onClick: () => navigateToEscalationPolicy(policyUrl),
|
|
423
487
|
className: classes.buttonStyle
|
|
424
488
|
},
|
|
425
|
-
/* @__PURE__ */ React.createElement("span", { className: classes.containerStyle }, /* @__PURE__ */ React.createElement(NotificationsIcon, { className: classes.iconStyle }),
|
|
489
|
+
/* @__PURE__ */ React.createElement("span", { className: classes.containerStyle }, /* @__PURE__ */ React.createElement(NotificationsIcon, { className: classes.iconStyle }), policyName)
|
|
426
490
|
)
|
|
427
491
|
}
|
|
428
|
-
), /* @__PURE__ */ React.createElement(ListItemSecondaryAction, null, /* @__PURE__ */ React.createElement(Tooltip, { title: "
|
|
492
|
+
), /* @__PURE__ */ React.createElement(ListItemSecondaryAction, null, /* @__PURE__ */ React.createElement(Tooltip, { title: "Open user in PagerDuty", placement: "top" }, /* @__PURE__ */ React.createElement(
|
|
429
493
|
IconButton,
|
|
430
494
|
{
|
|
431
495
|
href: user.html_url,
|
|
@@ -437,7 +501,7 @@ const EscalationUser = ({ user }) => {
|
|
|
437
501
|
))));
|
|
438
502
|
};
|
|
439
503
|
|
|
440
|
-
const EscalationPolicy = ({ policyId }) => {
|
|
504
|
+
const EscalationPolicy = ({ policyId, policyUrl, policyName }) => {
|
|
441
505
|
const api = useApi(pagerDutyApiRef);
|
|
442
506
|
const {
|
|
443
507
|
value: users,
|
|
@@ -458,7 +522,7 @@ const EscalationPolicy = ({ policyId }) => {
|
|
|
458
522
|
if (!(users == null ? void 0 : users.length)) {
|
|
459
523
|
return /* @__PURE__ */ React.createElement(EscalationUsersEmptyState, null);
|
|
460
524
|
}
|
|
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 })));
|
|
525
|
+
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
526
|
};
|
|
463
527
|
|
|
464
528
|
const MissingTokenError = () => /* @__PURE__ */ React.createElement(
|
|
@@ -497,91 +561,7 @@ const ServiceNotFoundError = () => /* @__PURE__ */ React.createElement(
|
|
|
497
561
|
}
|
|
498
562
|
);
|
|
499
563
|
|
|
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({
|
|
564
|
+
const useStyles$4 = makeStyles((theme) => ({
|
|
585
565
|
denseListIcon: {
|
|
586
566
|
marginRight: 0,
|
|
587
567
|
display: "flex",
|
|
@@ -591,10 +571,17 @@ const useStyles$3 = makeStyles({
|
|
|
591
571
|
},
|
|
592
572
|
listItemPrimary: {
|
|
593
573
|
fontWeight: "bold"
|
|
574
|
+
},
|
|
575
|
+
smallExternalLinkIconStyle: {
|
|
576
|
+
color: theme.palette.text.primary
|
|
577
|
+
},
|
|
578
|
+
smallIconStyle: {
|
|
579
|
+
color: theme.palette.text.primary,
|
|
580
|
+
marginRight: "-20px"
|
|
594
581
|
}
|
|
595
|
-
});
|
|
582
|
+
}));
|
|
596
583
|
const ChangeEventListItem = ({ changeEvent }) => {
|
|
597
|
-
const classes = useStyles$
|
|
584
|
+
const classes = useStyles$4();
|
|
598
585
|
const duration = (/* @__PURE__ */ new Date()).getTime() - new Date(changeEvent.timestamp).getTime();
|
|
599
586
|
const changedAt = DateTime.local().minus(Duration.fromMillis(duration)).toRelative({ locale: "en" });
|
|
600
587
|
let externalLinkElem;
|
|
@@ -605,9 +592,9 @@ const ChangeEventListItem = ({ changeEvent }) => {
|
|
|
605
592
|
{
|
|
606
593
|
component: Link,
|
|
607
594
|
to: changeEvent.links[0].href,
|
|
608
|
-
|
|
595
|
+
className: classes.smallExternalLinkIconStyle
|
|
609
596
|
},
|
|
610
|
-
/* @__PURE__ */ React.createElement(
|
|
597
|
+
/* @__PURE__ */ React.createElement(LinkIcon, null)
|
|
611
598
|
));
|
|
612
599
|
}
|
|
613
600
|
return /* @__PURE__ */ React.createElement(ListItem, { dense: true, key: changeEvent.id }, /* @__PURE__ */ React.createElement(
|
|
@@ -625,7 +612,7 @@ const ChangeEventListItem = ({ changeEvent }) => {
|
|
|
625
612
|
{
|
|
626
613
|
component: Link,
|
|
627
614
|
to: changeEvent.html_url,
|
|
628
|
-
|
|
615
|
+
className: classes.smallIconStyle
|
|
629
616
|
},
|
|
630
617
|
/* @__PURE__ */ React.createElement(OpenInBrowserIcon, null)
|
|
631
618
|
))));
|
|
@@ -708,7 +695,91 @@ function usePagerdutyEntity() {
|
|
|
708
695
|
return getPagerDutyEntity(entity);
|
|
709
696
|
}
|
|
710
697
|
|
|
711
|
-
const
|
|
698
|
+
const TriggerDialog = ({
|
|
699
|
+
showDialog,
|
|
700
|
+
handleDialog,
|
|
701
|
+
onIncidentCreated,
|
|
702
|
+
name,
|
|
703
|
+
integrationKey
|
|
704
|
+
}) => {
|
|
705
|
+
const alertApi = useApi(alertApiRef);
|
|
706
|
+
const identityApi = useApi(identityApiRef);
|
|
707
|
+
const api = useApi(pagerDutyApiRef);
|
|
708
|
+
const [description, setDescription] = useState("");
|
|
709
|
+
const [{ value, loading, error }, handleTriggerAlarm] = useAsyncFn(
|
|
710
|
+
async (descriptions) => {
|
|
711
|
+
const { userEntityRef } = await identityApi.getBackstageIdentity();
|
|
712
|
+
const { name: userName } = parseEntityRef(userEntityRef, {
|
|
713
|
+
defaultKind: "User",
|
|
714
|
+
defaultNamespace: DEFAULT_NAMESPACE
|
|
715
|
+
});
|
|
716
|
+
return await api.triggerAlarm({
|
|
717
|
+
integrationKey,
|
|
718
|
+
source: window.location.toString(),
|
|
719
|
+
description: descriptions,
|
|
720
|
+
userName
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
);
|
|
724
|
+
const descriptionChanged = (event) => {
|
|
725
|
+
setDescription(event.target.value);
|
|
726
|
+
};
|
|
727
|
+
useEffect(() => {
|
|
728
|
+
if (value) {
|
|
729
|
+
(async () => {
|
|
730
|
+
alertApi.post({
|
|
731
|
+
message: `Alarm successfully triggered`
|
|
732
|
+
});
|
|
733
|
+
handleDialog();
|
|
734
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
735
|
+
onIncidentCreated == null ? void 0 : onIncidentCreated();
|
|
736
|
+
})();
|
|
737
|
+
}
|
|
738
|
+
}, [value, alertApi, handleDialog, onIncidentCreated]);
|
|
739
|
+
if (error) {
|
|
740
|
+
alertApi.post({
|
|
741
|
+
message: `Failed to trigger alarm. ${error.message}`,
|
|
742
|
+
severity: "error"
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
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(
|
|
746
|
+
Typography,
|
|
747
|
+
{
|
|
748
|
+
variant: "body1",
|
|
749
|
+
style: { marginTop: "1em" },
|
|
750
|
+
gutterBottom: true,
|
|
751
|
+
align: "justify"
|
|
752
|
+
},
|
|
753
|
+
"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."
|
|
754
|
+
), /* @__PURE__ */ React.createElement(
|
|
755
|
+
TextField,
|
|
756
|
+
{
|
|
757
|
+
inputProps: { "data-testid": "trigger-input" },
|
|
758
|
+
id: "description",
|
|
759
|
+
multiline: true,
|
|
760
|
+
fullWidth: true,
|
|
761
|
+
rows: "4",
|
|
762
|
+
margin: "normal",
|
|
763
|
+
label: "Problem description",
|
|
764
|
+
variant: "outlined",
|
|
765
|
+
onChange: descriptionChanged
|
|
766
|
+
}
|
|
767
|
+
)), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(
|
|
768
|
+
Button,
|
|
769
|
+
{
|
|
770
|
+
"data-testid": "trigger-button",
|
|
771
|
+
id: "trigger",
|
|
772
|
+
color: "secondary",
|
|
773
|
+
disabled: !description || loading,
|
|
774
|
+
variant: "contained",
|
|
775
|
+
onClick: () => handleTriggerAlarm(description),
|
|
776
|
+
endIcon: loading && /* @__PURE__ */ React.createElement(CircularProgress, { size: 16 })
|
|
777
|
+
},
|
|
778
|
+
"Trigger Incident"
|
|
779
|
+
), /* @__PURE__ */ React.createElement(Button, { id: "close", color: "primary", onClick: handleDialog }, "Close")));
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
const useStyles$3 = makeStyles((theme) => ({
|
|
712
783
|
buttonStyle: {
|
|
713
784
|
color: theme.palette.text.primary,
|
|
714
785
|
"&:hover": {
|
|
@@ -727,8 +798,8 @@ const useStyles$2 = makeStyles((theme) => ({
|
|
|
727
798
|
marginBottom: "-10px"
|
|
728
799
|
}
|
|
729
800
|
}));
|
|
730
|
-
function TriggerIncidentButton() {
|
|
731
|
-
const { buttonStyle, containerStyle, iconStyle } = useStyles$
|
|
801
|
+
function TriggerIncidentButton({ handleRefresh }) {
|
|
802
|
+
const { buttonStyle, containerStyle, iconStyle } = useStyles$3();
|
|
732
803
|
const { integrationKey, name } = usePagerdutyEntity();
|
|
733
804
|
const [dialogShown, setDialogShown] = useState(false);
|
|
734
805
|
const showDialog = useCallback(() => {
|
|
@@ -746,19 +817,20 @@ function TriggerIncidentButton() {
|
|
|
746
817
|
className: disabled ? "" : buttonStyle,
|
|
747
818
|
disabled
|
|
748
819
|
},
|
|
749
|
-
/* @__PURE__ */ React.createElement("div", { className: containerStyle }, /* @__PURE__ */ React.createElement(AddAlert, { className: iconStyle }), /* @__PURE__ */ React.createElement("p", null, "Create
|
|
820
|
+
/* @__PURE__ */ React.createElement("div", { className: containerStyle }, /* @__PURE__ */ React.createElement(AddAlert, { className: iconStyle }), /* @__PURE__ */ React.createElement("p", null, "Create new incident"))
|
|
750
821
|
), integrationKey && /* @__PURE__ */ React.createElement(
|
|
751
822
|
TriggerDialog,
|
|
752
823
|
{
|
|
753
824
|
showDialog: dialogShown,
|
|
754
825
|
handleDialog: hideDialog,
|
|
755
826
|
integrationKey,
|
|
756
|
-
name
|
|
827
|
+
name,
|
|
828
|
+
onIncidentCreated: handleRefresh
|
|
757
829
|
}
|
|
758
830
|
));
|
|
759
831
|
}
|
|
760
832
|
|
|
761
|
-
const useStyles$
|
|
833
|
+
const useStyles$2 = makeStyles((theme) => ({
|
|
762
834
|
buttonStyle: {
|
|
763
835
|
color: theme.palette.text.primary,
|
|
764
836
|
"&:hover": {
|
|
@@ -778,7 +850,7 @@ const useStyles$1 = makeStyles((theme) => ({
|
|
|
778
850
|
}
|
|
779
851
|
}));
|
|
780
852
|
function OpenServiceButton(props) {
|
|
781
|
-
const { buttonStyle, containerStyle, iconStyle } = useStyles$
|
|
853
|
+
const { buttonStyle, containerStyle, iconStyle } = useStyles$2();
|
|
782
854
|
function navigateToService() {
|
|
783
855
|
window.open(props.serviceUrl, "_blank");
|
|
784
856
|
}
|
|
@@ -793,20 +865,253 @@ function OpenServiceButton(props) {
|
|
|
793
865
|
));
|
|
794
866
|
}
|
|
795
867
|
|
|
868
|
+
function labelFromStatus(status) {
|
|
869
|
+
let label;
|
|
870
|
+
switch (status) {
|
|
871
|
+
case "active":
|
|
872
|
+
label = "OK";
|
|
873
|
+
break;
|
|
874
|
+
case "warning":
|
|
875
|
+
label = "ACTIVE";
|
|
876
|
+
break;
|
|
877
|
+
case "critical":
|
|
878
|
+
label = "ALARM";
|
|
879
|
+
break;
|
|
880
|
+
case "maintenance":
|
|
881
|
+
label = "MAINTENANCE";
|
|
882
|
+
break;
|
|
883
|
+
case "disabled":
|
|
884
|
+
label = "DISABLED";
|
|
885
|
+
break;
|
|
886
|
+
default:
|
|
887
|
+
label = "OK";
|
|
888
|
+
break;
|
|
889
|
+
}
|
|
890
|
+
return label;
|
|
891
|
+
}
|
|
892
|
+
function colorFromStatus(theme, status) {
|
|
893
|
+
let color;
|
|
894
|
+
switch (status) {
|
|
895
|
+
case "active":
|
|
896
|
+
color = theme.palette.success.main;
|
|
897
|
+
break;
|
|
898
|
+
case "warning":
|
|
899
|
+
color = theme.palette.warningBackground;
|
|
900
|
+
break;
|
|
901
|
+
case "critical":
|
|
902
|
+
color = theme.palette.error.main;
|
|
903
|
+
break;
|
|
904
|
+
case "maintenance":
|
|
905
|
+
color = "#ebdc00";
|
|
906
|
+
break;
|
|
907
|
+
case "disabled":
|
|
908
|
+
color = "#A9A9A9";
|
|
909
|
+
break;
|
|
910
|
+
default:
|
|
911
|
+
color = theme.palette.success.main;
|
|
912
|
+
break;
|
|
913
|
+
}
|
|
914
|
+
return color;
|
|
915
|
+
}
|
|
916
|
+
function StatusCard({ serviceId, refreshStatus }) {
|
|
917
|
+
const api = useApi(pagerDutyApiRef);
|
|
918
|
+
const [{ value: status, loading, error }, getStatus] = useAsyncFn$1(
|
|
919
|
+
async () => {
|
|
920
|
+
const { service: foundService } = await api.getServiceById(serviceId);
|
|
921
|
+
return foundService.status;
|
|
922
|
+
}
|
|
923
|
+
);
|
|
924
|
+
const useStyles = makeStyles$1((theme) => ({
|
|
925
|
+
cardStyle: {
|
|
926
|
+
height: "120px",
|
|
927
|
+
display: "flex",
|
|
928
|
+
alignItems: "center",
|
|
929
|
+
justifyContent: "center",
|
|
930
|
+
backgroundColor: status !== void 0 ? colorFromStatus(theme, status) : colorFromStatus(theme, "active"),
|
|
931
|
+
marginRight: "10px"
|
|
932
|
+
},
|
|
933
|
+
largeTextStyle: {
|
|
934
|
+
color: "white",
|
|
935
|
+
fontWeight: "bold",
|
|
936
|
+
fontSize: "20px",
|
|
937
|
+
wordWrap: "break-word"
|
|
938
|
+
}
|
|
939
|
+
}));
|
|
940
|
+
const { cardStyle, largeTextStyle } = useStyles();
|
|
941
|
+
useEffect(() => {
|
|
942
|
+
getStatus();
|
|
943
|
+
}, [refreshStatus, getStatus]);
|
|
944
|
+
if (error) {
|
|
945
|
+
if (error.message.includes("Forbidden")) {
|
|
946
|
+
return /* @__PURE__ */ React.createElement("p", null, "forbidden");
|
|
947
|
+
}
|
|
948
|
+
return /* @__PURE__ */ React.createElement(Alert$1, { severity: "error" }, "Error encountered while fetching information. ", error.message);
|
|
949
|
+
}
|
|
950
|
+
if (loading) {
|
|
951
|
+
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
952
|
+
}
|
|
953
|
+
if (!status) {
|
|
954
|
+
return /* @__PURE__ */ React.createElement("p", null, "not found");
|
|
955
|
+
}
|
|
956
|
+
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"));
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
function colorFromPercentage(theme, percentage) {
|
|
960
|
+
if (percentage < 0.5) {
|
|
961
|
+
return theme.palette.error.main;
|
|
962
|
+
} else if (percentage < 0.8) {
|
|
963
|
+
return theme.palette.warning.main;
|
|
964
|
+
}
|
|
965
|
+
return theme.palette.success.main;
|
|
966
|
+
}
|
|
967
|
+
function ServiceStandardsCard({ total, completed, standards }) {
|
|
968
|
+
const useStyles = makeStyles((theme) => ({
|
|
969
|
+
cardStyle: {
|
|
970
|
+
height: "120px",
|
|
971
|
+
display: "grid",
|
|
972
|
+
gridTemplateRows: "1fr auto auto",
|
|
973
|
+
backgroundColor: "rgba(0, 0, 0, 0.03)"
|
|
974
|
+
},
|
|
975
|
+
containerStyle: {
|
|
976
|
+
display: "flex",
|
|
977
|
+
justifyContent: "center"
|
|
978
|
+
},
|
|
979
|
+
largeTextStyle: {
|
|
980
|
+
fontSize: "50px",
|
|
981
|
+
color: completed !== void 0 && total !== void 0 ? colorFromPercentage(theme, completed / total) : colorFromPercentage(theme, 0),
|
|
982
|
+
alignSelf: "center",
|
|
983
|
+
justifyContent: "center"
|
|
984
|
+
},
|
|
985
|
+
smallTextStyle: {
|
|
986
|
+
color: theme.palette.textSubtle,
|
|
987
|
+
fontSize: "14px",
|
|
988
|
+
fontWeight: "bold",
|
|
989
|
+
alignSelf: "center",
|
|
990
|
+
justifyContent: "center",
|
|
991
|
+
marginLeft: "-2px",
|
|
992
|
+
marginTop: "25px"
|
|
993
|
+
},
|
|
994
|
+
tooltipContainer: {
|
|
995
|
+
position: "absolute"
|
|
996
|
+
},
|
|
997
|
+
tooltipIcon: {
|
|
998
|
+
marginRight: "5px"
|
|
999
|
+
},
|
|
1000
|
+
standardItem: {
|
|
1001
|
+
display: "flex",
|
|
1002
|
+
alignItems: "center"
|
|
1003
|
+
}
|
|
1004
|
+
}));
|
|
1005
|
+
const BorderLinearProgress = withStyles((theme) => ({
|
|
1006
|
+
root: {
|
|
1007
|
+
height: 10,
|
|
1008
|
+
borderRadius: 5,
|
|
1009
|
+
margin: 5
|
|
1010
|
+
},
|
|
1011
|
+
colorPrimary: {
|
|
1012
|
+
backgroundColor: theme.palette.grey[theme.palette.type === "light" ? 200 : 700]
|
|
1013
|
+
},
|
|
1014
|
+
bar: {
|
|
1015
|
+
borderRadius: 5,
|
|
1016
|
+
backgroundColor: completed !== void 0 && total !== void 0 ? colorFromPercentage(theme, completed / total) : colorFromPercentage(theme, 0)
|
|
1017
|
+
}
|
|
1018
|
+
}))(LinearProgress);
|
|
1019
|
+
const { cardStyle, containerStyle, largeTextStyle, smallTextStyle, tooltipContainer, tooltipIcon, standardItem } = useStyles();
|
|
1020
|
+
return /* @__PURE__ */ React.createElement(Card, { className: cardStyle }, completed !== void 0 && total !== void 0 ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: tooltipContainer }, /* @__PURE__ */ React.createElement(IconButton, null, /* @__PURE__ */ React.createElement(
|
|
1021
|
+
Tooltip,
|
|
1022
|
+
{
|
|
1023
|
+
interactive: true,
|
|
1024
|
+
title: /* @__PURE__ */ React.createElement(React.Fragment, null, standards == null ? void 0 : standards.map((standard, _) => /* @__PURE__ */ React.createElement("p", null, standard.pass ? /* @__PURE__ */ React.createElement(
|
|
1025
|
+
"span",
|
|
1026
|
+
{
|
|
1027
|
+
className: standardItem
|
|
1028
|
+
},
|
|
1029
|
+
/* @__PURE__ */ React.createElement(CheckCircle, { className: tooltipIcon }),
|
|
1030
|
+
" ",
|
|
1031
|
+
standard.name
|
|
1032
|
+
) : /* @__PURE__ */ React.createElement("span", { className: standardItem }, /* @__PURE__ */ React.createElement(RadioButtonUncheckedIcon, { className: tooltipIcon }), " ", standard.name))))
|
|
1033
|
+
},
|
|
1034
|
+
/* @__PURE__ */ React.createElement(InfoIcon, null)
|
|
1035
|
+
))), /* @__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(
|
|
1036
|
+
BorderLinearProgress,
|
|
1037
|
+
{
|
|
1038
|
+
variant: "determinate",
|
|
1039
|
+
value: completed / total * 100
|
|
1040
|
+
}
|
|
1041
|
+
))) : /* @__PURE__ */ React.createElement("div", { className: containerStyle }, /* @__PURE__ */ React.createElement(Typography, { className: largeTextStyle }, "Unable to retrieve Scores")));
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
function IncidentCounterCard({ count, label, color }) {
|
|
1045
|
+
const textColor = color && validateColor(color) ? color : "black";
|
|
1046
|
+
const useStyles = makeStyles(() => ({
|
|
1047
|
+
cardStyle: {
|
|
1048
|
+
marginRight: "10px",
|
|
1049
|
+
height: "120px",
|
|
1050
|
+
display: "flex",
|
|
1051
|
+
alignItems: "center",
|
|
1052
|
+
justifyContent: "center",
|
|
1053
|
+
backgroundColor: "rgba(0, 0, 0, 0.03)"
|
|
1054
|
+
},
|
|
1055
|
+
largeTextStyle: {
|
|
1056
|
+
color: textColor,
|
|
1057
|
+
fontSize: "30px",
|
|
1058
|
+
marginTop: "-10px"
|
|
1059
|
+
},
|
|
1060
|
+
smallTextStyle: {
|
|
1061
|
+
color: textColor,
|
|
1062
|
+
fontWeight: "bold",
|
|
1063
|
+
fontSize: "10px",
|
|
1064
|
+
marginTop: "-5px",
|
|
1065
|
+
textTransform: "uppercase",
|
|
1066
|
+
flexWrap: "wrap"
|
|
1067
|
+
}
|
|
1068
|
+
}));
|
|
1069
|
+
const { cardStyle, largeTextStyle, smallTextStyle } = useStyles();
|
|
1070
|
+
return /* @__PURE__ */ React.createElement(Card, { className: cardStyle }, /* @__PURE__ */ React.createElement(Typography, { className: largeTextStyle }, count), /* @__PURE__ */ React.createElement(Typography, { className: smallTextStyle }, label));
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
const useStyles$1 = makeStyles$1(
|
|
1074
|
+
(theme) => createStyles({
|
|
1075
|
+
overviewHeaderTextStyle: {
|
|
1076
|
+
fontSize: "14px",
|
|
1077
|
+
fontWeight: 500,
|
|
1078
|
+
color: theme.palette.type === "light" ? "rgba(0, 0, 0, 0.54)" : "rgba(255, 255, 255, 0.7)"
|
|
1079
|
+
},
|
|
1080
|
+
headerStyle: {
|
|
1081
|
+
marginRight: "1em"
|
|
1082
|
+
},
|
|
1083
|
+
overviewHeaderContainerStyle: {
|
|
1084
|
+
display: "flex",
|
|
1085
|
+
margin: "15px",
|
|
1086
|
+
marginBottom: "20px"
|
|
1087
|
+
},
|
|
1088
|
+
overviewCardsContainerStyle: {
|
|
1089
|
+
display: "flex",
|
|
1090
|
+
margin: "15px",
|
|
1091
|
+
marginTop: "-15px"
|
|
1092
|
+
},
|
|
1093
|
+
incidentMetricsContainerStyle: {
|
|
1094
|
+
display: "flex",
|
|
1095
|
+
height: "100%",
|
|
1096
|
+
justifyContent: "center",
|
|
1097
|
+
columnSpan: "all"
|
|
1098
|
+
}
|
|
1099
|
+
})
|
|
1100
|
+
);
|
|
796
1101
|
const BasicCard = ({ children }) => /* @__PURE__ */ React.createElement(InfoCard, { title: "PagerDuty" }, children);
|
|
797
1102
|
const PagerDutyCard$1 = (props) => {
|
|
1103
|
+
var _a, _b, _c, _d, _e;
|
|
1104
|
+
const classes = useStyles$1();
|
|
798
1105
|
const theme = useTheme();
|
|
799
|
-
const { readOnly, disableChangeEvents
|
|
1106
|
+
const { readOnly, disableChangeEvents } = props;
|
|
800
1107
|
const api = useApi(pagerDutyApiRef);
|
|
801
1108
|
const [refreshIncidents, setRefreshIncidents] = useState(false);
|
|
802
1109
|
const [refreshChangeEvents, setRefreshChangeEvents] = useState(false);
|
|
803
|
-
const [
|
|
804
|
-
const hideDialog = useCallback(() => {
|
|
805
|
-
setDialogShown(false);
|
|
806
|
-
}, [setDialogShown]);
|
|
1110
|
+
const [refreshStatus, setRefreshStatus] = useState(false);
|
|
807
1111
|
const handleRefresh = useCallback(() => {
|
|
808
1112
|
setRefreshIncidents((x) => !x);
|
|
809
1113
|
setRefreshChangeEvents((x) => !x);
|
|
1114
|
+
setRefreshStatus((x) => !x);
|
|
810
1115
|
}, []);
|
|
811
1116
|
const {
|
|
812
1117
|
value: service,
|
|
@@ -816,13 +1121,18 @@ const PagerDutyCard$1 = (props) => {
|
|
|
816
1121
|
const { service: foundService } = await api.getServiceByPagerDutyEntity(
|
|
817
1122
|
props
|
|
818
1123
|
);
|
|
819
|
-
|
|
1124
|
+
const { standards: serviceStandards } = await api.getServiceStandardsByServiceId(foundService.id);
|
|
1125
|
+
const result = {
|
|
820
1126
|
id: foundService.id,
|
|
821
1127
|
name: foundService.name,
|
|
822
1128
|
url: foundService.html_url,
|
|
823
1129
|
policyId: foundService.escalation_policy.id,
|
|
824
|
-
policyLink: foundService.escalation_policy.html_url
|
|
1130
|
+
policyLink: foundService.escalation_policy.html_url,
|
|
1131
|
+
policyName: foundService.escalation_policy.name,
|
|
1132
|
+
status: foundService.status,
|
|
1133
|
+
standards: serviceStandards
|
|
825
1134
|
};
|
|
1135
|
+
return result;
|
|
826
1136
|
}, [props]);
|
|
827
1137
|
if (error) {
|
|
828
1138
|
let errorNode;
|
|
@@ -841,250 +1151,42 @@ const PagerDutyCard$1 = (props) => {
|
|
|
841
1151
|
if (loading) {
|
|
842
1152
|
return /* @__PURE__ */ React.createElement(BasicCard, null, /* @__PURE__ */ React.createElement(Progress, null));
|
|
843
1153
|
}
|
|
844
|
-
const createIncidentDisabled = !integrationKey;
|
|
845
1154
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Card, { "data-testid": "pagerduty-card" }, /* @__PURE__ */ React.createElement(
|
|
846
1155
|
CardHeader,
|
|
847
1156
|
{
|
|
848
|
-
|
|
1157
|
+
className: classes.headerStyle,
|
|
849
1158
|
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,
|
|
1159
|
+
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
1160
|
}
|
|
852
|
-
), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 12,
|
|
853
|
-
|
|
1161
|
+
), /* @__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(
|
|
1162
|
+
IncidentCounterCard,
|
|
854
1163
|
{
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
"SERVICE STANDARDS"
|
|
862
|
-
))), /* @__PURE__ */ React.createElement(
|
|
863
|
-
Grid,
|
|
1164
|
+
count: 29,
|
|
1165
|
+
label: "interruptions",
|
|
1166
|
+
color: theme.palette.textSubtle
|
|
1167
|
+
}
|
|
1168
|
+
)), /* @__PURE__ */ React.createElement(Grid, { md: 4 }, /* @__PURE__ */ React.createElement(
|
|
1169
|
+
IncidentCounterCard,
|
|
864
1170
|
{
|
|
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(
|
|
1171
|
+
count: 29,
|
|
1172
|
+
label: "high urgency",
|
|
1173
|
+
color: theme.palette.warning.main
|
|
1174
|
+
}
|
|
1175
|
+
)), /* @__PURE__ */ React.createElement(Grid, { md: 4 }, /* @__PURE__ */ React.createElement(
|
|
1176
|
+
IncidentCounterCard,
|
|
1177
|
+
{
|
|
1178
|
+
count: 32,
|
|
1179
|
+
label: "incidents",
|
|
1180
|
+
color: theme.palette.error.main
|
|
1181
|
+
}
|
|
1182
|
+
))), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 3 }, /* @__PURE__ */ React.createElement(
|
|
1183
|
+
ServiceStandardsCard,
|
|
1184
|
+
{
|
|
1185
|
+
total: (_b = (_a = service == null ? void 0 : service.standards) == null ? void 0 : _a.score) == null ? void 0 : _b.total,
|
|
1186
|
+
completed: (_d = (_c = service == null ? void 0 : service.standards) == null ? void 0 : _c.score) == null ? void 0 : _d.passing,
|
|
1187
|
+
standards: (_e = service == null ? void 0 : service.standards) == null ? void 0 : _e.standards
|
|
1188
|
+
}
|
|
1189
|
+
))), /* @__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
1190
|
Incidents,
|
|
1089
1191
|
{
|
|
1090
1192
|
serviceId: service.id,
|
|
@@ -1096,17 +1198,14 @@ const PagerDutyCard$1 = (props) => {
|
|
|
1096
1198
|
serviceId: service.id,
|
|
1097
1199
|
refreshEvents: refreshChangeEvents
|
|
1098
1200
|
}
|
|
1099
|
-
)) : /* @__PURE__ */ React.createElement(React.Fragment, null)), /* @__PURE__ */ React.createElement(
|
|
1100
|
-
|
|
1201
|
+
)) : /* @__PURE__ */ React.createElement(React.Fragment, null)), /* @__PURE__ */ React.createElement(
|
|
1202
|
+
EscalationPolicy,
|
|
1101
1203
|
{
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
onIncidentCreated: handleRefresh,
|
|
1106
|
-
name,
|
|
1107
|
-
integrationKey
|
|
1204
|
+
policyId: service.policyId,
|
|
1205
|
+
policyUrl: service.policyLink,
|
|
1206
|
+
policyName: service.policyName
|
|
1108
1207
|
}
|
|
1109
|
-
));
|
|
1208
|
+
))));
|
|
1110
1209
|
};
|
|
1111
1210
|
|
|
1112
1211
|
const isPluginApplicableToEntity = (entity) => {
|
|
@@ -1164,7 +1263,7 @@ function TriggerButton(props) {
|
|
|
1164
1263
|
className: disabled ? "" : buttonStyle,
|
|
1165
1264
|
disabled
|
|
1166
1265
|
},
|
|
1167
|
-
integrationKey ? (_a = props.children) != null ? _a : "Create
|
|
1266
|
+
integrationKey ? (_a = props.children) != null ? _a : "Create new incident" : "Missing integration key"
|
|
1168
1267
|
), integrationKey && /* @__PURE__ */ React.createElement(
|
|
1169
1268
|
TriggerDialog,
|
|
1170
1269
|
{
|
|
@@ -1179,4 +1278,4 @@ function TriggerButton(props) {
|
|
|
1179
1278
|
const PagerDutyCard = EntityPagerDutyCard;
|
|
1180
1279
|
|
|
1181
1280
|
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-
|
|
1281
|
+
//# sourceMappingURL=index-90a6424d.esm.js.map
|