@pagerduty/backstage-plugin 0.12.1-next.96 → 0.12.1-next.98

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/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.96",
4
+ "version": "0.12.1-next.98",
5
5
  "main": "dist/index.esm.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "license": "Apache-2.0",
@@ -33,42 +33,35 @@
33
33
  "clean": "backstage-cli package clean"
34
34
  },
35
35
  "dependencies": {
36
- "@backstage/catalog-client": "^1.6.3",
37
36
  "@backstage/catalog-model": "^1.4.3",
38
- "@backstage/core-components": "^0.13.8",
39
- "@backstage/core-plugin-api": "^1.8.0",
40
- "@backstage/errors": "^1.2.3",
37
+ "@backstage/core-components": "^0.14.7",
38
+ "@backstage/core-plugin-api": "^1.9.1",
39
+ "@backstage/errors": "^1.2.4",
41
40
  "@backstage/plugin-catalog-react": "^1.9.1",
42
41
  "@backstage/plugin-home-react": "^0.1.5",
43
- "@backstage/theme": "^0.5.2",
44
- "@emotion/react": "^11.11.4",
45
- "@emotion/styled": "^11.11.5",
42
+ "@backstage/theme": "^0.4.4",
46
43
  "@material-ui/core": "^4.12.2",
47
44
  "@material-ui/icons": "^4.9.1",
48
45
  "@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",
54
46
  "classnames": "^2.2.6",
55
47
  "luxon": "^3.4.1",
56
- "material-react-table": "^2.13.0",
57
48
  "react-use": "^17.2.4",
58
49
  "validate-color": "^2.2.4"
59
50
  },
60
51
  "peerDependencies": {
61
- "react": "^18.0.0 || ^20.0.0",
62
- "react-dom": "^18.0.0 || ^20.0.0",
63
- "react-router-dom": "^6.3.0"
52
+ "@pagerduty/backstage-plugin-common": "^0.1.2",
53
+ "react": "^16.13.1 || ^17.0.0 || ^18.0.0",
54
+ "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0",
55
+ "react-router-dom": "6.0.0-beta.0 || ^6.3.0"
64
56
  },
65
57
  "devDependencies": {
66
58
  "@backstage/cli": "^0.24.0",
67
- "@backstage/core-app-api": "^1.11.1",
59
+ "@backstage/core-app-api": "^1.12.1",
68
60
  "@backstage/dev-utils": "^1.0.24",
69
61
  "@backstage/test-utils": "^1.5.1",
70
62
  "@commitlint/cli": "^17.7.1",
71
63
  "@commitlint/config-conventional": "^17.7.0",
64
+ "@pagerduty/backstage-plugin-common": "^0.1.2",
72
65
  "@testing-library/dom": "^8.0.0",
73
66
  "@testing-library/jest-dom": "^5.10.1",
74
67
  "@testing-library/react": "^12.1.3",
@@ -1,291 +0,0 @@
1
- import React, { useState, useMemo } from 'react';
2
- import { Typography, 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-9253eb7d.esm.js';
7
- import { QueryClient, QueryClientProvider, useQuery, 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 OpenInBrowserIcon from '@material-ui/icons/OpenInBrowser';
11
- import '@backstage/errors';
12
- import '@backstage/plugin-home-react';
13
- import 'luxon';
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
- function makeReadable(status) {
48
- switch (status) {
49
- case "InSync":
50
- return "In Sync";
51
- case "OutOfSync":
52
- return "Out of Sync";
53
- case "NotMapped":
54
- return "Not Mapped";
55
- default:
56
- return "Refresh to Update";
57
- }
58
- }
59
- const ServiceMappingComponent = () => {
60
- const [entityMappings, setEntityMappings] = useState([]);
61
- const [catalogEntities, setCatalogEntities] = useState([]);
62
- const pagerDutyApi = useApi(pagerDutyApiRef);
63
- const catalogApi = useApi(catalogApiRef);
64
- function getCatalogEntityOptions() {
65
- const options = [];
66
- options.push({ value: "", label: "None" });
67
- catalogEntities.forEach((entity) => {
68
- const foundEntity = entityMappings.find(
69
- (item) => item.entityRef === entity.id
70
- );
71
- if (!foundEntity) {
72
- options.push({
73
- value: entity.id,
74
- label: entity.name
75
- });
76
- }
77
- });
78
- return options;
79
- }
80
- function useGetMappings() {
81
- return useQuery({
82
- queryKey: ["mappings"],
83
- queryFn: async () => {
84
- const { mappings: foundMappings } = await pagerDutyApi.getEntityMappings();
85
- setEntityMappings(foundMappings);
86
- return foundMappings;
87
- },
88
- refetchOnWindowFocus: false
89
- });
90
- }
91
- function useGetCatalogEntities() {
92
- return useQuery({
93
- queryKey: ["catalogEntities"],
94
- queryFn: async () => {
95
- const result = await catalogApi.getEntities({
96
- filter: { kind: "Component" }
97
- });
98
- const entities = [];
99
- result.items.forEach((entity) => {
100
- var _a, _b, _c, _d, _e, _f;
101
- entities.push({
102
- name: (_a = entity.metadata) == null ? void 0 : _a.name,
103
- id: (_c = (_b = entity.metadata) == null ? void 0 : _b.uid) != null ? _c : "",
104
- system: JSON.stringify((_d = entity.spec) == null ? void 0 : _d.system) || "",
105
- owner: JSON.stringify((_e = entity.spec) == null ? void 0 : _e.owner) || "",
106
- lifecycle: JSON.stringify((_f = entity.spec) == null ? void 0 : _f.lifecycle) || ""
107
- });
108
- });
109
- setCatalogEntities(entities);
110
- return entities;
111
- },
112
- refetchOnWindowFocus: false
113
- });
114
- }
115
- function useUpdateMapping() {
116
- return useMutation({
117
- mutationFn: async (mapping) => {
118
- return await pagerDutyApi.storeServiceMapping(
119
- mapping.serviceId,
120
- mapping.entityRef
121
- );
122
- }
123
- // client side optimistic update
124
- // onMutate: (newMappingInfo: PagerDutyEntityMapping) => {
125
- // queryClient.setQueryData(["updateMappings"], (prevMappings: any) =>
126
- // prevMappings?.map((prevMapping: PagerDutyEntityMapping) => {
127
- // if (prevMapping.serviceId === newMappingInfo.serviceId) {
128
- // newMappingInfo.entityName =
129
- // fetchedCatalogEntities.find(
130
- // (entity) => entity.id === newMappingInfo.entityRef
131
- // )?.name || "";
132
- // return newMappingInfo;
133
- // }
134
- // return prevMapping;
135
- // })
136
- // );
137
- // },
138
- });
139
- }
140
- const DenseTable = () => {
141
- const [validationErrors, setValidationErrors] = useState({});
142
- const columns = useMemo(
143
- () => [
144
- {
145
- accessorKey: "serviceId",
146
- header: "Service ID",
147
- visibleInShowHideMenu: false,
148
- enableEditing: false,
149
- Edit: () => null,
150
- Cell: ({ cell }) => /* @__PURE__ */ React.createElement(Typography, { variant: "body1", style: { fontWeight: 600 } }, cell.getValue())
151
- },
152
- {
153
- accessorKey: "serviceName",
154
- header: "PagerDuty Service",
155
- enableEditing: false
156
- },
157
- {
158
- accessorKey: "team",
159
- header: "Team",
160
- enableEditing: false
161
- },
162
- {
163
- accessorKey: "escalationPolicy",
164
- header: "Escalation Policy",
165
- enableEditing: false
166
- },
167
- {
168
- accessorKey: "entityRef",
169
- header: "Mapping",
170
- visibleInShowHideMenu: false,
171
- editVariant: "select",
172
- editSelectOptions: getCatalogEntityOptions(),
173
- muiEditTextFieldProps: {
174
- select: true,
175
- error: !!(validationErrors == null ? void 0 : validationErrors.state),
176
- helperText: validationErrors == null ? void 0 : validationErrors.state
177
- }
178
- },
179
- {
180
- accessorKey: "entityName",
181
- header: "Mapped Entity Name",
182
- enableEditing: false,
183
- Edit: () => null
184
- },
185
- {
186
- accessorKey: "status",
187
- header: "Status",
188
- enableEditing: false,
189
- Edit: () => null,
190
- Cell: ({ cell }) => /* @__PURE__ */ React.createElement(
191
- Box,
192
- {
193
- component: "span",
194
- bgcolor: getColorFromStatus(cell.getValue()),
195
- borderRadius: "0.25rem",
196
- color: "white",
197
- p: "0.25rem"
198
- },
199
- makeReadable(cell.getValue())
200
- )
201
- },
202
- {
203
- accessorKey: "serviceUrl",
204
- header: "Service URL",
205
- visibleInShowHideMenu: false,
206
- enableEditing: false,
207
- Edit: () => null
208
- }
209
- ],
210
- [validationErrors]
211
- );
212
- const {
213
- data: fetchedMappings = [],
214
- isError: isLoadingMappingsError,
215
- isFetching: isFetchingMappings,
216
- isLoading: isLoadingMappings
217
- } = useGetMappings();
218
- const {
219
- data: fetchedCatalogEntities = [],
220
- isError: isLoadingCatalogEntitiesError,
221
- isFetching: isFetchingCatalogEntities,
222
- isLoading: isLoadingCatalogEntities
223
- } = useGetCatalogEntities();
224
- const { mutateAsync: updateMapping, isPending: isUpdatingMapping } = useUpdateMapping();
225
- const handleSaveMapping = async ({ values, table }) => {
226
- var _a;
227
- setValidationErrors({});
228
- values.entityName = ((_a = fetchedCatalogEntities.find(
229
- (entity) => entity.id === values.entityRef
230
- )) == null ? void 0 : _a.name) || "";
231
- values.status = "RefreshToUpdate";
232
- await updateMapping(values);
233
- table.setEditingRow(null);
234
- };
235
- const openInBrowser = (url) => {
236
- window.open(url, "_blank", "noreferrer");
237
- };
238
- const dataTable = useMaterialReactTable({
239
- columns,
240
- data: fetchedMappings,
241
- editDisplayMode: "modal",
242
- // default ('row', 'cell', 'table', and 'custom' are also available)
243
- enableEditing: true,
244
- positionActionsColumn: "last",
245
- enableStickyHeader: true,
246
- enableFilters: true,
247
- getRowId: (row) => row.serviceId,
248
- muiToolbarAlertBannerProps: isLoadingMappingsError ? {
249
- color: "error",
250
- children: "Error loading data"
251
- } : void 0,
252
- muiTableContainerProps: {
253
- sx: {
254
- minHeight: "500px"
255
- }
256
- },
257
- onEditingRowCancel: () => setValidationErrors({}),
258
- onEditingRowSave: handleSaveMapping,
259
- // optionally customize modal content
260
- 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 }))),
261
- 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))), /* @__PURE__ */ React.createElement(Tooltip, { title: "Open in PagerDuty" }, /* @__PURE__ */ React.createElement(
262
- IconButton,
263
- {
264
- onClick: () => openInBrowser(row.getValue("serviceUrl"))
265
- },
266
- /* @__PURE__ */ React.createElement(OpenInBrowserIcon, null)
267
- ))),
268
- state: {
269
- isLoading: isLoadingMappings || isLoadingCatalogEntities,
270
- isSaving: isUpdatingMapping,
271
- showAlertBanner: isLoadingMappingsError || isLoadingCatalogEntitiesError,
272
- showProgressBars: isFetchingMappings || isFetchingCatalogEntities,
273
- columnVisibility: {
274
- serviceId: false,
275
- entityRef: false,
276
- serviceUrl: false
277
- }
278
- }
279
- });
280
- return /* @__PURE__ */ React.createElement(MaterialReactTable, { table: dataTable });
281
- };
282
- const queryClient = new QueryClient();
283
- return /* @__PURE__ */ React.createElement(QueryClientProvider, { client: queryClient }, /* @__PURE__ */ React.createElement(DenseTable, null));
284
- };
285
-
286
- const PagerDutyPage = () => {
287
- 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(Typography, { variant: "h4" }, "Service to Entity mapping"), /* @__PURE__ */ React.createElement(Typography, { variant: "body1" }, "Easily map your services to entities in Backstage without the need to add anotations to all your projects."), /* @__PURE__ */ React.createElement(Typography, { variant: "body1" }, /* @__PURE__ */ React.createElement("b", null, "Warning: "), "Only 1:1 mapping is allowed at this time.")), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(ServiceMappingComponent, null)))));
288
- };
289
-
290
- export { PagerDutyPage };
291
- //# sourceMappingURL=index-700b938a.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-700b938a.esm.js","sources":["../../src/components/PagerDutyPage/ServiceMappingComponent.tsx","../../src/components/PagerDutyPage/index.tsx"],"sourcesContent":["import React, { useMemo, useState } from \"react\";\nimport {\n Box,\n DialogActions,\n DialogContent,\n DialogTitle,\n IconButton,\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} from \"@tanstack/react-query\";\nimport {\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\";\nimport OpenInBrowser from \"@material-ui/icons/OpenInBrowser\";\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\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\nfunction makeReadable(status?: string) {\n switch (status) {\n case \"InSync\":\n return \"In Sync\";\n case \"OutOfSync\":\n return \"Out of Sync\";\n case \"NotMapped\":\n return \"Not Mapped\";\n default:\n return \"Refresh to Update\";\n }\n}\n\nexport const ServiceMappingComponent = () => {\n const [entityMappings, setEntityMappings] = useState<\n PagerDutyEntityMapping[]\n >([]);\n const [catalogEntities, setCatalogEntities] = useState<Service[]>([]);\n // const [entityOptions, setEntityOptions] = useState<CatalogEntityOptions[]>([]);\n\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const catalogApi = useApi(catalogApiRef);\n\n // function fetchCatalogEntities() {\n // catalogApi\n // .getEntities({\n // filter: { kind: \"Component\" },\n // })\n // .then((result) => {\n // const entities: Service[] = [];\n // result.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\n // setCatalogEntities(entities);\n // });\n // }\n\n type CatalogEntityOptions = {\n value: string;\n label: string;\n };\n\n function getCatalogEntityOptions(): CatalogEntityOptions[] {\n const options: CatalogEntityOptions[] = [];\n // if (entityOptions.length === 0) {\n // initialize with empty object\n options.push({ value: \"\", label: \"None\" });\n // }\n\n catalogEntities.forEach((entity) => {\n // find entity with entity.id in entityMappings array\n const foundEntity = entityMappings.find(\n (item) => item.entityRef === entity.id\n );\n\n if (!foundEntity) {\n options.push({\n value: entity.id,\n label: entity.name,\n });\n }\n });\n\n // setEntityOptions(options);\n\n return options;\n }\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 setEntityMappings(foundMappings);\n\n return foundMappings;\n },\n refetchOnWindowFocus: false,\n });\n }\n\n // READ hook (get catalog entities from api)\n function useGetCatalogEntities() {\n return useQuery<Service[]>({\n queryKey: [\"catalogEntities\"],\n queryFn: async () => {\n // send api request here\n const result = await catalogApi.getEntities({\n filter: { kind: \"Component\" },\n });\n\n const entities: Service[] = [];\n result.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\n setCatalogEntities(entities);\n\n return entities;\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 =\n // fetchedCatalogEntities.find(\n // (entity) => entity.id === newMappingInfo.entityRef\n // )?.name || \"\";\n\n // return newMappingInfo;\n // }\n // return prevMapping;\n // })\n // );\n // },\n });\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 Edit: () => null,\n Cell: ({ cell }) => (\n <Typography variant=\"body1\" style={{ fontWeight: 600 }}>\n {cell.getValue<string>()}\n </Typography>\n ),\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 Edit: () => null,\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n enableEditing: false,\n Edit: () => null,\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 {makeReadable(cell.getValue<string>())}\n </Box>\n ),\n },\n {\n accessorKey: \"serviceUrl\",\n header: \"Service URL\",\n visibleInShowHideMenu: false,\n enableEditing: false,\n Edit: () => null,\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 READ hook\n const {\n data: fetchedCatalogEntities = [],\n isError: isLoadingCatalogEntitiesError,\n isFetching: isFetchingCatalogEntities,\n isLoading: isLoadingCatalogEntities,\n } = useGetCatalogEntities();\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 =\n fetchedCatalogEntities.find(\n (entity) => entity.id === values.entityRef\n )?.name || \"\";\n values.status = \"RefreshToUpdate\";\n await updateMapping(values);\n table.setEditingRow(null); // exit editing mode\n };\n\n const openInBrowser = (url: string) => {\n window.open(url, \"_blank\", \"noreferrer\");\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 enableFilters: 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>{internalEditComponents} </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 <Tooltip title=\"Open in PagerDuty\">\n <IconButton\n onClick={() => openInBrowser(row.getValue(\"serviceUrl\"))}\n >\n <OpenInBrowser />\n </IconButton>\n </Tooltip>\n </Box>\n ),\n state: {\n isLoading: isLoadingMappings || isLoadingCatalogEntities,\n isSaving: isUpdatingMapping,\n showAlertBanner:\n isLoadingMappingsError || isLoadingCatalogEntitiesError,\n showProgressBars: isFetchingMappings || isFetchingCatalogEntities,\n columnVisibility: {\n serviceId: false,\n entityRef: false,\n serviceUrl: 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, Typography } 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>\n <Typography variant=\"h4\">Service to Entity mapping</Typography>\n <Typography variant=\"body1\">\n Easily map your services to entities in Backstage without the need to add anotations to all your projects.\n </Typography>\n <Typography variant=\"body1\">\n <b>Warning: </b>Only 1:1 mapping is allowed at this time.\n </Typography>\n </Grid>\n <Grid item>\n <ServiceMappingComponent />\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":["OpenInBrowser"],"mappings":"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"}