@c8y/ngx-components 1024.15.16 → 1024.16.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs +303 -63
  2. package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs.map +1 -1
  3. package/fesm2022/c8y-ngx-components-ai-agents-html.mjs +9 -0
  4. package/fesm2022/c8y-ngx-components-ai-agents-html.mjs.map +1 -1
  5. package/fesm2022/c8y-ngx-components-ai-agents-scada.mjs +4 -0
  6. package/fesm2022/c8y-ngx-components-ai-agents-scada.mjs.map +1 -1
  7. package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs +394 -52
  8. package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs.map +1 -1
  9. package/fesm2022/c8y-ngx-components-ai.mjs +329 -19
  10. package/fesm2022/c8y-ngx-components-ai.mjs.map +1 -1
  11. package/fesm2022/c8y-ngx-components-bookmarks.mjs +1 -1
  12. package/fesm2022/c8y-ngx-components-bookmarks.mjs.map +1 -1
  13. package/fesm2022/c8y-ngx-components-context-dashboard.mjs +5 -1
  14. package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  15. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +96 -77
  16. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
  17. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs +92 -47
  18. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs.map +1 -1
  19. package/fesm2022/c8y-ngx-components-device-profile.mjs +1 -1
  20. package/fesm2022/c8y-ngx-components-device-profile.mjs.map +1 -1
  21. package/fesm2022/c8y-ngx-components-echart.mjs +25 -4
  22. package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
  23. package/fesm2022/c8y-ngx-components-ecosystem.mjs +1 -1
  24. package/fesm2022/c8y-ngx-components-ecosystem.mjs.map +1 -1
  25. package/fesm2022/c8y-ngx-components-protocol-opcua.mjs +1 -1
  26. package/fesm2022/c8y-ngx-components-protocol-opcua.mjs.map +1 -1
  27. package/fesm2022/c8y-ngx-components-register-device.mjs +5 -6
  28. package/fesm2022/c8y-ngx-components-register-device.mjs.map +1 -1
  29. package/fesm2022/c8y-ngx-components-repository-firmware.mjs +1 -1
  30. package/fesm2022/c8y-ngx-components-repository-firmware.mjs.map +1 -1
  31. package/fesm2022/c8y-ngx-components-repository-software.mjs +1 -1
  32. package/fesm2022/c8y-ngx-components-repository-software.mjs.map +1 -1
  33. package/fesm2022/c8y-ngx-components-sub-assets.mjs +30 -10
  34. package/fesm2022/c8y-ngx-components-sub-assets.mjs.map +1 -1
  35. package/fesm2022/c8y-ngx-components-time-context.mjs +13 -9
  36. package/fesm2022/c8y-ngx-components-time-context.mjs.map +1 -1
  37. package/fesm2022/c8y-ngx-components-trusted-certificates.mjs +1 -1
  38. package/fesm2022/c8y-ngx-components-trusted-certificates.mjs.map +1 -1
  39. package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs +3 -2
  40. package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs.map +1 -1
  41. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +4 -6
  42. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
  43. package/fesm2022/c8y-ngx-components-widgets-implementations-scada.mjs +3 -2
  44. package/fesm2022/c8y-ngx-components-widgets-implementations-scada.mjs.map +1 -1
  45. package/fesm2022/c8y-ngx-components.mjs +122 -24
  46. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  47. package/locales/de.po +147 -16
  48. package/locales/es.po +143 -11
  49. package/locales/fr.po +459 -324
  50. package/locales/ja_JP.po +143 -11
  51. package/locales/ko.po +143 -11
  52. package/locales/locales.pot +136 -10
  53. package/locales/nl.po +143 -11
  54. package/locales/pl.po +143 -11
  55. package/locales/pt_BR.po +143 -11
  56. package/locales/zh_CN.po +143 -11
  57. package/locales/zh_TW.po +143 -11
  58. package/package.json +1 -1
  59. package/types/c8y-ngx-components-ai-agent-chat.d.ts +111 -4
  60. package/types/c8y-ngx-components-ai-agent-chat.d.ts.map +1 -1
  61. package/types/c8y-ngx-components-ai-agents-html.d.ts.map +1 -1
  62. package/types/c8y-ngx-components-ai-agents-scada.d.ts.map +1 -1
  63. package/types/c8y-ngx-components-ai-ai-chat.d.ts +224 -10
  64. package/types/c8y-ngx-components-ai-ai-chat.d.ts.map +1 -1
  65. package/types/c8y-ngx-components-ai.d.ts +176 -6
  66. package/types/c8y-ngx-components-ai.d.ts.map +1 -1
  67. package/types/c8y-ngx-components-context-dashboard.d.ts.map +1 -1
  68. package/types/c8y-ngx-components-datapoint-explorer-view.d.ts +7 -2
  69. package/types/c8y-ngx-components-datapoint-explorer-view.d.ts.map +1 -1
  70. package/types/c8y-ngx-components-datapoint-selector.d.ts +63 -50
  71. package/types/c8y-ngx-components-datapoint-selector.d.ts.map +1 -1
  72. package/types/c8y-ngx-components-echart.d.ts +12 -0
  73. package/types/c8y-ngx-components-echart.d.ts.map +1 -1
  74. package/types/c8y-ngx-components-register-device.d.ts.map +1 -1
  75. package/types/c8y-ngx-components-sub-assets.d.ts +10 -1
  76. package/types/c8y-ngx-components-sub-assets.d.ts.map +1 -1
  77. package/types/c8y-ngx-components-time-context.d.ts +2 -0
  78. package/types/c8y-ngx-components-time-context.d.ts.map +1 -1
  79. package/types/c8y-ngx-components-widgets-implementations-scada.d.ts.map +1 -1
  80. package/types/c8y-ngx-components.d.ts +37 -5
  81. package/types/c8y-ngx-components.d.ts.map +1 -1
@@ -179,9 +179,8 @@ class TimeContextComponent {
179
179
  aggregation: incomingAutoAggregation ? null : this.changedDateContext.aggregation,
180
180
  autoAggregation: incomingAutoAggregation
181
181
  }, false);
182
- if (this.changedDateContext.realtime) {
183
- this.form.controls.aggregation.disable();
184
- }
182
+ // Silent like the update() above: parent-driven changes must not emit back.
183
+ this.setRealtimeControlsLocked(!!this.changedDateContext.realtime, { emitEvent: false });
185
184
  }
186
185
  }
187
186
  /** Called by the aggregation picker's (autoModeChange) output. */
@@ -213,14 +212,21 @@ class TimeContextComponent {
213
212
  }
214
213
  stopRealtime() {
215
214
  this.realtimeSubscription?.unsubscribe();
216
- this.form?.controls.temporaryUserSelectedFromDate.enable();
217
- this.form?.controls.temporaryUserSelectedToDate.enable();
218
- this.form?.controls.aggregation.enable();
215
+ this.setRealtimeControlsLocked(false);
219
216
  // Update the form value without triggering valueChanges to avoid infinite loop
220
217
  if (this.form?.value.realtime) {
221
218
  this.form.patchValue({ realtime: false }, { emitEvent: false });
222
219
  }
223
220
  }
221
+ /** Realtime locks manual range selection and aggregation; single owner of that control set. */
222
+ setRealtimeControlsLocked(locked, options) {
223
+ const controls = [
224
+ this.form.controls.temporaryUserSelectedFromDate,
225
+ this.form.controls.temporaryUserSelectedToDate,
226
+ this.form.controls.aggregation
227
+ ];
228
+ controls.forEach(control => (locked ? control.disable(options) : control.enable(options)));
229
+ }
224
230
  subscribeToIntervalChange() {
225
231
  this.form.controls.currentDateContextInterval.valueChanges
226
232
  .pipe(takeUntilDestroyed(this.#destroyRef))
@@ -367,9 +373,7 @@ class TimeContextComponent {
367
373
  });
368
374
  }
369
375
  startRealtime() {
370
- this.form.controls.temporaryUserSelectedFromDate.disable();
371
- this.form.controls.temporaryUserSelectedToDate.disable();
372
- this.form.controls.aggregation.disable();
376
+ this.setRealtimeControlsLocked(true);
373
377
  this.realtimeSubscription = interval(this.REALTIME_INTERVAL)
374
378
  .pipe(takeUntilDestroyed(this.#destroyRef))
375
379
  .subscribe(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"c8y-ngx-components-time-context.mjs","sources":["../../time-context/time-context.service.ts","../../time-context/time-context.component.ts","../../time-context/time-context.component.html","../../time-context/c8y-ngx-components-time-context.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { aggregationType } from '@c8y/client';\nimport { AGGREGATION_LIMITS, DateTimeContext } from '@c8y/ngx-components';\nimport { Interval, INTERVALS, TimeSpanInMs } from '@c8y/ngx-components/interval-picker';\nimport { TimeContext } from './time-context.model';\n\ninterface TimeRangeValidation {\n aggregationType: aggregationType;\n isDisabled: boolean;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class DatapointExplorerService {\n readonly DEFAULT_INTERVAL: Interval['id'] = 'days';\n\n // Create generic? Based on packages/ngx-components/core/dashboard/wiget-time-context/widget-time-context.component.html\n getDefaultContext(overrides?: Partial<TimeContext>): TimeContext {\n return {\n date: this.getDateTimeContextByInterval(overrides?.interval ?? this.DEFAULT_INTERVAL),\n interval: this.DEFAULT_INTERVAL,\n realtime: false,\n aggregation: aggregationType.MINUTELY,\n ...overrides\n };\n }\n\n calculateAggregation(\n [dateFrom, dateTo]: DateTimeContext,\n requestedAggregation: aggregationType | null\n ): {\n selectedAggregation: aggregationType | null;\n disabledAggregations: Partial<Record<aggregationType, boolean>>;\n } {\n const timeRangeValidations = this.validateTimeRanges([dateFrom, dateTo]);\n const disabledAggregations = this.getDisabledAggregations(timeRangeValidations);\n\n const timeRangeInMs = this.getTimeRangeInMs(dateFrom, dateTo);\n\n const isRequestedAggregationValid =\n requestedAggregation === null || !disabledAggregations[requestedAggregation];\n\n const selectedAggregation = isRequestedAggregationValid\n ? requestedAggregation\n : this.determineAggregation(timeRangeInMs);\n\n return {\n selectedAggregation,\n disabledAggregations\n };\n }\n\n getDateTimeContextByInterval(intervalId: Interval['id']): DateTimeContext {\n const interval = INTERVALS.find(({ id }) => id === intervalId);\n const dateTo = new Date();\n const dateFrom = new Date(dateTo.valueOf() - interval.timespanInMs);\n return [dateFrom, dateTo];\n }\n\n private getTimeRangeInMs(dateFrom: Date, dateTo: Date): number {\n return dateTo.valueOf() - dateFrom.valueOf();\n }\n\n private validateTimeRanges([dateFrom, dateTo]: DateTimeContext): TimeRangeValidation[] {\n const timeRangeInMs = this.getTimeRangeInMs(dateFrom, dateTo);\n\n return [\n {\n aggregationType: aggregationType.DAILY,\n isDisabled: timeRangeInMs <= TimeSpanInMs.DAY\n },\n {\n aggregationType: aggregationType.HOURLY,\n isDisabled: timeRangeInMs <= TimeSpanInMs.HOUR\n },\n {\n aggregationType: aggregationType.MINUTELY,\n isDisabled: timeRangeInMs <= TimeSpanInMs.MINUTE\n }\n ];\n }\n\n private getDisabledAggregations(\n timeRangeValidations: TimeRangeValidation[]\n ): Partial<Record<aggregationType, boolean>> {\n return timeRangeValidations.reduce(\n (acc, { aggregationType, isDisabled }) => ({\n ...acc,\n [aggregationType]: isDisabled\n }),\n {}\n );\n }\n\n private determineAggregation(timeRangeInMs: number): aggregationType | null {\n if (timeRangeInMs >= AGGREGATION_LIMITS.DAILY_LIMIT) {\n return aggregationType.DAILY;\n } else if (timeRangeInMs >= AGGREGATION_LIMITS.HOURLY_LIMIT) {\n return aggregationType.HOURLY;\n } else if (timeRangeInMs >= AGGREGATION_LIMITS.MINUTELY_LIMIT) {\n return aggregationType.MINUTELY;\n }\n return null;\n }\n}\n","import {\n Component,\n DestroyRef,\n inject,\n Input,\n model,\n OnInit,\n signal,\n SimpleChanges,\n ViewChild\n} from '@angular/core';\nimport { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';\nimport { FormBuilder } from '@angular/forms';\nimport {\n AggregationPickerComponent,\n CoreModule,\n DateAndTimeOptions,\n DateTimeContext,\n DateTimePickerModule,\n WidgetTimeContextDateRangeService\n} from '@c8y/ngx-components';\nimport {\n AGGREGATION_POPOVER_TEXT,\n AUTO_AGGREGATION_DATAPOINTS,\n AutoAggregationConfig,\n RealtimeControlComponent,\n TimeSeriesMigrationService,\n TIMING\n} from '@c8y/ngx-components/global-context';\nimport {\n Interval,\n INTERVAL_TITLES,\n IntervalPickerComponent\n} from '@c8y/ngx-components/interval-picker';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { BsDatepickerModule } from 'ngx-bootstrap/datepicker';\nimport { BsDropdownDirective, BsDropdownModule } from 'ngx-bootstrap/dropdown';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\nimport { PopoverModule } from 'ngx-bootstrap/popover';\nimport { debounceTime, interval, Subscription } from 'rxjs';\nimport { TimeContext } from './time-context.model';\nimport { DatapointExplorerService } from './time-context.service';\n\n// TODO: REMOVE THIS FILE\n@Component({\n selector: 'c8y-time-context',\n templateUrl: './time-context.component.html',\n standalone: true,\n imports: [\n CoreModule,\n BsDatepickerModule,\n DateTimePickerModule,\n BsDropdownModule,\n AggregationPickerComponent,\n TooltipModule,\n PopoverModule,\n IntervalPickerComponent,\n RealtimeControlComponent\n ]\n})\nexport class TimeContextComponent implements OnInit {\n @Input() changedDateContext: {\n dateFrom?: Date;\n dateTo?: Date;\n interval?: Interval['id'];\n realtime?: boolean;\n aggregation?: string;\n autoAggregation?: AutoAggregationConfig | null;\n };\n @Input() controlsAvailable: any;\n @Input() timeContext: Partial<TimeContext> = {};\n @Input() timePickerConfig: DateAndTimeOptions = {\n showMinutes: true,\n showSeconds: false,\n showSpinners: false\n };\n @Input() enableAutoAggregation = false;\n @ViewChild(BsDropdownDirective) dropdown: BsDropdownDirective;\n datapointExplorerService = inject(DatapointExplorerService);\n formBuilder = inject(FormBuilder);\n #destroyRef = inject(DestroyRef);\n #timeSeriesMigrationService = inject(TimeSeriesMigrationService);\n\n readonly DATE_FORMAT = 'short';\n readonly INTERVAL_TITLES = INTERVAL_TITLES;\n readonly REALTIME_INTERVAL = 1000;\n readonly AUTO_AGGREGATION_DATAPOINTS = AUTO_AGGREGATION_DATAPOINTS;\n readonly AGGREGATION_POPOVER = AGGREGATION_POPOVER_TEXT;\n readonly KEEP_DATA_ON_ZOOM_IN_POPOVER = gettext(\n 'When enabled, the chart reloads data at a finer or coarser interval as you zoom in or out, so it always shows the number of points you set. When disabled, it reuses the already loaded data.'\n );\n /** Whether auto-aggregation mode is active. */\n readonly isAutoModeActive = signal(false);\n /**\n * The \"Auto\" aggregation option requires the tenant to be migrated to time series\n * (auto mode uses `aggregationInterval`, unsupported on non-migrated tenants).\n */\n readonly isTimeSeriesMigrated = signal(false);\n form = this.createForm(this.datapointExplorerService.getDefaultContext());\n disabledAggregations;\n\n /** Last datapoints value applied to the context; restored when the field is left empty. */\n private lastAppliedDatapoints: number = AUTO_AGGREGATION_DATAPOINTS.DEFAULT;\n\n readonly valuesSignal = toSignal(this.form.controls.currentDateContextFromDate.valueChanges, {\n initialValue: this.form.controls.currentDateContextFromDate.value\n });\n\n context = model(this.form.value);\n\n private realtimeSubscription: Subscription;\n\n constructor(private widgetTimeContextDateRangeService: WidgetTimeContextDateRangeService) {}\n\n ngOnInit(): void {\n this.form.patchValue(this.datapointExplorerService.getDefaultContext(this.timeContext));\n const context = this.datapointExplorerService.getDefaultContext(this.timeContext);\n const { disabledAggregations } = this.datapointExplorerService.calculateAggregation(\n context.date,\n context.aggregation\n );\n this.disabledAggregations = disabledAggregations;\n\n this.#timeSeriesMigrationService\n .isTimeSeriesMigrated()\n .then(isMigrated => this.isTimeSeriesMigrated.set(isMigrated));\n\n this.subscribeToIntervalChange();\n this.subscribeToRealtimeChange();\n this.subscribeToAggregationChange();\n this.subscribeToDatapointsChange();\n this.subscribeToKeepDataOnZoomInChange();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes.changedDateContext && changes.changedDateContext.currentValue) {\n // In realtime mode, ignore updates from parent - the component updates itself via interval\n if (this.changedDateContext.realtime && this.form.value.realtime) {\n return;\n }\n\n // Check if values actually changed (not just object reference)\n const currentFormValues = this.form.value;\n const newDateFrom = this.changedDateContext.dateFrom?.toISOString();\n const newDateTo = this.changedDateContext.dateTo?.toISOString();\n\n const hasActualChanges =\n newDateFrom !== currentFormValues.currentDateContextFromDate ||\n newDateTo !== currentFormValues.currentDateContextToDate ||\n this.changedDateContext.interval !== currentFormValues.currentDateContextInterval ||\n this.changedDateContext.realtime !== currentFormValues.realtime ||\n this.changedDateContext.aggregation !== currentFormValues.aggregation ||\n !!this.changedDateContext.autoAggregation !== currentFormValues.autoAggregationEnabled;\n\n if (!hasActualChanges) {\n return;\n }\n\n // Don't emit when update comes from parent (avoid infinite loop)\n const incomingAutoAggregation = this.changedDateContext.autoAggregation ?? null;\n this.isAutoModeActive.set(!!incomingAutoAggregation);\n this.update(\n {\n date: [this.changedDateContext.dateFrom, this.changedDateContext.dateTo],\n interval: this.changedDateContext.interval,\n realtime: this.changedDateContext.realtime || false,\n aggregation: incomingAutoAggregation ? null : this.changedDateContext.aggregation,\n autoAggregation: incomingAutoAggregation\n },\n false\n );\n if (this.changedDateContext.realtime) {\n this.form.controls.aggregation.disable();\n }\n }\n }\n\n /** Called by the aggregation picker's (autoModeChange) output. */\n onAutoModeChange(isAuto: boolean): void {\n this.isAutoModeActive.set(isAuto);\n this.update({\n date: [\n new Date(this.form.value.currentDateContextFromDate),\n new Date(this.form.value.currentDateContextToDate)\n ],\n interval: this.form.value.currentDateContextInterval,\n realtime: this.form.value.realtime,\n aggregation: isAuto ? null : this.form.value.aggregation,\n autoAggregation: isAuto ? this.buildAutoAggregationConfig() : null\n });\n }\n\n applyDatetimeContext(): void {\n const isAuto = this.isAutoModeActive();\n this.update({\n date: [\n new Date(this.form.controls.temporaryUserSelectedFromDate.value),\n new Date(this.form.controls.temporaryUserSelectedToDate.value)\n ],\n interval: 'custom',\n realtime: this.form.value.realtime,\n aggregation: isAuto ? null : this.form.value.aggregation,\n autoAggregation: isAuto ? this.buildAutoAggregationConfig() : null\n });\n }\n\n stopRealtime(): void {\n this.realtimeSubscription?.unsubscribe();\n this.form?.controls.temporaryUserSelectedFromDate.enable();\n this.form?.controls.temporaryUserSelectedToDate.enable();\n this.form?.controls.aggregation.enable();\n // Update the form value without triggering valueChanges to avoid infinite loop\n if (this.form?.value.realtime) {\n this.form.patchValue({ realtime: false }, { emitEvent: false });\n }\n }\n\n private subscribeToIntervalChange(): void {\n this.form.controls.currentDateContextInterval.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(interval => {\n let date: DateTimeContext;\n // Only reset initialTimeRange for preset intervals, not 'custom'\n // Custom interval is set by user slider interaction, which shouldn't reset the chart\n if (interval !== 'custom') {\n this.widgetTimeContextDateRangeService.updateInitialTimeRange(null);\n }\n if (interval === 'custom') {\n date = [\n new Date(this.form.controls.currentDateContextFromDate.value),\n new Date(this.form.controls.currentDateContextToDate.value)\n ];\n } else {\n date = this.datapointExplorerService.getDateTimeContextByInterval(\n interval as Interval['id']\n );\n this.dropdown.isOpen = false;\n }\n this.update({\n date,\n interval,\n realtime: this.form.value.realtime,\n aggregation: this.isAutoModeActive() ? null : this.form.value.aggregation,\n autoAggregation: this.isAutoModeActive() ? this.buildAutoAggregationConfig() : null\n });\n });\n }\n\n private subscribeToRealtimeChange(): void {\n this.form.controls.realtime.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(realtime => {\n this.onRealtimeValueChange(realtime as boolean);\n\n if (realtime) {\n this.startRealtime();\n } else {\n this.stopRealtime();\n }\n });\n }\n\n private subscribeToAggregationChange() {\n this.form.controls.aggregation.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(aggregation => {\n // Skip during auto mode transitions — onAutoModeChange handles the update\n if (this.isAutoModeActive()) {\n return;\n }\n this.update({\n date: [\n new Date(this.form.value.currentDateContextFromDate),\n new Date(this.form.value.currentDateContextToDate)\n ],\n interval: this.form.value.currentDateContextInterval,\n realtime: this.form.value.realtime,\n aggregation,\n autoAggregation: null\n });\n });\n }\n\n private subscribeToDatapointsChange(): void {\n this.form.controls.autoAggregationDatapoints.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef), debounceTime(TIMING.TYPING_DEBOUNCE))\n .subscribe(datapoints => {\n if (!this.isAutoModeActive()) {\n return;\n }\n // Skip while the field is empty or out of range — the user is still typing. Rewriting\n // or emitting a clamped value here would snap the field back mid-edit;\n // commitDatapoints() (blur) commits a valid value instead.\n if (!this.isValidDatapoints(datapoints)) {\n return;\n }\n this.emitAutoAggregationUpdate();\n });\n }\n\n private isValidDatapoints(value: number | null | undefined): value is number {\n return (\n typeof value === 'number' &&\n !Number.isNaN(value) &&\n value >= AUTO_AGGREGATION_DATAPOINTS.MIN &&\n value <= AUTO_AGGREGATION_DATAPOINTS.MAX\n );\n }\n\n private clampToDatapointsBounds(value: number): number {\n return Math.min(\n AUTO_AGGREGATION_DATAPOINTS.MAX,\n Math.max(AUTO_AGGREGATION_DATAPOINTS.MIN, value)\n );\n }\n\n private subscribeToKeepDataOnZoomInChange(): void {\n this.form.controls.autoAggregationKeepDataOnZoomIn.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(() => {\n if (!this.isAutoModeActive()) {\n return;\n }\n this.emitAutoAggregationUpdate();\n });\n }\n\n private emitAutoAggregationUpdate(): void {\n this.update({\n date: [\n new Date(this.form.value.currentDateContextFromDate),\n new Date(this.form.value.currentDateContextToDate)\n ],\n interval: this.form.value.currentDateContextInterval,\n realtime: this.form.value.realtime,\n aggregation: null,\n autoAggregation: this.buildAutoAggregationConfig()\n });\n }\n\n /**\n * Builds the auto-aggregation config from the current form state, clamped to the allowed\n * range. Falls back to the last applied value while the field is empty (mid-edit).\n *\n * Reads control values instead of `this.form.value`: a control's valueChanges fires before\n * the parent group recomputes its cached value, so the group value is stale inside the\n * subscriptions that call this method.\n */\n private buildAutoAggregationConfig(): AutoAggregationConfig {\n const datapoints = this.clampToDatapointsBounds(\n this.form.controls.autoAggregationDatapoints.value ?? this.lastAppliedDatapoints\n );\n return {\n datapoints,\n keepDataOnZoomIn: this.form.controls.autoAggregationKeepDataOnZoomIn.value ?? true\n };\n }\n\n private onRealtimeValueChange(realtime: boolean): void {\n let dateTimeContext: DateTimeContext;\n if (this.form.value.currentDateContextInterval !== 'custom') {\n dateTimeContext = this.datapointExplorerService.getDateTimeContextByInterval(\n this.form.value.currentDateContextInterval as Interval['id']\n );\n } else {\n const currentTimeSpanInMs =\n new Date(this.form.value.currentDateContextToDate).valueOf() -\n new Date(this.form.value.currentDateContextFromDate).valueOf();\n const dateTo = new Date();\n const dateFrom = new Date(dateTo.valueOf() - currentTimeSpanInMs);\n dateTimeContext = [dateFrom, dateTo];\n }\n\n this.isAutoModeActive.set(false);\n this.update({\n date: dateTimeContext,\n interval: this.form.value.currentDateContextInterval,\n realtime,\n aggregation: null,\n autoAggregation: null\n });\n }\n\n private startRealtime(): void {\n this.form.controls.temporaryUserSelectedFromDate.disable();\n this.form.controls.temporaryUserSelectedToDate.disable();\n this.form.controls.aggregation.disable();\n\n this.realtimeSubscription = interval(this.REALTIME_INTERVAL)\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(() => {\n if (!this.form.value.realtime) {\n this.realtimeSubscription.unsubscribe();\n return;\n }\n const newDateFrom = new Date(\n new Date(this.form.value.currentDateContextFromDate).valueOf() + this.REALTIME_INTERVAL\n );\n const newDateTo = new Date(\n new Date(this.form.value.currentDateContextToDate).valueOf() + this.REALTIME_INTERVAL\n );\n this.updateFormValues(\n {\n date: [newDateFrom, newDateTo],\n interval: this.form.value.currentDateContextInterval,\n realtime: true,\n aggregation: null\n },\n false\n ); // Don't emit during automatic realtime ticks\n });\n }\n\n private update(\n { date, interval, realtime, aggregation, autoAggregation = null },\n shouldEmit = true\n ): void {\n const { selectedAggregation, disabledAggregations } =\n this.datapointExplorerService.calculateAggregation(\n date,\n autoAggregation ? null : aggregation\n );\n this.disabledAggregations = disabledAggregations;\n this.updateFormValues(\n { date, interval, realtime, aggregation: selectedAggregation, autoAggregation },\n shouldEmit\n );\n }\n\n private createForm(context) {\n return this.formBuilder.group({\n temporaryUserSelectedFromDate: context.date[0].toISOString() as string,\n temporaryUserSelectedToDate: context.date[1].toISOString() as string,\n currentDateContextFromDate: context.date[0].toISOString() as string,\n currentDateContextToDate: context.date[1].toISOString() as string,\n currentDateContextInterval: context.interval || 'custom',\n realtime: context.realtime,\n aggregation: context.aggregation,\n autoAggregationEnabled: false,\n autoAggregationDatapoints: AUTO_AGGREGATION_DATAPOINTS.DEFAULT as number,\n autoAggregationKeepDataOnZoomIn: true\n });\n }\n\n private updateFormValues(\n { date, interval, realtime, aggregation, autoAggregation = null },\n shouldEmit = true\n ): void {\n const newFormValues = {\n temporaryUserSelectedFromDate: date[0].toISOString() as string,\n temporaryUserSelectedToDate: date[1].toISOString() as string,\n currentDateContextFromDate: date[0].toISOString() as string,\n currentDateContextToDate: date[1].toISOString() as string,\n realtime,\n currentDateContextInterval: interval || 'custom',\n aggregation: autoAggregation ? null : aggregation || null,\n autoAggregation\n };\n\n if (shouldEmit) {\n this.context.set(newFormValues);\n }\n if (autoAggregation?.datapoints != null) {\n this.lastAppliedDatapoints = this.clampToDatapointsBounds(autoAggregation.datapoints);\n }\n this.form.patchValue(\n {\n ...newFormValues,\n autoAggregationEnabled: !!autoAggregation,\n autoAggregationDatapoints:\n autoAggregation?.datapoints ?? this.form.value.autoAggregationDatapoints,\n autoAggregationKeepDataOnZoomIn:\n autoAggregation?.keepDataOnZoomIn ?? this.form.value.autoAggregationKeepDataOnZoomIn\n },\n { emitEvent: false }\n );\n }\n}\n","@if (controlsAvailable) {\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n} @else {\n <c8y-action-bar-item\n [groupId]=\"'timeContext'\"\n [inGroupPriority]=\"1\"\n [placement]=\"'left'\"\n itemClass=\"navbar-form\"\n >\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n </c8y-action-bar-item>\n}\n\n<ng-template\n #dateTimePicker\n let-date=\"date\"\n>\n <form\n class=\"d-flex gap-8 p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n [formGroup]=\"form\"\n >\n <ng-container>\n @if (date) {\n <div\n class=\"dropdown flex-grow\"\n #dropdown=\"bs-dropdown\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ date[0] | c8yDate: DATE_FORMAT }} — {{\n date[1] | c8yDate: DATE_FORMAT\n }}\"\n tooltip=\"{{ date[0] | c8yDate: DATE_FORMAT }} — {{ date[1] | c8yDate: DATE_FORMAT }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"widget-time-context--date-picker-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-8\"\n c8yIcon=\"schedule1\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span\n class=\"text-muted fit-w text-10 l-h-1\"\n data-cy=\"widget-time-context--selected-interval\"\n >\n {{ INTERVAL_TITLES[form.controls.currentDateContextInterval.value] | translate }}\n </span>\n <span\n class=\"text-bold text-12 fit-w l-h-1 text-truncate\"\n data-cy=\"widget-time-context--selected-time-range\"\n >\n {{ date[0] | c8yDate: DATE_FORMAT }} — {{ date[1] | c8yDate: DATE_FORMAT }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n\n <ul\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu--date-range\"\n *dropdownMenu\n >\n <c8y-interval-picker\n class=\"d-contents\"\n formControlName=\"currentDateContextInterval\"\n ></c8y-interval-picker>\n\n @if (form.controls.currentDateContextInterval.value === 'custom') {\n <div class=\"p-l-16 p-r-16\">\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'From`date`' | translate\"\n for=\"temporaryUserSelectedFromDate\"\n translate\n >\n From`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedFromDate\"\n [maxDate]=\"form.value.temporaryUserSelectedToDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'From`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedFromDate\"\n [ngClass]=\"\n form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\n \"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedFromDate.errors\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"'This date is after the latest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'To`date`' | translate\"\n for=\"temporaryUserSelectedToDate\"\n translate\n >\n To`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedToDate\"\n [minDate]=\"form.value.temporaryUserSelectedFromDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'To`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedToDate\"\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedToDate.errors\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"'This date is before the earliest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n\n <div class=\"p-16 d-flex gap-8 separator-top\">\n <button\n class=\"btn btn-default btn-sm flex-grow\"\n title=\"{{ 'Reset' | translate }}\"\n type=\"button\"\n (click)=\"dropdown.isOpen = false\"\n [disabled]=\"form.value.realtime\"\n translate\n >\n Reset\n </button>\n\n <button\n class=\"btn btn-primary btn-sm flex-grow\"\n title=\"{{ 'Apply' | translate }}\"\n type=\"button\"\n (click)=\"applyDatetimeContext(); dropdown.isOpen = false\"\n [disabled]=\"\n (form.pristine && form.untouched) || form.invalid || form.value.realtime\n \"\n translate\n >\n Apply\n </button>\n </div>\n }\n </ul>\n </div>\n }\n </ng-container>\n\n <div class=\"input-group w-auto\">\n <c8y-realtime-control\n class=\"form-control p-0 flex-no-grow w-auto\"\n formControlName=\"realtime\"\n ></c8y-realtime-control>\n\n @if (enableAutoAggregation && isTimeSeriesMigrated()) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [showAutoMode]=\"true\"\n [autoModeActive]=\"isAutoModeActive()\"\n [autoPoints]=\"form.value.autoAggregationDatapoints\"\n [autoKeepPointCount]=\"form.value.autoAggregationKeepDataOnZoomIn\"\n [disabledAggregations]=\"disabledAggregations\"\n (autoModeChange)=\"onAutoModeChange($event)\"\n >\n <div\n class=\"d-col\"\n autoAggregationOptions\n >\n <div class=\"d-flex a-i-center gap-8\">\n <label class=\"m-b-0 m-r-8\">\n {{ 'Points per chart' | translate }}\n </label>\n <input\n class=\"form-control input-sm\"\n style=\"width: 80px\"\n [attr.title]=\"\n 'Enter a value between {{ min }} and {{ max }}.'\n | translate\n : {\n min: AUTO_AGGREGATION_DATAPOINTS.MIN,\n max: AUTO_AGGREGATION_DATAPOINTS.MAX\n }\n \"\n [attr.aria-label]=\"'Points per chart' | translate\"\n type=\"number\"\n [min]=\"AUTO_AGGREGATION_DATAPOINTS.MIN\"\n [max]=\"AUTO_AGGREGATION_DATAPOINTS.MAX\"\n [step]=\"AUTO_AGGREGATION_DATAPOINTS.STEP\"\n [formControl]=\"form.controls.autoAggregationDatapoints\"\n />\n </div>\n <label\n class=\"c8y-switch m-b-0 m-t-8 text-nowrap\"\n [title]=\"'Keep point count on zoom' | translate\"\n >\n <input\n type=\"checkbox\"\n [formControl]=\"form.controls.autoAggregationKeepDataOnZoomIn\"\n data-cy=\"time-context--auto-aggregation-keep-data-on-zoom-in\"\n />\n <span></span>\n <span class=\"text-12\">{{ 'Keep point count on zoom' | translate }}</span>\n <button\n class=\"btn-help btn-help--sm m-l-4\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"KEEP_DATA_ON_ZOOM_IN_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </label>\n </div>\n </c8y-aggregation-picker>\n } @else if (\n enableAutoAggregation || (controlsAvailable ? controlsAvailable.aggregation : true)\n ) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [disabledAggregations]=\"disabledAggregations\"\n ></c8y-aggregation-picker>\n }\n\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"AGGREGATION_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </form>\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;MAYa,wBAAwB,CAAA;AADrC,IAAA,WAAA,GAAA;QAEW,IAAA,CAAA,gBAAgB,GAAmB,MAAM;AA0FnD,IAAA;;AAvFC,IAAA,iBAAiB,CAAC,SAAgC,EAAA;QAChD,OAAO;AACL,YAAA,IAAI,EAAE,IAAI,CAAC,4BAA4B,CAAC,SAAS,EAAE,QAAQ,IAAI,IAAI,CAAC,gBAAgB,CAAC;YACrF,QAAQ,EAAE,IAAI,CAAC,gBAAgB;AAC/B,YAAA,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,eAAe,CAAC,QAAQ;AACrC,YAAA,GAAG;SACJ;IACH;AAEA,IAAA,oBAAoB,CAClB,CAAC,QAAQ,EAAE,MAAM,CAAkB,EACnC,oBAA4C,EAAA;AAK5C,QAAA,MAAM,oBAAoB,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACxE,MAAM,oBAAoB,GAAG,IAAI,CAAC,uBAAuB,CAAC,oBAAoB,CAAC;QAE/E,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC;QAE7D,MAAM,2BAA2B,GAC/B,oBAAoB,KAAK,IAAI,IAAI,CAAC,oBAAoB,CAAC,oBAAoB,CAAC;QAE9E,MAAM,mBAAmB,GAAG;AAC1B,cAAE;AACF,cAAE,IAAI,CAAC,oBAAoB,CAAC,aAAa,CAAC;QAE5C,OAAO;YACL,mBAAmB;YACnB;SACD;IACH;AAEA,IAAA,4BAA4B,CAAC,UAA0B,EAAA;AACrD,QAAA,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,UAAU,CAAC;AAC9D,QAAA,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE;AACzB,QAAA,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,YAAY,CAAC;AACnE,QAAA,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC3B;IAEQ,gBAAgB,CAAC,QAAc,EAAE,MAAY,EAAA;QACnD,OAAO,MAAM,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE;IAC9C;AAEQ,IAAA,kBAAkB,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAkB,EAAA;QAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC;QAE7D,OAAO;AACL,YAAA;gBACE,eAAe,EAAE,eAAe,CAAC,KAAK;AACtC,gBAAA,UAAU,EAAE,aAAa,IAAI,YAAY,CAAC;AAC3C,aAAA;AACD,YAAA;gBACE,eAAe,EAAE,eAAe,CAAC,MAAM;AACvC,gBAAA,UAAU,EAAE,aAAa,IAAI,YAAY,CAAC;AAC3C,aAAA;AACD,YAAA;gBACE,eAAe,EAAE,eAAe,CAAC,QAAQ;AACzC,gBAAA,UAAU,EAAE,aAAa,IAAI,YAAY,CAAC;AAC3C;SACF;IACH;AAEQ,IAAA,uBAAuB,CAC7B,oBAA2C,EAAA;AAE3C,QAAA,OAAO,oBAAoB,CAAC,MAAM,CAChC,CAAC,GAAG,EAAE,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM;AACzC,YAAA,GAAG,GAAG;YACN,CAAC,eAAe,GAAG;SACpB,CAAC,EACF,EAAE,CACH;IACH;AAEQ,IAAA,oBAAoB,CAAC,aAAqB,EAAA;AAChD,QAAA,IAAI,aAAa,IAAI,kBAAkB,CAAC,WAAW,EAAE;YACnD,OAAO,eAAe,CAAC,KAAK;QAC9B;AAAO,aAAA,IAAI,aAAa,IAAI,kBAAkB,CAAC,YAAY,EAAE;YAC3D,OAAO,eAAe,CAAC,MAAM;QAC/B;AAAO,aAAA,IAAI,aAAa,IAAI,kBAAkB,CAAC,cAAc,EAAE;YAC7D,OAAO,eAAe,CAAC,QAAQ;QACjC;AACA,QAAA,OAAO,IAAI;IACb;+GA1FW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAxB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,wBAAwB,cADX,MAAM,EAAA,CAAA,CAAA;;4FACnB,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBADpC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACgClC;MAiBa,oBAAoB,CAAA;AAoB/B,IAAA,WAAW;AACX,IAAA,2BAA2B;AA+B3B,IAAA,WAAA,CAAoB,iCAAoE,EAAA;QAApE,IAAA,CAAA,iCAAiC,GAAjC,iCAAiC;QA1C5C,IAAA,CAAA,WAAW,GAAyB,EAAE;AACtC,QAAA,IAAA,CAAA,gBAAgB,GAAuB;AAC9C,YAAA,WAAW,EAAE,IAAI;AACjB,YAAA,WAAW,EAAE,KAAK;AAClB,YAAA,YAAY,EAAE;SACf;QACQ,IAAA,CAAA,qBAAqB,GAAG,KAAK;AAEtC,QAAA,IAAA,CAAA,wBAAwB,GAAG,MAAM,CAAC,wBAAwB,CAAC;AAC3D,QAAA,IAAA,CAAA,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AACjC,QAAA,IAAA,CAAA,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC;AAChC,QAAA,IAAA,CAAA,2BAA2B,GAAG,MAAM,CAAC,0BAA0B,CAAC;QAEvD,IAAA,CAAA,WAAW,GAAG,OAAO;QACrB,IAAA,CAAA,eAAe,GAAG,eAAe;QACjC,IAAA,CAAA,iBAAiB,GAAG,IAAI;QACxB,IAAA,CAAA,2BAA2B,GAAG,2BAA2B;QACzD,IAAA,CAAA,mBAAmB,GAAG,wBAAwB;AAC9C,QAAA,IAAA,CAAA,4BAA4B,GAAG,OAAO,CAC7C,+LAA+L,CAChM;;AAEQ,QAAA,IAAA,CAAA,gBAAgB,GAAG,MAAM,CAAC,KAAK,uFAAC;AACzC;;;AAGG;AACM,QAAA,IAAA,CAAA,oBAAoB,GAAG,MAAM,CAAC,KAAK,2FAAC;AAC7C,QAAA,IAAA,CAAA,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,wBAAwB,CAAC,iBAAiB,EAAE,CAAC;;AAIjE,QAAA,IAAA,CAAA,qBAAqB,GAAW,2BAA2B,CAAC,OAAO;AAElE,QAAA,IAAA,CAAA,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC,YAAY,EAAE;YAC3F,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC;AAC7D,SAAA,CAAC;QAEF,IAAA,CAAA,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,SAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAC;IAI2D;IAE3F,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,wBAAwB,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACvF,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,wBAAwB,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC;AACjF,QAAA,MAAM,EAAE,oBAAoB,EAAE,GAAG,IAAI,CAAC,wBAAwB,CAAC,oBAAoB,CACjF,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,WAAW,CACpB;AACD,QAAA,IAAI,CAAC,oBAAoB,GAAG,oBAAoB;AAEhD,QAAA,IAAI,CAAC;AACF,aAAA,oBAAoB;AACpB,aAAA,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAEhE,IAAI,CAAC,yBAAyB,EAAE;QAChC,IAAI,CAAC,yBAAyB,EAAE;QAChC,IAAI,CAAC,4BAA4B,EAAE;QACnC,IAAI,CAAC,2BAA2B,EAAE;QAClC,IAAI,CAAC,iCAAiC,EAAE;IAC1C;AAEA,IAAA,WAAW,CAAC,OAAsB,EAAA;QAChC,IAAI,OAAO,CAAC,kBAAkB,IAAI,OAAO,CAAC,kBAAkB,CAAC,YAAY,EAAE;;AAEzE,YAAA,IAAI,IAAI,CAAC,kBAAkB,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;gBAChE;YACF;;AAGA,YAAA,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK;YACzC,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,WAAW,EAAE;YACnE,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE;AAE/D,YAAA,MAAM,gBAAgB,GACpB,WAAW,KAAK,iBAAiB,CAAC,0BAA0B;gBAC5D,SAAS,KAAK,iBAAiB,CAAC,wBAAwB;AACxD,gBAAA,IAAI,CAAC,kBAAkB,CAAC,QAAQ,KAAK,iBAAiB,CAAC,0BAA0B;AACjF,gBAAA,IAAI,CAAC,kBAAkB,CAAC,QAAQ,KAAK,iBAAiB,CAAC,QAAQ;AAC/D,gBAAA,IAAI,CAAC,kBAAkB,CAAC,WAAW,KAAK,iBAAiB,CAAC,WAAW;gBACrE,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,eAAe,KAAK,iBAAiB,CAAC,sBAAsB;YAExF,IAAI,CAAC,gBAAgB,EAAE;gBACrB;YACF;;YAGA,MAAM,uBAAuB,GAAG,IAAI,CAAC,kBAAkB,CAAC,eAAe,IAAI,IAAI;YAC/E,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,uBAAuB,CAAC;YACpD,IAAI,CAAC,MAAM,CACT;AACE,gBAAA,IAAI,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC;AACxE,gBAAA,QAAQ,EAAE,IAAI,CAAC,kBAAkB,CAAC,QAAQ;AAC1C,gBAAA,QAAQ,EAAE,IAAI,CAAC,kBAAkB,CAAC,QAAQ,IAAI,KAAK;AACnD,gBAAA,WAAW,EAAE,uBAAuB,GAAG,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,WAAW;AACjF,gBAAA,eAAe,EAAE;aAClB,EACD,KAAK,CACN;AACD,YAAA,IAAI,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE;gBACpC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE;YAC1C;QACF;IACF;;AAGA,IAAA,gBAAgB,CAAC,MAAe,EAAA;AAC9B,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC;AACV,YAAA,IAAI,EAAE;gBACJ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC;gBACpD,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,wBAAwB;AAClD,aAAA;AACD,YAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B;AACpD,YAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;AAClC,YAAA,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW;AACxD,YAAA,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC,0BAA0B,EAAE,GAAG;AAC/D,SAAA,CAAC;IACJ;IAEA,oBAAoB,GAAA;AAClB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE;QACtC,IAAI,CAAC,MAAM,CAAC;AACV,YAAA,IAAI,EAAE;gBACJ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,6BAA6B,CAAC,KAAK,CAAC;gBAChE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,2BAA2B,CAAC,KAAK;AAC9D,aAAA;AACD,YAAA,QAAQ,EAAE,QAAQ;AAClB,YAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;AAClC,YAAA,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW;AACxD,YAAA,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC,0BAA0B,EAAE,GAAG;AAC/D,SAAA,CAAC;IACJ;IAEA,YAAY,GAAA;AACV,QAAA,IAAI,CAAC,oBAAoB,EAAE,WAAW,EAAE;QACxC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,6BAA6B,CAAC,MAAM,EAAE;QAC1D,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,2BAA2B,CAAC,MAAM,EAAE;QACxD,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE;;QAExC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE;AAC7B,YAAA,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACjE;IACF;IAEQ,yBAAyB,GAAA;AAC/B,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC;AAC3C,aAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC;aACzC,SAAS,CAAC,QAAQ,IAAG;AACpB,YAAA,IAAI,IAAqB;;;AAGzB,YAAA,IAAI,QAAQ,KAAK,QAAQ,EAAE;AACzB,gBAAA,IAAI,CAAC,iCAAiC,CAAC,sBAAsB,CAAC,IAAI,CAAC;YACrE;AACA,YAAA,IAAI,QAAQ,KAAK,QAAQ,EAAE;AACzB,gBAAA,IAAI,GAAG;oBACL,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC,KAAK,CAAC;oBAC7D,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,wBAAwB,CAAC,KAAK;iBAC3D;YACH;iBAAO;gBACL,IAAI,GAAG,IAAI,CAAC,wBAAwB,CAAC,4BAA4B,CAC/D,QAA0B,CAC3B;AACD,gBAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK;YAC9B;YACA,IAAI,CAAC,MAAM,CAAC;gBACV,IAAI;gBACJ,QAAQ;AACR,gBAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;AAClC,gBAAA,WAAW,EAAE,IAAI,CAAC,gBAAgB,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW;AACzE,gBAAA,eAAe,EAAE,IAAI,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,0BAA0B,EAAE,GAAG;AAChF,aAAA,CAAC;AACJ,QAAA,CAAC,CAAC;IACN;IAEQ,yBAAyB,GAAA;AAC/B,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;AACzB,aAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC;aACzC,SAAS,CAAC,QAAQ,IAAG;AACpB,YAAA,IAAI,CAAC,qBAAqB,CAAC,QAAmB,CAAC;YAE/C,IAAI,QAAQ,EAAE;gBACZ,IAAI,CAAC,aAAa,EAAE;YACtB;iBAAO;gBACL,IAAI,CAAC,YAAY,EAAE;YACrB;AACF,QAAA,CAAC,CAAC;IACN;IAEQ,4BAA4B,GAAA;AAClC,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;AAC5B,aAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC;aACzC,SAAS,CAAC,WAAW,IAAG;;AAEvB,YAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE;gBAC3B;YACF;YACA,IAAI,CAAC,MAAM,CAAC;AACV,gBAAA,IAAI,EAAE;oBACJ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC;oBACpD,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,wBAAwB;AAClD,iBAAA;AACD,gBAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B;AACpD,gBAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAClC,WAAW;AACX,gBAAA,eAAe,EAAE;AAClB,aAAA,CAAC;AACJ,QAAA,CAAC,CAAC;IACN;IAEQ,2BAA2B,GAAA;AACjC,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC;AAC1C,aAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,eAAe,CAAC;aAC/E,SAAS,CAAC,UAAU,IAAG;AACtB,YAAA,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE;gBAC5B;YACF;;;;YAIA,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE;gBACvC;YACF;YACA,IAAI,CAAC,yBAAyB,EAAE;AAClC,QAAA,CAAC,CAAC;IACN;AAEQ,IAAA,iBAAiB,CAAC,KAAgC,EAAA;AACxD,QAAA,QACE,OAAO,KAAK,KAAK,QAAQ;AACzB,YAAA,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YACpB,KAAK,IAAI,2BAA2B,CAAC,GAAG;AACxC,YAAA,KAAK,IAAI,2BAA2B,CAAC,GAAG;IAE5C;AAEQ,IAAA,uBAAuB,CAAC,KAAa,EAAA;AAC3C,QAAA,OAAO,IAAI,CAAC,GAAG,CACb,2BAA2B,CAAC,GAAG,EAC/B,IAAI,CAAC,GAAG,CAAC,2BAA2B,CAAC,GAAG,EAAE,KAAK,CAAC,CACjD;IACH;IAEQ,iCAAiC,GAAA;AACvC,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,+BAA+B,CAAC;AAChD,aAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC;aACzC,SAAS,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE;gBAC5B;YACF;YACA,IAAI,CAAC,yBAAyB,EAAE;AAClC,QAAA,CAAC,CAAC;IACN;IAEQ,yBAAyB,GAAA;QAC/B,IAAI,CAAC,MAAM,CAAC;AACV,YAAA,IAAI,EAAE;gBACJ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC;gBACpD,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,wBAAwB;AAClD,aAAA;AACD,YAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B;AACpD,YAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;AAClC,YAAA,WAAW,EAAE,IAAI;AACjB,YAAA,eAAe,EAAE,IAAI,CAAC,0BAA0B;AACjD,SAAA,CAAC;IACJ;AAEA;;;;;;;AAOG;IACK,0BAA0B,GAAA;QAChC,MAAM,UAAU,GAAG,IAAI,CAAC,uBAAuB,CAC7C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC,KAAK,IAAI,IAAI,CAAC,qBAAqB,CACjF;QACD,OAAO;YACL,UAAU;YACV,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,+BAA+B,CAAC,KAAK,IAAI;SAC/E;IACH;AAEQ,IAAA,qBAAqB,CAAC,QAAiB,EAAA;AAC7C,QAAA,IAAI,eAAgC;QACpC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,KAAK,QAAQ,EAAE;AAC3D,YAAA,eAAe,GAAG,IAAI,CAAC,wBAAwB,CAAC,4BAA4B,CAC1E,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA4C,CAC7D;QACH;aAAO;AACL,YAAA,MAAM,mBAAmB,GACvB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,OAAO,EAAE;AAC5D,gBAAA,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,OAAO,EAAE;AAChE,YAAA,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE;AACzB,YAAA,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,mBAAmB,CAAC;AACjE,YAAA,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC;QACtC;AAEA,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC;AACV,YAAA,IAAI,EAAE,eAAe;AACrB,YAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B;YACpD,QAAQ;AACR,YAAA,WAAW,EAAE,IAAI;AACjB,YAAA,eAAe,EAAE;AAClB,SAAA,CAAC;IACJ;IAEQ,aAAa,GAAA;QACnB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,6BAA6B,CAAC,OAAO,EAAE;QAC1D,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,2BAA2B,CAAC,OAAO,EAAE;QACxD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE;QAExC,IAAI,CAAC,oBAAoB,GAAG,QAAQ,CAAC,IAAI,CAAC,iBAAiB;AACxD,aAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC;aACzC,SAAS,CAAC,MAAK;YACd,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;AAC7B,gBAAA,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE;gBACvC;YACF;YACA,MAAM,WAAW,GAAG,IAAI,IAAI,CAC1B,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,iBAAiB,CACxF;YACD,MAAM,SAAS,GAAG,IAAI,IAAI,CACxB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,iBAAiB,CACtF;YACD,IAAI,CAAC,gBAAgB,CACnB;AACE,gBAAA,IAAI,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;AAC9B,gBAAA,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B;AACpD,gBAAA,QAAQ,EAAE,IAAI;AACd,gBAAA,WAAW,EAAE;AACd,aAAA,EACD,KAAK,CACN,CAAC;AACJ,QAAA,CAAC,CAAC;IACN;AAEQ,IAAA,MAAM,CACZ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,GAAG,IAAI,EAAE,EACjE,UAAU,GAAG,IAAI,EAAA;QAEjB,MAAM,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,GACjD,IAAI,CAAC,wBAAwB,CAAC,oBAAoB,CAChD,IAAI,EACJ,eAAe,GAAG,IAAI,GAAG,WAAW,CACrC;AACH,QAAA,IAAI,CAAC,oBAAoB,GAAG,oBAAoB;AAChD,QAAA,IAAI,CAAC,gBAAgB,CACnB,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,eAAe,EAAE,EAC/E,UAAU,CACX;IACH;AAEQ,IAAA,UAAU,CAAC,OAAO,EAAA;AACxB,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;YAC5B,6BAA6B,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAY;YACtE,2BAA2B,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAY;YACpE,0BAA0B,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAY;YACnE,wBAAwB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAY;AACjE,YAAA,0BAA0B,EAAE,OAAO,CAAC,QAAQ,IAAI,QAAQ;YACxD,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;AAChC,YAAA,sBAAsB,EAAE,KAAK;YAC7B,yBAAyB,EAAE,2BAA2B,CAAC,OAAiB;AACxE,YAAA,+BAA+B,EAAE;AAClC,SAAA,CAAC;IACJ;AAEQ,IAAA,gBAAgB,CACtB,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,GAAG,IAAI,EAAE,EACjE,UAAU,GAAG,IAAI,EAAA;AAEjB,QAAA,MAAM,aAAa,GAAG;AACpB,YAAA,6BAA6B,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAY;AAC9D,YAAA,2BAA2B,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAY;AAC5D,YAAA,0BAA0B,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAY;AAC3D,YAAA,wBAAwB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAY;YACzD,QAAQ;YACR,0BAA0B,EAAE,QAAQ,IAAI,QAAQ;YAChD,WAAW,EAAE,eAAe,GAAG,IAAI,GAAG,WAAW,IAAI,IAAI;YACzD;SACD;QAED,IAAI,UAAU,EAAE;AACd,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QACjC;AACA,QAAA,IAAI,eAAe,EAAE,UAAU,IAAI,IAAI,EAAE;YACvC,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,uBAAuB,CAAC,eAAe,CAAC,UAAU,CAAC;QACvF;AACA,QAAA,IAAI,CAAC,IAAI,CAAC,UAAU,CAClB;AACE,YAAA,GAAG,aAAa;YAChB,sBAAsB,EAAE,CAAC,CAAC,eAAe;YACzC,yBAAyB,EACvB,eAAe,EAAE,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,yBAAyB;YAC1E,+BAA+B,EAC7B,eAAe,EAAE,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;AACxD,SAAA,EACD,EAAE,SAAS,EAAE,KAAK,EAAE,CACrB;IACH;+GAhaW,oBAAoB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,iCAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAApB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,kjCAiBpB,mBAAmB,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC7EhC,uqUAyQA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EDxNI,UAAU,i+GACV,kBAAkB,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAClB,oBAAoB,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACpB,gBAAgB,slBAEhB,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,MAAA,EAAA,CAAA,kBAAA,EAAA,SAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,YAAA,EAAA,OAAA,EAAA,aAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,eAAA,EAAA,qBAAA,EAAA,kBAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,mBAAA,EAAA,qBAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,EAAA,SAAA,EAAA,UAAA,EAAA,qBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACb,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,kBAAA,EAAA,mBAAA,EAAA,SAAA,EAAA,gBAAA,EAAA,cAAA,EAAA,WAAA,EAAA,cAAA,EAAA,UAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACb,uBAAuB,uFACvB,wBAAwB,EAAA,QAAA,EAAA,sBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,IAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,EAAA,CAAA,QAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,EAAA,CAAA,CAAA;;4FAGf,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAhBhC,SAAS;+BACE,kBAAkB,EAAA,UAAA,EAEhB,IAAI,EAAA,OAAA,EACP;wBACP,UAAU;wBACV,kBAAkB;wBAClB,oBAAoB;wBACpB,gBAAgB;wBAChB,0BAA0B;wBAC1B,aAAa;wBACb,aAAa;wBACb,uBAAuB;wBACvB;AACD,qBAAA,EAAA,QAAA,EAAA,uqUAAA,EAAA;;sBAGA;;sBAQA;;sBACA;;sBACA;;sBAKA;;sBACA,SAAS;uBAAC,mBAAmB;;;AE7EhC;;AAEG;;;;"}
1
+ {"version":3,"file":"c8y-ngx-components-time-context.mjs","sources":["../../time-context/time-context.service.ts","../../time-context/time-context.component.ts","../../time-context/time-context.component.html","../../time-context/c8y-ngx-components-time-context.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { aggregationType } from '@c8y/client';\nimport { AGGREGATION_LIMITS, DateTimeContext } from '@c8y/ngx-components';\nimport { Interval, INTERVALS, TimeSpanInMs } from '@c8y/ngx-components/interval-picker';\nimport { TimeContext } from './time-context.model';\n\ninterface TimeRangeValidation {\n aggregationType: aggregationType;\n isDisabled: boolean;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class DatapointExplorerService {\n readonly DEFAULT_INTERVAL: Interval['id'] = 'days';\n\n // Create generic? Based on packages/ngx-components/core/dashboard/wiget-time-context/widget-time-context.component.html\n getDefaultContext(overrides?: Partial<TimeContext>): TimeContext {\n return {\n date: this.getDateTimeContextByInterval(overrides?.interval ?? this.DEFAULT_INTERVAL),\n interval: this.DEFAULT_INTERVAL,\n realtime: false,\n aggregation: aggregationType.MINUTELY,\n ...overrides\n };\n }\n\n calculateAggregation(\n [dateFrom, dateTo]: DateTimeContext,\n requestedAggregation: aggregationType | null\n ): {\n selectedAggregation: aggregationType | null;\n disabledAggregations: Partial<Record<aggregationType, boolean>>;\n } {\n const timeRangeValidations = this.validateTimeRanges([dateFrom, dateTo]);\n const disabledAggregations = this.getDisabledAggregations(timeRangeValidations);\n\n const timeRangeInMs = this.getTimeRangeInMs(dateFrom, dateTo);\n\n const isRequestedAggregationValid =\n requestedAggregation === null || !disabledAggregations[requestedAggregation];\n\n const selectedAggregation = isRequestedAggregationValid\n ? requestedAggregation\n : this.determineAggregation(timeRangeInMs);\n\n return {\n selectedAggregation,\n disabledAggregations\n };\n }\n\n getDateTimeContextByInterval(intervalId: Interval['id']): DateTimeContext {\n const interval = INTERVALS.find(({ id }) => id === intervalId);\n const dateTo = new Date();\n const dateFrom = new Date(dateTo.valueOf() - interval.timespanInMs);\n return [dateFrom, dateTo];\n }\n\n private getTimeRangeInMs(dateFrom: Date, dateTo: Date): number {\n return dateTo.valueOf() - dateFrom.valueOf();\n }\n\n private validateTimeRanges([dateFrom, dateTo]: DateTimeContext): TimeRangeValidation[] {\n const timeRangeInMs = this.getTimeRangeInMs(dateFrom, dateTo);\n\n return [\n {\n aggregationType: aggregationType.DAILY,\n isDisabled: timeRangeInMs <= TimeSpanInMs.DAY\n },\n {\n aggregationType: aggregationType.HOURLY,\n isDisabled: timeRangeInMs <= TimeSpanInMs.HOUR\n },\n {\n aggregationType: aggregationType.MINUTELY,\n isDisabled: timeRangeInMs <= TimeSpanInMs.MINUTE\n }\n ];\n }\n\n private getDisabledAggregations(\n timeRangeValidations: TimeRangeValidation[]\n ): Partial<Record<aggregationType, boolean>> {\n return timeRangeValidations.reduce(\n (acc, { aggregationType, isDisabled }) => ({\n ...acc,\n [aggregationType]: isDisabled\n }),\n {}\n );\n }\n\n private determineAggregation(timeRangeInMs: number): aggregationType | null {\n if (timeRangeInMs >= AGGREGATION_LIMITS.DAILY_LIMIT) {\n return aggregationType.DAILY;\n } else if (timeRangeInMs >= AGGREGATION_LIMITS.HOURLY_LIMIT) {\n return aggregationType.HOURLY;\n } else if (timeRangeInMs >= AGGREGATION_LIMITS.MINUTELY_LIMIT) {\n return aggregationType.MINUTELY;\n }\n return null;\n }\n}\n","import {\n Component,\n DestroyRef,\n inject,\n Input,\n model,\n OnInit,\n signal,\n SimpleChanges,\n ViewChild\n} from '@angular/core';\nimport { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';\nimport { FormBuilder } from '@angular/forms';\nimport {\n AggregationPickerComponent,\n CoreModule,\n DateAndTimeOptions,\n DateTimeContext,\n DateTimePickerModule,\n WidgetTimeContextDateRangeService\n} from '@c8y/ngx-components';\nimport {\n AGGREGATION_POPOVER_TEXT,\n AUTO_AGGREGATION_DATAPOINTS,\n AutoAggregationConfig,\n RealtimeControlComponent,\n TimeSeriesMigrationService,\n TIMING\n} from '@c8y/ngx-components/global-context';\nimport {\n Interval,\n INTERVAL_TITLES,\n IntervalPickerComponent\n} from '@c8y/ngx-components/interval-picker';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { BsDatepickerModule } from 'ngx-bootstrap/datepicker';\nimport { BsDropdownDirective, BsDropdownModule } from 'ngx-bootstrap/dropdown';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\nimport { PopoverModule } from 'ngx-bootstrap/popover';\nimport { debounceTime, interval, Subscription } from 'rxjs';\nimport { TimeContext } from './time-context.model';\nimport { DatapointExplorerService } from './time-context.service';\n\n// TODO: REMOVE THIS FILE\n@Component({\n selector: 'c8y-time-context',\n templateUrl: './time-context.component.html',\n standalone: true,\n imports: [\n CoreModule,\n BsDatepickerModule,\n DateTimePickerModule,\n BsDropdownModule,\n AggregationPickerComponent,\n TooltipModule,\n PopoverModule,\n IntervalPickerComponent,\n RealtimeControlComponent\n ]\n})\nexport class TimeContextComponent implements OnInit {\n @Input() changedDateContext: {\n dateFrom?: Date;\n dateTo?: Date;\n interval?: Interval['id'];\n realtime?: boolean;\n aggregation?: string;\n autoAggregation?: AutoAggregationConfig | null;\n };\n @Input() controlsAvailable: any;\n @Input() timeContext: Partial<TimeContext> = {};\n @Input() timePickerConfig: DateAndTimeOptions = {\n showMinutes: true,\n showSeconds: false,\n showSpinners: false\n };\n @Input() enableAutoAggregation = false;\n @ViewChild(BsDropdownDirective) dropdown: BsDropdownDirective;\n datapointExplorerService = inject(DatapointExplorerService);\n formBuilder = inject(FormBuilder);\n #destroyRef = inject(DestroyRef);\n #timeSeriesMigrationService = inject(TimeSeriesMigrationService);\n\n readonly DATE_FORMAT = 'short';\n readonly INTERVAL_TITLES = INTERVAL_TITLES;\n readonly REALTIME_INTERVAL = 1000;\n readonly AUTO_AGGREGATION_DATAPOINTS = AUTO_AGGREGATION_DATAPOINTS;\n readonly AGGREGATION_POPOVER = AGGREGATION_POPOVER_TEXT;\n readonly KEEP_DATA_ON_ZOOM_IN_POPOVER = gettext(\n 'When enabled, the chart reloads data at a finer or coarser interval as you zoom in or out, so it always shows the number of points you set. When disabled, it reuses the already loaded data.'\n );\n /** Whether auto-aggregation mode is active. */\n readonly isAutoModeActive = signal(false);\n /**\n * The \"Auto\" aggregation option requires the tenant to be migrated to time series\n * (auto mode uses `aggregationInterval`, unsupported on non-migrated tenants).\n */\n readonly isTimeSeriesMigrated = signal(false);\n form = this.createForm(this.datapointExplorerService.getDefaultContext());\n disabledAggregations;\n\n /** Last datapoints value applied to the context; restored when the field is left empty. */\n private lastAppliedDatapoints: number = AUTO_AGGREGATION_DATAPOINTS.DEFAULT;\n\n readonly valuesSignal = toSignal(this.form.controls.currentDateContextFromDate.valueChanges, {\n initialValue: this.form.controls.currentDateContextFromDate.value\n });\n\n context = model(this.form.value);\n\n private realtimeSubscription: Subscription;\n\n constructor(private widgetTimeContextDateRangeService: WidgetTimeContextDateRangeService) {}\n\n ngOnInit(): void {\n this.form.patchValue(this.datapointExplorerService.getDefaultContext(this.timeContext));\n const context = this.datapointExplorerService.getDefaultContext(this.timeContext);\n const { disabledAggregations } = this.datapointExplorerService.calculateAggregation(\n context.date,\n context.aggregation\n );\n this.disabledAggregations = disabledAggregations;\n\n this.#timeSeriesMigrationService\n .isTimeSeriesMigrated()\n .then(isMigrated => this.isTimeSeriesMigrated.set(isMigrated));\n\n this.subscribeToIntervalChange();\n this.subscribeToRealtimeChange();\n this.subscribeToAggregationChange();\n this.subscribeToDatapointsChange();\n this.subscribeToKeepDataOnZoomInChange();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes.changedDateContext && changes.changedDateContext.currentValue) {\n // In realtime mode, ignore updates from parent - the component updates itself via interval\n if (this.changedDateContext.realtime && this.form.value.realtime) {\n return;\n }\n\n // Check if values actually changed (not just object reference)\n const currentFormValues = this.form.value;\n const newDateFrom = this.changedDateContext.dateFrom?.toISOString();\n const newDateTo = this.changedDateContext.dateTo?.toISOString();\n\n const hasActualChanges =\n newDateFrom !== currentFormValues.currentDateContextFromDate ||\n newDateTo !== currentFormValues.currentDateContextToDate ||\n this.changedDateContext.interval !== currentFormValues.currentDateContextInterval ||\n this.changedDateContext.realtime !== currentFormValues.realtime ||\n this.changedDateContext.aggregation !== currentFormValues.aggregation ||\n !!this.changedDateContext.autoAggregation !== currentFormValues.autoAggregationEnabled;\n\n if (!hasActualChanges) {\n return;\n }\n\n // Don't emit when update comes from parent (avoid infinite loop)\n const incomingAutoAggregation = this.changedDateContext.autoAggregation ?? null;\n this.isAutoModeActive.set(!!incomingAutoAggregation);\n this.update(\n {\n date: [this.changedDateContext.dateFrom, this.changedDateContext.dateTo],\n interval: this.changedDateContext.interval,\n realtime: this.changedDateContext.realtime || false,\n aggregation: incomingAutoAggregation ? null : this.changedDateContext.aggregation,\n autoAggregation: incomingAutoAggregation\n },\n false\n );\n // Silent like the update() above: parent-driven changes must not emit back.\n this.setRealtimeControlsLocked(!!this.changedDateContext.realtime, { emitEvent: false });\n }\n }\n\n /** Called by the aggregation picker's (autoModeChange) output. */\n onAutoModeChange(isAuto: boolean): void {\n this.isAutoModeActive.set(isAuto);\n this.update({\n date: [\n new Date(this.form.value.currentDateContextFromDate),\n new Date(this.form.value.currentDateContextToDate)\n ],\n interval: this.form.value.currentDateContextInterval,\n realtime: this.form.value.realtime,\n aggregation: isAuto ? null : this.form.value.aggregation,\n autoAggregation: isAuto ? this.buildAutoAggregationConfig() : null\n });\n }\n\n applyDatetimeContext(): void {\n const isAuto = this.isAutoModeActive();\n this.update({\n date: [\n new Date(this.form.controls.temporaryUserSelectedFromDate.value),\n new Date(this.form.controls.temporaryUserSelectedToDate.value)\n ],\n interval: 'custom',\n realtime: this.form.value.realtime,\n aggregation: isAuto ? null : this.form.value.aggregation,\n autoAggregation: isAuto ? this.buildAutoAggregationConfig() : null\n });\n }\n\n stopRealtime(): void {\n this.realtimeSubscription?.unsubscribe();\n this.setRealtimeControlsLocked(false);\n // Update the form value without triggering valueChanges to avoid infinite loop\n if (this.form?.value.realtime) {\n this.form.patchValue({ realtime: false }, { emitEvent: false });\n }\n }\n\n /** Realtime locks manual range selection and aggregation; single owner of that control set. */\n private setRealtimeControlsLocked(locked: boolean, options?: { emitEvent: boolean }): void {\n const controls = [\n this.form.controls.temporaryUserSelectedFromDate,\n this.form.controls.temporaryUserSelectedToDate,\n this.form.controls.aggregation\n ];\n controls.forEach(control => (locked ? control.disable(options) : control.enable(options)));\n }\n\n private subscribeToIntervalChange(): void {\n this.form.controls.currentDateContextInterval.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(interval => {\n let date: DateTimeContext;\n // Only reset initialTimeRange for preset intervals, not 'custom'\n // Custom interval is set by user slider interaction, which shouldn't reset the chart\n if (interval !== 'custom') {\n this.widgetTimeContextDateRangeService.updateInitialTimeRange(null);\n }\n if (interval === 'custom') {\n date = [\n new Date(this.form.controls.currentDateContextFromDate.value),\n new Date(this.form.controls.currentDateContextToDate.value)\n ];\n } else {\n date = this.datapointExplorerService.getDateTimeContextByInterval(\n interval as Interval['id']\n );\n this.dropdown.isOpen = false;\n }\n this.update({\n date,\n interval,\n realtime: this.form.value.realtime,\n aggregation: this.isAutoModeActive() ? null : this.form.value.aggregation,\n autoAggregation: this.isAutoModeActive() ? this.buildAutoAggregationConfig() : null\n });\n });\n }\n\n private subscribeToRealtimeChange(): void {\n this.form.controls.realtime.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(realtime => {\n this.onRealtimeValueChange(realtime as boolean);\n\n if (realtime) {\n this.startRealtime();\n } else {\n this.stopRealtime();\n }\n });\n }\n\n private subscribeToAggregationChange() {\n this.form.controls.aggregation.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(aggregation => {\n // Skip during auto mode transitions — onAutoModeChange handles the update\n if (this.isAutoModeActive()) {\n return;\n }\n this.update({\n date: [\n new Date(this.form.value.currentDateContextFromDate),\n new Date(this.form.value.currentDateContextToDate)\n ],\n interval: this.form.value.currentDateContextInterval,\n realtime: this.form.value.realtime,\n aggregation,\n autoAggregation: null\n });\n });\n }\n\n private subscribeToDatapointsChange(): void {\n this.form.controls.autoAggregationDatapoints.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef), debounceTime(TIMING.TYPING_DEBOUNCE))\n .subscribe(datapoints => {\n if (!this.isAutoModeActive()) {\n return;\n }\n // Skip while the field is empty or out of range — the user is still typing. Rewriting\n // or emitting a clamped value here would snap the field back mid-edit;\n // commitDatapoints() (blur) commits a valid value instead.\n if (!this.isValidDatapoints(datapoints)) {\n return;\n }\n this.emitAutoAggregationUpdate();\n });\n }\n\n private isValidDatapoints(value: number | null | undefined): value is number {\n return (\n typeof value === 'number' &&\n !Number.isNaN(value) &&\n value >= AUTO_AGGREGATION_DATAPOINTS.MIN &&\n value <= AUTO_AGGREGATION_DATAPOINTS.MAX\n );\n }\n\n private clampToDatapointsBounds(value: number): number {\n return Math.min(\n AUTO_AGGREGATION_DATAPOINTS.MAX,\n Math.max(AUTO_AGGREGATION_DATAPOINTS.MIN, value)\n );\n }\n\n private subscribeToKeepDataOnZoomInChange(): void {\n this.form.controls.autoAggregationKeepDataOnZoomIn.valueChanges\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(() => {\n if (!this.isAutoModeActive()) {\n return;\n }\n this.emitAutoAggregationUpdate();\n });\n }\n\n private emitAutoAggregationUpdate(): void {\n this.update({\n date: [\n new Date(this.form.value.currentDateContextFromDate),\n new Date(this.form.value.currentDateContextToDate)\n ],\n interval: this.form.value.currentDateContextInterval,\n realtime: this.form.value.realtime,\n aggregation: null,\n autoAggregation: this.buildAutoAggregationConfig()\n });\n }\n\n /**\n * Builds the auto-aggregation config from the current form state, clamped to the allowed\n * range. Falls back to the last applied value while the field is empty (mid-edit).\n *\n * Reads control values instead of `this.form.value`: a control's valueChanges fires before\n * the parent group recomputes its cached value, so the group value is stale inside the\n * subscriptions that call this method.\n */\n private buildAutoAggregationConfig(): AutoAggregationConfig {\n const datapoints = this.clampToDatapointsBounds(\n this.form.controls.autoAggregationDatapoints.value ?? this.lastAppliedDatapoints\n );\n return {\n datapoints,\n keepDataOnZoomIn: this.form.controls.autoAggregationKeepDataOnZoomIn.value ?? true\n };\n }\n\n private onRealtimeValueChange(realtime: boolean): void {\n let dateTimeContext: DateTimeContext;\n if (this.form.value.currentDateContextInterval !== 'custom') {\n dateTimeContext = this.datapointExplorerService.getDateTimeContextByInterval(\n this.form.value.currentDateContextInterval as Interval['id']\n );\n } else {\n const currentTimeSpanInMs =\n new Date(this.form.value.currentDateContextToDate).valueOf() -\n new Date(this.form.value.currentDateContextFromDate).valueOf();\n const dateTo = new Date();\n const dateFrom = new Date(dateTo.valueOf() - currentTimeSpanInMs);\n dateTimeContext = [dateFrom, dateTo];\n }\n\n this.isAutoModeActive.set(false);\n this.update({\n date: dateTimeContext,\n interval: this.form.value.currentDateContextInterval,\n realtime,\n aggregation: null,\n autoAggregation: null\n });\n }\n\n private startRealtime(): void {\n this.setRealtimeControlsLocked(true);\n\n this.realtimeSubscription = interval(this.REALTIME_INTERVAL)\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(() => {\n if (!this.form.value.realtime) {\n this.realtimeSubscription.unsubscribe();\n return;\n }\n const newDateFrom = new Date(\n new Date(this.form.value.currentDateContextFromDate).valueOf() + this.REALTIME_INTERVAL\n );\n const newDateTo = new Date(\n new Date(this.form.value.currentDateContextToDate).valueOf() + this.REALTIME_INTERVAL\n );\n this.updateFormValues(\n {\n date: [newDateFrom, newDateTo],\n interval: this.form.value.currentDateContextInterval,\n realtime: true,\n aggregation: null\n },\n false\n ); // Don't emit during automatic realtime ticks\n });\n }\n\n private update(\n { date, interval, realtime, aggregation, autoAggregation = null },\n shouldEmit = true\n ): void {\n const { selectedAggregation, disabledAggregations } =\n this.datapointExplorerService.calculateAggregation(\n date,\n autoAggregation ? null : aggregation\n );\n this.disabledAggregations = disabledAggregations;\n this.updateFormValues(\n { date, interval, realtime, aggregation: selectedAggregation, autoAggregation },\n shouldEmit\n );\n }\n\n private createForm(context) {\n return this.formBuilder.group({\n temporaryUserSelectedFromDate: context.date[0].toISOString() as string,\n temporaryUserSelectedToDate: context.date[1].toISOString() as string,\n currentDateContextFromDate: context.date[0].toISOString() as string,\n currentDateContextToDate: context.date[1].toISOString() as string,\n currentDateContextInterval: context.interval || 'custom',\n realtime: context.realtime,\n aggregation: context.aggregation,\n autoAggregationEnabled: false,\n autoAggregationDatapoints: AUTO_AGGREGATION_DATAPOINTS.DEFAULT as number,\n autoAggregationKeepDataOnZoomIn: true\n });\n }\n\n private updateFormValues(\n { date, interval, realtime, aggregation, autoAggregation = null },\n shouldEmit = true\n ): void {\n const newFormValues = {\n temporaryUserSelectedFromDate: date[0].toISOString() as string,\n temporaryUserSelectedToDate: date[1].toISOString() as string,\n currentDateContextFromDate: date[0].toISOString() as string,\n currentDateContextToDate: date[1].toISOString() as string,\n realtime,\n currentDateContextInterval: interval || 'custom',\n aggregation: autoAggregation ? null : aggregation || null,\n autoAggregation\n };\n\n if (shouldEmit) {\n this.context.set(newFormValues);\n }\n if (autoAggregation?.datapoints != null) {\n this.lastAppliedDatapoints = this.clampToDatapointsBounds(autoAggregation.datapoints);\n }\n this.form.patchValue(\n {\n ...newFormValues,\n autoAggregationEnabled: !!autoAggregation,\n autoAggregationDatapoints:\n autoAggregation?.datapoints ?? this.form.value.autoAggregationDatapoints,\n autoAggregationKeepDataOnZoomIn:\n autoAggregation?.keepDataOnZoomIn ?? this.form.value.autoAggregationKeepDataOnZoomIn\n },\n { emitEvent: false }\n );\n }\n}\n","@if (controlsAvailable) {\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n} @else {\n <c8y-action-bar-item\n [groupId]=\"'timeContext'\"\n [inGroupPriority]=\"1\"\n [placement]=\"'left'\"\n itemClass=\"navbar-form\"\n >\n <ng-container\n [ngTemplateOutlet]=\"dateTimePicker\"\n [ngTemplateOutletContext]=\"{\n date: [form.value.currentDateContextFromDate, form.value.currentDateContextToDate]\n }\"\n ></ng-container>\n </c8y-action-bar-item>\n}\n\n<ng-template\n #dateTimePicker\n let-date=\"date\"\n>\n <form\n class=\"d-flex gap-8 p-l-xs-16 p-r-xs-16 m-t-xs-8 m-b-xs-8\"\n [formGroup]=\"form\"\n >\n <ng-container>\n @if (date) {\n <div\n class=\"dropdown flex-grow\"\n #dropdown=\"bs-dropdown\"\n dropdown\n [insideClick]=\"true\"\n >\n <button\n class=\"dropdown-toggle form-control l-h-tight d-flex a-i-center\"\n attr.aria-label=\"{{ date[0] | c8yDate: DATE_FORMAT }} — {{\n date[1] | c8yDate: DATE_FORMAT\n }}\"\n tooltip=\"{{ date[0] | c8yDate: DATE_FORMAT }} — {{ date[1] | c8yDate: DATE_FORMAT }}\"\n placement=\"top\"\n container=\"body\"\n data-cy=\"widget-time-context--date-picker-dropdown-button\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i\n class=\"m-r-8\"\n c8yIcon=\"schedule1\"\n ></i>\n <div class=\"d-col text-left fit-w\">\n <span\n class=\"text-muted fit-w text-10 l-h-1\"\n data-cy=\"widget-time-context--selected-interval\"\n >\n {{ INTERVAL_TITLES[form.controls.currentDateContextInterval.value] | translate }}\n </span>\n <span\n class=\"text-bold text-12 fit-w l-h-1 text-truncate\"\n data-cy=\"widget-time-context--selected-time-range\"\n >\n {{ date[0] | c8yDate: DATE_FORMAT }} — {{ date[1] | c8yDate: DATE_FORMAT }}\n </span>\n </div>\n <span class=\"caret m-r-16 m-l-4\"></span>\n </button>\n\n <ul\n class=\"dropdown-menu dropdown-menu-wide dropdown-menu--date-range\"\n *dropdownMenu\n >\n <c8y-interval-picker\n class=\"d-contents\"\n formControlName=\"currentDateContextInterval\"\n ></c8y-interval-picker>\n\n @if (form.controls.currentDateContextInterval.value === 'custom') {\n <div class=\"p-l-16 p-r-16\">\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'From`date`' | translate\"\n for=\"temporaryUserSelectedFromDate\"\n translate\n >\n From`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedFromDate\"\n [maxDate]=\"form.value.temporaryUserSelectedToDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'From`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedFromDate\"\n [ngClass]=\"\n form.controls.temporaryUserSelectedFromDate.errors ? 'has-error' : ''\n \"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedFromDate.errors\">\n <c8y-message\n name=\"dateAfterRangeMax\"\n [text]=\"'This date is after the latest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n >\n <label\n [title]=\"'To`date`' | translate\"\n for=\"temporaryUserSelectedToDate\"\n translate\n >\n To`date`\n </label>\n <c8y-date-time-picker\n id=\"temporaryUserSelectedToDate\"\n [minDate]=\"form.value.temporaryUserSelectedFromDate\"\n [config]=\"timePickerConfig\"\n [placeholder]=\"'To`date`' | translate\"\n [formControl]=\"form.controls.temporaryUserSelectedToDate\"\n [ngClass]=\"form.controls.temporaryUserSelectedToDate.errors ? 'has-error' : ''\"\n ></c8y-date-time-picker>\n <c8y-messages [show]=\"form.controls.temporaryUserSelectedToDate.errors\">\n <c8y-message\n name=\"dateBeforeRangeMin\"\n [text]=\"'This date is before the earliest allowed date.' | translate\"\n ></c8y-message>\n <c8y-message\n name=\"invalidDateTime\"\n [text]=\"'This date is invalid.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n\n <div class=\"p-16 d-flex gap-8 separator-top\">\n <button\n class=\"btn btn-default btn-sm flex-grow\"\n title=\"{{ 'Reset' | translate }}\"\n type=\"button\"\n (click)=\"dropdown.isOpen = false\"\n [disabled]=\"form.value.realtime\"\n translate\n >\n Reset\n </button>\n\n <button\n class=\"btn btn-primary btn-sm flex-grow\"\n title=\"{{ 'Apply' | translate }}\"\n type=\"button\"\n (click)=\"applyDatetimeContext(); dropdown.isOpen = false\"\n [disabled]=\"\n (form.pristine && form.untouched) || form.invalid || form.value.realtime\n \"\n translate\n >\n Apply\n </button>\n </div>\n }\n </ul>\n </div>\n }\n </ng-container>\n\n <div class=\"input-group w-auto\">\n <c8y-realtime-control\n class=\"form-control p-0 flex-no-grow w-auto\"\n formControlName=\"realtime\"\n ></c8y-realtime-control>\n\n @if (enableAutoAggregation && isTimeSeriesMigrated()) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [showAutoMode]=\"true\"\n [autoModeActive]=\"isAutoModeActive()\"\n [autoPoints]=\"form.value.autoAggregationDatapoints\"\n [autoKeepPointCount]=\"form.value.autoAggregationKeepDataOnZoomIn\"\n [disabledAggregations]=\"disabledAggregations\"\n (autoModeChange)=\"onAutoModeChange($event)\"\n >\n <div\n class=\"d-col\"\n autoAggregationOptions\n >\n <div class=\"d-flex a-i-center gap-8\">\n <label class=\"m-b-0 m-r-8\">\n {{ 'Points per chart' | translate }}\n </label>\n <input\n class=\"form-control input-sm\"\n style=\"width: 80px\"\n [attr.title]=\"\n 'Enter a value between {{ min }} and {{ max }}.'\n | translate\n : {\n min: AUTO_AGGREGATION_DATAPOINTS.MIN,\n max: AUTO_AGGREGATION_DATAPOINTS.MAX\n }\n \"\n [attr.aria-label]=\"'Points per chart' | translate\"\n type=\"number\"\n [min]=\"AUTO_AGGREGATION_DATAPOINTS.MIN\"\n [max]=\"AUTO_AGGREGATION_DATAPOINTS.MAX\"\n [step]=\"AUTO_AGGREGATION_DATAPOINTS.STEP\"\n [formControl]=\"form.controls.autoAggregationDatapoints\"\n />\n </div>\n <label\n class=\"c8y-switch m-b-0 m-t-8 text-nowrap\"\n [title]=\"'Keep point count on zoom' | translate\"\n >\n <input\n type=\"checkbox\"\n [formControl]=\"form.controls.autoAggregationKeepDataOnZoomIn\"\n data-cy=\"time-context--auto-aggregation-keep-data-on-zoom-in\"\n />\n <span></span>\n <span class=\"text-12\">{{ 'Keep point count on zoom' | translate }}</span>\n <button\n class=\"btn-help btn-help--sm m-l-4\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"KEEP_DATA_ON_ZOOM_IN_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </label>\n </div>\n </c8y-aggregation-picker>\n } @else if (\n enableAutoAggregation || (controlsAvailable ? controlsAvailable.aggregation : true)\n ) {\n <c8y-aggregation-picker\n formControlName=\"aggregation\"\n [disabledAggregations]=\"disabledAggregations\"\n ></c8y-aggregation-picker>\n }\n\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"AGGREGATION_POPOVER | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </form>\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -682,7 +682,7 @@ class TrustedCertificateListComponent {
682
682
  this.certificateAuthorityFeatureEnabled = await firstValueFrom(this.featureCacheService.getFeatureState('certificate-authority'));
683
683
  }
684
684
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TrustedCertificateListComponent, deps: [{ token: i1$1.BsModalService }, { token: i2.AlertService }, { token: i2$1.TrustedCertificateService }, { token: i2.ModalService }, { token: i4$1.TranslateService }, { token: i2.ClipboardService }, { token: i2.GainsightService }, { token: i2$1.SystemOptionsService }, { token: i2.FeatureCacheService }, { token: TrustedCertificatesGuard }], target: i0.ɵɵFactoryTarget.Component }); }
685
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: TrustedCertificateListComponent, isStandalone: true, selector: "c8y-trusted-certificates", ngImport: i0, template: "@if ((hasReadRole$ | async) || (hasAdminRole$ | async)) {\n <div>\n <c8y-title>{{ 'Trusted certificates' | translate }}</c8y-title>\n\n <c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-management\"\n label=\"{{ 'Management' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n icon=\"certificate\"\n label=\"{{ 'Trusted certificates' | translate }}\"\n ></c8y-breadcrumb-item>\n </c8y-breadcrumb>\n\n @if (certificateAuthorityFeatureEnabled) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"1000\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Generate CA certificate' | translate }}\"\n type=\"button\"\n data-cy=\"trusted-certificate-list--generate-ca-certificate\"\n [disabled]=\"!(hasAdminRole$ | async) || certificateAuthorityExists\"\n (click)=\"addCACertificate()\"\n >\n <i c8yIcon=\"contract\"></i>\n {{ 'Generate CA certificate' | translate }}\n </button>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The Certificate Authority (CA) certificate is used to sign device certificates for secure authentication. Only one CA certificate can be generated for the tenant.'\n | translate\n }}\"\n placement=\"bottom\"\n triggers=\"focus\"\n type=\"button\"\n ></button>\n </c8y-action-bar-item>\n }\n\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"900\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Add trusted certificate' | translate }}\"\n type=\"button\"\n data-cy=\"trusted-certificate-list--add-trusted-certificate\"\n (click)=\"addTrustedCertificate()\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add trusted certificate' | translate }}\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"800\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n type=\"button\"\n (click)=\"loadTrustedCertificates()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading | async }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n </c8y-action-bar-item>\n\n <c8y-help\n src=\"/docs/device-certificate-authentication/managing-trusted-certificates/#managing-trusted-certificates\"\n ></c8y-help>\n\n @if ((trustedCertificates | async)?.data.length === 0) {\n <c8y-ui-empty-state\n [icon]=\"'certificate'\"\n [title]=\"'No trusted certificates to display.' | translate\"\n [subtitle]=\"'Add your first certificate by clicking below.' | translate\"\n >\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Add trusted certificate' | translate }}\"\n type=\"button\"\n (click)=\"addTrustedCertificate()\"\n >\n {{ 'Add trusted certificate' | translate }}\n </button>\n </c8y-ui-empty-state>\n }\n\n <c8y-list-group class=\"m-b-24\">\n @if ((trustedCertificates | async)?.data.length > 0) {\n <div class=\"page-sticky-header hidden-xs c8y-list__item c8y-list__item--empty-actions\">\n <div class=\"c8y-list__item__block\">\n <div class=\"c8y-list__item__icon\">\n <i\n class=\"invisible\"\n c8yIcon=\"certificate\"\n ></i>\n </div>\n <div class=\"c8y-list__item__body\">\n <div class=\"content-flex-60\">\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Certificate' | translate }} \"\n >\n {{ 'Certificate' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Status' | translate }}\"\n >\n {{ 'Status' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Algorithm' | translate }}\"\n >\n {{ 'Algorithm' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Expiration date' | translate }}\"\n >\n {{ 'Expiration date' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Auto registration' | translate }}\"\n >\n {{ 'Auto registration' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Proof of possession' | translate }}\"\n >\n {{ 'Proof of possession' | translate }}\n </span>\n </div>\n </div>\n </div>\n <div class=\"c8y-list__item__actions\"></div>\n </div>\n </div>\n }\n\n <c8y-li\n *c8yFor=\"\n let trustedCertificate of trustedCertificates | async;\n let i = index;\n pipe: sortByExpirationDateAsc;\n loadMore: 'none'\n \"\n #listItem\n data-cy=\"c8y-trusted-certificates-list--item-block\"\n >\n <c8y-li-icon>\n @if (!trustedCertificate.tenantCertificateAuthority) {\n <button\n class=\"btn-clean\"\n attr.aria-label=\"{{ 'Certificate' | translate }}\"\n tooltip=\"{{ 'Certificate' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"certificate\"></i>\n </button>\n }\n @if (trustedCertificate.tenantCertificateAuthority) {\n <button\n class=\"btn-clean\"\n attr.aria-label=\"{{ 'CA certificate' | translate }}\"\n tooltip=\"{{ 'CA certificate' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"contract\"></i>\n </button>\n }\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-60\">\n <div class=\"col-2\">\n <button\n class=\"btn-clean text-truncate\"\n title=\"{{ trustedCertificate.name }}\"\n type=\"button\"\n (click)=\"listItem.toggleCollapsed()\"\n >\n {{ trustedCertificate.name }}\n </button>\n </div>\n <div class=\"col-2\">\n <div class=\"visible-xs p-8\"></div>\n <button\n class=\"btn c8y-btn-checkbox--inline\"\n name=\"certificateStatus\"\n type=\"button\"\n [(ngModel)]=\"trustedCertificate.status\"\n btnCheckbox\n btnCheckboxTrue=\"ENABLED\"\n btnCheckboxFalse=\"DISABLED\"\n (ngModelChange)=\"updateCertificate(trustedCertificate, { status: $event })\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n [ngClass]=\"{\n disabled: !(hasAdminRole$ | async)\n }\"\n >\n <small\n title=\"{{ 'Disabled`trusted certificate status`' | translate }}\"\n [hidden]=\"trustedCertificate.status !== 'DISABLED'\"\n >\n {{ 'Disabled`trusted certificate status`' | translate }}\n </small>\n <small\n title=\"{{ 'Enabled`trusted certificate status`' | translate }}\"\n [hidden]=\"trustedCertificate.status !== 'ENABLED'\"\n >\n {{ 'Enabled`trusted certificate status`' | translate }}\n </small>\n </button>\n <div class=\"visible-xs p-8\"></div>\n </div>\n <div class=\"col-2\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Algorithm' | translate }}: {{ trustedCertificate.algorithmName }}\"\n >\n <span\n class=\"text-label-small m-t-8 m-r-8 visible-xs-inline\"\n translate\n >\n Algorithm\n </span>\n {{ trustedCertificate.algorithmName }}\n </div>\n </div>\n\n <div class=\"col-2\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Expiration date' | translate }}: {{\n trustedCertificate.notAfter | c8yDate\n }}\"\n >\n <span\n class=\"text-label-small m-t-8 m-r-8 visible-xs-inline\"\n translate\n >\n Expiration date\n </span>\n @let expirationHighlight = getExpirationHighlight(trustedCertificate);\n <span>\n <small\n [attr.title]=\"expirationHighlight?.tooltipText\"\n [ngClass]=\"expirationHighlight?.textClass\"\n >\n @if (expirationHighlight?.expired) {\n <del>\n <ng-container *ngTemplateOutlet=\"expirationDateTpl\"></ng-container>\n </del>\n } @else {\n <ng-container *ngTemplateOutlet=\"expirationDateTpl\"></ng-container>\n }\n <ng-template #expirationDateTpl>\n @if (expirationHighlight?.icon) {\n <i\n class=\"m-r-4\"\n c8yIcon=\"{{ expirationHighlight?.icon }}\"\n ></i>\n }\n <span>{{ trustedCertificate.notAfter | c8yDate }}</span>\n </ng-template>\n </small>\n @if (expirationHighlight?.renewable) {\n <button\n class=\"btn btn-link btn-icon\"\n title=\"{{ 'Renew certificate' | translate }}\"\n type=\"button\"\n (click)=\"renewCertificate()\"\n >\n <i c8yIcon=\"refresh\"></i>\n </button>\n }\n </span>\n </div>\n </div>\n <div class=\"col-2\">\n <div class=\"text-truncate\">\n <span class=\"text-label-small m-t-8 m-r-4 visible-xs-inline\">\n {{ 'Auto registration' | translate }}\n </span>\n @if (trustedCertificate.autoRegistrationEnabled) {\n <span\n title=\"{{ 'Auto registration' | translate }}: {{\n 'Enabled`auto registration`' | translate\n }}\"\n >\n {{ 'Enabled`auto registration`' | translate }}\n </span>\n }\n @if (!trustedCertificate.autoRegistrationEnabled) {\n <span\n title=\"{{ 'Auto registration' | translate }}: {{\n 'Disabled`auto registration`' | translate\n }}\"\n >\n {{ 'Disabled`auto registration`' | translate }}\n </span>\n }\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ AUTO_REGISTRATION_POPOVER | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-2 d-flex\">\n <div class=\"text-truncate\">\n <span class=\"text-label-small m-t-8 m-r-4 visible-xs-inline\">\n {{ 'Proof of possession' | translate }}\n </span>\n @if (trustedCertificate.tenantCertificateAuthority) {\n <span title=\"{{ 'Proof of possession' | translate }}: {{ 'N/A' | translate }}\">\n {{ 'N/A' | translate }}\n </span>\n }\n @if (!trustedCertificate.tenantCertificateAuthority) {\n <span>\n @if (trustedCertificate.proofOfPossessionValid) {\n <span\n title=\"{{ 'Proof of possession' | translate }}: {{\n 'Complete`proof of possession`' | translate\n }}\"\n >\n <div class=\"icon-flex\">\n <i\n class=\"text-success\"\n c8yIcon=\"success\"\n ></i>\n {{ 'Complete`proof of possession`' | translate }}\n </div>\n </span>\n }\n @if (!trustedCertificate.proofOfPossessionValid) {\n <span\n title=\"{{ 'Proof of possession' | translate }}: {{\n 'Incomplete`proof of possession`' | translate\n }}\"\n >\n <div class=\"icon-flex\">\n <i\n class=\"text-warning\"\n c8yIcon=\"warning\"\n ></i>\n {{ 'Incomplete`proof of possession`' | translate }}\n </div>\n </span>\n }\n </span>\n }\n </div>\n <button\n class=\"m-l-auto btn-dot btn-dot--danger btn showOnHover m-r-8\"\n [attr.aria-label]=\"'Delete' | translate\"\n tooltip=\"{{ 'Delete' | translate }}\"\n placement=\"right\"\n type=\"button\"\n data-cy=\"c8y-trusted-certificate--delete\"\n [delay]=\"500\"\n (click)=\"deleteTrustedCertificate(trustedCertificate)\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n </div>\n </c8y-li-body>\n\n <c8y-li-collapse>\n <div class=\"p-t-16 p-b-16\">\n <div class=\"row\">\n <div class=\"col-md-4\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Certificate name' | translate }}\n </label>\n <c8y-input-group-editable\n required\n formGroupClass=\"m-b-0\"\n [ariaLabel]=\"'Certificate name' | translate\"\n data-cy=\"c8y-trusted-certificates--edit-certificate-name\"\n [(ngModel)]=\"trustedCertificate.name\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n (save)=\"\n updateCertificate(trustedCertificate, { name: trustedCertificate.name })\n \"\n ></c8y-input-group-editable>\n </c8y-form-group>\n </div>\n <div class=\"col-md-1\"></div>\n <div class=\"col-md-7\">\n <c8y-form-group>\n <label\n class=\"control-label\"\n for=\"certInPemFormat\"\n translate\n >\n Certificate\n </label>\n <textarea\n class=\"form-control no-resize\"\n id=\"certInPemFormat\"\n name=\"certInPemFormat\"\n type=\"text\"\n rows=\"7\"\n readonly\n [(ngModel)]=\"trustedCertificate.certInPemFormat\"\n ></textarea>\n </c8y-form-group>\n <c8y-form-group>\n <label\n class=\"c8y-checkbox\"\n title=\"{{ 'Auto registration' | translate }}\"\n [ngClass]=\"{\n disabled: !(hasAdminRole$ | async)\n }\"\n >\n <input\n type=\"checkbox\"\n [(ngModel)]=\"trustedCertificate.autoRegistrationEnabled\"\n (ngModelChange)=\"\n updateCertificate(trustedCertificate, { autoRegistrationEnabled: $event })\n \"\n [disabled]=\"!(hasAdminRole$ | async)\"\n />\n <span></span>\n <span>{{ 'Auto registration' | translate }}</span>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ AUTO_REGISTRATION_POPOVER | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n type=\"button\"\n ></button>\n </label>\n </c8y-form-group>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-4\">\n <div\n class=\"legend form-block\"\n translate\n >\n Additional properties\n </div>\n <ul class=\"list-unstyled\">\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Algorithm' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.algorithmName }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Version' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.version }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Valid from' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.notBefore | c8yDate }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Issuer' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.issuer }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Expiration date' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.notAfter | c8yDate }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Serial number' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.serialNumber }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Subject`of a certificate`' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.subject }}\n </span>\n </li>\n </ul>\n </div>\n <div class=\"col-md-1\"></div>\n @if (!trustedCertificate.tenantCertificateAuthority) {\n <div class=\"col-md-7\">\n <div class=\"legend form-block\">\n {{ 'Proof of possession' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ PROOF_OF_POSSESSION_POPOVER | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n type=\"button\"\n ></button>\n </div>\n @if (trustedCertificate.proofOfPossessionValid) {\n <div>\n <span\n class=\"icon-flex\"\n title=\"{{ 'Proof of possession' | translate }}: {{\n 'Complete`proof of possession`' | translate\n }}\"\n >\n <i\n class=\"text-success\"\n c8yIcon=\"success\"\n ></i>\n {{ 'Complete`proof of possession`' | translate }}\n </span>\n </div>\n }\n @if (!trustedCertificate.proofOfPossessionValid) {\n <div>\n <div class=\"row m-b-16\">\n <div class=\"col-md-6\">\n <span\n class=\"icon-flex\"\n title=\"{{ 'Proof of possession' | translate }}: {{\n 'Incomplete`proof of possession`' | translate\n }}\"\n >\n <i\n class=\"text-warning\"\n c8yIcon=\"warning\"\n ></i>\n {{ 'Incomplete`proof of possession`' | translate }}\n </span>\n </div>\n <div class=\"col-md-6 col-lg-6 text-right-md\">\n <span class=\"text-label-small m-r-4\">\n {{ 'Verification code expires/expired on' | translate }}\n </span>\n {{\n (trustedCertificate.proofOfPossessionVerificationCodeUsableUntil\n | c8yDate) || '---'\n }}\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6 col-lg-6\">\n <c8y-form-group>\n <label\n class=\"control-label\"\n for=\"unsignedVerificationCode\"\n translate\n >\n Verification code\n </label>\n <textarea\n class=\"form-control no-resize\"\n id=\"unsignedVerificationCode\"\n name=\"unsignedVerificationCode\"\n type=\"text\"\n rows=\"5\"\n readonly\n [(ngModel)]=\"\n trustedCertificate.proofOfPossessionUnsignedVerificationCode\n \"\n ></textarea>\n </c8y-form-group>\n <div class=\"d-flex\">\n <button\n class=\"btn btn-primary btn-sm\"\n title=\"{{ 'Regenerate verification code' | translate }}\"\n type=\"button\"\n (click)=\"regenerateUnsignedVerificationCode(trustedCertificate)\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n >\n {{ 'Regenerate`verification code`' | translate }}\n </button>\n\n <button\n class=\"btn btn-sm btn-default m-l-auto m-r-0\"\n [attr.aria-label]=\"'Copy to clipboard' | translate\"\n tooltip=\"{{ 'Copy to clipboard' | translate }}\"\n placement=\"right\"\n type=\"button\"\n data-cy=\"c8y-trusted-certificates--copy-to-clipboard\"\n [delay]=\"500\"\n [disabled]=\"\n !trustedCertificate.proofOfPossessionUnsignedVerificationCode\n \"\n (click)=\"copyUnsignedVerificationCodeToClipboard(trustedCertificate)\"\n >\n <i c8yIcon=\"clipboard\"></i>\n </button>\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Download as file' | translate\"\n tooltip=\"{{ 'Download as file' | translate }}\"\n type=\"button\"\n data-cy=\"c8y-trusted-certificates--download-as-file\"\n [delay]=\"500\"\n [disabled]=\"\n !trustedCertificate.proofOfPossessionUnsignedVerificationCode\n \"\n (click)=\"downloadUnsignedVerificationCode(trustedCertificate)\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component:\n PRODUCT_EXPERIENCE.VERIFICATION_CODE.COMPONENTS.DOWNLOAD_CODE,\n action: PRODUCT_EXPERIENCE.VERIFICATION_CODE.ACTIONS.DOWNLOAD\n }\"\n >\n <i c8yIcon=\"download\"></i>\n </button>\n </div>\n </div>\n\n <div class=\"col-md-6 col-lg-6\">\n <c8y-form-group>\n <label\n class=\"control-label\"\n for=\"signedVerificationCode\"\n >\n {{ 'Signed verification code' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ SIGNED_VERIFICATION_CODE_POPOVER | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n data-cy=\"c8y-trusted-certificates--signed-verification-code-popup\"\n [outsideClick]=\"true\"\n ></button>\n </label>\n <textarea\n class=\"form-control no-resize\"\n id=\"signedVerificationCode\"\n name=\"signedVerificationCode\"\n type=\"text\"\n rows=\"5\"\n [(ngModel)]=\"trustedCertificate.signedVerificationCode\"\n ></textarea>\n </c8y-form-group>\n <div class=\"d-flex\">\n <button\n class=\"btn btn-primary btn-sm\"\n title=\"{{ 'Verify signed verification code' | translate }}\"\n type=\"button\"\n (click)=\"verifySignedVerificationCode(trustedCertificate)\"\n [disabled]=\"!trustedCertificate.signedVerificationCode\"\n >\n {{ 'Verify`signed verification code`' | translate }}\n </button>\n <button\n class=\"btn btn-sm btn-default m-l-auto\"\n [attr.aria-label]=\"'Upload file' | translate\"\n tooltip=\"{{ 'Upload file' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"fileInput.click()\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n >\n <i c8yIcon=\"upload\"></i>\n </button>\n <input\n class=\"hidden\"\n type=\"file\"\n #fileInput\n (change)=\"onFileInput($event, trustedCertificate)\"\n />\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </c8y-li-collapse>\n </c8y-li>\n </c8y-list-group>\n </div>\n}\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "directive", type: ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "directive", type: TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "directive", type: ButtonCheckboxDirective, selector: "[btnCheckbox]", inputs: ["btnCheckboxTrue", "btnCheckboxFalse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: ListItemCollapseComponent, selector: "c8y-list-item-collapse, c8y-li-collapse", inputs: ["collapseWay"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: InputGroupEditableComponent, selector: "c8y-input-group-editable", inputs: ["ariaLabel", "name", "size", "placeholder", "multiline", "maxHeight", "maxLength", "noSaveButton", "formGroupClass", "validators", "asyncValidators", "autocomplete"], outputs: ["save", "cancel"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] }); }
685
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: TrustedCertificateListComponent, isStandalone: true, selector: "c8y-trusted-certificates", ngImport: i0, template: "@if ((hasReadRole$ | async) || (hasAdminRole$ | async)) {\n <div>\n <c8y-title>{{ 'Trusted certificates' | translate }}</c8y-title>\n\n <c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-management\"\n label=\"{{ 'Management' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n icon=\"certificate\"\n label=\"{{ 'Trusted certificates' | translate }}\"\n ></c8y-breadcrumb-item>\n </c8y-breadcrumb>\n\n @if (certificateAuthorityFeatureEnabled) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"1000\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Generate CA certificate' | translate }}\"\n type=\"button\"\n data-cy=\"trusted-certificate-list--generate-ca-certificate\"\n [disabled]=\"!(hasAdminRole$ | async) || certificateAuthorityExists\"\n (click)=\"addCACertificate()\"\n >\n <i c8yIcon=\"contract\"></i>\n {{ 'Generate CA certificate' | translate }}\n </button>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The Certificate Authority (CA) certificate is used to sign device certificates for secure authentication. Only one CA certificate can be generated for the tenant.'\n | translate\n }}\"\n placement=\"bottom\"\n triggers=\"focus\"\n type=\"button\"\n ></button>\n </c8y-action-bar-item>\n }\n\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"900\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Add trusted certificate' | translate }}\"\n type=\"button\"\n data-cy=\"trusted-certificate-list--add-trusted-certificate\"\n (click)=\"addTrustedCertificate()\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add trusted certificate' | translate }}\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"800\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n type=\"button\"\n (click)=\"loadTrustedCertificates()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading | async }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n </c8y-action-bar-item>\n\n <c8y-help\n src=\"/docs/device-certificate-authentication/managing-trusted-certificates/#managing-trusted-certificates\"\n ></c8y-help>\n\n @if ((trustedCertificates | async)?.data.length === 0) {\n <c8y-ui-empty-state\n [icon]=\"'certificate'\"\n [title]=\"'No trusted certificates to display.' | translate\"\n [subtitle]=\"'Add your first certificate by clicking below.' | translate\"\n >\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Add trusted certificate' | translate }}\"\n type=\"button\"\n (click)=\"addTrustedCertificate()\"\n >\n {{ 'Add trusted certificate' | translate }}\n </button>\n </c8y-ui-empty-state>\n }\n\n <c8y-list-group class=\"m-b-24\">\n @if ((trustedCertificates | async)?.data.length > 0) {\n <div class=\"page-sticky-header hidden-xs c8y-list__item c8y-list__item--empty-actions\">\n <div class=\"c8y-list__item__block\">\n <div class=\"c8y-list__item__icon\">\n <i\n class=\"invisible\"\n c8yIcon=\"certificate\"\n ></i>\n </div>\n <div class=\"c8y-list__item__body\">\n <div class=\"content-flex-60\">\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Certificate' | translate }} \"\n >\n {{ 'Certificate' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Status' | translate }}\"\n >\n {{ 'Status' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Algorithm' | translate }}\"\n >\n {{ 'Algorithm' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Expiration date' | translate }}\"\n >\n {{ 'Expiration date' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Auto registration' | translate }}\"\n >\n {{ 'Auto registration' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Proof of possession' | translate }}\"\n >\n {{ 'Proof of possession' | translate }}\n </span>\n </div>\n </div>\n </div>\n <div class=\"c8y-list__item__actions\"></div>\n </div>\n </div>\n }\n\n <c8y-li\n *c8yFor=\"\n let trustedCertificate of trustedCertificates | async;\n let i = index;\n pipe: sortByExpirationDateAsc;\n loadMore: 'none'\n \"\n #listItem\n data-cy=\"c8y-trusted-certificates-list--item-block\"\n >\n <c8y-li-icon>\n @if (!trustedCertificate.tenantCertificateAuthority) {\n <button\n class=\"btn-clean\"\n attr.aria-label=\"{{ 'Certificate' | translate }}\"\n tooltip=\"{{ 'Certificate' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"certificate\"></i>\n </button>\n }\n @if (trustedCertificate.tenantCertificateAuthority) {\n <button\n class=\"btn-clean\"\n attr.aria-label=\"{{ 'CA certificate' | translate }}\"\n tooltip=\"{{ 'CA certificate' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"contract\"></i>\n </button>\n }\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-60\">\n <div class=\"col-2\">\n <button\n class=\"btn-clean text-truncate\"\n title=\"{{ trustedCertificate.name }}\"\n type=\"button\"\n (click)=\"listItem.toggleCollapsed()\"\n >\n {{ trustedCertificate.name }}\n </button>\n </div>\n <div class=\"col-2\">\n <div class=\"visible-xs p-8\"></div>\n <button\n class=\"btn c8y-btn-checkbox--inline\"\n name=\"certificateStatus\"\n type=\"button\"\n [(ngModel)]=\"trustedCertificate.status\"\n btnCheckbox\n btnCheckboxTrue=\"ENABLED\"\n btnCheckboxFalse=\"DISABLED\"\n (ngModelChange)=\"updateCertificate(trustedCertificate, { status: $event })\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n [ngClass]=\"{\n disabled: !(hasAdminRole$ | async)\n }\"\n >\n <small\n title=\"{{ 'Disabled`trusted certificate status`' | translate }}\"\n [hidden]=\"trustedCertificate.status !== 'DISABLED'\"\n >\n {{ 'Disabled`trusted certificate status`' | translate }}\n </small>\n <small\n title=\"{{ 'Enabled`trusted certificate status`' | translate }}\"\n [hidden]=\"trustedCertificate.status !== 'ENABLED'\"\n >\n {{ 'Enabled`trusted certificate status`' | translate }}\n </small>\n </button>\n <div class=\"visible-xs p-8\"></div>\n </div>\n <div class=\"col-2\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Algorithm' | translate }}: {{ trustedCertificate.algorithmName }}\"\n >\n <span\n class=\"text-label-small m-t-8 m-r-8 visible-xs-inline\"\n translate\n >\n Algorithm\n </span>\n {{ trustedCertificate.algorithmName }}\n </div>\n </div>\n\n <div class=\"col-2\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Expiration date' | translate }}: {{\n trustedCertificate.notAfter | c8yDate\n }}\"\n >\n <span\n class=\"text-label-small m-t-8 m-r-8 visible-xs-inline\"\n translate\n >\n Expiration date\n </span>\n @let expirationHighlight = getExpirationHighlight(trustedCertificate);\n <span>\n <small\n [attr.title]=\"expirationHighlight?.tooltipText\"\n [ngClass]=\"expirationHighlight?.textClass\"\n >\n @if (expirationHighlight?.expired) {\n <del>\n <ng-container *ngTemplateOutlet=\"expirationDateTpl\"></ng-container>\n </del>\n } @else {\n <ng-container *ngTemplateOutlet=\"expirationDateTpl\"></ng-container>\n }\n <ng-template #expirationDateTpl>\n @if (expirationHighlight?.icon) {\n <i\n class=\"m-r-4\"\n c8yIcon=\"{{ expirationHighlight?.icon }}\"\n ></i>\n }\n <span>{{ trustedCertificate.notAfter | c8yDate }}</span>\n </ng-template>\n </small>\n @if (expirationHighlight?.renewable) {\n <button\n class=\"btn btn-link btn-icon\"\n title=\"{{ 'Renew certificate' | translate }}\"\n type=\"button\"\n (click)=\"renewCertificate()\"\n >\n <i c8yIcon=\"refresh\"></i>\n </button>\n }\n </span>\n </div>\n </div>\n <div class=\"col-2\">\n <div class=\"text-truncate\">\n <span class=\"text-label-small m-t-8 m-r-4 visible-xs-inline\">\n {{ 'Auto registration' | translate }}\n </span>\n @if (trustedCertificate.autoRegistrationEnabled) {\n <span\n title=\"{{ 'Auto registration' | translate }}: {{\n 'Enabled`auto registration`' | translate\n }}\"\n >\n {{ 'Enabled`auto registration`' | translate }}\n </span>\n }\n @if (!trustedCertificate.autoRegistrationEnabled) {\n <span\n title=\"{{ 'Auto registration' | translate }}: {{\n 'Disabled`auto registration`' | translate\n }}\"\n >\n {{ 'Disabled`auto registration`' | translate }}\n </span>\n }\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ AUTO_REGISTRATION_POPOVER | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-2 d-flex\">\n <div class=\"text-truncate\">\n <span class=\"text-label-small m-t-8 m-r-4 visible-xs-inline\">\n {{ 'Proof of possession' | translate }}\n </span>\n @if (trustedCertificate.tenantCertificateAuthority) {\n <span title=\"{{ 'Proof of possession' | translate }}: {{ 'N/A' | translate }}\">\n {{ 'N/A' | translate }}\n </span>\n }\n @if (!trustedCertificate.tenantCertificateAuthority) {\n <span>\n @if (trustedCertificate.proofOfPossessionValid) {\n <span\n title=\"{{ 'Proof of possession' | translate }}: {{\n 'Complete`proof of possession`' | translate\n }}\"\n >\n <div class=\"icon-flex\">\n <i\n class=\"text-success\"\n c8yIcon=\"success\"\n ></i>\n {{ 'Complete`proof of possession`' | translate }}\n </div>\n </span>\n }\n @if (!trustedCertificate.proofOfPossessionValid) {\n <span\n title=\"{{ 'Proof of possession' | translate }}: {{\n 'Incomplete`proof of possession`' | translate\n }}\"\n >\n <div class=\"icon-flex\">\n <i\n class=\"text-warning\"\n c8yIcon=\"warning\"\n ></i>\n {{ 'Incomplete`proof of possession`' | translate }}\n </div>\n </span>\n }\n </span>\n }\n </div>\n <button\n class=\"m-l-auto btn-dot btn-dot--danger btn showOnHover m-r-8\"\n [attr.aria-label]=\"'Delete' | translate\"\n tooltip=\"{{ 'Delete' | translate }}\"\n placement=\"right\"\n type=\"button\"\n data-cy=\"c8y-trusted-certificate--delete\"\n [delay]=\"500\"\n (click)=\"deleteTrustedCertificate(trustedCertificate)\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n </div>\n </c8y-li-body>\n\n <c8y-li-collapse>\n <div class=\"p-t-16 p-b-16\">\n <div class=\"row\">\n <div class=\"col-md-4\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Certificate name' | translate }}\n </label>\n <c8y-input-group-editable\n required\n formGroupClass=\"m-b-0\"\n [ariaLabel]=\"'Certificate name' | translate\"\n data-cy=\"c8y-trusted-certificates--edit-certificate-name\"\n [(ngModel)]=\"trustedCertificate.name\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n (save)=\"\n updateCertificate(trustedCertificate, { name: trustedCertificate.name })\n \"\n ></c8y-input-group-editable>\n </c8y-form-group>\n </div>\n <div class=\"col-md-1\"></div>\n <div class=\"col-md-7\">\n <c8y-form-group>\n <label\n class=\"control-label\"\n for=\"certInPemFormat\"\n translate\n >\n Certificate\n </label>\n <textarea\n class=\"form-control no-resize\"\n id=\"certInPemFormat\"\n name=\"certInPemFormat\"\n type=\"text\"\n rows=\"7\"\n readonly\n [(ngModel)]=\"trustedCertificate.certInPemFormat\"\n ></textarea>\n </c8y-form-group>\n <c8y-form-group>\n <label\n class=\"c8y-checkbox\"\n title=\"{{ 'Auto registration' | translate }}\"\n [ngClass]=\"{\n disabled: !(hasAdminRole$ | async)\n }\"\n >\n <input\n type=\"checkbox\"\n [(ngModel)]=\"trustedCertificate.autoRegistrationEnabled\"\n (ngModelChange)=\"\n updateCertificate(trustedCertificate, { autoRegistrationEnabled: $event })\n \"\n [disabled]=\"!(hasAdminRole$ | async)\"\n />\n <span></span>\n <span>{{ 'Auto registration' | translate }}</span>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ AUTO_REGISTRATION_POPOVER | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n type=\"button\"\n ></button>\n </label>\n </c8y-form-group>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-4\">\n <div\n class=\"legend form-block\"\n translate\n >\n Additional properties\n </div>\n <ul class=\"list-unstyled\">\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Algorithm' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.algorithmName }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Version' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.version }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Valid from' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.notBefore | c8yDate }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Issuer' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.issuer }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Expiration date' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.notAfter | c8yDate }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Serial number' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.serialNumber }}\n </span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom flex-wrap\">\n <label class=\"small m-b-0 m-r-8 a-s-start flex-grow\">\n {{ 'Subject`of a certificate`' | translate }}\n </label>\n <span class=\"m-l-auto text-break-word\">\n {{ trustedCertificate.subject }}\n </span>\n </li>\n </ul>\n </div>\n <div class=\"col-md-1\"></div>\n @if (!trustedCertificate.tenantCertificateAuthority) {\n <div class=\"col-md-7\">\n <div class=\"legend form-block\">\n {{ 'Proof of possession' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ PROOF_OF_POSSESSION_POPOVER | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n type=\"button\"\n ></button>\n </div>\n @if (trustedCertificate.proofOfPossessionValid) {\n <div>\n <span\n class=\"icon-flex\"\n title=\"{{ 'Proof of possession' | translate }}: {{\n 'Complete`proof of possession`' | translate\n }}\"\n >\n <i\n class=\"text-success\"\n c8yIcon=\"success\"\n ></i>\n {{ 'Complete`proof of possession`' | translate }}\n </span>\n </div>\n }\n @if (!trustedCertificate.proofOfPossessionValid) {\n <div>\n <div class=\"row m-b-16\">\n <div class=\"col-md-6\">\n <span\n class=\"icon-flex\"\n title=\"{{ 'Proof of possession' | translate }}: {{\n 'Incomplete`proof of possession`' | translate\n }}\"\n >\n <i\n class=\"text-warning\"\n c8yIcon=\"warning\"\n ></i>\n {{ 'Incomplete`proof of possession`' | translate }}\n </span>\n </div>\n <div class=\"col-md-6 col-lg-6 text-right-md\">\n <span class=\"text-label-small m-r-4\">\n {{ 'Verification code expires/expired on' | translate }}\n </span>\n {{\n (trustedCertificate.proofOfPossessionVerificationCodeUsableUntil\n | c8yDate) || '---'\n }}\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6 col-lg-6\">\n <c8y-form-group>\n <label\n class=\"control-label\"\n for=\"unsignedVerificationCode\"\n translate\n >\n Verification code\n </label>\n <textarea\n class=\"form-control no-resize\"\n id=\"unsignedVerificationCode\"\n name=\"unsignedVerificationCode\"\n type=\"text\"\n rows=\"5\"\n readonly\n [(ngModel)]=\"\n trustedCertificate.proofOfPossessionUnsignedVerificationCode\n \"\n ></textarea>\n </c8y-form-group>\n <div class=\"d-flex\">\n <button\n class=\"btn btn-primary btn-sm\"\n title=\"{{ 'Regenerate verification code' | translate }}\"\n type=\"button\"\n (click)=\"regenerateUnsignedVerificationCode(trustedCertificate)\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n >\n {{ 'Regenerate`verification code`' | translate }}\n </button>\n\n <button\n class=\"btn btn-sm btn-default m-l-auto m-r-0\"\n [attr.aria-label]=\"'Copy to clipboard' | translate\"\n tooltip=\"{{ 'Copy to clipboard' | translate }}\"\n placement=\"right\"\n type=\"button\"\n data-cy=\"c8y-trusted-certificates--copy-to-clipboard\"\n [delay]=\"500\"\n [disabled]=\"\n !trustedCertificate.proofOfPossessionUnsignedVerificationCode\n \"\n (click)=\"copyUnsignedVerificationCodeToClipboard(trustedCertificate)\"\n >\n <i c8yIcon=\"clipboard\"></i>\n </button>\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Download as file' | translate\"\n tooltip=\"{{ 'Download as file' | translate }}\"\n type=\"button\"\n data-cy=\"c8y-trusted-certificates--download-as-file\"\n [delay]=\"500\"\n [disabled]=\"\n !trustedCertificate.proofOfPossessionUnsignedVerificationCode\n \"\n (click)=\"downloadUnsignedVerificationCode(trustedCertificate)\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component:\n PRODUCT_EXPERIENCE.VERIFICATION_CODE.COMPONENTS.DOWNLOAD_CODE,\n action: PRODUCT_EXPERIENCE.VERIFICATION_CODE.ACTIONS.DOWNLOAD\n }\"\n >\n <i c8yIcon=\"download\"></i>\n </button>\n </div>\n </div>\n\n <div class=\"col-md-6 col-lg-6\">\n <c8y-form-group>\n <label\n class=\"control-label\"\n for=\"signedVerificationCode\"\n >\n {{ 'Signed verification code' | translate }}\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ SIGNED_VERIFICATION_CODE_POPOVER | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n data-cy=\"c8y-trusted-certificates--signed-verification-code-popup\"\n [outsideClick]=\"true\"\n ></button>\n </label>\n <textarea\n class=\"form-control no-resize\"\n id=\"signedVerificationCode\"\n name=\"signedVerificationCode\"\n type=\"text\"\n rows=\"5\"\n [(ngModel)]=\"trustedCertificate.signedVerificationCode\"\n ></textarea>\n </c8y-form-group>\n <div class=\"d-flex\">\n <button\n class=\"btn btn-primary btn-sm\"\n title=\"{{ 'Verify signed verification code' | translate }}\"\n type=\"button\"\n (click)=\"verifySignedVerificationCode(trustedCertificate)\"\n [disabled]=\"!trustedCertificate.signedVerificationCode\"\n >\n {{ 'Verify`signed verification code`' | translate }}\n </button>\n <button\n class=\"btn btn-sm btn-default m-l-auto\"\n [attr.aria-label]=\"'Upload file' | translate\"\n tooltip=\"{{ 'Upload file' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"fileInput.click()\"\n [disabled]=\"!(hasAdminRole$ | async)\"\n >\n <i c8yIcon=\"upload\"></i>\n </button>\n <input\n class=\"hidden\"\n type=\"file\"\n #fileInput\n (change)=\"onFileInput($event, trustedCertificate)\"\n />\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </c8y-li-collapse>\n </c8y-li>\n </c8y-list-group>\n </div>\n}\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "directive", type: ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "directive", type: TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "directive", type: ButtonCheckboxDirective, selector: "[btnCheckbox]", inputs: ["btnCheckboxTrue", "btnCheckboxFalse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: ListItemCollapseComponent, selector: "c8y-list-item-collapse, c8y-li-collapse", inputs: ["collapseWay"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: InputGroupEditableComponent, selector: "c8y-input-group-editable", inputs: ["ariaLabel", "name", "size", "placeholder", "title", "multiline", "maxHeight", "maxLength", "noSaveButton", "formGroupClass", "validators", "asyncValidators", "autocomplete", "required"], outputs: ["save", "cancel"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] }); }
686
686
  }
687
687
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TrustedCertificateListComponent, decorators: [{
688
688
  type: Component,