@pagerduty/backstage-plugin 0.12.1-next.8 → 0.12.1-next.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/{index-9c96bd08.esm.js → index-03e34683.esm.js} +2 -2
- package/dist/esm/{index-9c96bd08.esm.js.map → index-03e34683.esm.js.map} +1 -1
- package/dist/esm/{index-df18b73c.esm.js → index-4c05ac30.esm.js} +23 -5
- package/dist/esm/index-4c05ac30.esm.js.map +1 -0
- package/dist/esm/index-f76a5582.esm.js +245 -0
- package/dist/esm/index-f76a5582.esm.js.map +1 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.esm.js +1 -1
- package/package.json +9 -3
- package/dist/esm/index-deaaadcb.esm.js +0 -171
- package/dist/esm/index-deaaadcb.esm.js.map +0 -1
- package/dist/esm/index-df18b73c.esm.js.map +0 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import React, { useState, useMemo } from 'react';
|
|
2
|
+
import { Box, DialogTitle, DialogContent, DialogActions, Tooltip, IconButton, Grid } from '@material-ui/core';
|
|
3
|
+
import { Page, Header, Content } from '@backstage/core-components';
|
|
4
|
+
import EditIcon from '@mui/icons-material/Edit';
|
|
5
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
6
|
+
import { p as pagerDutyApiRef } from './index-4c05ac30.esm.js';
|
|
7
|
+
import { QueryClient, QueryClientProvider, useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
8
|
+
import { useMaterialReactTable, MRT_EditActionButtons, MaterialReactTable } from 'material-react-table';
|
|
9
|
+
import { catalogApiRef } from '@backstage/plugin-catalog-react';
|
|
10
|
+
import '@backstage/errors';
|
|
11
|
+
import '@backstage/plugin-home-react';
|
|
12
|
+
import 'luxon';
|
|
13
|
+
import '@material-ui/icons/OpenInBrowser';
|
|
14
|
+
import '../assets/emptystate.svg';
|
|
15
|
+
import 'react-use/lib/useAsyncFn';
|
|
16
|
+
import '@material-ui/lab';
|
|
17
|
+
import '../assets/forbiddenstate.svg';
|
|
18
|
+
import '@material-ui/core/Avatar';
|
|
19
|
+
import '@material-ui/icons/Notifications';
|
|
20
|
+
import 'react-use/lib/useAsync';
|
|
21
|
+
import '@material-ui/icons/Link';
|
|
22
|
+
import '../assets/PD-Green.svg';
|
|
23
|
+
import '../assets/PD-White.svg';
|
|
24
|
+
import 'validate-color';
|
|
25
|
+
import '@material-ui/icons/Info';
|
|
26
|
+
import '@material-ui/icons/CheckCircle';
|
|
27
|
+
import '@material-ui/icons/RadioButtonUnchecked';
|
|
28
|
+
import '@material-ui/core/styles';
|
|
29
|
+
import 'react-use';
|
|
30
|
+
import '@material-ui/lab/Alert/Alert';
|
|
31
|
+
import '@backstage/catalog-model';
|
|
32
|
+
import '@material-ui/icons/AddAlert';
|
|
33
|
+
import '@material-ui/icons/ExpandMore';
|
|
34
|
+
|
|
35
|
+
function getColorFromStatus(status) {
|
|
36
|
+
switch (status) {
|
|
37
|
+
case "InSync":
|
|
38
|
+
return "green";
|
|
39
|
+
case "OutOfSync":
|
|
40
|
+
return "red";
|
|
41
|
+
case "NotMapped":
|
|
42
|
+
return "orange";
|
|
43
|
+
default:
|
|
44
|
+
return "gray";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const ServiceMappingComponent = () => {
|
|
48
|
+
const [catalogEntities, setCatalogEntities] = useState([]);
|
|
49
|
+
const [entityOptions, setEntityOptions] = useState([]);
|
|
50
|
+
const pagerDutyApi = useApi(pagerDutyApiRef);
|
|
51
|
+
const catalogApi = useApi(catalogApiRef);
|
|
52
|
+
function useGetMappings() {
|
|
53
|
+
return useQuery({
|
|
54
|
+
queryKey: ["mappings"],
|
|
55
|
+
queryFn: async () => {
|
|
56
|
+
const { mappings: foundMappings } = await pagerDutyApi.getEntityMappings();
|
|
57
|
+
return foundMappings;
|
|
58
|
+
},
|
|
59
|
+
refetchOnWindowFocus: false
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function useUpdateMapping() {
|
|
63
|
+
const queryClient2 = useQueryClient();
|
|
64
|
+
return useMutation({
|
|
65
|
+
mutationFn: async (mapping) => {
|
|
66
|
+
return await pagerDutyApi.storeServiceMapping(
|
|
67
|
+
mapping.serviceId,
|
|
68
|
+
mapping.entityRef
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
// client side optimistic update
|
|
72
|
+
onMutate: (newMappingInfo) => {
|
|
73
|
+
queryClient2.setQueryData(
|
|
74
|
+
["updateMappings"],
|
|
75
|
+
(prevMappings) => prevMappings == null ? void 0 : prevMappings.map(
|
|
76
|
+
(prevMapping) => {
|
|
77
|
+
var _a;
|
|
78
|
+
if (prevMapping.serviceId === newMappingInfo.serviceId) {
|
|
79
|
+
newMappingInfo.entityName = ((_a = catalogEntities.find((entity) => entity.id === newMappingInfo.entityRef)) == null ? void 0 : _a.name) || "";
|
|
80
|
+
return newMappingInfo;
|
|
81
|
+
}
|
|
82
|
+
return prevMapping;
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function fetchCatalogEntities() {
|
|
90
|
+
catalogApi.getEntities({
|
|
91
|
+
filter: { kind: "Component" }
|
|
92
|
+
}).then(({ items }) => {
|
|
93
|
+
const entities = [];
|
|
94
|
+
items.forEach((entity) => {
|
|
95
|
+
var _a, _b, _c, _d, _e, _f;
|
|
96
|
+
entities.push({
|
|
97
|
+
name: (_a = entity.metadata) == null ? void 0 : _a.name,
|
|
98
|
+
id: (_c = (_b = entity.metadata) == null ? void 0 : _b.uid) != null ? _c : "",
|
|
99
|
+
system: JSON.stringify((_d = entity.spec) == null ? void 0 : _d.system) || "",
|
|
100
|
+
owner: JSON.stringify((_e = entity.spec) == null ? void 0 : _e.owner) || "",
|
|
101
|
+
lifecycle: JSON.stringify((_f = entity.spec) == null ? void 0 : _f.lifecycle) || ""
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
setCatalogEntities(entities);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function getCatalogEntityOptions() {
|
|
108
|
+
if (catalogEntities.length === 0) {
|
|
109
|
+
fetchCatalogEntities();
|
|
110
|
+
}
|
|
111
|
+
if (entityOptions.length === 0) {
|
|
112
|
+
const options = [];
|
|
113
|
+
options.push({ value: "", label: "None" });
|
|
114
|
+
catalogEntities.forEach((entity) => {
|
|
115
|
+
options.push({
|
|
116
|
+
value: entity.id,
|
|
117
|
+
label: entity.name
|
|
118
|
+
});
|
|
119
|
+
setEntityOptions(options);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return entityOptions;
|
|
123
|
+
}
|
|
124
|
+
const DenseTable = () => {
|
|
125
|
+
const [validationErrors, setValidationErrors] = useState({});
|
|
126
|
+
const columns = useMemo(
|
|
127
|
+
() => [
|
|
128
|
+
{
|
|
129
|
+
accessorKey: "serviceId",
|
|
130
|
+
header: "Service ID",
|
|
131
|
+
visibleInShowHideMenu: false,
|
|
132
|
+
enableEditing: false
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
accessorKey: "serviceName",
|
|
136
|
+
header: "PagerDuty Service",
|
|
137
|
+
enableEditing: false
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
accessorKey: "team",
|
|
141
|
+
header: "Team",
|
|
142
|
+
enableEditing: false
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
accessorKey: "escalationPolicy",
|
|
146
|
+
header: "Escalation Policy",
|
|
147
|
+
enableEditing: false
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
accessorKey: "entityRef",
|
|
151
|
+
header: "Mapping",
|
|
152
|
+
visibleInShowHideMenu: false,
|
|
153
|
+
editVariant: "select",
|
|
154
|
+
editSelectOptions: getCatalogEntityOptions(),
|
|
155
|
+
muiEditTextFieldProps: {
|
|
156
|
+
select: true,
|
|
157
|
+
error: !!(validationErrors == null ? void 0 : validationErrors.state),
|
|
158
|
+
helperText: validationErrors == null ? void 0 : validationErrors.state
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
accessorKey: "entityName",
|
|
163
|
+
header: "Mapped Entity Name",
|
|
164
|
+
enableEditing: false
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
accessorKey: "status",
|
|
168
|
+
header: "Status",
|
|
169
|
+
enableEditing: false,
|
|
170
|
+
Cell: ({ cell }) => /* @__PURE__ */ React.createElement(
|
|
171
|
+
Box,
|
|
172
|
+
{
|
|
173
|
+
component: "span",
|
|
174
|
+
bgcolor: getColorFromStatus(cell.getValue()),
|
|
175
|
+
borderRadius: "0.25rem",
|
|
176
|
+
color: "white",
|
|
177
|
+
p: "0.25rem"
|
|
178
|
+
},
|
|
179
|
+
cell.getValue()
|
|
180
|
+
)
|
|
181
|
+
}
|
|
182
|
+
],
|
|
183
|
+
[validationErrors]
|
|
184
|
+
);
|
|
185
|
+
const {
|
|
186
|
+
data: fetchedMappings = [],
|
|
187
|
+
isError: isLoadingMappingsError,
|
|
188
|
+
isFetching: isFetchingMappings,
|
|
189
|
+
isLoading: isLoadingMappings
|
|
190
|
+
} = useGetMappings();
|
|
191
|
+
const { mutateAsync: updateMapping, isPending: isUpdatingMapping } = useUpdateMapping();
|
|
192
|
+
const handleSaveMapping = async ({ values, table }) => {
|
|
193
|
+
var _a;
|
|
194
|
+
setValidationErrors({});
|
|
195
|
+
values.entityName = ((_a = catalogEntities.find((entity) => entity.id === values.entityRef)) == null ? void 0 : _a.name) || "";
|
|
196
|
+
values.status = "RefreshToUpdate";
|
|
197
|
+
await updateMapping(values);
|
|
198
|
+
table.setEditingRow(null);
|
|
199
|
+
};
|
|
200
|
+
const dataTable = useMaterialReactTable({
|
|
201
|
+
columns,
|
|
202
|
+
data: fetchedMappings,
|
|
203
|
+
editDisplayMode: "modal",
|
|
204
|
+
// default ('row', 'cell', 'table', and 'custom' are also available)
|
|
205
|
+
enableEditing: true,
|
|
206
|
+
positionActionsColumn: "last",
|
|
207
|
+
enableStickyHeader: true,
|
|
208
|
+
getRowId: (row) => row.serviceId,
|
|
209
|
+
muiToolbarAlertBannerProps: isLoadingMappingsError ? {
|
|
210
|
+
color: "error",
|
|
211
|
+
children: "Error loading data"
|
|
212
|
+
} : void 0,
|
|
213
|
+
muiTableContainerProps: {
|
|
214
|
+
sx: {
|
|
215
|
+
minHeight: "500px"
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
onEditingRowCancel: () => setValidationErrors({}),
|
|
219
|
+
onEditingRowSave: handleSaveMapping,
|
|
220
|
+
// optionally customize modal content
|
|
221
|
+
renderEditRowDialogContent: ({ table, row, internalEditComponents }) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(DialogTitle, null, "Edit Mapping"), /* @__PURE__ */ React.createElement(DialogContent, null, internalEditComponents, " "), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(MRT_EditActionButtons, { variant: "text", table, row }))),
|
|
222
|
+
renderRowActions: ({ row, table }) => /* @__PURE__ */ React.createElement(Box, { sx: { display: "flex" } }, /* @__PURE__ */ React.createElement(Tooltip, { title: "Edit" }, /* @__PURE__ */ React.createElement(IconButton, { onClick: () => table.setEditingRow(row) }, /* @__PURE__ */ React.createElement(EditIcon, null)))),
|
|
223
|
+
state: {
|
|
224
|
+
isLoading: isLoadingMappings,
|
|
225
|
+
isSaving: isUpdatingMapping,
|
|
226
|
+
showAlertBanner: isLoadingMappingsError,
|
|
227
|
+
showProgressBars: isFetchingMappings,
|
|
228
|
+
columnVisibility: {
|
|
229
|
+
serviceId: false,
|
|
230
|
+
entityRef: false
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
return /* @__PURE__ */ React.createElement(MaterialReactTable, { table: dataTable });
|
|
235
|
+
};
|
|
236
|
+
const queryClient = new QueryClient();
|
|
237
|
+
return /* @__PURE__ */ React.createElement(QueryClientProvider, { client: queryClient }, /* @__PURE__ */ React.createElement(DenseTable, null));
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const PagerDutyPage = () => {
|
|
241
|
+
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(Header, { title: "PagerDuty", subtitle: "Advanced configurations" }), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(ServiceMappingComponent, null)))));
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
export { PagerDutyPage };
|
|
245
|
+
//# sourceMappingURL=index-f76a5582.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-f76a5582.esm.js","sources":["../../src/components/PagerDutyPage/ServiceMappingComponent.tsx","../../src/components/PagerDutyPage/index.tsx"],"sourcesContent":["import React, { useMemo, useState } from \"react\";\nimport {\n Box,\n // Button,\n DialogActions,\n DialogContent,\n DialogTitle,\n // FormControl,\n IconButton,\n // MenuItem,\n // Select,\n Tooltip,\n // Typography,\n} from \"@material-ui/core\";\nimport EditIcon from \"@mui/icons-material/Edit\";\nimport { PagerDutyEntityMapping } from \"@pagerduty/backstage-plugin-common\";\nimport { useApi } from \"@backstage/core-plugin-api\";\nimport { pagerDutyApiRef } from \"../../api\";\nimport {\n QueryClient,\n QueryClientProvider,\n useMutation,\n useQuery,\n useQueryClient,\n} from \"@tanstack/react-query\";\nimport {\n DropdownOption,\n MRT_ColumnDef,\n MRT_EditActionButtons,\n MRT_TableOptions,\n MaterialReactTable,\n useMaterialReactTable,\n} from \"material-react-table\";\nimport { catalogApiRef } from \"@backstage/plugin-catalog-react\";\n// import { catalogApiRef } from \"@backstage/plugin-catalog-react\";\n// import { Entity } from \"@backstage/catalog-model\";\n\ntype Service = {\n name: string; // \"Ads\"\n id: string; // \"QWe1j283n12j132\"\n system: string; // \"Production\"\n owner: string; // \"Mapped\"\n lifecycle: string; // \"Ads\"\n};\n\n// type TableItem = {\n// name: string | undefined;\n// team: string | undefined;\n// escalationPolicy: string | undefined;\n// mappingStatus: JSX.Element;\n// mapping: JSX.Element;\n// actions: JSX.Element;\n// };\n\n// type DenseTableProps = {\n// items: TableItem[];\n// };\n\nfunction getColorFromStatus(status?: string) {\n switch (status) {\n case \"InSync\":\n return \"green\";\n case \"OutOfSync\":\n return \"red\";\n case \"NotMapped\":\n return \"orange\";\n default:\n return \"gray\";\n }\n}\n\nexport const ServiceMappingComponent = () => {\n\n const [catalogEntities, setCatalogEntities] = useState<Service[]>([]);\n const [entityOptions, setEntityOptions] = useState<DropdownOption[]>([]);\n\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const catalogApi = useApi(catalogApiRef);\n\n // READ hook (get mappings from api)\n function useGetMappings() {\n return useQuery<PagerDutyEntityMapping[]>({\n queryKey: [\"mappings\"],\n queryFn: async () => {\n // send api request here\n const { mappings: foundMappings } =\n await pagerDutyApi.getEntityMappings();\n\n return foundMappings;\n },\n refetchOnWindowFocus: false,\n });\n }\n\n // UPDATE hook (put mapping in api)\n function useUpdateMapping() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (mapping: PagerDutyEntityMapping) => {\n return await pagerDutyApi.storeServiceMapping(\n mapping.serviceId,\n mapping.entityRef\n );\n },\n // client side optimistic update\n onMutate: (newMappingInfo: PagerDutyEntityMapping) => {\n queryClient.setQueryData([\"updateMappings\"], (prevMappings: any) =>\n prevMappings?.map((prevMapping: PagerDutyEntityMapping) => {\n if (prevMapping.serviceId === newMappingInfo.serviceId) {\n newMappingInfo.entityName = catalogEntities.find((entity) => entity.id === newMappingInfo.entityRef)?.name || \"\";\n\n return newMappingInfo;\n }\n return prevMapping; \n }\n )\n );\n },\n });\n }\n\n function fetchCatalogEntities() {\n catalogApi\n .getEntities({\n filter: { kind: \"Component\" },\n })\n .then(({ items }) => {\n const entities: Service[] = [];\n items.forEach((entity: any) => {\n entities.push({\n name: entity.metadata?.name,\n id: entity.metadata?.uid ?? \"\",\n system: JSON.stringify(entity.spec?.system) || \"\",\n owner: JSON.stringify(entity.spec?.owner) || \"\",\n lifecycle: JSON.stringify(entity.spec?.lifecycle) || \"\",\n });\n });\n setCatalogEntities(entities);\n });\n }\n\n function getCatalogEntityOptions() : DropdownOption[] {\n // fetch entities if not already fetched\n if (catalogEntities.length === 0) {\n fetchCatalogEntities();\n }\n\n if(entityOptions.length === 0) {\n const options : DropdownOption[] = [];\n // Add empty object\n options.push({ value: \"\", label: \"None\" });\n\n catalogEntities.forEach((entity) => {\n options.push({\n value: entity.id,\n label: entity.name,\n });\n setEntityOptions(options);\n });\n }\n\n return entityOptions;\n }\n\n const DenseTable = () => {\n const [validationErrors, setValidationErrors] = useState<\n Record<string, string | undefined>\n >({});\n\n const columns = useMemo<MRT_ColumnDef<PagerDutyEntityMapping>[]>(\n () => [\n {\n accessorKey: \"serviceId\",\n header: \"Service ID\",\n visibleInShowHideMenu: false,\n enableEditing: false,\n },\n {\n accessorKey: \"serviceName\",\n header: \"PagerDuty Service\",\n enableEditing: false,\n },\n {\n accessorKey: \"team\",\n header: \"Team\",\n enableEditing: false,\n },\n {\n accessorKey: \"escalationPolicy\",\n header: \"Escalation Policy\",\n enableEditing: false,\n },\n {\n accessorKey: \"entityRef\",\n header: \"Mapping\",\n visibleInShowHideMenu: false,\n editVariant: \"select\",\n editSelectOptions: getCatalogEntityOptions(),\n muiEditTextFieldProps: {\n select: true,\n error: !!validationErrors?.state,\n helperText: validationErrors?.state,\n },\n },\n {\n accessorKey: \"entityName\",\n header: \"Mapped Entity Name\",\n enableEditing: false,\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n enableEditing: false,\n Cell: ({ cell }) => (\n <Box\n component=\"span\"\n bgcolor={getColorFromStatus(cell.getValue<string>())}\n borderRadius=\"0.25rem\"\n color=\"white\"\n p=\"0.25rem\"\n >\n {cell.getValue<string>()}\n </Box>\n ),\n },\n ],\n [validationErrors]\n );\n\n // call READ hook\n const {\n data: fetchedMappings = [],\n isError: isLoadingMappingsError,\n isFetching: isFetchingMappings,\n isLoading: isLoadingMappings,\n } = useGetMappings();\n\n // call UPDATE hook\n const { mutateAsync: updateMapping, isPending: isUpdatingMapping } =\n useUpdateMapping();\n\n // UPDATE action\n const handleSaveMapping: MRT_TableOptions<PagerDutyEntityMapping>[\"onEditingRowSave\"] =\n async ({ values, table }) => {\n setValidationErrors({});\n values.entityName = catalogEntities.find((entity) => entity.id === values.entityRef)?.name || \"\";\n values.status = \"RefreshToUpdate\";\n await updateMapping(values);\n table.setEditingRow(null); // exit editing mode\n };\n\n const dataTable = useMaterialReactTable({\n columns,\n data: fetchedMappings,\n editDisplayMode: \"modal\", // default ('row', 'cell', 'table', and 'custom' are also available)\n enableEditing: true,\n positionActionsColumn: \"last\",\n enableStickyHeader: true,\n getRowId: (row) => row.serviceId,\n muiToolbarAlertBannerProps: isLoadingMappingsError\n ? {\n color: \"error\",\n children: \"Error loading data\",\n }\n : undefined,\n muiTableContainerProps: {\n sx: {\n minHeight: \"500px\",\n },\n },\n onEditingRowCancel: () => setValidationErrors({}),\n onEditingRowSave: handleSaveMapping,\n // optionally customize modal content\n renderEditRowDialogContent: ({ table, row, internalEditComponents }) => (\n <>\n <DialogTitle>Edit Mapping</DialogTitle>\n <DialogContent>\n {internalEditComponents}{\" \"}\n {/* or render custom edit components here */}\n </DialogContent>\n <DialogActions>\n <MRT_EditActionButtons variant=\"text\" table={table} row={row} />\n </DialogActions>\n </>\n ),\n renderRowActions: ({ row, table }) => (\n <Box sx={{ display: \"flex\" }}>\n <Tooltip title=\"Edit\">\n <IconButton onClick={() => table.setEditingRow(row)}>\n <EditIcon />\n </IconButton>\n </Tooltip>\n </Box>\n ),\n state: {\n isLoading: isLoadingMappings, \n isSaving: isUpdatingMapping,\n showAlertBanner: isLoadingMappingsError, \n showProgressBars: isFetchingMappings, \n columnVisibility: {\n serviceId: false,\n entityRef: false,\n }\n },\n });\n\n return <MaterialReactTable table={dataTable} />;\n };\n\n const queryClient = new QueryClient();\n\n return (\n <QueryClientProvider client={queryClient}>\n <DenseTable />\n </QueryClientProvider>\n );\n};\n","import React from \"react\";\nimport { Grid } from \"@material-ui/core\";\nimport { Header, Page, Content } from \"@backstage/core-components\";\nimport { ServiceMappingComponent } from \"./ServiceMappingComponent\";\n\n/** @public */\nexport const PagerDutyPage = () => {\n return (\n <Page themeId=\"home\">\n <Header title=\"PagerDuty\" subtitle=\"Advanced configurations\" />\n <Content>\n {/* <Grid container spacing={3} direction=\"column\">\n <Grid item alignContent=\"flex-end\">\n <Button variant=\"contained\" color=\"primary\" onClick={() => {handleImport()}}>\n Import\n </Button>\n <Button variant=\"outlined\" color=\"primary\" onClick={() => {handleSave()}}>\n Save\n </Button>\n </Grid>\n </Grid> */}\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <ServiceMappingComponent />\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":["queryClient"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import * as react from 'react';
|
|
|
5
5
|
import react__default, { ReactNode } from 'react';
|
|
6
6
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
7
7
|
import { DiscoveryApi, FetchApi, ConfigApi } from '@backstage/core-plugin-api';
|
|
8
|
-
import {
|
|
8
|
+
import { PagerDutyEntityMappingResponse, PagerDutyServiceResponse, PagerDutyIncidentsResponse, PagerDutyChangeEventsResponse, PagerDutyServiceStandardsResponse, PagerDutyServiceMetricsResponse, PagerDutyUser } from '@pagerduty/backstage-plugin-common';
|
|
9
9
|
|
|
10
10
|
/** @public */
|
|
11
11
|
declare const isPluginApplicableToEntity$1: (entity: Entity) => boolean;
|
|
@@ -63,10 +63,15 @@ type PagerDutyTriggerAlarmRequest = {
|
|
|
63
63
|
/** @public */
|
|
64
64
|
interface PagerDutyApi {
|
|
65
65
|
/**
|
|
66
|
-
* Fetches all
|
|
66
|
+
* Fetches all entity mappings.
|
|
67
67
|
*
|
|
68
68
|
*/
|
|
69
|
-
|
|
69
|
+
getEntityMappings(): Promise<PagerDutyEntityMappingResponse>;
|
|
70
|
+
/**
|
|
71
|
+
* Stores the service mapping in the database.
|
|
72
|
+
*
|
|
73
|
+
*/
|
|
74
|
+
storeServiceMapping(serviceId: string, entityId: string): Promise<Response>;
|
|
70
75
|
/**
|
|
71
76
|
* Fetches the service for the provided pager duty Entity.
|
|
72
77
|
*
|
|
@@ -133,7 +138,8 @@ declare class PagerDutyClient implements PagerDutyApi {
|
|
|
133
138
|
static fromConfig(configApi: ConfigApi, dependencies: PagerDutyClientApiDependencies): PagerDutyClient;
|
|
134
139
|
constructor(config: PagerDutyClientApiConfig);
|
|
135
140
|
getServiceByPagerDutyEntity(pagerDutyEntity: PagerDutyEntity): Promise<PagerDutyServiceResponse>;
|
|
136
|
-
|
|
141
|
+
getEntityMappings(): Promise<PagerDutyEntityMappingResponse>;
|
|
142
|
+
storeServiceMapping(serviceId: string, backstageEntityId: string): Promise<Response>;
|
|
137
143
|
getServiceByEntity(entity: Entity): Promise<PagerDutyServiceResponse>;
|
|
138
144
|
getServiceById(serviceId: string): Promise<PagerDutyServiceResponse>;
|
|
139
145
|
getIncidentsByServiceId(serviceId: string): Promise<PagerDutyIncidentsResponse>;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { E as EntityPagerDutyCard, c as EntityPagerDutySmallCard, H as HomePagePagerDutyCard, f as PagerDutyCard, e as PagerDutyClient, b as PagerDutyPage, T as TriggerButton, U as UnauthorizedError, i as isPagerDutyAvailable, d as isPagerDutySmallCardAvailable, i as isPluginApplicableToEntity, p as pagerDutyApiRef, a as pagerDutyPlugin, a as plugin } from './esm/index-
|
|
1
|
+
export { E as EntityPagerDutyCard, c as EntityPagerDutySmallCard, H as HomePagePagerDutyCard, f as PagerDutyCard, e as PagerDutyClient, b as PagerDutyPage, T as TriggerButton, U as UnauthorizedError, i as isPagerDutyAvailable, d as isPagerDutySmallCardAvailable, i as isPluginApplicableToEntity, p as pagerDutyApiRef, a as pagerDutyPlugin, a as plugin } from './esm/index-4c05ac30.esm.js';
|
|
2
2
|
import '@backstage/core-plugin-api';
|
|
3
3
|
import '@backstage/errors';
|
|
4
4
|
import '@backstage/plugin-home-react';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagerduty/backstage-plugin",
|
|
3
3
|
"description": "A Backstage plugin that integrates towards PagerDuty",
|
|
4
|
-
"version": "0.12.1-next.
|
|
4
|
+
"version": "0.12.1-next.81",
|
|
5
5
|
"main": "dist/index.esm.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -41,16 +41,23 @@
|
|
|
41
41
|
"@backstage/plugin-catalog-react": "^1.9.1",
|
|
42
42
|
"@backstage/plugin-home-react": "^0.1.5",
|
|
43
43
|
"@backstage/theme": "^0.5.2",
|
|
44
|
+
"@emotion/react": "^11.11.4",
|
|
45
|
+
"@emotion/styled": "^11.11.5",
|
|
44
46
|
"@material-ui/core": "^4.12.2",
|
|
45
47
|
"@material-ui/icons": "^4.9.1",
|
|
46
48
|
"@material-ui/lab": "4.0.0-alpha.61",
|
|
49
|
+
"@mui/icons-material": "^5.15.19",
|
|
50
|
+
"@mui/material": "^5.15.19",
|
|
51
|
+
"@mui/x-date-pickers": "^7.6.1",
|
|
52
|
+
"@pagerduty/backstage-plugin-common": "^0.1.5-next.8",
|
|
53
|
+
"@tanstack/react-query": "^5.40.1",
|
|
47
54
|
"classnames": "^2.2.6",
|
|
48
55
|
"luxon": "^3.4.1",
|
|
56
|
+
"material-react-table": "^2.13.0",
|
|
49
57
|
"react-use": "^17.2.4",
|
|
50
58
|
"validate-color": "^2.2.4"
|
|
51
59
|
},
|
|
52
60
|
"peerDependencies": {
|
|
53
|
-
"@pagerduty/backstage-plugin-common": "^0.1.2",
|
|
54
61
|
"react": "^18.0.0 || ^20.0.0",
|
|
55
62
|
"react-dom": "^18.0.0 || ^20.0.0",
|
|
56
63
|
"react-router-dom": "^6.3.0"
|
|
@@ -62,7 +69,6 @@
|
|
|
62
69
|
"@backstage/test-utils": "^1.5.1",
|
|
63
70
|
"@commitlint/cli": "^17.7.1",
|
|
64
71
|
"@commitlint/config-conventional": "^17.7.0",
|
|
65
|
-
"@pagerduty/backstage-plugin-common": "^0.1.2",
|
|
66
72
|
"@testing-library/dom": "^8.0.0",
|
|
67
73
|
"@testing-library/jest-dom": "^5.10.1",
|
|
68
74
|
"@testing-library/react": "^12.1.3",
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Typography, FormControl, InputLabel, Select, MenuItem, Button, Grid } from '@material-ui/core';
|
|
3
|
-
import { Table, Page, Header, Content } from '@backstage/core-components';
|
|
4
|
-
import { useApi } from '@backstage/core-plugin-api';
|
|
5
|
-
import { p as pagerDutyApiRef } from './index-df18b73c.esm.js';
|
|
6
|
-
import { catalogApiRef } from '@backstage/plugin-catalog-react';
|
|
7
|
-
import { useAsync } from 'react-use';
|
|
8
|
-
import '@backstage/errors';
|
|
9
|
-
import '@backstage/plugin-home-react';
|
|
10
|
-
import 'luxon';
|
|
11
|
-
import '@material-ui/icons/OpenInBrowser';
|
|
12
|
-
import '../assets/emptystate.svg';
|
|
13
|
-
import 'react-use/lib/useAsyncFn';
|
|
14
|
-
import '@material-ui/lab';
|
|
15
|
-
import '../assets/forbiddenstate.svg';
|
|
16
|
-
import '@material-ui/core/Avatar';
|
|
17
|
-
import '@material-ui/icons/Notifications';
|
|
18
|
-
import 'react-use/lib/useAsync';
|
|
19
|
-
import '@material-ui/icons/Link';
|
|
20
|
-
import '../assets/PD-Green.svg';
|
|
21
|
-
import '../assets/PD-White.svg';
|
|
22
|
-
import 'validate-color';
|
|
23
|
-
import '@material-ui/icons/Info';
|
|
24
|
-
import '@material-ui/icons/CheckCircle';
|
|
25
|
-
import '@material-ui/icons/RadioButtonUnchecked';
|
|
26
|
-
import '@material-ui/core/styles';
|
|
27
|
-
import '@material-ui/lab/Alert/Alert';
|
|
28
|
-
import '@backstage/catalog-model';
|
|
29
|
-
import '@material-ui/icons/AddAlert';
|
|
30
|
-
import '@material-ui/icons/ExpandMore';
|
|
31
|
-
|
|
32
|
-
function getMappingStatus(serviceName) {
|
|
33
|
-
if (serviceName === "Ads") {
|
|
34
|
-
return "In Sync" /* InSync */;
|
|
35
|
-
}
|
|
36
|
-
return "Out Of Sync" /* OutOfSync */;
|
|
37
|
-
}
|
|
38
|
-
function getColorFromStatus(status) {
|
|
39
|
-
switch (status) {
|
|
40
|
-
case "In Sync" /* InSync */:
|
|
41
|
-
return "green";
|
|
42
|
-
case "Out Of Sync" /* OutOfSync */:
|
|
43
|
-
return "red";
|
|
44
|
-
default:
|
|
45
|
-
return "orange";
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
const DenseTable = ({
|
|
49
|
-
BackstageServices,
|
|
50
|
-
PagerDutyServices
|
|
51
|
-
}) => {
|
|
52
|
-
const columns = [
|
|
53
|
-
{ title: "PagerDuty Service", field: "name" },
|
|
54
|
-
{ title: "Team", field: "team" },
|
|
55
|
-
{ title: "Escalation Policy", field: "escalationPolicy" },
|
|
56
|
-
{ title: "Mapping", field: "mapping" },
|
|
57
|
-
{ title: "Status", field: "mappingStatus", width: "10%" },
|
|
58
|
-
{ title: "Actions", field: "actions" }
|
|
59
|
-
];
|
|
60
|
-
const data = PagerDutyServices.map((service) => {
|
|
61
|
-
var _a, _b;
|
|
62
|
-
const status = getMappingStatus(service.name);
|
|
63
|
-
return {
|
|
64
|
-
name: service.name,
|
|
65
|
-
team: (_b = (_a = service.teams) == null ? void 0 : _a.at(0)) == null ? void 0 : _b.summary,
|
|
66
|
-
escalationPolicy: service.escalation_policy.name,
|
|
67
|
-
// status of mapping
|
|
68
|
-
mappingStatus: /* @__PURE__ */ React.createElement(
|
|
69
|
-
Typography,
|
|
70
|
-
{
|
|
71
|
-
variant: "body2",
|
|
72
|
-
style: {
|
|
73
|
-
color: getColorFromStatus(status)
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
status
|
|
77
|
-
),
|
|
78
|
-
mapping: (
|
|
79
|
-
// dropdown menu with static options. If service.mapping is defined select that option
|
|
80
|
-
/* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(InputLabel, { id: "demo-simple-select-helper-label" }, "Service"), /* @__PURE__ */ React.createElement(
|
|
81
|
-
Select,
|
|
82
|
-
{
|
|
83
|
-
labelId: "demo-simple-select-helper-label",
|
|
84
|
-
id: "demo-simple-select-helper"
|
|
85
|
-
},
|
|
86
|
-
/* @__PURE__ */ React.createElement(MenuItem, { value: "" }, /* @__PURE__ */ React.createElement("em", null, "None")),
|
|
87
|
-
BackstageServices.map((backstageService) => {
|
|
88
|
-
return /* @__PURE__ */ React.createElement(
|
|
89
|
-
MenuItem,
|
|
90
|
-
{
|
|
91
|
-
key: backstageService.name,
|
|
92
|
-
value: backstageService.name
|
|
93
|
-
},
|
|
94
|
-
backstageService.name
|
|
95
|
-
);
|
|
96
|
-
})
|
|
97
|
-
))
|
|
98
|
-
),
|
|
99
|
-
actions: /* @__PURE__ */ React.createElement(Button, { variant: "contained", color: "primary", href: service.html_url }, "Open in PagerDuty")
|
|
100
|
-
};
|
|
101
|
-
});
|
|
102
|
-
return /* @__PURE__ */ React.createElement(
|
|
103
|
-
Table,
|
|
104
|
-
{
|
|
105
|
-
title: "PagerDuty Service Import",
|
|
106
|
-
subtitle: "Use this page to import services from PagerDuty and map them to existing Backstage services ",
|
|
107
|
-
options: {
|
|
108
|
-
search: true,
|
|
109
|
-
paging: true,
|
|
110
|
-
pageSize: 10,
|
|
111
|
-
pageSizeOptions: [10, 25, 50],
|
|
112
|
-
sorting: true,
|
|
113
|
-
emptyRowsWhenPaging: false,
|
|
114
|
-
showFirstLastPageButtons: true,
|
|
115
|
-
columnResizable: true,
|
|
116
|
-
columnsButton: true,
|
|
117
|
-
rowStyle: {
|
|
118
|
-
height: "10px"
|
|
119
|
-
},
|
|
120
|
-
padding: "dense"
|
|
121
|
-
},
|
|
122
|
-
columns,
|
|
123
|
-
data
|
|
124
|
-
}
|
|
125
|
-
);
|
|
126
|
-
};
|
|
127
|
-
const ServiceMappingComponent = () => {
|
|
128
|
-
const backstageServices = [];
|
|
129
|
-
const pagerDutyApi = useApi(pagerDutyApiRef);
|
|
130
|
-
const catalogApi = useApi(catalogApiRef);
|
|
131
|
-
const {
|
|
132
|
-
value: pagerDutyServices,
|
|
133
|
-
loading,
|
|
134
|
-
error
|
|
135
|
-
} = useAsync(async () => {
|
|
136
|
-
catalogApi.getEntities({ filter: { kind: "Component" } }).then((response) => {
|
|
137
|
-
response.items.forEach((entity) => {
|
|
138
|
-
var _a, _b, _c, _d, _e, _f;
|
|
139
|
-
backstageServices.push({
|
|
140
|
-
name: (_a = entity.metadata) == null ? void 0 : _a.name,
|
|
141
|
-
id: (_c = (_b = entity.metadata) == null ? void 0 : _b.uid) != null ? _c : "",
|
|
142
|
-
system: JSON.stringify((_d = entity.spec) == null ? void 0 : _d.system) || "",
|
|
143
|
-
owner: JSON.stringify((_e = entity.spec) == null ? void 0 : _e.owner) || "",
|
|
144
|
-
lifecycle: JSON.stringify((_f = entity.spec) == null ? void 0 : _f.lifecycle) || ""
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
const { services: foundServices } = await pagerDutyApi.getAllServices();
|
|
149
|
-
return foundServices;
|
|
150
|
-
}, []);
|
|
151
|
-
if (error) {
|
|
152
|
-
return /* @__PURE__ */ React.createElement("p", null, "Error: ", error.message);
|
|
153
|
-
}
|
|
154
|
-
if (loading) {
|
|
155
|
-
return /* @__PURE__ */ React.createElement("p", null, "Loading...");
|
|
156
|
-
}
|
|
157
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, backstageServices.length > 0 && /* @__PURE__ */ React.createElement(
|
|
158
|
-
DenseTable,
|
|
159
|
-
{
|
|
160
|
-
BackstageServices: backstageServices,
|
|
161
|
-
PagerDutyServices: pagerDutyServices != null ? pagerDutyServices : []
|
|
162
|
-
}
|
|
163
|
-
));
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const PagerDutyPage = () => {
|
|
167
|
-
return /* @__PURE__ */ React.createElement(Page, { themeId: "home" }, /* @__PURE__ */ React.createElement(Header, { title: "PagerDuty", subtitle: "Advanced configurations" }), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(ServiceMappingComponent, null)))));
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
export { PagerDutyPage };
|
|
171
|
-
//# sourceMappingURL=index-deaaadcb.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-deaaadcb.esm.js","sources":["../../src/components/PagerDutyPage/ServiceMappingComponent.tsx","../../src/components/PagerDutyPage/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { Table, TableColumn } from \"@backstage/core-components\";\nimport {\n Button,\n FormControl,\n InputLabel,\n MenuItem,\n Select,\n Typography,\n} from \"@material-ui/core\";\nimport { PagerDutyService } from \"@pagerduty/backstage-plugin-common\";\nimport { useApi } from \"@backstage/core-plugin-api\";\nimport { pagerDutyApiRef } from \"../../api\";\nimport { catalogApiRef } from \"@backstage/plugin-catalog-react\";\nimport { useAsync } from \"react-use\";\nimport { Entity } from \"@backstage/catalog-model\";\n\nenum MappingStatus {\n InSync = \"In Sync\",\n OutOfSync = \"Out Of Sync\",\n NotMapped = \"Not Mapped\",\n}\n\ntype Service = {\n name: string; // \"Ads\"\n id: string; // \"QWe1j283n12j132\"\n system: string; // \"Production\"\n owner: string; // \"Mapped\"\n lifecycle: string; // \"Ads\"\n};\n\ntype DenseTableProps = {\n BackstageServices: Service[];\n PagerDutyServices: PagerDutyService[];\n};\n\nfunction getMappingStatus(serviceName: string): MappingStatus {\n if (serviceName === \"Ads\") {\n return MappingStatus.InSync;\n }\n\n return MappingStatus.OutOfSync;\n}\n\nfunction getColorFromStatus(status: MappingStatus) {\n switch (status) {\n case MappingStatus.InSync:\n return \"green\";\n case MappingStatus.OutOfSync:\n return \"red\";\n default:\n return \"orange\";\n }\n}\n\nexport const DenseTable = ({\n BackstageServices,\n PagerDutyServices,\n}: DenseTableProps) => {\n // const classes = useStyles();\n\n const columns: TableColumn[] = [\n { title: \"PagerDuty Service\", field: \"name\" },\n { title: \"Team\", field: \"team\" },\n { title: \"Escalation Policy\", field: \"escalationPolicy\" },\n { title: \"Mapping\", field: \"mapping\" },\n { title: \"Status\", field: \"mappingStatus\", width: \"10%\" },\n { title: \"Actions\", field: \"actions\" },\n ];\n\n const data = PagerDutyServices.map((service) => {\n const status = getMappingStatus(service.name);\n\n return {\n name: service.name,\n team: service.teams?.at(0)?.summary,\n escalationPolicy: service.escalation_policy.name,\n // status of mapping\n mappingStatus: (\n <Typography\n variant=\"body2\"\n style={{\n color: getColorFromStatus(status),\n }}\n >\n {status}\n </Typography>\n ),\n mapping: (\n // dropdown menu with static options. If service.mapping is defined select that option\n <FormControl>\n <InputLabel id=\"demo-simple-select-helper-label\">Service</InputLabel>\n <Select\n labelId=\"demo-simple-select-helper-label\"\n id=\"demo-simple-select-helper\"\n // onChange={handleChange}\n >\n <MenuItem value=\"\">\n <em>None</em>\n </MenuItem>\n {BackstageServices.map((backstageService) => {\n return (\n <MenuItem\n key={backstageService.name}\n value={backstageService.name}\n >\n {backstageService.name}\n </MenuItem>\n );\n })}\n </Select>\n </FormControl>\n // <select title=\"Mapping\" value={service.mapping}>\n // <option aria-label=\"None\" value=\"\" />\n // <option value=\"Ads\">Ads</option>\n // <option value=\"Cache\">Cache</option>\n // <option value=\"Catalog\">Catalog</option>\n // <option value=\"Checkout\">Checkout</option>\n // </select>\n ),\n actions: (\n <Button variant=\"contained\" color=\"primary\" href={service.html_url}>\n Open in PagerDuty\n </Button>\n ),\n };\n });\n\n return (\n <Table\n title=\"PagerDuty Service Import\"\n subtitle=\"Use this page to import services from PagerDuty and map them to existing Backstage services \"\n options={{\n search: true,\n paging: true,\n pageSize: 10,\n pageSizeOptions: [10, 25, 50],\n sorting: true,\n emptyRowsWhenPaging: false,\n showFirstLastPageButtons: true,\n columnResizable: true,\n columnsButton: true,\n rowStyle: {\n height: \"10px\",\n },\n padding: \"dense\",\n }}\n columns={columns}\n data={data}\n />\n );\n};\n\nexport const ServiceMappingComponent = () => {\n const backstageServices: Service[] = [];\n // const [catalogEntities, setCatalogEntities] = useState<Entity[]>([]);\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const catalogApi = useApi(catalogApiRef);\n\n // useEffect(() => {\n // async function fetchServices() {\n // const { services: foundServices } = await pagerDutyApi.getAllServices();\n\n // setPagerDutyServices(foundServices);\n // }\n\n // async function fetchEntities() {\n // const response : GetEntitiesResponse = await catalogApi.getEntities();\n\n // setCatalogEntities(response.items);\n // }\n\n // await fetchServices();\n // fetchEntities();\n // }, [catalogApi, pagerDutyApi]);\n\n const {\n value: pagerDutyServices,\n loading,\n error,\n } = useAsync(async () => {\n catalogApi\n .getEntities({ filter: { kind: \"Component\" } })\n .then((response) => {\n // setCatalogEntities(response.items);\n\n response.items.forEach((entity: Entity) => {\n backstageServices.push({\n name: entity.metadata?.name,\n id: entity.metadata?.uid ?? \"\",\n system: JSON.stringify(entity.spec?.system) || \"\",\n owner: JSON.stringify(entity.spec?.owner) || \"\",\n lifecycle: JSON.stringify(entity.spec?.lifecycle) || \"\",\n });\n });\n });\n\n const { services: foundServices } = await pagerDutyApi.getAllServices();\n return foundServices;\n }, []);\n\n if (error) {\n return <p>Error: {error.message}</p>;\n }\n\n if (loading) {\n return <p>Loading...</p>;\n }\n\n return (\n <>\n {backstageServices.length > 0 && (\n <DenseTable\n BackstageServices={backstageServices}\n PagerDutyServices={pagerDutyServices ?? []}\n />\n )}\n </>\n );\n};\n","import React from \"react\";\nimport { Grid } from \"@material-ui/core\";\nimport { Header, Page, Content } from \"@backstage/core-components\";\nimport { ServiceMappingComponent } from \"./ServiceMappingComponent\";\n\n/** @public */\nexport const PagerDutyPage = () => {\n // const [toggleImport, setToggleImport] = useState(false);\n // const [toggleSave, setToggleSave] = useState(false);\n\n // const handleImport = () => {\n // setToggleImport(!toggleImport);\n // };\n\n // const handleSave = () => {\n // setToggleSave(!toggleSave);\n // }\n\n return (\n <Page themeId=\"home\">\n <Header title=\"PagerDuty\" subtitle=\"Advanced configurations\" />\n <Content>\n {/* <Grid container spacing={3} direction=\"column\">\n <Grid item alignContent=\"flex-end\">\n <Button variant=\"contained\" color=\"primary\" onClick={() => {handleImport()}}>\n Import\n </Button>\n <Button variant=\"outlined\" color=\"primary\" onClick={() => {handleSave()}}>\n Save\n </Button>\n </Grid>\n </Grid> */}\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <ServiceMappingComponent />\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}
|