@pagerduty/backstage-plugin 0.15.10-next.0 → 0.16.0
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/assets/PD-Green.svg +21 -0
- package/assets/PD-Icon.svg +13 -0
- package/assets/PD-White.svg +21 -0
- package/assets/emptystate.svg +6 -0
- package/assets/forbiddenstate.svg +25 -0
- package/dist/alpha/api.esm.js +22 -0
- package/dist/alpha/api.esm.js.map +1 -0
- package/dist/alpha/entity-cards.esm.js +69 -0
- package/dist/alpha/entity-cards.esm.js.map +1 -0
- package/dist/alpha/nav-items.esm.js +21 -0
- package/dist/alpha/nav-items.esm.js.map +1 -0
- package/dist/alpha/pages.esm.js +15 -0
- package/dist/alpha/pages.esm.js.map +1 -0
- package/dist/alpha/plugin.esm.js +26 -0
- package/dist/alpha/plugin.esm.js.map +1 -0
- package/dist/alpha.d.ts +139 -0
- package/dist/alpha.esm.js +2 -0
- package/dist/alpha.esm.js.map +1 -0
- package/dist/api/client.esm.js +225 -0
- package/dist/api/client.esm.js.map +1 -0
- package/dist/assets/PD-Green.svg +21 -0
- package/dist/assets/PD-Icon.svg +13 -0
- package/dist/assets/PD-White.svg +21 -0
- package/dist/assets/emptystate.svg +6 -0
- package/dist/assets/forbiddenstate.svg +25 -0
- package/dist/components/ChangeEvents/ChangeEventEmptyState.esm.js +29 -0
- package/dist/components/ChangeEvents/ChangeEventEmptyState.esm.js.map +1 -0
- package/dist/components/ChangeEvents/ChangeEventForbiddenState.esm.js +29 -0
- package/dist/components/ChangeEvents/ChangeEventForbiddenState.esm.js.map +1 -0
- package/dist/components/ChangeEvents/ChangeEventListItem.esm.js +85 -0
- package/dist/components/ChangeEvents/ChangeEventListItem.esm.js.map +1 -0
- package/dist/components/ChangeEvents/ChangeEvents.esm.js +60 -0
- package/dist/components/ChangeEvents/ChangeEvents.esm.js.map +1 -0
- package/dist/components/EntityPagerDutyCard/index.esm.js +29 -0
- package/dist/components/EntityPagerDutyCard/index.esm.js.map +1 -0
- package/dist/components/EntityPagerDutySmallCard/index.esm.js +29 -0
- package/dist/components/EntityPagerDutySmallCard/index.esm.js.map +1 -0
- package/dist/components/Errors/ForbiddenError.esm.js +24 -0
- package/dist/components/Errors/ForbiddenError.esm.js.map +1 -0
- package/dist/components/Errors/MissingTokenError.esm.js +24 -0
- package/dist/components/Errors/MissingTokenError.esm.js.map +1 -0
- package/dist/components/Errors/ServiceNotFoundError.esm.js +24 -0
- package/dist/components/Errors/ServiceNotFoundError.esm.js.map +1 -0
- package/dist/components/Escalation/EscalationPolicy.esm.js +53 -0
- package/dist/components/Escalation/EscalationPolicy.esm.js.map +1 -0
- package/dist/components/Escalation/EscalationUser.esm.js +97 -0
- package/dist/components/Escalation/EscalationUser.esm.js.map +1 -0
- package/dist/components/Escalation/EscalationUsersEmptyState.esm.js +23 -0
- package/dist/components/Escalation/EscalationUsersEmptyState.esm.js.map +1 -0
- package/dist/components/Escalation/EscalationUsersForbiddenState.esm.js +23 -0
- package/dist/components/Escalation/EscalationUsersForbiddenState.esm.js.map +1 -0
- package/dist/components/HomePagePagerDutyCard/Content.esm.js +9 -0
- package/dist/components/HomePagePagerDutyCard/Content.esm.js.map +1 -0
- package/dist/components/HomePagePagerDutyCard/index.esm.js +2 -0
- package/dist/components/HomePagePagerDutyCard/index.esm.js.map +1 -0
- package/dist/components/Icons/index.esm.js +9 -0
- package/dist/components/Icons/index.esm.js.map +1 -0
- package/dist/components/Incident/IncidentEmptyState.esm.js +29 -0
- package/dist/components/Incident/IncidentEmptyState.esm.js.map +1 -0
- package/dist/components/Incident/IncidentForbiddenState.esm.js +29 -0
- package/dist/components/Incident/IncidentForbiddenState.esm.js.map +1 -0
- package/dist/components/Incident/IncidentListItem.esm.js +128 -0
- package/dist/components/Incident/IncidentListItem.esm.js.map +1 -0
- package/dist/components/Incident/Incidents.esm.js +54 -0
- package/dist/components/Incident/Incidents.esm.js.map +1 -0
- package/dist/components/PagerDutyCard/index.esm.js +231 -0
- package/dist/components/PagerDutyCard/index.esm.js.map +1 -0
- package/dist/components/PagerDutyCardCommon/InsightsCard.esm.js +42 -0
- package/dist/components/PagerDutyCardCommon/InsightsCard.esm.js.map +1 -0
- package/dist/components/PagerDutyCardCommon/OpenServiceButton.esm.js +43 -0
- package/dist/components/PagerDutyCardCommon/OpenServiceButton.esm.js.map +1 -0
- package/dist/components/PagerDutyCardCommon/ServiceStandardsCard.esm.js +134 -0
- package/dist/components/PagerDutyCardCommon/ServiceStandardsCard.esm.js.map +1 -0
- package/dist/components/PagerDutyCardCommon/StatusCard.esm.js +109 -0
- package/dist/components/PagerDutyCardCommon/StatusCard.esm.js.map +1 -0
- package/dist/components/PagerDutyCardCommon/TriggerIncidentButton.esm.js +66 -0
- package/dist/components/PagerDutyCardCommon/TriggerIncidentButton.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/MappingTable.esm.js +282 -0
- package/dist/components/PagerDutyPage/MappingTable.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/ServiceMappingComponent.esm.js +50 -0
- package/dist/components/PagerDutyPage/ServiceMappingComponent.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/index.esm.js +117 -0
- package/dist/components/PagerDutyPage/index.esm.js.map +1 -0
- package/dist/components/PagerDutySmallCard/index.esm.js +227 -0
- package/dist/components/PagerDutySmallCard/index.esm.js.map +1 -0
- package/dist/components/TriggerButton/index.esm.js +51 -0
- package/dist/components/TriggerButton/index.esm.js.map +1 -0
- package/dist/components/TriggerDialog/TriggerDialog.esm.js +120 -0
- package/dist/components/TriggerDialog/TriggerDialog.esm.js.map +1 -0
- package/dist/components/constants.esm.js +6 -0
- package/dist/components/constants.esm.js.map +1 -0
- package/dist/components/pagerDutyEntity.esm.js +14 -0
- package/dist/components/pagerDutyEntity.esm.js.map +1 -0
- package/dist/deprecated.esm.js +10 -0
- package/dist/deprecated.esm.js.map +1 -0
- package/dist/hooks/index.esm.js +10 -0
- package/dist/hooks/index.esm.js.map +1 -0
- package/dist/index.d.ts +182 -0
- package/dist/index.esm.js +8 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/package.json.esm.js +133 -0
- package/dist/package.json.esm.js.map +1 -0
- package/dist/plugin.esm.js +76 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/routes.esm.js +6 -0
- package/dist/routes.esm.js.map +1 -0
- package/package.json +19 -7
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { makeStyles, withStyles, LinearProgress, Typography } from '@material-ui/core';
|
|
3
|
+
import InfoIcon from '@material-ui/icons/Info';
|
|
4
|
+
import CheckCircle from '@material-ui/icons/CheckCircle';
|
|
5
|
+
import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked';
|
|
6
|
+
import { Card, Flex, TooltipTrigger, ButtonIcon, Tooltip } from '@backstage/ui';
|
|
7
|
+
|
|
8
|
+
function colorFromPercentage(theme, percentage) {
|
|
9
|
+
if (percentage < 0.5) {
|
|
10
|
+
return theme.palette.error.main;
|
|
11
|
+
} else if (percentage < 0.8) {
|
|
12
|
+
return theme.palette.warning.main;
|
|
13
|
+
}
|
|
14
|
+
return theme.palette.success.main;
|
|
15
|
+
}
|
|
16
|
+
function ServiceStandardsCard({ total, completed, standards, compact }) {
|
|
17
|
+
const useStyles = makeStyles((theme) => ({
|
|
18
|
+
cardStyle: {
|
|
19
|
+
height: compact !== true ? "120px" : "80px",
|
|
20
|
+
padding: 0,
|
|
21
|
+
position: "relative",
|
|
22
|
+
backgroundColor: "rgba(0, 0, 0, 0.03)"
|
|
23
|
+
},
|
|
24
|
+
largeTextStyle: {
|
|
25
|
+
fontSize: compact !== true ? "50px" : "40px",
|
|
26
|
+
color: completed !== void 0 && total !== void 0 ? colorFromPercentage(theme, completed / total) : colorFromPercentage(theme, 0),
|
|
27
|
+
alignSelf: "center",
|
|
28
|
+
justifyContent: "center"
|
|
29
|
+
},
|
|
30
|
+
smallTextStyle: {
|
|
31
|
+
color: theme.palette.textSubtle,
|
|
32
|
+
fontSize: compact !== true ? "14px" : "12px",
|
|
33
|
+
fontWeight: "bold",
|
|
34
|
+
alignSelf: "center",
|
|
35
|
+
marginLeft: "-17px",
|
|
36
|
+
marginBottom: "-26px"
|
|
37
|
+
},
|
|
38
|
+
tooltipIcon: {
|
|
39
|
+
marginRight: "5px"
|
|
40
|
+
},
|
|
41
|
+
infoIcon: {
|
|
42
|
+
color: "gray",
|
|
43
|
+
"&:hover": {
|
|
44
|
+
backgroundColor: "transparent"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
standardItem: {
|
|
48
|
+
display: "flex",
|
|
49
|
+
alignItems: "center"
|
|
50
|
+
},
|
|
51
|
+
linearProgressContainer: {
|
|
52
|
+
left: 0,
|
|
53
|
+
position: "absolute",
|
|
54
|
+
bottom: 0,
|
|
55
|
+
width: "100%",
|
|
56
|
+
padding: "0px"
|
|
57
|
+
},
|
|
58
|
+
textContainerStyle: {
|
|
59
|
+
position: "absolute",
|
|
60
|
+
top: compact ? "5px" : "20px",
|
|
61
|
+
width: "100%"
|
|
62
|
+
},
|
|
63
|
+
tooltipTriggerStyles: {
|
|
64
|
+
position: "relative",
|
|
65
|
+
zIndex: 1
|
|
66
|
+
}
|
|
67
|
+
}));
|
|
68
|
+
const BorderLinearProgress = withStyles((theme) => ({
|
|
69
|
+
root: {
|
|
70
|
+
height: 10,
|
|
71
|
+
borderRadius: 5,
|
|
72
|
+
margin: 5
|
|
73
|
+
},
|
|
74
|
+
colorPrimary: {
|
|
75
|
+
backgroundColor: theme.palette.grey[theme.palette.type === "light" ? 200 : 700]
|
|
76
|
+
},
|
|
77
|
+
bar: {
|
|
78
|
+
borderRadius: 5,
|
|
79
|
+
backgroundColor: completed !== void 0 && total !== void 0 ? colorFromPercentage(theme, completed / total) : colorFromPercentage(theme, 0)
|
|
80
|
+
}
|
|
81
|
+
}))(LinearProgress);
|
|
82
|
+
const {
|
|
83
|
+
cardStyle,
|
|
84
|
+
largeTextStyle,
|
|
85
|
+
smallTextStyle,
|
|
86
|
+
linearProgressContainer,
|
|
87
|
+
tooltipIcon,
|
|
88
|
+
textContainerStyle,
|
|
89
|
+
infoIcon,
|
|
90
|
+
standardItem,
|
|
91
|
+
tooltipTriggerStyles
|
|
92
|
+
} = useStyles();
|
|
93
|
+
if (standards === void 0 || completed === void 0 || total === void 0) {
|
|
94
|
+
return /* @__PURE__ */ jsx(Card, { className: cardStyle, children: /* @__PURE__ */ jsx(Flex, { justify: "center", children: /* @__PURE__ */ jsx(Typography, { className: smallTextStyle, children: "Unable to retrieve Scores" }) }) });
|
|
95
|
+
}
|
|
96
|
+
return /* @__PURE__ */ jsx(Card, { className: cardStyle, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
|
|
97
|
+
/* @__PURE__ */ jsxs(TooltipTrigger, { children: [
|
|
98
|
+
/* @__PURE__ */ jsx(
|
|
99
|
+
ButtonIcon,
|
|
100
|
+
{
|
|
101
|
+
className: tooltipTriggerStyles,
|
|
102
|
+
icon: /* @__PURE__ */ jsx(InfoIcon, { className: infoIcon }),
|
|
103
|
+
variant: "tertiary"
|
|
104
|
+
}
|
|
105
|
+
),
|
|
106
|
+
/* @__PURE__ */ jsx(Tooltip, { children: standards?.map((standard, key) => /* @__PURE__ */ jsx(Typography, { children: standard.pass ? /* @__PURE__ */ jsxs(Typography, { className: standardItem, children: [
|
|
107
|
+
/* @__PURE__ */ jsx(CheckCircle, { className: tooltipIcon }),
|
|
108
|
+
" ",
|
|
109
|
+
standard.name
|
|
110
|
+
] }) : /* @__PURE__ */ jsxs(Typography, { className: standardItem, children: [
|
|
111
|
+
/* @__PURE__ */ jsx(RadioButtonUncheckedIcon, { className: tooltipIcon }),
|
|
112
|
+
" ",
|
|
113
|
+
standard.name
|
|
114
|
+
] }) }, key)) })
|
|
115
|
+
] }),
|
|
116
|
+
/* @__PURE__ */ jsxs(Flex, { justify: "center", className: textContainerStyle, children: [
|
|
117
|
+
/* @__PURE__ */ jsx(Typography, { className: largeTextStyle, children: completed }),
|
|
118
|
+
/* @__PURE__ */ jsxs(Typography, { className: smallTextStyle, children: [
|
|
119
|
+
"/",
|
|
120
|
+
total
|
|
121
|
+
] })
|
|
122
|
+
] }),
|
|
123
|
+
/* @__PURE__ */ jsx("div", { className: linearProgressContainer, children: /* @__PURE__ */ jsx(
|
|
124
|
+
BorderLinearProgress,
|
|
125
|
+
{
|
|
126
|
+
variant: "determinate",
|
|
127
|
+
value: completed / total * 100
|
|
128
|
+
}
|
|
129
|
+
) })
|
|
130
|
+
] }) });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { colorFromPercentage, ServiceStandardsCard as default };
|
|
134
|
+
//# sourceMappingURL=ServiceStandardsCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceStandardsCard.esm.js","sources":["../../../src/components/PagerDutyCardCommon/ServiceStandardsCard.tsx"],"sourcesContent":["import { BackstageTheme } from '@backstage/theme';\nimport {\n LinearProgress,\n Theme,\n Typography,\n makeStyles,\n withStyles,\n} from '@material-ui/core';\nimport InfoIcon from '@material-ui/icons/Info';\nimport { PagerDutyServiceStandard } from '@pagerduty/backstage-plugin-common';\nimport CheckCircle from '@material-ui/icons/CheckCircle';\nimport RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked';\nimport { ButtonIcon, Card, Flex, Tooltip, TooltipTrigger } from '@backstage/ui';\n\ntype Props = {\n total: number | undefined;\n completed: number | undefined;\n standards: PagerDutyServiceStandard[] | undefined;\n compact?: boolean;\n};\n\nexport function colorFromPercentage(theme: Theme, percentage: number) {\n if (percentage < 0.5) {\n return theme.palette.error.main;\n } else if (percentage < 0.8) {\n return theme.palette.warning.main;\n }\n return theme.palette.success.main;\n}\n\nfunction ServiceStandardsCard({ total, completed, standards, compact }: Props) {\n const useStyles = makeStyles<BackstageTheme>(theme => ({\n cardStyle: {\n height: compact !== true ? '120px' : '80px',\n padding: 0,\n position: 'relative',\n backgroundColor: 'rgba(0, 0, 0, 0.03)',\n },\n largeTextStyle: {\n fontSize: compact !== true ? '50px' : '40px',\n color:\n completed !== undefined && total !== undefined\n ? colorFromPercentage(theme, completed / total)\n : colorFromPercentage(theme, 0),\n alignSelf: 'center',\n justifyContent: 'center',\n },\n smallTextStyle: {\n color: theme.palette.textSubtle,\n fontSize: compact !== true ? '14px' : '12px',\n fontWeight: 'bold',\n alignSelf: 'center',\n marginLeft: '-17px',\n marginBottom: '-26px',\n },\n tooltipIcon: {\n marginRight: '5px',\n },\n infoIcon: {\n color: 'gray',\n '&:hover': {\n backgroundColor: 'transparent',\n },\n },\n standardItem: {\n display: 'flex',\n alignItems: 'center',\n },\n linearProgressContainer: {\n left: 0,\n position: 'absolute',\n bottom: 0,\n width: '100%',\n padding: '0px',\n },\n textContainerStyle: {\n position: 'absolute',\n top: compact ? '5px' : '20px',\n width: '100%',\n },\n tooltipTriggerStyles: {\n position: 'relative',\n zIndex: 1,\n },\n }));\n\n const BorderLinearProgress = withStyles(theme => ({\n root: {\n height: 10,\n borderRadius: 5,\n margin: 5,\n },\n colorPrimary: {\n backgroundColor:\n theme.palette.grey[theme.palette.type === 'light' ? 200 : 700],\n },\n bar: {\n borderRadius: 5,\n backgroundColor:\n completed !== undefined && total !== undefined\n ? colorFromPercentage(theme, completed / total)\n : colorFromPercentage(theme, 0),\n },\n }))(LinearProgress);\n\n const {\n cardStyle,\n largeTextStyle,\n smallTextStyle,\n linearProgressContainer,\n tooltipIcon,\n textContainerStyle,\n infoIcon,\n standardItem,\n tooltipTriggerStyles,\n } = useStyles();\n\n if (\n standards === undefined ||\n completed === undefined ||\n total === undefined\n ) {\n return (\n <Card className={cardStyle}>\n <Flex justify=\"center\">\n <Typography className={smallTextStyle}>\n Unable to retrieve Scores\n </Typography>\n </Flex>\n </Card>\n );\n }\n\n return (\n <Card className={cardStyle}>\n <Flex direction=\"column\">\n <TooltipTrigger>\n <ButtonIcon\n className={tooltipTriggerStyles}\n icon={<InfoIcon className={infoIcon} />}\n variant=\"tertiary\"\n />\n <Tooltip>\n {standards?.map((standard, key) => (\n <Typography key={key}>\n {standard.pass ? (\n <Typography className={standardItem}>\n <CheckCircle className={tooltipIcon} /> {standard.name}\n </Typography>\n ) : (\n <Typography className={standardItem}>\n <RadioButtonUncheckedIcon className={tooltipIcon} />{' '}\n {standard.name}\n </Typography>\n )}\n </Typography>\n ))}\n </Tooltip>\n </TooltipTrigger>\n <Flex justify=\"center\" className={textContainerStyle}>\n <Typography className={largeTextStyle}>{completed}</Typography>\n <Typography className={smallTextStyle}>/{total}</Typography>\n </Flex>\n <div className={linearProgressContainer}>\n <BorderLinearProgress\n variant=\"determinate\"\n value={(completed! / total!) * 100}\n />\n </div>\n </Flex>\n </Card>\n );\n}\n\nexport default ServiceStandardsCard;\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
4
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
5
|
+
import { pagerDutyApiRef } from '../../api/client.esm.js';
|
|
6
|
+
import { useAsyncFn } from 'react-use';
|
|
7
|
+
import Alert from '@material-ui/lab/Alert/Alert';
|
|
8
|
+
import { Progress } from '@backstage/core-components';
|
|
9
|
+
import { Card } from '@backstage/ui';
|
|
10
|
+
import { Typography } from '@material-ui/core';
|
|
11
|
+
|
|
12
|
+
function labelFromStatus(status) {
|
|
13
|
+
let label;
|
|
14
|
+
switch (status) {
|
|
15
|
+
case "active":
|
|
16
|
+
label = "OK";
|
|
17
|
+
break;
|
|
18
|
+
case "warning":
|
|
19
|
+
label = "ACTIVE";
|
|
20
|
+
break;
|
|
21
|
+
case "critical":
|
|
22
|
+
label = "ALARM";
|
|
23
|
+
break;
|
|
24
|
+
case "maintenance":
|
|
25
|
+
label = "MAINTENANCE";
|
|
26
|
+
break;
|
|
27
|
+
case "disabled":
|
|
28
|
+
label = "DISABLED";
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
label = "OK";
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
return label;
|
|
35
|
+
}
|
|
36
|
+
function colorFromStatus(theme, status) {
|
|
37
|
+
let color;
|
|
38
|
+
switch (status) {
|
|
39
|
+
case "active":
|
|
40
|
+
color = theme.palette.success.main;
|
|
41
|
+
break;
|
|
42
|
+
case "warning":
|
|
43
|
+
color = theme.palette.warningBackground;
|
|
44
|
+
break;
|
|
45
|
+
case "critical":
|
|
46
|
+
color = theme.palette.error.main;
|
|
47
|
+
break;
|
|
48
|
+
case "maintenance":
|
|
49
|
+
color = "#ebdc00";
|
|
50
|
+
break;
|
|
51
|
+
case "disabled":
|
|
52
|
+
color = "#A9A9A9";
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
color = theme.palette.success.main;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
return color;
|
|
59
|
+
}
|
|
60
|
+
function StatusCard({ serviceId, refreshStatus, account, compact }) {
|
|
61
|
+
const api = useApi(pagerDutyApiRef);
|
|
62
|
+
const [{ value: status, loading, error }, getStatus] = useAsyncFn(
|
|
63
|
+
async () => {
|
|
64
|
+
const { service: foundService } = await api.getServiceById(
|
|
65
|
+
serviceId,
|
|
66
|
+
account
|
|
67
|
+
);
|
|
68
|
+
return foundService.status;
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
const useStyles = makeStyles((theme) => ({
|
|
72
|
+
cardStyle: {
|
|
73
|
+
height: compact !== true ? "120px" : "80px",
|
|
74
|
+
display: "flex",
|
|
75
|
+
alignItems: "center",
|
|
76
|
+
justifyContent: "center",
|
|
77
|
+
backgroundColor: status !== void 0 ? colorFromStatus(theme, status) : colorFromStatus(theme, "active")
|
|
78
|
+
},
|
|
79
|
+
largeTextStyle: {
|
|
80
|
+
color: "white",
|
|
81
|
+
fontWeight: "bold",
|
|
82
|
+
fontSize: "20px",
|
|
83
|
+
wordWrap: "break-word"
|
|
84
|
+
}
|
|
85
|
+
}));
|
|
86
|
+
const { cardStyle, largeTextStyle } = useStyles();
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
getStatus();
|
|
89
|
+
}, [refreshStatus, getStatus]);
|
|
90
|
+
if (error) {
|
|
91
|
+
if (error.message.includes("Forbidden")) {
|
|
92
|
+
return /* @__PURE__ */ jsx(Typography, { children: "forbidden" });
|
|
93
|
+
}
|
|
94
|
+
return /* @__PURE__ */ jsxs(Alert, { severity: "error", children: [
|
|
95
|
+
"Error encountered while fetching information. ",
|
|
96
|
+
error.message
|
|
97
|
+
] });
|
|
98
|
+
}
|
|
99
|
+
if (loading) {
|
|
100
|
+
return /* @__PURE__ */ jsx(Progress, {});
|
|
101
|
+
}
|
|
102
|
+
if (!status) {
|
|
103
|
+
return /* @__PURE__ */ jsx(Typography, { children: "not found" });
|
|
104
|
+
}
|
|
105
|
+
return /* @__PURE__ */ jsx(Card, { className: cardStyle, children: status !== void 0 ? /* @__PURE__ */ jsx(Typography, { className: largeTextStyle, children: labelFromStatus(status) }) : /* @__PURE__ */ jsx(Typography, { className: largeTextStyle, children: "Unable to get status" }) });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export { StatusCard as default };
|
|
109
|
+
//# sourceMappingURL=StatusCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusCard.esm.js","sources":["../../../src/components/PagerDutyCardCommon/StatusCard.tsx"],"sourcesContent":["import { useEffect } from 'react';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { BackstageTheme } from '@backstage/theme';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { pagerDutyApiRef } from '../../api';\nimport { useAsyncFn } from 'react-use';\nimport Alert from '@material-ui/lab/Alert/Alert';\nimport { Progress } from '@backstage/core-components';\nimport { Card } from '@backstage/ui';\nimport { Typography } from '@material-ui/core';\n\ntype Props = {\n serviceId: string;\n refreshStatus: boolean;\n account?: string;\n compact?: boolean;\n};\n\nfunction labelFromStatus(status: string) {\n let label;\n switch (status) {\n case 'active':\n label = 'OK';\n break;\n case 'warning':\n label = 'ACTIVE';\n break;\n case 'critical':\n label = 'ALARM';\n break;\n case 'maintenance':\n label = 'MAINTENANCE';\n break;\n case 'disabled':\n label = 'DISABLED';\n break;\n default:\n label = 'OK';\n break;\n }\n\n return label;\n}\n\nfunction colorFromStatus(theme: Theme, status: string) {\n let color;\n switch (status) {\n case 'active':\n color = theme.palette.success.main;\n break;\n case 'warning':\n color = theme.palette.warningBackground;\n break;\n case 'critical':\n color = theme.palette.error.main;\n break;\n case 'maintenance':\n color = '#ebdc00';\n break;\n case 'disabled':\n color = '#A9A9A9';\n break;\n default:\n color = theme.palette.success.main;\n break;\n }\n\n return color;\n}\n\nfunction StatusCard({ serviceId, refreshStatus, account, compact }: Props) {\n const api = useApi(pagerDutyApiRef);\n const [{ value: status, loading, error }, getStatus] = useAsyncFn(\n async () => {\n const { service: foundService } = await api.getServiceById(\n serviceId,\n account,\n );\n return foundService.status;\n },\n );\n\n const useStyles = makeStyles<BackstageTheme>(theme => ({\n cardStyle: {\n height: compact !== true ? '120px' : '80px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor:\n status !== undefined\n ? colorFromStatus(theme, status)\n : colorFromStatus(theme, 'active'),\n },\n largeTextStyle: {\n color: 'white',\n fontWeight: 'bold',\n fontSize: '20px',\n wordWrap: 'break-word',\n },\n }));\n\n const { cardStyle, largeTextStyle } = useStyles();\n\n useEffect(() => {\n getStatus();\n }, [refreshStatus, getStatus]);\n\n if (error) {\n if (error.message.includes('Forbidden')) {\n return <Typography>forbidden</Typography>;\n }\n\n return (\n <Alert severity=\"error\">\n Error encountered while fetching information. {error.message}\n </Alert>\n );\n }\n\n if (loading) {\n return <Progress />;\n }\n\n if (!status) {\n return <Typography>not found</Typography>;\n }\n\n return (\n <Card className={cardStyle}>\n {status !== undefined ? (\n <Typography className={largeTextStyle}>\n {labelFromStatus(status)}\n </Typography>\n ) : (\n <Typography className={largeTextStyle}>Unable to get status</Typography>\n )}\n </Card>\n );\n}\n\nexport default StatusCard;\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useCallback } from 'react';
|
|
3
|
+
import { makeStyles, Typography } from '@material-ui/core';
|
|
4
|
+
import { TriggerDialog } from '../TriggerDialog/TriggerDialog.esm.js';
|
|
5
|
+
import AddAlert from '@material-ui/icons/AddAlert';
|
|
6
|
+
import { ButtonIcon } from '@backstage/ui';
|
|
7
|
+
|
|
8
|
+
function TriggerIncidentButton({
|
|
9
|
+
integrationKey,
|
|
10
|
+
entityName,
|
|
11
|
+
compact,
|
|
12
|
+
handleRefresh
|
|
13
|
+
}) {
|
|
14
|
+
const useStyles = makeStyles(() => ({
|
|
15
|
+
containerStyle: {
|
|
16
|
+
fontSize: compact !== true ? "12px" : "10px",
|
|
17
|
+
width: compact !== true ? "80px" : "60px",
|
|
18
|
+
display: "flex",
|
|
19
|
+
flexDirection: "column",
|
|
20
|
+
alignItems: "center"
|
|
21
|
+
},
|
|
22
|
+
textStyle: {
|
|
23
|
+
textAlign: "center",
|
|
24
|
+
fontSize: "12px",
|
|
25
|
+
minWidth: "30px"
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
const { containerStyle, textStyle } = useStyles();
|
|
29
|
+
const [dialogShown, setDialogShown] = useState(false);
|
|
30
|
+
const showDialog = useCallback(() => {
|
|
31
|
+
setDialogShown(true);
|
|
32
|
+
}, [setDialogShown]);
|
|
33
|
+
const hideDialog = useCallback(() => {
|
|
34
|
+
setDialogShown(false);
|
|
35
|
+
}, [setDialogShown]);
|
|
36
|
+
const disabled = !integrationKey;
|
|
37
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38
|
+
/* @__PURE__ */ jsxs("div", { className: containerStyle, children: [
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
ButtonIcon,
|
|
41
|
+
{
|
|
42
|
+
variant: "tertiary",
|
|
43
|
+
size: "medium",
|
|
44
|
+
"aria-label": "create-incident",
|
|
45
|
+
onClick: showDialog,
|
|
46
|
+
isDisabled: disabled,
|
|
47
|
+
icon: /* @__PURE__ */ jsx(AddAlert, {})
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
/* @__PURE__ */ jsx(Typography, { className: textStyle, children: "Create new incident" })
|
|
51
|
+
] }),
|
|
52
|
+
integrationKey && /* @__PURE__ */ jsx(
|
|
53
|
+
TriggerDialog,
|
|
54
|
+
{
|
|
55
|
+
showDialog: dialogShown,
|
|
56
|
+
handleDialog: hideDialog,
|
|
57
|
+
integrationKey,
|
|
58
|
+
serviceName: entityName,
|
|
59
|
+
onIncidentCreated: handleRefresh
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
] });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { TriggerIncidentButton };
|
|
66
|
+
//# sourceMappingURL=TriggerIncidentButton.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TriggerIncidentButton.esm.js","sources":["../../../src/components/PagerDutyCardCommon/TriggerIncidentButton.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// eslint-disable-next-line @backstage/no-undeclared-imports\nimport { useCallback, useState } from 'react';\nimport { makeStyles, Typography } from '@material-ui/core';\nimport { BackstageTheme } from '@backstage/theme';\n\nimport { TriggerDialog } from '../TriggerDialog';\nimport AddAlert from '@material-ui/icons/AddAlert';\nimport { ButtonIcon } from '@backstage/ui';\n\n/** @public */\nexport type TriggerIncidentButtonProps = {\n integrationKey: string | undefined;\n entityName: string;\n compact?: boolean;\n handleRefresh: () => void;\n};\n\n/** @public */\nexport function TriggerIncidentButton({\n integrationKey,\n entityName,\n compact,\n handleRefresh,\n}: TriggerIncidentButtonProps) {\n const useStyles = makeStyles<BackstageTheme>(() => ({\n containerStyle: {\n fontSize: compact !== true ? '12px' : '10px',\n width: compact !== true ? '80px' : '60px',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n },\n textStyle: {\n textAlign: 'center',\n fontSize: '12px',\n minWidth: '30px',\n },\n }));\n\n const { containerStyle, textStyle } = useStyles();\n const [dialogShown, setDialogShown] = useState<boolean>(false);\n\n const showDialog = useCallback(() => {\n setDialogShown(true);\n }, [setDialogShown]);\n const hideDialog = useCallback(() => {\n setDialogShown(false);\n }, [setDialogShown]);\n\n const disabled = !integrationKey;\n\n return (\n <>\n <div className={containerStyle}>\n <ButtonIcon\n variant=\"tertiary\"\n size=\"medium\"\n aria-label=\"create-incident\"\n onClick={showDialog}\n isDisabled={disabled}\n icon={<AddAlert />}\n />\n\n <Typography className={textStyle}>Create new incident</Typography>\n </div>\n {integrationKey && (\n <TriggerDialog\n showDialog={dialogShown}\n handleDialog={hideDialog}\n integrationKey={integrationKey}\n serviceName={entityName}\n onIncidentCreated={handleRefresh}\n />\n )}\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAkCO,SAAS,qBAAA,CAAsB;AAAA,EACpC,cAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAA+B;AAC7B,EAAA,MAAM,SAAA,GAAY,WAA2B,OAAO;AAAA,IAClD,cAAA,EAAgB;AAAA,MACd,QAAA,EAAU,OAAA,KAAY,IAAA,GAAO,MAAA,GAAS,MAAA;AAAA,MACtC,KAAA,EAAO,OAAA,KAAY,IAAA,GAAO,MAAA,GAAS,MAAA;AAAA,MACnC,OAAA,EAAS,MAAA;AAAA,MACT,aAAA,EAAe,QAAA;AAAA,MACf,UAAA,EAAY;AAAA,KACd;AAAA,IACA,SAAA,EAAW;AAAA,MACT,SAAA,EAAW,QAAA;AAAA,MACX,QAAA,EAAU,MAAA;AAAA,MACV,QAAA,EAAU;AAAA;AACZ,GACF,CAAE,CAAA;AAEF,EAAA,MAAM,EAAE,cAAA,EAAgB,SAAA,EAAU,GAAI,SAAA,EAAU;AAChD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAkB,KAAK,CAAA;AAE7D,EAAA,MAAM,UAAA,GAAa,YAAY,MAAM;AACnC,IAAA,cAAA,CAAe,IAAI,CAAA;AAAA,EACrB,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AACnB,EAAA,MAAM,UAAA,GAAa,YAAY,MAAM;AACnC,IAAA,cAAA,CAAe,KAAK,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,EAAA,MAAM,WAAW,CAAC,cAAA;AAElB,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAW,cAAA,EACd,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAQ,UAAA;AAAA,UACR,IAAA,EAAK,QAAA;AAAA,UACL,YAAA,EAAW,iBAAA;AAAA,UACX,OAAA,EAAS,UAAA;AAAA,UACT,UAAA,EAAY,QAAA;AAAA,UACZ,IAAA,sBAAO,QAAA,EAAA,EAAS;AAAA;AAAA,OAClB;AAAA,sBAEA,GAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,SAAA,EAAW,QAAA,EAAA,qBAAA,EAAmB;AAAA,KAAA,EACvD,CAAA;AAAA,IACC,cAAA,oBACC,GAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACC,UAAA,EAAY,WAAA;AAAA,QACZ,YAAA,EAAc,UAAA;AAAA,QACd,cAAA;AAAA,QACA,WAAA,EAAa,UAAA;AAAA,QACb,iBAAA,EAAmB;AAAA;AAAA;AACrB,GAAA,EAEJ,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useEffect, useMemo } from 'react';
|
|
3
|
+
import { useMaterialReactTable, MRT_EditActionButtons, MaterialReactTable } from 'material-react-table';
|
|
4
|
+
import { Typography, Box, DialogTitle, DialogContent, DialogActions } from '@material-ui/core';
|
|
5
|
+
import { Flex, TooltipTrigger, ButtonIcon, Tooltip } from '@backstage/ui';
|
|
6
|
+
import { QueryClient, QueryClientProvider, useMutation } from '@tanstack/react-query';
|
|
7
|
+
import { Edit, OpenInBrowser } from '@mui/icons-material';
|
|
8
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
9
|
+
import { pagerDutyApiRef } from '../../api/client.esm.js';
|
|
10
|
+
|
|
11
|
+
function getColorFromStatus(status) {
|
|
12
|
+
switch (status) {
|
|
13
|
+
case "InSync":
|
|
14
|
+
return "green";
|
|
15
|
+
case "OutOfSync":
|
|
16
|
+
return "red";
|
|
17
|
+
case "NotMapped":
|
|
18
|
+
return "orange";
|
|
19
|
+
default:
|
|
20
|
+
return "gray";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function makeReadable(status) {
|
|
24
|
+
switch (status) {
|
|
25
|
+
case "InSync":
|
|
26
|
+
return "In Sync";
|
|
27
|
+
case "OutOfSync":
|
|
28
|
+
return "Out of Sync";
|
|
29
|
+
case "NotMapped":
|
|
30
|
+
return "Not Mapped";
|
|
31
|
+
default:
|
|
32
|
+
return "Refresh to Update";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const MappingTable = ({
|
|
36
|
+
mappings,
|
|
37
|
+
catalogEntities
|
|
38
|
+
}) => {
|
|
39
|
+
const DenseTable = () => {
|
|
40
|
+
const [validationErrors, setValidationErrors] = useState({});
|
|
41
|
+
const [entityOptions, setEntityOptions] = useState(
|
|
42
|
+
[]
|
|
43
|
+
);
|
|
44
|
+
const pagerDutyApi = useApi(pagerDutyApiRef);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
getEntityOptions();
|
|
47
|
+
}, []);
|
|
48
|
+
const columns = useMemo(
|
|
49
|
+
() => [
|
|
50
|
+
{
|
|
51
|
+
id: "serviceId",
|
|
52
|
+
accessorKey: "serviceId",
|
|
53
|
+
header: "Service ID",
|
|
54
|
+
visibleInShowHideMenu: false,
|
|
55
|
+
enableEditing: false,
|
|
56
|
+
Edit: () => null,
|
|
57
|
+
Cell: ({ cell }) => /* @__PURE__ */ jsx(Typography, { variant: "body1", style: { fontWeight: 600 }, children: cell.getValue() })
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "integrationKey",
|
|
61
|
+
accessorKey: "integrationKey",
|
|
62
|
+
header: "Integration Key",
|
|
63
|
+
visibleInShowHideMenu: false,
|
|
64
|
+
enableEditing: false,
|
|
65
|
+
Edit: () => null
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: "serviceName",
|
|
69
|
+
accessorKey: "serviceName",
|
|
70
|
+
header: "PagerDuty Service",
|
|
71
|
+
enableEditing: false
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: "account",
|
|
75
|
+
accessorKey: "account",
|
|
76
|
+
header: "Account",
|
|
77
|
+
enableEditing: false,
|
|
78
|
+
Edit: () => null
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "team",
|
|
82
|
+
accessorKey: "team",
|
|
83
|
+
header: "Team",
|
|
84
|
+
enableEditing: false
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: "escalationPolicy",
|
|
88
|
+
accessorKey: "escalationPolicy",
|
|
89
|
+
header: "Escalation Policy",
|
|
90
|
+
enableEditing: false
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: "entityRef",
|
|
94
|
+
accessorKey: "entityRef",
|
|
95
|
+
header: "Mapping",
|
|
96
|
+
visibleInShowHideMenu: false,
|
|
97
|
+
editVariant: "select",
|
|
98
|
+
editSelectOptions: entityOptions,
|
|
99
|
+
muiEditTextFieldProps: {
|
|
100
|
+
select: true,
|
|
101
|
+
error: !!validationErrors?.state,
|
|
102
|
+
helperText: validationErrors?.state,
|
|
103
|
+
multiline: true,
|
|
104
|
+
type: "range"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "entityName",
|
|
109
|
+
accessorKey: "entityName",
|
|
110
|
+
header: "Mapped Entity Name",
|
|
111
|
+
enableEditing: false,
|
|
112
|
+
Edit: () => null
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "status",
|
|
116
|
+
accessorKey: "status",
|
|
117
|
+
header: "Status",
|
|
118
|
+
enableEditing: false,
|
|
119
|
+
Edit: () => null,
|
|
120
|
+
Cell: ({ cell }) => /* @__PURE__ */ jsx(
|
|
121
|
+
Box,
|
|
122
|
+
{
|
|
123
|
+
component: "span",
|
|
124
|
+
bgcolor: getColorFromStatus(cell.getValue()),
|
|
125
|
+
borderRadius: "0.25rem",
|
|
126
|
+
color: "white",
|
|
127
|
+
p: "0.25rem",
|
|
128
|
+
children: makeReadable(cell.getValue())
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: "serviceUrl",
|
|
134
|
+
accessorKey: "serviceUrl",
|
|
135
|
+
header: "Service URL",
|
|
136
|
+
visibleInShowHideMenu: false,
|
|
137
|
+
enableEditing: false,
|
|
138
|
+
Edit: () => null
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
[validationErrors, entityOptions]
|
|
142
|
+
);
|
|
143
|
+
function useUpdateMapping() {
|
|
144
|
+
return useMutation({
|
|
145
|
+
mutationFn: async (mapping) => {
|
|
146
|
+
return await pagerDutyApi.storeServiceMapping(
|
|
147
|
+
mapping.serviceId,
|
|
148
|
+
mapping.integrationKey ?? "",
|
|
149
|
+
mapping.entityRef,
|
|
150
|
+
mapping.account ?? ""
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
const { mutateAsync: updateMapping, isPending: isUpdatingMapping } = useUpdateMapping();
|
|
156
|
+
const handleSaveMapping = async ({ values, table }) => {
|
|
157
|
+
setValidationErrors({});
|
|
158
|
+
values.entityName = catalogEntities.find(
|
|
159
|
+
(entity) => `${entity.type}:${entity.namespace}/${entity.name}`.toLowerCase() === values.entityRef
|
|
160
|
+
)?.name ?? "";
|
|
161
|
+
values.status = "RefreshToUpdate";
|
|
162
|
+
await updateMapping(values);
|
|
163
|
+
const existingMapping = mappings.find(
|
|
164
|
+
(item) => item.serviceId === values.serviceId
|
|
165
|
+
);
|
|
166
|
+
if (existingMapping) {
|
|
167
|
+
existingMapping.entityRef = values.entityRef;
|
|
168
|
+
existingMapping.entityName = values.entityName;
|
|
169
|
+
}
|
|
170
|
+
table.setEditingRow(null);
|
|
171
|
+
};
|
|
172
|
+
const openInBrowser = (url) => {
|
|
173
|
+
window.open(url, "_blank", "noreferrer");
|
|
174
|
+
};
|
|
175
|
+
const dataTable = useMaterialReactTable({
|
|
176
|
+
columns,
|
|
177
|
+
data: mappings,
|
|
178
|
+
editDisplayMode: "modal",
|
|
179
|
+
enableEditing: true,
|
|
180
|
+
positionActionsColumn: "last",
|
|
181
|
+
enableStickyHeader: true,
|
|
182
|
+
enableFilters: true,
|
|
183
|
+
getRowId: (row) => row.serviceId,
|
|
184
|
+
muiToolbarAlertBannerProps: mappings === void 0 ? {
|
|
185
|
+
color: "error",
|
|
186
|
+
children: "Error loading data"
|
|
187
|
+
} : void 0,
|
|
188
|
+
muiTableContainerProps: {
|
|
189
|
+
sx: {
|
|
190
|
+
minHeight: "500px"
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
onEditingRowCancel: () => setValidationErrors({}),
|
|
194
|
+
onEditingRowSave: handleSaveMapping,
|
|
195
|
+
renderEditRowDialogContent: ({ table, row, internalEditComponents }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
196
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Update Entity Mapping" }),
|
|
197
|
+
/* @__PURE__ */ jsx(
|
|
198
|
+
DialogContent,
|
|
199
|
+
{
|
|
200
|
+
style: { display: "flex", flexDirection: "column", gap: "1rem" },
|
|
201
|
+
children: internalEditComponents
|
|
202
|
+
}
|
|
203
|
+
),
|
|
204
|
+
/* @__PURE__ */ jsx(DialogActions, { children: /* @__PURE__ */ jsx(MRT_EditActionButtons, { variant: "text", table, row }) })
|
|
205
|
+
] }),
|
|
206
|
+
renderRowActions: ({ row, table }) => /* @__PURE__ */ jsxs(Flex, { children: [
|
|
207
|
+
/* @__PURE__ */ jsxs(TooltipTrigger, { children: [
|
|
208
|
+
/* @__PURE__ */ jsx(
|
|
209
|
+
ButtonIcon,
|
|
210
|
+
{
|
|
211
|
+
"aria-label": "Edit",
|
|
212
|
+
variant: "tertiary",
|
|
213
|
+
onClick: () => {
|
|
214
|
+
getEntityOptions();
|
|
215
|
+
table.setEditingRow(row);
|
|
216
|
+
},
|
|
217
|
+
icon: /* @__PURE__ */ jsx(Edit, {})
|
|
218
|
+
}
|
|
219
|
+
),
|
|
220
|
+
/* @__PURE__ */ jsx(Tooltip, { children: "Edit" })
|
|
221
|
+
] }),
|
|
222
|
+
/* @__PURE__ */ jsxs(TooltipTrigger, { children: [
|
|
223
|
+
/* @__PURE__ */ jsx(
|
|
224
|
+
ButtonIcon,
|
|
225
|
+
{
|
|
226
|
+
"aria-label": "Open in PagerDuty",
|
|
227
|
+
variant: "tertiary",
|
|
228
|
+
onClick: () => openInBrowser(row.getValue("serviceUrl")),
|
|
229
|
+
icon: /* @__PURE__ */ jsx(OpenInBrowser, {})
|
|
230
|
+
}
|
|
231
|
+
),
|
|
232
|
+
/* @__PURE__ */ jsx(Tooltip, { children: " Open in PagerDuty" })
|
|
233
|
+
] })
|
|
234
|
+
] }),
|
|
235
|
+
state: {
|
|
236
|
+
isLoading: mappings.length === 0 || catalogEntities.length === 0,
|
|
237
|
+
isSaving: isUpdatingMapping,
|
|
238
|
+
showAlertBanner: mappings === void 0 || catalogEntities === void 0,
|
|
239
|
+
showProgressBars: mappings.length === 0 || catalogEntities.length === 0
|
|
240
|
+
},
|
|
241
|
+
initialState: {
|
|
242
|
+
columnVisibility: {
|
|
243
|
+
serviceId: false,
|
|
244
|
+
entityRef: false,
|
|
245
|
+
serviceUrl: false,
|
|
246
|
+
integrationKey: false
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
function getEntityOptions() {
|
|
251
|
+
const options = [];
|
|
252
|
+
options.push({ value: "", label: "None" });
|
|
253
|
+
catalogEntities.forEach((entity) => {
|
|
254
|
+
const foundServiceAnnotation = entity.annotations["pagerduty.com/service-id"];
|
|
255
|
+
const foundIntegrationKeyAnnotation = entity.annotations["pagerduty.com/integration-key"];
|
|
256
|
+
let foundServiceMapping;
|
|
257
|
+
if (foundServiceAnnotation || foundIntegrationKeyAnnotation) {
|
|
258
|
+
foundServiceMapping = mappings.find(
|
|
259
|
+
(item) => item.serviceId === foundServiceAnnotation || item.integrationKey === foundIntegrationKeyAnnotation
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
const entityRef = `${entity.type}:${entity.namespace}/${entity.name}`.toLowerCase();
|
|
263
|
+
const foundEntityMapping = mappings.find(
|
|
264
|
+
(item) => item.entityRef === entityRef
|
|
265
|
+
);
|
|
266
|
+
if (!foundEntityMapping && (!foundServiceAnnotation || !foundIntegrationKeyAnnotation) || (foundServiceAnnotation || foundIntegrationKeyAnnotation) && foundServiceMapping && !foundEntityMapping) {
|
|
267
|
+
options.push({
|
|
268
|
+
value: entityRef,
|
|
269
|
+
label: entity.name
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
setEntityOptions(options);
|
|
274
|
+
}
|
|
275
|
+
return /* @__PURE__ */ jsx(MaterialReactTable, { table: dataTable });
|
|
276
|
+
};
|
|
277
|
+
const queryClient = new QueryClient();
|
|
278
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(DenseTable, {}) });
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export { MappingTable };
|
|
282
|
+
//# sourceMappingURL=MappingTable.esm.js.map
|