@pagerduty/backstage-plugin 0.12.1-next.7 → 0.12.1-next.71

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.
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { P as PagerDutyCard } from './index-814058ce.esm.js';
2
+ import { P as PagerDutyCard } from './index-9e997679.esm.js';
3
3
  import '@backstage/core-plugin-api';
4
4
  import '@backstage/errors';
5
5
  import '@backstage/plugin-home-react';
@@ -34,4 +34,4 @@ const Content = (props) => {
34
34
  };
35
35
 
36
36
  export { Content };
37
- //# sourceMappingURL=index-76060cea.esm.js.map
37
+ //# sourceMappingURL=index-1dd9ce58.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-76060cea.esm.js","sources":["../../src/components/HomePagePagerDutyCard/Content.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// eslint-disable-next-line @backstage/no-undeclared-imports\nimport React from 'react';\n\nimport { PagerDutyEntity } from '../../types';\nimport { PagerDutyCard } from '../PagerDutyCard';\n\n/** @public */\nexport type HomePagePagerDutyCardProps = PagerDutyEntity & {\n readOnly?: boolean;\n};\n\n/** @public */\nexport const Content = (props: HomePagePagerDutyCardProps) => {\n return <PagerDutyCard {...props} />;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2Ba,MAAA,OAAA,GAAU,CAAC,KAAsC,KAAA;AAC5D,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,aAAe,EAAA,EAAA,GAAG,KAAO,EAAA,CAAA,CAAA;AACnC;;;;"}
1
+ {"version":3,"file":"index-1dd9ce58.esm.js","sources":["../../src/components/HomePagePagerDutyCard/Content.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// eslint-disable-next-line @backstage/no-undeclared-imports\nimport React from 'react';\n\nimport { PagerDutyEntity } from '../../types';\nimport { PagerDutyCard } from '../PagerDutyCard';\n\n/** @public */\nexport type HomePagePagerDutyCardProps = PagerDutyEntity & {\n readOnly?: boolean;\n};\n\n/** @public */\nexport const Content = (props: HomePagePagerDutyCardProps) => {\n return <PagerDutyCard {...props} />;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2Ba,MAAA,OAAA,GAAU,CAAC,KAAsC,KAAA;AAC5D,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,aAAe,EAAA,EAAA,GAAG,KAAO,EAAA,CAAA,CAAA;AACnC;;;;"}
@@ -0,0 +1,198 @@
1
+ import React, { useState, useMemo } from 'react';
2
+ import { DialogTitle, DialogContent, DialogActions, Box, 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-9e997679.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 '@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
+ const ServiceMappingComponent = () => {
36
+ const [catalogEntities, setCatalogEntities] = useState([]);
37
+ const pagerDutyApi = useApi(pagerDutyApiRef);
38
+ const catalogApi = useApi(catalogApiRef);
39
+ function useGetMappings() {
40
+ return useQuery({
41
+ queryKey: ["mappings"],
42
+ queryFn: async () => {
43
+ const { mappings: foundMappings } = await pagerDutyApi.getEntityMappings();
44
+ return foundMappings;
45
+ },
46
+ refetchOnWindowFocus: false
47
+ });
48
+ }
49
+ function useUpdateMapping() {
50
+ return useMutation({
51
+ mutationFn: async (mapping) => {
52
+ await pagerDutyApi.storeServiceMapping(
53
+ mapping.serviceId,
54
+ mapping.entityRef
55
+ );
56
+ }
57
+ // client side optimistic update
58
+ // onMutate: (newMappingInfo: PagerDutyEntityMapping) => {
59
+ // queryClient.setQueryData(["mappings"], (prevMappings: any) =>
60
+ // prevMappings?.map((prevMapping: PagerDutyEntityMapping) =>
61
+ // prevMapping.serviceId === newMappingInfo.serviceId
62
+ // ? newMappingInfo
63
+ // : prevMapping
64
+ // )
65
+ // );
66
+ // },
67
+ });
68
+ }
69
+ function fetchCatalogEntities() {
70
+ catalogApi.getEntities({
71
+ filter: { kind: "Component" }
72
+ }).then(({ items }) => {
73
+ const entities = [];
74
+ items.forEach((entity) => {
75
+ var _a, _b, _c, _d, _e, _f;
76
+ entities.push({
77
+ name: (_a = entity.metadata) == null ? void 0 : _a.name,
78
+ id: (_c = (_b = entity.metadata) == null ? void 0 : _b.uid) != null ? _c : "",
79
+ system: JSON.stringify((_d = entity.spec) == null ? void 0 : _d.system) || "",
80
+ owner: JSON.stringify((_e = entity.spec) == null ? void 0 : _e.owner) || "",
81
+ lifecycle: JSON.stringify((_f = entity.spec) == null ? void 0 : _f.lifecycle) || ""
82
+ });
83
+ });
84
+ setCatalogEntities(entities);
85
+ });
86
+ }
87
+ function getCatalogEntityOptions() {
88
+ if (catalogEntities.length === 0) {
89
+ fetchCatalogEntities();
90
+ }
91
+ const options = catalogEntities.map((entity) => ({
92
+ value: entity.id,
93
+ label: entity.name
94
+ }));
95
+ return options;
96
+ }
97
+ const DenseTable = () => {
98
+ const [validationErrors, setValidationErrors] = useState({});
99
+ const columns = useMemo(
100
+ () => [
101
+ {
102
+ accessorKey: "serviceId",
103
+ header: "Service ID",
104
+ visibleInShowHideMenu: false,
105
+ enableEditing: false
106
+ },
107
+ {
108
+ accessorKey: "serviceName",
109
+ header: "PagerDuty Service",
110
+ enableEditing: false
111
+ },
112
+ {
113
+ accessorKey: "team",
114
+ header: "Team",
115
+ enableEditing: false
116
+ },
117
+ {
118
+ accessorKey: "escalationPolicy",
119
+ header: "Escalation Policy",
120
+ enableEditing: false
121
+ },
122
+ {
123
+ accessorKey: "entityRef",
124
+ header: "Mapping",
125
+ editVariant: "select",
126
+ editSelectOptions: getCatalogEntityOptions(),
127
+ muiEditTextFieldProps: {
128
+ select: true,
129
+ error: !!(validationErrors == null ? void 0 : validationErrors.state),
130
+ helperText: validationErrors == null ? void 0 : validationErrors.state
131
+ }
132
+ },
133
+ {
134
+ accessorKey: "status",
135
+ header: "Status",
136
+ enableEditing: false
137
+ }
138
+ ],
139
+ [validationErrors]
140
+ );
141
+ const {
142
+ data: fetchedMappings = [],
143
+ isError: isLoadingMappingsError,
144
+ isFetching: isFetchingMappings,
145
+ isLoading: isLoadingMappings
146
+ } = useGetMappings();
147
+ const { mutateAsync: updateUser, isPending: isUpdatingMapping } = useUpdateMapping();
148
+ const handleSaveUser = async ({ values, table }) => {
149
+ await updateUser(values);
150
+ table.setEditingRow(null);
151
+ };
152
+ const dataTable = useMaterialReactTable({
153
+ columns,
154
+ data: fetchedMappings,
155
+ editDisplayMode: "modal",
156
+ // default ('row', 'cell', 'table', and 'custom' are also available)
157
+ enableEditing: true,
158
+ positionActionsColumn: "last",
159
+ getRowId: (row) => row.serviceId,
160
+ muiToolbarAlertBannerProps: isLoadingMappingsError ? {
161
+ color: "error",
162
+ children: "Error loading data"
163
+ } : void 0,
164
+ muiTableContainerProps: {
165
+ sx: {
166
+ minHeight: "500px"
167
+ }
168
+ },
169
+ onEditingRowCancel: () => setValidationErrors({}),
170
+ onEditingRowSave: handleSaveUser,
171
+ // optionally customize modal content
172
+ 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 }))),
173
+ 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)))),
174
+ state: {
175
+ isLoading: isLoadingMappings,
176
+ // || isLoadingEntities,
177
+ isSaving: isUpdatingMapping,
178
+ showAlertBanner: isLoadingMappingsError,
179
+ // || isLoadingEntitiesError,
180
+ showProgressBars: isFetchingMappings,
181
+ // || isFetchingEntities,
182
+ columnVisibility: {
183
+ serviceId: false
184
+ }
185
+ }
186
+ });
187
+ return /* @__PURE__ */ React.createElement(MaterialReactTable, { table: dataTable });
188
+ };
189
+ const queryClient = new QueryClient();
190
+ return /* @__PURE__ */ React.createElement(QueryClientProvider, { client: queryClient }, /* @__PURE__ */ React.createElement(DenseTable, null));
191
+ };
192
+
193
+ const PagerDutyPage = () => {
194
+ 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)))));
195
+ };
196
+
197
+ export { PagerDutyPage };
198
+ //# sourceMappingURL=index-447645f1.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-447645f1.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} 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\n// function 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 // const [catalogEntities, setCatalogEntities] = useState<Service[]>([]);\n // const [, setServiceMappings] = useState<PagerDutyEntityMapping[]>([]);\n // const [tableData, setTableData] = useState<TableItem[]>([]);\n // const [isLoading, setIsLoading] = useState(true);\n\n // const pagerDutyApi = useApi(pagerDutyApiRef);\n // const catalogApi = useApi(catalogApiRef);\n\n // useEffect(() => {\n // async function fetchEntities(): Promise<Service[]> {\n // const { items } = await catalogApi.getEntities({\n // filter: { kind: \"Component\" },\n // });\n\n // const backstageServices: Service[] = [];\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 // return backstageServices;\n // }\n\n // async function fetchServices(): Promise<PagerDutyEntityMapping[]> {\n // const { mappings: foundServices } = await pagerDutyApi.getEntityMappings();\n\n // return foundServices;\n // }\n\n // if (catalogEntities.length === 0) {\n // Promise.all([fetchEntities(), fetchServices()]).then(\n // ([entities, mappings]) => {\n // setCatalogEntities(entities);\n // setServiceMappings(mappings);\n\n // const data: TableItem[] = buildTableData(\n // entities,\n // mappings\n // );\n\n // setTableData(data);\n // setIsLoading(false);\n // }\n // );\n // }\n // }, [catalogApi, catalogEntities, pagerDutyApi]);\n\n // function buildTableData(\n // entities: Service[],\n // mappings: PagerDutyEntityMapping[]\n // ): TableItem[] {\n // const data: TableItem[] = mappings.map((service) => {\n // return {\n // name: service.serviceName,\n // team: service.team,\n // escalationPolicy: service.escalationPolicy,\n // // status of mapping\n // mappingStatus: (\n // <Typography\n // variant=\"body2\"\n // style={{\n // color: getColorFromStatus(service.status),\n // }}\n // >\n // {service.status}\n // </Typography>\n // ),\n // mapping: (\n // // dropdown menu with static options. If service.mapping is defined select that option\n // <FormControl variant=\"standard\">\n // <Select\n // displayEmpty\n // onChange={(selection) => {\n // handleMappingChange(service, selection);\n\n // }}\n // value={service.entityRef}\n // >\n // <MenuItem value=\"\">\n // <em>None</em>\n // </MenuItem>\n // {entities.map((backstageService) => {\n // return (\n // <MenuItem\n // key={backstageService.id}\n // value={backstageService.id}\n // >\n // {backstageService.name}\n // </MenuItem>\n // );\n // })}\n // </Select>\n // </FormControl>\n // ),\n // actions: (\n // <Button variant=\"contained\" color=\"primary\" href={service.serviceUrl}>\n // Open in PagerDuty\n // </Button>\n // ),\n // };\n // });\n\n // return data;\n // }\n\n // async function handleMappingChange(\n // service: PagerDutyEntityMapping,\n // event: ChangeEvent<{\n // name?: string | undefined;\n // value: unknown;\n // }>\n // ) {\n // // event.preventDefault();\n // const updatedData = [...tableData];\n\n // // find the service in updatedData\n // updatedData.findIndex((item) => item.name === service.serviceName);\n // // // updatedData[serviceIndex].mappingStatus = (\n // // // <Typography\n // // // variant=\"body2\"\n // // // style={{\n // // // color: getColorFromStatus(\"OutOfSync\"),\n // // // }}\n // // // >\n // // // \"OutOfSync\"\n // // // </Typography>\n // // // );\n\n // // // update the mapping status\n // // // service.status = \"OutOfSync\";\n\n // // // // update the mapping\n // // // service.entityRef = entityId;\n\n // // // store the mapping in the database\n // await pagerDutyApi.storeServiceMapping(\n // service.serviceId,\n // event.target.value as string\n // );\n // setTableData(updatedData);\n // }\n\n // const DenseTable = ({ items }: DenseTableProps) => {\n // // const [data, _] = useState<TableItem[]>(items);\n\n // // useEffect(() => {\n // // setData(items);\n // // }, [items]);\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\" },\n // { title: \"Actions\", field: \"actions\" },\n // ];\n\n // return (\n // <Table\n // isLoading={isLoading}\n // title=\"PagerDuty Service Import\"\n // subtitle=\"Use this page to import services from PagerDuty and map them to existing Backstage services. Only 1:1 mapping is allowed.\"\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={items}\n // />\n // );\n // };\n\n // return <DenseTable items={tableData} />;\n\n const [catalogEntities, setCatalogEntities] = useState<Service[]>([]);\n\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const catalogApi = useApi(catalogApiRef);\n\n // function useGetCatalogEntities() {\n // return useQuery<DropdownOption[]>({\n // queryKey: [\"catalogEntities\"],\n // queryFn: async () => {\n // // send api request here\n // const { items } = await catalogApi.getEntities({\n // filter: { kind: \"Component\" },\n // });\n\n // const entities: DropdownOption[] = [];\n // items.forEach((entity: Entity) => {\n // entities.push({\n // value: entity.metadata?.uid ?? \"\",\n // label: entity.metadata?.name,\n // });\n // });\n\n // return entities;\n // },\n // refetchOnWindowFocus: false,\n // });\n // }\n // const {\n // data: fetchedEntities = [],\n // isError: isLoadingEntitiesError,\n // isFetching: isFetchingEntities,\n // isLoading: isLoadingEntities,\n // } = useGetCatalogEntities();\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 await pagerDutyApi.storeServiceMapping(\n mapping.serviceId,\n mapping.entityRef\n );\n },\n // client side optimistic update\n // onMutate: (newMappingInfo: PagerDutyEntityMapping) => {\n // queryClient.setQueryData([\"mappings\"], (prevMappings: any) =>\n // prevMappings?.map((prevMapping: PagerDutyEntityMapping) =>\n // prevMapping.serviceId === newMappingInfo.serviceId\n // ? newMappingInfo\n // : prevMapping\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\n // fetch entities if not already fetched\n if (catalogEntities.length === 0) {\n fetchCatalogEntities();\n }\n \n const options : DropdownOption[] = catalogEntities.map((entity) => ({\n value: entity.id,\n label: entity.name,\n }));\n\n return options;\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\n header: \"Mapping\",\n editVariant: \"select\",\n editSelectOptions: getCatalogEntityOptions(),\n muiEditTextFieldProps: {\n select: true,\n error: !!validationErrors?.state,\n helperText: validationErrors?.state,\n },\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\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: updateUser, isPending: isUpdatingMapping } =\n useUpdateMapping();\n\n // UPDATE action\n const handleSaveUser: MRT_TableOptions<PagerDutyEntityMapping>[\"onEditingRowSave\"] =\n async ({ values, table }) => {\n await updateUser(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 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: handleSaveUser,\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, // || isLoadingEntities,\n isSaving: isUpdatingMapping,\n showAlertBanner: isLoadingMappingsError, // || isLoadingEntitiesError,\n showProgressBars: isFetchingMappings, // || isFetchingEntities,\n columnVisibility: {\n serviceId: false\n }\n },\n });\n\n return <MaterialReactTable table={dataTable} />;\n };\n\n const queryClient = new QueryClient();\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":[],"mappings":"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"}
@@ -83,12 +83,30 @@ class PagerDutyClient {
83
83
  }
84
84
  return response;
85
85
  }
86
- async getAllServices() {
86
+ async getEntityMappings() {
87
87
  const url = `${await this.config.discoveryApi.getBaseUrl(
88
88
  "pagerduty"
89
- )}/services`;
89
+ )}/mapping/entity`;
90
90
  return await this.findByUrl(url);
91
91
  }
92
+ async storeServiceMapping(serviceId, backstageEntityId) {
93
+ const body = JSON.stringify({
94
+ entityRef: backstageEntityId,
95
+ serviceId
96
+ });
97
+ const options = {
98
+ method: "POST",
99
+ headers: {
100
+ "Content-Type": "application/json; charset=UTF-8",
101
+ Accept: "application/json, text/plain, */*"
102
+ },
103
+ body
104
+ };
105
+ const url = `${await this.config.discoveryApi.getBaseUrl(
106
+ "pagerduty"
107
+ )}/mapping/entity`;
108
+ return this.request(url, options);
109
+ }
92
110
  async getServiceByEntity(entity) {
93
111
  return await this.getServiceByPagerDutyEntity(getPagerDutyEntity(entity));
94
112
  }
@@ -211,7 +229,7 @@ const pagerDutyPlugin = createPlugin({
211
229
  const PagerDutyPage = pagerDutyPlugin.provide(
212
230
  createRoutableExtension({
213
231
  name: "PagerDutyPage",
214
- component: () => import('./index-5125111c.esm.js').then((m) => m.PagerDutyPage),
232
+ component: () => import('./index-447645f1.esm.js').then((m) => m.PagerDutyPage),
215
233
  mountPoint: rootRouteRef
216
234
  })
217
235
  );
@@ -239,7 +257,7 @@ const HomePagePagerDutyCard = pagerDutyPlugin.provide(
239
257
  createCardExtension({
240
258
  name: "HomePagePagerDutyCard",
241
259
  title: "PagerDuty Homepage Card",
242
- components: () => import('./index-76060cea.esm.js'),
260
+ components: () => import('./index-1dd9ce58.esm.js'),
243
261
  settings: {
244
262
  schema: {
245
263
  title: "PagerDuty",
@@ -1605,4 +1623,4 @@ function TriggerButton(props) {
1605
1623
  const PagerDutyCard = EntityPagerDutyCard;
1606
1624
 
1607
1625
  export { EntityPagerDutyCard$1 as E, HomePagePagerDutyCard as H, PagerDutyCard$1 as P, TriggerButton as T, UnauthorizedError as U, pagerDutyPlugin as a, PagerDutyPage as b, EntityPagerDutySmallCard$1 as c, isPluginApplicableToEntity as d, PagerDutyClient as e, PagerDutyCard as f, isPluginApplicableToEntity$1 as i, pagerDutyApiRef as p };
1608
- //# sourceMappingURL=index-814058ce.esm.js.map
1626
+ //# sourceMappingURL=index-9e997679.esm.js.map