@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
1 lines • 241 kB
Source Map (JSON)
{"version":3,"file":"c8y-ngx-components-alarms.mjs","sources":["../../alarms/alarm-details-custom-button/alarm-details-button.service.ts","../../alarms/alarm-details-custom-button/alarm-details-button.pipe.ts","../../alarms/alarm-details.service.ts","../../alarms/alarms.model.ts","../../alarms/ng1-smart-rules-upgrade.service.ts","../../alarms/alarms-view.service.ts","../../alarms/alarm-severity-to-icon.pipe.ts","../../alarms/alarm-status-to-icon.pipe.ts","../../alarms/audit-changes-message.pipe.ts","../../alarms/alarm-details.component.ts","../../alarms/alarm-details.component.html","../../alarms/alarm-empty.component.ts","../../alarms/alarm-empty.component.html","../../alarms/alarm-info.component.ts","../../alarms/alarm-info.component.html","../../alarms/alarm-list-custom-indicator/alarm-list-indicator.service.ts","../../alarms/alarm-list-custom-indicator/alarm-list-indicator.pipe.ts","../../alarms/alarm-severities-to-title.pipe.ts","../../alarms/alarm-severity-to-label.pipe.ts","../../alarms/alarm-status-to-label.pipe.ts","../../alarms/alarms-filter.component.ts","../../alarms/alarms-filter.component.html","../../alarms/alarms-icon.component.ts","../../alarms/alarms-icon.component.html","../../alarms/alarms-interval-refresh.component.ts","../../alarms/alarms-interval-refresh.component.html","../../alarms/alarms-list.component.ts","../../alarms/alarms-list.component.html","../../alarms/alarms-date-filter.component.ts","../../alarms/alarms-date-filter.component.html","../../alarms/alarms-type-filter.component.ts","../../alarms/alarms-type-filter.component.html","../../alarms/alarms.component.ts","../../alarms/alarms.component.html","../../alarms/alarms.helper.ts","../../alarms/alarms.module.ts","../../alarms/c8y-ngx-components-alarms.ts"],"sourcesContent":["import { IAlarm, IManagedObject } from '@c8y/client';\nimport { combineLatest, Observable } from 'rxjs';\nimport { filter, map, startWith, switchMap } from 'rxjs/operators';\nimport { Injectable } from '@angular/core';\nimport { PluginsResolveService, ServiceRegistry } from '@c8y/ngx-components';\nimport { AlarmDetailsButton } from '../alarms.model';\nimport { sortBy } from 'lodash-es';\n\n@Injectable({ providedIn: 'root' })\n/**\n * A service to retrieve custom buttons for the alarm details view.\n */\nexport class AlarmDetailsButtonService {\n constructor(\n private serviceRegistry: ServiceRegistry,\n private pluginsResolver: PluginsResolveService\n ) {}\n\n get$(alarm: IAlarm, source: IManagedObject): Observable<AlarmDetailsButton[]> {\n const providers$ = this.pluginsResolver.allPluginsLoaded$.pipe(\n filter(Boolean),\n map(() => {\n return this.serviceRegistry.get('alarmDetailsButton');\n })\n );\n\n return providers$.pipe(\n switchMap(providers => {\n const observables$ = providers.map(provider =>\n provider.getAlarmDetailsButton$(alarm, source).pipe(startWith(false))\n );\n return combineLatest(observables$);\n }),\n map(indicators => {\n return indicators.filter(Boolean) as AlarmDetailsButton[];\n }),\n map(indicators => sortBy(indicators, this.byPriority))\n );\n }\n\n private byPriority(item: AlarmDetailsButton) {\n if (item.priority === undefined) {\n return 0;\n }\n return -item.priority;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { IAlarm, IManagedObject } from '@c8y/client';\nimport { Observable } from 'rxjs';\nimport { AlarmDetailsButtonService } from './alarm-details-button.service';\nimport { AlarmDetailsButton } from '../alarms.model';\n\n@Pipe({\n standalone: true,\n name: 'alarmDetailsButton',\n pure: true\n})\n/**\n * A pipe to provide custom buttons for the alarm details view.\n *\n * Will call `get$()` method of `AlarmDetailsButtonService` to get the custom buttons for the provided alarm.\n */\nexport class AlarmDetailsButtonPipe implements PipeTransform {\n constructor(private alarmDetailsButtonService: AlarmDetailsButtonService) {}\n\n transform(alarm: IAlarm, source: IManagedObject): Observable<AlarmDetailsButton[]> {\n return this.alarmDetailsButtonService.get$(alarm, source);\n }\n}\n","import { Injectable } from '@angular/core';\nimport { AlarmStatus, AlarmStatusType, IAuditRecord, IChange } from '@c8y/client';\nimport { Permissions } from '@c8y/ngx-components';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class AlarmDetailsService {\n private readonly STATUS_ATTRIBUTE = 'status';\n\n constructor(private permissions: Permissions) {}\n\n /**\n * Retrieves the username of the user who acknowledged an alarm status.\n *\n * This method checks if the provided status is equal to the acknowledged\n * status. If it is not, or if the\n * audit log is empty or the first log item does not contain a user, the\n * method returns a default value ('--').\n *\n * If the status is the acknowledged status and the audit log contains valid\n * records, the method iterates over the audit records in reverse order\n * (starting from the most recent). It finds the first record where the\n * status attribute (defined by this.STATUS_ATTRIBUTE) has been changed to\n * the acknowledged status. The method then returns the username of the user\n * who made this change.\n *\n * If no such change is found in the audit records, it returns the username\n * from the first record of the audit log.\n *\n * There can be multiple audit logs with ACKNOWLEDGED status.\n *\n * @param status - The current status of the alarm.\n * @param auditLog - An array of audit records to process.\n * @returns The username of the user who acknowledged the status\n * or '--' if the status is not acknowledged or audit log is invalid.\n */\n getAcknowledgedBy(status: AlarmStatusType, auditLog: IAuditRecord[]): string {\n let acknowledgedBy = '--';\n\n if (status !== AlarmStatus.ACKNOWLEDGED || !auditLog || !auditLog[0]?.user) {\n return acknowledgedBy;\n }\n\n acknowledgedBy = auditLog[0].user;\n\n return auditLog.reduceRight((acc, auditLogItem) => {\n const changes = Array.from(auditLogItem.changes || []);\n const acknowledgedStatusChange = changes.find(\n (change: IChange) =>\n change.attribute === this.STATUS_ATTRIBUTE && change.newValue === AlarmStatus.ACKNOWLEDGED\n );\n return (acknowledgedStatusChange && auditLogItem.user) || acc;\n }, acknowledgedBy);\n }\n\n /**\n * Calculates the acknowledge time from a list of audit records.\n *\n * This method iterates over the provided audit records in reverse order\n * (starting from the most recent) and finds the first record where a\n * specific status attribute (defined by this.STATUS_ATTRIBUTE) has been\n * acknowledged. It then returns the creation time of that record.\n *\n * If no such record is found, the method returns the creation time of the\n * first audit record. If the audit record list is empty, it returns null.\n *\n * There can be multiple audit logs with ACKNOWLEDGED status.\n *\n * @param auditLog - An array of audit records to process.\n * @returns The creation time of the acknowledged record,\n * the creation time of the first record if no acknowledged record is found,\n * or null if the audit log is empty.\n */\n getAcknowledgeTime(auditLog: IAuditRecord[]): string | null {\n const initialValue = auditLog.length ? auditLog[0].creationTime : null;\n\n return auditLog.reduceRight((acc, auditLogItem) => {\n const changes = Array.from(auditLogItem.changes || []);\n const acknowledgedStatusChange = changes.find(\n (change: IChange) =>\n change.attribute === this.STATUS_ATTRIBUTE && change.newValue === AlarmStatus.ACKNOWLEDGED\n );\n return acknowledgedStatusChange ? auditLogItem.creationTime : acc;\n }, initialValue);\n }\n\n /**\n * Retrieves the end time of an event from an audit log.\n *\n * The method processes the provided audit log to find the first instance\n * (starting from the most recent record) where the status was changed to 'CLEARED'.\n * It iterates over the audit records and\n * checks the changes in each record to find this status change.\n *\n * If a record with the CLEARED status is found, the method returns the creation time\n * of that record. If the entire audit log is processed without finding a CLEARED status,\n * the creation time of the first audit log record is returned.\n *\n * If the audit log is empty or null, the method returns null.\n *\n * There can be only one audit log with CLEARED status.\n *\n * @param auditLog - An array of audit records to process.\n * @returns The creation time of the record with the CLEARED status,\n * the creation time of the first record if no CLEARED status is found,\n * or null if the audit log is empty or null.\n */\n getEndTime(auditLog: IAuditRecord[]): string | null {\n if (!auditLog || auditLog.length === 0) {\n return null;\n }\n\n let latestClearedAuditTime = null;\n\n for (const auditLogItem of auditLog) {\n const changes = Array.from(auditLogItem.changes || []);\n const clearedStatusChange = changes.find(\n change =>\n change.attribute === this.STATUS_ATTRIBUTE && change.newValue === AlarmStatus.CLEARED\n );\n\n if (clearedStatusChange) {\n if (!latestClearedAuditTime || auditLogItem.creationTime > latestClearedAuditTime) {\n latestClearedAuditTime = auditLogItem.creationTime;\n }\n }\n }\n\n return latestClearedAuditTime || auditLog[0].creationTime;\n }\n\n checkIfHasAnyRoleAllowingToCreateSmartRule(): boolean {\n const ROLES_ALLOWING_SMART_RULE_CREATION = [\n [\n Permissions.ROLE_INVENTORY_ADMIN,\n Permissions.ROLE_INVENTORY_CREATE,\n Permissions.ROLE_MANAGED_OBJECT_ADMIN,\n Permissions.ROLE_MANAGED_OBJECT_CREATE\n ],\n [Permissions.ROLE_CEP_MANAGEMENT_ADMIN, Permissions.ROLE_SMARTRULE_ADMIN]\n ];\n\n return (\n this.permissions.hasAnyRole(ROLES_ALLOWING_SMART_RULE_CREATION[0]) &&\n this.permissions.hasAnyRole(ROLES_ALLOWING_SMART_RULE_CREATION[1])\n );\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport {\n AlarmStatus,\n AlarmStatusSettings,\n AlarmStatusType,\n IAlarm,\n IManagedObject,\n Severity,\n SeverityFilter,\n SeverityType\n} from '@c8y/client';\nimport {\n DateTimeContext,\n gettext,\n NavigatorNode,\n NavigatorNodeData,\n Route\n} from '@c8y/ngx-components';\nimport { QueryParamsHandling } from '@angular/router';\nimport type { SupportedIcons } from '@c8y/ngx-components/icon-selector/icons';\nimport { Observable } from 'rxjs';\nimport {\n INTERVALS,\n INTERVAL_TITLES,\n AlarmFilterInterval\n} from '@c8y/ngx-components/interval-picker';\n\nexport interface AlarmsModuleConfig {\n /**\n * Indicates whether the application is a combination of Angular and AngularJS.\n * @optional\n */\n hybrid?: boolean;\n\n /**\n * The root node of the navigator, which can be either a `NavigatorNode` or `NavigatorNodeData`.\n * This serves as the entry point for navigation structure for Alarms views.\n * @optional\n */\n rootNavigatorNode?: NavigatorNode | NavigatorNodeData;\n\n /**\n * An array of `Route` objects representing the navigation routes available.\n * Each route defines a navigation path and its associated components related to Alarms.\n * @optional\n */\n route?: Route[];\n}\n\nexport const ALARMS_MODULE_CONFIG = new InjectionToken('AlarmsModuleConfig');\n\nexport type AlarmCount = { [key in SeverityType]: number };\n\nexport const ALARM_STATUS_ICON = {\n ALERT_IDLE: 'c8y-alert-idle',\n BELL_SLASH: 'bell-slash',\n BELL: 'bell'\n} as const;\n\nexport type AlarmStatusIcon = (typeof ALARM_STATUS_ICON)[keyof typeof ALARM_STATUS_ICON];\n\n/**\n * A lookup table to map alarm statuses to corresponding icons.\n */\nexport const AlarmIconMap: Record<AlarmStatusType, AlarmStatusIcon> = {\n [AlarmStatus.CLEARED]: ALARM_STATUS_ICON.ALERT_IDLE,\n [AlarmStatus.ACKNOWLEDGED]: ALARM_STATUS_ICON.BELL_SLASH,\n [AlarmStatus.ACTIVE]: ALARM_STATUS_ICON.BELL\n} as const;\n\nexport const ALARM_SEVERITY_ICON = {\n CIRCLE: 'circle',\n HIGH_PRIORITY: 'high-priority',\n WARNING: 'warning',\n EXCLAMATION_CIRCLE: 'exclamation-circle'\n} as const;\n\nexport const HELP_ICON = 'help';\n\nexport type AlarmSeverityIcon = (typeof ALARM_SEVERITY_ICON)[keyof typeof ALARM_SEVERITY_ICON];\n/**\n * A lookup table to map alarm severity types to corresponding icons.\n */\nexport const ALARM_SEVERITY_ICON_MAP: Record<SeverityType, AlarmSeverityIcon> = {\n [Severity.CRITICAL]: ALARM_SEVERITY_ICON.EXCLAMATION_CIRCLE,\n [Severity.MAJOR]: ALARM_SEVERITY_ICON.WARNING,\n [Severity.MINOR]: ALARM_SEVERITY_ICON.HIGH_PRIORITY,\n [Severity.WARNING]: ALARM_SEVERITY_ICON.CIRCLE\n} as const;\n\nexport type AlarmListFormFilters = {\n showCleared: boolean;\n severityOptions: SeverityFilter;\n selectedDates?: DateTimeContext;\n};\n\n/**\n * Extended interval titles with an additional title for the case when no date is selected.\n */\nexport const INTERVAL_TITLES_EXTENDED: Record<AlarmFilterInterval['id'], string> = {\n ...INTERVAL_TITLES,\n none: gettext('No date filter')\n};\n\nexport const INTERVALS_EXTENDED: AlarmFilterInterval[] = [\n {\n id: 'none',\n title: gettext('No date filter')\n },\n ...INTERVALS\n];\n\nexport type WidgetTimeContextStateExtended = {\n date: DateTimeContext;\n interval: AlarmFilterInterval['id'];\n};\n\nexport type SelectedAlarm = IAlarm | null;\n\nexport const DEFAULT_ALARM_COUNTS: AlarmCount = { CRITICAL: 0, MAJOR: 0, MINOR: 0, WARNING: 0 };\n\nexport const DEFAULT_SEVERITY_VALUES: SeverityFilter = {\n [Severity.CRITICAL]: true,\n [Severity.MAJOR]: true,\n [Severity.MINOR]: true,\n [Severity.WARNING]: true\n};\n\nexport const DEFAULT_STATUS_VALUES: AlarmStatusSettings = {\n [AlarmStatus.ACTIVE]: true,\n [AlarmStatus.ACKNOWLEDGED]: true,\n [AlarmStatus.CLEARED]: true\n};\n\nexport const ALARMS_PATH = 'alarms';\n\nexport type CustomFragment = {\n [key: string]: unknown;\n};\n\n/**\n * Default properties of a alarm. Used to extract the custom properties from a Alarm object.\n */\nexport const ALARM_DEFAULT_PROPERTIES = [\n 'severity',\n 'source',\n 'type',\n 'time',\n 'text',\n 'id',\n 'status',\n 'count',\n 'name',\n 'history',\n 'self',\n 'creationTime',\n 'firstOccurrenceTime',\n 'lastUpdated'\n] as const satisfies ReadonlyArray<keyof IAlarm>;\n\nexport const THROTTLE_REALTIME_REFRESH = 1_000;\n\n/**\n * Represents the navigation options for an alarm component.\n */\nexport type AlarmNavigationOptions = {\n /**\n * Defines if the alarm should navigate to a detail view when clicked.\n */\n allowNavigationToAlarmsView: boolean;\n /**\n * Defines if the component should try to determine the context to navigate\n * to the correct alarm detail view or not. If set to true, the component will\n * not try to determine the context and will always navigate to the all alarms view.\n */\n alwaysNavigateToAllAlarms: boolean;\n /**\n * Defines if the cleared query parameter should be included in the navigation if\n * the alarm is cleared.\n */\n includeClearedQueryParams: boolean;\n /**\n * Determines how query parameters should be handled during navigation.\n * This property can be set to one of three values:\n *\n * - `\"merge\"` : Merge new parameters with current parameters.\n * - `\"preserve\"` : Preserve current parameters.\n * - `\"\"` : Replace current parameters with new parameters. This is the default behavior.\n */\n queryParamsHandling: QueryParamsHandling;\n};\n\nexport interface AlarmDetailsButton {\n additionalButtonClasses?: string;\n title: string;\n icon: SupportedIcons;\n additionalIconClasses?: string;\n label?: string;\n disabled?: boolean;\n /**\n * Action to be executed when the button is clicked.\n * @param alarm The alarm to apply this action to\n * @returns A boolean or a promise that resolves to a boolean or to the updated alarm. If the result is true, a reload will be triggered. If the result is an alarm, the alarm will be updated with the new values.\n */\n action: (alarm: IAlarm) => boolean | Promise<boolean | IAlarm>;\n priority?: number;\n}\n\nexport interface AlarmListIndicatorBase {\n priority?: number;\n}\n\nexport interface AlarmListIndicatorIcon extends AlarmListIndicatorBase {\n icon: SupportedIcons;\n title: string;\n class?: string;\n}\n\nexport type AlarmListIndicator = AlarmListIndicatorIcon;\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace CumulocityServiceRegistry {\n interface SpecificExtensionKeys {\n alarmDetailsButton: AlarmDetailsButtonProvider;\n alarmListIndicator: AlarmListIndicatorProvider;\n }\n\n interface AlarmDetailsButtonProvider {\n /**\n * Determines whether the button should be shown for a given alarm.\n * @param alarm The alarm for which to determine button visibility.\n * @param source The managed object associated with the alarm.\n * @returns The button details or false.\n */\n getAlarmDetailsButton$(\n alarm: IAlarm,\n source: IManagedObject\n ): Observable<AlarmDetailsButton | false>;\n }\n\n interface AlarmListIndicatorProvider {\n /**\n * Determines whether the indicator should be shown for a given alarm.\n * @param alarm The alarm for which to determine indicator visibility.\n * @returns The indicator details or false.\n */\n getAlarmListIndicator$(alarm: IAlarm): Observable<AlarmListIndicator | false>;\n }\n }\n}\n","/**\n * This service is a duplicate of smart-rules-service with slight name change.\n * Duplicating allows to pass 'Verify App tutorial' job.\n * Name renames allows to pass 'Reusable build codex' job.\n * Overall this service is considered as a workaround.\n * In ticket MTM-58985 we will investigate if it's possible to remove this service\n * along with making failing jobs pass.\n */\nexport abstract class Ng1SmartRulesUpgradeService {\n abstract permissionsCfgs;\n abstract addNewForOutputOperationWithUI(operation);\n abstract addNewForInputAlarmAndOutputUserWithUI(alarm, user);\n}\n\nexport function SmartRulesUpgradeServiceFactory(injector: any) {\n return injector.get('smartRulesSvc');\n}\n\nexport const smartRulesUpgradeServiceProvider = {\n provide: Ng1SmartRulesUpgradeService,\n useFactory: SmartRulesUpgradeServiceFactory,\n deps: ['$injector']\n};\n","import { Injectable } from '@angular/core';\nimport {\n ALARM_STATUS_LABELS,\n AlarmQueryFilter,\n AlarmService,\n AlarmStatus,\n AlarmStatusType,\n IAlarm,\n IResultList,\n Severity,\n SeverityFilter,\n SeverityType\n} from '@c8y/client';\nimport {\n ApplicationOptions,\n ContextData,\n DateTimeContext,\n OptionsService,\n ViewContext,\n gettext\n} from '@c8y/ngx-components';\nimport { BehaviorSubject, Observable, Subject } from 'rxjs';\nimport { ALARMS_PATH, INTERVALS_EXTENDED } from './alarms.model';\nimport { AlarmFilterInterval } from '@c8y/ngx-components/interval-picker';\n\n/**\n * Service for managing and retrieving alarms data within the alarms view.\n *\n * The `AlarmsViewService` provides functionality to interact with alarms,\n * including filtering, counting, and translation-related operations in an alarms view.\n *\n * This service relies on the `AlarmService` for fetching alarm data and the `OptionsService`\n * for configuring alarms view options.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class AlarmsViewService {\n readonly ALARM_REFRESH_TYPE_KEY: keyof ApplicationOptions = 'alarmsRefreshType';\n readonly DEFAULT_INTERVAL_VALUE = 30_000;\n readonly DEFAULT_REFRESH_OPTION_VALUE = 'interval';\n readonly DEFAULT_INTERVAL_VALUES = [5_000, 10_000, 15_000, 30_000, 60_000];\n readonly REALTIME_UPDATE_ALARMS_MESSAGE = gettext('The list was updated, click to refresh.');\n\n isIntervalEnabled$: Observable<boolean>;\n reloadAlarmsList$ = new Subject<void>();\n\n private _isIntervalEnabled: BehaviorSubject<boolean>;\n\n constructor(\n private alarmService: AlarmService,\n private optionsService: OptionsService\n ) {\n if (this.isIntervalRefresh()) {\n this._isIntervalEnabled = new BehaviorSubject<boolean>(true);\n this.isIntervalEnabled$ = this._isIntervalEnabled.asObservable();\n }\n }\n\n /**\n * Emits a subject to initialize the alarms reloading.\n */\n updateAlarmList(): void {\n this.reloadAlarmsList$.next();\n }\n\n /**\n * Retrieves a list of alarms filtered by specified severities and other optional query filters.\n *\n * @param severities an array of severities to filter the alarms.\n * @param showCleared flag indicating whether to show cleared alarms. Defaults to false.\n * @param selectedDates an array of two dates to filter alarms by creation and last update dates.\n * @param filter additional query filters for retrieving alarms.\n *\n * @returns A promise that resolves to a list of alarms satisfying the specified filters.\n */\n retrieveFilteredAlarms(\n severities: SeverityType[],\n showCleared = false,\n selectedDates?: [Date, Date],\n filter?: AlarmQueryFilter\n ): Promise<IResultList<IAlarm>> {\n const severitiesQuery = this.getSeverityQueryParameter(severities);\n const statusesQuery = this.getStatusQueryParameter(showCleared);\n\n const _filter: AlarmQueryFilter = {\n pageSize: 50,\n withTotalPages: true,\n ...(severitiesQuery && { severity: severitiesQuery }),\n ...(statusesQuery && { status: statusesQuery }),\n ...(selectedDates && {\n lastUpdatedFrom: selectedDates[0].toISOString(),\n createdTo: selectedDates[1].toISOString()\n }),\n ...filter\n };\n return this.alarmService.list(_filter);\n }\n\n retrieveAlarmsByDate(dates: DateTimeContext) {\n return this.alarmService.list({\n lastUpdatedFrom: dates[0].toISOString(),\n createdTo: dates[1].toISOString(),\n pageSize: 50,\n withTotalPages: true\n });\n }\n\n /**\n * Updates the state to enable or disable intervals.\n * @param value - A boolean value to indicate whether to enable intervals.\n */\n updateIntervalState(value: boolean): void {\n this._isIntervalEnabled?.next(value);\n }\n\n /**\n * Fetches the count of alarms filtered by severity and clearance status.\n *\n * @param severity - The severity level to filter by (e.g., CRITICAL, MAJOR, etc.).\n * @param showCleared - Whether or not to include cleared alarms in the count.\n * @param filter - Additional filter criteria for alarms.\n *\n * @returns A promise that resolves to the number of alarms that match the filter criteria.\n *\n */\n async getAlarmsCountBySeverity(\n severity: SeverityType,\n showCleared: boolean,\n filter?: AlarmQueryFilter\n ): Promise<number> {\n const statusesQuery = this.getStatusQueryParameter(showCleared);\n const _filter: AlarmQueryFilter = {\n ...(severity && { severity: severity }),\n ...(statusesQuery && { status: statusesQuery }),\n ...filter\n };\n const { data } = await this.alarmService.count(_filter);\n\n return data;\n }\n\n /**\n * Retrieves the current alarms refresh type from the OptionsService\n * and determines whether it is set to \"interval\".\n *\n * @returns `true` if the alarms refresh type is \"interval,\" otherwise `false`.\n */\n isIntervalRefresh(): boolean {\n const value = this.optionsService.get(this.ALARM_REFRESH_TYPE_KEY, 'interval');\n return value === 'interval';\n }\n\n /**\n * Updates the list of selected severities based on the new severity filter.\n *\n * @param severityUpdates - The object representing the updates to each severity.\n *\n * @returns An array representing the updated selected severities.\n */\n updateSelectedSeverities(severityUpdates: SeverityFilter): SeverityType[] {\n return (Object.keys(severityUpdates) as SeverityType[])\n .filter(key => severityUpdates[key])\n .map(key => key.toUpperCase() as SeverityType);\n }\n\n /**\n * Clears all active alarms of the selected severities.\n *\n * This method clears all active alarms for the given list of severities by making bulk update calls. If no severities are selected, it defaults to using all available severities.\n * It works by sending a series of update requests for each severity and returns a Promise that resolves with an object indicating if all alarms were resolved immediately.\n *\n * @param selectedSeverities An array of severities to be cleared. If not provided, all severities will be cleared.\n * @param sourceId - Identifier for the source associated with the alarms to be cleared.\n *\n * @returns A Promise that resolves with an object with a flag `resolvedImmediately`. The flag is true if all alarms for all selected severities were cleared successfully; otherwise false.\n *\n * **Example**\n * ```typescript\n * const severitiesToClear: SeverityType[] = [Severity.MAJOR, Severity.MINOR];\n *\n * clearAllActiveAlarms(severitiesToClear).then(({ resolvedImmediately }) => {\n * if (resolvedImmediately) {\n * console.log('All selected alarms were cleared successfully.');\n * } else {\n * console.log('Some alarms could not be cleared.');\n * }\n * });\n * ```\n *\n * **Note**\n * - The method uses the `alarmService.updateBulk` for each severity to clear the active alarms.\n * - It may fetch the `sourceId` based on the view (if applicable) and include it as a query parameter in the update calls.\n * - The method returns immediately but the returned Promise needs to have a `then` or `catch` method call to handle the result or error respectively.\n * - Uses `Promise.all` to wait for all update requests to complete before resolving the final result.\n */\n async clearAllActiveAlarms(\n selectedSeverities: SeverityType[],\n sourceId: string | number\n ): Promise<{ resolvedImmediately: boolean }> {\n const severitiesToUpdate = selectedSeverities || Severity;\n\n const promises = Object.values(severitiesToUpdate).map((severity: SeverityType) => {\n const commonParams = { resolved: false, severity };\n\n const parameters = sourceId\n ? {\n ...commonParams,\n source: sourceId,\n withSourceAssets: true,\n withSourceDevices: true\n }\n : commonParams;\n\n return this.alarmService.updateBulk({ status: AlarmStatus.CLEARED }, parameters);\n });\n\n const responses = await Promise.all(promises);\n return {\n resolvedImmediately: responses.every(res => res)\n };\n }\n\n /**\n * Returns the correct link based on the provided context data.\n * @param contextData The context the navigation was triggered from.\n * @param alarm The alarm to navigate to.\n * @returns A link to be used as an url navigation.\n */\n getRouterLink(contextData?: ContextData, alarm?: IAlarm): string {\n let detailUrl = `/${ALARMS_PATH}`;\n if (alarm) {\n detailUrl = `/${ALARMS_PATH}/${alarm.id}`;\n }\n if (!contextData) {\n return detailUrl;\n }\n\n switch (contextData.context) {\n case ViewContext.Device:\n return `/device/${contextData.contextData.id}${detailUrl}`;\n case ViewContext.Group:\n return `/group/${contextData.contextData.id}${detailUrl}`;\n case ViewContext.Simulators:\n return `/simulators/${contextData.contextData.id}${detailUrl}`;\n default:\n return detailUrl;\n }\n }\n\n /**\n * Returns the correct array navigation.\n * @param contextData The context the navigation was triggered from.\n * @param alarm The alarm to navigate to.\n * @returns A link to be used as a router.navigation.\n */\n getRouterNavigationArray(contextData?: ContextData, alarm?: IAlarm): string[] {\n return this.getRouterLink(contextData, alarm).split('/').filter(Boolean);\n }\n\n /**\n * Returns the correct from and to dates based on the selected interval\n * @param intervalId the selected interval. E.g. 'none', 'hours', 'custom' ...\n * @returns The calculated date context based on the selected interval.\n */\n getDateTimeContextByInterval(intervalId: AlarmFilterInterval['id']): DateTimeContext {\n const interval = INTERVALS_EXTENDED.find(({ id }) => id === intervalId);\n if (interval.id === 'none') {\n return [new Date(0), new Date()];\n }\n\n const dateTo = new Date();\n const dateFrom = new Date(dateTo.valueOf() - interval.timespanInMs);\n return [dateFrom, dateTo];\n }\n\n /**\n * Creates a value for query parameter for filtering alarms by severity based on array of selected severities.\n *\n * @param severities - An array of alarm severity types to include in the filter.\n * If the array is empty or undefined, no severity filter will be applied.\n *\n * @returns A comma-separated string of selected alarm severities,\n * or null if no severities are provided.\n */\n private getSeverityQueryParameter(severities: SeverityType[]): string | null {\n if (!severities || severities.length === 0) {\n return;\n }\n if (severities.length === Object.keys(Severity).length) {\n return;\n }\n\n return severities.join(',');\n }\n\n /**\n * Creates a value for query parameter for filtering alarms by statuses based on showCleared option.\n *\n * @param showCleared - A flag indicating whether to include cleared statuses.\n * If true, all statuses, including 'CLEARED', will be included; if false, 'CLEARED' will be excluded.\n *\n * @returns A comma-separated string of alarm statuses.\n */\n private getStatusQueryParameter(showCleared: boolean): string {\n const statuses = Object.keys(ALARM_STATUS_LABELS) as AlarmStatusType[];\n const filteredStatuses = showCleared\n ? statuses\n : statuses.filter(status => status !== 'CLEARED');\n return filteredStatuses.join(',');\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { Severity, SeverityType } from '@c8y/client';\nimport { ALARM_SEVERITY_ICON_MAP, AlarmSeverityIcon, HELP_ICON } from './alarms.model';\n\n/**\n * Pipe for transforming alarm severity types into corresponding icons.\n *\n * @example\n * Usage in an Angular template:\n * {{ 'CRITICAL' | AlarmSeverityToIcon }}\n * Result: 'exclamation-circle'\n */\n@Pipe({\n name: 'AlarmSeverityToIcon',\n standalone: true\n})\nexport class AlarmSeverityToIconPipe implements PipeTransform {\n /**\n * Transforms an alarm severity type into a corresponding icon.\n *\n * @param alarmSeverity - The severity type of the alarm.\n * @returns The corresponding icon for the given alarm severity type.\n */\n transform(alarmSeverity: SeverityType): AlarmSeverityIcon | typeof HELP_ICON {\n const alarmSeverityMapped = Severity[alarmSeverity?.toUpperCase()];\n return ALARM_SEVERITY_ICON_MAP[alarmSeverityMapped] || HELP_ICON;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { AlarmIconMap, AlarmStatusIcon, HELP_ICON } from './alarms.model';\nimport { AlarmStatusType } from '@c8y/client';\n/**\n * Angular pipe for transforming alarm statuses into corresponding icons.\n *\n * @example\n * Usage in an Angular template:\n * {{ 'ACTIVE' | AlarmStatusToIcon }}\n * Result: 'bell'\n */\n@Pipe({\n name: 'AlarmStatusToIcon'\n})\nexport class AlarmStatusToIconPipe implements PipeTransform {\n /**\n * Transforms an alarm status into a corresponding icon.\n *\n * @param alarmStatus - The status of the alarm.\n * @returns - The corresponding icon for the given alarm status.\n */\n transform(alarmStatus: AlarmStatusType): AlarmStatusIcon | typeof HELP_ICON {\n return AlarmIconMap[alarmStatus?.toUpperCase()] || HELP_ICON;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { IAuditRecord } from '@c8y/client';\nimport { gettext } from '@c8y/ngx-components';\nimport { TranslateService } from '@ngx-translate/core';\n\n/**\n * A pipe for transforming audit record data into localized messages.\n * It specifically addresses changes in the audit records, with an emphasis on status changes.\n */\n@Pipe({\n name: 'auditChangesMessage'\n})\nexport class AuditChangesMessagePipe implements PipeTransform {\n constructor(private translateService: TranslateService) {}\n\n /**\n * Transforms an IAuditRecord into a localized string message.\n * If the record contains changes, and if the first change is related to the 'status' attribute,\n * it formats a message indicating the status change. Otherwise, it returns a general activity message.\n * Example when there is a status change: \"Alarm status changed from ACKNOWLEDGED to ACTIVE\".\n * Example when record does not have a status attribute: \"Alarm updated\".\n *\n * @param record - The audit record to be transformed.\n * @returns The localized message describing the audit record,\n * particularly focusing on status changes if applicable.\n */\n transform(record: IAuditRecord): string {\n const firstItem = !!record.changes && Array.from(record.changes)[0];\n if (!firstItem || firstItem.attribute !== 'status') {\n const activityString = gettext(record.activity);\n return this.translateService.instant(activityString);\n }\n\n const { newValue, previousValue } = firstItem;\n\n const message = gettext(`Alarm status changed from {{ previousValue }} to {{ newValue }}`);\n\n return this.translateService.instant(message, {\n previousValue: this.translateService.instant(previousValue),\n newValue: this.translateService.instant(newValue)\n });\n }\n}\n","import { Component, Input, OnChanges, Optional, SimpleChanges } from '@angular/core';\nimport {\n ALARM_STATUS_LABELS,\n AlarmStatus,\n AlarmService,\n AlarmStatusType,\n AuditService,\n IAlarm,\n IApplication,\n IAuditRecord,\n IManagedObject,\n IResultList,\n InventoryService,\n SEVERITY_LABELS\n} from '@c8y/client';\nimport {\n AlertService,\n AppStateService,\n ColorService,\n RelativeTimePipe,\n gettext,\n SupportedAppKey,\n InterAppService,\n SupportedApps\n} from '@c8y/ngx-components';\nimport { TranslateService } from '@ngx-translate/core';\nimport { cloneDeep } from 'lodash-es';\nimport { AlarmDetailsService } from './alarm-details.service';\nimport {\n ALARM_DEFAULT_PROPERTIES,\n ALARM_STATUS_ICON,\n AlarmDetailsButton,\n CustomFragment\n} from './alarms.model';\nimport { Ng1SmartRulesUpgradeService } from './ng1-smart-rules-upgrade.service';\nimport { AlarmsViewService } from './alarms-view.service';\nimport { firstValueFrom, Observable } from 'rxjs';\n\n@Component({\n selector: 'c8y-alarm-details',\n templateUrl: './alarm-details.component.html'\n})\nexport class AlarmDetailsComponent implements OnChanges {\n @Input() selectedAlarm: IAlarm;\n\n readonly ACKNOWLEDGED_STATUS_VALUE = AlarmStatus.ACKNOWLEDGED;\n readonly ACTIVE_STATUS_VALUE = AlarmStatus.ACTIVE;\n readonly CLEARED_STATUS_VALUE = AlarmStatus.CLEARED;\n readonly ACKNOWLEDGE_LABEL = gettext('Acknowledge');\n readonly REACTIVATE_LABEL = gettext('Reactivate');\n readonly SEVERITY_LABELS = SEVERITY_LABELS;\n readonly BELL_SLASH_ICON = ALARM_STATUS_ICON.BELL_SLASH;\n readonly BELL_ICON = ALARM_STATUS_ICON.BELL;\n\n /**\n * Represents a Device Management application used by the user.\n * Determines the accurate name and context path required for navigating to alarms of the current device\n */\n userDeviceManagementApp$: Observable<IApplication>;\n /**\n * Manages the visibility of the navigation link.\n * If set to true, the link is visible, otherwise, it remains hidden.\n */\n showSourceNavigationLink$: Observable<boolean>;\n deviceManagementAppKey: SupportedAppKey = SupportedApps.devicemanagement;\n readonly linkTitle = gettext('Open in {{ appName }}');\n /**\n * Contains audit logs, including the very first audit log record in the alarms' history.\n * This ensures that the historical starting point of the audit logs is always included in the data set.\n * Usually it's an 'Alarm created' audit log.\n *\n * Only used when audit logs exceed PAGE_SIZE.\n *\n * @private\n */\n private extendedAuditLogs: IResultList<IAuditRecord>;\n private readonly PAGE_SIZE = 100;\n\n /**\n * Prevents the pipeline from failing for a tutorial application\n * because it's a pure Angular application and doesn't support any\n * AngularJS services.\n */\n isCreateSmartRulesButtonAvailable: boolean;\n /**\n * Property contains a 100 (see PAGE_SIZE) of most recent audit logs records.\n */\n auditLog: IResultList<IAuditRecord>;\n\n isLoading: boolean;\n /**\n * Indicates when alarms status change was started (Acknowledge/Reactivate)\n */\n isAlarmStatusChanging = false;\n /**\n * Represents a value for a 'Last updated' section in details.\n */\n lastUpdated: string;\n /**\n * Represents a value for a 'Status' section in details.\n */\n statusMessage: string;\n /**\n * The color of the alarm type.\n */\n typeColor: string;\n /**\n * Custom fragments of the selected alarm. If none exist, null is returned.\n */\n customFragments: CustomFragment = null;\n\n selectedAlarmMO: IManagedObject;\n\n constructor(\n private alarmDetailsService: AlarmDetailsService,\n private alarmService: AlarmService,\n private alertService: AlertService,\n private appState: AppStateService,\n private auditService: AuditService,\n private relativeTime: RelativeTimePipe,\n @Optional() private ng1SmartRulesUpgradeService: Ng1SmartRulesUpgradeService,\n private translateService: TranslateService,\n private inventoryService: InventoryService,\n private alarmsViewService: AlarmsViewService,\n private colorService: ColorService,\n private interAppService: InterAppService\n ) {}\n\n async ngOnInit(): Promise<void> {\n const isSmartRulesServiceSubscribed = !!(await firstValueFrom(\n this.interAppService.getApp$(SupportedApps.smartrules)\n ));\n const hasAnyRoleAllowingToCreateSmartRule =\n this.alarmDetailsService.checkIfHasAnyRoleAllowingToCreateSmartRule();\n this.isCreateSmartRulesButtonAvailable =\n !!this.ng1SmartRulesUpgradeService &&\n isSmartRulesServiceSubscribed &&\n hasAnyRoleAllowingToCreateSmartRule;\n this.userDeviceManagementApp$ = this.interAppService.getApp$(this.deviceManagementAppKey);\n this.showSourceNavigationLink$ = this.interAppService.shouldShowAppLink$(\n this.deviceManagementAppKey\n );\n this.typeColor = await this.colorService.generateColor(this.selectedAlarm.type);\n }\n\n async ngOnChanges(changes: SimpleChanges): Promise<void> {\n if (changes.selectedAlarm && changes.selectedAlarm.currentValue) {\n await this.reloadAuditLog(true, true);\n await this.updateStatusMessage();\n const { data } = await this.inventoryService.detail(this.selectedAlarm.source.id);\n this.selectedAlarmMO = data;\n this.updateLastUpdatedDate(this.auditLog.data[0]);\n this.customFragments = this.getCustomFragments(this.selectedAlarm);\n }\n }\n\n createSmartRule(): void {\n if (!this.isCreateSmartRulesButtonAvailable) {\n return;\n }\n this.ng1SmartRulesUpgradeService.addNewForInputAlarmAndOutputUserWithUI(\n this.selectedAlarm,\n this.appState.currentUser.value\n );\n }\n\n /**\n * Navigates to a specific alarm source device based on the provided source.\n *\n * @param sourceId - The source id.\n */\n async goToAlarmSource(sourceId: string | number): Promise<void> {\n const { data } = await this.alarmService.detail(sourceId);\n await this.interAppService.navigateToApp(\n this.deviceManagementAppKey,\n `#/device/${data.source.id}/alarms`\n );\n }\n\n /**\n * Reloads audit log data asynchronously.\n *\n * This method fetches audit records using `getAlarmAuditRecords` and optionally updates the audit logs\n * state in the component based on the `isSetAuditLogs` flag. It handles the loading state and potential\n * errors during the fetch operation.\n *\n * @param isRevert - A boolean flag indicating whether to retrieve a 100 (see PAGE_SIZE) records (true)\n * or only record, that chronologically will be the oldest one (false). Defaults to true.\n * If set to false, it will set PAGE_SIZE to 1 and trigger a logic\n * concatenating a most recent record with the very first one to\n * calculate the alarm duration (change to CLEARED status).\n * It's passed to the `getAlarmAuditRecords` method.\n * @param isSetAuditLogs - A boolean flag to determine if the fetched audit logs should be set in the component state. Defaults to `false`.\n * @returns A promise that resolves to a list of `IAuditRecord` objects.\n */\n async reloadAuditLog(\n isRevert = true,\n isSetAuditLogs = false\n ): Promise<IResultList<IAuditRecord>> {\n try {\n this.isLoading = true;\n const auditLogs = await this.getAlarmAuditRecords(isRevert);\n\n if (isSetAuditLogs) {\n this.setAuditLogs(auditLogs);\n }\n\n return auditLogs;\n } catch (error) {\n this.alertService.addServerFailure(error);\n } finally {\n this.isLoading = false;\n }\n }\n\n async onUpdateDetails(status: AlarmStatusType): Promise<void> {\n try {\n this.isAlarmStatusChanging = true;\n await this.updateAlarmStatus(status);\n await this.reloadAuditLog(true, true);\n await this.updateStatusMessage();\n this.updateLastUpdatedDate(this.auditLog.data[0]);\n } catch (error) {\n this.alertService.addServerFailure(error);\n } finally {\n this.isAlarmStatusChanging = false;\n }\n }\n\n async detailsButtonAction(button: AlarmDetailsButton, alarm: IAlarm): Promise<void> {\n const result = button.action(alarm);\n let shouldReload: boolean | IAlarm = false;\n if (result instanceof Promise) {\n shouldReload = await result;\n } else {\n shouldReload = result;\n }\n\n if (shouldReload) {\n let alarm: IAlarm;\n if (shouldReload === true) {\n const { data: updatedAlarm } = await this.alarmService.detail(this.selectedAlarm.id);\n alarm = updatedAlarm;\n } else {\n alarm = shouldReload;\n }\n this.alarmsViewService.updateAlarmList();\n\n const previousValue = this.selectedAlarm;\n this.selectedAlarm = alarm;\n this.ngOnChanges({\n selectedAlarm: {\n currentValue: alarm,\n previousValue,\n firstChange: false,\n isFirstChange: () => false\n }\n });\n }\n }\n\n private async updateAlarmStatus(status: AlarmStatusType): Promise<void> {\n const partiallyUpdatedAlarm: Partial<IAlarm> = { id: this.selectedAlarm.id, status };\n await this.alarmService.update(partiallyUpdatedAlarm);\n const translatedStatusLabel = this.translateService.instant(ALARM_STATUS_LABELS[status]);\n this.alertService.success(\n this.translateService.instant(gettext('Alarm status changed to {{ status }}'), {\n status: translatedStatusLabel.toUpperCase()\n })\n );\n this.selectedAlarm.status = status;\n this.alarmsViewService.updateAlarmList();\n }\n\n /**\n * Retrieves the audit log and appends the last audit record to it.\n *\n * This method fetches the existing audit log data and makes a deep copy of it. It then\n * retrieves the last audit record and appends it to the copied audit log data. This is\n * useful for scenarios where the most recent audit record needs to be included in the\n * existing audit log data (calculating the CLEARED period).\n *\n * @returns A promise of `IResultList<IAuditRecord>`, which includes the\n * existing audit log data along with the last audit record appended.\n * @private\n */\n private async auditLogWithFirstRecord(): Promise<IResultList<IAuditRecord>> {\n const existingData = this.auditLog;\n const copiedExistingData = cloneDeep(existingData);\n\n const lastAuditRecord = await this.reloadAuditLog(false);\n const lastRecord = lastAuditRecord.data[lastAuditRecord.data.length - 1];\n copiedExistingData.data.push(lastRecord);\n return copiedExistingData;\n }\n\n private setAuditLogs(auditLogs: IResultList<IAuditRecord>): void {\n this.auditLog = auditLogs;\n }\n\n private updateLastUpdatedDate(updatedAuditRecords: IAuditRecord): void {\n if (!updatedAuditRecords) {\n return;\n }\n\n const { creationTime } = updatedAuditRecords;\n this.lastUpdated = creationTime;\n }\n\n private getActiveStatusMessage(time: string): string {\n return this.translateService.instant(gettext('ACTIVE`alarm`: triggered {{alarmTimeFromNow}}'), {\n alarmTimeFromNow: this.relativeTime.transform(new Date(time))\n });\n }\n\n private getAcknowledgedStatusMessage(status: AlarmStatusType, changeLog: IAuditRecord[]): string {\n if (changeLog.length === 0) {\n return this.translateService.instant(gettext('ACKNOWLEDGED`alarm`'));\n }\n\n const acknowledgedBy = this.alarmDetailsService.getAcknowledgedBy(status, changeLog);\n const acknowledgeTime = this.alarmDetailsService.getAcknowledgeTime(changeLog);\n\n if (acknowledgedBy) {\n return this.translateService.instant(\n gettext('ACKNOWLEDGED`alarm` by: {{ackBy}} {{ackTimeFromNow}}'),\n {\n ackBy: acknowledgedBy,\n ackTimeFromNow: this.relativeTime.transform(new Date(acknowledgeTime))\n }\n );\n }\n\n return this.translateService.instant(gettext('ACKNOWLEDGED`alarm` {{ackTimeFromNow}}'), {\n ackTimeFromNow: this.relativeTime.transform(new Date(acknowledgeTime))\n });\n }\n\n private getClearedStatusMessage(auditLog: IAuditRecord[]): string {\n if (auditLog.length === 0) {\n return this.translateService.instant(gettext('CLEARED`alarm`'));\n }\n\n const differenceInMs = this.calculateAlarmDuration(auditLog);\n\n return this.translateService.instant(\n gettext('CLEARED`alarm`: was active for {{alarmDuration}}'),\n {\n alarmDuration: this.relativeTime.transform(differenceInMs, true)\n }\n );\n }\n\n /**\n * Calculates the duration of an alarm based on audit log records.\n *\n * This method computes the duration of an alarm by finding the difference\n * between the start and end times of the alarm. The start time is determined\n * from the last record in the audit log, using the first available time field\n * (`firstOccurrenceTime`, `time`, or `creationTime`). The end time is obtained\n * from the `alarmDetailsService`.\n *\n * @param auditLog - An array of `IAuditRecord` objects representing the audit log records.\n * @returns The duration of the alarm in milliseconds, or `null` if the end time is not available.\n * @private\n */\n private calculateAlarmDuration(auditLog: IAuditRecord[]): number | null {\n const firstAlarm = auditLog[auditLog.length - 1];\n const startTime = firstAlarm.firstOccurrenceTime || firstAlarm.time || firstAlarm.creationTime;\n const endTime = this.alarmDetailsService.getEndTime(auditLog);\n\n if (!endTime) {\n return null;\n }\n\n const startTimeToDate = new Date(startTime);\n const endTimeToDate = new Date(endTime);\n\n return endTimeToDate.getTime() - startTimeToDate.getTime();\n }\n\n /**\n * Retrieves a list of audit records for a selected alarm.\n *\n * This method fetches audit records based on the specified properties, including\n * the date, page size, whether to revert, the source alarm ID, and whether to include total pages.\n *\n * @param isRevert - A boolean flag indicating whether to retrieve a 100 (see PAGE_SIZE) records (true)\n * or only record, that chronologically will be the oldest one (false). Defaults to true.\n * If set to false, it will set PAGE_SIZE to 1 and trigger a logic\n * concatenating a most recent record with the very first one to\n * calculate the alarm duration (change to CLEARED status).\n * @returns A Promise that resolves to an IResultList of IAuditRecord objects, representing the audit records.\n * @async\n * @private\n */\n private async getAlarmAuditRecords(isRevert = true): Promise<IResultList<IAuditRecord>> {\n const properties = {\n dateTo: new Date(Date.now()).toISOString(),\n pageSize: isRevert ? this.PAGE_SIZE : 1,\n revert: isRevert,\n source: this.selectedAlarm.id,\n withTotalPages: true\n };\n\n return await this.auditService.list(properties);\n }\n\n private async updateStatusMessage(): Promise<void> {\n switch (this.selectedAlarm.status) {\n case this.ACTIVE_STATUS_VALUE:\n this.statusMessage = this.getActiveStatusMessage(this.selectedAlarm.time);\n break;\n case this.ACKNOWLEDGED_STATUS_VALUE:\n this.statusMessage = this.getAcknowledgedStatusMessage(\n this.selectedAlarm.status as unknown as AlarmStatusType,\n this.auditLog.data\n );\n break;\n case this.CLEARED_STATUS_VALUE:\n if (this.hasReachedOrExceededPageSizeLimit()) {\n this.extendedAuditLogs = await this.auditLogWithFirstRecord();\n this.statusMessage = this.getClearedStatusMessage(this.extendedAuditLogs.data);\n return;\n }\n