@pagerduty/backstage-plugin 0.18.0 → 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 (46) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/alpha/api.esm.js.map +1 -1
  3. package/dist/api/client.esm.js +91 -2
  4. package/dist/api/client.esm.js.map +1 -1
  5. package/dist/components/PagerDutyPage/AccountContext.esm.js +56 -0
  6. package/dist/components/PagerDutyPage/AccountContext.esm.js.map +1 -0
  7. package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js +197 -0
  8. package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js.map +1 -0
  9. package/dist/components/PagerDutyPage/MappingsDialog.esm.js +242 -0
  10. package/dist/components/PagerDutyPage/MappingsDialog.esm.js.map +1 -0
  11. package/dist/components/PagerDutyPage/MappingsTable/AutoMappingsButton.esm.js +74 -0
  12. package/dist/components/PagerDutyPage/MappingsTable/AutoMappingsButton.esm.js.map +1 -0
  13. package/dist/components/PagerDutyPage/MappingsTable/EmptyTableState.esm.js +26 -0
  14. package/dist/components/PagerDutyPage/MappingsTable/EmptyTableState.esm.js.map +1 -0
  15. package/dist/components/PagerDutyPage/MappingsTable/FilterRow.esm.js +67 -0
  16. package/dist/components/PagerDutyPage/MappingsTable/FilterRow.esm.js.map +1 -0
  17. package/dist/components/PagerDutyPage/MappingsTable/MappingToast.esm.js +69 -0
  18. package/dist/components/PagerDutyPage/MappingsTable/MappingToast.esm.js.map +1 -0
  19. package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js +202 -0
  20. package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js.map +1 -0
  21. package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js +231 -0
  22. package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js.map +1 -0
  23. package/dist/components/PagerDutyPage/MappingsTable/ServiceCell.esm.js +31 -0
  24. package/dist/components/PagerDutyPage/MappingsTable/ServiceCell.esm.js.map +1 -0
  25. package/dist/components/PagerDutyPage/MappingsTable/StatusCell.esm.js +112 -0
  26. package/dist/components/PagerDutyPage/MappingsTable/StatusCell.esm.js.map +1 -0
  27. package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js +50 -0
  28. package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js.map +1 -0
  29. package/dist/components/PagerDutyPage/MappingsTable/hooks/useConfirmMappings.esm.js +70 -0
  30. package/dist/components/PagerDutyPage/MappingsTable/hooks/useConfirmMappings.esm.js.map +1 -0
  31. package/dist/components/PagerDutyPage/ServiceMappingComponent.esm.js +67 -44
  32. package/dist/components/PagerDutyPage/ServiceMappingComponent.esm.js.map +1 -1
  33. package/dist/components/PagerDutyPage/index.esm.js +27 -12
  34. package/dist/components/PagerDutyPage/index.esm.js.map +1 -1
  35. package/dist/components/TriggerButton/index.esm.js +1 -1
  36. package/dist/components/TriggerButton/index.esm.js.map +1 -1
  37. package/dist/hooks/useDebounce.esm.js +13 -0
  38. package/dist/hooks/useDebounce.esm.js.map +1 -0
  39. package/dist/hooks/{index.esm.js → usePagerDutyEntity.esm.js} +1 -1
  40. package/dist/hooks/usePagerDutyEntity.esm.js.map +1 -0
  41. package/dist/index.d.ts +96 -4
  42. package/dist/package.json.esm.js +1 -1
  43. package/package.json +13 -13
  44. package/dist/components/PagerDutyPage/MappingTable.esm.js +0 -282
  45. package/dist/components/PagerDutyPage/MappingTable.esm.js.map +0 -1
  46. package/dist/hooks/index.esm.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @backstage/plugin-pagerduty
2
2
 
3
+ ## 0.19.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ae2a9c3: Refactor the service mappings screen and add an auto-matching functionality to mass map PagerDuty service to Backstage entities
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [ae2a9c3]
12
+ - @pagerduty/backstage-plugin-common@0.3.0
13
+
3
14
  ## 0.18.0
4
15
 
5
16
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"api.esm.js","sources":["../../src/alpha/api.ts"],"sourcesContent":["import { \n ApiBlueprint, \n configApiRef, \n discoveryApiRef, \n fetchApiRef \n} from \"@backstage/frontend-plugin-api\";\nimport { pagerDutyApiRef, PagerDutyClient } from \"../api\";\n\n/** @alpha */\nexport const pagerDutyApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\n api: pagerDutyApiRef,\n deps: {\n configApi: configApiRef,\n fetchApi: fetchApiRef,\n discoveryApi: discoveryApiRef,\n },\n factory({ configApi, fetchApi, discoveryApi }) {\n return PagerDutyClient.fromConfig(configApi, {\n fetchApi,\n discoveryApi,\n });\n },\n }),\n});\n"],"names":[],"mappings":";;;AASO,MAAM,YAAA,GAAe,aAAa,IAAA,CAAK;AAAA,EAC5C,MAAA,EAAQ,kBACN,YAAA,CAAa;AAAA,IACX,GAAA,EAAK,eAAA;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,SAAA,EAAW,YAAA;AAAA,MACX,QAAA,EAAU,WAAA;AAAA,MACV,YAAA,EAAc;AAAA,KAChB;AAAA,IACA,OAAA,CAAQ,EAAE,SAAA,EAAW,QAAA,EAAU,cAAa,EAAG;AAC7C,MAAA,OAAO,eAAA,CAAgB,WAAW,SAAA,EAAW;AAAA,QAC3C,QAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AAAA,GACD;AACL,CAAC;;;;"}
1
+ {"version":3,"file":"api.esm.js","sources":["../../src/alpha/api.ts"],"sourcesContent":["import {\n ApiBlueprint,\n configApiRef,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { pagerDutyApiRef, PagerDutyClient } from '../api';\n\n/** @alpha */\nexport const pagerDutyApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\n api: pagerDutyApiRef,\n deps: {\n configApi: configApiRef,\n fetchApi: fetchApiRef,\n discoveryApi: discoveryApiRef,\n },\n factory({ configApi, fetchApi, discoveryApi }) {\n return PagerDutyClient.fromConfig(configApi, {\n fetchApi,\n discoveryApi,\n });\n },\n }),\n});\n"],"names":[],"mappings":";;;AASO,MAAM,YAAA,GAAe,aAAa,IAAA,CAAK;AAAA,EAC5C,MAAA,EAAQ,kBACN,YAAA,CAAa;AAAA,IACX,GAAA,EAAK,eAAA;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,SAAA,EAAW,YAAA;AAAA,MACX,QAAA,EAAU,WAAA;AAAA,MACV,YAAA,EAAc;AAAA,KAChB;AAAA,IACA,OAAA,CAAQ,EAAE,SAAA,EAAW,QAAA,EAAU,cAAa,EAAG;AAC7C,MAAA,OAAO,eAAA,CAAgB,WAAW,SAAA,EAAW;AAAA,QAC3C,QAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AAAA,GACD;AACL,CAAC;;;;"}
@@ -72,10 +72,56 @@ class PagerDutyClient {
72
72
  )}/settings`;
73
73
  return this.request(url, options);
74
74
  }
75
- async getEntityMappings() {
75
+ async getEntityMappingsWithPagination(options) {
76
76
  const url = `${await this.config.discoveryApi.getBaseUrl(
77
77
  "pagerduty"
78
- )}/mapping/entity`;
78
+ )}/mapping/entities`;
79
+ const body = JSON.stringify({
80
+ offset: options.offset,
81
+ limit: options.limit,
82
+ filters: options.filters || {},
83
+ sort: options.sort,
84
+ account: options.account
85
+ });
86
+ const requestOptions = {
87
+ method: "POST",
88
+ headers: {
89
+ "Content-Type": "application/json; charset=UTF-8",
90
+ Accept: "application/json, text/plain, */*"
91
+ },
92
+ body
93
+ };
94
+ const response = await this.request(url, requestOptions);
95
+ return response.json();
96
+ }
97
+ async getAllServices() {
98
+ const url = `${await this.config.discoveryApi.getBaseUrl(
99
+ "pagerduty"
100
+ )}/all-pd-services`;
101
+ return await this.findByUrl(url);
102
+ }
103
+ async getAllTeams(account) {
104
+ const baseUrl = await this.config.discoveryApi.getBaseUrl("pagerduty");
105
+ const url = account ? `${baseUrl}/teams?account=${encodeURIComponent(account)}` : `${baseUrl}/teams`;
106
+ return await this.findByUrl(url);
107
+ }
108
+ async getFilteredServices(teamIds, query, limit, account) {
109
+ const baseUrl = await this.config.discoveryApi.getBaseUrl("pagerduty");
110
+ const params = new URLSearchParams();
111
+ if (teamIds && teamIds.length > 0) {
112
+ params.append("team_id", teamIds[0]);
113
+ }
114
+ if (query && query.trim() !== "") {
115
+ params.append("query", query.trim());
116
+ }
117
+ if (limit) {
118
+ params.append("limit", limit.toString());
119
+ }
120
+ if (account) {
121
+ params.append("account", account);
122
+ }
123
+ const queryString = params.toString();
124
+ const url = queryString ? `${baseUrl}/services?${queryString}` : `${baseUrl}/services`;
79
125
  return await this.findByUrl(url);
80
126
  }
81
127
  async storeServiceMapping(serviceId, integrationKey, backstageEntityRef, account) {
@@ -109,6 +155,21 @@ class PagerDutyClient {
109
155
  )}/mapping/entity/${kind}/${namespace}/${name}`;
110
156
  return await this.findByUrl(url);
111
157
  }
158
+ async storeBulkServiceMappings(mappings) {
159
+ const body = JSON.stringify({ mappings });
160
+ const options = {
161
+ method: "POST",
162
+ headers: {
163
+ "Content-Type": "application/json; charset=UTF-8",
164
+ Accept: "application/json, text/plain, */*"
165
+ },
166
+ body
167
+ };
168
+ const url = `${await this.config.discoveryApi.getBaseUrl(
169
+ "pagerduty"
170
+ )}/mapping/entities/bulk`;
171
+ return this.request(url, options);
172
+ }
112
173
  async removeServiceMapping(entityRef) {
113
174
  const { mapping } = await this.getEntityMapping(entityRef);
114
175
  await this.storeServiceMapping(
@@ -207,6 +268,34 @@ class PagerDutyClient {
207
268
  const url = this.config.eventsBaseUrl ?? "https://events.pagerduty.com/v2";
208
269
  return this.request(`${url}/enqueue`, options);
209
270
  }
271
+ async autoMatchEntityMappings(options) {
272
+ const url = `${await this.config.discoveryApi.getBaseUrl(
273
+ "pagerduty"
274
+ )}/mapping/entity/auto-match`;
275
+ const body = JSON.stringify({
276
+ team: options.team === "all" ? void 0 : options.team,
277
+ threshold: options.threshold,
278
+ bestOnly: true,
279
+ account: options.account
280
+ });
281
+ const requestOptions = {
282
+ method: "POST",
283
+ headers: {
284
+ "Content-Type": "application/json; charset=UTF-8",
285
+ Accept: "application/json, text/plain, */*"
286
+ },
287
+ body
288
+ };
289
+ const response = await this.request(url, requestOptions);
290
+ return response.json();
291
+ }
292
+ async getAccounts() {
293
+ const url = `${await this.config.discoveryApi.getBaseUrl(
294
+ "pagerduty"
295
+ )}/accounts`;
296
+ const response = await this.findByUrl(url);
297
+ return response.accounts;
298
+ }
210
299
  async findByUrl(url) {
211
300
  const options = {
212
301
  method: "GET",
@@ -1 +1 @@
1
- {"version":3,"file":"client.esm.js","sources":["../../src/api/client.ts"],"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\nimport {\n PagerDutyApi,\n PagerDutyTriggerAlarmRequest,\n PagerDutyClientApiDependencies,\n PagerDutyClientApiConfig,\n RequestOptions,\n} from './types';\nimport {\n PagerDutyChangeEventsResponse,\n PagerDutyOnCallUsersResponse,\n PagerDutyUser,\n PagerDutyServiceResponse,\n PagerDutyIncidentsResponse,\n PagerDutyServiceStandardsResponse,\n PagerDutyServiceMetricsResponse,\n PagerDutyEntityMappingsResponse,\n PagerDutySetting,\n} from '@pagerduty/backstage-plugin-common';\nimport { createApiRef, ConfigApi } from '@backstage/core-plugin-api';\nimport { NotFoundError } from '@backstage/errors';\nimport { Entity } from '@backstage/catalog-model';\nimport { getPagerDutyEntity } from '../components/pagerDutyEntity';\nimport { PagerDutyEntity } from '../types';\n\n/** @public */\nexport class UnauthorizedError extends Error {}\n\n/** @public */\nexport class ForbiddenError extends Error {}\n\n/** @public */\nexport const pagerDutyApiRef = createApiRef<PagerDutyApi>({\n id: 'plugin.pagerduty.api',\n});\n\n/** @public */\nexport class PagerDutyClient implements PagerDutyApi {\n static fromConfig(\n configApi: ConfigApi,\n dependencies: PagerDutyClientApiDependencies,\n ) {\n const { discoveryApi, fetchApi } = dependencies;\n\n const eventsBaseUrl: string =\n configApi.getOptionalString('pagerDuty.eventsBaseUrl') ??\n 'https://events.pagerduty.com/v2';\n\n return new PagerDutyClient({\n eventsBaseUrl,\n discoveryApi,\n fetchApi,\n });\n }\n\n constructor(private readonly config: PagerDutyClientApiConfig) {}\n\n async getServiceByPagerDutyEntity(\n pagerDutyEntity: PagerDutyEntity,\n ): Promise<PagerDutyServiceResponse> {\n const { integrationKey, serviceId, account } = pagerDutyEntity;\n\n let response: PagerDutyServiceResponse;\n let url: string;\n\n if (integrationKey) {\n url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services?integration_key=${integrationKey}`;\n\n if (account) {\n url = `${url}&account=${account}`;\n }\n const serviceResponse = await this.findByUrl<PagerDutyServiceResponse>(\n url,\n );\n\n if (serviceResponse.service === undefined) throw new NotFoundError();\n\n response = serviceResponse;\n } else if (serviceId) {\n url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}`;\n\n if (account) {\n url = `${url}?account=${account}`;\n }\n\n response = await this.findByUrl<PagerDutyServiceResponse>(url);\n } else {\n throw new NotFoundError();\n }\n\n return response;\n }\n\n async getSetting(id: string): Promise<PagerDutySetting> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/settings/${id}`;\n\n return await this.findByUrl<PagerDutySetting>(url);\n }\n\n async storeSettings(settings: PagerDutySetting[]): Promise<Response> {\n const body = JSON.stringify(settings);\n\n const options = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/settings`;\n\n return this.request(url, options);\n }\n\n async getEntityMappings(): Promise<PagerDutyEntityMappingsResponse> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entity`;\n\n return await this.findByUrl<PagerDutyEntityMappingsResponse>(url);\n }\n\n async storeServiceMapping(\n serviceId: string,\n integrationKey: string,\n backstageEntityRef: string,\n account: string,\n ): Promise<Response> {\n const body = JSON.stringify({\n entityRef: backstageEntityRef,\n serviceId: serviceId,\n integrationKey: integrationKey,\n account: account,\n });\n\n const options = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entity`;\n\n return this.request(url, options);\n }\n\n async getEntityMapping(entityRef: string): Promise<{\n mapping: {\n serviceId: string;\n integrationKey: string;\n entityRef: string;\n account: string;\n };\n }> {\n const match = entityRef.match(/^([^:]+):([^/]+)\\/(.+)$/);\n if (!match) {\n throw new Error(`Invalid entity reference: ${entityRef}`);\n }\n\n const [, kind, namespace, name] = match;\n\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entity/${kind}/${namespace}/${name}`;\n\n return await this.findByUrl(url);\n }\n\n async removeServiceMapping(entityRef: string): Promise<boolean> {\n // First, get the current mapping to retrieve serviceId and integrationKey\n const { mapping } = await this.getEntityMapping(entityRef);\n\n // Then call storeServiceMapping with empty entityRef to unmap\n // This is the SAME approach used in MappingTable.tsx line 200-204\n await this.storeServiceMapping(\n mapping.serviceId,\n mapping.integrationKey,\n '', // Empty string = unmap (same as \"None\" option in admin page)\n mapping.account,\n );\n return true;\n }\n\n async getServiceByEntity(entity: Entity): Promise<PagerDutyServiceResponse> {\n return await this.getServiceByPagerDutyEntity(getPagerDutyEntity(entity));\n }\n\n async getServiceById(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyServiceResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyServiceResponse>(url);\n }\n\n async getIncidentsByServiceId(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyIncidentsResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}/incidents`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyIncidentsResponse>(url);\n }\n\n async getChangeEventsByServiceId(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyChangeEventsResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}/change-events`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyChangeEventsResponse>(url);\n }\n\n async getServiceStandardsByServiceId(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyServiceStandardsResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}/standards`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyServiceStandardsResponse>(url);\n }\n\n async getServiceMetricsByServiceId(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyServiceMetricsResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}/metrics`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyServiceMetricsResponse>(url);\n }\n\n async getOnCallByPolicyId(\n policyId: string,\n account?: string,\n ): Promise<PagerDutyUser[]> {\n const params = `escalation_policy_ids[]=${policyId}`;\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/oncall-users?${params}`;\n\n if (account) {\n url = url.concat(`&account=${account}`);\n }\n\n const response: PagerDutyOnCallUsersResponse =\n await this.findByUrl<PagerDutyOnCallUsersResponse>(url);\n return response.users;\n }\n\n triggerAlarm(request: PagerDutyTriggerAlarmRequest): Promise<Response> {\n const { integrationKey, source, description, userName } = request;\n\n const body = JSON.stringify({\n event_action: 'trigger',\n routing_key: integrationKey,\n client: 'Backstage',\n client_url: source,\n payload: {\n summary: description,\n source: source,\n severity: 'error',\n class: 'manual trigger',\n custom_details: {\n user: userName,\n },\n },\n });\n\n const options = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n const url = this.config.eventsBaseUrl ?? 'https://events.pagerduty.com/v2';\n\n return this.request(`${url}/enqueue`, options);\n }\n\n private async findByUrl<T>(url: string): Promise<T> {\n const options = {\n method: 'GET',\n headers: {\n Accept: 'application/vnd.pagerduty+json;version=2',\n 'Content-Type': 'application/json',\n },\n };\n const response = await this.request(url, options);\n return response.json();\n }\n\n private async request(\n url: string,\n options: RequestOptions,\n ): Promise<Response> {\n const response = await this.config.fetchApi.fetch(url, options);\n if (response.status === 401) {\n throw new UnauthorizedError(\n \"Unauthorized: You don't have access to this resource\",\n );\n }\n\n if (response.status === 403) {\n throw new ForbiddenError(\n 'Forbidden: You are not allowed to perform this action',\n );\n }\n\n if (response.status === 404) {\n throw new NotFoundError('Not Found: Resource not found');\n }\n\n if (!response.ok) {\n const payload = await response.json();\n const errors = payload.errors.map((error: string) => error).join(' ');\n const message = `Request failed with ${response.status}, ${errors}`;\n throw new Error(message);\n }\n return response;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.esm.js","sources":["../../src/api/client.ts"],"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\nimport {\n PagerDutyApi,\n PagerDutyTriggerAlarmRequest,\n PagerDutyClientApiDependencies,\n PagerDutyClientApiConfig,\n RequestOptions,\n} from './types';\nimport {\n PagerDutyChangeEventsResponse,\n PagerDutyOnCallUsersResponse,\n PagerDutyUser,\n PagerDutyServiceResponse,\n PagerDutyIncidentsResponse,\n PagerDutyServiceStandardsResponse,\n PagerDutyServiceMetricsResponse,\n PagerDutyEnhancedEntityMappingsResponse,\n PagerDutySetting,\n PagerDutyService,\n AutoMatchEntityMappingsResponse,\n PagerDutyTeam,\n} from '@pagerduty/backstage-plugin-common';\nimport { createApiRef, ConfigApi } from '@backstage/core-plugin-api';\nimport { NotFoundError } from '@backstage/errors';\nimport { Entity } from '@backstage/catalog-model';\nimport { getPagerDutyEntity } from '../components/pagerDutyEntity';\nimport { PagerDutyEntity } from '../types';\n\n/** @public */\nexport class UnauthorizedError extends Error {}\n\n/** @public */\nexport class ForbiddenError extends Error {}\n\n/** @public */\nexport const pagerDutyApiRef = createApiRef<PagerDutyApi>({\n id: 'plugin.pagerduty.api',\n});\n\n/** @public */\nexport class PagerDutyClient implements PagerDutyApi {\n static fromConfig(\n configApi: ConfigApi,\n dependencies: PagerDutyClientApiDependencies,\n ) {\n const { discoveryApi, fetchApi } = dependencies;\n\n const eventsBaseUrl: string =\n configApi.getOptionalString('pagerDuty.eventsBaseUrl') ??\n 'https://events.pagerduty.com/v2';\n\n return new PagerDutyClient({\n eventsBaseUrl,\n discoveryApi,\n fetchApi,\n });\n }\n\n constructor(private readonly config: PagerDutyClientApiConfig) {}\n\n async getServiceByPagerDutyEntity(\n pagerDutyEntity: PagerDutyEntity,\n ): Promise<PagerDutyServiceResponse> {\n const { integrationKey, serviceId, account } = pagerDutyEntity;\n\n let response: PagerDutyServiceResponse;\n let url: string;\n\n if (integrationKey) {\n url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services?integration_key=${integrationKey}`;\n\n if (account) {\n url = `${url}&account=${account}`;\n }\n const serviceResponse = await this.findByUrl<PagerDutyServiceResponse>(\n url,\n );\n\n if (serviceResponse.service === undefined) throw new NotFoundError();\n\n response = serviceResponse;\n } else if (serviceId) {\n url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}`;\n\n if (account) {\n url = `${url}?account=${account}`;\n }\n\n response = await this.findByUrl<PagerDutyServiceResponse>(url);\n } else {\n throw new NotFoundError();\n }\n\n return response;\n }\n\n async getSetting(id: string): Promise<PagerDutySetting> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/settings/${id}`;\n\n return await this.findByUrl<PagerDutySetting>(url);\n }\n\n async storeSettings(settings: PagerDutySetting[]): Promise<Response> {\n const body = JSON.stringify(settings);\n\n const options = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/settings`;\n\n return this.request(url, options);\n }\n\n async getEntityMappingsWithPagination(options: {\n offset: number;\n limit: number;\n filters?: {\n name?: string;\n serviceName?: string;\n status?: string;\n teamName?: string;\n };\n sort?: { column: string; direction: 'ascending' | 'descending' };\n account?: string;\n }): Promise<PagerDutyEnhancedEntityMappingsResponse> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entities`;\n\n const body = JSON.stringify({\n offset: options.offset,\n limit: options.limit,\n filters: options.filters || {},\n sort: options.sort,\n account: options.account,\n });\n\n const requestOptions = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n const response = await this.request(url, requestOptions);\n return response.json();\n }\n\n async getAllServices(): Promise<PagerDutyService[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/all-pd-services`;\n\n return await this.findByUrl<PagerDutyService[]>(url);\n }\n\n async getAllTeams(account?: string): Promise<PagerDutyTeam[]> {\n const baseUrl = await this.config.discoveryApi.getBaseUrl('pagerduty');\n const url = account\n ? `${baseUrl}/teams?account=${encodeURIComponent(account)}`\n : `${baseUrl}/teams`;\n\n return await this.findByUrl<PagerDutyTeam[]>(url);\n }\n\n async getFilteredServices(\n teamIds?: string[],\n query?: string,\n limit?: number,\n account?: string,\n ): Promise<PagerDutyService[]> {\n const baseUrl = await this.config.discoveryApi.getBaseUrl('pagerduty');\n const params = new URLSearchParams();\n\n if (teamIds && teamIds.length > 0) {\n params.append('team_id', teamIds[0]);\n }\n\n if (query && query.trim() !== '') {\n params.append('query', query.trim());\n }\n\n if (limit) {\n params.append('limit', limit.toString());\n }\n\n if (account) {\n params.append('account', account);\n }\n\n const queryString = params.toString();\n const url = queryString\n ? `${baseUrl}/services?${queryString}`\n : `${baseUrl}/services`;\n\n return await this.findByUrl<PagerDutyService[]>(url);\n }\n\n async storeServiceMapping(\n serviceId: string,\n integrationKey: string,\n backstageEntityRef: string,\n account: string,\n ): Promise<Response> {\n const body = JSON.stringify({\n entityRef: backstageEntityRef,\n serviceId: serviceId,\n integrationKey: integrationKey,\n account: account,\n });\n\n const options = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entity`;\n\n return this.request(url, options);\n }\n\n\n async getEntityMapping(entityRef: string): Promise<{\n mapping: {serviceId: string;\n integrationKey: string;\n entityRef: string;\n account: string;\n };\n }> {\n const match = entityRef.match(/^([^:]+):([^/]+)\\/(.+)$/);\n if (!match) {\n throw new Error(`Invalid entity reference: ${entityRef}`);\n }\n\n const [, kind, namespace, name] = match;\n\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entity/${kind}/${namespace}/${name}`;\n\n return await this.findByUrl(url);\n }\n\n async storeBulkServiceMappings(\n mappings: Array<{\n serviceId: string;\n integrationKey: string;\n entityRef: string;\n account: string;\n }>,\n ): Promise<Response> {\n const body = JSON.stringify({ mappings });\n\n const options = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entities/bulk`;\n\n return this.request(url, options);\n }\n\n async removeServiceMapping(entityRef: string): Promise<boolean> {\n // First, get the current mapping to retrieve serviceId and integrationKey\n const { mapping } = await this.getEntityMapping(entityRef);\n\n // Then call storeServiceMapping with empty entityRef to unmap\n // This is the SAME approach used in MappingTable.tsx line 200-204\n await this.storeServiceMapping(\n mapping.serviceId,\n mapping.integrationKey,\n '', // Empty string = unmap (same as \"None\" option in admin page)\n mapping.account,\n );\n return true;\n }\n\n async getServiceByEntity(entity: Entity): Promise<PagerDutyServiceResponse> {\n return await this.getServiceByPagerDutyEntity(getPagerDutyEntity(entity));\n }\n\n async getServiceById(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyServiceResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyServiceResponse>(url);\n }\n\n async getIncidentsByServiceId(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyIncidentsResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}/incidents`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyIncidentsResponse>(url);\n }\n\n async getChangeEventsByServiceId(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyChangeEventsResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}/change-events`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyChangeEventsResponse>(url);\n }\n\n async getServiceStandardsByServiceId(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyServiceStandardsResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}/standards`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyServiceStandardsResponse>(url);\n }\n\n async getServiceMetricsByServiceId(\n serviceId: string,\n account?: string,\n ): Promise<PagerDutyServiceMetricsResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/services/${serviceId}/metrics`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<PagerDutyServiceMetricsResponse>(url);\n }\n\n async getOnCallByPolicyId(\n policyId: string,\n account?: string,\n ): Promise<PagerDutyUser[]> {\n const params = `escalation_policy_ids[]=${policyId}`;\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/oncall-users?${params}`;\n\n if (account) {\n url = url.concat(`&account=${account}`);\n }\n\n const response: PagerDutyOnCallUsersResponse =\n await this.findByUrl<PagerDutyOnCallUsersResponse>(url);\n return response.users;\n }\n\n triggerAlarm(request: PagerDutyTriggerAlarmRequest): Promise<Response> {\n const { integrationKey, source, description, userName } = request;\n\n const body = JSON.stringify({\n event_action: 'trigger',\n routing_key: integrationKey,\n client: 'Backstage',\n client_url: source,\n payload: {\n summary: description,\n source: source,\n severity: 'error',\n class: 'manual trigger',\n custom_details: {\n user: userName,\n },\n },\n });\n\n const options = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n const url = this.config.eventsBaseUrl ?? 'https://events.pagerduty.com/v2';\n\n return this.request(`${url}/enqueue`, options);\n }\n\n async autoMatchEntityMappings(options: {\n team?: string;\n threshold: number;\n account?: string;\n }): Promise<AutoMatchEntityMappingsResponse> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entity/auto-match`;\n\n const body = JSON.stringify({\n team: options.team === 'all' ? undefined : options.team,\n threshold: options.threshold,\n bestOnly: true,\n account: options.account,\n });\n\n const requestOptions = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n const response = await this.request(url, requestOptions);\n return response.json();\n }\n\n async getAccounts(): Promise<Array<{ id: string; isDefault: boolean }>> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/accounts`;\n\n const response = await this.findByUrl<{\n accounts: Array<{ id: string; isDefault: boolean }>;\n }>(url);\n return response.accounts;\n }\n\n private async findByUrl<T>(url: string): Promise<T> {\n const options = {\n method: 'GET',\n headers: {\n Accept: 'application/vnd.pagerduty+json;version=2',\n 'Content-Type': 'application/json',\n },\n };\n const response = await this.request(url, options);\n return response.json();\n }\n\n private async request(\n url: string,\n options: RequestOptions,\n ): Promise<Response> {\n const response = await this.config.fetchApi.fetch(url, options);\n if (response.status === 401) {\n throw new UnauthorizedError(\n \"Unauthorized: You don't have access to this resource\",\n );\n }\n\n if (response.status === 403) {\n throw new ForbiddenError(\n 'Forbidden: You are not allowed to perform this action',\n );\n }\n\n if (response.status === 404) {\n throw new NotFoundError('Not Found: Resource not found');\n }\n\n if (!response.ok) {\n const payload = await response.json();\n const errors = payload.errors.map((error: string) => error).join(' ');\n const message = `Request failed with ${response.status}, ${errors}`;\n throw new Error(message);\n }\n return response;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState, useMemo, createContext, useContext } from 'react';
3
+ import { useQuery } from '@tanstack/react-query';
4
+ import { useApi } from '@backstage/core-plugin-api';
5
+ import { pagerDutyApiRef } from '../../api/client.esm.js';
6
+
7
+ const AccountContext = createContext(
8
+ void 0
9
+ );
10
+ const useAccountContext = () => {
11
+ const context = useContext(AccountContext);
12
+ if (!context) {
13
+ throw new Error("useAccountContext must be used within an AccountProvider");
14
+ }
15
+ return context;
16
+ };
17
+ const AccountProvider = ({ children }) => {
18
+ const pagerDutyApi = useApi(pagerDutyApiRef);
19
+ const [selectedAccount, setSelectedAccount] = useState("");
20
+ const { data: accountsData, isLoading } = useQuery({
21
+ queryKey: ["pagerduty", "accounts"],
22
+ queryFn: () => pagerDutyApi.getAccounts()
23
+ });
24
+ const accounts = useMemo(() => {
25
+ if (accountsData && accountsData.length > 0) {
26
+ return accountsData.map((account) => ({
27
+ label: account.id,
28
+ value: account.id
29
+ }));
30
+ }
31
+ return [];
32
+ }, [accountsData]);
33
+ useMemo(() => {
34
+ if (accountsData && accountsData.length > 0 && !selectedAccount) {
35
+ const defaultAccount = accountsData.find((account) => account.isDefault);
36
+ if (defaultAccount) {
37
+ setSelectedAccount(defaultAccount.id);
38
+ } else {
39
+ setSelectedAccount(accountsData[0].id);
40
+ }
41
+ }
42
+ }, [accountsData, selectedAccount]);
43
+ const value = useMemo(
44
+ () => ({
45
+ selectedAccount,
46
+ setSelectedAccount,
47
+ accounts,
48
+ isLoading
49
+ }),
50
+ [selectedAccount, accounts, isLoading]
51
+ );
52
+ return /* @__PURE__ */ jsx(AccountContext.Provider, { value, children });
53
+ };
54
+
55
+ export { AccountProvider, useAccountContext };
56
+ //# sourceMappingURL=AccountContext.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccountContext.esm.js","sources":["../../../src/components/PagerDutyPage/AccountContext.tsx"],"sourcesContent":["import { createContext, useContext, useState, useMemo } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { pagerDutyApiRef } from '../../api';\n\ninterface AccountContextValue {\n selectedAccount: string;\n setSelectedAccount: (account: string) => void;\n accounts: Array<{ label: string; value: string }>;\n isLoading: boolean;\n}\n\nconst AccountContext = createContext<AccountContextValue | undefined>(\n undefined,\n);\n\nexport const useAccountContext = () => {\n const context = useContext(AccountContext);\n if (!context) {\n throw new Error('useAccountContext must be used within an AccountProvider');\n }\n return context;\n};\n\ninterface AccountProviderProps {\n children: React.ReactNode;\n}\n\nexport const AccountProvider = ({ children }: AccountProviderProps) => {\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const [selectedAccount, setSelectedAccount] = useState<string>('');\n\n const { data: accountsData, isLoading } = useQuery({\n queryKey: ['pagerduty', 'accounts'],\n queryFn: () => pagerDutyApi.getAccounts(),\n });\n\n const accounts = useMemo(() => {\n if (accountsData && accountsData.length > 0) {\n return accountsData.map(account => ({\n label: account.id,\n value: account.id,\n }));\n }\n return [];\n }, [accountsData]);\n\n useMemo(() => {\n if (accountsData && accountsData.length > 0 && !selectedAccount) {\n const defaultAccount = accountsData.find(account => account.isDefault);\n if (defaultAccount) {\n setSelectedAccount(defaultAccount.id);\n } else {\n setSelectedAccount(accountsData[0].id);\n }\n }\n }, [accountsData, selectedAccount]);\n\n const value = useMemo(\n () => ({\n selectedAccount,\n setSelectedAccount,\n accounts,\n isLoading,\n }),\n [selectedAccount, accounts, isLoading],\n );\n\n return (\n <AccountContext.Provider value={value}>{children}</AccountContext.Provider>\n );\n};\n"],"names":[],"mappings":";;;;;;AAYA,MAAM,cAAA,GAAiB,aAAA;AAAA,EACrB;AACF,CAAA;AAEO,MAAM,oBAAoB,MAAM;AACrC,EAAA,MAAM,OAAA,GAAU,WAAW,cAAc,CAAA;AACzC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,0DAA0D,CAAA;AAAA,EAC5E;AACA,EAAA,OAAO,OAAA;AACT;AAMO,MAAM,eAAA,GAAkB,CAAC,EAAE,QAAA,EAAS,KAA4B;AACrE,EAAA,MAAM,YAAA,GAAe,OAAO,eAAe,CAAA;AAC3C,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAI,SAAiB,EAAE,CAAA;AAEjE,EAAA,MAAM,EAAE,IAAA,EAAM,YAAA,EAAc,SAAA,KAAc,QAAA,CAAS;AAAA,IACjD,QAAA,EAAU,CAAC,WAAA,EAAa,UAAU,CAAA;AAAA,IAClC,OAAA,EAAS,MAAM,YAAA,CAAa,WAAA;AAAY,GACzC,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,QAAQ,MAAM;AAC7B,IAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG;AAC3C,MAAA,OAAO,YAAA,CAAa,IAAI,CAAA,OAAA,MAAY;AAAA,QAClC,OAAO,OAAA,CAAQ,EAAA;AAAA,QACf,OAAO,OAAA,CAAQ;AAAA,OACjB,CAAE,CAAA;AAAA,IACJ;AACA,IAAA,OAAO,EAAC;AAAA,EACV,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,OAAA,CAAQ,MAAM;AACZ,IAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,MAAA,GAAS,CAAA,IAAK,CAAC,eAAA,EAAiB;AAC/D,MAAA,MAAM,cAAA,GAAiB,YAAA,CAAa,IAAA,CAAK,CAAA,OAAA,KAAW,QAAQ,SAAS,CAAA;AACrE,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,kBAAA,CAAmB,eAAe,EAAE,CAAA;AAAA,MACtC,CAAA,MAAO;AACL,QAAA,kBAAA,CAAmB,YAAA,CAAa,CAAC,CAAA,CAAE,EAAE,CAAA;AAAA,MACvC;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,YAAA,EAAc,eAAe,CAAC,CAAA;AAElC,EAAA,MAAM,KAAA,GAAQ,OAAA;AAAA,IACZ,OAAO;AAAA,MACL,eAAA;AAAA,MACA,kBAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA,CAAC,eAAA,EAAiB,QAAA,EAAU,SAAS;AAAA,GACvC;AAEA,EAAA,uBACE,GAAA,CAAC,cAAA,CAAe,QAAA,EAAf,EAAwB,OAAe,QAAA,EAAS,CAAA;AAErD;;;;"}
@@ -0,0 +1,197 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Dialog, DialogHeader, DialogBody, Box, Flex, Text, Select, DialogFooter, Button } from '@backstage/ui';
3
+ import { useState } from 'react';
4
+ import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
5
+ import { useApi } from '@backstage/core-plugin-api';
6
+ import { catalogApiRef } from '@backstage/plugin-catalog-react';
7
+ import { pagerDutyApiRef } from '../../api/client.esm.js';
8
+ import { Warning } from '@mui/icons-material';
9
+ import { useAccountContext } from './AccountContext.esm.js';
10
+
11
+ function AutomaticMappingsDialog({
12
+ isOpen,
13
+ setIsOpen,
14
+ onAutoMatchComplete
15
+ }) {
16
+ const catalogApi = useApi(catalogApiRef);
17
+ const pagerDutyApi = useApi(pagerDutyApiRef);
18
+ const queryClient = useQueryClient();
19
+ const { selectedAccount } = useAccountContext();
20
+ const [selectedTeam, setSelectedTeam] = useState("all");
21
+ const [selectedThreshold, setSelectedThreshold] = useState("");
22
+ const { data: groups, isLoading: isGroupsLoading } = useQuery({
23
+ queryKey: ["catalog", "groups"],
24
+ queryFn: async () => {
25
+ const response = await catalogApi.getEntities({
26
+ filter: {
27
+ kind: "Group"
28
+ }
29
+ });
30
+ return response.items;
31
+ },
32
+ enabled: isOpen
33
+ });
34
+ const { mutateAsync: autoMatch, isPending: isAutoMatching } = useMutation({
35
+ mutationFn: async (params) => pagerDutyApi.autoMatchEntityMappings(params),
36
+ onSuccess: (data) => {
37
+ const matchMap = {};
38
+ const matches = data?.matches;
39
+ if (Array.isArray(matches)) {
40
+ matches.forEach((match) => {
41
+ const entityName = match.backstageComponent?.name;
42
+ const score = match.score;
43
+ const serviceId = match.pagerDutyService?.serviceId;
44
+ const serviceName = match.pagerDutyService?.name;
45
+ const account = match.pagerDutyService?.account || "";
46
+ const entityRef = match.backstageComponent?.entityRef;
47
+ const owner = match.backstageComponent?.owner;
48
+ if (entityName && score !== void 0 && serviceId) {
49
+ matchMap[entityName] = {
50
+ score,
51
+ serviceId,
52
+ account,
53
+ serviceName,
54
+ entity: {
55
+ name: entityName,
56
+ entityRef: entityRef || "",
57
+ owner: owner || ""
58
+ }
59
+ };
60
+ }
61
+ });
62
+ }
63
+ onAutoMatchComplete(matchMap);
64
+ queryClient.invalidateQueries({
65
+ queryKey: ["pagerduty", "enhancedEntityMappings"]
66
+ });
67
+ setIsOpen(false);
68
+ }
69
+ });
70
+ const teamOptions = [
71
+ { value: "all", label: "All Teams" },
72
+ ...groups?.map((group) => ({
73
+ value: group.metadata.name,
74
+ label: group.metadata.name
75
+ })) || []
76
+ ];
77
+ const thresholdOptions = [
78
+ { value: "100", label: "Exact Match (100%)" },
79
+ { value: "90", label: "High Confidence (>= 90%)" },
80
+ { value: "80", label: "Medium Confidence (>= 80%)" }
81
+ ];
82
+ const handleBegin = async () => {
83
+ if (!selectedThreshold) return;
84
+ await autoMatch({
85
+ team: selectedTeam,
86
+ threshold: parseInt(selectedThreshold, 10),
87
+ account: selectedAccount
88
+ });
89
+ };
90
+ return /* @__PURE__ */ jsxs(Dialog, { isOpen, onOpenChange: setIsOpen, style: { width: "460px" }, children: [
91
+ /* @__PURE__ */ jsx(DialogHeader, { children: "Service Auto-Mapping" }),
92
+ /* @__PURE__ */ jsx(DialogBody, { children: /* @__PURE__ */ jsxs(Box, { p: "0 24px 8px 24px", children: [
93
+ /* @__PURE__ */ jsx(
94
+ Box,
95
+ {
96
+ style: {
97
+ backgroundColor: "#FEF3CD",
98
+ border: "1px solid #F4C430",
99
+ borderRadius: "8px",
100
+ padding: "16px",
101
+ marginBottom: "8px"
102
+ },
103
+ children: /* @__PURE__ */ jsxs(Flex, { gap: "2", align: "start", direction: "column", children: [
104
+ /* @__PURE__ */ jsxs(Flex, { gap: "1", children: [
105
+ /* @__PURE__ */ jsx(
106
+ Warning,
107
+ {
108
+ style: {
109
+ color: "#F4C430",
110
+ fontSize: "var(--bui-font-size-3)"
111
+ }
112
+ }
113
+ ),
114
+ /* @__PURE__ */ jsx(
115
+ Text,
116
+ {
117
+ variant: "body-medium",
118
+ weight: "bold",
119
+ style: { color: "#D97706", marginLeft: "4px" },
120
+ children: "Disclaimer:"
121
+ }
122
+ )
123
+ ] }),
124
+ /* @__PURE__ */ jsx(Text, { variant: "body-medium", style: { color: "#6B7280" }, children: "Service auto-mapping uses service and team names to match components. Please review and confirm any mappings with confidence scores below 100% before syncing." })
125
+ ] })
126
+ }
127
+ ),
128
+ /* @__PURE__ */ jsx(
129
+ Text,
130
+ {
131
+ variant: "body-medium",
132
+ style: {
133
+ marginBottom: "16px",
134
+ display: "block",
135
+ lineHeight: "1.6"
136
+ },
137
+ children: "This feature will map unmapped Backstage components to PagerDuty services and provide a confidence score for each match."
138
+ }
139
+ ),
140
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "5", children: [
141
+ /* @__PURE__ */ jsx(
142
+ Select,
143
+ {
144
+ name: "team",
145
+ isDisabled: isGroupsLoading || isAutoMatching,
146
+ label: "Backstage Team (optional)",
147
+ placeholder: isGroupsLoading ? "Loading teams..." : "Select a team",
148
+ options: teamOptions,
149
+ value: selectedTeam,
150
+ onChange: (value) => setSelectedTeam(value)
151
+ }
152
+ ),
153
+ /* @__PURE__ */ jsxs(Box, { children: [
154
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { marginBottom: "8px" }, gap: "0", children: [
155
+ /* @__PURE__ */ jsx(Text, { variant: "body-small", children: "Confidence Threshold *" }),
156
+ /* @__PURE__ */ jsx(
157
+ Text,
158
+ {
159
+ variant: "body-x-small",
160
+ style: {
161
+ color: "#6B7280"
162
+ },
163
+ children: "Only mappings at or above this threshold will sync automatically"
164
+ }
165
+ )
166
+ ] }),
167
+ /* @__PURE__ */ jsx(
168
+ Select,
169
+ {
170
+ name: "threshold",
171
+ placeholder: "Select Confidence Threshold",
172
+ options: thresholdOptions,
173
+ value: selectedThreshold,
174
+ onChange: (value) => setSelectedThreshold(value),
175
+ isDisabled: isAutoMatching
176
+ }
177
+ )
178
+ ] })
179
+ ] })
180
+ ] }) }),
181
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
182
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", slot: "close", children: "Cancel" }),
183
+ /* @__PURE__ */ jsx(
184
+ Button,
185
+ {
186
+ variant: "primary",
187
+ onClick: handleBegin,
188
+ isDisabled: !selectedThreshold || isAutoMatching,
189
+ children: isAutoMatching ? "Processing..." : "Begin"
190
+ }
191
+ )
192
+ ] })
193
+ ] });
194
+ }
195
+
196
+ export { AutomaticMappingsDialog as default };
197
+ //# sourceMappingURL=AutomaticMappingsDialog.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutomaticMappingsDialog.esm.js","sources":["../../../src/components/PagerDutyPage/AutomaticMappingsDialog.tsx"],"sourcesContent":["import {\n Dialog,\n DialogHeader,\n DialogBody,\n DialogFooter,\n Button,\n Select,\n Flex,\n Text,\n Box,\n} from '@backstage/ui';\nimport { Dispatch, useState } from 'react';\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { pagerDutyApiRef } from '../../api';\nimport { Warning } from '@mui/icons-material';\nimport { useAccountContext } from './AccountContext';\n\ninterface AutomaticMappingsDialogProps {\n isOpen: boolean;\n setIsOpen: Dispatch<React.SetStateAction<boolean>>;\n onAutoMatchComplete: (\n results: Record<\n string,\n {\n score: number;\n serviceId: string;\n account: string;\n serviceName: string;\n entity?: {\n name: string;\n entityRef: string;\n owner: string;\n };\n }\n >,\n ) => void;\n}\n\nexport default function AutomaticMappingsDialog({\n isOpen,\n setIsOpen,\n onAutoMatchComplete,\n}: AutomaticMappingsDialogProps) {\n const catalogApi = useApi(catalogApiRef);\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const queryClient = useQueryClient();\n const { selectedAccount } = useAccountContext();\n const [selectedTeam, setSelectedTeam] = useState<string>('all');\n const [selectedThreshold, setSelectedThreshold] = useState<string>('');\n\n const { data: groups, isLoading: isGroupsLoading } = useQuery({\n queryKey: ['catalog', 'groups'],\n queryFn: async () => {\n const response = await catalogApi.getEntities({\n filter: {\n kind: 'Group',\n },\n });\n return response.items;\n },\n enabled: isOpen,\n });\n\n const { mutateAsync: autoMatch, isPending: isAutoMatching } = useMutation({\n mutationFn: async (params: { team?: string; threshold: number; account?: string }) =>\n pagerDutyApi.autoMatchEntityMappings(params),\n onSuccess: data => {\n const matchMap: Record<\n string,\n {\n score: number;\n serviceId: string;\n account: string;\n serviceName: string;\n entity?: {\n name: string;\n entityRef: string;\n owner: string;\n };\n }\n > = {};\n\n const matches = data?.matches;\n\n if (Array.isArray(matches)) {\n matches.forEach(match => {\n const entityName = match.backstageComponent?.name;\n const score = match.score;\n\n const serviceId = match.pagerDutyService?.serviceId;\n const serviceName = match.pagerDutyService?.name;\n const account = match.pagerDutyService?.account || '';\n const entityRef = match.backstageComponent?.entityRef;\n const owner = match.backstageComponent?.owner;\n\n if (entityName && score !== undefined && serviceId) {\n matchMap[entityName] = {\n score,\n serviceId,\n account,\n serviceName,\n entity: {\n name: entityName,\n entityRef: entityRef || '',\n owner: owner || '',\n },\n };\n }\n });\n }\n onAutoMatchComplete(matchMap);\n queryClient.invalidateQueries({\n queryKey: ['pagerduty', 'enhancedEntityMappings'],\n });\n setIsOpen(false);\n },\n });\n\n const teamOptions = [\n { value: 'all', label: 'All Teams' },\n ...(groups?.map(group => ({\n value: group.metadata.name,\n label: group.metadata.name,\n })) || []),\n ];\n\n const thresholdOptions = [\n { value: '100', label: 'Exact Match (100%)' },\n { value: '90', label: 'High Confidence (>= 90%)' },\n { value: '80', label: 'Medium Confidence (>= 80%)' },\n ];\n\n const handleBegin = async () => {\n if (!selectedThreshold) return;\n\n await autoMatch({\n team: selectedTeam,\n threshold: parseInt(selectedThreshold, 10),\n account: selectedAccount,\n });\n };\n\n return (\n <Dialog isOpen={isOpen} onOpenChange={setIsOpen} style={{ width: '460px' }}>\n <DialogHeader>Service Auto-Mapping</DialogHeader>\n <DialogBody>\n <Box p=\"0 24px 8px 24px\">\n <Box\n style={{\n backgroundColor: '#FEF3CD',\n border: '1px solid #F4C430',\n borderRadius: '8px',\n padding: '16px',\n marginBottom: '8px',\n }}\n >\n <Flex gap=\"2\" align=\"start\" direction=\"column\">\n <Flex gap=\"1\">\n <Warning\n style={{\n color: '#F4C430',\n fontSize: 'var(--bui-font-size-3)',\n }}\n />\n <Text\n variant=\"body-medium\"\n weight=\"bold\"\n style={{ color: '#D97706', marginLeft: '4px' }}\n >\n Disclaimer:\n </Text>\n </Flex>\n\n <Text variant=\"body-medium\" style={{ color: '#6B7280' }}>\n Service auto-mapping uses service and team names to match\n components. Please review and confirm any mappings with\n confidence scores below 100% before syncing.\n </Text>\n </Flex>\n </Box>\n\n <Text\n variant=\"body-medium\"\n style={{\n marginBottom: '16px',\n display: 'block',\n lineHeight: '1.6',\n }}\n >\n This feature will map unmapped Backstage components to PagerDuty\n services and provide a confidence score for each match.\n </Text>\n\n <Flex direction=\"column\" gap=\"5\">\n <Select\n name=\"team\"\n isDisabled={isGroupsLoading || isAutoMatching}\n label=\"Backstage Team (optional)\"\n placeholder={\n isGroupsLoading ? 'Loading teams...' : 'Select a team'\n }\n options={teamOptions}\n value={selectedTeam}\n onChange={value => setSelectedTeam(value as string)}\n />\n\n <Box>\n <Flex direction=\"column\" style={{ marginBottom: '8px' }} gap=\"0\">\n <Text variant=\"body-small\">Confidence Threshold *</Text>\n <Text\n variant=\"body-x-small\"\n style={{\n color: '#6B7280',\n }}\n >\n Only mappings at or above this threshold will sync\n automatically\n </Text>\n </Flex>\n <Select\n name=\"threshold\"\n placeholder=\"Select Confidence Threshold\"\n options={thresholdOptions}\n value={selectedThreshold}\n onChange={value => setSelectedThreshold(value as string)}\n isDisabled={isAutoMatching}\n />\n </Box>\n </Flex>\n </Box>\n </DialogBody>\n <DialogFooter>\n <Button variant=\"secondary\" slot=\"close\">\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n onClick={handleBegin}\n isDisabled={!selectedThreshold || isAutoMatching}\n >\n {isAutoMatching ? 'Processing...' : 'Begin'}\n </Button>\n </DialogFooter>\n </Dialog>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;AAwCA,SAAwB,uBAAA,CAAwB;AAAA,EAC9C,MAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAAiC;AAC/B,EAAA,MAAM,UAAA,GAAa,OAAO,aAAa,CAAA;AACvC,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,SAAiB,KAAK,CAAA;AAC9D,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,SAAiB,EAAE,CAAA;AAErE,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAW,eAAA,KAAoB,QAAA,CAAS;AAAA,IAC5D,QAAA,EAAU,CAAC,SAAA,EAAW,QAAQ,CAAA;AAAA,IAC9B,SAAS,YAAY;AACnB,MAAA,MAAM,QAAA,GAAW,MAAM,UAAA,CAAW,WAAA,CAAY;AAAA,QAC5C,MAAA,EAAQ;AAAA,UACN,IAAA,EAAM;AAAA;AACR,OACD,CAAA;AACD,MAAA,OAAO,QAAA,CAAS,KAAA;AAAA,IAClB,CAAA;AAAA,IACA,OAAA,EAAS;AAAA,GACV,CAAA;AAED,EAAA,MAAM,EAAE,WAAA,EAAa,SAAA,EAAW,SAAA,EAAW,cAAA,KAAmB,WAAA,CAAY;AAAA,IACxE,UAAA,EAAY,OAAO,MAAA,KACjB,YAAA,CAAa,wBAAwB,MAAM,CAAA;AAAA,IAC7C,WAAW,CAAA,IAAA,KAAQ;AACjB,MAAA,MAAM,WAaF,EAAC;AAEL,MAAA,MAAM,UAAU,IAAA,EAAM,OAAA;AAEtB,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC1B,QAAA,OAAA,CAAQ,QAAQ,CAAA,KAAA,KAAS;AACvB,UAAA,MAAM,UAAA,GAAa,MAAM,kBAAA,EAAoB,IAAA;AAC7C,UAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AAEpB,UAAA,MAAM,SAAA,GAAY,MAAM,gBAAA,EAAkB,SAAA;AAC1C,UAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,EAAkB,IAAA;AAC5C,UAAA,MAAM,OAAA,GAAU,KAAA,CAAM,gBAAA,EAAkB,OAAA,IAAW,EAAA;AACnD,UAAA,MAAM,SAAA,GAAY,MAAM,kBAAA,EAAoB,SAAA;AAC5C,UAAA,MAAM,KAAA,GAAQ,MAAM,kBAAA,EAAoB,KAAA;AAExC,UAAA,IAAI,UAAA,IAAc,KAAA,KAAU,MAAA,IAAa,SAAA,EAAW;AAClD,YAAA,QAAA,CAAS,UAAU,CAAA,GAAI;AAAA,cACrB,KAAA;AAAA,cACA,SAAA;AAAA,cACA,OAAA;AAAA,cACA,WAAA;AAAA,cACA,MAAA,EAAQ;AAAA,gBACN,IAAA,EAAM,UAAA;AAAA,gBACN,WAAW,SAAA,IAAa,EAAA;AAAA,gBACxB,OAAO,KAAA,IAAS;AAAA;AAClB,aACF;AAAA,UACF;AAAA,QACF,CAAC,CAAA;AAAA,MACH;AACA,MAAA,mBAAA,CAAoB,QAAQ,CAAA;AAC5B,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,QAAA,EAAU,CAAC,WAAA,EAAa,wBAAwB;AAAA,OACjD,CAAA;AACD,MAAA,SAAA,CAAU,KAAK,CAAA;AAAA,IACjB;AAAA,GACD,CAAA;AAED,EAAA,MAAM,WAAA,GAAc;AAAA,IAClB,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,WAAA,EAAY;AAAA,IACnC,GAAI,MAAA,EAAQ,GAAA,CAAI,CAAA,KAAA,MAAU;AAAA,MACxB,KAAA,EAAO,MAAM,QAAA,CAAS,IAAA;AAAA,MACtB,KAAA,EAAO,MAAM,QAAA,CAAS;AAAA,KACxB,CAAE,KAAK;AAAC,GACV;AAEA,EAAA,MAAM,gBAAA,GAAmB;AAAA,IACvB,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,oBAAA,EAAqB;AAAA,IAC5C,EAAE,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,0BAAA,EAA2B;AAAA,IACjD,EAAE,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,4BAAA;AAA6B,GACrD;AAEA,EAAA,MAAM,cAAc,YAAY;AAC9B,IAAA,IAAI,CAAC,iBAAA,EAAmB;AAExB,IAAA,MAAM,SAAA,CAAU;AAAA,MACd,IAAA,EAAM,YAAA;AAAA,MACN,SAAA,EAAW,QAAA,CAAS,iBAAA,EAAmB,EAAE,CAAA;AAAA,MACzC,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,uBACE,IAAA,CAAC,UAAO,MAAA,EAAgB,YAAA,EAAc,WAAW,KAAA,EAAO,EAAE,KAAA,EAAO,OAAA,EAAQ,EACvE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,gBAAa,QAAA,EAAA,sBAAA,EAAoB,CAAA;AAAA,oBAClC,GAAA,CAAC,UAAA,EAAA,EACC,QAAA,kBAAA,IAAA,CAAC,GAAA,EAAA,EAAI,GAAE,iBAAA,EACL,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,GAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO;AAAA,YACL,eAAA,EAAiB,SAAA;AAAA,YACjB,MAAA,EAAQ,mBAAA;AAAA,YACR,YAAA,EAAc,KAAA;AAAA,YACd,OAAA,EAAS,MAAA;AAAA,YACT,YAAA,EAAc;AAAA,WAChB;AAAA,UAEA,+BAAC,IAAA,EAAA,EAAK,GAAA,EAAI,KAAI,KAAA,EAAM,OAAA,EAAQ,WAAU,QAAA,EACpC,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,IAAA,EAAA,EAAK,KAAI,GAAA,EACR,QAAA,EAAA;AAAA,8BAAA,GAAA;AAAA,gBAAC,OAAA;AAAA,gBAAA;AAAA,kBACC,KAAA,EAAO;AAAA,oBACL,KAAA,EAAO,SAAA;AAAA,oBACP,QAAA,EAAU;AAAA;AACZ;AAAA,eACF;AAAA,8BACA,GAAA;AAAA,gBAAC,IAAA;AAAA,gBAAA;AAAA,kBACC,OAAA,EAAQ,aAAA;AAAA,kBACR,MAAA,EAAO,MAAA;AAAA,kBACP,KAAA,EAAO,EAAE,KAAA,EAAO,SAAA,EAAW,YAAY,KAAA,EAAM;AAAA,kBAC9C,QAAA,EAAA;AAAA;AAAA;AAED,aAAA,EACF,CAAA;AAAA,4BAEA,GAAA,CAAC,QAAK,OAAA,EAAQ,aAAA,EAAc,OAAO,EAAE,KAAA,EAAO,SAAA,EAAU,EAAG,QAAA,EAAA,gKAAA,EAIzD;AAAA,WAAA,EACF;AAAA;AAAA,OACF;AAAA,sBAEA,GAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAQ,aAAA;AAAA,UACR,KAAA,EAAO;AAAA,YACL,YAAA,EAAc,MAAA;AAAA,YACd,OAAA,EAAS,OAAA;AAAA,YACT,UAAA,EAAY;AAAA,WACd;AAAA,UACD,QAAA,EAAA;AAAA;AAAA,OAGD;AAAA,sBAEA,IAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,QAAA,EAAS,KAAI,GAAA,EAC3B,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,MAAA;AAAA,YACL,YAAY,eAAA,IAAmB,cAAA;AAAA,YAC/B,KAAA,EAAM,2BAAA;AAAA,YACN,WAAA,EACE,kBAAkB,kBAAA,GAAqB,eAAA;AAAA,YAEzC,OAAA,EAAS,WAAA;AAAA,YACT,KAAA,EAAO,YAAA;AAAA,YACP,QAAA,EAAU,CAAA,KAAA,KAAS,eAAA,CAAgB,KAAe;AAAA;AAAA,SACpD;AAAA,6BAEC,GAAA,EAAA,EACC,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,IAAA,EAAA,EAAK,WAAU,QAAA,EAAS,KAAA,EAAO,EAAE,YAAA,EAAc,KAAA,EAAM,EAAG,GAAA,EAAI,GAAA,EAC3D,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,YAAA,EAAa,QAAA,EAAA,wBAAA,EAAsB,CAAA;AAAA,4BACjD,GAAA;AAAA,cAAC,IAAA;AAAA,cAAA;AAAA,gBACC,OAAA,EAAQ,cAAA;AAAA,gBACR,KAAA,EAAO;AAAA,kBACL,KAAA,EAAO;AAAA,iBACT;AAAA,gBACD,QAAA,EAAA;AAAA;AAAA;AAGD,WAAA,EACF,CAAA;AAAA,0BACA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,WAAA;AAAA,cACL,WAAA,EAAY,6BAAA;AAAA,cACZ,OAAA,EAAS,gBAAA;AAAA,cACT,KAAA,EAAO,iBAAA;AAAA,cACP,QAAA,EAAU,CAAA,KAAA,KAAS,oBAAA,CAAqB,KAAe,CAAA;AAAA,cACvD,UAAA,EAAY;AAAA;AAAA;AACd,SAAA,EACF;AAAA,OAAA,EACF;AAAA,KAAA,EACF,CAAA,EACF,CAAA;AAAA,yBACC,YAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,SAAQ,QAAA,EAAA,QAAA,EAEzC,CAAA;AAAA,sBACA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAQ,SAAA;AAAA,UACR,OAAA,EAAS,WAAA;AAAA,UACT,UAAA,EAAY,CAAC,iBAAA,IAAqB,cAAA;AAAA,UAEjC,2BAAiB,eAAA,GAAkB;AAAA;AAAA;AACtC,KAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}