@pagerduty/backstage-plugin 0.19.0 → 0.21.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 +24 -0
- package/dist/alpha/pages.esm.js +41 -4
- package/dist/alpha/pages.esm.js.map +1 -1
- package/dist/alpha/plugin.esm.js +4 -3
- package/dist/alpha/plugin.esm.js.map +1 -1
- package/dist/alpha.d.ts +105 -26
- package/dist/api/client.esm.js +145 -3
- package/dist/api/client.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js +86 -40
- package/dist/components/PagerDutyPage/AutomaticMappingsDialog.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/ConfigurationPage.esm.js +119 -0
- package/dist/components/PagerDutyPage/ConfigurationPage.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFieldModal.esm.js +152 -0
- package/dist/components/PagerDutyPage/CustomFieldModal.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/ButtonTabs.esm.js +51 -0
- package/dist/components/PagerDutyPage/CustomFields/ButtonTabs.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/CustomFieldsEmptyState.esm.js +46 -0
- package/dist/components/PagerDutyPage/CustomFields/CustomFieldsEmptyState.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/CustomFieldsTabPanel.esm.js +154 -0
- package/dist/components/PagerDutyPage/CustomFields/CustomFieldsTabPanel.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/DeleteCustomFieldDialog.esm.js +63 -0
- package/dist/components/PagerDutyPage/CustomFields/DeleteCustomFieldDialog.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/SyncLogsFilters.esm.js +126 -0
- package/dist/components/PagerDutyPage/CustomFields/SyncLogsFilters.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/SyncLogsTab.esm.js +285 -0
- package/dist/components/PagerDutyPage/CustomFields/SyncLogsTab.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields/customFieldErrors.esm.js +13 -0
- package/dist/components/PagerDutyPage/CustomFields/customFieldErrors.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/CustomFields.esm.js +192 -0
- package/dist/components/PagerDutyPage/CustomFields.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/MappingsDialog.esm.js +2 -0
- package/dist/components/PagerDutyPage/MappingsDialog.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js +1 -1
- package/dist/components/PagerDutyPage/MappingsTable/MappingsTable.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js +15 -3
- package/dist/components/PagerDutyPage/MappingsTable/MappingsTableContent.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/MappingsTable/NameCell.esm.js +35 -0
- package/dist/components/PagerDutyPage/MappingsTable/NameCell.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js +26 -29
- package/dist/components/PagerDutyPage/MappingsTable/TableSkeleton.esm.js.map +1 -1
- package/dist/components/PagerDutyPage/ServiceMappingPage.esm.js +22 -0
- package/dist/components/PagerDutyPage/ServiceMappingPage.esm.js.map +1 -0
- package/dist/components/PagerDutyPage/index.esm.js +12 -127
- package/dist/components/PagerDutyPage/index.esm.js.map +1 -1
- package/dist/index.d.ts +60 -8
- package/dist/package.json.esm.js +1 -1
- package/package.json +17 -17
- package/dist/alpha/nav-items.esm.js +0 -21
- package/dist/alpha/nav-items.esm.js.map +0 -1
|
@@ -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 Result,\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 BackstageCustomFieldCreateRequest,\n BackstageCustomFieldUpdateRequest,\n BackstageCustomField,\n BackstageCustomFieldsResponse,\n CustomFieldSyncLogsResponse,\n CustomFieldSyncLogFilters,\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\nfunction parseCustomFieldError(\n error: unknown,\n fallbackMessage: string,\n): Result<BackstageCustomField> {\n if (error instanceof Error) {\n const msg = error.message;\n if (msg.includes('already been taken')) {\n return { status: 'error', data: null, error: 'A custom field with this name already exists' };\n }\n if (msg.toLowerCase().includes('entity path already exists')) {\n return { status: 'error', data: null, error: 'A custom field with this entity path already exists' };\n }\n if (msg.toLowerCase().includes('limit reached')) {\n return { status: 'error', data: null, error: 'Custom field limit reached. Maximum number of custom fields has been exceeded.' };\n }\n return { status: 'error', data: null, error: msg };\n }\n return { status: 'error', data: null, error: fallbackMessage };\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 async createCustomField(\n request: BackstageCustomFieldCreateRequest,\n account?: string,\n ): Promise<Result<BackstageCustomField>> {\n const body = JSON.stringify(request);\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 let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/custom-fields`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n try {\n const response = await this.request(url, options);\n const result = await response.json();\n return { status: 'ok', data: result.customField, error: null };\n } catch (error) {\n return parseCustomFieldError(error, 'Failed to create custom field');\n }\n }\n\n async getCustomFields(account?: string): Promise<BackstageCustomFieldsResponse> {\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/custom-fields`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n return await this.findByUrl<BackstageCustomFieldsResponse>(url);\n }\n\n async getSyncLogs(\n account?: string,\n options?: { limit?: number; offset?: number } & CustomFieldSyncLogFilters,\n ): Promise<CustomFieldSyncLogsResponse> {\n const params = new URLSearchParams();\n if (account) params.set('account', account);\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.offset !== undefined) params.set('offset', String(options.offset));\n if (options?.search) params.set('search', options.search);\n if (options?.severity) params.set('severity', options.severity);\n if (options?.customFieldName) params.set('customFieldName', options.customFieldName);\n if (options?.entityPath) params.set('entityPath', options.entityPath);\n if (options?.serviceName) params.set('serviceName', options.serviceName);\n\n const query = params.toString() ? `?${params.toString()}` : '';\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/custom-fields/sync-logs${query}`;\n\n return await this.findByUrl<CustomFieldSyncLogsResponse>(url);\n }\n\n async updateCustomField(\n id: number,\n request: BackstageCustomFieldUpdateRequest,\n account?: string,\n ): Promise<Result<BackstageCustomField>> {\n const body = JSON.stringify(request);\n\n const options = {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body,\n };\n\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/custom-fields/${id}`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n try {\n const response = await this.request(url, options);\n const result = await response.json();\n return { status: 'ok', data: result.customField, error: null };\n } catch (error) {\n return parseCustomFieldError(error, 'Failed to update custom field');\n }\n }\n\n async setCustomFieldEnabled(\n id: number,\n enabled: boolean,\n account?: string,\n ): Promise<Result<BackstageCustomField>> {\n const options = {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json; charset=UTF-8',\n Accept: 'application/json, text/plain, */*',\n },\n body: JSON.stringify({ enabled }),\n };\n\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/custom-fields/${id}/enabled`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n try {\n const response = await this.request(url, options);\n const result = await response.json();\n return { status: 'ok', data: result.customField, error: null };\n } catch (error) {\n return parseCustomFieldError(\n error,\n `Failed to ${enabled ? 'enable' : 'disable'} custom field`,\n );\n }\n }\n\n async deleteCustomField(\n id: number,\n account?: string,\n ): Promise<Result<void>> {\n const options = {\n method: 'DELETE',\n headers: {\n Accept: 'application/json, text/plain, */*',\n },\n };\n\n let url = `${await this.config.discoveryApi.getBaseUrl(\n 'pagerduty',\n )}/custom-fields/${id}`;\n\n if (account) {\n url = url.concat(`?account=${account}`);\n }\n\n try {\n await this.request(url, options);\n return { status: 'ok', data: undefined, error: null };\n } catch (error) {\n const result = parseCustomFieldError(error, 'Failed to delete custom field');\n return { status: 'error', data: null, error: result.error! };\n }\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":";;;;AAoDO,MAAM,0BAA0B,KAAA,CAAM;AAAC;AAGvC,MAAM,uBAAuB,KAAA,CAAM;AAAC;AAGpC,MAAM,kBAAkB,YAAA,CAA2B;AAAA,EACxD,EAAA,EAAI;AACN,CAAC;AAED,SAAS,qBAAA,CACP,OACA,eAAA,EAC8B;AAC9B,EAAA,IAAI,iBAAiB,KAAA,EAAO;AAC1B,IAAA,MAAM,MAAM,KAAA,CAAM,OAAA;AAClB,IAAA,IAAI,GAAA,CAAI,QAAA,CAAS,oBAAoB,CAAA,EAAG;AACtC,MAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,OAAO,8CAAA,EAA+C;AAAA,IAC9F;AACA,IAAA,IAAI,GAAA,CAAI,WAAA,EAAY,CAAE,QAAA,CAAS,4BAA4B,CAAA,EAAG;AAC5D,MAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,OAAO,qDAAA,EAAsD;AAAA,IACrG;AACA,IAAA,IAAI,GAAA,CAAI,WAAA,EAAY,CAAE,QAAA,CAAS,eAAe,CAAA,EAAG;AAC/C,MAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,OAAO,gFAAA,EAAiF;AAAA,IAChI;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,OAAO,GAAA,EAAI;AAAA,EACnD;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,OAAO,eAAA,EAAgB;AAC/D;AAGO,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,MAAM,iBAAA,CACJ,OAAA,EACA,OAAA,EACuC;AACvC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAEnC,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,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,CAAA,cAAA,CAAA;AAED,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAK,OAAO,CAAA;AAChD,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,MAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,MAAM,MAAA,CAAO,WAAA,EAAa,OAAO,IAAA,EAAK;AAAA,IAC/D,SAAS,KAAA,EAAO;AACd,MAAA,OAAO,qBAAA,CAAsB,OAAO,+BAA+B,CAAA;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,OAAA,EAA0D;AAC9E,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,CAAA,cAAA,CAAA;AAED,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,WAAA,CACJ,OAAA,EACA,OAAA,EACsC;AACtC,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,IAAA,IAAI,OAAA,EAAS,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,OAAO,CAAA;AAC1C,IAAA,IAAI,OAAA,EAAS,OAAO,MAAA,CAAO,GAAA,CAAI,SAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAC7D,IAAA,IAAI,OAAA,EAAS,WAAW,MAAA,EAAW,MAAA,CAAO,IAAI,QAAA,EAAU,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAC,CAAA;AAC9E,IAAA,IAAI,SAAS,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,QAAQ,MAAM,CAAA;AACxD,IAAA,IAAI,SAAS,QAAA,EAAU,MAAA,CAAO,GAAA,CAAI,UAAA,EAAY,QAAQ,QAAQ,CAAA;AAC9D,IAAA,IAAI,SAAS,eAAA,EAAiB,MAAA,CAAO,GAAA,CAAI,iBAAA,EAAmB,QAAQ,eAAe,CAAA;AACnF,IAAA,IAAI,SAAS,UAAA,EAAY,MAAA,CAAO,GAAA,CAAI,YAAA,EAAc,QAAQ,UAAU,CAAA;AACpE,IAAA,IAAI,SAAS,WAAA,EAAa,MAAA,CAAO,GAAA,CAAI,aAAA,EAAe,QAAQ,WAAW,CAAA;AAEvE,IAAA,MAAM,KAAA,GAAQ,OAAO,QAAA,EAAS,GAAI,IAAI,MAAA,CAAO,QAAA,EAAU,CAAA,CAAA,GAAK,EAAA;AAC5D,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC5C;AAAA,KACD,2BAA2B,KAAK,CAAA,CAAA;AAEjC,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAuC,GAAG,CAAA;AAAA,EAC9D;AAAA,EAEA,MAAM,iBAAA,CACJ,EAAA,EACA,OAAA,EACA,OAAA,EACuC;AACvC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAEnC,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,iCAAA;AAAA,QAChB,MAAA,EAAQ;AAAA,OACV;AAAA,MACA;AAAA,KACF;AAEA,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,kBAAkB,EAAE,CAAA,CAAA;AAErB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAK,OAAO,CAAA;AAChD,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,MAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,MAAM,MAAA,CAAO,WAAA,EAAa,OAAO,IAAA,EAAK;AAAA,IAC/D,SAAS,KAAA,EAAO;AACd,MAAA,OAAO,qBAAA,CAAsB,OAAO,+BAA+B,CAAA;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,MAAM,qBAAA,CACJ,EAAA,EACA,OAAA,EACA,OAAA,EACuC;AACvC,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,MAAA,EAAQ,OAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,iCAAA;AAAA,QAChB,MAAA,EAAQ;AAAA,OACV;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,SAAS;AAAA,KAClC;AAEA,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,kBAAkB,EAAE,CAAA,QAAA,CAAA;AAErB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAK,OAAO,CAAA;AAChD,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,MAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,MAAM,MAAA,CAAO,WAAA,EAAa,OAAO,IAAA,EAAK;AAAA,IAC/D,SAAS,KAAA,EAAO;AACd,MAAA,OAAO,qBAAA;AAAA,QACL,KAAA;AAAA,QACA,CAAA,UAAA,EAAa,OAAA,GAAU,QAAA,GAAW,SAAS,CAAA,aAAA;AAAA,OAC7C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,iBAAA,CACJ,EAAA,EACA,OAAA,EACuB;AACvB,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,MAAA,EAAQ,QAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA;AACV,KACF;AAEA,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAA,CAAa,UAAA;AAAA,MAC1C;AAAA,KACD,kBAAkB,EAAE,CAAA,CAAA;AAErB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IACxC;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,OAAO,CAAA;AAC/B,MAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,KAAA,CAAA,EAAW,OAAO,IAAA,EAAK;AAAA,IACtD,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,KAAA,EAAO,+BAA+B,CAAA;AAC3E,MAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,MAAM,IAAA,EAAM,KAAA,EAAO,OAAO,KAAA,EAAO;AAAA,IAC7D;AAAA,EACF;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
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
|
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
|
-
|
|
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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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { makeStyles, Typography, createStyles } from '@material-ui/core';
|
|
4
|
+
import { Box, Alert, Card, RadioGroup, Radio } from '@backstage/ui';
|
|
5
|
+
import { useApi, alertApiRef } from '@backstage/core-plugin-api';
|
|
6
|
+
import { NotFoundError } from '@backstage/errors';
|
|
7
|
+
import { pagerDutyApiRef } from '../../api/client.esm.js';
|
|
8
|
+
|
|
9
|
+
const SERVICE_DEPENDENCY_SYNC_STRATEGY = "settings::service-dependency-sync-strategy";
|
|
10
|
+
const useStyles = makeStyles(
|
|
11
|
+
() => createStyles({
|
|
12
|
+
cardStyles: {
|
|
13
|
+
padding: "15px",
|
|
14
|
+
marginTop: "8px",
|
|
15
|
+
paddingBottom: "20px"
|
|
16
|
+
},
|
|
17
|
+
textContainerStyles: {
|
|
18
|
+
marginTop: "16px"
|
|
19
|
+
},
|
|
20
|
+
linkStyles: {
|
|
21
|
+
color: "cadetblue"
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
);
|
|
25
|
+
const ConfigurationPage = () => {
|
|
26
|
+
const { cardStyles, textContainerStyles, linkStyles } = useStyles();
|
|
27
|
+
const pagerDutyApi = useApi(pagerDutyApiRef);
|
|
28
|
+
const alertApi = useApi(alertApiRef);
|
|
29
|
+
const [
|
|
30
|
+
selectedServiceDependencyStrategy,
|
|
31
|
+
setSelectedServiceDependencyStrategy
|
|
32
|
+
] = useState("disabled");
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
function fetchSetting() {
|
|
35
|
+
pagerDutyApi.getSetting(SERVICE_DEPENDENCY_SYNC_STRATEGY).then((result) => {
|
|
36
|
+
if (result !== void 0) {
|
|
37
|
+
setSelectedServiceDependencyStrategy(result.value);
|
|
38
|
+
}
|
|
39
|
+
}).catch((error) => {
|
|
40
|
+
if (error instanceof NotFoundError) {
|
|
41
|
+
setSelectedServiceDependencyStrategy("disabled");
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
fetchSetting();
|
|
46
|
+
}, [pagerDutyApi]);
|
|
47
|
+
const handleChange = async (value) => {
|
|
48
|
+
const previousValue = selectedServiceDependencyStrategy;
|
|
49
|
+
setSelectedServiceDependencyStrategy(value);
|
|
50
|
+
try {
|
|
51
|
+
await pagerDutyApi.storeSettings([
|
|
52
|
+
{
|
|
53
|
+
id: SERVICE_DEPENDENCY_SYNC_STRATEGY,
|
|
54
|
+
value
|
|
55
|
+
}
|
|
56
|
+
]);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
setSelectedServiceDependencyStrategy(previousValue);
|
|
59
|
+
alertApi.post({
|
|
60
|
+
message: `Failed to save service dependency synchronization strategy. ${error instanceof Error ? error.message : error}`,
|
|
61
|
+
severity: "error"
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
return /* @__PURE__ */ jsxs(Box, { pl: "20px", pr: "20px", children: [
|
|
66
|
+
/* @__PURE__ */ jsx(
|
|
67
|
+
Alert,
|
|
68
|
+
{
|
|
69
|
+
className: textContainerStyles,
|
|
70
|
+
status: "warning",
|
|
71
|
+
icon: true,
|
|
72
|
+
title: "Changing this setting will affect how your service dependencies are synchronized and may cause data loss.",
|
|
73
|
+
description: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
74
|
+
"Check the",
|
|
75
|
+
" ",
|
|
76
|
+
/* @__PURE__ */ jsx(
|
|
77
|
+
"a",
|
|
78
|
+
{
|
|
79
|
+
className: linkStyles,
|
|
80
|
+
href: "https://pagerduty.github.io/backstage-plugin-docs/index.html",
|
|
81
|
+
target: "_blank",
|
|
82
|
+
rel: "noopener noreferrer",
|
|
83
|
+
children: "documentation"
|
|
84
|
+
}
|
|
85
|
+
),
|
|
86
|
+
" ",
|
|
87
|
+
"for more information."
|
|
88
|
+
] })
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
/* @__PURE__ */ jsxs(
|
|
92
|
+
Card,
|
|
93
|
+
{
|
|
94
|
+
title: "Service dependency synchronization preferences",
|
|
95
|
+
className: cardStyles,
|
|
96
|
+
children: [
|
|
97
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h6", children: "Service dependency synchronization strategy" }),
|
|
98
|
+
/* @__PURE__ */ jsxs(
|
|
99
|
+
RadioGroup,
|
|
100
|
+
{
|
|
101
|
+
label: "Select the main source of truth for your service dependencies",
|
|
102
|
+
value: selectedServiceDependencyStrategy,
|
|
103
|
+
onChange: (value) => void handleChange(value),
|
|
104
|
+
children: [
|
|
105
|
+
/* @__PURE__ */ jsx(Radio, { value: "backstage" /* backstage */, children: "Backstage" }),
|
|
106
|
+
/* @__PURE__ */ jsx(Radio, { value: "pagerduty" /* pagerduty */, children: "PagerDuty" }),
|
|
107
|
+
/* @__PURE__ */ jsx(Radio, { value: "both" /* both */, children: "Both" }),
|
|
108
|
+
/* @__PURE__ */ jsx(Radio, { value: "disabled" /* disabled */, children: "Disabled" })
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
] });
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export { ConfigurationPage };
|
|
119
|
+
//# sourceMappingURL=ConfigurationPage.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigurationPage.esm.js","sources":["../../../src/components/PagerDutyPage/ConfigurationPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { createStyles, makeStyles, Typography } from '@material-ui/core';\nimport { Card, RadioGroup, Radio, Box, Alert } from '@backstage/ui';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\nimport { NotFoundError } from '@backstage/errors';\nimport { pagerDutyApiRef } from '../../api';\n\nenum StoreSettings {\n backstage = 'backstage',\n pagerduty = 'pagerduty',\n both = 'both',\n disabled = 'disabled',\n}\n\nconst SERVICE_DEPENDENCY_SYNC_STRATEGY =\n 'settings::service-dependency-sync-strategy';\n\nconst useStyles = makeStyles(() =>\n createStyles({\n cardStyles: {\n padding: '15px',\n marginTop: '8px',\n paddingBottom: \"20px\"\n },\n textContainerStyles: {\n marginTop: '16px',\n },\n linkStyles: {\n color: 'cadetblue',\n },\n }),\n);\n\n/** @public */\nexport const ConfigurationPage = () => {\n const { cardStyles, textContainerStyles, linkStyles } = useStyles();\n const pagerDutyApi = useApi(pagerDutyApiRef);\n const alertApi = useApi(alertApiRef);\n const [\n selectedServiceDependencyStrategy,\n setSelectedServiceDependencyStrategy,\n ] = useState('disabled');\n\n useEffect(() => {\n function fetchSetting() {\n pagerDutyApi\n .getSetting(SERVICE_DEPENDENCY_SYNC_STRATEGY)\n .then(result => {\n if (result !== undefined) {\n setSelectedServiceDependencyStrategy(result.value);\n }\n })\n .catch(error => {\n if (error instanceof NotFoundError) {\n // If the setting is not found, set the default value to \"disabled\"\n setSelectedServiceDependencyStrategy('disabled');\n }\n });\n }\n\n fetchSetting();\n }, [pagerDutyApi]);\n\n const handleChange = async (value: StoreSettings) => {\n // Optimistically reflect the selection, remembering the previous value so we\n // can roll back if the save fails — otherwise the radio would show a setting\n // that was never persisted and silently revert on the next page load.\n const previousValue = selectedServiceDependencyStrategy;\n setSelectedServiceDependencyStrategy(value);\n\n try {\n await pagerDutyApi.storeSettings([\n {\n id: SERVICE_DEPENDENCY_SYNC_STRATEGY,\n value,\n },\n ]);\n } catch (error) {\n setSelectedServiceDependencyStrategy(previousValue);\n alertApi.post({\n message: `Failed to save service dependency synchronization strategy. ${\n error instanceof Error ? error.message : error\n }`,\n severity: 'error',\n });\n }\n };\n\n return (\n <Box pl=\"20px\" pr=\"20px\">\n <Alert\n className={textContainerStyles}\n status=\"warning\"\n icon\n title=\"Changing this setting will affect how your service dependencies are synchronized and may cause data loss.\"\n description={\n <>\n Check the{' '}\n <a\n className={linkStyles}\n href=\"https://pagerduty.github.io/backstage-plugin-docs/index.html\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n documentation\n </a>{' '}\n for more information.\n </>\n }\n />\n <Card\n title=\"Service dependency synchronization preferences\"\n className={cardStyles}\n >\n <Typography variant=\"h6\">\n Service dependency synchronization strategy\n </Typography>\n <RadioGroup\n label=\"Select the main source of truth for your service dependencies\"\n value={selectedServiceDependencyStrategy}\n onChange={value => void handleChange(value as StoreSettings)}\n >\n <Radio value={StoreSettings.backstage}>Backstage</Radio>\n <Radio value={StoreSettings.pagerduty}>PagerDuty</Radio>\n <Radio value={StoreSettings.both}>Both</Radio>\n <Radio value={StoreSettings.disabled}>Disabled</Radio>\n </RadioGroup>\n </Card>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|