@pagerduty/backstage-plugin 0.19.0 → 0.20.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @backstage/plugin-pagerduty
2
2
 
3
+ ## 0.20.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9941800: 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
+ - ef0af04: Moved to a process/polling based loading of the automatic mapping matches
12
+ - Updated dependencies [9941800]
13
+ - Updated dependencies [ef0af04]
14
+ - @pagerduty/backstage-plugin-common@0.4.0
15
+
3
16
  ## 0.19.0
4
17
 
5
18
  ### Minor Changes
@@ -268,12 +268,12 @@ class PagerDutyClient {
268
268
  const url = this.config.eventsBaseUrl ?? "https://events.pagerduty.com/v2";
269
269
  return this.request(`${url}/enqueue`, options);
270
270
  }
271
- async autoMatchEntityMappings(options) {
271
+ async startAutoMatchEntityMappings(options) {
272
272
  const url = `${await this.config.discoveryApi.getBaseUrl(
273
273
  "pagerduty"
274
- )}/mapping/entity/auto-match`;
274
+ )}/mapping/entity/auto-match/start`;
275
275
  const body = JSON.stringify({
276
- team: options.team === "all" ? void 0 : options.team,
276
+ team: options.team,
277
277
  threshold: options.threshold,
278
278
  bestOnly: true,
279
279
  account: options.account
@@ -289,6 +289,12 @@ class PagerDutyClient {
289
289
  const response = await this.request(url, requestOptions);
290
290
  return response.json();
291
291
  }
292
+ async getAutoMatchStatus(jobId) {
293
+ const url = `${await this.config.discoveryApi.getBaseUrl(
294
+ "pagerduty"
295
+ )}/mapping/entity/auto-match/${encodeURIComponent(jobId)}`;
296
+ return await this.findByUrl(url);
297
+ }
292
298
  async getAccounts() {
293
299
  const url = `${await this.config.discoveryApi.getBaseUrl(
294
300
  "pagerduty"
@@ -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 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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"}
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 AutoMatchStartResponse,\n AutoMatchStatusResponse,\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 startAutoMatchEntityMappings(options: {\n team?: string;\n threshold: number;\n account?: string;\n }): Promise<AutoMatchStartResponse> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entity/auto-match/start`;\n\n const body = JSON.stringify({\n team: 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 getAutoMatchStatus(jobId: string): Promise<AutoMatchStatusResponse> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/mapping/entity/auto-match/${encodeURIComponent(jobId)}`;\n\n return await this.findByUrl<AutoMatchStatusResponse>(url);\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":";;;;AA6CO,MAAM,0BAA0B,KAAA,CAAM;AAAC;AAGvC,MAAM,uBAAuB,KAAA,CAAM;AAAC;AAGpC,MAAM,kBAAkB,YAAA,CAA2B;AAAA,EACxD,EAAA,EAAI;AACN,CAAC;AAGM,MAAM,eAAA,CAAwC;AAAA,EAkBnD,YAA6B,MAAA,EAAkC;AAAlC,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAmC;AAAA,EAjBhE,OAAO,UAAA,CACL,SAAA,EACA,YAAA,EACA;AACA,IAAA,MAAM,EAAE,YAAA,EAAc,QAAA,EAAS,GAAI,YAAA;AAEnC,IAAA,MAAM,aAAA,GACJ,SAAA,CAAU,iBAAA,CAAkB,yBAAyB,CAAA,IACrD,iCAAA;AAEF,IAAA,OAAO,IAAI,eAAA,CAAgB;AAAA,MACzB,aAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAAA,EAIA,MAAM,4BACJ,eAAA,EACmC;AACnC,IAAA,MAAM,EAAE,cAAA,EAAgB,SAAA,EAAW,OAAA,EAAQ,GAAI,eAAA;AAE/C,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI,GAAA;AAEJ,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,UAAA;AAAA,QACtC;AAAA,OACD,6BAA6B,cAAc,CAAA,CAAA;AAE5C,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,GAAA,GAAM,CAAA,EAAG,GAAG,CAAA,SAAA,EAAY,OAAO,CAAA,CAAA;AAAA,MACjC;AACA,MAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,SAAA;AAAA,QACjC;AAAA,OACF;AAEA,MAAA,IAAI,eAAA,CAAgB,OAAA,KAAY,MAAA,EAAW,MAAM,IAAI,aAAA,EAAc;AAEnE,MAAA,QAAA,GAAW,eAAA;AAAA,IACb,WAAW,SAAA,EAAW;AACpB,MAAA,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,UAAA;AAAA,QACtC;AAAA,OACD,aAAa,SAAS,CAAA,CAAA;AAEvB,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,GAAA,GAAM,CAAA,EAAG,GAAG,CAAA,SAAA,EAAY,OAAO,CAAA,CAAA;AAAA,MACjC;AAEA,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAoC,GAAG,CAAA;AAAA,IAC/D,CAAA,MAAO;AACL,MAAA,MAAM,IAAI,aAAA,EAAc;AAAA,IAC1B;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,EAAA,EAAuC;AACtD,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,aAAa,EAAE,CAAA,CAAA;AAEhB,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAA4B,GAAG,CAAA;AAAA,EACnD;AAAA,EAEA,MAAM,cAAc,QAAA,EAAiD;AACnE,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA;AAEpC,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,iCAAA;AAAA,QAChB,MAAA,EAAQ;AAAA,OACV;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,SAAA,CAAA;AAED,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,OAAO,CAAA;AAAA,EAClC;AAAA,EAEA,MAAM,gCAAgC,OAAA,EAWe;AACnD,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,iBAAA,CAAA;AAED,IAAA,MAAM,IAAA,GAAO,KAAK,SAAA,CAAU;AAAA,MAC1B,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,OAAA,EAAS,OAAA,CAAQ,OAAA,IAAW,EAAC;AAAA,MAC7B,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,SAAS,OAAA,CAAQ;AAAA,KAClB,CAAA;AAED,IAAA,MAAM,cAAA,GAAiB;AAAA,MACrB,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,iCAAA;AAAA,QAChB,MAAA,EAAQ;AAAA,OACV;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAK,cAAc,CAAA;AACvD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA,EAEA,MAAM,cAAA,GAA8C;AAClD,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,gBAAA,CAAA;AAED,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAA8B,GAAG,CAAA;AAAA,EACrD;AAAA,EAEA,MAAM,YAAY,OAAA,EAA4C;AAC5D,IAAA,MAAM,UAAU,MAAM,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,WAAW,WAAW,CAAA;AACrE,IAAA,MAAM,GAAA,GAAM,OAAA,GACR,CAAA,EAAG,OAAO,CAAA,eAAA,EAAkB,mBAAmB,OAAO,CAAC,CAAA,CAAA,GACvD,CAAA,EAAG,OAAO,CAAA,MAAA,CAAA;AAEd,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAA2B,GAAG,CAAA;AAAA,EAClD;AAAA,EAEA,MAAM,mBAAA,CACJ,OAAA,EACA,KAAA,EACA,OACA,OAAA,EAC6B;AAC7B,IAAA,MAAM,UAAU,MAAM,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,WAAW,WAAW,CAAA;AACrE,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AAEnC,IAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AACjC,MAAA,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA,IACrC;AAEA,IAAA,IAAI,KAAA,IAAS,KAAA,CAAM,IAAA,EAAK,KAAM,EAAA,EAAI;AAChC,MAAA,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,KAAA,CAAM,IAAA,EAAM,CAAA;AAAA,IACrC;AAEA,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,KAAA,CAAM,QAAA,EAAU,CAAA;AAAA,IACzC;AAEA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAA,CAAO,MAAA,CAAO,WAAW,OAAO,CAAA;AAAA,IAClC;AAEA,IAAA,MAAM,WAAA,GAAc,OAAO,QAAA,EAAS;AACpC,IAAA,MAAM,GAAA,GAAM,cACR,CAAA,EAAG,OAAO,aAAa,WAAW,CAAA,CAAA,GAClC,GAAG,OAAO,CAAA,SAAA,CAAA;AAEd,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAA8B,GAAG,CAAA;AAAA,EACrD;AAAA,EAEA,MAAM,mBAAA,CACJ,SAAA,EACA,cAAA,EACA,oBACA,OAAA,EACmB;AACnB,IAAA,MAAM,IAAA,GAAO,KAAK,SAAA,CAAU;AAAA,MAC1B,SAAA,EAAW,kBAAA;AAAA,MACX,SAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,iCAAA;AAAA,QAChB,MAAA,EAAQ;AAAA,OACV;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,eAAA,CAAA;AAED,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,OAAO,CAAA;AAAA,EAClC;AAAA,EAGA,MAAM,iBAAiB,SAAA,EAMpB;AACD,IAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,KAAA,CAAM,yBAAyB,CAAA;AACvD,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,SAAS,CAAA,CAAE,CAAA;AAAA,IAC1D;AAEA,IAAA,MAAM,GAAG,IAAA,EAAM,SAAA,EAAW,IAAI,CAAA,GAAI,KAAA;AAElC,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,gBAAA,EAAmB,IAAI,CAAA,CAAA,EAAI,SAAS,IAAI,IAAI,CAAA,CAAA;AAE7C,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAU,GAAG,CAAA;AAAA,EACjC;AAAA,EAEA,MAAM,yBACJ,QAAA,EAMmB;AACnB,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,EAAE,UAAU,CAAA;AAExC,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,iCAAA;AAAA,QAChB,MAAA,EAAQ;AAAA,OACV;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,sBAAA,CAAA;AAED,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,OAAO,CAAA;AAAA,EAClC;AAAA,EAEA,MAAM,qBAAqB,SAAA,EAAqC;AAE9D,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAM,IAAA,CAAK,iBAAiB,SAAS,CAAA;AAIzD,IAAA,MAAM,IAAA,CAAK,mBAAA;AAAA,MACT,OAAA,CAAQ,SAAA;AAAA,MACR,OAAA,CAAQ,cAAA;AAAA,MACR,EAAA;AAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACV;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,mBAAmB,MAAA,EAAmD;AAC1E,IAAA,OAAO,MAAM,IAAA,CAAK,2BAAA,CAA4B,kBAAA,CAAmB,MAAM,CAAC,CAAA;AAAA,EAC1E;AAAA,EAEA,MAAM,cAAA,CACJ,SAAA,EACA,OAAA,EACmC;AACnC,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,aAAa,SAAS,CAAA,CAAA;AAEvB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAoC,GAAG,CAAA;AAAA,EAC3D;AAAA,EAEA,MAAM,uBAAA,CACJ,SAAA,EACA,OAAA,EACqC;AACrC,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,aAAa,SAAS,CAAA,UAAA,CAAA;AAEvB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAsC,GAAG,CAAA;AAAA,EAC7D;AAAA,EAEA,MAAM,0BAAA,CACJ,SAAA,EACA,OAAA,EACwC;AACxC,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,aAAa,SAAS,CAAA,cAAA,CAAA;AAEvB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAyC,GAAG,CAAA;AAAA,EAChE;AAAA,EAEA,MAAM,8BAAA,CACJ,SAAA,EACA,OAAA,EAC4C;AAC5C,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,aAAa,SAAS,CAAA,UAAA,CAAA;AAEvB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAA6C,GAAG,CAAA;AAAA,EACpE;AAAA,EAEA,MAAM,4BAAA,CACJ,SAAA,EACA,OAAA,EAC0C;AAC1C,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,aAAa,SAAS,CAAA,QAAA,CAAA;AAEvB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAA2C,GAAG,CAAA;AAAA,EAClE;AAAA,EAEA,MAAM,mBAAA,CACJ,QAAA,EACA,OAAA,EAC0B;AAC1B,IAAA,MAAM,MAAA,GAAS,2BAA2B,QAAQ,CAAA,CAAA;AAClD,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,iBAAiB,MAAM,CAAA,CAAA;AAExB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,MAAM,QAAA,GACJ,MAAM,IAAA,CAAK,SAAA,CAAwC,GAAG,CAAA;AACxD,IAAA,OAAO,QAAA,CAAS,KAAA;AAAA,EAClB;AAAA,EAEA,aAAa,OAAA,EAA0D;AACrE,IAAA,MAAM,EAAE,cAAA,EAAgB,MAAA,EAAQ,WAAA,EAAa,UAAS,GAAI,OAAA;AAE1D,IAAA,MAAM,IAAA,GAAO,KAAK,SAAA,CAAU;AAAA,MAC1B,YAAA,EAAc,SAAA;AAAA,MACd,WAAA,EAAa,cAAA;AAAA,MACb,MAAA,EAAQ,WAAA;AAAA,MACR,UAAA,EAAY,MAAA;AAAA,MACZ,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,WAAA;AAAA,QACT,MAAA;AAAA,QACA,QAAA,EAAU,OAAA;AAAA,QACV,KAAA,EAAO,gBAAA;AAAA,QACP,cAAA,EAAgB;AAAA,UACd,IAAA,EAAM;AAAA;AACR;AACF,KACD,CAAA;AAED,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,iCAAA;AAAA,QAChB,MAAA,EAAQ;AAAA,OACV;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,aAAA,IAAiB,iCAAA;AAEzC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,CAAA,EAAG,GAAG,YAAY,OAAO,CAAA;AAAA,EAC/C;AAAA,EAEA,MAAM,6BAA6B,OAAA,EAIC;AAClC,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,gCAAA,CAAA;AAED,IAAA,MAAM,IAAA,GAAO,KAAK,SAAA,CAAU;AAAA,MAC1B,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,QAAA,EAAU,IAAA;AAAA,MACV,SAAS,OAAA,CAAQ;AAAA,KAClB,CAAA;AAED,IAAA,MAAM,cAAA,GAAiB;AAAA,MACrB,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,iCAAA;AAAA,QAChB,MAAA,EAAQ;AAAA,OACV;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAK,cAAc,CAAA;AACvD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA,EAEA,MAAM,mBAAmB,KAAA,EAAiD;AACxE,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,2BAAA,EAA8B,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA;AAExD,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAmC,GAAG,CAAA;AAAA,EAC1D;AAAA,EAEA,MAAM,WAAA,GAAkE;AACtE,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,SAAA,CAAA;AAED,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAEzB,GAAG,CAAA;AACN,IAAA,OAAO,QAAA,CAAS,QAAA;AAAA,EAClB;AAAA,EAEA,MAAc,UAAa,GAAA,EAAyB;AAClD,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ,0CAAA;AAAA,QACR,cAAA,EAAgB;AAAA;AAClB,KACF;AACA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAK,OAAO,CAAA;AAChD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA,EAEA,MAAc,OAAA,CACZ,GAAA,EACA,OAAA,EACmB;AACnB,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAO,QAAA,CAAS,KAAA,CAAM,KAAK,OAAO,CAAA;AAC9D,IAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,MAAA,MAAM,IAAI,iBAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,MAAA,MAAM,IAAI,cAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,MAAA,MAAM,IAAI,cAAc,+BAA+B,CAAA;AAAA,IACzD;AAEA,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AACpC,MAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAkB,KAAK,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AACpE,MAAA,MAAM,OAAA,GAAU,CAAA,oBAAA,EAAuB,QAAA,CAAS,MAAM,KAAK,MAAM,CAAA,CAAA;AACjE,MAAA,MAAM,IAAI,MAAM,OAAO,CAAA;AAAA,IACzB;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AACF;;;;"}
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { Dialog, DialogHeader, DialogBody, Box, Flex, Text, Select, DialogFooter, Button } from '@backstage/ui';
3
- import { useState } from 'react';
3
+ import { useState, useCallback } from 'react';
4
4
  import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
5
5
  import { useApi } from '@backstage/core-plugin-api';
6
6
  import { catalogApiRef } from '@backstage/plugin-catalog-react';
@@ -19,54 +19,90 @@ function AutomaticMappingsDialog({
19
19
  const { selectedAccount } = useAccountContext();
20
20
  const [selectedTeam, setSelectedTeam] = useState("all");
21
21
  const [selectedThreshold, setSelectedThreshold] = useState("");
22
+ const [activeJobId, setActiveJobId] = useState();
23
+ const resetDialogState = useCallback(() => {
24
+ setSelectedTeam("all");
25
+ setSelectedThreshold("");
26
+ setActiveJobId(void 0);
27
+ }, []);
28
+ const handleOpenChange = useCallback(
29
+ (open) => {
30
+ if (!open) resetDialogState();
31
+ setIsOpen(open);
32
+ },
33
+ [resetDialogState, setIsOpen]
34
+ );
22
35
  const { data: groups, isLoading: isGroupsLoading } = useQuery({
23
36
  queryKey: ["catalog", "groups"],
24
37
  queryFn: async () => {
25
38
  const response = await catalogApi.getEntities({
26
39
  filter: {
27
40
  kind: "Group"
28
- }
41
+ },
42
+ order: [{ field: "metadata.name", order: "asc" }]
29
43
  });
30
44
  return response.items;
31
45
  },
32
46
  enabled: isOpen
33
47
  });
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"]
48
+ const handleAutoMatchResult = (data) => {
49
+ const matchMap = {};
50
+ const matches = data?.matches;
51
+ if (Array.isArray(matches)) {
52
+ matches.forEach((match) => {
53
+ const entityName = match.backstageComponent?.name;
54
+ const score = match.score;
55
+ const serviceId = match.pagerDutyService?.serviceId;
56
+ const serviceName = match.pagerDutyService?.name;
57
+ const account = match.pagerDutyService?.account || "";
58
+ const entityRef = match.backstageComponent?.entityRef;
59
+ const owner = match.backstageComponent?.owner;
60
+ if (entityName && score !== void 0 && serviceId) {
61
+ matchMap[entityName] = {
62
+ score,
63
+ serviceId,
64
+ account,
65
+ serviceName,
66
+ entity: {
67
+ name: entityName,
68
+ entityRef: entityRef || "",
69
+ owner: owner || ""
70
+ }
71
+ };
72
+ }
66
73
  });
67
- setIsOpen(false);
68
74
  }
75
+ onAutoMatchComplete(matchMap);
76
+ queryClient.invalidateQueries({
77
+ queryKey: ["pagerduty", "enhancedEntityMappings"]
78
+ });
79
+ resetDialogState();
80
+ setIsOpen(false);
81
+ };
82
+ const { mutateAsync: startAutoMatch, isPending: isStartingAutoMatch } = useMutation({
83
+ mutationFn: async (params) => pagerDutyApi.startAutoMatchEntityMappings(params),
84
+ onSuccess: (data) => {
85
+ setActiveJobId(data.jobId);
86
+ }
87
+ });
88
+ const { data: jobStatus, error: jobStatusError } = useQuery({
89
+ queryKey: ["pagerduty", "autoMatchJob", activeJobId],
90
+ queryFn: () => pagerDutyApi.getAutoMatchStatus(activeJobId),
91
+ enabled: Boolean(activeJobId) && isOpen,
92
+ refetchInterval: (query) => {
93
+ if (!isOpen) return false;
94
+ const status = query.state.data?.status;
95
+ if (status === "completed" || status === "failed") {
96
+ return false;
97
+ }
98
+ return 5e3;
99
+ },
100
+ refetchIntervalInBackground: false
69
101
  });
102
+ if (jobStatus?.status === "completed" && jobStatus.result) {
103
+ handleAutoMatchResult(jobStatus.result);
104
+ }
105
+ const isAutoMatching = isStartingAutoMatch || Boolean(activeJobId) && jobStatus?.status !== "completed" && jobStatus?.status !== "failed";
70
106
  const teamOptions = [
71
107
  { value: "all", label: "All Teams" },
72
108
  ...groups?.map((group) => ({
@@ -81,13 +117,19 @@ function AutomaticMappingsDialog({
81
117
  ];
82
118
  const handleBegin = async () => {
83
119
  if (!selectedThreshold) return;
84
- await autoMatch({
85
- team: selectedTeam,
120
+ await startAutoMatch({
121
+ team: selectedTeam === "all" ? void 0 : selectedTeam,
86
122
  threshold: parseInt(selectedThreshold, 10),
87
123
  account: selectedAccount
88
124
  });
89
125
  };
90
- return /* @__PURE__ */ jsxs(Dialog, { isOpen, onOpenChange: setIsOpen, style: { width: "460px" }, children: [
126
+ let failureMessage;
127
+ if (jobStatus?.status === "failed") {
128
+ failureMessage = jobStatus.error || "Auto-match failed";
129
+ } else if (jobStatusError instanceof Error) {
130
+ failureMessage = jobStatusError.message;
131
+ }
132
+ return /* @__PURE__ */ jsxs(Dialog, { isOpen, onOpenChange: handleOpenChange, style: { width: "460px" }, children: [
91
133
  /* @__PURE__ */ jsx(DialogHeader, { children: "Service Auto-Mapping" }),
92
134
  /* @__PURE__ */ jsx(DialogBody, { children: /* @__PURE__ */ jsxs(Box, { p: "0 24px 8px 24px", children: [
93
135
  /* @__PURE__ */ jsx(
@@ -147,7 +189,9 @@ function AutomaticMappingsDialog({
147
189
  placeholder: isGroupsLoading ? "Loading teams..." : "Select a team",
148
190
  options: teamOptions,
149
191
  value: selectedTeam,
150
- onChange: (value) => setSelectedTeam(value)
192
+ onChange: (value) => setSelectedTeam(value),
193
+ searchable: true,
194
+ searchPlaceholder: "Search teams..."
151
195
  }
152
196
  ),
153
197
  /* @__PURE__ */ jsxs(Box, { children: [
@@ -175,7 +219,9 @@ function AutomaticMappingsDialog({
175
219
  isDisabled: isAutoMatching
176
220
  }
177
221
  )
178
- ] })
222
+ ] }),
223
+ isAutoMatching && /* @__PURE__ */ jsx(Text, { variant: "body-small", style: { color: "#6B7280" }, children: "Running auto-match in the background. This may take a few minutes for large amounts of PagerDuty services." }),
224
+ failureMessage && /* @__PURE__ */ jsx(Text, { variant: "body-small", style: { color: "#B91C1C" }, children: failureMessage })
179
225
  ] })
180
226
  ] }) }),
181
227
  /* @__PURE__ */ jsxs(DialogFooter, { children: [
@@ -1 +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":"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"}
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, useCallback, useState } from 'react';\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport type { AutoMatchEntityMappingsResponse } from '@pagerduty/backstage-plugin-common';\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 const [activeJobId, setActiveJobId] = useState<string | undefined>();\n\n const resetDialogState = useCallback(() => {\n setSelectedTeam('all');\n setSelectedThreshold('');\n setActiveJobId(undefined);\n }, []);\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (!open) resetDialogState();\n setIsOpen(open);\n },\n [resetDialogState, setIsOpen],\n );\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 order: [{ field: 'metadata.name', order: 'asc' }],\n });\n return response.items;\n },\n enabled: isOpen,\n });\n\n const handleAutoMatchResult = (data: AutoMatchEntityMappingsResponse) => {\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 resetDialogState();\n setIsOpen(false);\n };\n\n const { mutateAsync: startAutoMatch, isPending: isStartingAutoMatch } =\n useMutation({\n mutationFn: async (params: {\n team?: string;\n threshold: number;\n account?: string;\n }) => pagerDutyApi.startAutoMatchEntityMappings(params),\n onSuccess: data => {\n setActiveJobId(data.jobId);\n },\n });\n\n const { data: jobStatus, error: jobStatusError } = useQuery({\n queryKey: ['pagerduty', 'autoMatchJob', activeJobId],\n queryFn: () => pagerDutyApi.getAutoMatchStatus(activeJobId!),\n enabled: Boolean(activeJobId) && isOpen,\n refetchInterval: query => {\n if (!isOpen) return false;\n const status = query.state.data?.status;\n if (status === 'completed' || status === 'failed') {\n return false;\n }\n return 5000;\n },\n refetchIntervalInBackground: false,\n });\n\n\n if (jobStatus?.status === 'completed' && jobStatus.result) {\n handleAutoMatchResult(jobStatus.result);\n }\n\n const isAutoMatching =\n isStartingAutoMatch ||\n (Boolean(activeJobId) &&\n jobStatus?.status !== 'completed' &&\n jobStatus?.status !== 'failed');\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 startAutoMatch({\n team: selectedTeam === 'all' ? undefined : selectedTeam,\n threshold: parseInt(selectedThreshold, 10),\n account: selectedAccount,\n });\n };\n\n let failureMessage: string | undefined;\n if (jobStatus?.status === 'failed') {\n failureMessage = jobStatus.error || 'Auto-match failed';\n } else if (jobStatusError instanceof Error) {\n failureMessage = jobStatusError.message;\n }\n\n return (\n <Dialog isOpen={isOpen} onOpenChange={handleOpenChange} 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 searchable\n searchPlaceholder='Search teams...'\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 {isAutoMatching && (\n <Text variant=\"body-small\" style={{ color: '#6B7280' }}>\n Running auto-match in the background. This may take a few\n minutes for large amounts of PagerDuty services.\n </Text>\n )}\n {failureMessage && (\n <Text variant=\"body-small\" style={{ color: '#B91C1C' }}>\n {failureMessage}\n </Text>\n )}\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":"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"}
@@ -178,6 +178,8 @@ function MappingsDialog({
178
178
  placeholder: "All Teams",
179
179
  options: teamOptions,
180
180
  value: selectedTeamId,
181
+ searchPlaceholder: "Search teams...",
182
+ searchable: true,
181
183
  onChange: (value) => {
182
184
  setSelectedTeamId(String(value || ""));
183
185
  setSelectedServiceId("");
@@ -1 +1 @@
1
- {"version":3,"file":"MappingsDialog.esm.js","sources":["../../../src/components/PagerDutyPage/MappingsDialog.tsx"],"sourcesContent":["import {\n Dialog,\n DialogHeader,\n DialogBody,\n DialogFooter,\n Button,\n Select,\n Flex,\n Text,\n SearchField,\n RadioGroup,\n Radio,\n Box,\n TextField,\n} from '@backstage/ui';\nimport { Dispatch, useState, useEffect } from 'react';\nimport { BackstageEntity } from '../types';\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { pagerDutyApiRef } from '../../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { makeStyles } from '@material-ui/core';\nimport { useAccountContext } from './AccountContext';\nimport useDebounce from '../../hooks/useDebounce';\n\nconst useStyles = makeStyles(() => ({\n radioListContainer: {\n maxHeight: '300px',\n overflowY: 'auto',\n border: '1px solid var(--bui-border)',\n borderRadius: 'var(--bui-radius-2)',\n padding: 0,\n '& > div > div': {\n gap: 0,\n },\n '& label[data-rac]': {\n margin: 0,\n padding: 'var(--bui-spacing-2) var(--bui-spacing-3)',\n minHeight: '32px',\n borderBottom: '1px solid var(--bui-gray-2)',\n borderLeft: '3px solid transparent',\n cursor: 'pointer',\n transition: 'background-color 0.15s ease',\n display: 'flex',\n alignItems: 'center',\n '&:last-child': {\n borderBottom: 'none',\n },\n '&:hover': {\n backgroundColor: 'var(--bui-gray-1)',\n },\n '&[data-selected=\"true\"]': {\n backgroundColor: 'var(--bui-blue-1)',\n borderLeft: '3px solid var(--bui-blue-6)',\n fontWeight: 'var(--bui-font-weight-bold)',\n },\n },\n },\n}));\n\ninterface MappingsDialogProps {\n isOpen: boolean;\n setIsOpen: Dispatch<React.SetStateAction<boolean>>;\n entity: BackstageEntity | null;\n onMappingSuccess?: (isUnmapping: boolean) => void;\n}\n\nexport default function MappingsDialog({\n isOpen,\n setIsOpen,\n entity,\n onMappingSuccess,\n}: MappingsDialogProps) {\n const classes = useStyles();\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const queryClient = useQueryClient();\n const { selectedAccount } = useAccountContext();\n const [selectedServiceId, setSelectedServiceId] = useState<string>('');\n const [selectedTeamId, setSelectedTeamId] = useState<string>('');\n const [searchQuery, setSearchQuery] = useState<string>('');\n const debouncedSearchQuery = useDebounce(searchQuery);\n\n useEffect(() => {\n if (!isOpen) {\n setSelectedServiceId('');\n setSelectedTeamId('');\n setSearchQuery('');\n }\n }, [isOpen]);\n\n const accountParam = selectedAccount || undefined;\n\n const { data: teams, isLoading: isTeamsLoading } = useQuery({\n queryKey: ['pagerduty', 'getAllTeams', accountParam],\n queryFn: () => pagerDutyApi.getAllTeams(accountParam),\n enabled: isOpen,\n });\n\n const { data: services, isLoading: isServicesLoading } = useQuery({\n queryKey: ['pagerduty', 'getFilteredServices', selectedTeamId, debouncedSearchQuery, accountParam],\n queryFn: async () => {\n const teamIdsToSend = selectedTeamId ? [selectedTeamId] : undefined;\n const queryToSend = debouncedSearchQuery || undefined;\n const result = await pagerDutyApi.getFilteredServices(\n teamIdsToSend,\n queryToSend,\n 10,\n accountParam,\n );\n return result;\n },\n enabled: isOpen,\n });\n\n const { mutateAsync: createMapping, isPending: isCreatingMapping } =\n useMutation({\n mutationFn: async ({\n serviceId,\n integrationKey,\n entityRef,\n account,\n isUnmapping,\n }: {\n serviceId: string;\n integrationKey: string;\n entityRef: string;\n account: string;\n isUnmapping: boolean;\n }) => {\n await pagerDutyApi.storeServiceMapping(\n serviceId,\n integrationKey,\n entityRef,\n account,\n );\n return isUnmapping;\n },\n\n onSuccess: async (isUnmapping) => {\n queryClient.invalidateQueries({\n queryKey: ['pagerduty', 'enhancedEntityMappings'],\n });\n setIsOpen(false);\n setSelectedServiceId('');\n onMappingSuccess?.(isUnmapping);\n },\n });\n\n const handleSaveMapping = () => {\n if (!entity || !selectedServiceId) return;\n\n if (selectedServiceId === 'none') {\n const currentServiceId = entity.annotations?.['pagerduty.com/service-id'];\n const currentIntegrationKey = entity.annotations?.['pagerduty.com/integration-key'] || '';\n const account = entity.account || '';\n\n if (!currentServiceId) return;\n\n createMapping({\n serviceId: currentServiceId,\n integrationKey: currentIntegrationKey,\n entityRef: '',\n account: account,\n isUnmapping: true,\n });\n return;\n }\n\n const selectedService = services?.find(\n service => service.id === selectedServiceId,\n );\n\n if (!selectedService) return;\n\n const entityRef =\n `${entity.type}:${entity.namespace}/${entity.name}`.toLowerCase();\n\n createMapping({\n serviceId: selectedServiceId,\n integrationKey: '',\n entityRef: entityRef,\n account: selectedService.account ?? '',\n isUnmapping: false,\n });\n };\n\n // Prepare team options for Select\n const teamOptions = [\n { value: '', label: 'All Teams' },\n ...(teams?.map(team => ({\n value: team.id,\n label: team.name,\n })) || []),\n ];\n\n return (\n <Dialog isOpen={isOpen} onOpenChange={setIsOpen}>\n <DialogHeader>Update Entity Mapping</DialogHeader>\n <DialogBody>\n <Flex direction=\"column\" gap=\"2\" mb=\"4\">\n <Text variant=\"body-medium\" weight=\"bold\">\n Backstage Component\n </Text>\n <TextField\n value={entity?.name || ''}\n isReadOnly\n />\n </Flex>\n\n <Flex direction=\"column\" gap=\"2\" mb=\"4\">\n <Text variant=\"body-medium\" weight=\"bold\">\n Team\n </Text>\n <TextField\n value={entity?.owner || ''}\n isReadOnly\n />\n </Flex>\n\n <Box mb=\"3\">\n <Text variant=\"body-medium\" weight=\"bold\">\n Map to Service\n </Text>\n </Box>\n\n <Box mb=\"3\">\n <Select\n name=\"team\"\n isDisabled={isTeamsLoading || isCreatingMapping}\n label=\"PagerDuty Team (Optional)\"\n placeholder=\"All Teams\"\n options={teamOptions}\n value={selectedTeamId}\n onChange={value => {\n setSelectedTeamId(String(value || ''));\n setSelectedServiceId('');\n }}\n />\n </Box>\n\n <Flex direction=\"column\" gap=\"2\" mb=\"3\">\n <Text variant=\"body-medium\" weight=\"bold\">\n PagerDuty Services\n </Text>\n <Text variant=\"body-small\">\n Search by service name or service ID\n </Text>\n <SearchField\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder=\"Search\"\n />\n </Flex>\n\n {isServicesLoading ? (\n <Text>Loading services...</Text>\n ) : (\n <>\n <Box\n className={classes.radioListContainer}\n mb=\"2\"\n >\n <RadioGroup\n value={selectedServiceId}\n onChange={setSelectedServiceId}\n >\n {entity?.annotations?.['pagerduty.com/service-id'] && (\n <Radio key=\"none\" value=\"none\">\n (None)\n </Radio>\n )}\n {services && services\n .filter(service => service.id !== entity?.annotations?.['pagerduty.com/service-id'])\n .map(service => (\n <Radio key={service.id} value={service.id}>\n {service.name}\n </Radio>\n ))}\n </RadioGroup>\n </Box>\n {services && services.length > 0 ? (\n <Text variant=\"body-small\">\n Showing {services.length} result{services.length !== 1 ? 's' : ''}\n </Text>\n ) : (\n <Text variant=\"body-small\">No services found</Text>\n )}\n </>\n )}\n </DialogBody>\n <DialogFooter>\n <Button variant=\"secondary\" slot=\"close\">\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n onClick={handleSaveMapping}\n isDisabled={!selectedServiceId || isCreatingMapping}\n >\n {isCreatingMapping ? 'Saving...' : 'Save'}\n </Button>\n </DialogFooter>\n </Dialog>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MappingsDialog.esm.js","sources":["../../../src/components/PagerDutyPage/MappingsDialog.tsx"],"sourcesContent":["import {\n Dialog,\n DialogHeader,\n DialogBody,\n DialogFooter,\n Button,\n Select,\n Flex,\n Text,\n SearchField,\n RadioGroup,\n Radio,\n Box,\n TextField,\n} from '@backstage/ui';\nimport { Dispatch, useState, useEffect } from 'react';\nimport { BackstageEntity } from '../types';\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { pagerDutyApiRef } from '../../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { makeStyles } from '@material-ui/core';\nimport { useAccountContext } from './AccountContext';\nimport useDebounce from '../../hooks/useDebounce';\n\nconst useStyles = makeStyles(() => ({\n radioListContainer: {\n maxHeight: '300px',\n overflowY: 'auto',\n border: '1px solid var(--bui-border)',\n borderRadius: 'var(--bui-radius-2)',\n padding: 0,\n '& > div > div': {\n gap: 0,\n },\n '& label[data-rac]': {\n margin: 0,\n padding: 'var(--bui-spacing-2) var(--bui-spacing-3)',\n minHeight: '32px',\n borderBottom: '1px solid var(--bui-gray-2)',\n borderLeft: '3px solid transparent',\n cursor: 'pointer',\n transition: 'background-color 0.15s ease',\n display: 'flex',\n alignItems: 'center',\n '&:last-child': {\n borderBottom: 'none',\n },\n '&:hover': {\n backgroundColor: 'var(--bui-gray-1)',\n },\n '&[data-selected=\"true\"]': {\n backgroundColor: 'var(--bui-blue-1)',\n borderLeft: '3px solid var(--bui-blue-6)',\n fontWeight: 'var(--bui-font-weight-bold)',\n },\n },\n },\n}));\n\ninterface MappingsDialogProps {\n isOpen: boolean;\n setIsOpen: Dispatch<React.SetStateAction<boolean>>;\n entity: BackstageEntity | null;\n onMappingSuccess?: (isUnmapping: boolean) => void;\n}\n\nexport default function MappingsDialog({\n isOpen,\n setIsOpen,\n entity,\n onMappingSuccess,\n}: MappingsDialogProps) {\n const classes = useStyles();\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const queryClient = useQueryClient();\n const { selectedAccount } = useAccountContext();\n const [selectedServiceId, setSelectedServiceId] = useState<string>('');\n const [selectedTeamId, setSelectedTeamId] = useState<string>('');\n const [searchQuery, setSearchQuery] = useState<string>('');\n const debouncedSearchQuery = useDebounce(searchQuery);\n\n useEffect(() => {\n if (!isOpen) {\n setSelectedServiceId('');\n setSelectedTeamId('');\n setSearchQuery('');\n }\n }, [isOpen]);\n\n const accountParam = selectedAccount || undefined;\n\n const { data: teams, isLoading: isTeamsLoading } = useQuery({\n queryKey: ['pagerduty', 'getAllTeams', accountParam],\n queryFn: () => pagerDutyApi.getAllTeams(accountParam),\n enabled: isOpen,\n });\n\n const { data: services, isLoading: isServicesLoading } = useQuery({\n queryKey: ['pagerduty', 'getFilteredServices', selectedTeamId, debouncedSearchQuery, accountParam],\n queryFn: async () => {\n const teamIdsToSend = selectedTeamId ? [selectedTeamId] : undefined;\n const queryToSend = debouncedSearchQuery || undefined;\n const result = await pagerDutyApi.getFilteredServices(\n teamIdsToSend,\n queryToSend,\n 10,\n accountParam,\n );\n return result;\n },\n enabled: isOpen,\n });\n\n const { mutateAsync: createMapping, isPending: isCreatingMapping } =\n useMutation({\n mutationFn: async ({\n serviceId,\n integrationKey,\n entityRef,\n account,\n isUnmapping,\n }: {\n serviceId: string;\n integrationKey: string;\n entityRef: string;\n account: string;\n isUnmapping: boolean;\n }) => {\n await pagerDutyApi.storeServiceMapping(\n serviceId,\n integrationKey,\n entityRef,\n account,\n );\n return isUnmapping;\n },\n\n onSuccess: async (isUnmapping) => {\n queryClient.invalidateQueries({\n queryKey: ['pagerduty', 'enhancedEntityMappings'],\n });\n setIsOpen(false);\n setSelectedServiceId('');\n onMappingSuccess?.(isUnmapping);\n },\n });\n\n const handleSaveMapping = () => {\n if (!entity || !selectedServiceId) return;\n\n if (selectedServiceId === 'none') {\n const currentServiceId = entity.annotations?.['pagerduty.com/service-id'];\n const currentIntegrationKey = entity.annotations?.['pagerduty.com/integration-key'] || '';\n const account = entity.account || '';\n\n if (!currentServiceId) return;\n\n createMapping({\n serviceId: currentServiceId,\n integrationKey: currentIntegrationKey,\n entityRef: '',\n account: account,\n isUnmapping: true,\n });\n return;\n }\n\n const selectedService = services?.find(\n service => service.id === selectedServiceId,\n );\n\n if (!selectedService) return;\n\n const entityRef =\n `${entity.type}:${entity.namespace}/${entity.name}`.toLowerCase();\n\n createMapping({\n serviceId: selectedServiceId,\n integrationKey: '',\n entityRef: entityRef,\n account: selectedService.account ?? '',\n isUnmapping: false,\n });\n };\n\n // Prepare team options for Select\n const teamOptions = [\n { value: '', label: 'All Teams' },\n ...(teams?.map(team => ({\n value: team.id,\n label: team.name,\n })) || []),\n ];\n\n return (\n <Dialog isOpen={isOpen} onOpenChange={setIsOpen}>\n <DialogHeader>Update Entity Mapping</DialogHeader>\n <DialogBody>\n <Flex direction=\"column\" gap=\"2\" mb=\"4\">\n <Text variant=\"body-medium\" weight=\"bold\">\n Backstage Component\n </Text>\n <TextField\n value={entity?.name || ''}\n isReadOnly\n />\n </Flex>\n\n <Flex direction=\"column\" gap=\"2\" mb=\"4\">\n <Text variant=\"body-medium\" weight=\"bold\">\n Team\n </Text>\n <TextField\n value={entity?.owner || ''}\n isReadOnly\n />\n </Flex>\n\n <Box mb=\"3\">\n <Text variant=\"body-medium\" weight=\"bold\">\n Map to Service\n </Text>\n </Box>\n\n <Box mb=\"3\">\n <Select\n name=\"team\"\n isDisabled={isTeamsLoading || isCreatingMapping}\n label=\"PagerDuty Team (Optional)\"\n placeholder=\"All Teams\"\n options={teamOptions}\n value={selectedTeamId}\n searchPlaceholder='Search teams...'\n searchable\n onChange={value => {\n setSelectedTeamId(String(value || ''));\n setSelectedServiceId('');\n }}\n />\n </Box>\n\n <Flex direction=\"column\" gap=\"2\" mb=\"3\">\n <Text variant=\"body-medium\" weight=\"bold\">\n PagerDuty Services\n </Text>\n <Text variant=\"body-small\">\n Search by service name or service ID\n </Text>\n <SearchField\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder=\"Search\"\n />\n </Flex>\n\n {isServicesLoading ? (\n <Text>Loading services...</Text>\n ) : (\n <>\n <Box\n className={classes.radioListContainer}\n mb=\"2\"\n >\n <RadioGroup\n value={selectedServiceId}\n onChange={setSelectedServiceId}\n >\n {entity?.annotations?.['pagerduty.com/service-id'] && (\n <Radio key=\"none\" value=\"none\">\n (None)\n </Radio>\n )}\n {services && services\n .filter(service => service.id !== entity?.annotations?.['pagerduty.com/service-id'])\n .map(service => (\n <Radio key={service.id} value={service.id}>\n {service.name}\n </Radio>\n ))}\n </RadioGroup>\n </Box>\n {services && services.length > 0 ? (\n <Text variant=\"body-small\">\n Showing {services.length} result{services.length !== 1 ? 's' : ''}\n </Text>\n ) : (\n <Text variant=\"body-small\">No services found</Text>\n )}\n </>\n )}\n </DialogBody>\n <DialogFooter>\n <Button variant=\"secondary\" slot=\"close\">\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n onClick={handleSaveMapping}\n isDisabled={!selectedServiceId || isCreatingMapping}\n >\n {isCreatingMapping ? 'Saving...' : 'Save'}\n </Button>\n </DialogFooter>\n </Dialog>\n );\n}\n"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
5
5
  import { DiscoveryApi, FetchApi, ConfigApi } from '@backstage/core-plugin-api';
6
6
  import { ReactNode } from 'react';
7
7
  import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
8
- import { PagerDutySetting, PagerDutyEnhancedEntityMappingsResponse, PagerDutyServiceResponse, PagerDutyIncidentsResponse, PagerDutyChangeEventsResponse, PagerDutyService, PagerDutyTeam, PagerDutyServiceStandardsResponse, PagerDutyServiceMetricsResponse, PagerDutyUser, AutoMatchEntityMappingsResponse } from '@pagerduty/backstage-plugin-common';
8
+ import { PagerDutySetting, PagerDutyEnhancedEntityMappingsResponse, PagerDutyServiceResponse, PagerDutyIncidentsResponse, PagerDutyChangeEventsResponse, PagerDutyService, PagerDutyTeam, PagerDutyServiceStandardsResponse, PagerDutyServiceMetricsResponse, PagerDutyUser, AutoMatchStartResponse, AutoMatchStatusResponse } from '@pagerduty/backstage-plugin-common';
9
9
  export { AutoMatchBackstageComponent, AutoMatchEntityMapping, AutoMatchEntityMappingsResponse, AutoMatchPagerDutyService, AutoMatchScoreBreakdown, AutoMatchStatistics } from '@pagerduty/backstage-plugin-common';
10
10
 
11
11
  /** @public */
@@ -195,13 +195,17 @@ interface PagerDutyApi {
195
195
  */
196
196
  triggerAlarm(request: PagerDutyTriggerAlarmRequest): Promise<Response>;
197
197
  /**
198
- * Automatically matches unmapped entities to PagerDuty services.
198
+ * Starts an async auto-match job and returns a jobId to poll.
199
199
  */
200
- autoMatchEntityMappings(options: {
200
+ startAutoMatchEntityMappings(options: {
201
201
  team?: string;
202
202
  threshold: number;
203
203
  account?: string;
204
- }): Promise<AutoMatchEntityMappingsResponse>;
204
+ }): Promise<AutoMatchStartResponse>;
205
+ /**
206
+ * Fetches the current status (and result, when complete) of an auto-match job.
207
+ */
208
+ getAutoMatchStatus(jobId: string): Promise<AutoMatchStatusResponse>;
205
209
  /**
206
210
  * Fetches the list of configured PagerDuty accounts.
207
211
  */
@@ -275,11 +279,12 @@ declare class PagerDutyClient implements PagerDutyApi {
275
279
  getServiceMetricsByServiceId(serviceId: string, account?: string): Promise<PagerDutyServiceMetricsResponse>;
276
280
  getOnCallByPolicyId(policyId: string, account?: string): Promise<PagerDutyUser[]>;
277
281
  triggerAlarm(request: PagerDutyTriggerAlarmRequest): Promise<Response>;
278
- autoMatchEntityMappings(options: {
282
+ startAutoMatchEntityMappings(options: {
279
283
  team?: string;
280
284
  threshold: number;
281
285
  account?: string;
282
- }): Promise<AutoMatchEntityMappingsResponse>;
286
+ }): Promise<AutoMatchStartResponse>;
287
+ getAutoMatchStatus(jobId: string): Promise<AutoMatchStatusResponse>;
283
288
  getAccounts(): Promise<Array<{
284
289
  id: string;
285
290
  isDefault: boolean;
@@ -1,6 +1,6 @@
1
1
  var name = "@pagerduty/backstage-plugin";
2
2
  var description = "A Backstage plugin that integrates towards PagerDuty";
3
- var version = "0.19.0";
3
+ var version = "0.20.0";
4
4
  var main = "dist/index.esm.js";
5
5
  var types = "dist/index.d.ts";
6
6
  var license = "Apache-2.0";
@@ -49,7 +49,7 @@ var dependencies = {
49
49
  "@backstage/plugin-catalog-react": "backstage:^",
50
50
  "@backstage/plugin-home-react": "backstage:^",
51
51
  "@backstage/theme": "backstage:^",
52
- "@backstage/ui": "backstage:^",
52
+ "@backstage/ui": "^0.14.3",
53
53
  "@emotion/react": "^11.11.4",
54
54
  "@emotion/styled": "^11.11.5",
55
55
  "@material-ui/core": "^4.12.2",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pagerduty/backstage-plugin",
3
3
  "description": "A Backstage plugin that integrates towards PagerDuty",
4
- "version": "0.19.0",
4
+ "version": "0.20.0",
5
5
  "main": "./dist/index.esm.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "license": "Apache-2.0",
@@ -53,7 +53,7 @@
53
53
  "@backstage/plugin-catalog-react": "^1.21.6",
54
54
  "@backstage/plugin-home-react": "^0.1.34",
55
55
  "@backstage/theme": "^0.7.1",
56
- "@backstage/ui": "^0.11.2",
56
+ "@backstage/ui": "^0.14.3",
57
57
  "@emotion/react": "^11.11.4",
58
58
  "@emotion/styled": "^11.11.5",
59
59
  "@material-ui/core": "^4.12.2",
@@ -62,7 +62,7 @@
62
62
  "@mui/icons-material": "^5.15.19",
63
63
  "@mui/material": "^5.15.19",
64
64
  "@mui/x-date-pickers": "^7.6.1",
65
- "@pagerduty/backstage-plugin-common": "~0.3.0",
65
+ "@pagerduty/backstage-plugin-common": "~0.4.0",
66
66
  "@tanstack/react-query": "^5.40.1",
67
67
  "luxon": "^3.4.1",
68
68
  "material-react-table": "^2.13.0",