@pagerduty/backstage-plugin 0.12.1-next.9 → 0.12.1-next.90

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.
@@ -0,0 +1,276 @@
1
+ import React, { useState, useMemo } from 'react';
2
+ import { Typography, Box, DialogTitle, DialogContent, Grid, DialogActions, Tooltip, IconButton } 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-d9389856.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 { OpenInBrowser } from '@material-ui/icons';
11
+ import '@backstage/errors';
12
+ import '@backstage/plugin-home-react';
13
+ import 'luxon';
14
+ import '@material-ui/icons/OpenInBrowser';
15
+ import '../assets/emptystate.svg';
16
+ import 'react-use/lib/useAsyncFn';
17
+ import '@material-ui/lab';
18
+ import '../assets/forbiddenstate.svg';
19
+ import '@material-ui/core/Avatar';
20
+ import '@material-ui/icons/Notifications';
21
+ import 'react-use/lib/useAsync';
22
+ import '@material-ui/icons/Link';
23
+ import '../assets/PD-Green.svg';
24
+ import '../assets/PD-White.svg';
25
+ import 'validate-color';
26
+ import '@material-ui/icons/Info';
27
+ import '@material-ui/icons/CheckCircle';
28
+ import '@material-ui/icons/RadioButtonUnchecked';
29
+ import '@material-ui/core/styles';
30
+ import 'react-use';
31
+ import '@material-ui/lab/Alert/Alert';
32
+ import '@backstage/catalog-model';
33
+ import '@material-ui/icons/AddAlert';
34
+ import '@material-ui/icons/ExpandMore';
35
+
36
+ function getColorFromStatus(status) {
37
+ switch (status) {
38
+ case "InSync":
39
+ return "green";
40
+ case "OutOfSync":
41
+ return "red";
42
+ case "NotMapped":
43
+ return "orange";
44
+ default:
45
+ return "gray";
46
+ }
47
+ }
48
+ function makeReadable(status) {
49
+ switch (status) {
50
+ case "InSync":
51
+ return "In Sync";
52
+ case "OutOfSync":
53
+ return "Out of Sync";
54
+ case "NotMapped":
55
+ return "Not Mapped";
56
+ default:
57
+ return "Refresh to Update";
58
+ }
59
+ }
60
+ const ServiceMappingComponent = () => {
61
+ const [catalogEntities, setCatalogEntities] = useState([]);
62
+ const [entityOptions, setEntityOptions] = useState([]);
63
+ const pagerDutyApi = useApi(pagerDutyApiRef);
64
+ const catalogApi = useApi(catalogApiRef);
65
+ function useGetMappings() {
66
+ return useQuery({
67
+ queryKey: ["mappings"],
68
+ queryFn: async () => {
69
+ const { mappings: foundMappings } = await pagerDutyApi.getEntityMappings();
70
+ return foundMappings;
71
+ },
72
+ refetchOnWindowFocus: false
73
+ });
74
+ }
75
+ function useUpdateMapping() {
76
+ const queryClient2 = useQueryClient();
77
+ return useMutation({
78
+ mutationFn: async (mapping) => {
79
+ return await pagerDutyApi.storeServiceMapping(
80
+ mapping.serviceId,
81
+ mapping.entityRef
82
+ );
83
+ },
84
+ // client side optimistic update
85
+ onMutate: (newMappingInfo) => {
86
+ queryClient2.setQueryData(
87
+ ["updateMappings"],
88
+ (prevMappings) => prevMappings == null ? void 0 : prevMappings.map(
89
+ (prevMapping) => {
90
+ var _a;
91
+ if (prevMapping.serviceId === newMappingInfo.serviceId) {
92
+ newMappingInfo.entityName = ((_a = catalogEntities.find((entity) => entity.id === newMappingInfo.entityRef)) == null ? void 0 : _a.name) || "";
93
+ return newMappingInfo;
94
+ }
95
+ return prevMapping;
96
+ }
97
+ )
98
+ );
99
+ }
100
+ });
101
+ }
102
+ function fetchCatalogEntities() {
103
+ catalogApi.getEntities({
104
+ filter: { kind: "Component" }
105
+ }).then(({ items }) => {
106
+ const entities = [];
107
+ items.forEach((entity) => {
108
+ var _a, _b, _c, _d, _e, _f;
109
+ entities.push({
110
+ name: (_a = entity.metadata) == null ? void 0 : _a.name,
111
+ id: (_c = (_b = entity.metadata) == null ? void 0 : _b.uid) != null ? _c : "",
112
+ system: JSON.stringify((_d = entity.spec) == null ? void 0 : _d.system) || "",
113
+ owner: JSON.stringify((_e = entity.spec) == null ? void 0 : _e.owner) || "",
114
+ lifecycle: JSON.stringify((_f = entity.spec) == null ? void 0 : _f.lifecycle) || ""
115
+ });
116
+ });
117
+ setCatalogEntities(entities);
118
+ });
119
+ }
120
+ function getCatalogEntityOptions() {
121
+ if (catalogEntities.length === 0) {
122
+ fetchCatalogEntities();
123
+ }
124
+ if (entityOptions.length === 0) {
125
+ const options = [];
126
+ options.push({ value: "", label: "None" });
127
+ catalogEntities.forEach((entity) => {
128
+ options.push({
129
+ value: entity.id,
130
+ label: entity.name
131
+ });
132
+ setEntityOptions(options);
133
+ });
134
+ }
135
+ return entityOptions;
136
+ }
137
+ const DenseTable = () => {
138
+ const [validationErrors, setValidationErrors] = useState({});
139
+ const columns = useMemo(
140
+ () => [
141
+ {
142
+ accessorKey: "serviceId",
143
+ header: "Service ID",
144
+ visibleInShowHideMenu: false,
145
+ enableEditing: false,
146
+ Cell: ({ cell }) => /* @__PURE__ */ React.createElement(Typography, { variant: "body1", style: { fontWeight: 600 } }, cell.getValue())
147
+ },
148
+ {
149
+ accessorKey: "serviceName",
150
+ header: "PagerDuty Service",
151
+ enableEditing: false
152
+ },
153
+ {
154
+ accessorKey: "team",
155
+ header: "Team",
156
+ enableEditing: false
157
+ },
158
+ {
159
+ accessorKey: "escalationPolicy",
160
+ header: "Escalation Policy",
161
+ enableEditing: false
162
+ },
163
+ {
164
+ accessorKey: "entityRef",
165
+ header: "Mapping",
166
+ visibleInShowHideMenu: false,
167
+ editVariant: "select",
168
+ editSelectOptions: getCatalogEntityOptions(),
169
+ muiEditTextFieldProps: {
170
+ select: true,
171
+ error: !!(validationErrors == null ? void 0 : validationErrors.state),
172
+ helperText: validationErrors == null ? void 0 : validationErrors.state
173
+ }
174
+ },
175
+ {
176
+ accessorKey: "entityName",
177
+ header: "Mapped Entity Name",
178
+ enableEditing: false
179
+ },
180
+ {
181
+ accessorKey: "status",
182
+ header: "Status",
183
+ enableEditing: false,
184
+ Cell: ({ cell }) => /* @__PURE__ */ React.createElement(
185
+ Box,
186
+ {
187
+ component: "span",
188
+ bgcolor: getColorFromStatus(cell.getValue()),
189
+ borderRadius: "0.25rem",
190
+ color: "white",
191
+ p: "0.25rem"
192
+ },
193
+ makeReadable(cell.getValue())
194
+ )
195
+ },
196
+ {
197
+ accessorKey: "serviceUrl",
198
+ header: "Service URL",
199
+ visibleInShowHideMenu: false,
200
+ enableEditing: false
201
+ }
202
+ ],
203
+ [validationErrors]
204
+ );
205
+ const {
206
+ data: fetchedMappings = [],
207
+ isError: isLoadingMappingsError,
208
+ isFetching: isFetchingMappings,
209
+ isLoading: isLoadingMappings
210
+ } = useGetMappings();
211
+ const { mutateAsync: updateMapping, isPending: isUpdatingMapping } = useUpdateMapping();
212
+ const handleSaveMapping = async ({ values, table }) => {
213
+ var _a;
214
+ setValidationErrors({});
215
+ values.entityName = ((_a = catalogEntities.find((entity) => entity.id === values.entityRef)) == null ? void 0 : _a.name) || "";
216
+ values.status = "RefreshToUpdate";
217
+ await updateMapping(values);
218
+ table.setEditingRow(null);
219
+ };
220
+ const openInBrowser = (url) => {
221
+ window.open(url, "_blank", "noreferrer");
222
+ };
223
+ const dataTable = useMaterialReactTable({
224
+ columns,
225
+ data: fetchedMappings,
226
+ editDisplayMode: "modal",
227
+ // default ('row', 'cell', 'table', and 'custom' are also available)
228
+ enableEditing: true,
229
+ positionActionsColumn: "last",
230
+ enableStickyHeader: true,
231
+ enableFilters: true,
232
+ getRowId: (row) => row.serviceId,
233
+ muiToolbarAlertBannerProps: isLoadingMappingsError ? {
234
+ color: "error",
235
+ children: "Error loading data"
236
+ } : void 0,
237
+ muiTableContainerProps: {
238
+ sx: {
239
+ minHeight: "500px"
240
+ }
241
+ },
242
+ onEditingRowCancel: () => setValidationErrors({}),
243
+ onEditingRowSave: handleSaveMapping,
244
+ // optionally customize modal content
245
+ renderEditRowDialogContent: ({ table, row }) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(DialogTitle, null, "Edit Mapping"), /* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Typography, { variant: "overline" }, "PagerDuty Service"), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, row.getValue("serviceName")), /* @__PURE__ */ React.createElement(Typography, { variant: "overline" }, /* @__PURE__ */ React.createElement("b", null, "Team")), /* @__PURE__ */ React.createElement(Typography, { variant: "overline" }, row.getValue("team")), /* @__PURE__ */ React.createElement(Typography, { variant: "body1" }, /* @__PURE__ */ React.createElement("b", null, "Escalation Policy:"), " ", row.getValue("escalationPolicy")))), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(MRT_EditActionButtons, { variant: "text", table, row }))),
246
+ 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(
247
+ IconButton,
248
+ {
249
+ onClick: () => openInBrowser(row.getValue("serviceUrl"))
250
+ },
251
+ /* @__PURE__ */ React.createElement(OpenInBrowser, null)
252
+ ))),
253
+ state: {
254
+ isLoading: isLoadingMappings,
255
+ isSaving: isUpdatingMapping,
256
+ showAlertBanner: isLoadingMappingsError,
257
+ showProgressBars: isFetchingMappings,
258
+ columnVisibility: {
259
+ serviceId: false,
260
+ entityRef: false,
261
+ serviceUrl: false
262
+ }
263
+ }
264
+ });
265
+ return /* @__PURE__ */ React.createElement(MaterialReactTable, { table: dataTable });
266
+ };
267
+ const queryClient = new QueryClient();
268
+ return /* @__PURE__ */ React.createElement(QueryClientProvider, { client: queryClient }, /* @__PURE__ */ React.createElement(DenseTable, null));
269
+ };
270
+
271
+ const PagerDutyPage = () => {
272
+ 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)))));
273
+ };
274
+
275
+ export { PagerDutyPage };
276
+ //# sourceMappingURL=index-dc4dace6.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-dc4dace6.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 Grid,\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 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\";\nimport { OpenInBrowser } from \"@material-ui/icons\";\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\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\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 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 },\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 {makeReadable(cell.getValue<string>())}\n </Box>\n ),\n },\n {\n accessorKey: \"serviceUrl\",\n header: \"Service URL\",\n visibleInShowHideMenu: false,\n enableEditing: false,\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 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 }) => (\n <>\n <DialogTitle>Edit Mapping</DialogTitle>\n <DialogContent>\n <Grid>\n <Typography variant=\"overline\">PagerDuty Service</Typography>\n <Typography variant=\"body2\">\n {row.getValue(\"serviceName\")}\n </Typography>\n <Typography variant=\"overline\">\n <b>Team</b>\n </Typography>\n <Typography variant=\"overline\">{row.getValue(\"team\")}</Typography>\n <Typography variant=\"body1\">\n <b>Escalation Policy:</b> {row.getValue(\"escalationPolicy\")}\n </Typography>\n </Grid>\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 <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,\n isSaving: isUpdatingMapping,\n showAlertBanner: isLoadingMappingsError,\n showProgressBars: isFetchingMappings,\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":["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 { PagerDutyServicesResponse, PagerDutyServiceResponse, PagerDutyIncidentsResponse, PagerDutyChangeEventsResponse, PagerDutyServiceStandardsResponse, PagerDutyServiceMetricsResponse, PagerDutyUser } from '@pagerduty/backstage-plugin-common';
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 services for service import purposes.
66
+ * Fetches all entity mappings.
67
67
  *
68
68
  */
69
- getAllServices(): Promise<PagerDutyServicesResponse>;
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
- getAllServices(): Promise<PagerDutyServicesResponse>;
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-d4b445d8.esm.js';
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-d9389856.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.9",
4
+ "version": "0.12.1-next.90",
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,71 +0,0 @@
1
- import React from 'react';
2
- import { Grid } from '@material-ui/core';
3
- import { Page, Header, Content } from '@backstage/core-components';
4
- import { useApi } from '@backstage/core-plugin-api';
5
- import { p as pagerDutyApiRef } from './index-d4b445d8.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
- const ServiceMappingComponent = () => {
33
- const backstageServices = [];
34
- const pagerDutyApi = useApi(pagerDutyApiRef);
35
- const catalogApi = useApi(catalogApiRef);
36
- const {
37
- value: pagerDutyServices,
38
- loading,
39
- error
40
- } = useAsync(async () => {
41
- const { items } = await catalogApi.getEntities({
42
- filter: { kind: "Component" }
43
- });
44
- items.forEach((entity) => {
45
- var _a, _b, _c, _d, _e, _f;
46
- backstageServices.push({
47
- name: (_a = entity.metadata) == null ? void 0 : _a.name,
48
- id: (_c = (_b = entity.metadata) == null ? void 0 : _b.uid) != null ? _c : "",
49
- system: JSON.stringify((_d = entity.spec) == null ? void 0 : _d.system) || "",
50
- owner: JSON.stringify((_e = entity.spec) == null ? void 0 : _e.owner) || "",
51
- lifecycle: JSON.stringify((_f = entity.spec) == null ? void 0 : _f.lifecycle) || ""
52
- });
53
- });
54
- const { services: foundServices } = await pagerDutyApi.getAllServices();
55
- return foundServices;
56
- }, []);
57
- if (error) {
58
- return /* @__PURE__ */ React.createElement("p", null, "Error: ", error.message);
59
- }
60
- if (loading) {
61
- return /* @__PURE__ */ React.createElement("p", null, "Loading...");
62
- }
63
- return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("p", null, "Backstage Services"), /* @__PURE__ */ React.createElement("p", null, JSON.stringify(backstageServices)), /* @__PURE__ */ React.createElement("p", null, "PagerDuty Services"), /* @__PURE__ */ React.createElement("p", null, JSON.stringify(pagerDutyServices)));
64
- };
65
-
66
- const PagerDutyPage = () => {
67
- 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)))));
68
- };
69
-
70
- export { PagerDutyPage };
71
- //# sourceMappingURL=index-c05cbebd.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-c05cbebd.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 const { items } = await catalogApi.getEntities({\n filter: { kind: \"Component\" },\n });\n\n 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 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 <div>\n <p>Backstage Services</p>\n <p>{JSON.stringify(backstageServices)}</p>\n <p>PagerDuty Services</p>\n <p>{JSON.stringify(pagerDutyServices)}</p>\n </div>\n\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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"}