@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
1 lines • 265 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/alarms-activity-tracker.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-icon-class.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 { gettext } from '@c8y/ngx-components/gettext';\nimport { DateTimeContext, NavigatorNode, NavigatorNodeData, Route } 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\nexport const PRODUCT_EXPERIENCE_ALARMS = {\n EVENTS: {\n ALARMS: 'Alarms'\n },\n COMPONENTS: {\n ALARMS_FILTER: 'alarms-filter',\n ALARMS_INTERVAL_REFRESH: 'alarms-interval-refresh',\n ALARMS: 'alarms',\n ALARMS_TYPE_FILTER: 'alarms-type-filter',\n ALARM_DETAILS: 'alarm-details'\n },\n ACTIONS: {\n APPLY_FILTER: 'applyFilter',\n REMOVE_CHIP_FILTER: 'removeChipFilter',\n APPLY_TYPE_FILTER: 'applyTypeFilter',\n CREATE_SMART_RULE: 'createSmartRule',\n ACKNOWLEDGE_ALARM: 'acknowledgeAlarm',\n REACTIVATE_ALARM: 'reactivateAlarm',\n CLEAR_ALARM: 'clearAlarm',\n RELOAD_AUDIT_LOGS: 'reloadAuditLogs',\n USER_SPEND_TIME_ON_COMPONENT: 'userSpendTimeOnComponent'\n }\n} as const;\n\nexport type ReloadAlarmsListType = 'gainsightTypeFilters' | null;\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 { ActivatedRoute, ActivatedRouteSnapshot, Router } from '@angular/router';\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 { gettext } from '@c8y/ngx-components/gettext';\nimport {\n ApplicationOptions,\n ContextData,\n ContextRouteService,\n DateTimeContext,\n OptionsService,\n ViewContext\n} from '@c8y/ngx-components';\nimport { DateTimeContextPickerService, TimeInterval } from '@c8y/ngx-components/global-context';\nimport { AlarmFilterInterval } from '@c8y/ngx-components/interval-picker';\nimport { Observable, Subject } from 'rxjs';\nimport { ALARMS_PATH, ReloadAlarmsListType } from './alarms.model';\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<ReloadAlarmsListType>();\n closeDetailsView$ = new Subject<void>();\n\n private _isIntervalEnabled: Subject<boolean>;\n\n constructor(\n private alarmService: AlarmService,\n private optionsService: OptionsService,\n private dateTimeContextPickerService: DateTimeContextPickerService,\n private router: Router,\n private contextRouteService: ContextRouteService\n ) {\n if (this.isIntervalRefresh()) {\n this._isIntervalEnabled = new Subject<boolean>();\n this.isIntervalEnabled$ = this._isIntervalEnabled.asObservable();\n }\n }\n\n /**\n * Emits a subject to initialize the alarms reloading.\n */\n updateAlarmList(value: ReloadAlarmsListType = null): void {\n this.reloadAlarmsList$.next(value);\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 * Closes the details view and navigates based on the current route context,\n * preserving existing query parameters.\n */\n async closeDetailsView(activatedRoute: ActivatedRoute | ActivatedRouteSnapshot): Promise<void> {\n const contextData = this.contextRouteService.getContextData(activatedRoute);\n await this.router.navigate(this.getRouterNavigationArray(contextData), {\n queryParamsHandling: 'merge'\n });\n this.updateIntervalState(true);\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 return this.dateTimeContextPickerService.getDateTimeContextByInterval(\n intervalId as TimeInterval\n );\n }\n\n /**\n * Converts a given number of seconds into a formatted string representing hours, minutes, and seconds.\n *\n * @param totalSeconds - The total number of seconds to convert.\n * @returns A string in the format \"HH:MM:SS\", where HH is hours, MM is minutes, and SS is seconds.\n */\n convertSecondsToTime(totalSeconds: number): string {\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = Math.floor(totalSeconds % 60);\n\n const paddedHours = hours.toString().padStart(2, '0');\n const paddedMinutes = minutes.toString().padStart(2, '0');\n const paddedSeconds = seconds.toString().padStart(2, '0');\n\n return `${paddedHours}:${paddedMinutes}:${paddedSeconds}`;\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 { Injectable, OnDestroy } from '@angular/core';\nimport { BehaviorSubject, fromEvent, Subject } from 'rxjs';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\n\n@Injectable()\nexport class AlarmsActivityTrackerService implements OnDestroy {\n isUserActive$ = new BehaviorSubject(true);\n userSecondsSpendOnPage = 0;\n\n private gainsightTimerId: ReturnType<typeof setInterval>;\n private readonly INACTIVITY_THRESHOLD_SECONDS = 10;\n private readonly ONE_SECOND_IN_MILLISECONDS = 1_000;\n private gainsightInactivityTimeoutId: ReturnType<typeof setTimeout>;\n private destroy$ = new Subject<void>();\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n setGainsightInterval(): void {\n this.gainsightTimerId = setInterval(\n () => this.userSecondsSpendOnPage++,\n this.ONE_SECOND_IN_MILLISECONDS\n );\n }\n\n clearGainsightInterval(): void {\n clearInterval(this.gainsightTimerId);\n }\n\n resetInactivityTimer(): void {\n this.isUserActive$.next(true);\n clearTimeout(this.gainsightInactivityTimeoutId);\n this.gainsightInactivityTimeoutId = setTimeout(() => {\n this.isUserActive$.next(false); // Pause counting if the user is inactive\n }, this.INACTIVITY_THRESHOLD_SECONDS * this.ONE_SECOND_IN_MILLISECONDS);\n }\n\n setupEventListenersForGainsight() {\n const events = ['mousemove', 'keydown', 'click'];\n\n events.forEach(event => {\n fromEvent(window, event)\n .pipe(debounceTime(30), takeUntil(this.destroy$))\n .subscribe(() => this.resetInactivityTimer());\n });\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({ name: 'AlarmStatusToIcon' })\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/gettext';\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({ name: 'auditChangesMessage' })\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 {\n Component,\n HostListener,\n Input,\n OnChanges,\n OnDestroy,\n OnInit,\n Optional,\n SimpleChanges\n} 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 { gettext } from '@c8y/ngx-components/gettext';\nimport {\n AlertService,\n AppStateService,\n ColorService,\n RelativeTimePipe,\n SupportedAppKey,\n InterAppService,\n SupportedApps,\n GainsightService,\n DatePipe,\n IconDirective,\n ProductExperienceDirective,\n EmptyStateComponent,\n LoadingComponent,\n ListGroupComponent,\n ForOfDirective,\n ListItemTimelineComponent,\n ListItemComponent,\n ListItemBodyComponent,\n C8yTranslatePipe,\n HumanizeAppNamePipe,\n AssetLinkPipe\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 PRODUCT_EXPERIENCE_ALARMS\n} from './alarms.model';\nimport { Ng1SmartRulesUpgradeService } from './ng1-smart-rules-upgrade.service';\nimport { AlarmsViewService } from './alarms-view.service';\nimport { firstValueFrom, Observable, Subject } from 'rxjs';\nimport { distinctUntilChanged, takeUntil } from 'rxjs/operators';\nimport { AlarmsActivityTrackerService } from './alarms-activity-tracker.service';\nimport { NgClass, NgIf, NgStyle, NgFor, AsyncPipe, LowerCasePipe, JsonPipe } from '@angular/common';\nimport { RouterLink } from '@angular/router';\nimport { PopoverDirective } from 'ngx-bootstrap/popover';\nimport { AlarmDetailsButtonPipe } from './alarm-details-custom-button/alarm-details-button.pipe';\nimport { AlarmSeverityToIconPipe } from './alarm-severity-to-icon.pipe';\nimport { AlarmStatusToIconPipe } from './alarm-status-to-icon.pipe';\nimport { AuditChangesMessagePipe } from './audit-changes-message.pipe';\n\n@Component({\n selector: 'c8y-alarm-details',\n templateUrl: './alarm-details.component.html',\n providers: [AlarmsActivityTrackerService],\n imports: [\n IconDirective,\n NgClass,\n RouterLink,\n NgIf,\n NgStyle,\n PopoverDirective,\n ProductExperienceDirective,\n NgFor,\n EmptyStateComponent,\n LoadingComponent,\n ListGroupComponent,\n ForOfDirective,\n ListItemTimelineComponent,\n ListItemComponent,\n ListItemBodyComponent,\n C8yTranslatePipe,\n AsyncPipe,\n LowerCasePipe,\n JsonPipe,\n DatePipe,\n HumanizeAppNamePipe,\n AssetLinkPipe,\n AlarmDetailsButtonPipe,\n AlarmSeverityToIconPipe,\n AlarmStatusToIconPipe,\n AuditChangesMessagePipe\n ]\n})\nexport class AlarmDetailsComponent implements OnInit, OnChanges, OnDestroy {\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 readonly PRODUCT_EXPERIENCE_ALARMS = PRODUCT_EXPERIENCE_ALARMS;\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 '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 private readonly USER_MINIMUM_SPEND_TIME_SECONDS_TO_TRIGGER_EVENT = 1;\n\n private destroy$ = new Subject<void>();\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 private gainsightService: GainsightService,\n private alarmsActivityTrackerService: AlarmsActivityTrackerService\n ) {}\n\n async ngOnInit(): Promise<void> {\n this.alarmsActivityTrackerService.setupEventListenersForGainsight();\n this.alarmsActivityTrackerService.resetInactivityTimer();\n\n this.alarmsActivityTrackerService.isUserActive$\n .pipe(distinctUntilChanged(), takeUntil(this.destroy$))\n .subscribe(isActive =>\n isActive\n ? this.alarmsActivityTrackerService.setGainsightInterval()\n : this.alarmsActivityTrackerService.clearGainsightInterval()\n );\n\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.customFragments = this.getCustomFragments(this.selectedAlarm);\n }\n }\n\n ngOnDestroy(): void {\n if (\n this.alarmsActivityTrackerService.userSecondsSpendOnPage >=\n this.USER_MINIMUM_SPEND_TIME_SECONDS_TO_TRIGGER_EVENT\n ) {\n this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ALARMS.EVENTS.ALARMS, {\n component: PRODUCT_EXPERIENCE_ALARMS.COMPONENTS.ALARM_DETAILS,\n action: PRODUCT_EXPERIENCE_ALARMS.ACTIONS.USER_SPEND_TIME_ON_COMPONENT,\n userSpendTime: this.alarmsViewService.convertSecondsToTime(\n this.alarmsActivityTrackerService.userSecondsSpendOnPage\n )\n });\n }\n this.alarmsActivityTrackerService.clearGainsightInterval();\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n @HostListener('document:visibilitychange')\n visibilityChange() {\n if (document.hidden) {\n this.alarmsActivityTrackerService.clearGainsightInterval();\n return;\n }\n this.alarmsActivityTrackerService.setGainsightInterval();\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 if (status === AlarmStatus.CLEARED) {\n this.alarmsViewService.closeDetailsView$.next();\n }\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: