@pagerduty/backstage-plugin 0.19.0 → 0.21.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/CHANGELOG.md +24 -0
- package/dist/alpha/pages.esm.js +41 -4
- package/dist/alpha/pages.esm.js.map +1 -1
- package/dist/alpha/plugin.esm.js +4 -3
- package/dist/alpha/plugin.esm.js.map +1 -1
- package/dist/alpha.d.ts +105 -26
- package/dist/api/client.esm.js +145 -3
- package/dist/api/client.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js +86 -40
- package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/ConfigurationPage.esm.js +119 -0
- package/dist/components/PagerDutyPage/ConfigurationPage.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFieldModal.esm.js +152 -0
- package/dist/components/PagerDutyPage/CustomFieldModal.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/ButtonTabs.esm.js +51 -0
- package/dist/components/PagerDutyPage/CustomFields/ButtonTabs.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/CustomFieldsEmptyState.esm.js +46 -0
- package/dist/components/PagerDutyPage/CustomFields/CustomFieldsEmptyState.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/CustomFieldsTabPanel.esm.js +154 -0
- package/dist/components/PagerDutyPage/CustomFields/CustomFieldsTabPanel.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/DeleteCustomFieldDialog.esm.js +63 -0
- package/dist/components/PagerDutyPage/CustomFields/DeleteCustomFieldDialog.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/SyncLogsFilters.esm.js +126 -0
- package/dist/components/PagerDutyPage/CustomFields/SyncLogsFilters.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/SyncLogsTab.esm.js +285 -0
- package/dist/components/PagerDutyPage/CustomFields/SyncLogsTab.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/customFieldErrors.esm.js +13 -0
- package/dist/components/PagerDutyPage/CustomFields/customFieldErrors.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields.esm.js +192 -0
- package/dist/components/PagerDutyPage/CustomFields.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/MappingsDialog.esm.js +2 -0
- package/dist/components/PagerDutyPage/MappingsDialog.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js +1 -1
- package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js +15 -3
- package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/MappingsTable/NameCell.esm.js +35 -0
- package/dist/components/PagerDutyPage/MappingsTable/NameCell.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js +26 -29
- package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/ServiceMappingPage.esm.js +22 -0
- package/dist/components/PagerDutyPage/ServiceMappingPage.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/index.esm.js +12 -127
- package/dist/components/PagerDutyPage/index.esm.js.map +1 -1
- package/dist/index.d.ts +60 -8
- package/dist/package.json.esm.js +1 -1
- package/package.json +17 -17
- package/dist/alpha/nav-items.esm.js +0 -21
- package/dist/alpha/nav-items.esm.js.map +0 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { Dialog, DialogHeader, DialogBody, Box, Text, Flex, TextField, DialogFooter, Button } from '@backstage/ui';
|
|
4
|
+
import { makeStyles, createStyles } from '@material-ui/core/styles';
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles(
|
|
7
|
+
(theme) => createStyles({
|
|
8
|
+
generalErrorBox: {
|
|
9
|
+
backgroundColor: "rgba(211, 47, 47, 0.08)",
|
|
10
|
+
borderRadius: theme.shape.borderRadius,
|
|
11
|
+
padding: `${theme.spacing(1)}px ${theme.spacing(1.5)}px`,
|
|
12
|
+
marginBottom: theme.spacing(2)
|
|
13
|
+
},
|
|
14
|
+
fieldErrorText: {
|
|
15
|
+
color: theme.palette.error.main,
|
|
16
|
+
fontSize: "0.75rem",
|
|
17
|
+
margin: `${theme.spacing(0.5)}px 0 0 0`
|
|
18
|
+
},
|
|
19
|
+
descriptionLabel: {
|
|
20
|
+
display: "block",
|
|
21
|
+
fontSize: "0.875rem",
|
|
22
|
+
marginBottom: theme.spacing(0.75)
|
|
23
|
+
},
|
|
24
|
+
textarea: {
|
|
25
|
+
width: "100%",
|
|
26
|
+
boxSizing: "border-box",
|
|
27
|
+
padding: `${theme.spacing(1)}px ${theme.spacing(1.5)}px`,
|
|
28
|
+
fontSize: "0.875rem",
|
|
29
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
30
|
+
borderRadius: theme.shape.borderRadius,
|
|
31
|
+
resize: "vertical",
|
|
32
|
+
fontFamily: "inherit",
|
|
33
|
+
color: "inherit",
|
|
34
|
+
backgroundColor: "transparent",
|
|
35
|
+
"&:disabled": {
|
|
36
|
+
backgroundColor: theme.palette.action.disabledBackground
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
);
|
|
41
|
+
const CustomFieldModal = ({
|
|
42
|
+
open,
|
|
43
|
+
saving,
|
|
44
|
+
error,
|
|
45
|
+
onClose,
|
|
46
|
+
onSave,
|
|
47
|
+
mode = "add",
|
|
48
|
+
initialValues
|
|
49
|
+
}) => {
|
|
50
|
+
const classes = useStyles();
|
|
51
|
+
const [formData, setFormData] = useState(
|
|
52
|
+
initialValues ?? { name: "", entityPath: "", description: "" }
|
|
53
|
+
);
|
|
54
|
+
const [localErrors, setLocalErrors] = useState({});
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (open) {
|
|
57
|
+
setFormData(initialValues ?? { name: "", entityPath: "", description: "" });
|
|
58
|
+
setLocalErrors({});
|
|
59
|
+
}
|
|
60
|
+
}, [open]);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
setLocalErrors(error ?? {});
|
|
63
|
+
}, [error]);
|
|
64
|
+
const handleFormChange = (field) => (value) => {
|
|
65
|
+
setFormData((prev) => ({ ...prev, [field]: value }));
|
|
66
|
+
if (field in localErrors) {
|
|
67
|
+
setLocalErrors((prev) => ({ ...prev, [field]: void 0 }));
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const handleClose = () => {
|
|
71
|
+
setFormData({ name: "", entityPath: "", description: "" });
|
|
72
|
+
setLocalErrors({});
|
|
73
|
+
onClose();
|
|
74
|
+
};
|
|
75
|
+
const handleSave = async () => {
|
|
76
|
+
await onSave(formData);
|
|
77
|
+
};
|
|
78
|
+
const getSaveLabel = () => {
|
|
79
|
+
return mode === "edit" ? "Save" : "Add";
|
|
80
|
+
};
|
|
81
|
+
const saveLabel = getSaveLabel();
|
|
82
|
+
return /* @__PURE__ */ jsxs(
|
|
83
|
+
Dialog,
|
|
84
|
+
{
|
|
85
|
+
isOpen: open,
|
|
86
|
+
onOpenChange: (isOpen) => !isOpen && handleClose(),
|
|
87
|
+
width: 500,
|
|
88
|
+
children: [
|
|
89
|
+
/* @__PURE__ */ jsx(DialogHeader, { children: mode === "edit" ? "Edit Custom Field" : "Add New Custom Field" }),
|
|
90
|
+
/* @__PURE__ */ jsxs(DialogBody, { children: [
|
|
91
|
+
localErrors.general && /* @__PURE__ */ jsx(Box, { className: classes.generalErrorBox, children: /* @__PURE__ */ jsx(Text, { variant: "body-small", color: "danger", children: localErrors.general }) }),
|
|
92
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "4", children: [
|
|
93
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
94
|
+
/* @__PURE__ */ jsx(
|
|
95
|
+
TextField,
|
|
96
|
+
{
|
|
97
|
+
label: "Name",
|
|
98
|
+
value: formData.name,
|
|
99
|
+
onChange: handleFormChange("name"),
|
|
100
|
+
isDisabled: saving,
|
|
101
|
+
isInvalid: !!localErrors.name
|
|
102
|
+
}
|
|
103
|
+
),
|
|
104
|
+
localErrors.name && /* @__PURE__ */ jsx(Text, { as: "p", className: classes.fieldErrorText, children: localErrors.name })
|
|
105
|
+
] }),
|
|
106
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
107
|
+
/* @__PURE__ */ jsx(
|
|
108
|
+
TextField,
|
|
109
|
+
{
|
|
110
|
+
label: "Entity Path",
|
|
111
|
+
value: formData.entityPath,
|
|
112
|
+
onChange: handleFormChange("entityPath"),
|
|
113
|
+
isDisabled: saving,
|
|
114
|
+
isInvalid: !!localErrors.entityPath
|
|
115
|
+
}
|
|
116
|
+
),
|
|
117
|
+
localErrors.entityPath && /* @__PURE__ */ jsx(Text, { as: "p", className: classes.fieldErrorText, children: localErrors.entityPath })
|
|
118
|
+
] }),
|
|
119
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
120
|
+
/* @__PURE__ */ jsx(Text, { as: "label", className: classes.descriptionLabel, children: "Description" }),
|
|
121
|
+
/* @__PURE__ */ jsx(
|
|
122
|
+
"textarea",
|
|
123
|
+
{
|
|
124
|
+
value: formData.description,
|
|
125
|
+
onChange: (e) => handleFormChange("description")(e.target.value),
|
|
126
|
+
disabled: saving,
|
|
127
|
+
rows: 5,
|
|
128
|
+
className: classes.textarea
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
] })
|
|
132
|
+
] })
|
|
133
|
+
] }),
|
|
134
|
+
/* @__PURE__ */ jsx(DialogFooter, { children: /* @__PURE__ */ jsxs(Flex, { gap: "2", justify: "end", children: [
|
|
135
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", isDisabled: saving, onClick: handleClose, children: "Cancel" }),
|
|
136
|
+
/* @__PURE__ */ jsx(
|
|
137
|
+
Button,
|
|
138
|
+
{
|
|
139
|
+
variant: "primary",
|
|
140
|
+
onClick: handleSave,
|
|
141
|
+
isDisabled: !formData.name || !formData.entityPath || saving,
|
|
142
|
+
children: saveLabel
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
] }) })
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export { CustomFieldModal };
|
|
152
|
+
//# sourceMappingURL=CustomFieldModal.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CustomFieldModal.esm.js","sources":["../../../src/components/PagerDutyPage/CustomFieldModal.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport {\n Box,\n Button,\n Dialog,\n DialogBody,\n DialogFooter,\n DialogHeader,\n Flex,\n Text,\n TextField,\n} from '@backstage/ui';\nimport { makeStyles, createStyles } from '@material-ui/core/styles';\nimport { BackstageTheme } from '@backstage/theme';\n\nconst useStyles = makeStyles<BackstageTheme>(theme =>\n createStyles({\n generalErrorBox: {\n backgroundColor: 'rgba(211, 47, 47, 0.08)',\n borderRadius: theme.shape.borderRadius,\n padding: `${theme.spacing(1)}px ${theme.spacing(1.5)}px`,\n marginBottom: theme.spacing(2),\n },\n fieldErrorText: {\n color: theme.palette.error.main,\n fontSize: '0.75rem',\n margin: `${theme.spacing(0.5)}px 0 0 0`,\n },\n descriptionLabel: {\n display: 'block',\n fontSize: '0.875rem',\n marginBottom: theme.spacing(0.75),\n },\n textarea: {\n width: '100%',\n boxSizing: 'border-box' as const,\n padding: `${theme.spacing(1)}px ${theme.spacing(1.5)}px`,\n fontSize: '0.875rem',\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.shape.borderRadius,\n resize: 'vertical' as const,\n fontFamily: 'inherit',\n color: 'inherit',\n backgroundColor: 'transparent',\n '&:disabled': {\n backgroundColor: theme.palette.action.disabledBackground,\n },\n },\n }),\n);\n\ninterface FormData {\n name: string;\n entityPath: string;\n description: string;\n}\n\n/** @public */\nexport interface FieldErrors {\n name?: string;\n entityPath?: string;\n general?: string;\n}\n\ninterface CustomFieldModalProps {\n open: boolean;\n saving: boolean;\n error: FieldErrors | null;\n onClose: () => void;\n onSave: (data: FormData) => Promise<void>;\n mode?: 'add' | 'edit';\n initialValues?: FormData;\n}\n\n/** @public */\nexport const CustomFieldModal = ({\n open,\n saving,\n error,\n onClose,\n onSave,\n mode = 'add',\n initialValues,\n}: CustomFieldModalProps) => {\n const classes = useStyles();\n const [formData, setFormData] = useState<FormData>(\n initialValues ?? { name: '', entityPath: '', description: '' },\n );\n const [localErrors, setLocalErrors] = useState<FieldErrors>({});\n\n useEffect(() => {\n if (open) {\n setFormData(initialValues ?? { name: '', entityPath: '', description: '' });\n setLocalErrors({});\n }\n // initialValues is intentionally excluded: the form must only reset when the\n // modal opens, not on every re-render of the parent that creates a new object\n // reference while the modal is already open (e.g. while saving).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n useEffect(() => {\n setLocalErrors(error ?? {});\n }, [error]);\n\n const handleFormChange = (field: keyof FormData) => (value: string) => {\n setFormData(prev => ({ ...prev, [field]: value }));\n if (field in localErrors) {\n setLocalErrors(prev => ({ ...prev, [field]: undefined }));\n }\n };\n\n const handleClose = () => {\n setFormData({ name: '', entityPath: '', description: '' });\n setLocalErrors({});\n onClose();\n };\n\n const handleSave = async () => {\n await onSave(formData);\n };\n\n const getSaveLabel = () => {\n return mode === 'edit' ? 'Save' : 'Add';\n };\n const saveLabel = getSaveLabel();\n\n return (\n <Dialog\n isOpen={open}\n onOpenChange={isOpen => !isOpen && handleClose()}\n width={500}\n >\n <DialogHeader>\n {mode === 'edit' ? 'Edit Custom Field' : 'Add New Custom Field'}\n </DialogHeader>\n <DialogBody>\n {localErrors.general && (\n <Box className={classes.generalErrorBox}>\n <Text variant=\"body-small\" color=\"danger\">\n {localErrors.general}\n </Text>\n </Box>\n )}\n <Flex direction=\"column\" gap=\"4\">\n <Box>\n <TextField\n label=\"Name\"\n value={formData.name}\n onChange={handleFormChange('name')}\n isDisabled={saving}\n isInvalid={!!localErrors.name}\n />\n {localErrors.name && (\n <Text as=\"p\" className={classes.fieldErrorText}>\n {localErrors.name}\n </Text>\n )}\n </Box>\n <Box>\n <TextField\n label=\"Entity Path\"\n value={formData.entityPath}\n onChange={handleFormChange('entityPath')}\n isDisabled={saving}\n isInvalid={!!localErrors.entityPath}\n />\n {localErrors.entityPath && (\n <Text as=\"p\" className={classes.fieldErrorText}>\n {localErrors.entityPath}\n </Text>\n )}\n </Box>\n <Box>\n <Text as=\"label\" className={classes.descriptionLabel}>\n Description\n </Text>\n <textarea\n value={formData.description}\n onChange={e => handleFormChange('description')(e.target.value)}\n disabled={saving}\n rows={5}\n className={classes.textarea}\n />\n </Box>\n </Flex>\n </DialogBody>\n <DialogFooter>\n <Flex gap=\"2\" justify=\"end\">\n <Button variant=\"secondary\" isDisabled={saving} onClick={handleClose}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n onClick={handleSave}\n isDisabled={!formData.name || !formData.entityPath || saving}\n >\n {saveLabel}\n </Button>\n </Flex>\n </DialogFooter>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Flex, Button } from '@backstage/ui';
|
|
3
|
+
import { makeStyles } from '@material-ui/core';
|
|
4
|
+
|
|
5
|
+
const useStyles = makeStyles(() => ({
|
|
6
|
+
buttonFirst: {
|
|
7
|
+
borderTopRightRadius: "0px !important",
|
|
8
|
+
borderBottomRightRadius: "0px !important"
|
|
9
|
+
},
|
|
10
|
+
buttonMiddle: {
|
|
11
|
+
borderRadius: "0px !important"
|
|
12
|
+
},
|
|
13
|
+
buttonLast: {
|
|
14
|
+
borderTopLeftRadius: "0px !important",
|
|
15
|
+
borderBottomLeftRadius: "0px !important"
|
|
16
|
+
}
|
|
17
|
+
}));
|
|
18
|
+
function ButtonTabs({
|
|
19
|
+
items,
|
|
20
|
+
value,
|
|
21
|
+
onChange
|
|
22
|
+
}) {
|
|
23
|
+
const classes = useStyles();
|
|
24
|
+
return /* @__PURE__ */ jsx(Flex, { gap: "0", align: "center", children: items.map((item, index) => {
|
|
25
|
+
const isActive = item.key === value;
|
|
26
|
+
const isFirst = index === 0;
|
|
27
|
+
const isLast = index === items.length - 1;
|
|
28
|
+
const isSingle = isFirst && isLast;
|
|
29
|
+
let className;
|
|
30
|
+
if (!isSingle) {
|
|
31
|
+
if (isFirst) className = classes.buttonFirst;
|
|
32
|
+
else if (isLast) className = classes.buttonLast;
|
|
33
|
+
else className = classes.buttonMiddle;
|
|
34
|
+
}
|
|
35
|
+
return /* @__PURE__ */ jsx(
|
|
36
|
+
Button,
|
|
37
|
+
{
|
|
38
|
+
variant: isActive ? "primary" : "secondary",
|
|
39
|
+
size: "small",
|
|
40
|
+
onClick: () => onChange(item.key),
|
|
41
|
+
"aria-pressed": isActive,
|
|
42
|
+
className,
|
|
43
|
+
children: item.label
|
|
44
|
+
},
|
|
45
|
+
item.key
|
|
46
|
+
);
|
|
47
|
+
}) });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { ButtonTabs };
|
|
51
|
+
//# sourceMappingURL=ButtonTabs.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ButtonTabs.esm.js","sources":["../../../../src/components/PagerDutyPage/CustomFields/ButtonTabs.tsx"],"sourcesContent":["import { ReactNode } from 'react';\nimport { Button, Flex } from '@backstage/ui';\nimport { makeStyles } from '@material-ui/core';\n\n/** @public */\nexport type ButtonTabItem<TKey extends string = string> = {\n key: TKey;\n label: ReactNode;\n};\n\ninterface ButtonTabsProps<TKey extends string = string> {\n items: ButtonTabItem<TKey>[];\n value: TKey;\n onChange: (key: TKey) => void;\n}\n\nconst useStyles = makeStyles(() => ({\n buttonFirst: {\n borderTopRightRadius: '0px !important',\n borderBottomRightRadius: '0px !important',\n },\n buttonMiddle: {\n borderRadius: '0px !important',\n },\n buttonLast: {\n borderTopLeftRadius: '0px !important',\n borderBottomLeftRadius: '0px !important',\n },\n}));\n\n/** @public */\nexport function ButtonTabs<TKey extends string = string>({\n items,\n value,\n onChange,\n}: ButtonTabsProps<TKey>) {\n const classes = useStyles();\n\n return (\n <Flex gap=\"0\" align=\"center\">\n {items.map((item, index) => {\n const isActive = item.key === value;\n const isFirst = index === 0;\n const isLast = index === items.length - 1;\n const isSingle = isFirst && isLast;\n\n let className: string | undefined;\n if (!isSingle) {\n if (isFirst) className = classes.buttonFirst;\n else if (isLast) className = classes.buttonLast;\n else className = classes.buttonMiddle;\n }\n\n return (\n <Button\n key={item.key}\n variant={isActive ? 'primary' : 'secondary'}\n size=\"small\"\n onClick={() => onChange(item.key)}\n aria-pressed={isActive}\n className={className}\n >\n {item.label}\n </Button>\n );\n })}\n </Flex>\n );\n}\n"],"names":[],"mappings":";;;;AAgBA,MAAM,SAAA,GAAY,WAAW,OAAO;AAAA,EAClC,WAAA,EAAa;AAAA,IACX,oBAAA,EAAsB,gBAAA;AAAA,IACtB,uBAAA,EAAyB;AAAA,GAC3B;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,YAAA,EAAc;AAAA,GAChB;AAAA,EACA,UAAA,EAAY;AAAA,IACV,mBAAA,EAAqB,gBAAA;AAAA,IACrB,sBAAA,EAAwB;AAAA;AAE5B,CAAA,CAAE,CAAA;AAGK,SAAS,UAAA,CAAyC;AAAA,EACvD,KAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,uBACE,GAAA,CAAC,IAAA,EAAA,EAAK,GAAA,EAAI,GAAA,EAAI,KAAA,EAAM,UACjB,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,KAAA,KAAU;AAC1B,IAAA,MAAM,QAAA,GAAW,KAAK,GAAA,KAAQ,KAAA;AAC9B,IAAA,MAAM,UAAU,KAAA,KAAU,CAAA;AAC1B,IAAA,MAAM,MAAA,GAAS,KAAA,KAAU,KAAA,CAAM,MAAA,GAAS,CAAA;AACxC,IAAA,MAAM,WAAW,OAAA,IAAW,MAAA;AAE5B,IAAA,IAAI,SAAA;AACJ,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,IAAI,OAAA,cAAqB,OAAA,CAAQ,WAAA;AAAA,WAAA,IACxB,MAAA,cAAoB,OAAA,CAAQ,UAAA;AAAA,uBACpB,OAAA,CAAQ,YAAA;AAAA,IAC3B;AAEA,IAAA,uBACE,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QAEC,OAAA,EAAS,WAAW,SAAA,GAAY,WAAA;AAAA,QAChC,IAAA,EAAK,OAAA;AAAA,QACL,OAAA,EAAS,MAAM,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AAAA,QAChC,cAAA,EAAc,QAAA;AAAA,QACd,SAAA;AAAA,QAEC,QAAA,EAAA,IAAA,CAAK;AAAA,OAAA;AAAA,MAPD,IAAA,CAAK;AAAA,KAQZ;AAAA,EAEJ,CAAC,CAAA,EACH,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Flex, TextField, Text } from '@backstage/ui';
|
|
3
|
+
import { ArrowForward } from '@mui/icons-material';
|
|
4
|
+
import { makeStyles, createStyles } from '@material-ui/core/styles';
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles(
|
|
7
|
+
(theme) => createStyles({
|
|
8
|
+
container: {
|
|
9
|
+
padding: theme.spacing(6),
|
|
10
|
+
width: "100%",
|
|
11
|
+
textAlign: "center"
|
|
12
|
+
},
|
|
13
|
+
inputWrapper: {
|
|
14
|
+
width: "8rem",
|
|
15
|
+
filter: "brightness(0.88)"
|
|
16
|
+
},
|
|
17
|
+
inputWrapperDark: {
|
|
18
|
+
width: "8rem",
|
|
19
|
+
filter: "brightness(0.5)"
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
);
|
|
23
|
+
function CustomFieldsEmptyState({ message }) {
|
|
24
|
+
const classes = useStyles();
|
|
25
|
+
return /* @__PURE__ */ jsxs(
|
|
26
|
+
Flex,
|
|
27
|
+
{
|
|
28
|
+
direction: "column",
|
|
29
|
+
align: "center",
|
|
30
|
+
justify: "center",
|
|
31
|
+
gap: "3",
|
|
32
|
+
className: classes.container,
|
|
33
|
+
children: [
|
|
34
|
+
/* @__PURE__ */ jsxs(Flex, { align: "center", gap: "3", "aria-hidden": true, children: [
|
|
35
|
+
/* @__PURE__ */ jsx("div", { className: classes.inputWrapper, children: /* @__PURE__ */ jsx(TextField, { value: "", isDisabled: true, "aria-label": "" }) }),
|
|
36
|
+
/* @__PURE__ */ jsx(ArrowForward, { fontSize: "small" }),
|
|
37
|
+
/* @__PURE__ */ jsx("div", { className: classes.inputWrapperDark, children: /* @__PURE__ */ jsx(TextField, { value: "", isDisabled: true, "aria-label": "" }) })
|
|
38
|
+
] }),
|
|
39
|
+
/* @__PURE__ */ jsx(Text, { variant: "body-medium", color: "secondary", children: message })
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { CustomFieldsEmptyState };
|
|
46
|
+
//# sourceMappingURL=CustomFieldsEmptyState.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CustomFieldsEmptyState.esm.js","sources":["../../../../src/components/PagerDutyPage/CustomFields/CustomFieldsEmptyState.tsx"],"sourcesContent":["import { Flex, Text, TextField } from '@backstage/ui';\nimport { ArrowForward } from '@mui/icons-material';\nimport { makeStyles, createStyles } from '@material-ui/core/styles';\nimport { BackstageTheme } from '@backstage/theme';\n\nconst useStyles = makeStyles<BackstageTheme>(theme =>\n createStyles({\n container: {\n padding: theme.spacing(6),\n width: '100%',\n textAlign: 'center',\n },\n inputWrapper: {\n width: '8rem',\n filter: 'brightness(0.88)'\n },\n inputWrapperDark: {\n width: '8rem',\n filter: 'brightness(0.5)',\n },\n }),\n);\n\ninterface CustomFieldsEmptyStateProps {\n message: string;\n}\n\nexport function CustomFieldsEmptyState({ message }: CustomFieldsEmptyStateProps) {\n const classes = useStyles();\n return (\n <Flex\n direction=\"column\"\n align=\"center\"\n justify=\"center\"\n gap=\"3\"\n className={classes.container}\n >\n <Flex align=\"center\" gap=\"3\" aria-hidden>\n <div className={classes.inputWrapper}>\n <TextField value=\"\" isDisabled aria-label=\"\" />\n </div>\n <ArrowForward fontSize=\"small\" />\n <div className={classes.inputWrapperDark}>\n <TextField value=\"\" isDisabled aria-label=\"\" />\n </div>\n </Flex>\n <Text variant=\"body-medium\" color=\"secondary\">\n {message}\n </Text>\n </Flex>\n );\n}\n"],"names":[],"mappings":";;;;;AAKA,MAAM,SAAA,GAAY,UAAA;AAAA,EAA2B,WAC3C,YAAA,CAAa;AAAA,IACX,SAAA,EAAW;AAAA,MACT,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,MACxB,KAAA,EAAO,MAAA;AAAA,MACP,SAAA,EAAW;AAAA,KACb;AAAA,IACA,YAAA,EAAc;AAAA,MACZ,KAAA,EAAO,MAAA;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,gBAAA,EAAkB;AAAA,MAChB,KAAA,EAAO,MAAA;AAAA,MACP,MAAA,EAAQ;AAAA;AACV,GACD;AACH,CAAA;AAMO,SAAS,sBAAA,CAAuB,EAAE,OAAA,EAAQ,EAAgC;AAC/E,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,uBACE,IAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,QAAA;AAAA,MACV,KAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAQ,QAAA;AAAA,MACR,GAAA,EAAI,GAAA;AAAA,MACJ,WAAW,OAAA,CAAQ,SAAA;AAAA,MAEnB,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,QAAK,KAAA,EAAM,QAAA,EAAS,GAAA,EAAI,GAAA,EAAI,eAAW,IAAA,EACtC,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,YAAA,EACtB,QAAA,kBAAA,GAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAM,EAAA,EAAG,UAAA,EAAU,IAAA,EAAC,YAAA,EAAW,EAAA,EAAG,CAAA,EAC/C,CAAA;AAAA,0BACA,GAAA,CAAC,YAAA,EAAA,EAAa,QAAA,EAAS,OAAA,EAAQ,CAAA;AAAA,0BAC/B,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,gBAAA,EACtB,QAAA,kBAAA,GAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAM,EAAA,EAAG,UAAA,EAAU,IAAA,EAAC,YAAA,EAAW,IAAG,CAAA,EAC/C;AAAA,SAAA,EACF,CAAA;AAAA,4BACC,IAAA,EAAA,EAAK,OAAA,EAAQ,aAAA,EAAc,KAAA,EAAM,aAC/B,QAAA,EAAA,OAAA,EACH;AAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useCallback, useMemo } from 'react';
|
|
3
|
+
import { useQueryClient, useQuery } from '@tanstack/react-query';
|
|
4
|
+
import { CellText, MenuTrigger, ButtonIcon, Menu, MenuItem, Table } from '@backstage/ui';
|
|
5
|
+
import { MoreVert, Edit, ToggleOn, ToggleOff, Delete } from '@mui/icons-material';
|
|
6
|
+
import Snackbar from '@mui/material/Snackbar';
|
|
7
|
+
import { Alert } from '@material-ui/lab';
|
|
8
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
9
|
+
import { pagerDutyApiRef } from '../../../api/client.esm.js';
|
|
10
|
+
import { CustomFieldModal } from '../CustomFieldModal.esm.js';
|
|
11
|
+
import { TableSkeleton } from '../MappingsTable/TableSkeleton.esm.js';
|
|
12
|
+
import { useAccountContext } from '../AccountContext.esm.js';
|
|
13
|
+
import { toFieldErrors } from './customFieldErrors.esm.js';
|
|
14
|
+
import { CustomFieldsEmptyState } from './CustomFieldsEmptyState.esm.js';
|
|
15
|
+
import { DeleteCustomFieldDialog } from './DeleteCustomFieldDialog.esm.js';
|
|
16
|
+
|
|
17
|
+
const CustomFieldsTabPanel = () => {
|
|
18
|
+
const pagerDutyApi = useApi(pagerDutyApiRef);
|
|
19
|
+
const queryClient = useQueryClient();
|
|
20
|
+
const { selectedAccount } = useAccountContext();
|
|
21
|
+
const account = selectedAccount || void 0;
|
|
22
|
+
const [selectedCustomField, setSelectedCustomField] = useState(null);
|
|
23
|
+
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
|
24
|
+
const [editSaving, setEditSaving] = useState(false);
|
|
25
|
+
const [editError, setEditError] = useState(null);
|
|
26
|
+
const [toggleError, setToggleError] = useState(null);
|
|
27
|
+
const [fieldToDelete, setFieldToDelete] = useState(null);
|
|
28
|
+
const { data: customFieldsData, isLoading } = useQuery({
|
|
29
|
+
queryKey: ["pagerduty", "customFields", account ?? ""],
|
|
30
|
+
queryFn: () => pagerDutyApi.getCustomFields(account)
|
|
31
|
+
});
|
|
32
|
+
const customFields = customFieldsData?.customFields ?? [];
|
|
33
|
+
const handleOpenEditModal = useCallback((field) => {
|
|
34
|
+
setSelectedCustomField(field);
|
|
35
|
+
setEditError(null);
|
|
36
|
+
setIsEditModalOpen(true);
|
|
37
|
+
}, []);
|
|
38
|
+
const handleCloseEditModal = () => {
|
|
39
|
+
setIsEditModalOpen(false);
|
|
40
|
+
setSelectedCustomField(null);
|
|
41
|
+
setEditError(null);
|
|
42
|
+
};
|
|
43
|
+
const handleUpdateCustomField = async (formData) => {
|
|
44
|
+
if (!selectedCustomField) return;
|
|
45
|
+
const fieldId = selectedCustomField.id;
|
|
46
|
+
setEditSaving(true);
|
|
47
|
+
setEditError(null);
|
|
48
|
+
const result = await pagerDutyApi.updateCustomField(fieldId, formData, account);
|
|
49
|
+
if (result.status === "ok") {
|
|
50
|
+
queryClient.invalidateQueries({ queryKey: ["pagerduty", "customFields", account ?? ""] });
|
|
51
|
+
setIsEditModalOpen(false);
|
|
52
|
+
setSelectedCustomField(null);
|
|
53
|
+
} else {
|
|
54
|
+
setEditError(toFieldErrors(result.error));
|
|
55
|
+
}
|
|
56
|
+
setEditSaving(false);
|
|
57
|
+
};
|
|
58
|
+
const handleToggleEnabled = useCallback(async (field) => {
|
|
59
|
+
const nextEnabled = !field.pagerdutyCustomFieldEnabled;
|
|
60
|
+
const result = await pagerDutyApi.setCustomFieldEnabled(field.id, nextEnabled, account);
|
|
61
|
+
if (result.status === "ok") {
|
|
62
|
+
queryClient.invalidateQueries({ queryKey: ["pagerduty", "customFields", account ?? ""] });
|
|
63
|
+
} else {
|
|
64
|
+
setToggleError(result.error);
|
|
65
|
+
}
|
|
66
|
+
}, [pagerDutyApi, account, queryClient]);
|
|
67
|
+
const columnConfig = useMemo(() => [
|
|
68
|
+
{ id: "name", label: "Custom Field", isRowHeader: true, isSortable: false, cell: (item) => /* @__PURE__ */ jsx(CellText, { title: item.pagerdutyCustomFieldDisplayName }) },
|
|
69
|
+
{ id: "entityPath", label: "Entity Path", isRowHeader: false, isSortable: false, cell: (item) => /* @__PURE__ */ jsx(CellText, { title: item.backstageEntityMappingPath }) },
|
|
70
|
+
{ id: "description", label: "Description", isRowHeader: false, isSortable: false, cell: (item) => /* @__PURE__ */ jsx(CellText, { title: item.description ?? "" }) },
|
|
71
|
+
{
|
|
72
|
+
id: "actions",
|
|
73
|
+
label: "",
|
|
74
|
+
isRowHeader: false,
|
|
75
|
+
isSortable: false,
|
|
76
|
+
cell: (item) => /* @__PURE__ */ jsx(CellText, { title: "", leadingIcon: /* @__PURE__ */ jsxs(MenuTrigger, { children: [
|
|
77
|
+
/* @__PURE__ */ jsx(ButtonIcon, { icon: /* @__PURE__ */ jsx(MoreVert, { fontSize: "small" }), "aria-label": "actions", variant: "tertiary", size: "small" }),
|
|
78
|
+
/* @__PURE__ */ jsxs(Menu, { children: [
|
|
79
|
+
/* @__PURE__ */ jsx(MenuItem, { iconStart: /* @__PURE__ */ jsx(Edit, { fontSize: "small" }), onAction: () => handleOpenEditModal(item), children: "Edit" }),
|
|
80
|
+
/* @__PURE__ */ jsx(
|
|
81
|
+
MenuItem,
|
|
82
|
+
{
|
|
83
|
+
iconStart: item.pagerdutyCustomFieldEnabled ? /* @__PURE__ */ jsx(ToggleOn, { fontSize: "small" }) : /* @__PURE__ */ jsx(ToggleOff, { fontSize: "small" }),
|
|
84
|
+
onAction: () => handleToggleEnabled(item),
|
|
85
|
+
children: item.pagerdutyCustomFieldEnabled ? "Disable" : "Enable"
|
|
86
|
+
}
|
|
87
|
+
),
|
|
88
|
+
/* @__PURE__ */ jsx(MenuItem, { iconStart: /* @__PURE__ */ jsx(Delete, { fontSize: "small" }), onAction: () => setFieldToDelete(item), children: "Delete" })
|
|
89
|
+
] })
|
|
90
|
+
] }) })
|
|
91
|
+
}
|
|
92
|
+
], [handleOpenEditModal, handleToggleEnabled]);
|
|
93
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
94
|
+
isLoading ? /* @__PURE__ */ jsx(
|
|
95
|
+
TableSkeleton,
|
|
96
|
+
{
|
|
97
|
+
columns: [
|
|
98
|
+
{ label: "Custom Field", width: "30%" },
|
|
99
|
+
{ label: "Entity Path", width: "25%" },
|
|
100
|
+
{ label: "Description", width: "35%" },
|
|
101
|
+
{ label: "", width: "10%" }
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
) : /* @__PURE__ */ jsx(
|
|
105
|
+
Table,
|
|
106
|
+
{
|
|
107
|
+
columnConfig,
|
|
108
|
+
data: customFields,
|
|
109
|
+
pagination: { type: "none" },
|
|
110
|
+
rowConfig: {
|
|
111
|
+
getIsDisabled: (item) => !item.pagerdutyCustomFieldEnabled
|
|
112
|
+
},
|
|
113
|
+
emptyState: /* @__PURE__ */ jsx(CustomFieldsEmptyState, { message: "No custom fields have been added" })
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
/* @__PURE__ */ jsx(
|
|
117
|
+
CustomFieldModal,
|
|
118
|
+
{
|
|
119
|
+
open: isEditModalOpen,
|
|
120
|
+
saving: editSaving,
|
|
121
|
+
error: editError,
|
|
122
|
+
onClose: handleCloseEditModal,
|
|
123
|
+
onSave: handleUpdateCustomField,
|
|
124
|
+
mode: "edit",
|
|
125
|
+
initialValues: selectedCustomField ? {
|
|
126
|
+
name: selectedCustomField.pagerdutyCustomFieldDisplayName,
|
|
127
|
+
entityPath: selectedCustomField.backstageEntityMappingPath,
|
|
128
|
+
description: selectedCustomField.description ?? ""
|
|
129
|
+
} : void 0
|
|
130
|
+
}
|
|
131
|
+
),
|
|
132
|
+
/* @__PURE__ */ jsx(
|
|
133
|
+
DeleteCustomFieldDialog,
|
|
134
|
+
{
|
|
135
|
+
field: fieldToDelete,
|
|
136
|
+
onClose: () => setFieldToDelete(null),
|
|
137
|
+
onSuccess: () => setFieldToDelete(null)
|
|
138
|
+
}
|
|
139
|
+
),
|
|
140
|
+
/* @__PURE__ */ jsx(
|
|
141
|
+
Snackbar,
|
|
142
|
+
{
|
|
143
|
+
open: toggleError !== null,
|
|
144
|
+
autoHideDuration: 5e3,
|
|
145
|
+
onClose: () => setToggleError(null),
|
|
146
|
+
anchorOrigin: { vertical: "bottom", horizontal: "right" },
|
|
147
|
+
children: /* @__PURE__ */ jsx(Alert, { severity: "error", onClose: () => setToggleError(null), children: toggleError })
|
|
148
|
+
}
|
|
149
|
+
)
|
|
150
|
+
] });
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export { CustomFieldsTabPanel };
|
|
154
|
+
//# sourceMappingURL=CustomFieldsTabPanel.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CustomFieldsTabPanel.esm.js","sources":["../../../../src/components/PagerDutyPage/CustomFields/CustomFieldsTabPanel.tsx"],"sourcesContent":["import { useState, useMemo, useCallback } from 'react';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport {\n ButtonIcon,\n CellText,\n Menu,\n MenuItem,\n MenuTrigger,\n Table,\n type ColumnConfig,\n} from '@backstage/ui';\nimport { Delete, Edit, MoreVert, ToggleOff, ToggleOn } from '@mui/icons-material';\nimport Snackbar from '@mui/material/Snackbar';\nimport { Alert } from '@material-ui/lab';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { pagerDutyApiRef } from '../../../api';\nimport { BackstageCustomField } from '@pagerduty/backstage-plugin-common';\nimport { CustomFieldModal, FieldErrors } from '../CustomFieldModal';\nimport { TableSkeleton } from '../MappingsTable/TableSkeleton';\nimport { useAccountContext } from '../AccountContext';\nimport { toFieldErrors } from './customFieldErrors';\nimport { CustomFieldsEmptyState } from './CustomFieldsEmptyState';\nimport { DeleteCustomFieldDialog } from './DeleteCustomFieldDialog';\n\nexport const CustomFieldsTabPanel = () => {\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const queryClient = useQueryClient();\n const { selectedAccount } = useAccountContext();\n const account = selectedAccount || undefined;\n const [selectedCustomField, setSelectedCustomField] = useState<BackstageCustomField | null>(null);\n const [isEditModalOpen, setIsEditModalOpen] = useState(false);\n const [editSaving, setEditSaving] = useState(false);\n const [editError, setEditError] = useState<FieldErrors | null>(null);\n const [toggleError, setToggleError] = useState<string | null>(null);\n const [fieldToDelete, setFieldToDelete] = useState<BackstageCustomField | null>(null);\n\n const { data: customFieldsData, isLoading } = useQuery({\n queryKey: ['pagerduty', 'customFields', account ?? ''],\n queryFn: () => pagerDutyApi.getCustomFields(account),\n });\n const customFields = customFieldsData?.customFields ?? [];\n\n const handleOpenEditModal = useCallback((field: BackstageCustomField) => {\n setSelectedCustomField(field);\n setEditError(null);\n setIsEditModalOpen(true);\n }, []);\n\n const handleCloseEditModal = () => {\n setIsEditModalOpen(false);\n setSelectedCustomField(null);\n setEditError(null);\n };\n\n const handleUpdateCustomField = async (formData: { name: string; entityPath: string; description: string }) => {\n if (!selectedCustomField) return;\n const fieldId = selectedCustomField.id;\n setEditSaving(true);\n setEditError(null);\n const result = await pagerDutyApi.updateCustomField(fieldId, formData, account);\n if (result.status === 'ok') {\n queryClient.invalidateQueries({ queryKey: ['pagerduty', 'customFields', account ?? ''] });\n setIsEditModalOpen(false);\n setSelectedCustomField(null);\n } else {\n setEditError(toFieldErrors(result.error));\n }\n setEditSaving(false);\n };\n\n const handleToggleEnabled = useCallback(async (field: BackstageCustomField) => {\n const nextEnabled = !field.pagerdutyCustomFieldEnabled;\n const result = await pagerDutyApi.setCustomFieldEnabled(field.id, nextEnabled, account);\n if (result.status === 'ok') {\n queryClient.invalidateQueries({ queryKey: ['pagerduty', 'customFields', account ?? ''] });\n } else {\n setToggleError(result.error);\n }\n }, [pagerDutyApi, account, queryClient]);\n\n const columnConfig: ColumnConfig<BackstageCustomField>[] = useMemo(() => [\n { id: 'name', label: 'Custom Field', isRowHeader: true, isSortable: false, cell: item => <CellText title={item.pagerdutyCustomFieldDisplayName} /> },\n { id: 'entityPath', label: 'Entity Path', isRowHeader: false, isSortable: false, cell: item => <CellText title={item.backstageEntityMappingPath} /> },\n { id: 'description', label: 'Description', isRowHeader: false, isSortable: false, cell: item => <CellText title={item.description ?? ''} /> },\n {\n id: 'actions', label: '', isRowHeader: false, isSortable: false,\n cell: item => (\n <CellText title=\"\" leadingIcon={\n <MenuTrigger>\n <ButtonIcon icon={<MoreVert fontSize=\"small\" />} aria-label=\"actions\" variant=\"tertiary\" size=\"small\" />\n <Menu>\n <MenuItem iconStart={<Edit fontSize=\"small\" />} onAction={() => handleOpenEditModal(item)}>Edit</MenuItem>\n <MenuItem\n iconStart={\n item.pagerdutyCustomFieldEnabled ? (\n <ToggleOn fontSize=\"small\" />\n ) : (\n <ToggleOff fontSize=\"small\" />\n )\n }\n onAction={() => handleToggleEnabled(item)}\n >\n {item.pagerdutyCustomFieldEnabled ? 'Disable' : 'Enable'}\n </MenuItem>\n <MenuItem iconStart={<Delete fontSize=\"small\" />} onAction={() => setFieldToDelete(item)}>Delete</MenuItem>\n </Menu>\n </MenuTrigger>\n } />\n ),\n },\n ], [handleOpenEditModal, handleToggleEnabled]);\n\n return (\n <>\n {isLoading ? (\n <TableSkeleton\n columns={[\n { label: 'Custom Field', width: '30%' },\n { label: 'Entity Path', width: '25%' },\n { label: 'Description', width: '35%' },\n { label: '', width: '10%' },\n ]}\n />\n ) : (\n <Table\n columnConfig={columnConfig}\n data={customFields}\n pagination={{ type: 'none' }}\n rowConfig={{\n getIsDisabled: item => !item.pagerdutyCustomFieldEnabled,\n }}\n emptyState={\n <CustomFieldsEmptyState message='No custom fields have been added' />\n }\n />\n )}\n\n <CustomFieldModal\n open={isEditModalOpen}\n saving={editSaving}\n error={editError}\n onClose={handleCloseEditModal}\n onSave={handleUpdateCustomField}\n mode=\"edit\"\n initialValues={selectedCustomField ? {\n name: selectedCustomField.pagerdutyCustomFieldDisplayName,\n entityPath: selectedCustomField.backstageEntityMappingPath,\n description: selectedCustomField.description ?? '',\n } : undefined}\n />\n\n <DeleteCustomFieldDialog\n field={fieldToDelete}\n onClose={() => setFieldToDelete(null)}\n onSuccess={() => setFieldToDelete(null)}\n />\n\n <Snackbar\n open={toggleError !== null}\n autoHideDuration={5000}\n onClose={() => setToggleError(null)}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n >\n <Alert severity=\"error\" onClose={() => setToggleError(null)}>\n {toggleError}\n </Alert>\n </Snackbar>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
4
|
+
import { Dialog, DialogHeader, DialogBody, Box, Text, DialogFooter, Flex, Button } from '@backstage/ui';
|
|
5
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
6
|
+
import { pagerDutyApiRef } from '../../../api/client.esm.js';
|
|
7
|
+
import { useAccountContext } from '../AccountContext.esm.js';
|
|
8
|
+
|
|
9
|
+
const DeleteCustomFieldDialog = ({
|
|
10
|
+
field,
|
|
11
|
+
onClose,
|
|
12
|
+
onSuccess
|
|
13
|
+
}) => {
|
|
14
|
+
const pagerDutyApi = useApi(pagerDutyApiRef);
|
|
15
|
+
const queryClient = useQueryClient();
|
|
16
|
+
const { selectedAccount } = useAccountContext();
|
|
17
|
+
const account = selectedAccount || void 0;
|
|
18
|
+
const [deleting, setDeleting] = useState(false);
|
|
19
|
+
const [error, setError] = useState(null);
|
|
20
|
+
const handleClose = () => {
|
|
21
|
+
setError(null);
|
|
22
|
+
onClose();
|
|
23
|
+
};
|
|
24
|
+
const handleConfirm = async () => {
|
|
25
|
+
if (!field) return;
|
|
26
|
+
setDeleting(true);
|
|
27
|
+
setError(null);
|
|
28
|
+
const result = await pagerDutyApi.deleteCustomField(field.id, account);
|
|
29
|
+
if (result.status === "ok") {
|
|
30
|
+
queryClient.invalidateQueries({ queryKey: ["pagerduty", "customFields", account ?? ""] });
|
|
31
|
+
onSuccess();
|
|
32
|
+
} else {
|
|
33
|
+
setError(result.error);
|
|
34
|
+
}
|
|
35
|
+
setDeleting(false);
|
|
36
|
+
};
|
|
37
|
+
return /* @__PURE__ */ jsxs(
|
|
38
|
+
Dialog,
|
|
39
|
+
{
|
|
40
|
+
isOpen: field !== null,
|
|
41
|
+
onOpenChange: (isOpen) => !isOpen && handleClose(),
|
|
42
|
+
width: 440,
|
|
43
|
+
children: [
|
|
44
|
+
/* @__PURE__ */ jsx(DialogHeader, { children: "Delete Custom Field" }),
|
|
45
|
+
/* @__PURE__ */ jsxs(DialogBody, { children: [
|
|
46
|
+
error && /* @__PURE__ */ jsx(Box, { style: { marginBottom: 16 }, children: /* @__PURE__ */ jsx(Text, { variant: "body-small", color: "danger", children: error }) }),
|
|
47
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
48
|
+
"Are you sure you want to delete ",
|
|
49
|
+
/* @__PURE__ */ jsx("strong", { children: field?.pagerdutyCustomFieldDisplayName }),
|
|
50
|
+
"? This will remove the custom field from PagerDuty and reclaim its slot."
|
|
51
|
+
] })
|
|
52
|
+
] }),
|
|
53
|
+
/* @__PURE__ */ jsx(DialogFooter, { children: /* @__PURE__ */ jsxs(Flex, { gap: "2", justify: "end", children: [
|
|
54
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", isDisabled: deleting, onClick: handleClose, children: "Cancel" }),
|
|
55
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", isDisabled: deleting, onClick: handleConfirm, children: deleting ? "Deleting\u2026" : "Delete" })
|
|
56
|
+
] }) })
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export { DeleteCustomFieldDialog };
|
|
63
|
+
//# sourceMappingURL=DeleteCustomFieldDialog.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeleteCustomFieldDialog.esm.js","sources":["../../../../src/components/PagerDutyPage/CustomFields/DeleteCustomFieldDialog.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport {\n Box,\n Button,\n Dialog,\n DialogBody,\n DialogFooter,\n DialogHeader,\n Flex,\n Text,\n} from '@backstage/ui';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { BackstageCustomField } from '@pagerduty/backstage-plugin-common';\nimport { pagerDutyApiRef } from '../../../api';\nimport { useAccountContext } from '../AccountContext';\n\ninterface DeleteCustomFieldDialogProps {\n field: BackstageCustomField | null;\n onClose: () => void;\n onSuccess: () => void;\n}\n\nexport const DeleteCustomFieldDialog = ({\n field,\n onClose,\n onSuccess,\n}: DeleteCustomFieldDialogProps) => {\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const queryClient = useQueryClient();\n const { selectedAccount } = useAccountContext();\n const account = selectedAccount || undefined;\n\n const [deleting, setDeleting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleClose = () => {\n setError(null);\n onClose();\n };\n\n const handleConfirm = async () => {\n if (!field) return;\n setDeleting(true);\n setError(null);\n const result = await pagerDutyApi.deleteCustomField(field.id, account);\n if (result.status === 'ok') {\n queryClient.invalidateQueries({ queryKey: ['pagerduty', 'customFields', account ?? ''] });\n onSuccess();\n } else {\n setError(result.error);\n }\n setDeleting(false);\n };\n\n return (\n <Dialog\n isOpen={field !== null}\n onOpenChange={isOpen => !isOpen && handleClose()}\n width={440}\n >\n <DialogHeader>Delete Custom Field</DialogHeader>\n <DialogBody>\n {error && (\n <Box style={{ marginBottom: 16 }}>\n <Text variant=\"body-small\" color=\"danger\">{error}</Text>\n </Box>\n )}\n <Text>\n Are you sure you want to delete <strong>{field?.pagerdutyCustomFieldDisplayName}</strong>? This will remove the custom field from PagerDuty and reclaim its slot.\n </Text>\n </DialogBody>\n <DialogFooter>\n <Flex gap=\"2\" justify=\"end\">\n <Button variant=\"secondary\" isDisabled={deleting} onClick={handleClose}>\n Cancel\n </Button>\n <Button variant=\"primary\" isDisabled={deleting} onClick={handleConfirm}>\n {deleting ? 'Deleting…' : 'Delete'}\n </Button>\n </Flex>\n </DialogFooter>\n </Dialog>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAuBO,MAAM,0BAA0B,CAAC;AAAA,EACtC,KAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,KAAoC;AAClC,EAAA,MAAM,YAAA,GAAe,OAAO,eAAe,CAAA;AAC3C,EAAA,MAAM,cAAc,cAAA,EAAe;AACnC,EAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,iBAAA,EAAkB;AAC9C,EAAA,MAAM,UAAU,eAAA,IAAmB,MAAA;AAEnC,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAS,KAAK,CAAA;AAC9C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AAEtD,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA;AAEA,EAAA,MAAM,gBAAgB,YAAY;AAChC,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,WAAA,CAAY,IAAI,CAAA;AAChB,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,MAAM,SAAS,MAAM,YAAA,CAAa,iBAAA,CAAkB,KAAA,CAAM,IAAI,OAAO,CAAA;AACrE,IAAA,IAAI,MAAA,CAAO,WAAW,IAAA,EAAM;AAC1B,MAAA,WAAA,CAAY,iBAAA,CAAkB,EAAE,QAAA,EAAU,CAAC,aAAa,cAAA,EAAgB,OAAA,IAAW,EAAE,CAAA,EAAG,CAAA;AACxF,MAAA,SAAA,EAAU;AAAA,IACZ,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,OAAO,KAAK,CAAA;AAAA,IACvB;AACA,IAAA,WAAA,CAAY,KAAK,CAAA;AAAA,EACnB,CAAA;AAEA,EAAA,uBACE,IAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,QAAQ,KAAA,KAAU,IAAA;AAAA,MAClB,YAAA,EAAc,CAAA,MAAA,KAAU,CAAC,MAAA,IAAU,WAAA,EAAY;AAAA,MAC/C,KAAA,EAAO,GAAA;AAAA,MAEP,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,gBAAa,QAAA,EAAA,qBAAA,EAAmB,CAAA;AAAA,6BAChC,UAAA,EAAA,EACE,QAAA,EAAA;AAAA,UAAA,KAAA,oBACC,GAAA,CAAC,GAAA,EAAA,EAAI,KAAA,EAAO,EAAE,cAAc,EAAA,EAAG,EAC7B,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,YAAA,EAAa,KAAA,EAAM,QAAA,EAAU,iBAAM,CAAA,EACnD,CAAA;AAAA,+BAED,IAAA,EAAA,EAAK,QAAA,EAAA;AAAA,YAAA,kCAAA;AAAA,4BAC4B,GAAA,CAAC,QAAA,EAAA,EAAQ,QAAA,EAAA,KAAA,EAAO,+BAAA,EAAgC,CAAA;AAAA,YAAS;AAAA,WAAA,EAC3F;AAAA,SAAA,EACF,CAAA;AAAA,4BACC,YAAA,EAAA,EACC,QAAA,kBAAA,IAAA,CAAC,QAAK,GAAA,EAAI,GAAA,EAAI,SAAQ,KAAA,EACpB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,UAAO,OAAA,EAAQ,WAAA,EAAY,YAAY,QAAA,EAAU,OAAA,EAAS,aAAa,QAAA,EAAA,QAAA,EAExE,CAAA;AAAA,0BACA,GAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAQ,SAAA,EAAU,UAAA,EAAY,UAAU,OAAA,EAAS,aAAA,EACtD,QAAA,EAAA,QAAA,GAAW,gBAAA,GAAc,QAAA,EAC5B;AAAA,SAAA,EACF,CAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
|