@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.
@@ -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 { parseEntityRef, DEFAULT_NAMESPACE } from '@backstage/catalog-model';
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 LinearProgress from '@material-ui/core/LinearProgress';
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-b2ba10a3.esm.js'),
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$7 = makeStyles((theme) => ({
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.status.warning,
234
- color: theme.palette.status.warning,
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: theme.palette.status.warning
254
+ color: "#fff"
237
255
  }
238
256
  },
239
257
  error: {
240
- borderColor: theme.palette.status.error,
241
- color: theme.palette.status.error,
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: theme.palette.status.error
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$7();
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(React.Fragment, null, /* @__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
- color: "primary"
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$6 = makeStyles({
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$6();
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$5 = makeStyles({
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$5();
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$4 = makeStyles((theme) => ({
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
- const EscalationUser = ({ user }) => {
407
- const classes = useStyles$4();
408
- return /* @__PURE__ */ React.createElement(ListItem, null, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement(Avatar, { alt: user.name, src: user.avatar_url })), /* @__PURE__ */ React.createElement(
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 }), "Web Team")
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: "Send e-mail to user", placement: "top" }, /* @__PURE__ */ React.createElement(IconButton, { href: `mailto:${user.email}` }, /* @__PURE__ */ React.createElement(MailOutline, { className: classes.smallIconStyle }))), /* @__PURE__ */ React.createElement(Tooltip, { title: "View in PagerDuty", placement: "top" }, /* @__PURE__ */ React.createElement(
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 TriggerDialog = ({
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$3();
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
- color: "primary"
595
+ className: classes.smallExternalLinkIconStyle
609
596
  },
610
- /* @__PURE__ */ React.createElement(OpenInBrowserIcon, null)
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
- color: "primary"
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 useStyles$2 = makeStyles((theme) => ({
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$2();
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 New Incident"))
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$1 = makeStyles((theme) => ({
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$1();
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, integrationKey, name } = props;
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 [dialogShown, setDialogShown] = useState(false);
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
- return {
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
- style: { marginRight: "1em" },
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, null), /* @__PURE__ */ React.createElement(OpenServiceButton, { serviceUrl: service.url })) : /* @__PURE__ */ React.createElement(OpenServiceButton, { serviceUrl: service.url })
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, style: { display: "flex", margin: "15px" } }, /* @__PURE__ */ React.createElement(Grid, { item: true, md: 3 }, /* @__PURE__ */ React.createElement(Typography, { style: { fontSize: "16px", fontWeight: "bold" } }, "STATUS")), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 6 }, /* @__PURE__ */ React.createElement(Typography, { style: { fontSize: "16px", fontWeight: "bold" } }, "INCIDENT HISTORY")), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 3 }, /* @__PURE__ */ React.createElement(
853
- Typography,
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
- style: {
856
- fontSize: "16px",
857
- fontWeight: "bold",
858
- marginLeft: "10px"
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
- item: true,
866
- md: 12,
867
- style: { display: "flex", margin: "15px", marginTop: "-15px" }
868
- },
869
- /* @__PURE__ */ React.createElement(Grid, { item: true, md: 3 }, /* @__PURE__ */ React.createElement(
870
- Card,
871
- {
872
- style: {
873
- background: "darkRed",
874
- marginRight: "20px",
875
- height: "150px",
876
- display: "flex",
877
- alignItems: "center",
878
- justifyContent: "center"
879
- }
880
- },
881
- /* @__PURE__ */ React.createElement(
882
- Typography,
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(EscalationPolicy, { policyId: service.policyId }))), !createIncidentDisabled && /* @__PURE__ */ React.createElement(
1100
- TriggerDialog,
1201
+ )) : /* @__PURE__ */ React.createElement(React.Fragment, null)), /* @__PURE__ */ React.createElement(
1202
+ EscalationPolicy,
1101
1203
  {
1102
- "data-testid": "trigger-dialog",
1103
- showDialog: dialogShown,
1104
- handleDialog: hideDialog,
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 Incident" : "Missing integration key"
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-46807363.esm.js.map
1281
+ //# sourceMappingURL=index-90a6424d.esm.js.map