@pagerduty/backstage-plugin 0.17.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/alpha/api.esm.js.map +1 -1
  3. package/dist/api/client.esm.js +113 -2
  4. package/dist/api/client.esm.js.map +1 -1
  5. package/dist/components/EntityPagerDutyCard/index.esm.js +1 -0
  6. package/dist/components/EntityPagerDutyCard/index.esm.js.map +1 -1
  7. package/dist/components/EntityPagerDutySmallCard/index.esm.js +1 -0
  8. package/dist/components/EntityPagerDutySmallCard/index.esm.js.map +1 -1
  9. package/dist/components/Errors/ServiceNotFoundError.esm.js +143 -16
  10. package/dist/components/Errors/ServiceNotFoundError.esm.js.map +1 -1
  11. package/dist/components/HomePagePagerDutyCard/Content.esm.js.map +1 -1
  12. package/dist/components/PagerDutyCard/index.esm.js +16 -2
  13. package/dist/components/PagerDutyCard/index.esm.js.map +1 -1
  14. package/dist/components/PagerDutyPage/AccountContext.esm.js +56 -0
  15. package/dist/components/PagerDutyPage/AccountContext.esm.js.map +1 -0
  16. package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js +197 -0
  17. package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js.map +1 -0
  18. package/dist/components/PagerDutyPage/MappingsDialog.esm.js +242 -0
  19. package/dist/components/PagerDutyPage/MappingsDialog.esm.js.map +1 -0
  20. package/dist/components/PagerDutyPage/MappingsTable/AutoMappingsButton.esm.js +74 -0
  21. package/dist/components/PagerDutyPage/MappingsTable/AutoMappingsButton.esm.js.map +1 -0
  22. package/dist/components/PagerDutyPage/MappingsTable/EmptyTableState.esm.js +26 -0
  23. package/dist/components/PagerDutyPage/MappingsTable/EmptyTableState.esm.js.map +1 -0
  24. package/dist/components/PagerDutyPage/MappingsTable/FilterRow.esm.js +67 -0
  25. package/dist/components/PagerDutyPage/MappingsTable/FilterRow.esm.js.map +1 -0
  26. package/dist/components/PagerDutyPage/MappingsTable/MappingToast.esm.js +69 -0
  27. package/dist/components/PagerDutyPage/MappingsTable/MappingToast.esm.js.map +1 -0
  28. package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js +202 -0
  29. package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js.map +1 -0
  30. package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js +231 -0
  31. package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js.map +1 -0
  32. package/dist/components/PagerDutyPage/MappingsTable/ServiceCell.esm.js +31 -0
  33. package/dist/components/PagerDutyPage/MappingsTable/ServiceCell.esm.js.map +1 -0
  34. package/dist/components/PagerDutyPage/MappingsTable/StatusCell.esm.js +112 -0
  35. package/dist/components/PagerDutyPage/MappingsTable/StatusCell.esm.js.map +1 -0
  36. package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js +50 -0
  37. package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js.map +1 -0
  38. package/dist/components/PagerDutyPage/MappingsTable/hooks/useConfirmMappings.esm.js +70 -0
  39. package/dist/components/PagerDutyPage/MappingsTable/hooks/useConfirmMappings.esm.js.map +1 -0
  40. package/dist/components/PagerDutyPage/ServiceMappingComponent.esm.js +67 -44
  41. package/dist/components/PagerDutyPage/ServiceMappingComponent.esm.js.map +1 -1
  42. package/dist/components/PagerDutyPage/index.esm.js +27 -12
  43. package/dist/components/PagerDutyPage/index.esm.js.map +1 -1
  44. package/dist/components/PagerDutySmallCard/index.esm.js +2 -2
  45. package/dist/components/PagerDutySmallCard/index.esm.js.map +1 -1
  46. package/dist/components/TriggerButton/index.esm.js +1 -1
  47. package/dist/components/TriggerButton/index.esm.js.map +1 -1
  48. package/dist/hooks/useDebounce.esm.js +13 -0
  49. package/dist/hooks/useDebounce.esm.js.map +1 -0
  50. package/dist/hooks/{index.esm.js → usePagerDutyEntity.esm.js} +1 -1
  51. package/dist/hooks/usePagerDutyEntity.esm.js.map +1 -0
  52. package/dist/index.d.ts +124 -4
  53. package/dist/package.json.esm.js +1 -1
  54. package/package.json +13 -13
  55. package/dist/components/PagerDutyPage/MappingTable.esm.js +0 -282
  56. package/dist/components/PagerDutyPage/MappingTable.esm.js.map +0 -1
  57. package/dist/hooks/index.esm.js.map +0 -1
@@ -0,0 +1,231 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useTable, CellText, Table } from '@backstage/ui';
3
+ import { useMemo } from 'react';
4
+ import { useApi } from '@backstage/core-plugin-api';
5
+ import StatusCell from './StatusCell.esm.js';
6
+ import { ServiceCell } from './ServiceCell.esm.js';
7
+ import { Delete, Edit } from '@mui/icons-material';
8
+ import { FilterRow } from './FilterRow.esm.js';
9
+ import { TableSkeleton } from './TableSkeleton.esm.js';
10
+ import { EmptyTableState } from './EmptyTableState.esm.js';
11
+ import useDebounce from '../../../hooks/useDebounce.esm.js';
12
+ import { pagerDutyApiRef } from '../../../api/client.esm.js';
13
+ import { useAccountContext } from '../AccountContext.esm.js';
14
+
15
+ function MappingsTableContent({
16
+ autoMatchResults,
17
+ hasMatches,
18
+ showFilters,
19
+ filters,
20
+ onFilterChange,
21
+ onEditEntity,
22
+ onRemoveMatch
23
+ }) {
24
+ const pagerDutyApi = useApi(pagerDutyApiRef);
25
+ const { selectedAccount } = useAccountContext();
26
+ const debouncedFilters = useDebounce(filters);
27
+ const { tableProps } = useTable({
28
+ mode: "offset",
29
+ filter: debouncedFilters,
30
+ getData: async ({ offset, pageSize, sort, filter }) => {
31
+ if (hasMatches) {
32
+ let matchedEntities = Object.entries(
33
+ autoMatchResults
34
+ ).map(([entityName, matchResult]) => {
35
+ const entityRef = matchResult.entity?.entityRef || "";
36
+ const refParts = entityRef.split(":");
37
+ const type = refParts[0] || "component";
38
+ const namespaceName = refParts[1]?.split("/") || ["default", entityName];
39
+ const namespace = namespaceName[0] || "default";
40
+ return {
41
+ id: entityRef || `${type}:${namespace}/${entityName}`,
42
+ name: entityName,
43
+ namespace,
44
+ type,
45
+ system: "",
46
+ owner: matchResult.entity?.owner || "",
47
+ lifecycle: "",
48
+ annotations: {
49
+ "pagerduty.com/integration-key": "",
50
+ "pagerduty.com/service-id": matchResult.serviceId
51
+ },
52
+ serviceName: matchResult.serviceName,
53
+ serviceUrl: `https://pagerduty.com/services/${matchResult.serviceId}`,
54
+ team: matchResult.entity?.owner || "",
55
+ escalationPolicy: "",
56
+ status: "AutoMapped",
57
+ account: matchResult.account,
58
+ mappingScore: matchResult.score,
59
+ autoMatchedServiceId: matchResult.serviceId,
60
+ autoMatchedServiceName: matchResult.serviceName
61
+ };
62
+ });
63
+ if (filter) {
64
+ matchedEntities = matchedEntities.filter((entity) => {
65
+ if (filter.name && !entity.name.toLowerCase().includes(filter.name.toLowerCase())) {
66
+ return false;
67
+ }
68
+ if (filter.serviceName && entity.serviceName && !entity.serviceName.toLowerCase().includes(filter.serviceName.toLowerCase())) {
69
+ return false;
70
+ }
71
+ if (filter.status && entity.status !== filter.status) {
72
+ return false;
73
+ }
74
+ if (filter.teamName && entity.owner && !entity.owner.toLowerCase().includes(filter.teamName.toLowerCase())) {
75
+ return false;
76
+ }
77
+ return true;
78
+ });
79
+ }
80
+ if (sort) {
81
+ matchedEntities.sort((a, b) => {
82
+ let aValue = "";
83
+ let bValue = "";
84
+ switch (sort.column) {
85
+ case "name":
86
+ aValue = a.name.toLowerCase();
87
+ bValue = b.name.toLowerCase();
88
+ break;
89
+ case "team":
90
+ aValue = (a.owner || "").toLowerCase();
91
+ bValue = (b.owner || "").toLowerCase();
92
+ break;
93
+ case "serviceName":
94
+ aValue = (a.serviceName || "").toLowerCase();
95
+ bValue = (b.serviceName || "").toLowerCase();
96
+ break;
97
+ case "status":
98
+ aValue = (a.status || "").toLowerCase();
99
+ bValue = (b.status || "").toLowerCase();
100
+ break;
101
+ case "mappingScore":
102
+ aValue = a.mappingScore ?? 0;
103
+ bValue = b.mappingScore ?? 0;
104
+ break;
105
+ default:
106
+ return 0;
107
+ }
108
+ if (aValue < bValue) {
109
+ return sort.direction === "ascending" ? -1 : 1;
110
+ }
111
+ if (aValue > bValue) {
112
+ return sort.direction === "ascending" ? 1 : -1;
113
+ }
114
+ return 0;
115
+ });
116
+ }
117
+ const start = offset;
118
+ const end = offset + pageSize;
119
+ const paginatedData = matchedEntities.slice(start, end);
120
+ return {
121
+ data: paginatedData,
122
+ totalCount: matchedEntities.length
123
+ };
124
+ }
125
+ const response = await pagerDutyApi.getEntityMappingsWithPagination({
126
+ offset,
127
+ limit: pageSize,
128
+ filters: filter,
129
+ sort: sort ? { column: String(sort.column), direction: sort.direction } : void 0,
130
+ account: selectedAccount
131
+ });
132
+ return {
133
+ data: response.entities,
134
+ totalCount: response.totalCount
135
+ };
136
+ },
137
+ paginationOptions: {
138
+ pageSize: 10,
139
+ pageSizeOptions: [10, 25, 50, 100]
140
+ }
141
+ });
142
+ const columnConfig = useMemo(() => {
143
+ const baseColumns = [
144
+ {
145
+ id: "name",
146
+ label: "Name",
147
+ isRowHeader: true,
148
+ isSortable: true,
149
+ cell: (entity) => /* @__PURE__ */ jsx(CellText, { title: entity.name })
150
+ },
151
+ {
152
+ id: "team",
153
+ label: "Team",
154
+ isRowHeader: true,
155
+ isSortable: true,
156
+ cell: (entity) => /* @__PURE__ */ jsx(CellText, { title: entity.owner })
157
+ },
158
+ {
159
+ id: "serviceName",
160
+ label: "PagerDuty service",
161
+ isRowHeader: true,
162
+ isSortable: true,
163
+ cell: (entity) => /* @__PURE__ */ jsx(ServiceCell, { entity })
164
+ },
165
+ {
166
+ id: "status",
167
+ label: "Status",
168
+ isRowHeader: true,
169
+ isSortable: true,
170
+ cell: (entity) => /* @__PURE__ */ jsx(StatusCell, { entity })
171
+ }
172
+ ];
173
+ if (hasMatches) {
174
+ baseColumns.push({
175
+ id: "mappingScore",
176
+ label: "Mapping Score",
177
+ isRowHeader: true,
178
+ isSortable: true,
179
+ cell: (entity) => /* @__PURE__ */ jsx(
180
+ CellText,
181
+ {
182
+ title: entity.mappingScore !== void 0 ? `${entity.mappingScore}%` : "\u2014"
183
+ }
184
+ )
185
+ });
186
+ }
187
+ baseColumns.push({
188
+ id: "actions",
189
+ label: "Actions",
190
+ isRowHeader: true,
191
+ isSortable: false,
192
+ cell: (entity) => /* @__PURE__ */ jsx(
193
+ CellText,
194
+ {
195
+ leadingIcon: entity.mappingScore !== void 0 ? /* @__PURE__ */ jsx(Delete, { fontSize: "small" }) : /* @__PURE__ */ jsx(Edit, { fontSize: "small" }),
196
+ color: "secondary",
197
+ style: {
198
+ paddingLeft: "25px",
199
+ cursor: "pointer",
200
+ maxWidth: "min-content"
201
+ },
202
+ title: "",
203
+ onClick: () => {
204
+ if (entity.mappingScore !== void 0) {
205
+ onRemoveMatch(entity.name);
206
+ } else {
207
+ onEditEntity(entity);
208
+ }
209
+ }
210
+ }
211
+ )
212
+ });
213
+ return baseColumns;
214
+ }, [hasMatches, onRemoveMatch, onEditEntity]);
215
+ const isInitialLoad = tableProps.loading && (!tableProps.data || tableProps.data.length === 0);
216
+ const hasActiveFilters = showFilters && (!!filters.name || !!filters.serviceName || !!filters.status || !!filters.teamName);
217
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
218
+ showFilters && /* @__PURE__ */ jsx(FilterRow, { filters, onFilterChange }),
219
+ isInitialLoad ? /* @__PURE__ */ jsx(TableSkeleton, {}) : /* @__PURE__ */ jsx(
220
+ Table,
221
+ {
222
+ columnConfig,
223
+ ...tableProps,
224
+ emptyState: /* @__PURE__ */ jsx(EmptyTableState, { hasActiveFilters })
225
+ }
226
+ )
227
+ ] });
228
+ }
229
+
230
+ export { MappingsTableContent as default };
231
+ //# sourceMappingURL=MappingsTableContent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MappingsTableContent.esm.js","sources":["../../../../src/components/PagerDutyPage/MappingsTable/MappingsTableContent.tsx"],"sourcesContent":["import {\n Table,\n useTable,\n CellText,\n type ColumnConfig,\n} from '@backstage/ui';\nimport { useMemo } from 'react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport StatusCell from './StatusCell';\nimport { ServiceCell } from './ServiceCell';\nimport { Edit, Delete } from '@mui/icons-material';\nimport { FilterRow } from './FilterRow';\nimport { TableSkeleton } from './TableSkeleton';\nimport { EmptyTableState } from './EmptyTableState';\nimport { BackstageEntity } from '../../types';\nimport useDebounce from '../../../hooks/useDebounce';\nimport { pagerDutyApiRef } from '../../../api';\nimport { AutoMatchResults } from './MappingsTable';\nimport { useAccountContext } from '../AccountContext';\n\ninterface MappingsTableContentProps {\n autoMatchResults: AutoMatchResults;\n hasMatches: boolean;\n showFilters: boolean;\n filters: {\n name: string;\n serviceName: string;\n status: string;\n teamName: string;\n };\n onFilterChange: (\n key: 'name' | 'serviceName' | 'status' | 'teamName',\n value: string,\n ) => void;\n onEditEntity: (entity: BackstageEntity) => void;\n onRemoveMatch: (entityName: string) => void;\n}\n\n\nexport default function MappingsTableContent({\n autoMatchResults,\n hasMatches,\n showFilters,\n filters,\n onFilterChange,\n onEditEntity,\n onRemoveMatch,\n}: MappingsTableContentProps) {\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const { selectedAccount } = useAccountContext();\n const debouncedFilters = useDebounce(filters);\n\n const { tableProps } = useTable<BackstageEntity, typeof filters>({\n mode: 'offset',\n filter: debouncedFilters,\n getData: async ({ offset, pageSize, sort, filter }) => {\n if (hasMatches) {\n let matchedEntities: BackstageEntity[] = Object.entries(\n autoMatchResults,\n ).map(([entityName, matchResult]) => {\n const entityRef = matchResult.entity?.entityRef || '';\n const refParts = entityRef.split(':');\n const type = refParts[0] || 'component';\n const namespaceName = refParts[1]?.split('/') || ['default', entityName];\n const namespace = namespaceName[0] || 'default';\n\n return {\n id: entityRef || `${type}:${namespace}/${entityName}`,\n name: entityName,\n namespace: namespace,\n type: type,\n system: '',\n owner: matchResult.entity?.owner || '',\n lifecycle: '',\n annotations: {\n 'pagerduty.com/integration-key': '',\n 'pagerduty.com/service-id': matchResult.serviceId,\n },\n serviceName: matchResult.serviceName,\n serviceUrl: `https://pagerduty.com/services/${matchResult.serviceId}`,\n team: matchResult.entity?.owner || '',\n escalationPolicy: '',\n status: 'AutoMapped' as const,\n account: matchResult.account,\n mappingScore: matchResult.score,\n autoMatchedServiceId: matchResult.serviceId,\n autoMatchedServiceName: matchResult.serviceName,\n } as BackstageEntity;\n });\n\n if (filter) {\n matchedEntities = matchedEntities.filter(entity => {\n if (filter.name && !entity.name.toLowerCase().includes(filter.name.toLowerCase())) {\n return false;\n }\n if (filter.serviceName && entity.serviceName && !entity.serviceName.toLowerCase().includes(filter.serviceName.toLowerCase())) {\n return false;\n }\n if (filter.status && entity.status !== filter.status) {\n return false;\n }\n if (filter.teamName && entity.owner && !entity.owner.toLowerCase().includes(filter.teamName.toLowerCase())) {\n return false;\n }\n return true;\n });\n }\n\n if (sort) {\n matchedEntities.sort((a, b) => {\n let aValue: string | number = '';\n let bValue: string | number = '';\n\n switch (sort.column) {\n case 'name':\n aValue = a.name.toLowerCase();\n bValue = b.name.toLowerCase();\n break;\n case 'team':\n aValue = (a.owner || '').toLowerCase();\n bValue = (b.owner || '').toLowerCase();\n break;\n case 'serviceName':\n aValue = (a.serviceName || '').toLowerCase();\n bValue = (b.serviceName || '').toLowerCase();\n break;\n case 'status':\n aValue = (a.status || '').toLowerCase();\n bValue = (b.status || '').toLowerCase();\n break;\n case 'mappingScore':\n aValue = a.mappingScore ?? 0;\n bValue = b.mappingScore ?? 0;\n break;\n default:\n return 0;\n }\n\n if (aValue < bValue) {\n return sort.direction === 'ascending' ? -1 : 1;\n }\n if (aValue > bValue) {\n return sort.direction === 'ascending' ? 1 : -1;\n }\n return 0;\n });\n }\n\n const start = offset;\n const end = offset + pageSize;\n const paginatedData = matchedEntities.slice(start, end);\n\n return {\n data: paginatedData,\n totalCount: matchedEntities.length,\n };\n }\n const response = await pagerDutyApi.getEntityMappingsWithPagination({\n offset,\n limit: pageSize,\n filters: filter,\n sort: sort\n ? { column: String(sort.column), direction: sort.direction }\n : undefined,\n account: selectedAccount,\n });\n\n return {\n data: response.entities as BackstageEntity[],\n totalCount: response.totalCount,\n };\n },\n paginationOptions: {\n pageSize: 10,\n pageSizeOptions: [10, 25, 50, 100],\n },\n });\n\n const columnConfig: ColumnConfig<BackstageEntity>[] = useMemo(() => {\n const baseColumns: ColumnConfig<BackstageEntity>[] = [\n {\n id: 'name',\n label: 'Name',\n isRowHeader: true,\n isSortable: true,\n cell: entity => <CellText title={entity.name} />,\n },\n {\n id: 'team',\n label: 'Team',\n isRowHeader: true,\n isSortable: true,\n cell: entity => <CellText title={entity.owner} />,\n },\n {\n id: 'serviceName',\n label: 'PagerDuty service',\n isRowHeader: true,\n isSortable: true,\n cell: entity => <ServiceCell entity={entity} />,\n },\n {\n id: 'status',\n label: 'Status',\n isRowHeader: true,\n isSortable: true,\n cell: entity => <StatusCell entity={entity} />,\n },\n ];\n \n if (hasMatches) {\n baseColumns.push({\n id: 'mappingScore',\n label: 'Mapping Score',\n isRowHeader: true,\n isSortable: true,\n cell: entity => (\n <CellText\n title={\n entity.mappingScore !== undefined\n ? `${entity.mappingScore}%`\n : '—'\n }\n />\n ),\n });\n }\n\n baseColumns.push({\n id: 'actions',\n label: 'Actions',\n isRowHeader: true,\n isSortable: false,\n cell: entity => (\n <CellText\n leadingIcon={\n entity.mappingScore !== undefined ? (\n <Delete fontSize=\"small\" />\n ) : (\n <Edit fontSize=\"small\" />\n )\n }\n color=\"secondary\"\n style={{\n paddingLeft: '25px',\n cursor: 'pointer',\n maxWidth: 'min-content',\n }}\n title=\"\"\n onClick={() => {\n if (entity.mappingScore !== undefined) {\n onRemoveMatch(entity.name);\n } else {\n onEditEntity(entity);\n }\n }}\n />\n ),\n });\n\n return baseColumns;\n }, [hasMatches, onRemoveMatch, onEditEntity]);\n\n const isInitialLoad =\n tableProps.loading && (!tableProps.data || tableProps.data.length === 0);\n\n const hasActiveFilters =\n showFilters &&\n (!!filters.name ||\n !!filters.serviceName ||\n !!filters.status ||\n !!filters.teamName);\n\n return (\n <>\n {showFilters && (\n <FilterRow filters={filters} onFilterChange={onFilterChange} />\n )}\n\n {isInitialLoad ? (\n <TableSkeleton />\n ) : (\n <Table\n columnConfig={columnConfig}\n {...tableProps}\n emptyState={<EmptyTableState hasActiveFilters={hasActiveFilters} />}\n />\n )}\n </>\n );\n}"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { CellText } from '@backstage/ui';
3
+ import { makeStyles } from '@material-ui/core';
4
+
5
+ const useStyles = makeStyles((theme) => ({
6
+ underlinedCell: {
7
+ "& .bui-Text": {
8
+ textDecoration: "underline",
9
+ color: theme.palette.link,
10
+ transition: "color 0.15s",
11
+ "&:hover": {
12
+ opacity: 0.8
13
+ }
14
+ }
15
+ }
16
+ }));
17
+ function ServiceCell({ entity }) {
18
+ const classes = useStyles();
19
+ return /* @__PURE__ */ jsx(
20
+ CellText,
21
+ {
22
+ color: "secondary",
23
+ className: classes.underlinedCell,
24
+ title: entity.serviceName ?? "",
25
+ href: entity.serviceUrl
26
+ }
27
+ );
28
+ }
29
+
30
+ export { ServiceCell };
31
+ //# sourceMappingURL=ServiceCell.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ServiceCell.esm.js","sources":["../../../../src/components/PagerDutyPage/MappingsTable/ServiceCell.tsx"],"sourcesContent":["import { CellText } from '@backstage/ui';\nimport { makeStyles } from '@material-ui/core';\nimport { BackstageEntity } from '../../types';\n\nconst useStyles = makeStyles(theme => ({\n underlinedCell: {\n '& .bui-Text': {\n textDecoration: 'underline',\n color: theme.palette.link,\n transition: 'color 0.15s',\n '&:hover': {\n opacity: 0.8,\n },\n },\n },\n}));\n\ntype ServiceCellProps = {\n entity: BackstageEntity;\n};\n\nexport function ServiceCell({ entity }: ServiceCellProps) {\n const classes = useStyles();\n\n return (\n <CellText\n color=\"secondary\"\n className={classes.underlinedCell}\n title={entity.serviceName ?? ''}\n href={entity.serviceUrl}\n />\n );\n}\n"],"names":[],"mappings":";;;;AAIA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,cAAA,EAAgB;AAAA,IACd,aAAA,EAAe;AAAA,MACb,cAAA,EAAgB,WAAA;AAAA,MAChB,KAAA,EAAO,MAAM,OAAA,CAAQ,IAAA;AAAA,MACrB,UAAA,EAAY,aAAA;AAAA,MACZ,SAAA,EAAW;AAAA,QACT,OAAA,EAAS;AAAA;AACX;AACF;AAEJ,CAAA,CAAE,CAAA;AAMK,SAAS,WAAA,CAAY,EAAE,MAAA,EAAO,EAAqB;AACxD,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,WAAA;AAAA,MACN,WAAW,OAAA,CAAQ,cAAA;AAAA,MACnB,KAAA,EAAO,OAAO,WAAA,IAAe,EAAA;AAAA,MAC7B,MAAM,MAAA,CAAO;AAAA;AAAA,GACf;AAEJ;;;;"}
@@ -0,0 +1,112 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { CellText } from '@backstage/ui';
3
+ import { useTheme, makeStyles } from '@material-ui/core';
4
+
5
+ const statusDictionary = {
6
+ InSync: "In Sync",
7
+ OutOfSync: "Out of Sync",
8
+ NotMapped: "Not Mapped",
9
+ AutoMapped: "Auto Mapped",
10
+ ErrorWhenFetchingService: "Error occured while fetching service"
11
+ };
12
+ function getStatusName(status) {
13
+ return statusDictionary[status] || "Refresh to Update";
14
+ }
15
+ function getStatusColors(status, isDarkTheme) {
16
+ const statusKey = status;
17
+ if (isDarkTheme) {
18
+ const darkColors = {
19
+ InSync: {
20
+ color: "#4CAF50",
21
+ backgroundColor: "rgba(76, 175, 80, 0.15)",
22
+ borderColor: "rgba(76, 175, 80, 0.4)"
23
+ },
24
+ OutOfSync: {
25
+ color: "#f44336",
26
+ backgroundColor: "rgba(244, 67, 54, 0.15)",
27
+ borderColor: "rgba(244, 67, 54, 0.4)"
28
+ },
29
+ NotMapped: {
30
+ color: "#FFA726",
31
+ backgroundColor: "rgba(255, 167, 38, 0.15)",
32
+ borderColor: "rgba(255, 167, 38, 0.4)"
33
+ },
34
+ AutoMapped: {
35
+ color: "#42A5F5",
36
+ backgroundColor: "rgba(66, 165, 245, 0.15)",
37
+ borderColor: "rgba(66, 165, 245, 0.4)"
38
+ },
39
+ ErrorWhenFetchingService: {
40
+ color: "#f44336",
41
+ backgroundColor: "rgba(244, 67, 54, 0.15)",
42
+ borderColor: "rgba(244, 67, 54, 0.4)"
43
+ }
44
+ };
45
+ return darkColors[statusKey] || {
46
+ color: "#999",
47
+ backgroundColor: "rgba(153, 153, 153, 0.15)",
48
+ borderColor: "rgba(153, 153, 153, 0.4)"
49
+ };
50
+ }
51
+ const lightColors = {
52
+ InSync: {
53
+ color: "#00875A",
54
+ backgroundColor: "#E3FCEF",
55
+ borderColor: "#57D9A3"
56
+ },
57
+ OutOfSync: {
58
+ color: "#fff",
59
+ backgroundColor: "red",
60
+ borderColor: "red"
61
+ },
62
+ NotMapped: {
63
+ color: "#B88A00",
64
+ backgroundColor: "#FFF8E6",
65
+ borderColor: "#E8C547"
66
+ },
67
+ AutoMapped: {
68
+ color: "#1565C0",
69
+ backgroundColor: "#E3F2FD",
70
+ borderColor: "#64B5F6"
71
+ },
72
+ ErrorWhenFetchingService: {
73
+ color: "#fff",
74
+ backgroundColor: "red",
75
+ borderColor: "red"
76
+ }
77
+ };
78
+ return lightColors[statusKey] || {
79
+ color: "gray",
80
+ backgroundColor: "#f0f0f0",
81
+ borderColor: "gray"
82
+ };
83
+ }
84
+ const useStyles = makeStyles(() => {
85
+ return {
86
+ pill: (props) => ({
87
+ "& .bui-Text": {
88
+ backgroundColor: props.backgroundColor,
89
+ borderRadius: "4px",
90
+ color: props.color,
91
+ padding: "4px 12px",
92
+ maxWidth: "min-content",
93
+ fontSize: "12px",
94
+ fontWeight: 500,
95
+ border: `1px solid ${props.borderColor}`,
96
+ display: "inline-block"
97
+ }
98
+ })
99
+ };
100
+ });
101
+ function StatusCell({ entity }) {
102
+ const theme = useTheme();
103
+ const isDarkTheme = theme.palette.type === "dark";
104
+ const statusValue = entity.status || "NotMapped";
105
+ const { color, backgroundColor, borderColor } = getStatusColors(statusValue, isDarkTheme);
106
+ const classes = useStyles({ color, backgroundColor, borderColor });
107
+ const statusName = getStatusName(statusValue);
108
+ return /* @__PURE__ */ jsx(CellText, { title: statusName, className: classes.pill });
109
+ }
110
+
111
+ export { StatusCell as default };
112
+ //# sourceMappingURL=StatusCell.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusCell.esm.js","sources":["../../../../src/components/PagerDutyPage/MappingsTable/StatusCell.tsx"],"sourcesContent":["import { CellText } from '@backstage/ui';\nimport { makeStyles, useTheme } from '@material-ui/core';\nimport { BackstageTheme } from '@backstage/theme';\nimport { BackstageEntity } from '../../types';\n\nconst statusDictionary = {\n InSync: 'In Sync',\n OutOfSync: 'Out of Sync',\n NotMapped: 'Not Mapped',\n AutoMapped: 'Auto Mapped',\n ErrorWhenFetchingService: 'Error occured while fetching service',\n} as const;\n\ntype StatusKey = keyof typeof statusDictionary;\n\nfunction getStatusName(status: string) {\n return statusDictionary[status as StatusKey] || 'Refresh to Update';\n}\n\nfunction getStatusColors(status: string, isDarkTheme: boolean) {\n const statusKey = status as StatusKey;\n\n if (isDarkTheme) {\n const darkColors = {\n InSync: {\n color: '#4CAF50',\n backgroundColor: 'rgba(76, 175, 80, 0.15)',\n borderColor: 'rgba(76, 175, 80, 0.4)',\n },\n OutOfSync: {\n color: '#f44336',\n backgroundColor: 'rgba(244, 67, 54, 0.15)',\n borderColor: 'rgba(244, 67, 54, 0.4)',\n },\n NotMapped: {\n color: '#FFA726',\n backgroundColor: 'rgba(255, 167, 38, 0.15)',\n borderColor: 'rgba(255, 167, 38, 0.4)',\n },\n AutoMapped: {\n color: '#42A5F5',\n backgroundColor: 'rgba(66, 165, 245, 0.15)',\n borderColor: 'rgba(66, 165, 245, 0.4)',\n },\n ErrorWhenFetchingService: {\n color: '#f44336',\n backgroundColor: 'rgba(244, 67, 54, 0.15)',\n borderColor: 'rgba(244, 67, 54, 0.4)',\n },\n };\n return darkColors[statusKey] || {\n color: '#999',\n backgroundColor: 'rgba(153, 153, 153, 0.15)',\n borderColor: 'rgba(153, 153, 153, 0.4)',\n };\n }\n\n const lightColors = {\n InSync: {\n color: '#00875A',\n backgroundColor: '#E3FCEF',\n borderColor: '#57D9A3',\n },\n OutOfSync: {\n color: '#fff',\n backgroundColor: 'red',\n borderColor: 'red',\n },\n NotMapped: {\n color: '#B88A00',\n backgroundColor: '#FFF8E6',\n borderColor: '#E8C547',\n },\n AutoMapped: {\n color: '#1565C0',\n backgroundColor: '#E3F2FD',\n borderColor: '#64B5F6',\n },\n ErrorWhenFetchingService: {\n color: '#fff',\n backgroundColor: 'red',\n borderColor: 'red',\n },\n };\n return lightColors[statusKey] || {\n color: 'gray',\n backgroundColor: '#f0f0f0',\n borderColor: 'gray',\n };\n}\n\ninterface StyleProps {\n color: string;\n backgroundColor: string;\n borderColor: string;\n}\n\nconst useStyles = makeStyles<BackstageTheme, StyleProps>(() => {\n return {\n pill: (props: StyleProps) => ({\n '& .bui-Text': {\n backgroundColor: props.backgroundColor,\n borderRadius: '4px',\n color: props.color,\n padding: '4px 12px',\n maxWidth: 'min-content',\n fontSize: '12px',\n fontWeight: 500,\n border: `1px solid ${props.borderColor}`,\n display: 'inline-block',\n },\n }),\n };\n});\n\nexport default function StatusCell({ entity }: { entity: BackstageEntity }) {\n const theme = useTheme();\n const isDarkTheme = theme.palette.type === 'dark';\n const statusValue = entity.status || 'NotMapped';\n const { color, backgroundColor, borderColor } = getStatusColors(statusValue, isDarkTheme);\n const classes = useStyles({ color, backgroundColor, borderColor });\n\n const statusName = getStatusName(statusValue);\n return <CellText title={statusName} className={classes.pill} />;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, Flex, Skeleton } from '@backstage/ui';
3
+
4
+ function TableSkeleton() {
5
+ return /* @__PURE__ */ jsxs(Box, { "data-testid": "mappings-table-skeleton", style: { width: "100%" }, mt: "4", children: [
6
+ /* @__PURE__ */ jsxs(
7
+ Flex,
8
+ {
9
+ gap: "4",
10
+ style: {
11
+ padding: "1rem",
12
+ borderBottom: "1px solid var(--bui-border-neutral-default)",
13
+ backgroundColor: "var(--bui-bg-surface-0)"
14
+ },
15
+ children: [
16
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "20px", width: "15%" } }),
17
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "20px", width: "15%" } }),
18
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "20px", width: "20%" } }),
19
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "20px", width: "12%" } }),
20
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "20px", width: "12%" } }),
21
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "20px", width: "12%" } }),
22
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "20px", width: "10%" } })
23
+ ]
24
+ }
25
+ ),
26
+ [...Array(10)].map((_, index) => /* @__PURE__ */ jsxs(
27
+ Flex,
28
+ {
29
+ gap: "4",
30
+ style: {
31
+ padding: "1rem",
32
+ borderBottom: "1px solid var(--bui-border-neutral-subtle)"
33
+ },
34
+ children: [
35
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "16px", width: "15%" } }),
36
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "16px", width: "15%" } }),
37
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "16px", width: "20%" } }),
38
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "16px", width: "12%" } }),
39
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "16px", width: "12%" } }),
40
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "16px", width: "12%" } }),
41
+ /* @__PURE__ */ jsx(Skeleton, { style: { height: "16px", width: "10%" } })
42
+ ]
43
+ },
44
+ index
45
+ ))
46
+ ] });
47
+ }
48
+
49
+ export { TableSkeleton };
50
+ //# sourceMappingURL=TableSkeleton.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TableSkeleton.esm.js","sources":["../../../../src/components/PagerDutyPage/MappingsTable/TableSkeleton.tsx"],"sourcesContent":["import { Box, Flex, Skeleton } from '@backstage/ui';\n\nexport function TableSkeleton() {\n return (\n <Box data-testid=\"mappings-table-skeleton\" style={{ width: '100%' }} mt=\"4\">\n <Flex\n gap=\"4\"\n style={{\n padding: '1rem',\n borderBottom: '1px solid var(--bui-border-neutral-default)',\n backgroundColor: 'var(--bui-bg-surface-0)',\n }}\n >\n <Skeleton style={{ height: '20px', width: '15%' }} />\n <Skeleton style={{ height: '20px', width: '15%' }} />\n <Skeleton style={{ height: '20px', width: '20%' }} />\n <Skeleton style={{ height: '20px', width: '12%' }} />\n <Skeleton style={{ height: '20px', width: '12%' }} />\n <Skeleton style={{ height: '20px', width: '12%' }} />\n <Skeleton style={{ height: '20px', width: '10%' }} />\n </Flex>\n\n {[...Array(10)].map((_, index) => (\n <Flex\n key={index}\n gap=\"4\"\n style={{\n padding: '1rem',\n borderBottom: '1px solid var(--bui-border-neutral-subtle)',\n }}\n >\n <Skeleton style={{ height: '16px', width: '15%' }} />\n <Skeleton style={{ height: '16px', width: '15%' }} />\n <Skeleton style={{ height: '16px', width: '20%' }} />\n <Skeleton style={{ height: '16px', width: '12%' }} />\n <Skeleton style={{ height: '16px', width: '12%' }} />\n <Skeleton style={{ height: '16px', width: '12%' }} />\n <Skeleton style={{ height: '16px', width: '10%' }} />\n </Flex>\n ))}\n </Box>\n );\n}\n"],"names":[],"mappings":";;;AAEO,SAAS,aAAA,GAAgB;AAC9B,EAAA,uBACE,IAAA,CAAC,GAAA,EAAA,EAAI,aAAA,EAAY,yBAAA,EAA0B,KAAA,EAAO,EAAE,KAAA,EAAO,MAAA,EAAO,EAAG,EAAA,EAAG,GAAA,EACtE,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAI,GAAA;AAAA,QACJ,KAAA,EAAO;AAAA,UACL,OAAA,EAAS,MAAA;AAAA,UACT,YAAA,EAAc,6CAAA;AAAA,UACd,eAAA,EAAiB;AAAA,SACnB;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG;AAAA;AAAA;AAAA,KACrD;AAAA,IAEC,CAAC,GAAG,KAAA,CAAM,EAAE,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,EAAG,KAAA,qBACtB,IAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QAEC,GAAA,EAAI,GAAA;AAAA,QACJ,KAAA,EAAO;AAAA,UACL,OAAA,EAAS,MAAA;AAAA,UACT,YAAA,EAAc;AAAA,SAChB;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG,CAAA;AAAA,0BACnD,GAAA,CAAC,YAAS,KAAA,EAAO,EAAE,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAM,EAAG;AAAA;AAAA,OAAA;AAAA,MAb9C;AAAA,KAeR;AAAA,GAAA,EACH,CAAA;AAEJ;;;;"}
@@ -0,0 +1,70 @@
1
+ import { useState } from 'react';
2
+ import { useQueryClient } from '@tanstack/react-query';
3
+ import { useApi } from '@backstage/core-plugin-api';
4
+ import { pagerDutyApiRef } from '../../../../api/client.esm.js';
5
+ import { useAccountContext } from '../../AccountContext.esm.js';
6
+
7
+ function useConfirmMappings({
8
+ autoMatchResults,
9
+ mappingEntities,
10
+ onSuccess,
11
+ onError
12
+ }) {
13
+ const pagerDutyApi = useApi(pagerDutyApiRef);
14
+ const queryClient = useQueryClient();
15
+ const { selectedAccount } = useAccountContext();
16
+ const [isConfirming, setIsConfirming] = useState(false);
17
+ const confirmMappings = async () => {
18
+ try {
19
+ setIsConfirming(true);
20
+ const totalCount = Object.keys(autoMatchResults).length;
21
+ const mappingsToCreate = Object.entries(autoMatchResults).map(
22
+ ([entityName, matchData]) => {
23
+ const entity = mappingEntities?.find(
24
+ (e) => e.name === entityName
25
+ );
26
+ const entityRef = entity ? `${entity.type}:${entity.namespace}/${entity.name}`.toLowerCase() : `component:default/${entityName}`;
27
+ return {
28
+ serviceId: matchData.serviceId,
29
+ integrationKey: "",
30
+ entityRef,
31
+ account: selectedAccount || ""
32
+ };
33
+ }
34
+ );
35
+ const response = await pagerDutyApi.storeBulkServiceMappings(
36
+ mappingsToCreate
37
+ );
38
+ if (response.ok) {
39
+ const result = await response.json();
40
+ const successCount = result.successCount || 0;
41
+ const skippedCount = result.skippedCount || 0;
42
+ const errorCount = result.errorCount || 0;
43
+ const counts = {
44
+ created: successCount,
45
+ skipped: skippedCount,
46
+ errored: errorCount
47
+ };
48
+ onSuccess(successCount, totalCount, counts);
49
+ queryClient.invalidateQueries({
50
+ queryKey: ["pagerduty", "enhancedEntityMappings"]
51
+ });
52
+ } else {
53
+ const errorData = await response.json().catch(() => ({}));
54
+ onError(
55
+ errorData.error || "Failed to save mappings. Please try again."
56
+ );
57
+ }
58
+ } catch (error) {
59
+ onError(
60
+ `An error occurred while saving mappings: ${error instanceof Error ? error.message : "Unknown error"}`
61
+ );
62
+ } finally {
63
+ setIsConfirming(false);
64
+ }
65
+ };
66
+ return { confirmMappings, isConfirming };
67
+ }
68
+
69
+ export { useConfirmMappings };
70
+ //# sourceMappingURL=useConfirmMappings.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useConfirmMappings.esm.js","sources":["../../../../../src/components/PagerDutyPage/MappingsTable/hooks/useConfirmMappings.ts"],"sourcesContent":["import { useState } from 'react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { pagerDutyApiRef } from '../../../../api';\nimport { AutoMatchResults } from '../MappingsTable';\nimport { MappingCounts } from '../MappingToast';\nimport { FormattedBackstageEntity } from '@pagerduty/backstage-plugin-common';\nimport { useAccountContext } from '../../AccountContext';\n\ninterface UseConfirmMappingsParams {\n autoMatchResults: AutoMatchResults;\n mappingEntities?: FormattedBackstageEntity[];\n onSuccess: (\n successCount: number,\n totalCount: number,\n counts: MappingCounts,\n ) => void;\n onError: (errorMessage: string) => void;\n}\n\nexport function useConfirmMappings({\n autoMatchResults,\n mappingEntities,\n onSuccess,\n onError,\n}: UseConfirmMappingsParams) {\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const queryClient = useQueryClient();\n const { selectedAccount } = useAccountContext();\n const [isConfirming, setIsConfirming] = useState(false);\n\n const confirmMappings = async () => {\n try {\n setIsConfirming(true);\n const totalCount = Object.keys(autoMatchResults).length;\n const mappingsToCreate = Object.entries(autoMatchResults).map(\n ([entityName, matchData]) => {\n const entity = mappingEntities?.find(\n (e: FormattedBackstageEntity) => e.name === entityName,\n );\n\n const entityRef = entity\n ? `${entity.type}:${entity.namespace}/${entity.name}`.toLowerCase()\n : `component:default/${entityName}`;\n\n return {\n serviceId: matchData.serviceId,\n integrationKey: '',\n entityRef: entityRef,\n account: selectedAccount || '',\n };\n },\n );\n\n const response = await pagerDutyApi.storeBulkServiceMappings(\n mappingsToCreate,\n );\n\n if (response.ok) {\n const result = await response.json();\n const successCount = result.successCount || 0;\n const skippedCount = result.skippedCount || 0;\n const errorCount = result.errorCount || 0;\n\n const counts: MappingCounts = {\n created: successCount,\n skipped: skippedCount,\n errored: errorCount,\n };\n onSuccess(successCount, totalCount, counts);\n queryClient.invalidateQueries({\n queryKey: ['pagerduty', 'enhancedEntityMappings'],\n });\n } else {\n const errorData = await response.json().catch(() => ({}));\n onError(\n errorData.error || 'Failed to save mappings. Please try again.',\n );\n }\n } catch (error) {\n onError(\n `An error occurred while saving mappings: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n } finally {\n setIsConfirming(false);\n }\n };\n\n return { confirmMappings, isConfirming };\n}\n"],"names":[],"mappings":";;;;;;AAoBO,SAAS,kBAAA,CAAmB;AAAA,EACjC,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAA6B;AAC3B,EAAA,MAAM,YAAA,GAAe,OAAO,eAAe,CAAA;AAC3C,EAAA,MAAM,cAAc,cAAA,EAAe;AACnC,EAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,iBAAA,EAAkB;AAC9C,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,KAAK,CAAA;AAEtD,EAAA,MAAM,kBAAkB,YAAY;AAClC,IAAA,IAAI;AACF,MAAA,eAAA,CAAgB,IAAI,CAAA;AACpB,MAAA,MAAM,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,gBAAgB,CAAA,CAAE,MAAA;AACjD,MAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,OAAA,CAAQ,gBAAgB,CAAA,CAAE,GAAA;AAAA,QACxD,CAAC,CAAC,UAAA,EAAY,SAAS,CAAA,KAAM;AAC3B,UAAA,MAAM,SAAS,eAAA,EAAiB,IAAA;AAAA,YAC9B,CAAC,CAAA,KAAgC,CAAA,CAAE,IAAA,KAAS;AAAA,WAC9C;AAEA,UAAA,MAAM,SAAA,GAAY,MAAA,GACd,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,MAAA,CAAO,SAAS,CAAA,CAAA,EAAI,OAAO,IAAI,CAAA,CAAA,CAAG,WAAA,EAAY,GAChE,qBAAqB,UAAU,CAAA,CAAA;AAEnC,UAAA,OAAO;AAAA,YACL,WAAW,SAAA,CAAU,SAAA;AAAA,YACrB,cAAA,EAAgB,EAAA;AAAA,YAChB,SAAA;AAAA,YACA,SAAS,eAAA,IAAmB;AAAA,WAC9B;AAAA,QACF;AAAA,OACF;AAEA,MAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,wBAAA;AAAA,QAClC;AAAA,OACF;AAEA,MAAA,IAAI,SAAS,EAAA,EAAI;AACf,QAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,QAAA,MAAM,YAAA,GAAe,OAAO,YAAA,IAAgB,CAAA;AAC5C,QAAA,MAAM,YAAA,GAAe,OAAO,YAAA,IAAgB,CAAA;AAC5C,QAAA,MAAM,UAAA,GAAa,OAAO,UAAA,IAAc,CAAA;AAExC,QAAA,MAAM,MAAA,GAAwB;AAAA,UAC5B,OAAA,EAAS,YAAA;AAAA,UACT,OAAA,EAAS,YAAA;AAAA,UACT,OAAA,EAAS;AAAA,SACX;AACA,QAAA,SAAA,CAAU,YAAA,EAAc,YAAY,MAAM,CAAA;AAC1C,QAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,UAC5B,QAAA,EAAU,CAAC,WAAA,EAAa,wBAAwB;AAAA,SACjD,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AACxD,QAAA,OAAA;AAAA,UACE,UAAU,KAAA,IAAS;AAAA,SACrB;AAAA,MACF;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA;AAAA,QACE,CAAA,yCAAA,EACE,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,eAC3C,CAAA;AAAA,OACF;AAAA,IACF,CAAA,SAAE;AACA,MAAA,eAAA,CAAgB,KAAK,CAAA;AAAA,IACvB;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,EAAE,iBAAiB,YAAA,EAAa;AACzC;;;;"}