@c8y/ngx-components 1024.15.13 → 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 +8 -2
  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 +39 -12
  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 +139 -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
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, input, effect, Directive, Pipe, createEnvironmentInjector, InjectionToken, Optional, Inject, EventEmitter, NgModule, LOCALE_ID, NgModuleRef, createNgModule, isDevMode, inject, DOCUMENT, EnvironmentInjector, Injector, Input, HostListener, Component, HostBinding, Output, forwardRef, DestroyRef, ViewChild, signal, viewChild, ChangeDetectionStrategy, contentChildren, untracked, SecurityContext, TemplateRef, ElementRef, provideAppInitializer, Self, SkipSelf, Attribute, ContentChild, computed, ContentChildren, ViewContainerRef, output, ChangeDetectorRef, ViewChildren, createComponent, runInInjectionContext, importProvidersFrom, SimpleChange, reflectComponentType, ViewEncapsulation, Type } from '@angular/core';
2
+ import { Injectable, input, effect, Directive, Pipe, createEnvironmentInjector, InjectionToken, Optional, Inject, EventEmitter, NgModule, LOCALE_ID, NgModuleRef, createNgModule, isDevMode, inject, DOCUMENT, EnvironmentInjector, Injector, Input, HostListener, Component, HostBinding, Output, forwardRef, DestroyRef, ViewChild, signal, viewChild, ChangeDetectionStrategy, contentChildren, untracked, SecurityContext, TemplateRef, ElementRef, provideAppInitializer, Self, SkipSelf, Attribute, ContentChild, computed, ContentChildren, ViewContainerRef, booleanAttribute, output, ChangeDetectorRef, ViewChildren, createComponent, runInInjectionContext, importProvidersFrom, SimpleChange, reflectComponentType, ViewEncapsulation, Type } from '@angular/core';
3
3
  import * as i1$2 from 'ngx-bootstrap/dropdown';
4
4
  import { BsDropdownDirective, BsDropdownModule } from 'ngx-bootstrap/dropdown';
5
5
  import * as i4$2 from '@angular/cdk/a11y';
@@ -3920,8 +3920,17 @@ function provideBootstrapMetadata(metadata) {
3920
3920
  hookCurrentTenant(metadata.currentTenant)
3921
3921
  ];
3922
3922
  }
3923
+ const HOOK_SKIP_APP_KEY_HEADER = new InjectionToken('HOOK_SKIP_APP_KEY_HEADER');
3924
+ /**
3925
+ * Allows to skip adding the application key header to the default headers of the FetchClient.
3926
+ * This is useful for applications that might be accessed without the application actually being subscribed to the tenant.
3927
+ * This is e.g. for the login app or the api-doc app the case.
3928
+ */
3929
+ function provideSkipAppKeyHeader() {
3930
+ return hookGeneric(true, HOOK_SKIP_APP_KEY_HEADER, { multi: false });
3931
+ }
3923
3932
  class AppStateService extends StateService {
3924
- constructor(applicationService, apiService, options, fetchClient, tenantLoginOptionsService, user, application, tenant) {
3933
+ constructor(applicationService, apiService, options, fetchClient, tenantLoginOptionsService, user, application, tenant, skipAppKeyHeader) {
3925
3934
  super();
3926
3935
  this.applicationService = applicationService;
3927
3936
  this.apiService = apiService;
@@ -3968,7 +3977,7 @@ class AppStateService extends StateService {
3968
3977
  this.apiService.isLoading$.subscribe(isLoading => {
3969
3978
  this.state.isLoading = isLoading;
3970
3979
  });
3971
- if (this.options.contextPath !== 'login') {
3980
+ if (!skipAppKeyHeader && this.options.contextPath !== 'login') {
3972
3981
  this.assignApplicationKeyToDefaultHeaders();
3973
3982
  }
3974
3983
  this.currentAppsOfUser = this.currentAppsOfUser$();
@@ -4098,7 +4107,7 @@ class AppStateService extends StateService {
4098
4107
  return;
4099
4108
  }));
4100
4109
  }
4101
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: AppStateService, deps: [{ token: i1.ApplicationService }, { token: i4.ApiService }, { token: OptionsService }, { token: i1.FetchClient }, { token: i1.TenantLoginOptionsService }, { token: HOOK_CURRENT_USER, optional: true }, { token: HOOK_CURRENT_APPLICATION, optional: true }, { token: HOOK_CURRENT_TENANT, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
4110
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: AppStateService, deps: [{ token: i1.ApplicationService }, { token: i4.ApiService }, { token: OptionsService }, { token: i1.FetchClient }, { token: i1.TenantLoginOptionsService }, { token: HOOK_CURRENT_USER, optional: true }, { token: HOOK_CURRENT_APPLICATION, optional: true }, { token: HOOK_CURRENT_TENANT, optional: true }, { token: HOOK_SKIP_APP_KEY_HEADER, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
4102
4111
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: AppStateService, providedIn: 'root' }); }
4103
4112
  }
4104
4113
  __decorate([
@@ -4125,6 +4134,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
4125
4134
  }, {
4126
4135
  type: Inject,
4127
4136
  args: [HOOK_CURRENT_TENANT]
4137
+ }] }, { type: undefined, decorators: [{
4138
+ type: Optional
4139
+ }, {
4140
+ type: Inject,
4141
+ args: [HOOK_SKIP_APP_KEY_HEADER]
4128
4142
  }] }], propDecorators: { refreshLoginOptions: [] } });
4129
4143
 
4130
4144
  /**
@@ -9472,10 +9486,25 @@ class DropdownFocusTrapDirective {
9472
9486
  }
9473
9487
  this.focusTrap = this.focusTrapFactory.create(this.dropdownMenuElement);
9474
9488
  this.focusTrap.enabled = true;
9489
+ this.fitMenuToViewport();
9475
9490
  this.document.addEventListener('keydown', this.handleSelection, true);
9476
9491
  this.document.addEventListener('keydown', this.handleEscape, true);
9477
9492
  }, 0);
9478
9493
  }
9494
+ /**
9495
+ * Caps the body-appended dropdown menu to the viewport height with an internal scroll, so its
9496
+ * lower controls (e.g. Apply) stay reachable when it opens from a toggle low on a short screen.
9497
+ * A menu that already fits is unaffected, as its natural height stays below the cap.
9498
+ * @private
9499
+ */
9500
+ fitMenuToViewport() {
9501
+ if (!this.dropdownMenuElement) {
9502
+ return;
9503
+ }
9504
+ const { top } = this.dropdownMenuElement.getBoundingClientRect();
9505
+ this.dropdownMenuElement.style.maxHeight = `${Math.max(120, window.innerHeight - top - 16)}px`;
9506
+ this.dropdownMenuElement.style.overflowY = 'auto';
9507
+ }
9479
9508
  onDropdownHidden() {
9480
9509
  const buttonToFocus = this.toggleButton;
9481
9510
  const shouldRestore = this.shouldRestoreFocus;
@@ -19610,6 +19639,9 @@ class InputGroupEditableComponent {
19610
19639
  this.size = input('', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
19611
19640
  /** Placeholder text shown inside the input when the value is empty. */
19612
19641
  this.placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
19642
+ /** Native `title` forwarded to the input, so a value that is truncated still shows in full on
19643
+ * hover. Passed through as-is (not translated). */
19644
+ this.title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
19613
19645
  /** When `true`, renders a `<textarea>` with `c8y-textarea-autoresize` instead of `<input>`.
19614
19646
  * The textarea starts at a single-line height and grows automatically as the user types. */
19615
19647
  this.multiline = input(false, ...(ngDevMode ? [{ debugName: "multiline" }] : /* istanbul ignore next */ []));
@@ -19634,6 +19666,8 @@ class InputGroupEditableComponent {
19634
19666
  this.asyncValidators = input(null, ...(ngDevMode ? [{ debugName: "asyncValidators" }] : /* istanbul ignore next */ []));
19635
19667
  /** The `autocomplete` attribute forwarded to the underlying `<input>` element. Defaults to `'off'`. */
19636
19668
  this.autocomplete = input('off', ...(ngDevMode ? [{ debugName: "autocomplete" }] : /* istanbul ignore next */ []));
19669
+ /** When `true`, the value must not be empty: a `Validators.required` check is applied.*/
19670
+ this.required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
19637
19671
  /** Emitted when the user confirms an edit. Provides the new string value.
19638
19672
  * Not emitted when `[noSaveButton]="true"`. */
19639
19673
  this.save = output();
@@ -19720,6 +19754,7 @@ class InputGroupEditableComponent {
19720
19754
  syncInternalValidators() {
19721
19755
  const inputV = this.validators();
19722
19756
  const syncList = [
19757
+ ...(this.required() ? [Validators.required] : []),
19723
19758
  ...(this.outerValidator ? [this.outerValidator] : []),
19724
19759
  ...(Array.isArray(inputV) ? inputV : inputV ? [inputV] : [])
19725
19760
  ];
@@ -19777,13 +19812,13 @@ class InputGroupEditableComponent {
19777
19812
  }, 0);
19778
19813
  }
19779
19814
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputGroupEditableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
19780
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputGroupEditableComponent, isStandalone: true, selector: "c8y-input-group-editable", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: true, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, multiline: { classPropertyName: "multiline", publicName: "multiline", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, noSaveButton: { classPropertyName: "noSaveButton", publicName: "noSaveButton", isSignal: true, isRequired: false, transformFunction: null }, formGroupClass: { classPropertyName: "formGroupClass", publicName: "formGroupClass", isSignal: true, isRequired: false, transformFunction: null }, validators: { classPropertyName: "validators", publicName: "validators", isSignal: true, isRequired: false, transformFunction: null }, asyncValidators: { classPropertyName: "asyncValidators", publicName: "asyncValidators", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { save: "save", cancel: "cancel" }, host: { classAttribute: "d-contents" }, providers: [
19815
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputGroupEditableComponent, isStandalone: true, selector: "c8y-input-group-editable", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: true, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, multiline: { classPropertyName: "multiline", publicName: "multiline", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, noSaveButton: { classPropertyName: "noSaveButton", publicName: "noSaveButton", isSignal: true, isRequired: false, transformFunction: null }, formGroupClass: { classPropertyName: "formGroupClass", publicName: "formGroupClass", isSignal: true, isRequired: false, transformFunction: null }, validators: { classPropertyName: "validators", publicName: "validators", isSignal: true, isRequired: false, transformFunction: null }, asyncValidators: { classPropertyName: "asyncValidators", publicName: "asyncValidators", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { save: "save", cancel: "cancel" }, host: { classAttribute: "d-contents" }, providers: [
19781
19816
  {
19782
19817
  provide: NG_VALUE_ACCESSOR,
19783
19818
  useExisting: forwardRef(() => InputGroupEditableComponent),
19784
19819
  multi: true
19785
19820
  }
19786
- ], queries: [{ propertyName: "customErrorMessages", predicate: MessageDirective }], viewQueries: [{ propertyName: "autoresizeDir", first: true, predicate: TextareaAutoresizeDirective, descendants: true, isSignal: true }, { propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<c8y-form-group\n [class]=\"formGroupClass()\"\n [status]=\"!!errors ? 'error' : ''\"\n>\n <div\n class=\"input-group input-group-editable\"\n [class.input-group-sm]=\"size() === 'sm'\"\n [class.input-group-lg]=\"size() === 'lg'\"\n [class.input-group-editable--no-actions]=\"noSaveButton()\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n role=\"group\"\n >\n @if (multiline()) {\n <textarea\n class=\"form-control no-resize\"\n [style.max-height]=\"maxHeight() || null\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n data-cy=\"c8y-input-group-editable--input\"\n #inputEl\n [attr.maxlength]=\"maxLength()\"\n [attr.name]=\"name() || null\"\n [placeholder]=\"(placeholder() | translate) || ''\"\n [formControl]=\"internalControl\"\n (keydown.control.enter)=\"noSaveButton() ? null : onSave()\"\n (keydown.escape)=\"onEscape($event)\"\n c8y-textarea-autoresize\n ></textarea>\n } @else {\n <input\n class=\"form-control\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n data-cy=\"c8y-input-group-editable--input\"\n #inputEl\n [attr.maxlength]=\"maxLength()\"\n [attr.name]=\"name() || null\"\n [attr.autocomplete]=\"autocomplete()\"\n [placeholder]=\"(placeholder() | translate) || ''\"\n [formControl]=\"internalControl\"\n (keydown.enter)=\"noSaveButton() ? null : onSave()\"\n (keydown.escape)=\"onEscape($event)\"\n data-1p-ignore\n data-lpignore=\"true\"\n data-bwignore\n />\n }\n <!-- Edit mode indicator hook used by _input-groups.scss -->\n <span aria-hidden=\"true\"></span>\n @if (!internalControl.disabled && !noSaveButton()) {\n <div class=\"input-group-btn min-width-0\">\n <button\n class=\"btn btn-clean\"\n [title]=\"'Cancel' | translate\"\n [attr.aria-label]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"onCancel()\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n </button>\n <button\n class=\"btn btn-clean text-primary\"\n [title]=\"'Save' | translate\"\n [attr.aria-label]=\"'Save' | translate\"\n type=\"button\"\n [disabled]=\"isSaveDisabled\"\n (click)=\"onSave()\"\n >\n <i\n c8yIcon=\"check\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n }\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >{{ liveMessage | translate }}</span\n >\n </div>\n <c8y-messages\n [show]=\"errors\"\n [additionalMessages]=\"customErrorMessages\"\n ></c8y-messages>\n</c8y-form-group>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.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: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage", "additionalMessages"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: TextareaAutoresizeDirective, selector: "[c8y-textarea-autoresize]" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
19821
+ ], queries: [{ propertyName: "customErrorMessages", predicate: MessageDirective }], viewQueries: [{ propertyName: "autoresizeDir", first: true, predicate: TextareaAutoresizeDirective, descendants: true, isSignal: true }, { propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<c8y-form-group\n [class]=\"formGroupClass()\"\n [status]=\"!!errors ? 'error' : ''\"\n>\n <div\n class=\"input-group input-group-editable\"\n [class.input-group-sm]=\"size() === 'sm'\"\n [class.input-group-lg]=\"size() === 'lg'\"\n [class.input-group-editable--no-actions]=\"noSaveButton()\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n role=\"group\"\n >\n @if (multiline()) {\n <textarea\n class=\"form-control no-resize\"\n [style.max-height]=\"maxHeight() || null\"\n [attr.title]=\"title() || null\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"errors ? 'true' : null\"\n data-cy=\"c8y-input-group-editable--input\"\n #inputEl\n [attr.maxlength]=\"maxLength()\"\n [attr.name]=\"name() || null\"\n [placeholder]=\"(placeholder() | translate) || ''\"\n [formControl]=\"internalControl\"\n (keydown.control.enter)=\"noSaveButton() ? null : onSave()\"\n (keydown.escape)=\"onEscape($event)\"\n c8y-textarea-autoresize\n ></textarea>\n } @else {\n <input\n class=\"form-control\"\n [attr.title]=\"title() || null\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"errors ? 'true' : null\"\n data-cy=\"c8y-input-group-editable--input\"\n #inputEl\n [attr.maxlength]=\"maxLength()\"\n [attr.name]=\"name() || null\"\n [attr.autocomplete]=\"autocomplete()\"\n [placeholder]=\"(placeholder() | translate) || ''\"\n [formControl]=\"internalControl\"\n (keydown.enter)=\"noSaveButton() ? null : onSave()\"\n (keydown.escape)=\"onEscape($event)\"\n data-1p-ignore\n data-lpignore=\"true\"\n data-bwignore\n />\n }\n <!-- Edit mode indicator hook used by _input-groups.scss -->\n <span aria-hidden=\"true\"></span>\n @if (!internalControl.disabled && !noSaveButton() && internalControl.dirty) {\n <div class=\"input-group-btn min-width-0\">\n <button\n class=\"btn btn-clean\"\n [title]=\"'Cancel' | translate\"\n [attr.aria-label]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"onCancel()\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n </button>\n <button\n class=\"btn btn-clean text-primary\"\n [title]=\"'Save' | translate\"\n [attr.aria-label]=\"'Save' | translate\"\n type=\"button\"\n [disabled]=\"isSaveDisabled\"\n (click)=\"onSave()\"\n >\n <i\n c8yIcon=\"check\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n }\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >{{ liveMessage | translate }}</span\n >\n </div>\n <c8y-messages\n role=\"alert\"\n [show]=\"errors\"\n [additionalMessages]=\"customErrorMessages\"\n ></c8y-messages>\n</c8y-form-group>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.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: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage", "additionalMessages"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: TextareaAutoresizeDirective, selector: "[c8y-textarea-autoresize]" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
19787
19822
  }
19788
19823
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputGroupEditableComponent, decorators: [{
19789
19824
  type: Component,
@@ -19800,8 +19835,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
19800
19835
  useExisting: forwardRef(() => InputGroupEditableComponent),
19801
19836
  multi: true
19802
19837
  }
19803
- ], template: "<c8y-form-group\n [class]=\"formGroupClass()\"\n [status]=\"!!errors ? 'error' : ''\"\n>\n <div\n class=\"input-group input-group-editable\"\n [class.input-group-sm]=\"size() === 'sm'\"\n [class.input-group-lg]=\"size() === 'lg'\"\n [class.input-group-editable--no-actions]=\"noSaveButton()\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n role=\"group\"\n >\n @if (multiline()) {\n <textarea\n class=\"form-control no-resize\"\n [style.max-height]=\"maxHeight() || null\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n data-cy=\"c8y-input-group-editable--input\"\n #inputEl\n [attr.maxlength]=\"maxLength()\"\n [attr.name]=\"name() || null\"\n [placeholder]=\"(placeholder() | translate) || ''\"\n [formControl]=\"internalControl\"\n (keydown.control.enter)=\"noSaveButton() ? null : onSave()\"\n (keydown.escape)=\"onEscape($event)\"\n c8y-textarea-autoresize\n ></textarea>\n } @else {\n <input\n class=\"form-control\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n data-cy=\"c8y-input-group-editable--input\"\n #inputEl\n [attr.maxlength]=\"maxLength()\"\n [attr.name]=\"name() || null\"\n [attr.autocomplete]=\"autocomplete()\"\n [placeholder]=\"(placeholder() | translate) || ''\"\n [formControl]=\"internalControl\"\n (keydown.enter)=\"noSaveButton() ? null : onSave()\"\n (keydown.escape)=\"onEscape($event)\"\n data-1p-ignore\n data-lpignore=\"true\"\n data-bwignore\n />\n }\n <!-- Edit mode indicator hook used by _input-groups.scss -->\n <span aria-hidden=\"true\"></span>\n @if (!internalControl.disabled && !noSaveButton()) {\n <div class=\"input-group-btn min-width-0\">\n <button\n class=\"btn btn-clean\"\n [title]=\"'Cancel' | translate\"\n [attr.aria-label]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"onCancel()\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n </button>\n <button\n class=\"btn btn-clean text-primary\"\n [title]=\"'Save' | translate\"\n [attr.aria-label]=\"'Save' | translate\"\n type=\"button\"\n [disabled]=\"isSaveDisabled\"\n (click)=\"onSave()\"\n >\n <i\n c8yIcon=\"check\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n }\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >{{ liveMessage | translate }}</span\n >\n </div>\n <c8y-messages\n [show]=\"errors\"\n [additionalMessages]=\"customErrorMessages\"\n ></c8y-messages>\n</c8y-form-group>\n" }]
19804
- }], ctorParameters: () => [], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: true }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], noSaveButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "noSaveButton", required: false }] }], formGroupClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGroupClass", required: false }] }], validators: [{ type: i0.Input, args: [{ isSignal: true, alias: "validators", required: false }] }], asyncValidators: [{ type: i0.Input, args: [{ isSignal: true, alias: "asyncValidators", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], save: [{ type: i0.Output, args: ["save"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], customErrorMessages: [{
19838
+ ], template: "<c8y-form-group\n [class]=\"formGroupClass()\"\n [status]=\"!!errors ? 'error' : ''\"\n>\n <div\n class=\"input-group input-group-editable\"\n [class.input-group-sm]=\"size() === 'sm'\"\n [class.input-group-lg]=\"size() === 'lg'\"\n [class.input-group-editable--no-actions]=\"noSaveButton()\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n role=\"group\"\n >\n @if (multiline()) {\n <textarea\n class=\"form-control no-resize\"\n [style.max-height]=\"maxHeight() || null\"\n [attr.title]=\"title() || null\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"errors ? 'true' : null\"\n data-cy=\"c8y-input-group-editable--input\"\n #inputEl\n [attr.maxlength]=\"maxLength()\"\n [attr.name]=\"name() || null\"\n [placeholder]=\"(placeholder() | translate) || ''\"\n [formControl]=\"internalControl\"\n (keydown.control.enter)=\"noSaveButton() ? null : onSave()\"\n (keydown.escape)=\"onEscape($event)\"\n c8y-textarea-autoresize\n ></textarea>\n } @else {\n <input\n class=\"form-control\"\n [attr.title]=\"title() || null\"\n [attr.aria-label]=\"ariaLabel() | translate\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"errors ? 'true' : null\"\n data-cy=\"c8y-input-group-editable--input\"\n #inputEl\n [attr.maxlength]=\"maxLength()\"\n [attr.name]=\"name() || null\"\n [attr.autocomplete]=\"autocomplete()\"\n [placeholder]=\"(placeholder() | translate) || ''\"\n [formControl]=\"internalControl\"\n (keydown.enter)=\"noSaveButton() ? null : onSave()\"\n (keydown.escape)=\"onEscape($event)\"\n data-1p-ignore\n data-lpignore=\"true\"\n data-bwignore\n />\n }\n <!-- Edit mode indicator hook used by _input-groups.scss -->\n <span aria-hidden=\"true\"></span>\n @if (!internalControl.disabled && !noSaveButton() && internalControl.dirty) {\n <div class=\"input-group-btn min-width-0\">\n <button\n class=\"btn btn-clean\"\n [title]=\"'Cancel' | translate\"\n [attr.aria-label]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"onCancel()\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n </button>\n <button\n class=\"btn btn-clean text-primary\"\n [title]=\"'Save' | translate\"\n [attr.aria-label]=\"'Save' | translate\"\n type=\"button\"\n [disabled]=\"isSaveDisabled\"\n (click)=\"onSave()\"\n >\n <i\n c8yIcon=\"check\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n }\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >{{ liveMessage | translate }}</span\n >\n </div>\n <c8y-messages\n role=\"alert\"\n [show]=\"errors\"\n [additionalMessages]=\"customErrorMessages\"\n ></c8y-messages>\n</c8y-form-group>\n" }]
19839
+ }], ctorParameters: () => [], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: true }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], noSaveButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "noSaveButton", required: false }] }], formGroupClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGroupClass", required: false }] }], validators: [{ type: i0.Input, args: [{ isSignal: true, alias: "validators", required: false }] }], asyncValidators: [{ type: i0.Input, args: [{ isSignal: true, alias: "asyncValidators", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], save: [{ type: i0.Output, args: ["save"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], customErrorMessages: [{
19805
19840
  type: ContentChildren,
19806
19841
  args: [MessageDirective]
19807
19842
  }], autoresizeDir: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TextareaAutoresizeDirective), { isSignal: true }] }], inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }] } });
@@ -23720,7 +23755,7 @@ class PluginsService {
23720
23755
  getMFRemotes(application) {
23721
23756
  const manifest = application.manifest || {};
23722
23757
  const config = application?.config;
23723
- let remotes = config?.remotes || manifest.remotes || {};
23758
+ let remotes = mergeRemotes([manifest.remotes || {}, config?.remotes || {}]);
23724
23759
  const manifestExports = manifest.exports || manifest.manifest?.exports || [];
23725
23760
  const selfRemotes = manifestExports
23726
23761
  .filter(plugin => plugin.scope === PluginsExportScopes.SELF)
@@ -24775,9 +24810,14 @@ class BottomDrawerComponent {
24775
24810
  return this.drawerOpenObs$;
24776
24811
  }
24777
24812
  /**
24778
- * Handles Escape key press to close the drawer.
24813
+ * Handles Escape key press to close the drawer. A modal on top owns the key and closes only
24814
+ * itself; it carries `modal-open` on the body and closes on a `window` listener, which runs
24815
+ * after this `document` one, so the class is still set here.
24779
24816
  */
24780
24817
  onEscapeKey(event) {
24818
+ if (document.body.classList.contains('modal-open')) {
24819
+ return;
24820
+ }
24781
24821
  if (this.closeOnEscape && this.bottomDrawerRef.isTop()) {
24782
24822
  event.preventDefault();
24783
24823
  this.hide();
@@ -34339,6 +34379,27 @@ class BaseColumn {
34339
34379
  }
34340
34380
  }
34341
34381
 
34382
+ /**
34383
+ * Built-in managed object attributes. Unlike fragments, these are not matched by the `has()`
34384
+ * query operator, so a "defined" filter on them must use a wildcard equality (`path eq '*'`),
34385
+ * which the backend evaluates as "attribute present".
34386
+ */
34387
+ const NON_FRAGMENT_PATHS = ['id', 'name', 'type', 'owner', 'creationTime', 'lastUpdated'];
34388
+ /**
34389
+ * Built-in attributes the platform always sets, so "value is defined" holds for every row and the
34390
+ * toggle would never filter anything. `creationTime`/`lastUpdated` also cannot be wildcard-matched
34391
+ * (dates do not accept `*`). The "defined" field is therefore hidden for these columns.
34392
+ */
34393
+ const ALWAYS_DEFINED_PATHS = ['id', 'creationTime', 'lastUpdated'];
34394
+ /**
34395
+ * Builds the "value is defined" condition for a fragment path. `has()` alone matches a fragment
34396
+ * that exists but holds an empty string, so rows with a blank value (e.g. a cleared `c8y_Notes`)
34397
+ * would survive the filter. Pairing it with `not(path eq '')` keeps only rows that actually carry
34398
+ * a value.
34399
+ */
34400
+ function definedFragmentCondition(path) {
34401
+ return { __and: [{ __has: path }, { __not: { [path]: '' } }] };
34402
+ }
34342
34403
  class CustomColumn extends BaseColumn {
34343
34404
  constructor(initialColumnConfig) {
34344
34405
  super(initialColumnConfig);
@@ -34348,14 +34409,18 @@ class CustomColumn extends BaseColumn {
34348
34409
  this.filterable = true;
34349
34410
  this.filteringConfig = {
34350
34411
  fields: [
34351
- {
34352
- key: 'exists',
34353
- type: 'switch',
34354
- defaultValue: false,
34355
- templateOptions: {
34356
- label: gettext$1('Only rows where value is defined')
34357
- }
34358
- },
34412
+ ...(ALWAYS_DEFINED_PATHS.includes(this.path)
34413
+ ? []
34414
+ : [
34415
+ {
34416
+ key: 'exists',
34417
+ type: 'switch',
34418
+ defaultValue: false,
34419
+ props: {
34420
+ label: gettext$1('Only rows where value is defined')
34421
+ }
34422
+ }
34423
+ ]),
34359
34424
  ...getBasicInputArrayFormFieldConfig({
34360
34425
  key: 'equals',
34361
34426
  label: gettext$1('Only rows where value equals to'),
@@ -34367,11 +34432,17 @@ class CustomColumn extends BaseColumn {
34367
34432
  ],
34368
34433
  getFilter: (model) => {
34369
34434
  const filter = {};
34435
+ const conditions = [];
34370
34436
  if (model.exists) {
34371
- filter.__has = this.path;
34437
+ conditions.push(NON_FRAGMENT_PATHS.includes(this.path)
34438
+ ? { [this.path]: '*' }
34439
+ : definedFragmentCondition(this.path));
34372
34440
  }
34373
34441
  if (model.equals) {
34374
- filter[this.path] = { __in: model.equals };
34442
+ conditions.push({ [this.path]: { __in: model.equals } });
34443
+ }
34444
+ if (conditions.length) {
34445
+ filter.__and = conditions;
34375
34446
  }
34376
34447
  return filter;
34377
34448
  }
@@ -36392,7 +36463,7 @@ class DataGridComponent {
36392
36463
  provide: PRODUCT_EXPERIENCE_EVENT_SOURCE,
36393
36464
  useExisting: forwardRef(() => DataGridComponent)
36394
36465
  }
36395
- ], queries: [{ propertyName: "expandableRow", first: true, predicate: ExpandableRowDirective, descendants: true }, { propertyName: "emptyState", first: true, predicate: EmptyStateContextDirective, descendants: true }, { propertyName: "columnRenderers", predicate: ColumnDirective }], viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scroll"], descendants: true, static: true }, { propertyName: "infiniteScrollContainer", first: true, predicate: ["infiniteScrollContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "tableRef", first: true, predicate: CdkTable, descendants: true }, { propertyName: "thRefs", predicate: CdkHeaderCell, descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "@let loadingData = ((dataSource.loading$ | async) && !loadMoreComponent?.isLoading) || loading;\n\n<div\n class=\"table-data-grid-scroll\"\n #scroll\n [ngClass]=\"{\n 'table-data-grid__overlay': loadingData\n }\"\n data-cy=\"c8y-data-grid--table-data-grid-scroll\"\n>\n @if (loadingData && displayOptions.showLoadingIndicator) {\n <div class=\"table-data-grid__loading--wrapper\">\n <div class=\"table-data-grid__loading--loader\">\n <c8y-loading\n layout=\"application\"\n [message]=\"loadingItemsLabel\"\n ></c8y-loading>\n </div>\n </div>\n }\n\n @if (displayOptions.gridHeader) {\n <div class=\"table-data-grid-header separator large-padding\">\n <div\n class=\"h4\"\n [ngClass]=\"{ 'm-r-16': !!title }\"\n >\n {{ title | translate }}\n </div>\n\n @if (displayOptions.filter) {\n @if (!filteringApplied) {\n <span>\n @if (!!filteringLabelsParams.allItemsCount) {\n <small\n class=\"m-r-4\"\n ngNonBindable\n translate\n [translateParams]=\"filteringLabelsParams\"\n >\n {{ filteredItemsCount }} of {{ allItemsCount }} items\n </small>\n }\n <span\n class=\"label label-default m-r-4\"\n translate\n >\n No filters\n </span>\n </span>\n }\n @if (filteringApplied) {\n <span class=\"d-flex a-i-center\">\n @if (!!filteringLabelsParams.allItemsCount) {\n <div class=\"a-i-center\">\n <span class=\"badge badge-info m-r-4\">\n {{ (dataSource.stats$ | async).filteredSize }}\n </span>\n <small\n ngNonBindable\n translate\n [translateParams]=\"filteringLabelsParams\"\n >\n of {{ allItemsCount }} items\n </small>\n </div>\n }\n <div\n class=\"dropdown\"\n placement=\"bottom left\"\n container=\"body\"\n dropdown\n #ddFilters=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btn btn-default btn-sm m-l-8\"\n title=\"{{ 'Active filters' | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n data-cy=\"c8y-data-grid--filters\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"filter\"\n ></i>\n <span>{{ 'Active filters' | translate }}</span>\n <span\n class=\"badge badge-system\"\n data-cy=\"c8y-data-grid--filters-count\"\n >\n {{ columnsWithFiltersApplied.length }}\n </span>\n </button>\n\n <div\n class=\"dropdown-menu\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"data-grid__dropdown bg-level-0\">\n <ul class=\"list-unstyled m-0\">\n @for (column of columnsWithFiltersApplied; track $index; let last = $last) {\n <li [ngClass]=\"{ 'separator-bottom': !last }\">\n <ng-container>\n <div\n class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n title=\"{{ (column.header | translate) || column.name }}\"\n >\n <label>\n {{ (column.header | translate) || column.name }}\n </label>\n </div>\n @for (\n groupedFilterChips of column\n | mapToFilterChips\n | async\n | groupedFilterChips;\n track $index;\n let first = $first\n ) {\n <div\n class=\"list-group-item borderless d-flex d-col\"\n [ngClass]=\"{ 'p-t-0': first }\"\n >\n @if (groupedFilterChips.label) {\n <p class=\"small p-b-4\">\n {{ groupedFilterChips.label | translate }}\n </p>\n }\n <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n @for (chip of groupedFilterChips.chips; track $index) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ 'Remove filter' | translate }}\"\n (click)=\"removeFilter(chip.remove())\"\n data-cy=\"c8y-data-grid--remove-chip\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ chip.displayValue | translate }}\n </span>\n }\n </div>\n </div>\n }\n </ng-container>\n </li>\n }\n </ul>\n </div>\n <div class=\"list-group-item separator-top sticky-bottom\">\n <button\n class=\"btn btn-sm btn-default\"\n title=\"{{ 'Clear all filters' | translate }}\"\n type=\"button\"\n (click)=\"clearFilters()\"\n data-cy=\"c8y-data-grid--clear-filters\"\n >\n {{ 'Clear all filters' | translate }}\n </button>\n </div>\n </div>\n </div>\n </span>\n }\n\n @if (displayOptions.filter) {\n <button\n class=\"btn-help btn-help--sm hidden-xs hidden-sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"filtersHelpPopover\"\n placement=\"right\"\n triggers=\"focus\"\n type=\"button\"\n data-cy=\"data-grid--help-filters\"\n >\n <i c8yIcon=\"question-circle-o\"></i>\n </button>\n }\n <ng-template #filtersHelpPopover>\n <div [innerHtml]=\"filtersHelpPopoverHtml | translate\"></div>\n </ng-template>\n\n @if (showCounterWarning) {\n <button\n class=\"btn-clean text-primary hidden-xs hidden-sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The counter for the total number of items might be inaccurate.' | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n type=\"button\"\n >\n <i c8yIcon=\"warning\"></i>\n </button>\n }\n }\n\n <div class=\"m-l-auto\">\n <div class=\"btnbar d-flex a-i-center\">\n @for (\n headerActionControl of headerActionControls | visibleControls | async;\n track $index\n ) {\n <ng-container>\n @if (!headerActionControl.template) {\n <button\n class=\"btnbar-btn btn-link\"\n title=\"{{ headerActionControl.text | translate }}\"\n type=\"button\"\n (click)=\"headerActionControl.callback()\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION,\n customActionName: headerActionControl.text,\n type: headerActionControl.type\n }\"\n >\n <i\n class=\"m-r-4\"\n [c8yIcon]=\"headerActionControl.icon\"\n ></i>\n <span>{{ headerActionControl.text | translate }}</span>\n </button>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"\n headerActionControl.template;\n context: { headerActionControl: headerActionControl }\n \"\n ></ng-container>\n }\n </ng-container>\n }\n\n @if (configureColumnsEnabled) {\n <div\n class=\"dropdown\"\n placement=\"bottom left\"\n container=\"body\"\n dropdown\n #ddConfigureColumns=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Configure columns' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--custom-column-btn\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"columns\"\n ></i>\n <span>{{ 'Configure columns' | translate }}</span>\n </button>\n\n <ul\n class=\"dropdown-menu data-grid__dropdown\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <li>\n <div\n class=\"list-group m-0\"\n cdkDropList\n (cdkDropListDropped)=\"onColumnDrop($event)\"\n >\n @for (column of columns; track $index) {\n <div\n cdkDrag\n cdkDragLockAxis=\"y\"\n >\n @if (!column.positionFixed) {\n <div class=\"list-group-item draggable-after p-l-16 p-r-16 a-i-center\">\n <label\n class=\"c8y-checkbox min-width-0\"\n title=\"{{ column.custom ? ('Custom' | translate) + ' ' : '' }}{{\n (column.header | translate) || column.name\n }}\"\n [attr.data-cy]=\"'data-grid--custom-column-header-' + column.header\"\n >\n <input\n type=\"checkbox\"\n [(ngModel)]=\"column.visible\"\n (change)=\"\n updateGridColumnsSize();\n emitConfigChange('changeColumnVisibility')\n \"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CHANGE_VISIBILITY,\n column: column.name,\n visible: !column.visible\n }\"\n />\n <span></span>\n <div class=\"d-col min-width-0 m-l-8 m-r-8\">\n @if (column?.custom) {\n <span class=\"text-muted text-10 m-b-0\">\n {{ 'Custom' | translate }}\n </span>\n }\n <span class=\"text-truncate l-h-1 m-t-2\">\n {{ (column.header | translate) || column.name }}\n </span>\n </div>\n @let canRetrieve = canRetrieveAssetProperties | async;\n @if (canRetrieve) {\n @if (canRetrieve && column?.type) {\n <span\n class=\"tag tag--default a-s-end\"\n title=\"{{ column.type | translate | humanize }}\"\n >\n {{ column.type | translate | humanize }}\n </span>\n }\n }\n </label>\n @if (column.custom) {\n <button\n class=\"btn btn-dot btn-dot--danger showOnHover max-width-fit a-i-center\"\n [attr.aria-label]=\"'Remove`column,verb`' | translate\"\n [popover]=\"confirmRemovePopover\"\n type=\"button\"\n #pop=\"bs-popover\"\n (click)=\"\n currentRemoveCustomColumnPopover !== pop &&\n currentRemoveCustomColumnPopover?.hide();\n currentRemoveCustomColumnPopover = pop\n \"\n >\n <i\n c8yIcon=\"minus-circle\"\n data-cy=\"data-grid--custom-column-remove-btn\"\n ></i>\n </button>\n\n <ng-template #confirmRemovePopover>\n <h3 class=\"popover-title popover-header\">\n {{ 'Confirm removal' | translate }}\n </h3>\n <div class=\"popover-content popover-body\">\n <p>{{ 'Do you want to remove this column?' | translate }}</p>\n <div class=\"popover-footer gap-16\">\n <button\n class=\"btn btn-default btn-sm\"\n type=\"button\"\n (click)=\"pop.hide()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-danger btn-sm\"\n type=\"button\"\n (click)=\"confirmRemoveColumn(column); pop.hide()\"\n data-cy=\"popover-confirm--Remove\"\n >\n {{ 'Remove' | translate }}\n </button>\n </div>\n </div>\n </ng-template>\n }\n </div>\n }\n </div>\n }\n </div>\n </li>\n @if (isConfigContextKnown) {\n <li class=\"p-8 sticky-bottom separator-top\">\n <button\n class=\"btn btn-default btn-block\"\n title=\"{{ 'Add custom column' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--add-custom-column\"\n (click)=\"openCustomColumn(); ddConfigureColumns.hide()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"plus-circle\"\n ></i>\n <span>{{ 'Add custom column' | translate }}</span>\n </button>\n </li>\n }\n </ul>\n </div>\n }\n\n @if (!hideReload) {\n <button\n class=\"btnbar-btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--reload-btn\"\n [disabled]=\"dataSource.loading$ | async\"\n (click)=\"clickReload()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"refresh\"\n ></i>\n <span>{{ 'Reload' | translate }}</span>\n </button>\n }\n\n @if (!serverSideDataCallback || showSearch) {\n <div class=\"input-group input-group-search m-l-sm-16 data-grid__search-input\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Search\u2026' | translate }}\"\n type=\"search\"\n [(ngModel)]=\"searchText\"\n (ngModelChange)=\"searchText$.emit($event)\"\n (keydown.enter)=\"$event.stopPropagation(); performSearch(searchText)\"\n />\n <div class=\"input-group-addon\">\n @if (searchText.length === 0) {\n <i c8yIcon=\"search\"></i>\n }\n @if (searchText.length > 0) {\n <i\n class=\"pointer\"\n c8yIcon=\"times\"\n (click)=\"searchText = ''; searchText$.emit('')\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.CLEAR_SEARCH }\"\n ></i>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if (selectedItemIds.length !== 0) {\n <div\n class=\"table-data-grid-header-bulk-actions animated slideInDown fast\"\n data-cy=\"table-data-grid-header-bulk-actions\"\n >\n <h4>\n <ng-container [ngPlural]=\"selectedItemIds.length\">\n <ng-template ngPluralCase=\"=1\">\n <span translate>1 selected item.</span>\n </ng-template>\n <ng-template ngPluralCase=\"other\">\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ count: selectedItemIds.length }\"\n >\n {{ count }} selected items.\n </span>\n </ng-template>\n </ng-container>\n <br class=\"visible-xs\" />\n @if (!serverSideDataCallback && selectedItemIds.length >= pagination.pageSize) {\n <small>\n <a\n class=\"interact\"\n (click)=\"setAllItemsSelected(true)\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.SELECT_ALL_ITEMS }\"\n >\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ count: (dataSource.stats$ | async).filteredSize }\"\n >\n Select all {{ count }} items\n </span>\n </a>\n </small>\n }\n </h4>\n <div class=\"m-l-auto\">\n <div class=\"btnbar d-flex\">\n @for (\n bulkActionControl of bulkActionControls | visibleControls: selectedItemIds | async;\n track $index\n ) {\n <ng-container>\n @switch (bulkActionControl.type) {\n @case (builtInActionType.Export) {\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Export' | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{ action: PX_ACTIONS.BULK_EXPORT }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"sign-out\"></i>\n <span>{{ 'Export' | translate }}</span>\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Delete' | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{ action: PX_ACTIONS.BULK_DELETE }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"delete\"></i>\n <span>{{ 'Delete' | translate }}</span>\n </button>\n }\n @default {\n <button\n class=\"btnbar-btn\"\n title=\"{{ bulkActionControl.text | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.BULK_CUSTOM_ACTION,\n customActionName: bulkActionControl.text\n }\"\n c8yProductExperience\n inherit\n >\n <i\n [class]=\"bulkActionControl.iconClasses\"\n c8yIcon=\"{{ bulkActionControl.icon }}\"\n ></i>\n <span>{{ bulkActionControl.text | translate }}</span>\n </button>\n }\n }\n </ng-container>\n }\n\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n [actionData]=\"{\n action: PX_ACTIONS.BULK_CANCEL\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"times\"></i>\n <span>{{ 'Cancel' | translate }}</span>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <table\n class=\"table table-filtered-sorted table-data-grid large-padding\"\n [class.table-striped]=\"displayOptions.striped && !treeGrid\"\n [class.table-bordered]=\"displayOptions.bordered\"\n [class.table-hover]=\"displayOptions.hover\"\n [class.table-data-grid-with-checkboxes]=\"selectable\"\n [class.table-data-grid-with-actions]=\"actionControls.length > 0\"\n [style.grid-template-columns]=\"styles.gridTemplateColumns\"\n cdk-table\n [dataSource]=\"dataSource\"\n [multiTemplateDataRows]=\"true\"\n (mousemove)=\"resizeHandleContainerMouseMove$.emit($event)\"\n data-cy=\"c8y-data-grid--table\"\n >\n @for (column of columns; track column.name; let i = $index) {\n <ng-container [cdkColumnDef]=\"column.name\">\n @switch (column.name) {\n @case ('checkbox') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n >\n <div>\n <label class=\"c8y-checkbox\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n type=\"checkbox\"\n [checked]=\"currentPageSelectionState.allSelected\"\n [indeterminate]=\"\n !(\n currentPageSelectionState.allSelected ||\n currentPageSelectionState.allDeselected\n )\n \"\n (change)=\"setAllItemsInCurrentPageSelected($event.target.checked)\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.SELECT_ALL_ITEMS }\"\n />\n <span></span>\n </label>\n </div>\n </th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n <label class=\"c8y-checkbox\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n type=\"checkbox\"\n [checked]=\"isItemSelected(row)\"\n (change)=\"setItemsSelected([row], $event.target.checked)\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.SELECT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--checkbox\"\n />\n <span></span>\n </label>\n </td>\n }\n\n @case ('radio-button') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n ></th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n <label class=\"c8y-radio\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n name=\"select-row\"\n type=\"radio\"\n [checked]=\"isItemSelected(row)\"\n (change)=\"changeSelectedItem(row)\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.SELECT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--radio\"\n />\n <span></span>\n </label>\n </td>\n }\n\n @case ('actions') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n >\n <p class=\"text-medium sr-only\">{{ 'Actions' | translate }}</p>\n </th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n @for (\n actionControl of actionControls\n | visibleControls: row\n | async\n | slice\n : 0\n : ((actionControls | visibleControls: row | async)?.length > 2 ? 1 : 2);\n track $index\n ) {\n <ng-container>\n @switch (actionControl.type) {\n @case (builtInActionType.Edit) {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"'Edit' | translate\"\n tooltip=\"{{ 'Edit' | translate }}\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.EDIT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--edit-button-in-row\"\n >\n <i c8yIcon=\"pencil\"></i>\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n class=\"btn btn-dot btn-dot--danger showOnHover\"\n [attr.aria-label]=\"'Delete' | translate\"\n tooltip=\"{{ 'Delete' | translate }}\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.DELETE_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n data-cy=\"c8y-data-grid--remove-button-in-row\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n }\n @default {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n (actionControl.icon ? actionControl.text : '') | translate\n \"\n tooltip=\"{{ (actionControl.icon ? actionControl.text : '') | translate }}\"\n container=\"body\"\n type=\"button\"\n [ngClass]=\"{ showOnHover: actionControl.showOnHover }\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION_ITEM,\n customActionName: actionControl.text,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n [attr.data-cy]=\"'c8y-data-grid--button-in-row--' + actionControl.text\"\n >\n @if (actionControl.icon) {\n <i\n c8yIcon=\"{{ actionControl.icon }}\"\n [ngClass]=\"actionControl.iconClasses\"\n ></i>\n } @else {\n <span>{{ actionControl.text | translate }}</span>\n }\n </button>\n }\n }\n </ng-container>\n }\n\n <div\n [ngClass]=\"{\n 'm-l-auto overflow-visible':\n (actionControls | visibleControls: row | async)?.length > 2\n }\"\n >\n @if ((actionControls | visibleControls: row | async)?.length > 2) {\n <div\n class=\"dropdown\"\n placement=\"bottom right\"\n container=\"body\"\n dropdown\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n title=\"{{ 'Actions' | translate }}\"\n aria-haspopup=\"true\"\n type=\"button\"\n data-cy=\"c8y-data-grid--row-actions-dropdown\"\n dropdownToggle\n >\n <i c8yIcon=\"ellipsis-v\"></i>\n </button>\n <ul\n class=\"dropdown-menu dropdown-menu-right\"\n *dropdownMenu\n >\n @for (\n actionControl of actionControls\n | visibleControls: row\n | async\n | slice\n : ((actionControls | visibleControls: row | async)?.length > 2 ? 1 : 2);\n track $index\n ) {\n <li>\n @switch (actionControl.type) {\n @case (builtInActionType.Edit) {\n <button\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.EDIT_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n title=\"{{ 'Delete' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.DELETE_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"delete\"></i>\n {{ 'Delete' | translate }}\n </button>\n }\n @case (builtInActionType.Export) {\n <button\n title=\"{{ 'Export' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.EXPORT_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"data-export\"></i>\n {{ 'Export' | translate }}\n </button>\n }\n @default {\n <button\n title=\"{{ actionControl.text | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION_ITEM,\n customActionName: actionControl.text,\n id: row.id\n }\"\n >\n <i\n c8yIcon=\"{{ actionControl.icon }}\"\n [ngClass]=\"actionControl.iconClasses\"\n ></i>\n {{ actionControl.text | translate }}\n </button>\n }\n }\n </li>\n }\n </ul>\n </div>\n }\n </div>\n </td>\n }\n @default {\n <th\n [class.sorted]=\"column.sortOrder\"\n [class.filtered]=\"column | map: isColumnFilteringApplied\"\n [class.hidden]=\"!column.visible\"\n cdk-header-cell\n *cdkHeaderCellDef\n [ngClass]=\"column.headerCSSClassName\"\n [attr.data-type]=\"column.dataType\"\n >\n @if (!column.filterable) {\n <div [title]=\"(column.header | translate) || column.name\">\n @let cellRendererSpec =\n [\n {\n columnName: column.name,\n value: (column.header | translate) || column.name\n }\n ] | map: getHeaderCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer [spec]=\"cellRendererSpec\"></c8y-cell-renderer>\n }\n </div>\n }\n\n <!-- isDropDownPlacedRight to be removed when columns are transformed to observables. -->\n @if (column.filterable) {\n <div\n class=\"dropdown\"\n placement=\"bottom {{ isDropDownPlacedRight(column) ? 'right' : 'left' }}\"\n container=\"body\"\n dropdown\n #gridHeaderDropdown=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btn-header\"\n [title]=\"(column.header | translate) || column.name\"\n type=\"button\"\n [attr.data-cy]=\"'data-grid--header-btn--' + column.header\"\n dropdownToggle\n >\n @let cellRendererSpec =\n [\n {\n columnName: column.name,\n value: (column.header | translate) || column.name\n }\n ] | map: getHeaderCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer\n data-cy=\"c8y-data-grid--c8y-cell-renderer\"\n [spec]=\"cellRendererSpec\"\n ></c8y-cell-renderer>\n }\n <i\n c8yIcon=\"filter\"\n title=\"{{ 'Filter' | translate }}\"\n ></i>\n </button>\n\n <!-- isDropDownPlacedRight to be removed when columns are transformed to observables. -->\n <ul\n class=\"dropdown-menu\"\n *dropdownMenu\n [ngClass]=\"{ 'dropdown-menu-right-grid': isDropDownPlacedRight(column) }\"\n (click)=\"$event.stopPropagation()\"\n >\n <li class=\"data-grid__dropdown\">\n @let filteringFormRendererSpec =\n [\n {\n column: column,\n dropdown: gridHeaderDropdown\n }\n ] | map: getFilteringFormRendererSpec : this;\n\n @if (filteringFormRendererSpec) {\n <c8y-filtering-form-renderer\n class=\"bg-component\"\n [spec]=\"filteringFormRendererSpec\"\n data-cy=\"c8y-data-grid--c8y-filtering-form-renderer\"\n ></c8y-filtering-form-renderer>\n }\n </li>\n </ul>\n </div>\n }\n\n @if (column.sortable) {\n <button\n class=\"btn-sort\"\n [style]=\"{\n 'margin-left': !column.filterable && column.sortable ? '-20px' : null\n }\"\n [title]=\"sortColumnTitle | translate: { name: column.header | translate }\"\n type=\"button\"\n (click)=\"changeSortOrder(column.name)\"\n data-cy=\"change-sort-order\"\n >\n @switch (column.sortOrder) {\n @case ('asc') {\n <i c8yIcon=\"long-arrow-up\"></i>\n }\n @case ('desc') {\n <i c8yIcon=\"long-arrow-down\"></i>\n }\n @default {\n <i c8yIcon=\"exchange\"></i>\n }\n }\n </button>\n }\n\n @if (column.resizable) {\n <span\n class=\"resize-handle\"\n (mousedown)=\"\n resizeHandleMouseDown$.emit({ event: $event, targetColumnName: column.name })\n \"\n ></span>\n }\n </th>\n\n <td\n [class.hidden]=\"!column.visible\"\n [attr.data-cell-title]=\"column.header | translate\"\n cdk-cell\n *cdkCellDef=\"let row\"\n [ngClass]=\"column.cellCSSClassName\"\n [attr.data-cy]=\"'data-grid--' + column.header\"\n [attr.data-type]=\"column.dataType\"\n >\n @let cellRendererSpec =\n [\n {\n value: resolveCellValue(row, column.path),\n row: row,\n columnName: column.name\n }\n ] | map: getCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer [spec]=\"cellRendererSpec\"></c8y-cell-renderer>\n }\n </td>\n }\n }\n </ng-container>\n }\n\n <ng-container cdkColumnDef=\"infiniteScrollFooter\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-footer-cell\n *cdkFooterCellDef\n >\n <template #infiniteScrollContainer></template>\n </td>\n </ng-container>\n\n <tr\n cdk-header-row\n *cdkHeaderRowDef=\"columnNames\"\n ></tr>\n\n <tr\n data-cy=\"c8y-data-grid--row-in-data-grid\"\n cdk-row\n *cdkRowDef=\"let row; columns: columnNames; let idx = dataIndex; when: isDataRow\"\n [ngClass]=\"[\n activeClassName && row === lastClickedRow ? activeClassName : '',\n idx % 2 === 0 ? 'even' : 'odd',\n row.level > 0 ? 'data-grid-child-node level-' + row.level : ''\n ]\"\n (mouseover)=\"rowMouseOver.emit(row)\"\n (mouseleave)=\"rowMouseLeave.emit(row)\"\n (click)=\"handleClick(row)\"\n ></tr>\n\n <tr\n class=\"expanded-row\"\n [ngClass]=\"{ hidden: !(expandedRows.get(row).visible$ | async) }\"\n data-cy=\"c8y-data-grid--expanded-row-in-data-grid\"\n cdk-row\n *cdkRowDef=\"let row; columns: ['expanded-row']; when: isRowExpanded\"\n ></tr>\n\n <ng-container cdkColumnDef=\"expanded-row\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-cell\n *cdkCellDef=\"let row\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n expandableRow?.template;\n context: {\n $implicit: row,\n asyncRenderSuccess: setExpandableRowVisible.bind(this, row, true),\n asyncRenderFail: setExpandableRowVisible.bind(this, row, false)\n }\n \"\n ></ng-container>\n </td>\n </ng-container>\n\n <tr\n [class]=\"'pagination-row level-' + (row.parentRow.level + 1)\"\n cdk-row\n *cdkRowDef=\"let row; columns: ['pagination-row']; when: isPaginationRow\"\n ></tr>\n\n <ng-container cdkColumnDef=\"pagination-row\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-cell\n *cdkCellDef=\"let row\"\n >\n <div class=\"col-sm-4 no-gutter\">\n @if ((dataSource.stats$ | async).currentPageSize > 0) {\n <div\n class=\"counter p-t-8 p-b-8\"\n data-cy=\"data-grid--child-counter\"\n >\n <span\n class=\"text-muted\"\n ngNonBindable\n translate\n [translateParams]=\"{\n pageFirstItemIdx:\n (row.childrenStats.currentPage - 1) * row.childrenStats.firstPageSize + 1,\n pageLastItemIdx:\n (row.childrenStats.currentPage - 1) * row.childrenStats.firstPageSize +\n 1 +\n (row.childrenStats.currentPageSize - 1),\n itemsTotal: row.childrenStats.filteredSize\n }\"\n >\n {{ pageFirstItemIdx }} - {{ pageLastItemIdx }} of {{ itemsTotal }}\n </span>\n <span class=\"text-muted text-12 m-r-4\">{{ 'Parent node' | translate }}</span>\n <span class=\"tag tag--default\">{{ row.parentRow?.[parentNodeLabelProperty] }}</span>\n </div>\n }\n </div>\n <div class=\"col-sm-4 col-sm-offset-4 no-gutter text-right\">\n @if (row.childrenStats.filteredSize > row.childrenStats.currentPageSize) {\n <pagination\n class=\"d-flex j-c-end\"\n [ngModel]=\"row.childrenStats.currentPage\"\n (pageChanged)=\"updateChildPagination($event, row)\"\n [totalItems]=\"row.childrenStats.filteredSize\"\n [itemsPerPage]=\"row?.parentRow?.pagination?.pageSize ?? childNodePagination.pageSize\"\n [maxSize]=\"5\"\n [boundaryLinks]=\"false\"\n [previousText]=\"'Previous' | translate\"\n [nextText]=\"'Next' | translate\"\n ></pagination>\n }\n </div>\n </td>\n </ng-container>\n\n <ng-container>\n <tr\n [ngClass]=\"{ hidden: !infiniteScroll }\"\n cdk-footer-row\n *cdkFooterRowDef=\"['infiniteScrollFooter']\"\n ></tr>\n </ng-container>\n </table>\n\n @if (\n !(dataSource.loading$ | async) &&\n !loading &&\n ((dataSource.stats$ | async).filteredSize === 0 || (dataSource.data$ | async).length === 0)\n ) {\n <div class=\"d-flex m-0 p-t-40 p-b-40\">\n <div class=\"col-lg-3 col-sm-4 m-l-auto m-r-auto\">\n <ng-content select=\"c8y-ui-empty-state, .c8y-empty-state\"></ng-content>\n <ng-container\n *ngTemplateOutlet=\"\n emptyState?.templateRef;\n context: { $implicit: emptyStateContext$ | async }\n \"\n ></ng-container>\n </div>\n </div>\n }\n\n @if (pagination && !infiniteScroll) {\n <div class=\"table-data-grid-footer separator large-padding\">\n <div class=\"col-sm-4 no-gutter\">\n @if ((dataSource.stats$ | async).currentPageSize > 0) {\n <div\n class=\"counter p-t-8 p-b-8\"\n data-cy=\"data-grid--counter\"\n >\n <span\n class=\"text-muted\"\n ngNonBindable\n translate\n [translateParams]=\"paginationLabelParams\"\n >\n {{ pageFirstItemIdx }} - {{ pageLastItemIdx }} of {{ itemsTotal }}\n </span>\n </div>\n }\n </div>\n\n <div class=\"col-sm-4 no-gutter text-center\">\n @if ((dataSource.stats$ | async).filteredSize > minPossiblePageSize) {\n <div class=\"form-group form-inline p-t-8 p-b-8\">\n <label\n class=\"m-r-4\"\n for=\"filteredSize\"\n >\n {{ 'Items per page' | translate }}\n </label>\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n id=\"filteredSize\"\n data-cy=\"data-grid--pagesize-options\"\n [ngModel]=\"pagination.pageSize\"\n (ngModelChange)=\"\n updatePagination({ itemsPerPage: $event, page: pagination.currentPage })\n \"\n >\n @for (pageSize of possiblePageSizes; track $index) {\n <option [ngValue]=\"pageSize\">\n {{ pageSize }}\n </option>\n }\n </select>\n </div>\n </div>\n }\n </div>\n\n <div class=\"col-sm-4 no-gutter text-right\">\n @if ((dataSource.stats$ | async).filteredSize > 0) {\n <pagination\n [class.hidden]=\"hidePagination$ | async\"\n class=\"d-flex j-c-end\"\n [ngModel]=\"pagination.currentPage\"\n (pageChanged)=\"updatePagination($event)\"\n [totalItems]=\"(dataSource.stats$ | async).filteredSize\"\n [itemsPerPage]=\"pagination.pageSize\"\n (numPages)=\"totalPagesCount$.next($event)\"\n [maxSize]=\"5\"\n [boundaryLinks]=\"false\"\n [previousText]=\"'Previous' | translate\"\n [nextText]=\"'Next' | translate\"\n ></pagination>\n }\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "progressLabel", "message"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: DropdownFocusTrapDirective, selector: "[c8yDropdownFocusTrap]" }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i1$8.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: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$7.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$7.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: i1$7.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$7.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$4.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: "directive", type: NgPlural, selector: "[ngPlural]", inputs: ["ngPlural"] }, { kind: "directive", type: NgPluralCase, selector: "[ngPluralCase]" }, { kind: "component", type: CdkTable, selector: "cdk-table, table[cdk-table]", inputs: ["trackBy", "dataSource", "multiTemplateDataRows", "fixedLayout", "recycleRows"], outputs: ["contentChanged"], exportAs: ["cdkTable"] }, { kind: "directive", type: CdkColumnDef, selector: "[cdkColumnDef]", inputs: ["cdkColumnDef", "sticky", "stickyEnd"] }, { kind: "directive", type: CdkHeaderCellDef, selector: "[cdkHeaderCellDef]" }, { kind: "directive", type: CdkHeaderCell, selector: "cdk-header-cell, th[cdk-header-cell]" }, { kind: "directive", type: CdkCellDef, selector: "[cdkCellDef]" }, { kind: "directive", type: CdkCell, selector: "cdk-cell, td[cdk-cell]" }, { kind: "component", type: CellRendererComponent, selector: "c8y-cell-renderer", inputs: ["spec"] }, { kind: "component", type: FilteringFormRendererComponent, selector: "c8y-filtering-form-renderer", inputs: ["spec"] }, { kind: "directive", type: CdkFooterCellDef, selector: "[cdkFooterCellDef]" }, { kind: "directive", type: CdkFooterCell, selector: "cdk-footer-cell, td[cdk-footer-cell]" }, { kind: "directive", type: CdkHeaderRowDef, selector: "[cdkHeaderRowDef]", inputs: ["cdkHeaderRowDef", "cdkHeaderRowDefSticky"] }, { kind: "component", type: CdkHeaderRow, selector: "cdk-header-row, tr[cdk-header-row]" }, { kind: "directive", type: CdkRowDef, selector: "[cdkRowDef]", inputs: ["cdkRowDefColumns", "cdkRowDefWhen"] }, { kind: "component", type: CdkRow, selector: "cdk-row, tr[cdk-row]" }, { kind: "directive", type: CdkFooterRowDef, selector: "[cdkFooterRowDef]", inputs: ["cdkFooterRowDef", "cdkFooterRowDefSticky"] }, { kind: "component", type: CdkFooterRow, selector: "cdk-footer-row, tr[cdk-footer-row]" }, { kind: "ngmodule", type: PaginationModule }, { kind: "component", type: i11.PaginationComponent, selector: "pagination", inputs: ["align", "maxSize", "boundaryLinks", "directionLinks", "firstText", "previousText", "nextText", "lastText", "rotate", "pageBtnClass", "disabled", "customPageTemplate", "customNextTemplate", "customPreviousTemplate", "customFirstTemplate", "customLastTemplate", "itemsPerPage", "totalItems"], outputs: ["numPages", "pageChanged"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: SlicePipe, name: "slice" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: MapFunctionPipe, name: "map" }, { kind: "pipe", type: FilterMapperPipe, name: "mapToFilterChips" }, { kind: "pipe", type: GroupedFilterChips, name: "groupedFilterChips" }, { kind: "pipe", type: VisibleControlsPipe, name: "visibleControls" }, { kind: "pipe", type: HumanizePipe, name: "humanize" }] }); }
36466
+ ], queries: [{ propertyName: "expandableRow", first: true, predicate: ExpandableRowDirective, descendants: true }, { propertyName: "emptyState", first: true, predicate: EmptyStateContextDirective, descendants: true }, { propertyName: "columnRenderers", predicate: ColumnDirective }], viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scroll"], descendants: true, static: true }, { propertyName: "infiniteScrollContainer", first: true, predicate: ["infiniteScrollContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "tableRef", first: true, predicate: CdkTable, descendants: true }, { propertyName: "thRefs", predicate: CdkHeaderCell, descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "@let loadingData = ((dataSource.loading$ | async) && !loadMoreComponent?.isLoading) || loading;\n\n<div\n class=\"table-data-grid-scroll\"\n #scroll\n [ngClass]=\"{\n 'table-data-grid__overlay': loadingData\n }\"\n data-cy=\"c8y-data-grid--table-data-grid-scroll\"\n>\n @if (loadingData && displayOptions.showLoadingIndicator) {\n <div class=\"table-data-grid__loading--wrapper\">\n <div class=\"table-data-grid__loading--loader\">\n <c8y-loading\n layout=\"application\"\n [message]=\"loadingItemsLabel\"\n ></c8y-loading>\n </div>\n </div>\n }\n\n @if (displayOptions.gridHeader) {\n <div class=\"table-data-grid-header separator large-padding\">\n <div\n class=\"h4\"\n [ngClass]=\"{ 'm-r-16': !!title }\"\n >\n {{ title | translate }}\n </div>\n\n @if (displayOptions.filter) {\n @if (!filteringApplied) {\n <span>\n @if (!!filteringLabelsParams.allItemsCount) {\n <small\n class=\"m-r-4\"\n ngNonBindable\n translate\n [translateParams]=\"filteringLabelsParams\"\n >\n {{ filteredItemsCount }} of {{ allItemsCount }} items\n </small>\n }\n <span\n class=\"label label-default m-r-4\"\n translate\n >\n No filters\n </span>\n </span>\n }\n @if (filteringApplied) {\n <span class=\"d-flex a-i-center\">\n @if (!!filteringLabelsParams.allItemsCount) {\n <div class=\"a-i-center\">\n <span class=\"badge badge-info m-r-4\">\n {{ (dataSource.stats$ | async).filteredSize }}\n </span>\n <small\n ngNonBindable\n translate\n [translateParams]=\"filteringLabelsParams\"\n >\n of {{ allItemsCount }} items\n </small>\n </div>\n }\n <div\n class=\"dropdown\"\n placement=\"bottom left\"\n container=\"body\"\n dropdown\n #ddFilters=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btn btn-default btn-sm m-l-8\"\n title=\"{{ 'Active filters' | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n data-cy=\"c8y-data-grid--filters\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"filter\"\n ></i>\n <span>{{ 'Active filters' | translate }}</span>\n <span\n class=\"badge badge-system\"\n data-cy=\"c8y-data-grid--filters-count\"\n >\n {{ columnsWithFiltersApplied.length }}\n </span>\n </button>\n\n <div\n class=\"dropdown-menu\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"data-grid__dropdown bg-level-0\">\n <ul class=\"list-unstyled m-0\">\n @for (column of columnsWithFiltersApplied; track $index; let last = $last) {\n <li [ngClass]=\"{ 'separator-bottom': !last }\">\n <ng-container>\n <div\n class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n title=\"{{ (column.header | translate) || column.name }}\"\n >\n <label>\n {{ (column.header | translate) || column.name }}\n </label>\n </div>\n @for (\n groupedFilterChips of column\n | mapToFilterChips\n | async\n | groupedFilterChips;\n track $index;\n let first = $first\n ) {\n <div\n class=\"list-group-item borderless d-flex d-col\"\n [ngClass]=\"{ 'p-t-0': first }\"\n >\n @if (groupedFilterChips.label) {\n <p class=\"small p-b-4\">\n {{ groupedFilterChips.label | translate }}\n </p>\n }\n <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n @for (chip of groupedFilterChips.chips; track $index) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ 'Remove filter' | translate }}\"\n (click)=\"removeFilter(chip.remove())\"\n data-cy=\"c8y-data-grid--remove-chip\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ chip.displayValue | translate }}\n </span>\n }\n </div>\n </div>\n }\n </ng-container>\n </li>\n }\n </ul>\n </div>\n <div class=\"list-group-item separator-top sticky-bottom\">\n <button\n class=\"btn btn-sm btn-default\"\n title=\"{{ 'Clear all filters' | translate }}\"\n type=\"button\"\n (click)=\"clearFilters()\"\n data-cy=\"c8y-data-grid--clear-filters\"\n >\n {{ 'Clear all filters' | translate }}\n </button>\n </div>\n </div>\n </div>\n </span>\n }\n\n @if (displayOptions.filter) {\n <button\n class=\"btn-help btn-help--sm hidden-xs hidden-sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"filtersHelpPopover\"\n placement=\"right\"\n triggers=\"focus\"\n type=\"button\"\n data-cy=\"data-grid--help-filters\"\n >\n <i c8yIcon=\"question-circle-o\"></i>\n </button>\n }\n <ng-template #filtersHelpPopover>\n <div [innerHtml]=\"filtersHelpPopoverHtml | translate\"></div>\n </ng-template>\n\n @if (showCounterWarning) {\n <button\n class=\"btn-clean text-primary hidden-xs hidden-sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The counter for the total number of items might be inaccurate.' | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n type=\"button\"\n >\n <i c8yIcon=\"warning\"></i>\n </button>\n }\n }\n\n <div class=\"m-l-auto\">\n <div class=\"btnbar d-flex a-i-center\">\n @for (\n headerActionControl of headerActionControls | visibleControls | async;\n track $index\n ) {\n <ng-container>\n @if (!headerActionControl.template) {\n <button\n class=\"btnbar-btn btn-link\"\n title=\"{{ headerActionControl.text | translate }}\"\n type=\"button\"\n (click)=\"headerActionControl.callback()\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION,\n customActionName: headerActionControl.text,\n type: headerActionControl.type\n }\"\n >\n <i\n class=\"m-r-4\"\n [c8yIcon]=\"headerActionControl.icon\"\n ></i>\n <span>{{ headerActionControl.text | translate }}</span>\n </button>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"\n headerActionControl.template;\n context: { headerActionControl: headerActionControl }\n \"\n ></ng-container>\n }\n </ng-container>\n }\n\n @if (configureColumnsEnabled) {\n <div\n class=\"dropdown\"\n placement=\"bottom left\"\n container=\"body\"\n dropdown\n #ddConfigureColumns=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Configure columns' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--custom-column-btn\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"columns\"\n ></i>\n <span>{{ 'Configure columns' | translate }}</span>\n </button>\n\n <ul\n class=\"dropdown-menu data-grid__dropdown\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <li>\n <div\n class=\"list-group m-0\"\n cdkDropList\n (cdkDropListDropped)=\"onColumnDrop($event)\"\n >\n @for (column of columns; track $index) {\n <div\n cdkDrag\n cdkDragLockAxis=\"y\"\n >\n @if (!column.positionFixed) {\n <div class=\"list-group-item draggable-after p-l-16 p-r-16 a-i-center\">\n <label\n class=\"c8y-checkbox min-width-0\"\n title=\"{{ column.custom ? ('Custom' | translate) + ' ' : '' }}{{\n (column.header | translate) || column.name\n }}\"\n [attr.data-cy]=\"'data-grid--custom-column-header-' + column.header\"\n >\n <input\n type=\"checkbox\"\n [(ngModel)]=\"column.visible\"\n (change)=\"\n updateGridColumnsSize();\n emitConfigChange('changeColumnVisibility')\n \"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CHANGE_VISIBILITY,\n column: column.name,\n visible: !column.visible\n }\"\n />\n <span></span>\n <div class=\"d-col min-width-0 m-l-8 m-r-8\">\n @if (column?.custom) {\n <span class=\"text-muted text-10 m-b-0\">\n {{ 'Custom' | translate }}\n </span>\n }\n <span class=\"text-truncate l-h-1 m-t-2\">\n {{ (column.header | translate) || column.name }}\n </span>\n </div>\n @let canRetrieve = canRetrieveAssetProperties | async;\n @if (canRetrieve) {\n @if (canRetrieve && column?.type) {\n <span\n class=\"tag tag--default a-s-end\"\n title=\"{{ column.type | translate | humanize }}\"\n >\n {{ column.type | translate | humanize }}\n </span>\n }\n }\n </label>\n @if (column.custom) {\n <button\n class=\"btn btn-dot btn-dot--danger showOnHover max-width-fit a-i-center\"\n [attr.aria-label]=\"'Remove`column,verb`' | translate\"\n [popover]=\"confirmRemovePopover\"\n type=\"button\"\n #pop=\"bs-popover\"\n (click)=\"\n currentRemoveCustomColumnPopover !== pop &&\n currentRemoveCustomColumnPopover?.hide();\n currentRemoveCustomColumnPopover = pop\n \"\n >\n <i\n c8yIcon=\"minus-circle\"\n data-cy=\"data-grid--custom-column-remove-btn\"\n ></i>\n </button>\n\n <ng-template #confirmRemovePopover>\n <h3 class=\"popover-title popover-header\">\n {{ 'Confirm removal' | translate }}\n </h3>\n <div class=\"popover-content popover-body\">\n <p>{{ 'Do you want to remove this column?' | translate }}</p>\n <div class=\"popover-footer gap-16\">\n <button\n class=\"btn btn-default btn-sm\"\n type=\"button\"\n (click)=\"pop.hide()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-danger btn-sm\"\n type=\"button\"\n (click)=\"confirmRemoveColumn(column); pop.hide()\"\n data-cy=\"popover-confirm--Remove\"\n >\n {{ 'Remove' | translate }}\n </button>\n </div>\n </div>\n </ng-template>\n }\n </div>\n }\n </div>\n }\n </div>\n </li>\n @if (isConfigContextKnown) {\n <li class=\"p-8 sticky-bottom separator-top\">\n <button\n class=\"btn btn-default btn-block\"\n title=\"{{ 'Add custom column' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--add-custom-column\"\n (click)=\"openCustomColumn(); ddConfigureColumns.hide()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"plus-circle\"\n ></i>\n <span>{{ 'Add custom column' | translate }}</span>\n </button>\n </li>\n }\n </ul>\n </div>\n }\n\n @if (!hideReload) {\n <button\n class=\"btnbar-btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--reload-btn\"\n [disabled]=\"dataSource.loading$ | async\"\n (click)=\"clickReload()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"refresh\"\n ></i>\n <span>{{ 'Reload' | translate }}</span>\n </button>\n }\n\n @if (!serverSideDataCallback || showSearch) {\n <div class=\"input-group input-group-search m-l-sm-16 data-grid__search-input\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Search\u2026' | translate }}\"\n type=\"search\"\n [(ngModel)]=\"searchText\"\n (ngModelChange)=\"searchText$.emit($event)\"\n (keydown.enter)=\"$event.stopPropagation(); performSearch(searchText)\"\n />\n <div class=\"input-group-addon\">\n @if (searchText.length === 0) {\n <i c8yIcon=\"search\"></i>\n }\n @if (searchText.length > 0) {\n <i\n class=\"pointer\"\n c8yIcon=\"times\"\n (click)=\"searchText = ''; searchText$.emit('')\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.CLEAR_SEARCH }\"\n ></i>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if (selectedItemIds.length !== 0) {\n <div\n class=\"table-data-grid-header-bulk-actions animated slideInDown fast\"\n data-cy=\"table-data-grid-header-bulk-actions\"\n >\n <h4>\n <ng-container [ngPlural]=\"selectedItemIds.length\">\n <ng-template ngPluralCase=\"=1\">\n <span translate>1 selected item.</span>\n </ng-template>\n <ng-template ngPluralCase=\"other\">\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ count: selectedItemIds.length }\"\n >\n {{ count }} selected items.\n </span>\n </ng-template>\n </ng-container>\n <br class=\"visible-xs\" />\n @if (!serverSideDataCallback && selectedItemIds.length >= pagination.pageSize) {\n <small>\n <a\n class=\"interact\"\n (click)=\"setAllItemsSelected(true)\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.SELECT_ALL_ITEMS }\"\n >\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ count: (dataSource.stats$ | async).filteredSize }\"\n >\n Select all {{ count }} items\n </span>\n </a>\n </small>\n }\n </h4>\n <div class=\"m-l-auto\">\n <div class=\"btnbar d-flex\">\n @for (\n bulkActionControl of bulkActionControls | visibleControls: selectedItemIds | async;\n track $index\n ) {\n <ng-container>\n @switch (bulkActionControl.type) {\n @case (builtInActionType.Export) {\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Export' | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{ action: PX_ACTIONS.BULK_EXPORT }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"sign-out\"></i>\n <span>{{ 'Export' | translate }}</span>\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Delete' | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{ action: PX_ACTIONS.BULK_DELETE }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"delete\"></i>\n <span>{{ 'Delete' | translate }}</span>\n </button>\n }\n @default {\n <button\n class=\"btnbar-btn\"\n title=\"{{ bulkActionControl.text | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.BULK_CUSTOM_ACTION,\n customActionName: bulkActionControl.text\n }\"\n c8yProductExperience\n inherit\n >\n <i\n [class]=\"bulkActionControl.iconClasses\"\n c8yIcon=\"{{ bulkActionControl.icon }}\"\n ></i>\n <span>{{ bulkActionControl.text | translate }}</span>\n </button>\n }\n }\n </ng-container>\n }\n\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n [actionData]=\"{\n action: PX_ACTIONS.BULK_CANCEL\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"times\"></i>\n <span>{{ 'Cancel' | translate }}</span>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <table\n class=\"table table-filtered-sorted table-data-grid large-padding\"\n [class.table-striped]=\"displayOptions.striped && !treeGrid\"\n [class.table-bordered]=\"displayOptions.bordered\"\n [class.table-hover]=\"displayOptions.hover\"\n [class.table-data-grid-with-checkboxes]=\"selectable\"\n [class.table-data-grid-with-actions]=\"actionControls.length > 0\"\n [style.grid-template-columns]=\"styles.gridTemplateColumns\"\n cdk-table\n [dataSource]=\"dataSource\"\n [multiTemplateDataRows]=\"true\"\n (mousemove)=\"resizeHandleContainerMouseMove$.emit($event)\"\n data-cy=\"c8y-data-grid--table\"\n >\n @for (column of columns; track column.name; let i = $index) {\n <ng-container [cdkColumnDef]=\"column.name\">\n @switch (column.name) {\n @case ('checkbox') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n >\n <div>\n <label class=\"c8y-checkbox\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n type=\"checkbox\"\n [checked]=\"currentPageSelectionState.allSelected\"\n [indeterminate]=\"\n !(\n currentPageSelectionState.allSelected ||\n currentPageSelectionState.allDeselected\n )\n \"\n (change)=\"setAllItemsInCurrentPageSelected($event.target.checked)\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.SELECT_ALL_ITEMS }\"\n />\n <span></span>\n </label>\n </div>\n </th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n <label class=\"c8y-checkbox\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n type=\"checkbox\"\n [checked]=\"isItemSelected(row)\"\n (change)=\"setItemsSelected([row], $event.target.checked)\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.SELECT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--checkbox\"\n />\n <span></span>\n </label>\n </td>\n }\n\n @case ('radio-button') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n ></th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n <label class=\"c8y-radio\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n name=\"select-row\"\n type=\"radio\"\n [checked]=\"isItemSelected(row)\"\n (change)=\"changeSelectedItem(row)\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.SELECT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--radio\"\n />\n <span></span>\n </label>\n </td>\n }\n\n @case ('actions') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n >\n <p class=\"text-medium sr-only\">{{ 'Actions' | translate }}</p>\n </th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n @for (\n actionControl of actionControls\n | visibleControls: row\n | async\n | slice\n : 0\n : ((actionControls | visibleControls: row | async)?.length > 2 ? 1 : 2);\n track $index\n ) {\n <ng-container>\n @switch (actionControl.type) {\n @case (builtInActionType.Edit) {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"'Edit' | translate\"\n tooltip=\"{{ 'Edit' | translate }}\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.EDIT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--edit-button-in-row\"\n >\n <i c8yIcon=\"pencil\"></i>\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n class=\"btn btn-dot btn-dot--danger showOnHover\"\n [attr.aria-label]=\"'Delete' | translate\"\n tooltip=\"{{ 'Delete' | translate }}\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.DELETE_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n data-cy=\"c8y-data-grid--remove-button-in-row\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n }\n @default {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n (actionControl.icon ? actionControl.text : '') | translate\n \"\n tooltip=\"{{ (actionControl.icon ? actionControl.text : '') | translate }}\"\n container=\"body\"\n type=\"button\"\n [ngClass]=\"{ showOnHover: actionControl.showOnHover }\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION_ITEM,\n customActionName: actionControl.text,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n [attr.data-cy]=\"'c8y-data-grid--button-in-row--' + actionControl.text\"\n >\n @if (actionControl.icon) {\n <i\n c8yIcon=\"{{ actionControl.icon }}\"\n [ngClass]=\"actionControl.iconClasses\"\n ></i>\n } @else {\n <span>{{ actionControl.text | translate }}</span>\n }\n </button>\n }\n }\n </ng-container>\n }\n\n <div\n [ngClass]=\"{\n 'm-l-auto overflow-visible':\n (actionControls | visibleControls: row | async)?.length > 2\n }\"\n >\n @if ((actionControls | visibleControls: row | async)?.length > 2) {\n <div\n class=\"dropdown\"\n placement=\"bottom right\"\n container=\"body\"\n dropdown\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n title=\"{{ 'Actions' | translate }}\"\n aria-haspopup=\"true\"\n type=\"button\"\n data-cy=\"c8y-data-grid--row-actions-dropdown\"\n dropdownToggle\n >\n <i c8yIcon=\"ellipsis-v\"></i>\n </button>\n <ul\n class=\"dropdown-menu dropdown-menu-right\"\n *dropdownMenu\n >\n @for (\n actionControl of actionControls\n | visibleControls: row\n | async\n | slice\n : ((actionControls | visibleControls: row | async)?.length > 2 ? 1 : 2);\n track $index\n ) {\n <li>\n @switch (actionControl.type) {\n @case (builtInActionType.Edit) {\n <button\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.EDIT_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n title=\"{{ 'Delete' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.DELETE_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"delete\"></i>\n {{ 'Delete' | translate }}\n </button>\n }\n @case (builtInActionType.Export) {\n <button\n title=\"{{ 'Export' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.EXPORT_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"data-export\"></i>\n {{ 'Export' | translate }}\n </button>\n }\n @default {\n <button\n title=\"{{ actionControl.text | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION_ITEM,\n customActionName: actionControl.text,\n id: row.id\n }\"\n >\n <i\n c8yIcon=\"{{ actionControl.icon }}\"\n [ngClass]=\"actionControl.iconClasses\"\n ></i>\n {{ actionControl.text | translate }}\n </button>\n }\n }\n </li>\n }\n </ul>\n </div>\n }\n </div>\n </td>\n }\n @default {\n <th\n [class.sorted]=\"column.sortOrder\"\n [class.filtered]=\"column | map: isColumnFilteringApplied\"\n [class.hidden]=\"!column.visible\"\n cdk-header-cell\n *cdkHeaderCellDef\n [ngClass]=\"column.headerCSSClassName\"\n [attr.data-type]=\"column.dataType\"\n >\n @if (!column.filterable) {\n <div [title]=\"(column.header | translate) || column.name\">\n @let cellRendererSpec =\n [\n {\n columnName: column.name,\n value: (column.header | translate) || column.name\n }\n ] | map: getHeaderCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer [spec]=\"cellRendererSpec\"></c8y-cell-renderer>\n }\n </div>\n }\n\n <!-- isDropDownPlacedRight to be removed when columns are transformed to observables. -->\n @if (column.filterable) {\n <div\n class=\"dropdown\"\n placement=\"bottom {{ isDropDownPlacedRight(column) ? 'right' : 'left' }}\"\n container=\"body\"\n dropdown\n c8yDropdownFocusTrap\n #gridHeaderDropdown=\"bs-dropdown\"\n [insideClick]=\"true\"\n >\n <button\n class=\"btn-header\"\n [title]=\"(column.header | translate) || column.name\"\n type=\"button\"\n [attr.data-cy]=\"'data-grid--header-btn--' + column.header\"\n dropdownToggle\n >\n @let cellRendererSpec =\n [\n {\n columnName: column.name,\n value: (column.header | translate) || column.name\n }\n ] | map: getHeaderCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer\n data-cy=\"c8y-data-grid--c8y-cell-renderer\"\n [spec]=\"cellRendererSpec\"\n ></c8y-cell-renderer>\n }\n <i\n c8yIcon=\"filter\"\n title=\"{{ 'Filter' | translate }}\"\n ></i>\n </button>\n\n <!-- isDropDownPlacedRight to be removed when columns are transformed to observables. -->\n <ul\n class=\"dropdown-menu\"\n *dropdownMenu\n [ngClass]=\"{ 'dropdown-menu-right-grid': isDropDownPlacedRight(column) }\"\n (click)=\"$event.stopPropagation()\"\n >\n <li class=\"data-grid__dropdown\">\n @let filteringFormRendererSpec =\n [\n {\n column: column,\n dropdown: gridHeaderDropdown\n }\n ] | map: getFilteringFormRendererSpec : this;\n\n @if (filteringFormRendererSpec) {\n <c8y-filtering-form-renderer\n class=\"bg-component\"\n [spec]=\"filteringFormRendererSpec\"\n data-cy=\"c8y-data-grid--c8y-filtering-form-renderer\"\n ></c8y-filtering-form-renderer>\n }\n </li>\n </ul>\n </div>\n }\n\n @if (column.sortable) {\n <button\n class=\"btn-sort\"\n [style]=\"{\n 'margin-left': !column.filterable && column.sortable ? '-20px' : null\n }\"\n [title]=\"sortColumnTitle | translate: { name: column.header | translate }\"\n type=\"button\"\n (click)=\"changeSortOrder(column.name)\"\n data-cy=\"change-sort-order\"\n >\n @switch (column.sortOrder) {\n @case ('asc') {\n <i c8yIcon=\"long-arrow-up\"></i>\n }\n @case ('desc') {\n <i c8yIcon=\"long-arrow-down\"></i>\n }\n @default {\n <i c8yIcon=\"exchange\"></i>\n }\n }\n </button>\n }\n\n @if (column.resizable) {\n <span\n class=\"resize-handle\"\n (mousedown)=\"\n resizeHandleMouseDown$.emit({ event: $event, targetColumnName: column.name })\n \"\n ></span>\n }\n </th>\n\n <td\n [class.hidden]=\"!column.visible\"\n [attr.data-cell-title]=\"column.header | translate\"\n cdk-cell\n *cdkCellDef=\"let row\"\n [ngClass]=\"column.cellCSSClassName\"\n [attr.data-cy]=\"'data-grid--' + column.header\"\n [attr.data-type]=\"column.dataType\"\n >\n @let cellRendererSpec =\n [\n {\n value: resolveCellValue(row, column.path),\n row: row,\n columnName: column.name\n }\n ] | map: getCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer [spec]=\"cellRendererSpec\"></c8y-cell-renderer>\n }\n </td>\n }\n }\n </ng-container>\n }\n\n <ng-container cdkColumnDef=\"infiniteScrollFooter\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-footer-cell\n *cdkFooterCellDef\n >\n <template #infiniteScrollContainer></template>\n </td>\n </ng-container>\n\n <tr\n cdk-header-row\n *cdkHeaderRowDef=\"columnNames\"\n ></tr>\n\n <tr\n data-cy=\"c8y-data-grid--row-in-data-grid\"\n cdk-row\n *cdkRowDef=\"let row; columns: columnNames; let idx = dataIndex; when: isDataRow\"\n [ngClass]=\"[\n activeClassName && row === lastClickedRow ? activeClassName : '',\n idx % 2 === 0 ? 'even' : 'odd',\n row.level > 0 ? 'data-grid-child-node level-' + row.level : ''\n ]\"\n (mouseover)=\"rowMouseOver.emit(row)\"\n (mouseleave)=\"rowMouseLeave.emit(row)\"\n (click)=\"handleClick(row)\"\n ></tr>\n\n <tr\n class=\"expanded-row\"\n [ngClass]=\"{ hidden: !(expandedRows.get(row).visible$ | async) }\"\n data-cy=\"c8y-data-grid--expanded-row-in-data-grid\"\n cdk-row\n *cdkRowDef=\"let row; columns: ['expanded-row']; when: isRowExpanded\"\n ></tr>\n\n <ng-container cdkColumnDef=\"expanded-row\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-cell\n *cdkCellDef=\"let row\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n expandableRow?.template;\n context: {\n $implicit: row,\n asyncRenderSuccess: setExpandableRowVisible.bind(this, row, true),\n asyncRenderFail: setExpandableRowVisible.bind(this, row, false)\n }\n \"\n ></ng-container>\n </td>\n </ng-container>\n\n <tr\n [class]=\"'pagination-row level-' + (row.parentRow.level + 1)\"\n cdk-row\n *cdkRowDef=\"let row; columns: ['pagination-row']; when: isPaginationRow\"\n ></tr>\n\n <ng-container cdkColumnDef=\"pagination-row\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-cell\n *cdkCellDef=\"let row\"\n >\n <div class=\"col-sm-4 no-gutter\">\n @if ((dataSource.stats$ | async).currentPageSize > 0) {\n <div\n class=\"counter p-t-8 p-b-8\"\n data-cy=\"data-grid--child-counter\"\n >\n <span\n class=\"text-muted\"\n ngNonBindable\n translate\n [translateParams]=\"{\n pageFirstItemIdx:\n (row.childrenStats.currentPage - 1) * row.childrenStats.firstPageSize + 1,\n pageLastItemIdx:\n (row.childrenStats.currentPage - 1) * row.childrenStats.firstPageSize +\n 1 +\n (row.childrenStats.currentPageSize - 1),\n itemsTotal: row.childrenStats.filteredSize\n }\"\n >\n {{ pageFirstItemIdx }} - {{ pageLastItemIdx }} of {{ itemsTotal }}\n </span>\n <span class=\"text-muted text-12 m-r-4\">{{ 'Parent node' | translate }}</span>\n <span class=\"tag tag--default\">{{ row.parentRow?.[parentNodeLabelProperty] }}</span>\n </div>\n }\n </div>\n <div class=\"col-sm-4 col-sm-offset-4 no-gutter text-right\">\n @if (row.childrenStats.filteredSize > row.childrenStats.currentPageSize) {\n <pagination\n class=\"d-flex j-c-end\"\n [ngModel]=\"row.childrenStats.currentPage\"\n (pageChanged)=\"updateChildPagination($event, row)\"\n [totalItems]=\"row.childrenStats.filteredSize\"\n [itemsPerPage]=\"row?.parentRow?.pagination?.pageSize ?? childNodePagination.pageSize\"\n [maxSize]=\"5\"\n [boundaryLinks]=\"false\"\n [previousText]=\"'Previous' | translate\"\n [nextText]=\"'Next' | translate\"\n ></pagination>\n }\n </div>\n </td>\n </ng-container>\n\n <ng-container>\n <tr\n [ngClass]=\"{ hidden: !infiniteScroll }\"\n cdk-footer-row\n *cdkFooterRowDef=\"['infiniteScrollFooter']\"\n ></tr>\n </ng-container>\n </table>\n\n @if (\n !(dataSource.loading$ | async) &&\n !loading &&\n ((dataSource.stats$ | async).filteredSize === 0 || (dataSource.data$ | async).length === 0)\n ) {\n <div class=\"d-flex m-0 p-t-40 p-b-40\">\n <div class=\"col-lg-3 col-sm-4 m-l-auto m-r-auto\">\n <ng-content select=\"c8y-ui-empty-state, .c8y-empty-state\"></ng-content>\n <ng-container\n *ngTemplateOutlet=\"\n emptyState?.templateRef;\n context: { $implicit: emptyStateContext$ | async }\n \"\n ></ng-container>\n </div>\n </div>\n }\n\n @if (pagination && !infiniteScroll) {\n <div class=\"table-data-grid-footer separator large-padding\">\n <div class=\"col-sm-4 no-gutter\">\n @if ((dataSource.stats$ | async).currentPageSize > 0) {\n <div\n class=\"counter p-t-8 p-b-8\"\n data-cy=\"data-grid--counter\"\n >\n <span\n class=\"text-muted\"\n ngNonBindable\n translate\n [translateParams]=\"paginationLabelParams\"\n >\n {{ pageFirstItemIdx }} - {{ pageLastItemIdx }} of {{ itemsTotal }}\n </span>\n </div>\n }\n </div>\n\n <div class=\"col-sm-4 no-gutter text-center\">\n @if ((dataSource.stats$ | async).filteredSize > minPossiblePageSize) {\n <div class=\"form-group form-inline p-t-8 p-b-8\">\n <label\n class=\"m-r-4\"\n for=\"filteredSize\"\n >\n {{ 'Items per page' | translate }}\n </label>\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n id=\"filteredSize\"\n data-cy=\"data-grid--pagesize-options\"\n [ngModel]=\"pagination.pageSize\"\n (ngModelChange)=\"\n updatePagination({ itemsPerPage: $event, page: pagination.currentPage })\n \"\n >\n @for (pageSize of possiblePageSizes; track $index) {\n <option [ngValue]=\"pageSize\">\n {{ pageSize }}\n </option>\n }\n </select>\n </div>\n </div>\n }\n </div>\n\n <div class=\"col-sm-4 no-gutter text-right\">\n @if ((dataSource.stats$ | async).filteredSize > 0) {\n <pagination\n [class.hidden]=\"hidePagination$ | async\"\n class=\"d-flex j-c-end\"\n [ngModel]=\"pagination.currentPage\"\n (pageChanged)=\"updatePagination($event)\"\n [totalItems]=\"(dataSource.stats$ | async).filteredSize\"\n [itemsPerPage]=\"pagination.pageSize\"\n (numPages)=\"totalPagesCount$.next($event)\"\n [maxSize]=\"5\"\n [boundaryLinks]=\"false\"\n [previousText]=\"'Previous' | translate\"\n [nextText]=\"'Next' | translate\"\n ></pagination>\n }\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "progressLabel", "message"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: DropdownFocusTrapDirective, selector: "[c8yDropdownFocusTrap]" }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i1$8.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: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$7.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$7.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: i1$7.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$7.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$4.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: "directive", type: NgPlural, selector: "[ngPlural]", inputs: ["ngPlural"] }, { kind: "directive", type: NgPluralCase, selector: "[ngPluralCase]" }, { kind: "component", type: CdkTable, selector: "cdk-table, table[cdk-table]", inputs: ["trackBy", "dataSource", "multiTemplateDataRows", "fixedLayout", "recycleRows"], outputs: ["contentChanged"], exportAs: ["cdkTable"] }, { kind: "directive", type: CdkColumnDef, selector: "[cdkColumnDef]", inputs: ["cdkColumnDef", "sticky", "stickyEnd"] }, { kind: "directive", type: CdkHeaderCellDef, selector: "[cdkHeaderCellDef]" }, { kind: "directive", type: CdkHeaderCell, selector: "cdk-header-cell, th[cdk-header-cell]" }, { kind: "directive", type: CdkCellDef, selector: "[cdkCellDef]" }, { kind: "directive", type: CdkCell, selector: "cdk-cell, td[cdk-cell]" }, { kind: "component", type: CellRendererComponent, selector: "c8y-cell-renderer", inputs: ["spec"] }, { kind: "component", type: FilteringFormRendererComponent, selector: "c8y-filtering-form-renderer", inputs: ["spec"] }, { kind: "directive", type: CdkFooterCellDef, selector: "[cdkFooterCellDef]" }, { kind: "directive", type: CdkFooterCell, selector: "cdk-footer-cell, td[cdk-footer-cell]" }, { kind: "directive", type: CdkHeaderRowDef, selector: "[cdkHeaderRowDef]", inputs: ["cdkHeaderRowDef", "cdkHeaderRowDefSticky"] }, { kind: "component", type: CdkHeaderRow, selector: "cdk-header-row, tr[cdk-header-row]" }, { kind: "directive", type: CdkRowDef, selector: "[cdkRowDef]", inputs: ["cdkRowDefColumns", "cdkRowDefWhen"] }, { kind: "component", type: CdkRow, selector: "cdk-row, tr[cdk-row]" }, { kind: "directive", type: CdkFooterRowDef, selector: "[cdkFooterRowDef]", inputs: ["cdkFooterRowDef", "cdkFooterRowDefSticky"] }, { kind: "component", type: CdkFooterRow, selector: "cdk-footer-row, tr[cdk-footer-row]" }, { kind: "ngmodule", type: PaginationModule }, { kind: "component", type: i11.PaginationComponent, selector: "pagination", inputs: ["align", "maxSize", "boundaryLinks", "directionLinks", "firstText", "previousText", "nextText", "lastText", "rotate", "pageBtnClass", "disabled", "customPageTemplate", "customNextTemplate", "customPreviousTemplate", "customFirstTemplate", "customLastTemplate", "itemsPerPage", "totalItems"], outputs: ["numPages", "pageChanged"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: SlicePipe, name: "slice" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: MapFunctionPipe, name: "map" }, { kind: "pipe", type: FilterMapperPipe, name: "mapToFilterChips" }, { kind: "pipe", type: GroupedFilterChips, name: "groupedFilterChips" }, { kind: "pipe", type: VisibleControlsPipe, name: "visibleControls" }, { kind: "pipe", type: HumanizePipe, name: "humanize" }] }); }
36396
36467
  }
36397
36468
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: DataGridComponent, decorators: [{
36398
36469
  type: Component,
@@ -36442,7 +36513,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
36442
36513
  GroupedFilterChips,
36443
36514
  VisibleControlsPipe,
36444
36515
  HumanizePipe
36445
- ], template: "@let loadingData = ((dataSource.loading$ | async) && !loadMoreComponent?.isLoading) || loading;\n\n<div\n class=\"table-data-grid-scroll\"\n #scroll\n [ngClass]=\"{\n 'table-data-grid__overlay': loadingData\n }\"\n data-cy=\"c8y-data-grid--table-data-grid-scroll\"\n>\n @if (loadingData && displayOptions.showLoadingIndicator) {\n <div class=\"table-data-grid__loading--wrapper\">\n <div class=\"table-data-grid__loading--loader\">\n <c8y-loading\n layout=\"application\"\n [message]=\"loadingItemsLabel\"\n ></c8y-loading>\n </div>\n </div>\n }\n\n @if (displayOptions.gridHeader) {\n <div class=\"table-data-grid-header separator large-padding\">\n <div\n class=\"h4\"\n [ngClass]=\"{ 'm-r-16': !!title }\"\n >\n {{ title | translate }}\n </div>\n\n @if (displayOptions.filter) {\n @if (!filteringApplied) {\n <span>\n @if (!!filteringLabelsParams.allItemsCount) {\n <small\n class=\"m-r-4\"\n ngNonBindable\n translate\n [translateParams]=\"filteringLabelsParams\"\n >\n {{ filteredItemsCount }} of {{ allItemsCount }} items\n </small>\n }\n <span\n class=\"label label-default m-r-4\"\n translate\n >\n No filters\n </span>\n </span>\n }\n @if (filteringApplied) {\n <span class=\"d-flex a-i-center\">\n @if (!!filteringLabelsParams.allItemsCount) {\n <div class=\"a-i-center\">\n <span class=\"badge badge-info m-r-4\">\n {{ (dataSource.stats$ | async).filteredSize }}\n </span>\n <small\n ngNonBindable\n translate\n [translateParams]=\"filteringLabelsParams\"\n >\n of {{ allItemsCount }} items\n </small>\n </div>\n }\n <div\n class=\"dropdown\"\n placement=\"bottom left\"\n container=\"body\"\n dropdown\n #ddFilters=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btn btn-default btn-sm m-l-8\"\n title=\"{{ 'Active filters' | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n data-cy=\"c8y-data-grid--filters\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"filter\"\n ></i>\n <span>{{ 'Active filters' | translate }}</span>\n <span\n class=\"badge badge-system\"\n data-cy=\"c8y-data-grid--filters-count\"\n >\n {{ columnsWithFiltersApplied.length }}\n </span>\n </button>\n\n <div\n class=\"dropdown-menu\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"data-grid__dropdown bg-level-0\">\n <ul class=\"list-unstyled m-0\">\n @for (column of columnsWithFiltersApplied; track $index; let last = $last) {\n <li [ngClass]=\"{ 'separator-bottom': !last }\">\n <ng-container>\n <div\n class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n title=\"{{ (column.header | translate) || column.name }}\"\n >\n <label>\n {{ (column.header | translate) || column.name }}\n </label>\n </div>\n @for (\n groupedFilterChips of column\n | mapToFilterChips\n | async\n | groupedFilterChips;\n track $index;\n let first = $first\n ) {\n <div\n class=\"list-group-item borderless d-flex d-col\"\n [ngClass]=\"{ 'p-t-0': first }\"\n >\n @if (groupedFilterChips.label) {\n <p class=\"small p-b-4\">\n {{ groupedFilterChips.label | translate }}\n </p>\n }\n <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n @for (chip of groupedFilterChips.chips; track $index) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ 'Remove filter' | translate }}\"\n (click)=\"removeFilter(chip.remove())\"\n data-cy=\"c8y-data-grid--remove-chip\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ chip.displayValue | translate }}\n </span>\n }\n </div>\n </div>\n }\n </ng-container>\n </li>\n }\n </ul>\n </div>\n <div class=\"list-group-item separator-top sticky-bottom\">\n <button\n class=\"btn btn-sm btn-default\"\n title=\"{{ 'Clear all filters' | translate }}\"\n type=\"button\"\n (click)=\"clearFilters()\"\n data-cy=\"c8y-data-grid--clear-filters\"\n >\n {{ 'Clear all filters' | translate }}\n </button>\n </div>\n </div>\n </div>\n </span>\n }\n\n @if (displayOptions.filter) {\n <button\n class=\"btn-help btn-help--sm hidden-xs hidden-sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"filtersHelpPopover\"\n placement=\"right\"\n triggers=\"focus\"\n type=\"button\"\n data-cy=\"data-grid--help-filters\"\n >\n <i c8yIcon=\"question-circle-o\"></i>\n </button>\n }\n <ng-template #filtersHelpPopover>\n <div [innerHtml]=\"filtersHelpPopoverHtml | translate\"></div>\n </ng-template>\n\n @if (showCounterWarning) {\n <button\n class=\"btn-clean text-primary hidden-xs hidden-sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The counter for the total number of items might be inaccurate.' | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n type=\"button\"\n >\n <i c8yIcon=\"warning\"></i>\n </button>\n }\n }\n\n <div class=\"m-l-auto\">\n <div class=\"btnbar d-flex a-i-center\">\n @for (\n headerActionControl of headerActionControls | visibleControls | async;\n track $index\n ) {\n <ng-container>\n @if (!headerActionControl.template) {\n <button\n class=\"btnbar-btn btn-link\"\n title=\"{{ headerActionControl.text | translate }}\"\n type=\"button\"\n (click)=\"headerActionControl.callback()\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION,\n customActionName: headerActionControl.text,\n type: headerActionControl.type\n }\"\n >\n <i\n class=\"m-r-4\"\n [c8yIcon]=\"headerActionControl.icon\"\n ></i>\n <span>{{ headerActionControl.text | translate }}</span>\n </button>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"\n headerActionControl.template;\n context: { headerActionControl: headerActionControl }\n \"\n ></ng-container>\n }\n </ng-container>\n }\n\n @if (configureColumnsEnabled) {\n <div\n class=\"dropdown\"\n placement=\"bottom left\"\n container=\"body\"\n dropdown\n #ddConfigureColumns=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Configure columns' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--custom-column-btn\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"columns\"\n ></i>\n <span>{{ 'Configure columns' | translate }}</span>\n </button>\n\n <ul\n class=\"dropdown-menu data-grid__dropdown\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <li>\n <div\n class=\"list-group m-0\"\n cdkDropList\n (cdkDropListDropped)=\"onColumnDrop($event)\"\n >\n @for (column of columns; track $index) {\n <div\n cdkDrag\n cdkDragLockAxis=\"y\"\n >\n @if (!column.positionFixed) {\n <div class=\"list-group-item draggable-after p-l-16 p-r-16 a-i-center\">\n <label\n class=\"c8y-checkbox min-width-0\"\n title=\"{{ column.custom ? ('Custom' | translate) + ' ' : '' }}{{\n (column.header | translate) || column.name\n }}\"\n [attr.data-cy]=\"'data-grid--custom-column-header-' + column.header\"\n >\n <input\n type=\"checkbox\"\n [(ngModel)]=\"column.visible\"\n (change)=\"\n updateGridColumnsSize();\n emitConfigChange('changeColumnVisibility')\n \"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CHANGE_VISIBILITY,\n column: column.name,\n visible: !column.visible\n }\"\n />\n <span></span>\n <div class=\"d-col min-width-0 m-l-8 m-r-8\">\n @if (column?.custom) {\n <span class=\"text-muted text-10 m-b-0\">\n {{ 'Custom' | translate }}\n </span>\n }\n <span class=\"text-truncate l-h-1 m-t-2\">\n {{ (column.header | translate) || column.name }}\n </span>\n </div>\n @let canRetrieve = canRetrieveAssetProperties | async;\n @if (canRetrieve) {\n @if (canRetrieve && column?.type) {\n <span\n class=\"tag tag--default a-s-end\"\n title=\"{{ column.type | translate | humanize }}\"\n >\n {{ column.type | translate | humanize }}\n </span>\n }\n }\n </label>\n @if (column.custom) {\n <button\n class=\"btn btn-dot btn-dot--danger showOnHover max-width-fit a-i-center\"\n [attr.aria-label]=\"'Remove`column,verb`' | translate\"\n [popover]=\"confirmRemovePopover\"\n type=\"button\"\n #pop=\"bs-popover\"\n (click)=\"\n currentRemoveCustomColumnPopover !== pop &&\n currentRemoveCustomColumnPopover?.hide();\n currentRemoveCustomColumnPopover = pop\n \"\n >\n <i\n c8yIcon=\"minus-circle\"\n data-cy=\"data-grid--custom-column-remove-btn\"\n ></i>\n </button>\n\n <ng-template #confirmRemovePopover>\n <h3 class=\"popover-title popover-header\">\n {{ 'Confirm removal' | translate }}\n </h3>\n <div class=\"popover-content popover-body\">\n <p>{{ 'Do you want to remove this column?' | translate }}</p>\n <div class=\"popover-footer gap-16\">\n <button\n class=\"btn btn-default btn-sm\"\n type=\"button\"\n (click)=\"pop.hide()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-danger btn-sm\"\n type=\"button\"\n (click)=\"confirmRemoveColumn(column); pop.hide()\"\n data-cy=\"popover-confirm--Remove\"\n >\n {{ 'Remove' | translate }}\n </button>\n </div>\n </div>\n </ng-template>\n }\n </div>\n }\n </div>\n }\n </div>\n </li>\n @if (isConfigContextKnown) {\n <li class=\"p-8 sticky-bottom separator-top\">\n <button\n class=\"btn btn-default btn-block\"\n title=\"{{ 'Add custom column' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--add-custom-column\"\n (click)=\"openCustomColumn(); ddConfigureColumns.hide()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"plus-circle\"\n ></i>\n <span>{{ 'Add custom column' | translate }}</span>\n </button>\n </li>\n }\n </ul>\n </div>\n }\n\n @if (!hideReload) {\n <button\n class=\"btnbar-btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--reload-btn\"\n [disabled]=\"dataSource.loading$ | async\"\n (click)=\"clickReload()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"refresh\"\n ></i>\n <span>{{ 'Reload' | translate }}</span>\n </button>\n }\n\n @if (!serverSideDataCallback || showSearch) {\n <div class=\"input-group input-group-search m-l-sm-16 data-grid__search-input\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Search\u2026' | translate }}\"\n type=\"search\"\n [(ngModel)]=\"searchText\"\n (ngModelChange)=\"searchText$.emit($event)\"\n (keydown.enter)=\"$event.stopPropagation(); performSearch(searchText)\"\n />\n <div class=\"input-group-addon\">\n @if (searchText.length === 0) {\n <i c8yIcon=\"search\"></i>\n }\n @if (searchText.length > 0) {\n <i\n class=\"pointer\"\n c8yIcon=\"times\"\n (click)=\"searchText = ''; searchText$.emit('')\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.CLEAR_SEARCH }\"\n ></i>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if (selectedItemIds.length !== 0) {\n <div\n class=\"table-data-grid-header-bulk-actions animated slideInDown fast\"\n data-cy=\"table-data-grid-header-bulk-actions\"\n >\n <h4>\n <ng-container [ngPlural]=\"selectedItemIds.length\">\n <ng-template ngPluralCase=\"=1\">\n <span translate>1 selected item.</span>\n </ng-template>\n <ng-template ngPluralCase=\"other\">\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ count: selectedItemIds.length }\"\n >\n {{ count }} selected items.\n </span>\n </ng-template>\n </ng-container>\n <br class=\"visible-xs\" />\n @if (!serverSideDataCallback && selectedItemIds.length >= pagination.pageSize) {\n <small>\n <a\n class=\"interact\"\n (click)=\"setAllItemsSelected(true)\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.SELECT_ALL_ITEMS }\"\n >\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ count: (dataSource.stats$ | async).filteredSize }\"\n >\n Select all {{ count }} items\n </span>\n </a>\n </small>\n }\n </h4>\n <div class=\"m-l-auto\">\n <div class=\"btnbar d-flex\">\n @for (\n bulkActionControl of bulkActionControls | visibleControls: selectedItemIds | async;\n track $index\n ) {\n <ng-container>\n @switch (bulkActionControl.type) {\n @case (builtInActionType.Export) {\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Export' | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{ action: PX_ACTIONS.BULK_EXPORT }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"sign-out\"></i>\n <span>{{ 'Export' | translate }}</span>\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Delete' | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{ action: PX_ACTIONS.BULK_DELETE }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"delete\"></i>\n <span>{{ 'Delete' | translate }}</span>\n </button>\n }\n @default {\n <button\n class=\"btnbar-btn\"\n title=\"{{ bulkActionControl.text | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.BULK_CUSTOM_ACTION,\n customActionName: bulkActionControl.text\n }\"\n c8yProductExperience\n inherit\n >\n <i\n [class]=\"bulkActionControl.iconClasses\"\n c8yIcon=\"{{ bulkActionControl.icon }}\"\n ></i>\n <span>{{ bulkActionControl.text | translate }}</span>\n </button>\n }\n }\n </ng-container>\n }\n\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n [actionData]=\"{\n action: PX_ACTIONS.BULK_CANCEL\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"times\"></i>\n <span>{{ 'Cancel' | translate }}</span>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <table\n class=\"table table-filtered-sorted table-data-grid large-padding\"\n [class.table-striped]=\"displayOptions.striped && !treeGrid\"\n [class.table-bordered]=\"displayOptions.bordered\"\n [class.table-hover]=\"displayOptions.hover\"\n [class.table-data-grid-with-checkboxes]=\"selectable\"\n [class.table-data-grid-with-actions]=\"actionControls.length > 0\"\n [style.grid-template-columns]=\"styles.gridTemplateColumns\"\n cdk-table\n [dataSource]=\"dataSource\"\n [multiTemplateDataRows]=\"true\"\n (mousemove)=\"resizeHandleContainerMouseMove$.emit($event)\"\n data-cy=\"c8y-data-grid--table\"\n >\n @for (column of columns; track column.name; let i = $index) {\n <ng-container [cdkColumnDef]=\"column.name\">\n @switch (column.name) {\n @case ('checkbox') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n >\n <div>\n <label class=\"c8y-checkbox\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n type=\"checkbox\"\n [checked]=\"currentPageSelectionState.allSelected\"\n [indeterminate]=\"\n !(\n currentPageSelectionState.allSelected ||\n currentPageSelectionState.allDeselected\n )\n \"\n (change)=\"setAllItemsInCurrentPageSelected($event.target.checked)\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.SELECT_ALL_ITEMS }\"\n />\n <span></span>\n </label>\n </div>\n </th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n <label class=\"c8y-checkbox\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n type=\"checkbox\"\n [checked]=\"isItemSelected(row)\"\n (change)=\"setItemsSelected([row], $event.target.checked)\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.SELECT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--checkbox\"\n />\n <span></span>\n </label>\n </td>\n }\n\n @case ('radio-button') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n ></th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n <label class=\"c8y-radio\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n name=\"select-row\"\n type=\"radio\"\n [checked]=\"isItemSelected(row)\"\n (change)=\"changeSelectedItem(row)\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.SELECT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--radio\"\n />\n <span></span>\n </label>\n </td>\n }\n\n @case ('actions') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n >\n <p class=\"text-medium sr-only\">{{ 'Actions' | translate }}</p>\n </th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n @for (\n actionControl of actionControls\n | visibleControls: row\n | async\n | slice\n : 0\n : ((actionControls | visibleControls: row | async)?.length > 2 ? 1 : 2);\n track $index\n ) {\n <ng-container>\n @switch (actionControl.type) {\n @case (builtInActionType.Edit) {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"'Edit' | translate\"\n tooltip=\"{{ 'Edit' | translate }}\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.EDIT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--edit-button-in-row\"\n >\n <i c8yIcon=\"pencil\"></i>\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n class=\"btn btn-dot btn-dot--danger showOnHover\"\n [attr.aria-label]=\"'Delete' | translate\"\n tooltip=\"{{ 'Delete' | translate }}\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.DELETE_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n data-cy=\"c8y-data-grid--remove-button-in-row\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n }\n @default {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n (actionControl.icon ? actionControl.text : '') | translate\n \"\n tooltip=\"{{ (actionControl.icon ? actionControl.text : '') | translate }}\"\n container=\"body\"\n type=\"button\"\n [ngClass]=\"{ showOnHover: actionControl.showOnHover }\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION_ITEM,\n customActionName: actionControl.text,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n [attr.data-cy]=\"'c8y-data-grid--button-in-row--' + actionControl.text\"\n >\n @if (actionControl.icon) {\n <i\n c8yIcon=\"{{ actionControl.icon }}\"\n [ngClass]=\"actionControl.iconClasses\"\n ></i>\n } @else {\n <span>{{ actionControl.text | translate }}</span>\n }\n </button>\n }\n }\n </ng-container>\n }\n\n <div\n [ngClass]=\"{\n 'm-l-auto overflow-visible':\n (actionControls | visibleControls: row | async)?.length > 2\n }\"\n >\n @if ((actionControls | visibleControls: row | async)?.length > 2) {\n <div\n class=\"dropdown\"\n placement=\"bottom right\"\n container=\"body\"\n dropdown\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n title=\"{{ 'Actions' | translate }}\"\n aria-haspopup=\"true\"\n type=\"button\"\n data-cy=\"c8y-data-grid--row-actions-dropdown\"\n dropdownToggle\n >\n <i c8yIcon=\"ellipsis-v\"></i>\n </button>\n <ul\n class=\"dropdown-menu dropdown-menu-right\"\n *dropdownMenu\n >\n @for (\n actionControl of actionControls\n | visibleControls: row\n | async\n | slice\n : ((actionControls | visibleControls: row | async)?.length > 2 ? 1 : 2);\n track $index\n ) {\n <li>\n @switch (actionControl.type) {\n @case (builtInActionType.Edit) {\n <button\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.EDIT_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n title=\"{{ 'Delete' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.DELETE_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"delete\"></i>\n {{ 'Delete' | translate }}\n </button>\n }\n @case (builtInActionType.Export) {\n <button\n title=\"{{ 'Export' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.EXPORT_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"data-export\"></i>\n {{ 'Export' | translate }}\n </button>\n }\n @default {\n <button\n title=\"{{ actionControl.text | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION_ITEM,\n customActionName: actionControl.text,\n id: row.id\n }\"\n >\n <i\n c8yIcon=\"{{ actionControl.icon }}\"\n [ngClass]=\"actionControl.iconClasses\"\n ></i>\n {{ actionControl.text | translate }}\n </button>\n }\n }\n </li>\n }\n </ul>\n </div>\n }\n </div>\n </td>\n }\n @default {\n <th\n [class.sorted]=\"column.sortOrder\"\n [class.filtered]=\"column | map: isColumnFilteringApplied\"\n [class.hidden]=\"!column.visible\"\n cdk-header-cell\n *cdkHeaderCellDef\n [ngClass]=\"column.headerCSSClassName\"\n [attr.data-type]=\"column.dataType\"\n >\n @if (!column.filterable) {\n <div [title]=\"(column.header | translate) || column.name\">\n @let cellRendererSpec =\n [\n {\n columnName: column.name,\n value: (column.header | translate) || column.name\n }\n ] | map: getHeaderCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer [spec]=\"cellRendererSpec\"></c8y-cell-renderer>\n }\n </div>\n }\n\n <!-- isDropDownPlacedRight to be removed when columns are transformed to observables. -->\n @if (column.filterable) {\n <div\n class=\"dropdown\"\n placement=\"bottom {{ isDropDownPlacedRight(column) ? 'right' : 'left' }}\"\n container=\"body\"\n dropdown\n #gridHeaderDropdown=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btn-header\"\n [title]=\"(column.header | translate) || column.name\"\n type=\"button\"\n [attr.data-cy]=\"'data-grid--header-btn--' + column.header\"\n dropdownToggle\n >\n @let cellRendererSpec =\n [\n {\n columnName: column.name,\n value: (column.header | translate) || column.name\n }\n ] | map: getHeaderCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer\n data-cy=\"c8y-data-grid--c8y-cell-renderer\"\n [spec]=\"cellRendererSpec\"\n ></c8y-cell-renderer>\n }\n <i\n c8yIcon=\"filter\"\n title=\"{{ 'Filter' | translate }}\"\n ></i>\n </button>\n\n <!-- isDropDownPlacedRight to be removed when columns are transformed to observables. -->\n <ul\n class=\"dropdown-menu\"\n *dropdownMenu\n [ngClass]=\"{ 'dropdown-menu-right-grid': isDropDownPlacedRight(column) }\"\n (click)=\"$event.stopPropagation()\"\n >\n <li class=\"data-grid__dropdown\">\n @let filteringFormRendererSpec =\n [\n {\n column: column,\n dropdown: gridHeaderDropdown\n }\n ] | map: getFilteringFormRendererSpec : this;\n\n @if (filteringFormRendererSpec) {\n <c8y-filtering-form-renderer\n class=\"bg-component\"\n [spec]=\"filteringFormRendererSpec\"\n data-cy=\"c8y-data-grid--c8y-filtering-form-renderer\"\n ></c8y-filtering-form-renderer>\n }\n </li>\n </ul>\n </div>\n }\n\n @if (column.sortable) {\n <button\n class=\"btn-sort\"\n [style]=\"{\n 'margin-left': !column.filterable && column.sortable ? '-20px' : null\n }\"\n [title]=\"sortColumnTitle | translate: { name: column.header | translate }\"\n type=\"button\"\n (click)=\"changeSortOrder(column.name)\"\n data-cy=\"change-sort-order\"\n >\n @switch (column.sortOrder) {\n @case ('asc') {\n <i c8yIcon=\"long-arrow-up\"></i>\n }\n @case ('desc') {\n <i c8yIcon=\"long-arrow-down\"></i>\n }\n @default {\n <i c8yIcon=\"exchange\"></i>\n }\n }\n </button>\n }\n\n @if (column.resizable) {\n <span\n class=\"resize-handle\"\n (mousedown)=\"\n resizeHandleMouseDown$.emit({ event: $event, targetColumnName: column.name })\n \"\n ></span>\n }\n </th>\n\n <td\n [class.hidden]=\"!column.visible\"\n [attr.data-cell-title]=\"column.header | translate\"\n cdk-cell\n *cdkCellDef=\"let row\"\n [ngClass]=\"column.cellCSSClassName\"\n [attr.data-cy]=\"'data-grid--' + column.header\"\n [attr.data-type]=\"column.dataType\"\n >\n @let cellRendererSpec =\n [\n {\n value: resolveCellValue(row, column.path),\n row: row,\n columnName: column.name\n }\n ] | map: getCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer [spec]=\"cellRendererSpec\"></c8y-cell-renderer>\n }\n </td>\n }\n }\n </ng-container>\n }\n\n <ng-container cdkColumnDef=\"infiniteScrollFooter\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-footer-cell\n *cdkFooterCellDef\n >\n <template #infiniteScrollContainer></template>\n </td>\n </ng-container>\n\n <tr\n cdk-header-row\n *cdkHeaderRowDef=\"columnNames\"\n ></tr>\n\n <tr\n data-cy=\"c8y-data-grid--row-in-data-grid\"\n cdk-row\n *cdkRowDef=\"let row; columns: columnNames; let idx = dataIndex; when: isDataRow\"\n [ngClass]=\"[\n activeClassName && row === lastClickedRow ? activeClassName : '',\n idx % 2 === 0 ? 'even' : 'odd',\n row.level > 0 ? 'data-grid-child-node level-' + row.level : ''\n ]\"\n (mouseover)=\"rowMouseOver.emit(row)\"\n (mouseleave)=\"rowMouseLeave.emit(row)\"\n (click)=\"handleClick(row)\"\n ></tr>\n\n <tr\n class=\"expanded-row\"\n [ngClass]=\"{ hidden: !(expandedRows.get(row).visible$ | async) }\"\n data-cy=\"c8y-data-grid--expanded-row-in-data-grid\"\n cdk-row\n *cdkRowDef=\"let row; columns: ['expanded-row']; when: isRowExpanded\"\n ></tr>\n\n <ng-container cdkColumnDef=\"expanded-row\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-cell\n *cdkCellDef=\"let row\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n expandableRow?.template;\n context: {\n $implicit: row,\n asyncRenderSuccess: setExpandableRowVisible.bind(this, row, true),\n asyncRenderFail: setExpandableRowVisible.bind(this, row, false)\n }\n \"\n ></ng-container>\n </td>\n </ng-container>\n\n <tr\n [class]=\"'pagination-row level-' + (row.parentRow.level + 1)\"\n cdk-row\n *cdkRowDef=\"let row; columns: ['pagination-row']; when: isPaginationRow\"\n ></tr>\n\n <ng-container cdkColumnDef=\"pagination-row\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-cell\n *cdkCellDef=\"let row\"\n >\n <div class=\"col-sm-4 no-gutter\">\n @if ((dataSource.stats$ | async).currentPageSize > 0) {\n <div\n class=\"counter p-t-8 p-b-8\"\n data-cy=\"data-grid--child-counter\"\n >\n <span\n class=\"text-muted\"\n ngNonBindable\n translate\n [translateParams]=\"{\n pageFirstItemIdx:\n (row.childrenStats.currentPage - 1) * row.childrenStats.firstPageSize + 1,\n pageLastItemIdx:\n (row.childrenStats.currentPage - 1) * row.childrenStats.firstPageSize +\n 1 +\n (row.childrenStats.currentPageSize - 1),\n itemsTotal: row.childrenStats.filteredSize\n }\"\n >\n {{ pageFirstItemIdx }} - {{ pageLastItemIdx }} of {{ itemsTotal }}\n </span>\n <span class=\"text-muted text-12 m-r-4\">{{ 'Parent node' | translate }}</span>\n <span class=\"tag tag--default\">{{ row.parentRow?.[parentNodeLabelProperty] }}</span>\n </div>\n }\n </div>\n <div class=\"col-sm-4 col-sm-offset-4 no-gutter text-right\">\n @if (row.childrenStats.filteredSize > row.childrenStats.currentPageSize) {\n <pagination\n class=\"d-flex j-c-end\"\n [ngModel]=\"row.childrenStats.currentPage\"\n (pageChanged)=\"updateChildPagination($event, row)\"\n [totalItems]=\"row.childrenStats.filteredSize\"\n [itemsPerPage]=\"row?.parentRow?.pagination?.pageSize ?? childNodePagination.pageSize\"\n [maxSize]=\"5\"\n [boundaryLinks]=\"false\"\n [previousText]=\"'Previous' | translate\"\n [nextText]=\"'Next' | translate\"\n ></pagination>\n }\n </div>\n </td>\n </ng-container>\n\n <ng-container>\n <tr\n [ngClass]=\"{ hidden: !infiniteScroll }\"\n cdk-footer-row\n *cdkFooterRowDef=\"['infiniteScrollFooter']\"\n ></tr>\n </ng-container>\n </table>\n\n @if (\n !(dataSource.loading$ | async) &&\n !loading &&\n ((dataSource.stats$ | async).filteredSize === 0 || (dataSource.data$ | async).length === 0)\n ) {\n <div class=\"d-flex m-0 p-t-40 p-b-40\">\n <div class=\"col-lg-3 col-sm-4 m-l-auto m-r-auto\">\n <ng-content select=\"c8y-ui-empty-state, .c8y-empty-state\"></ng-content>\n <ng-container\n *ngTemplateOutlet=\"\n emptyState?.templateRef;\n context: { $implicit: emptyStateContext$ | async }\n \"\n ></ng-container>\n </div>\n </div>\n }\n\n @if (pagination && !infiniteScroll) {\n <div class=\"table-data-grid-footer separator large-padding\">\n <div class=\"col-sm-4 no-gutter\">\n @if ((dataSource.stats$ | async).currentPageSize > 0) {\n <div\n class=\"counter p-t-8 p-b-8\"\n data-cy=\"data-grid--counter\"\n >\n <span\n class=\"text-muted\"\n ngNonBindable\n translate\n [translateParams]=\"paginationLabelParams\"\n >\n {{ pageFirstItemIdx }} - {{ pageLastItemIdx }} of {{ itemsTotal }}\n </span>\n </div>\n }\n </div>\n\n <div class=\"col-sm-4 no-gutter text-center\">\n @if ((dataSource.stats$ | async).filteredSize > minPossiblePageSize) {\n <div class=\"form-group form-inline p-t-8 p-b-8\">\n <label\n class=\"m-r-4\"\n for=\"filteredSize\"\n >\n {{ 'Items per page' | translate }}\n </label>\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n id=\"filteredSize\"\n data-cy=\"data-grid--pagesize-options\"\n [ngModel]=\"pagination.pageSize\"\n (ngModelChange)=\"\n updatePagination({ itemsPerPage: $event, page: pagination.currentPage })\n \"\n >\n @for (pageSize of possiblePageSizes; track $index) {\n <option [ngValue]=\"pageSize\">\n {{ pageSize }}\n </option>\n }\n </select>\n </div>\n </div>\n }\n </div>\n\n <div class=\"col-sm-4 no-gutter text-right\">\n @if ((dataSource.stats$ | async).filteredSize > 0) {\n <pagination\n [class.hidden]=\"hidePagination$ | async\"\n class=\"d-flex j-c-end\"\n [ngModel]=\"pagination.currentPage\"\n (pageChanged)=\"updatePagination($event)\"\n [totalItems]=\"(dataSource.stats$ | async).filteredSize\"\n [itemsPerPage]=\"pagination.pageSize\"\n (numPages)=\"totalPagesCount$.next($event)\"\n [maxSize]=\"5\"\n [boundaryLinks]=\"false\"\n [previousText]=\"'Previous' | translate\"\n [nextText]=\"'Next' | translate\"\n ></pagination>\n }\n </div>\n </div>\n }\n</div>\n" }]
36516
+ ], template: "@let loadingData = ((dataSource.loading$ | async) && !loadMoreComponent?.isLoading) || loading;\n\n<div\n class=\"table-data-grid-scroll\"\n #scroll\n [ngClass]=\"{\n 'table-data-grid__overlay': loadingData\n }\"\n data-cy=\"c8y-data-grid--table-data-grid-scroll\"\n>\n @if (loadingData && displayOptions.showLoadingIndicator) {\n <div class=\"table-data-grid__loading--wrapper\">\n <div class=\"table-data-grid__loading--loader\">\n <c8y-loading\n layout=\"application\"\n [message]=\"loadingItemsLabel\"\n ></c8y-loading>\n </div>\n </div>\n }\n\n @if (displayOptions.gridHeader) {\n <div class=\"table-data-grid-header separator large-padding\">\n <div\n class=\"h4\"\n [ngClass]=\"{ 'm-r-16': !!title }\"\n >\n {{ title | translate }}\n </div>\n\n @if (displayOptions.filter) {\n @if (!filteringApplied) {\n <span>\n @if (!!filteringLabelsParams.allItemsCount) {\n <small\n class=\"m-r-4\"\n ngNonBindable\n translate\n [translateParams]=\"filteringLabelsParams\"\n >\n {{ filteredItemsCount }} of {{ allItemsCount }} items\n </small>\n }\n <span\n class=\"label label-default m-r-4\"\n translate\n >\n No filters\n </span>\n </span>\n }\n @if (filteringApplied) {\n <span class=\"d-flex a-i-center\">\n @if (!!filteringLabelsParams.allItemsCount) {\n <div class=\"a-i-center\">\n <span class=\"badge badge-info m-r-4\">\n {{ (dataSource.stats$ | async).filteredSize }}\n </span>\n <small\n ngNonBindable\n translate\n [translateParams]=\"filteringLabelsParams\"\n >\n of {{ allItemsCount }} items\n </small>\n </div>\n }\n <div\n class=\"dropdown\"\n placement=\"bottom left\"\n container=\"body\"\n dropdown\n #ddFilters=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btn btn-default btn-sm m-l-8\"\n title=\"{{ 'Active filters' | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n data-cy=\"c8y-data-grid--filters\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"filter\"\n ></i>\n <span>{{ 'Active filters' | translate }}</span>\n <span\n class=\"badge badge-system\"\n data-cy=\"c8y-data-grid--filters-count\"\n >\n {{ columnsWithFiltersApplied.length }}\n </span>\n </button>\n\n <div\n class=\"dropdown-menu\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"data-grid__dropdown bg-level-0\">\n <ul class=\"list-unstyled m-0\">\n @for (column of columnsWithFiltersApplied; track $index; let last = $last) {\n <li [ngClass]=\"{ 'separator-bottom': !last }\">\n <ng-container>\n <div\n class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n title=\"{{ (column.header | translate) || column.name }}\"\n >\n <label>\n {{ (column.header | translate) || column.name }}\n </label>\n </div>\n @for (\n groupedFilterChips of column\n | mapToFilterChips\n | async\n | groupedFilterChips;\n track $index;\n let first = $first\n ) {\n <div\n class=\"list-group-item borderless d-flex d-col\"\n [ngClass]=\"{ 'p-t-0': first }\"\n >\n @if (groupedFilterChips.label) {\n <p class=\"small p-b-4\">\n {{ groupedFilterChips.label | translate }}\n </p>\n }\n <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n @for (chip of groupedFilterChips.chips; track $index) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ 'Remove filter' | translate }}\"\n (click)=\"removeFilter(chip.remove())\"\n data-cy=\"c8y-data-grid--remove-chip\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ chip.displayValue | translate }}\n </span>\n }\n </div>\n </div>\n }\n </ng-container>\n </li>\n }\n </ul>\n </div>\n <div class=\"list-group-item separator-top sticky-bottom\">\n <button\n class=\"btn btn-sm btn-default\"\n title=\"{{ 'Clear all filters' | translate }}\"\n type=\"button\"\n (click)=\"clearFilters()\"\n data-cy=\"c8y-data-grid--clear-filters\"\n >\n {{ 'Clear all filters' | translate }}\n </button>\n </div>\n </div>\n </div>\n </span>\n }\n\n @if (displayOptions.filter) {\n <button\n class=\"btn-help btn-help--sm hidden-xs hidden-sm\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"filtersHelpPopover\"\n placement=\"right\"\n triggers=\"focus\"\n type=\"button\"\n data-cy=\"data-grid--help-filters\"\n >\n <i c8yIcon=\"question-circle-o\"></i>\n </button>\n }\n <ng-template #filtersHelpPopover>\n <div [innerHtml]=\"filtersHelpPopoverHtml | translate\"></div>\n </ng-template>\n\n @if (showCounterWarning) {\n <button\n class=\"btn-clean text-primary hidden-xs hidden-sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The counter for the total number of items might be inaccurate.' | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n type=\"button\"\n >\n <i c8yIcon=\"warning\"></i>\n </button>\n }\n }\n\n <div class=\"m-l-auto\">\n <div class=\"btnbar d-flex a-i-center\">\n @for (\n headerActionControl of headerActionControls | visibleControls | async;\n track $index\n ) {\n <ng-container>\n @if (!headerActionControl.template) {\n <button\n class=\"btnbar-btn btn-link\"\n title=\"{{ headerActionControl.text | translate }}\"\n type=\"button\"\n (click)=\"headerActionControl.callback()\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION,\n customActionName: headerActionControl.text,\n type: headerActionControl.type\n }\"\n >\n <i\n class=\"m-r-4\"\n [c8yIcon]=\"headerActionControl.icon\"\n ></i>\n <span>{{ headerActionControl.text | translate }}</span>\n </button>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"\n headerActionControl.template;\n context: { headerActionControl: headerActionControl }\n \"\n ></ng-container>\n }\n </ng-container>\n }\n\n @if (configureColumnsEnabled) {\n <div\n class=\"dropdown\"\n placement=\"bottom left\"\n container=\"body\"\n dropdown\n #ddConfigureColumns=\"bs-dropdown\"\n c8yDropdownFocusTrap\n [insideClick]=\"true\"\n >\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Configure columns' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--custom-column-btn\"\n dropdownToggle\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"columns\"\n ></i>\n <span>{{ 'Configure columns' | translate }}</span>\n </button>\n\n <ul\n class=\"dropdown-menu data-grid__dropdown\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <li>\n <div\n class=\"list-group m-0\"\n cdkDropList\n (cdkDropListDropped)=\"onColumnDrop($event)\"\n >\n @for (column of columns; track $index) {\n <div\n cdkDrag\n cdkDragLockAxis=\"y\"\n >\n @if (!column.positionFixed) {\n <div class=\"list-group-item draggable-after p-l-16 p-r-16 a-i-center\">\n <label\n class=\"c8y-checkbox min-width-0\"\n title=\"{{ column.custom ? ('Custom' | translate) + ' ' : '' }}{{\n (column.header | translate) || column.name\n }}\"\n [attr.data-cy]=\"'data-grid--custom-column-header-' + column.header\"\n >\n <input\n type=\"checkbox\"\n [(ngModel)]=\"column.visible\"\n (change)=\"\n updateGridColumnsSize();\n emitConfigChange('changeColumnVisibility')\n \"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CHANGE_VISIBILITY,\n column: column.name,\n visible: !column.visible\n }\"\n />\n <span></span>\n <div class=\"d-col min-width-0 m-l-8 m-r-8\">\n @if (column?.custom) {\n <span class=\"text-muted text-10 m-b-0\">\n {{ 'Custom' | translate }}\n </span>\n }\n <span class=\"text-truncate l-h-1 m-t-2\">\n {{ (column.header | translate) || column.name }}\n </span>\n </div>\n @let canRetrieve = canRetrieveAssetProperties | async;\n @if (canRetrieve) {\n @if (canRetrieve && column?.type) {\n <span\n class=\"tag tag--default a-s-end\"\n title=\"{{ column.type | translate | humanize }}\"\n >\n {{ column.type | translate | humanize }}\n </span>\n }\n }\n </label>\n @if (column.custom) {\n <button\n class=\"btn btn-dot btn-dot--danger showOnHover max-width-fit a-i-center\"\n [attr.aria-label]=\"'Remove`column,verb`' | translate\"\n [popover]=\"confirmRemovePopover\"\n type=\"button\"\n #pop=\"bs-popover\"\n (click)=\"\n currentRemoveCustomColumnPopover !== pop &&\n currentRemoveCustomColumnPopover?.hide();\n currentRemoveCustomColumnPopover = pop\n \"\n >\n <i\n c8yIcon=\"minus-circle\"\n data-cy=\"data-grid--custom-column-remove-btn\"\n ></i>\n </button>\n\n <ng-template #confirmRemovePopover>\n <h3 class=\"popover-title popover-header\">\n {{ 'Confirm removal' | translate }}\n </h3>\n <div class=\"popover-content popover-body\">\n <p>{{ 'Do you want to remove this column?' | translate }}</p>\n <div class=\"popover-footer gap-16\">\n <button\n class=\"btn btn-default btn-sm\"\n type=\"button\"\n (click)=\"pop.hide()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-danger btn-sm\"\n type=\"button\"\n (click)=\"confirmRemoveColumn(column); pop.hide()\"\n data-cy=\"popover-confirm--Remove\"\n >\n {{ 'Remove' | translate }}\n </button>\n </div>\n </div>\n </ng-template>\n }\n </div>\n }\n </div>\n }\n </div>\n </li>\n @if (isConfigContextKnown) {\n <li class=\"p-8 sticky-bottom separator-top\">\n <button\n class=\"btn btn-default btn-block\"\n title=\"{{ 'Add custom column' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--add-custom-column\"\n (click)=\"openCustomColumn(); ddConfigureColumns.hide()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"plus-circle\"\n ></i>\n <span>{{ 'Add custom column' | translate }}</span>\n </button>\n </li>\n }\n </ul>\n </div>\n }\n\n @if (!hideReload) {\n <button\n class=\"btnbar-btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n type=\"button\"\n data-cy=\"data-grid--reload-btn\"\n [disabled]=\"dataSource.loading$ | async\"\n (click)=\"clickReload()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"refresh\"\n ></i>\n <span>{{ 'Reload' | translate }}</span>\n </button>\n }\n\n @if (!serverSideDataCallback || showSearch) {\n <div class=\"input-group input-group-search m-l-sm-16 data-grid__search-input\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Search\u2026' | translate }}\"\n type=\"search\"\n [(ngModel)]=\"searchText\"\n (ngModelChange)=\"searchText$.emit($event)\"\n (keydown.enter)=\"$event.stopPropagation(); performSearch(searchText)\"\n />\n <div class=\"input-group-addon\">\n @if (searchText.length === 0) {\n <i c8yIcon=\"search\"></i>\n }\n @if (searchText.length > 0) {\n <i\n class=\"pointer\"\n c8yIcon=\"times\"\n (click)=\"searchText = ''; searchText$.emit('')\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.CLEAR_SEARCH }\"\n ></i>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if (selectedItemIds.length !== 0) {\n <div\n class=\"table-data-grid-header-bulk-actions animated slideInDown fast\"\n data-cy=\"table-data-grid-header-bulk-actions\"\n >\n <h4>\n <ng-container [ngPlural]=\"selectedItemIds.length\">\n <ng-template ngPluralCase=\"=1\">\n <span translate>1 selected item.</span>\n </ng-template>\n <ng-template ngPluralCase=\"other\">\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ count: selectedItemIds.length }\"\n >\n {{ count }} selected items.\n </span>\n </ng-template>\n </ng-container>\n <br class=\"visible-xs\" />\n @if (!serverSideDataCallback && selectedItemIds.length >= pagination.pageSize) {\n <small>\n <a\n class=\"interact\"\n (click)=\"setAllItemsSelected(true)\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.SELECT_ALL_ITEMS }\"\n >\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ count: (dataSource.stats$ | async).filteredSize }\"\n >\n Select all {{ count }} items\n </span>\n </a>\n </small>\n }\n </h4>\n <div class=\"m-l-auto\">\n <div class=\"btnbar d-flex\">\n @for (\n bulkActionControl of bulkActionControls | visibleControls: selectedItemIds | async;\n track $index\n ) {\n <ng-container>\n @switch (bulkActionControl.type) {\n @case (builtInActionType.Export) {\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Export' | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{ action: PX_ACTIONS.BULK_EXPORT }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"sign-out\"></i>\n <span>{{ 'Export' | translate }}</span>\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Delete' | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{ action: PX_ACTIONS.BULK_DELETE }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"delete\"></i>\n <span>{{ 'Delete' | translate }}</span>\n </button>\n }\n @default {\n <button\n class=\"btnbar-btn\"\n title=\"{{ bulkActionControl.text | translate }}\"\n type=\"button\"\n (click)=\"bulkActionControl.callback(selectedItemIds, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.BULK_CUSTOM_ACTION,\n customActionName: bulkActionControl.text\n }\"\n c8yProductExperience\n inherit\n >\n <i\n [class]=\"bulkActionControl.iconClasses\"\n c8yIcon=\"{{ bulkActionControl.icon }}\"\n ></i>\n <span>{{ bulkActionControl.text | translate }}</span>\n </button>\n }\n }\n </ng-container>\n }\n\n <button\n class=\"btnbar-btn\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancel()\"\n [actionData]=\"{\n action: PX_ACTIONS.BULK_CANCEL\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"times\"></i>\n <span>{{ 'Cancel' | translate }}</span>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <table\n class=\"table table-filtered-sorted table-data-grid large-padding\"\n [class.table-striped]=\"displayOptions.striped && !treeGrid\"\n [class.table-bordered]=\"displayOptions.bordered\"\n [class.table-hover]=\"displayOptions.hover\"\n [class.table-data-grid-with-checkboxes]=\"selectable\"\n [class.table-data-grid-with-actions]=\"actionControls.length > 0\"\n [style.grid-template-columns]=\"styles.gridTemplateColumns\"\n cdk-table\n [dataSource]=\"dataSource\"\n [multiTemplateDataRows]=\"true\"\n (mousemove)=\"resizeHandleContainerMouseMove$.emit($event)\"\n data-cy=\"c8y-data-grid--table\"\n >\n @for (column of columns; track column.name; let i = $index) {\n <ng-container [cdkColumnDef]=\"column.name\">\n @switch (column.name) {\n @case ('checkbox') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n >\n <div>\n <label class=\"c8y-checkbox\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n type=\"checkbox\"\n [checked]=\"currentPageSelectionState.allSelected\"\n [indeterminate]=\"\n !(\n currentPageSelectionState.allSelected ||\n currentPageSelectionState.allDeselected\n )\n \"\n (change)=\"setAllItemsInCurrentPageSelected($event.target.checked)\"\n c8yProductExperience\n inherit\n [actionData]=\"{ action: PX_ACTIONS.SELECT_ALL_ITEMS }\"\n />\n <span></span>\n </label>\n </div>\n </th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n <label class=\"c8y-checkbox\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n type=\"checkbox\"\n [checked]=\"isItemSelected(row)\"\n (change)=\"setItemsSelected([row], $event.target.checked)\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.SELECT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--checkbox\"\n />\n <span></span>\n </label>\n </td>\n }\n\n @case ('radio-button') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n ></th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n <label class=\"c8y-radio\">\n <input\n [attr.aria-label]=\"'Selected' | translate\"\n name=\"select-row\"\n type=\"radio\"\n [checked]=\"isItemSelected(row)\"\n (change)=\"changeSelectedItem(row)\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.SELECT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--radio\"\n />\n <span></span>\n </label>\n </td>\n }\n\n @case ('actions') {\n <th\n cdk-header-cell\n *cdkHeaderCellDef\n data-type=\"icon\"\n >\n <p class=\"text-medium sr-only\">{{ 'Actions' | translate }}</p>\n </th>\n\n <td\n cdk-cell\n *cdkCellDef=\"let row\"\n data-type=\"icon\"\n >\n @for (\n actionControl of actionControls\n | visibleControls: row\n | async\n | slice\n : 0\n : ((actionControls | visibleControls: row | async)?.length > 2 ? 1 : 2);\n track $index\n ) {\n <ng-container>\n @switch (actionControl.type) {\n @case (builtInActionType.Edit) {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"'Edit' | translate\"\n tooltip=\"{{ 'Edit' | translate }}\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.EDIT_ITEM,\n id: row.id\n }\"\n data-cy=\"c8y-data-grid--edit-button-in-row\"\n >\n <i c8yIcon=\"pencil\"></i>\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n class=\"btn btn-dot btn-dot--danger showOnHover\"\n [attr.aria-label]=\"'Delete' | translate\"\n tooltip=\"{{ 'Delete' | translate }}\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.DELETE_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n data-cy=\"c8y-data-grid--remove-button-in-row\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n }\n @default {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n (actionControl.icon ? actionControl.text : '') | translate\n \"\n tooltip=\"{{ (actionControl.icon ? actionControl.text : '') | translate }}\"\n container=\"body\"\n type=\"button\"\n [ngClass]=\"{ showOnHover: actionControl.showOnHover }\"\n [delay]=\"500\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION_ITEM,\n customActionName: actionControl.text,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n [attr.data-cy]=\"'c8y-data-grid--button-in-row--' + actionControl.text\"\n >\n @if (actionControl.icon) {\n <i\n c8yIcon=\"{{ actionControl.icon }}\"\n [ngClass]=\"actionControl.iconClasses\"\n ></i>\n } @else {\n <span>{{ actionControl.text | translate }}</span>\n }\n </button>\n }\n }\n </ng-container>\n }\n\n <div\n [ngClass]=\"{\n 'm-l-auto overflow-visible':\n (actionControls | visibleControls: row | async)?.length > 2\n }\"\n >\n @if ((actionControls | visibleControls: row | async)?.length > 2) {\n <div\n class=\"dropdown\"\n placement=\"bottom right\"\n container=\"body\"\n dropdown\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n title=\"{{ 'Actions' | translate }}\"\n aria-haspopup=\"true\"\n type=\"button\"\n data-cy=\"c8y-data-grid--row-actions-dropdown\"\n dropdownToggle\n >\n <i c8yIcon=\"ellipsis-v\"></i>\n </button>\n <ul\n class=\"dropdown-menu dropdown-menu-right\"\n *dropdownMenu\n >\n @for (\n actionControl of actionControls\n | visibleControls: row\n | async\n | slice\n : ((actionControls | visibleControls: row | async)?.length > 2 ? 1 : 2);\n track $index\n ) {\n <li>\n @switch (actionControl.type) {\n @case (builtInActionType.Edit) {\n <button\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.EDIT_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n }\n @case (builtInActionType.Delete) {\n <button\n title=\"{{ 'Delete' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.DELETE_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"delete\"></i>\n {{ 'Delete' | translate }}\n </button>\n }\n @case (builtInActionType.Export) {\n <button\n title=\"{{ 'Export' | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n [actionData]=\"{\n action: PX_ACTIONS.EXPORT_ITEM,\n id: row.id\n }\"\n c8yProductExperience\n inherit\n >\n <i c8yIcon=\"data-export\"></i>\n {{ 'Export' | translate }}\n </button>\n }\n @default {\n <button\n title=\"{{ actionControl.text | translate }}\"\n type=\"button\"\n (click)=\"actionControl.callback(row, reload.bind(this))\"\n c8yProductExperience\n inherit\n [actionData]=\"{\n action: PX_ACTIONS.CUSTOM_ACTION_ITEM,\n customActionName: actionControl.text,\n id: row.id\n }\"\n >\n <i\n c8yIcon=\"{{ actionControl.icon }}\"\n [ngClass]=\"actionControl.iconClasses\"\n ></i>\n {{ actionControl.text | translate }}\n </button>\n }\n }\n </li>\n }\n </ul>\n </div>\n }\n </div>\n </td>\n }\n @default {\n <th\n [class.sorted]=\"column.sortOrder\"\n [class.filtered]=\"column | map: isColumnFilteringApplied\"\n [class.hidden]=\"!column.visible\"\n cdk-header-cell\n *cdkHeaderCellDef\n [ngClass]=\"column.headerCSSClassName\"\n [attr.data-type]=\"column.dataType\"\n >\n @if (!column.filterable) {\n <div [title]=\"(column.header | translate) || column.name\">\n @let cellRendererSpec =\n [\n {\n columnName: column.name,\n value: (column.header | translate) || column.name\n }\n ] | map: getHeaderCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer [spec]=\"cellRendererSpec\"></c8y-cell-renderer>\n }\n </div>\n }\n\n <!-- isDropDownPlacedRight to be removed when columns are transformed to observables. -->\n @if (column.filterable) {\n <div\n class=\"dropdown\"\n placement=\"bottom {{ isDropDownPlacedRight(column) ? 'right' : 'left' }}\"\n container=\"body\"\n dropdown\n c8yDropdownFocusTrap\n #gridHeaderDropdown=\"bs-dropdown\"\n [insideClick]=\"true\"\n >\n <button\n class=\"btn-header\"\n [title]=\"(column.header | translate) || column.name\"\n type=\"button\"\n [attr.data-cy]=\"'data-grid--header-btn--' + column.header\"\n dropdownToggle\n >\n @let cellRendererSpec =\n [\n {\n columnName: column.name,\n value: (column.header | translate) || column.name\n }\n ] | map: getHeaderCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer\n data-cy=\"c8y-data-grid--c8y-cell-renderer\"\n [spec]=\"cellRendererSpec\"\n ></c8y-cell-renderer>\n }\n <i\n c8yIcon=\"filter\"\n title=\"{{ 'Filter' | translate }}\"\n ></i>\n </button>\n\n <!-- isDropDownPlacedRight to be removed when columns are transformed to observables. -->\n <ul\n class=\"dropdown-menu\"\n *dropdownMenu\n [ngClass]=\"{ 'dropdown-menu-right-grid': isDropDownPlacedRight(column) }\"\n (click)=\"$event.stopPropagation()\"\n >\n <li class=\"data-grid__dropdown\">\n @let filteringFormRendererSpec =\n [\n {\n column: column,\n dropdown: gridHeaderDropdown\n }\n ] | map: getFilteringFormRendererSpec : this;\n\n @if (filteringFormRendererSpec) {\n <c8y-filtering-form-renderer\n class=\"bg-component\"\n [spec]=\"filteringFormRendererSpec\"\n data-cy=\"c8y-data-grid--c8y-filtering-form-renderer\"\n ></c8y-filtering-form-renderer>\n }\n </li>\n </ul>\n </div>\n }\n\n @if (column.sortable) {\n <button\n class=\"btn-sort\"\n [style]=\"{\n 'margin-left': !column.filterable && column.sortable ? '-20px' : null\n }\"\n [title]=\"sortColumnTitle | translate: { name: column.header | translate }\"\n type=\"button\"\n (click)=\"changeSortOrder(column.name)\"\n data-cy=\"change-sort-order\"\n >\n @switch (column.sortOrder) {\n @case ('asc') {\n <i c8yIcon=\"long-arrow-up\"></i>\n }\n @case ('desc') {\n <i c8yIcon=\"long-arrow-down\"></i>\n }\n @default {\n <i c8yIcon=\"exchange\"></i>\n }\n }\n </button>\n }\n\n @if (column.resizable) {\n <span\n class=\"resize-handle\"\n (mousedown)=\"\n resizeHandleMouseDown$.emit({ event: $event, targetColumnName: column.name })\n \"\n ></span>\n }\n </th>\n\n <td\n [class.hidden]=\"!column.visible\"\n [attr.data-cell-title]=\"column.header | translate\"\n cdk-cell\n *cdkCellDef=\"let row\"\n [ngClass]=\"column.cellCSSClassName\"\n [attr.data-cy]=\"'data-grid--' + column.header\"\n [attr.data-type]=\"column.dataType\"\n >\n @let cellRendererSpec =\n [\n {\n value: resolveCellValue(row, column.path),\n row: row,\n columnName: column.name\n }\n ] | map: getCellRendererSpec : this;\n\n @if (cellRendererSpec) {\n <c8y-cell-renderer [spec]=\"cellRendererSpec\"></c8y-cell-renderer>\n }\n </td>\n }\n }\n </ng-container>\n }\n\n <ng-container cdkColumnDef=\"infiniteScrollFooter\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-footer-cell\n *cdkFooterCellDef\n >\n <template #infiniteScrollContainer></template>\n </td>\n </ng-container>\n\n <tr\n cdk-header-row\n *cdkHeaderRowDef=\"columnNames\"\n ></tr>\n\n <tr\n data-cy=\"c8y-data-grid--row-in-data-grid\"\n cdk-row\n *cdkRowDef=\"let row; columns: columnNames; let idx = dataIndex; when: isDataRow\"\n [ngClass]=\"[\n activeClassName && row === lastClickedRow ? activeClassName : '',\n idx % 2 === 0 ? 'even' : 'odd',\n row.level > 0 ? 'data-grid-child-node level-' + row.level : ''\n ]\"\n (mouseover)=\"rowMouseOver.emit(row)\"\n (mouseleave)=\"rowMouseLeave.emit(row)\"\n (click)=\"handleClick(row)\"\n ></tr>\n\n <tr\n class=\"expanded-row\"\n [ngClass]=\"{ hidden: !(expandedRows.get(row).visible$ | async) }\"\n data-cy=\"c8y-data-grid--expanded-row-in-data-grid\"\n cdk-row\n *cdkRowDef=\"let row; columns: ['expanded-row']; when: isRowExpanded\"\n ></tr>\n\n <ng-container cdkColumnDef=\"expanded-row\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-cell\n *cdkCellDef=\"let row\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n expandableRow?.template;\n context: {\n $implicit: row,\n asyncRenderSuccess: setExpandableRowVisible.bind(this, row, true),\n asyncRenderFail: setExpandableRowVisible.bind(this, row, false)\n }\n \"\n ></ng-container>\n </td>\n </ng-container>\n\n <tr\n [class]=\"'pagination-row level-' + (row.parentRow.level + 1)\"\n cdk-row\n *cdkRowDef=\"let row; columns: ['pagination-row']; when: isPaginationRow\"\n ></tr>\n\n <ng-container cdkColumnDef=\"pagination-row\">\n <td\n [style.grid-column]=\"styles.gridInfiniteScrollColumn\"\n cdk-cell\n *cdkCellDef=\"let row\"\n >\n <div class=\"col-sm-4 no-gutter\">\n @if ((dataSource.stats$ | async).currentPageSize > 0) {\n <div\n class=\"counter p-t-8 p-b-8\"\n data-cy=\"data-grid--child-counter\"\n >\n <span\n class=\"text-muted\"\n ngNonBindable\n translate\n [translateParams]=\"{\n pageFirstItemIdx:\n (row.childrenStats.currentPage - 1) * row.childrenStats.firstPageSize + 1,\n pageLastItemIdx:\n (row.childrenStats.currentPage - 1) * row.childrenStats.firstPageSize +\n 1 +\n (row.childrenStats.currentPageSize - 1),\n itemsTotal: row.childrenStats.filteredSize\n }\"\n >\n {{ pageFirstItemIdx }} - {{ pageLastItemIdx }} of {{ itemsTotal }}\n </span>\n <span class=\"text-muted text-12 m-r-4\">{{ 'Parent node' | translate }}</span>\n <span class=\"tag tag--default\">{{ row.parentRow?.[parentNodeLabelProperty] }}</span>\n </div>\n }\n </div>\n <div class=\"col-sm-4 col-sm-offset-4 no-gutter text-right\">\n @if (row.childrenStats.filteredSize > row.childrenStats.currentPageSize) {\n <pagination\n class=\"d-flex j-c-end\"\n [ngModel]=\"row.childrenStats.currentPage\"\n (pageChanged)=\"updateChildPagination($event, row)\"\n [totalItems]=\"row.childrenStats.filteredSize\"\n [itemsPerPage]=\"row?.parentRow?.pagination?.pageSize ?? childNodePagination.pageSize\"\n [maxSize]=\"5\"\n [boundaryLinks]=\"false\"\n [previousText]=\"'Previous' | translate\"\n [nextText]=\"'Next' | translate\"\n ></pagination>\n }\n </div>\n </td>\n </ng-container>\n\n <ng-container>\n <tr\n [ngClass]=\"{ hidden: !infiniteScroll }\"\n cdk-footer-row\n *cdkFooterRowDef=\"['infiniteScrollFooter']\"\n ></tr>\n </ng-container>\n </table>\n\n @if (\n !(dataSource.loading$ | async) &&\n !loading &&\n ((dataSource.stats$ | async).filteredSize === 0 || (dataSource.data$ | async).length === 0)\n ) {\n <div class=\"d-flex m-0 p-t-40 p-b-40\">\n <div class=\"col-lg-3 col-sm-4 m-l-auto m-r-auto\">\n <ng-content select=\"c8y-ui-empty-state, .c8y-empty-state\"></ng-content>\n <ng-container\n *ngTemplateOutlet=\"\n emptyState?.templateRef;\n context: { $implicit: emptyStateContext$ | async }\n \"\n ></ng-container>\n </div>\n </div>\n }\n\n @if (pagination && !infiniteScroll) {\n <div class=\"table-data-grid-footer separator large-padding\">\n <div class=\"col-sm-4 no-gutter\">\n @if ((dataSource.stats$ | async).currentPageSize > 0) {\n <div\n class=\"counter p-t-8 p-b-8\"\n data-cy=\"data-grid--counter\"\n >\n <span\n class=\"text-muted\"\n ngNonBindable\n translate\n [translateParams]=\"paginationLabelParams\"\n >\n {{ pageFirstItemIdx }} - {{ pageLastItemIdx }} of {{ itemsTotal }}\n </span>\n </div>\n }\n </div>\n\n <div class=\"col-sm-4 no-gutter text-center\">\n @if ((dataSource.stats$ | async).filteredSize > minPossiblePageSize) {\n <div class=\"form-group form-inline p-t-8 p-b-8\">\n <label\n class=\"m-r-4\"\n for=\"filteredSize\"\n >\n {{ 'Items per page' | translate }}\n </label>\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n id=\"filteredSize\"\n data-cy=\"data-grid--pagesize-options\"\n [ngModel]=\"pagination.pageSize\"\n (ngModelChange)=\"\n updatePagination({ itemsPerPage: $event, page: pagination.currentPage })\n \"\n >\n @for (pageSize of possiblePageSizes; track $index) {\n <option [ngValue]=\"pageSize\">\n {{ pageSize }}\n </option>\n }\n </select>\n </div>\n </div>\n }\n </div>\n\n <div class=\"col-sm-4 no-gutter text-right\">\n @if ((dataSource.stats$ | async).filteredSize > 0) {\n <pagination\n [class.hidden]=\"hidePagination$ | async\"\n class=\"d-flex j-c-end\"\n [ngModel]=\"pagination.currentPage\"\n (pageChanged)=\"updatePagination($event)\"\n [totalItems]=\"(dataSource.stats$ | async).filteredSize\"\n [itemsPerPage]=\"pagination.pageSize\"\n (numPages)=\"totalPagesCount$.next($event)\"\n [maxSize]=\"5\"\n [boundaryLinks]=\"false\"\n [previousText]=\"'Previous' | translate\"\n [nextText]=\"'Next' | translate\"\n ></pagination>\n }\n </div>\n </div>\n }\n</div>\n" }]
36446
36517
  }], ctorParameters: () => [{ type: undefined, decorators: [{
36447
36518
  type: Optional
36448
36519
  }, {
@@ -41297,13 +41368,34 @@ class SplitViewListItemDirective {
41297
41368
  get role() {
41298
41369
  return 'button';
41299
41370
  }
41371
+ /**
41372
+ * The row carries `role="button"`, so it has to be reachable and operable like one. Without a tab
41373
+ * stop a screen reader announces a button that a keyboard user can never get to.
41374
+ */
41375
+ get tabindex() {
41376
+ return '0';
41377
+ }
41300
41378
  onClick() {
41379
+ this.select();
41380
+ }
41381
+ /**
41382
+ * Enter and Space activate a button, and Space additionally scrolls the page unless that is
41383
+ * suppressed — so the default is prevented here rather than letting the row select and scroll.
41384
+ */
41385
+ onKeydown(event) {
41386
+ if (event.key !== 'Enter' && event.key !== ' ') {
41387
+ return;
41388
+ }
41389
+ event.preventDefault();
41390
+ this.select();
41391
+ }
41392
+ select() {
41301
41393
  if (this.item && this.selectionService) {
41302
41394
  this.selectionService.select(this.item);
41303
41395
  }
41304
41396
  }
41305
41397
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SplitViewListItemDirective, deps: [{ token: SplitViewSelectionService, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
41306
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.19", type: SplitViewListItemDirective, isStandalone: true, selector: "[c8ySvListItem]", inputs: { item: ["c8ySvListItem", "item"] }, host: { listeners: { "click": "onClick()" }, properties: { "class.active": "this.isActive", "attr.role": "this.role" }, classAttribute: "pointer" }, ngImport: i0 }); }
41398
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.19", type: SplitViewListItemDirective, isStandalone: true, selector: "[c8ySvListItem]", inputs: { item: ["c8ySvListItem", "item"] }, host: { listeners: { "click": "onClick()", "keydown": "onKeydown($event)" }, properties: { "class.active": "this.isActive", "attr.role": "this.role", "attr.tabindex": "this.tabindex" }, classAttribute: "pointer" }, ngImport: i0 }); }
41307
41399
  }
41308
41400
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SplitViewListItemDirective, decorators: [{
41309
41401
  type: Directive,
@@ -41323,9 +41415,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
41323
41415
  }], role: [{
41324
41416
  type: HostBinding,
41325
41417
  args: ['attr.role']
41418
+ }], tabindex: [{
41419
+ type: HostBinding,
41420
+ args: ['attr.tabindex']
41326
41421
  }], onClick: [{
41327
41422
  type: HostListener,
41328
41423
  args: ['click']
41424
+ }], onKeydown: [{
41425
+ type: HostListener,
41426
+ args: ['keydown', ['$event']]
41329
41427
  }] } });
41330
41428
 
41331
41429
  /**
@@ -41336,5 +41434,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
41336
41434
  * Generated bundle index. Do not edit.
41337
41435
  */
41338
41436
 
41339
- export { ACTIONS_STEPPER, AGGREGATIONS, AGGREGATION_ICONS, AGGREGATION_LABELS, AGGREGATION_LIMITS, AGGREGATION_TEXTS, AGGREGATION_VALUES, AGGREGATION_VALUES_ARR, ARRAY_VALIDATION_PREFIX, ASSET_PATH, AUTO_AGGREGATION_ICON, AUTO_POINTS_TOOLTIP, AUTO_POINTS_TOOLTIP_KEPT, AbstractConfigurationStrategy, ActionBarComponent, ActionBarItemComponent, ActionBarModule, ActionBarService, ActionComponent, ActionControlsExtensionService, ActionModule, ActionOutletComponent, ActionService, AggregationPickerComponent, AggregationService, AlarmRealtimeService, AlarmWithChildrenRealtimeService, AlertComponent, AlertDetailsComponent, AlertModule, AlertOutletBase, AlertOutletComponent, AlertService, AlertTextComponent, AppHrefPipe, AppIconComponent, AppStateService, AppSwitcherComponent, AppSwitcherInlineComponent, AppSwitcherService, ApplicationModule, ApplicationPluginStatus, ApplyRangeClassPipe, AssetDefinitionsService, AssetHierarchyService, AssetLinkPipe, AssetPropertyService, AssetTypesRealtimeService, AssetTypesService, AuditLogComponent, AuditLogModule, AuthenticationModule, BASELINE_COLUMNS, BASELINE_ROWS, BackendVersionFactory, BaseColumn, BaseFilteringFormRendererComponent, BooleanFilterMapper, BootstrapComponent, BootstrapModule, BottomDrawerComponent, BottomDrawerRef, BottomDrawerService, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbModule, BreadcrumbOutletComponent, BreadcrumbService, BuiltInActionType, BytesPipe, C8Y_PLUGIN_CONTEXT_PATH, C8Y_PLUGIN_NAME, C8yComponentOutlet, C8yJSONSchema, C8yStepper, C8yStepperButtons, C8yStepperIcon, C8yStepperProgress, C8yTranslateDirective, C8yTranslateModule, C8yTranslatePipe, C8yTranslationCache, C8yTranslationLoader, C8yValidators, CUSTOM, CachedLocaleDictionaryService, CellRendererComponent, CellRendererContext, CellRendererDefDirective, ChangeCurrentUserPasswordService, ChangeIconComponent, ClipboardModule, ClipboardService, ColorInputComponent, ColorService, ColumnDirective, CommonModule, ConditionalTabsOutletComponent, ConfigureCustomColumnComponent, ConfirmModalComponent, ContextRouteComponent, ContextRouteGuard, ContextRouteService, CookieBannerComponent, CopyDashboardDisabledReason, CoreModule, CoreSearchModule, CountdownIntervalComponent, CountdownIntervalModule, CurrentPasswordModalComponent, CustomColumn, CustomTranslateService, CustomTranslateStore, DATA_GRID_CONFIGURATION_CONTEXT, DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER, DATA_GRID_CONFIGURATION_STRATEGY, DEFAULT_INTERVAL_STATE, DEFAULT_INTERVAL_VALUE, DEFAULT_INTERVAL_VALUES, DRAWER_ANIMATION_TIME, DashboardChildActionComponent, DashboardChildChange, DashboardChildComponent, DashboardChildTitleComponent, DashboardComponent, DashboardModule, DataGridComponent, DataGridModule, DataGridService, DatapointLibraryValidationErrors, DatapointSyncService, DateContextQueryParamNames, DateFilterMapper, DateFormatService, DatePickerComponent, DatePickerModule, DatePipe, DateTimePickerComponent, DateTimePickerModule, DefaultValidationDirective, DeviceBootstrapRealtimeService, DeviceService, DeviceStatusComponent, DeviceStatusModule, DismissAlertStrategy, DocsModule, DocsService, DrawerModule, DrawerOutletComponent, DrawerService, DropAreaComponent, DropAreaModule, DropdownDirectionDirective, DropdownFocusTrapDirective, DynamicBulkDetailsResolver, DynamicBulkIIdentifiedResolver, DynamicComponentAlert, DynamicComponentAlertAggregator, DynamicComponentAlertsComponent, DynamicComponentComponent, DynamicComponentErrorStrategy, DynamicComponentModule, DynamicComponentService, DynamicDatapointsResolver, DynamicFormsModule, DynamicManagedObjectResolver, DynamicResolverService, ES_MAX_TIME_MILLISECONDS, EmailsValidatorDirective, EmptyComponent, EmptyStateComponent, EmptyStateContextDirective, EventRealtimeService, ExpandableRowDirective, ExtensionPointForPlugins, ExtensionPointWithoutStateForPlugins, ExtractArrayValidationErrorsPipe, FeatureCacheService, FeedbackFormComponent, FilePickerComponent, FilePickerFormControlComponent, FilePickerFormControlModule, FilePickerModule, FilesService, FilterByPipe, FilterInputComponent, FilterMapperFactory, FilterMapperModule, FilterMapperPipe, FilterMapperService, FilterNonArrayValidationErrorsPipe, FilteringActionType, FilteringFormRendererComponent, FilteringFormRendererContext, FilteringFormRendererDefDirective, ForOfDirective, FormGroupComponent, FormsModule, GENERIC_FILE_TYPE, GLOBAL_CONTEXT_AUTO_REFRESH, GainsightService, GenericFileIconPipe, GeoService, GetGroupIconPipe, GlobalConfigService, GridDataSource, GroupFragment, GroupService, GroupedFilterChips, GuideDocsComponent, GuideHrefDirective, HOOK_ACTION, HOOK_ACTION_BAR, HOOK_BREADCRUMB, HOOK_COMPONENTS, HOOK_CURRENT_APPLICATION, HOOK_CURRENT_TENANT, HOOK_CURRENT_USER, HOOK_DOCS, HOOK_DYNAMIC_PROVIDER_CONFIG, HOOK_NAVIGATOR_NODES, HOOK_OPTIONS, HOOK_PATTERN_MESSAGES, HOOK_PLUGIN, HOOK_PREVIEW, HOOK_QUERY_PARAM, HOOK_QUERY_PARAM_BOTTOM_DRAWER, HOOK_QUERY_PARAM_MODAL, HOOK_ROUTE, HOOK_SEARCH, HOOK_STEPPER, HOOK_TABS, HOOK_VERSION, HOOK_WIZARD, HeaderBarComponent, HeaderCellRendererDefDirective, HeaderModule, HeaderService, HelpComponent, HelpModule, HighlightComponent, HookProviderTypes, HumanizeAppNamePipe, HumanizePipe, HumanizeValidationMessagePipe, I18nModule, INTERVAL_OPTIONS, IconDirective, IconPanelComponent, IfAllowedDirective, InjectionType, InputGroupEditableComponent, InputGroupListComponent, InputGroupListContainerDirective, InterAppService, IntersectionObserverService, IntervalBasedReload, InventorySearchService, IpRangeInputListComponent, JsonValidationPrettifierDirective, LANGUAGES, LAST_DAY, LAST_HOUR, LAST_MINUTE, LAST_MONTH, LAST_WEEK, LOCALE_PATH, LegacyGridConfigMapperService, LegendFieldWrapper, ListDisplaySwitchComponent, ListDisplaySwitchModule, ListGroupComponent, ListGroupModule, ListItemActionComponent, ListItemBodyComponent, ListItemCheckboxComponent, ListItemCollapseComponent, ListItemComponent, ListItemDragHandleComponent, ListItemFooterComponent, ListItemIconComponent, ListItemRadioComponent, ListItemTimelineComponent, LoadMoreComponent, LoadingComponent, LoadingMessageComponent, MAX_PAGE_SIZE, MESSAGES_CORE_I18N, MOChunkLoaderService, ManagedObjectRealtimeService, ManagedObjectType, MapFunctionPipe, MarkdownToHtmlPipe, MaxValidationDirective, MeasurementRealtimeService, MessageBannerService, MessageDirective, MessagesComponent, MinValidationDirective, MissingTranslationCustomHandler, MoNamePipe, ModalComponent, ModalModule, ModalSelectionMode, ModalService, NEEDED_ROLE_FOR_SETUP, NEW_DASHBOARD_ROUTER_STATE_PROP, NULL_VALUE_PLACEHOLDER, NUMBER_FORMAT_REGEXP, NameTransformPipe, NavigatorBottomModule, NavigatorIconComponent, NavigatorModule, NavigatorNode, NavigatorNodeComponent, NavigatorNodeRoot, NavigatorOutletComponent, NavigatorService, NavigatorTopModule, NewPasswordComponent, NumberPipe, OperationBulkRealtimeService, OperationRealtimeService, OperationResultComponent, OptionsService, OutletDirective, PREVIEW_FEATURE_PROVIDERS, PRODUCT_EXPERIENCE_EVENT_SOURCE, PX_ACTIONS, PX_EVENT_NAME, PackageType, PasswordCheckListComponent, PasswordConfirm, PasswordConfirmModalComponent, PasswordInputComponent, PasswordService, PasswordStrengthCheckerService, PasswordStrengthComponent, PasswordStrengthService, PasswordValidationDirective, PasswordValidationService, PatternMessagesService, Permissions, PhoneValidationDirective, PlatformDetailsService, PluginLoadedPipe, PluginsExportScopes, PluginsLoaderService, PluginsModule, PluginsResolveService, PluginsService, PopoverConfirmComponent, PreviewFeatureButtonComponent, PreviewFeatureShowNotification, PreviewService, ProductExperienceDirective, ProductExperienceModule, ProgressBarComponent, PropertiesListComponent, PropertiesListModule, PropertyValueTransformService, ProviderConfigurationComponent, ProviderConfigurationModule, ProviderConfigurationNodeFactory, ProviderConfigurationRouteFactory, ProviderConfigurationService, ProviderDefinitionsService, PushStatus, PushStatusLabels, QUERY_PARAM_HANDLER_PROVIDERS, QueryParamBottomDrawerFactory, QueryParamBottomDrawerStateService, QueryParamHandlerService, QueryParamModalFactory, QueryParamModalStateService, QuickLinkComponent, QuickLinkModule, RELOAD_QUERY_PARAM, RESOLVING_COMPONENT_WAIT_TIME, RadioFilterMapper, RangeComponent, RangeDirective, RangeDisplayComponent, RangeDisplayModule, RealtimeButtonComponent, RealtimeControlComponent, RealtimeMessage, RealtimeModule, RealtimeService, RealtimeSubjectService, RelativeTimePipe, RequiredInputPlaceholderDirective, ResizableGridComponent, ResolverServerError, RouterModule, RouterService, RouterTabsResolver, SETUP_FINISHED_STEP_ID, SHOW_PREVIEW_FEATURES, SearchComponent, SearchFilters, SearchInputComponent, SearchOutletComponent, SearchResultEmptyComponent, SearchService, SelectComponent, SelectFilterMapper, SelectItemDirective, SelectKeyboardService, SelectLegacyComponent, SelectModalComponent, SelectModalFilterPipe, SelectModalModule, SelectModule, SelectedItemsComponent, SelectedItemsDirective, SendStatus, SendStatusLabels, ServiceRegistry, SetupCompletedComponent, SetupComponent, SetupModule, SetupService, SetupState, SetupStepperFactory, ShortenUserNamePipe, ShouldShowMoPipe, ShowIfFilterPipe, SimpleJsonPathValidatorDirective, SimplifiedAuthService, SkipLinkDirective, SplitViewAlertsComponent, SplitViewComponent, SplitViewDetailsActionsComponent, SplitViewDetailsComponent, SplitViewExtraHeaderComponent, SplitViewFooterComponent, SplitViewHeaderActionsComponent, SplitViewListComponent, SplitViewListItemDirective, SplitViewSelectionService, StateService, Status, StepperModule, StepperOutletComponent, StepperService, Steppers, StringFilterMapper, StringifyObjectPipe, StripHtmlPipe, SupportedApps, TabComponent, TabsModule, TabsOutletComponent, TabsService, TabsetAriaDirective, TenantUiService, TextAreaRowHeightDirective, TextareaAutoresizeDirective, ThemeSwitcherService, TimeIntervalComponent, TimePickerComponent, TimePickerModule, TitleComponent, TitleOutletComponent, TotpChallengeComponent, TotpSetupComponent, TranslateService, TreeNodeCellRendererComponent, TreeNodeColumn, TreeNodeHeaderCellRendererComponent, TypeaheadComponent, TypeaheadFilterMapper, UiSettingsComponent, UiSettingsModule, UniqueInCollectionByPathValidationDirective, UserEditComponent, UserEditModalComponent, UserEngagementsService, UserMenuItemComponent, UserMenuOutletComponent, UserMenuService, UserModule, UserNameInitialsPipe, UserPreferencesConfigurationStrategy, UserPreferencesService, UserPreferencesStorageInventory, UserPreferencesStorageLocal, UserTotpRevokeComponent, UserTotpSetupComponent, VERSION_MODULE_CONFIG, ValidationPattern, VersionListComponent, VersionModule, VersionService, ViewContext, ViewContextServices, VirtualScrollListenerDirective, VirtualScrollWindowDirective, VirtualScrollWindowStrategy, VirtualScrollerWrapperComponent, VisibleControlsPipe, WIDGET_CONFIGURATION_GRID_SIZE, WIDGET_TYPE_VALUES, WILDCARD_SEARCH_FEATURE_KEY, WebSDKVersionFactory, WidgetActionWrapperComponent, WidgetGlobalAutoRefreshService, WidgetTimeContextActionBarPriority, WidgetTimeContextComponent, WidgetTimeContextDateRangeService, WidgetTimeContextMediatorService, WidgetsDashboardComponent, WidgetsDashboardEventService, WizardBodyComponent, WizardComponent, WizardFooterComponent, WizardHeaderComponent, WizardModalService, WizardModule, WizardOutletComponent, WizardService, ZipService, _virtualScrollWindowStrategyFactory, alertOnError, allEntriesAreEqual, asyncValidateArrayElements, colorValidator, deviceAvailabilityIconMap, extraRoutes, fromFactories, fromTrigger, fromTriggerOnce, getActivatedRoute, getAngularLocalesLanguageString, getBasicInputArrayFormFieldConfig, getDictionaryWithTrimmedKeys, getInjectedHooks, gettext, globalAutoRefreshLoading, hookAction, hookActionBar, hookBreadcrumb, hookComponent, hookCurrentApplication, hookCurrentTenant, hookCurrentUser, hookDataGridActionControls, hookDocs, hookDrawer, hookDynamicProviderConfig, hookFilterMapper, hookGeneric, hookNavigator, hookOptions, hookPatternMessages, hookPlugin, hookPreview, hookQueryParam, hookQueryParamBottomDrawer, hookQueryParamModal, hookRoute, hookSearch, hookService, hookStepper, hookTab, hookUserMenu, hookVersion, hookWidget, hookWizard, internalApps, isBinaryFile, isEagerDynamicComponents, isExtensionFactory, isLazyDynamicComponents, isPromise, languagesFactory, loadLocale, localeId, localePathFactory, memoize, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, provideBootstrapMetadata, provideCommonPipes, provideCommonServices, provideDefaultOptionsAppInitializer, provideI18n, provideLanguageSelectorAppInitializer, providePluginsLoaderServiceAppInitializer, provideTranslationServiceInstance, ratiosByColumnTypes, removeContextIndicators, removeDuplicatesIds, resolveInjectedFactories, retryWithDelay, runGuardsOnParamsOrReloadChange, scaleWidgetDimensions, simpleJsonPathValidator, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, throttle, toObservable, toObservableOfArrays, tooltips, trimTranslationKey, uniqueInCollectionByPathValidator, validateArrayElements, validateInternationalPhoneNumber, viewContextRoutes, wrapperLegendFieldConfig };
41437
+ export { ACTIONS_STEPPER, AGGREGATIONS, AGGREGATION_ICONS, AGGREGATION_LABELS, AGGREGATION_LIMITS, AGGREGATION_TEXTS, AGGREGATION_VALUES, AGGREGATION_VALUES_ARR, ARRAY_VALIDATION_PREFIX, ASSET_PATH, AUTO_AGGREGATION_ICON, AUTO_POINTS_TOOLTIP, AUTO_POINTS_TOOLTIP_KEPT, AbstractConfigurationStrategy, ActionBarComponent, ActionBarItemComponent, ActionBarModule, ActionBarService, ActionComponent, ActionControlsExtensionService, ActionModule, ActionOutletComponent, ActionService, AggregationPickerComponent, AggregationService, AlarmRealtimeService, AlarmWithChildrenRealtimeService, AlertComponent, AlertDetailsComponent, AlertModule, AlertOutletBase, AlertOutletComponent, AlertService, AlertTextComponent, AppHrefPipe, AppIconComponent, AppStateService, AppSwitcherComponent, AppSwitcherInlineComponent, AppSwitcherService, ApplicationModule, ApplicationPluginStatus, ApplyRangeClassPipe, AssetDefinitionsService, AssetHierarchyService, AssetLinkPipe, AssetPropertyService, AssetTypesRealtimeService, AssetTypesService, AuditLogComponent, AuditLogModule, AuthenticationModule, BASELINE_COLUMNS, BASELINE_ROWS, BackendVersionFactory, BaseColumn, BaseFilteringFormRendererComponent, BooleanFilterMapper, BootstrapComponent, BootstrapModule, BottomDrawerComponent, BottomDrawerRef, BottomDrawerService, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbModule, BreadcrumbOutletComponent, BreadcrumbService, BuiltInActionType, BytesPipe, C8Y_PLUGIN_CONTEXT_PATH, C8Y_PLUGIN_NAME, C8yComponentOutlet, C8yJSONSchema, C8yStepper, C8yStepperButtons, C8yStepperIcon, C8yStepperProgress, C8yTranslateDirective, C8yTranslateModule, C8yTranslatePipe, C8yTranslationCache, C8yTranslationLoader, C8yValidators, CUSTOM, CachedLocaleDictionaryService, CellRendererComponent, CellRendererContext, CellRendererDefDirective, ChangeCurrentUserPasswordService, ChangeIconComponent, ClipboardModule, ClipboardService, ColorInputComponent, ColorService, ColumnDirective, CommonModule, ConditionalTabsOutletComponent, ConfigureCustomColumnComponent, ConfirmModalComponent, ContextRouteComponent, ContextRouteGuard, ContextRouteService, CookieBannerComponent, CopyDashboardDisabledReason, CoreModule, CoreSearchModule, CountdownIntervalComponent, CountdownIntervalModule, CurrentPasswordModalComponent, CustomColumn, CustomTranslateService, CustomTranslateStore, DATA_GRID_CONFIGURATION_CONTEXT, DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER, DATA_GRID_CONFIGURATION_STRATEGY, DEFAULT_INTERVAL_STATE, DEFAULT_INTERVAL_VALUE, DEFAULT_INTERVAL_VALUES, DRAWER_ANIMATION_TIME, DashboardChildActionComponent, DashboardChildChange, DashboardChildComponent, DashboardChildTitleComponent, DashboardComponent, DashboardModule, DataGridComponent, DataGridModule, DataGridService, DatapointLibraryValidationErrors, DatapointSyncService, DateContextQueryParamNames, DateFilterMapper, DateFormatService, DatePickerComponent, DatePickerModule, DatePipe, DateTimePickerComponent, DateTimePickerModule, DefaultValidationDirective, DeviceBootstrapRealtimeService, DeviceService, DeviceStatusComponent, DeviceStatusModule, DismissAlertStrategy, DocsModule, DocsService, DrawerModule, DrawerOutletComponent, DrawerService, DropAreaComponent, DropAreaModule, DropdownDirectionDirective, DropdownFocusTrapDirective, DynamicBulkDetailsResolver, DynamicBulkIIdentifiedResolver, DynamicComponentAlert, DynamicComponentAlertAggregator, DynamicComponentAlertsComponent, DynamicComponentComponent, DynamicComponentErrorStrategy, DynamicComponentModule, DynamicComponentService, DynamicDatapointsResolver, DynamicFormsModule, DynamicManagedObjectResolver, DynamicResolverService, ES_MAX_TIME_MILLISECONDS, EmailsValidatorDirective, EmptyComponent, EmptyStateComponent, EmptyStateContextDirective, EventRealtimeService, ExpandableRowDirective, ExtensionPointForPlugins, ExtensionPointWithoutStateForPlugins, ExtractArrayValidationErrorsPipe, FeatureCacheService, FeedbackFormComponent, FilePickerComponent, FilePickerFormControlComponent, FilePickerFormControlModule, FilePickerModule, FilesService, FilterByPipe, FilterInputComponent, FilterMapperFactory, FilterMapperModule, FilterMapperPipe, FilterMapperService, FilterNonArrayValidationErrorsPipe, FilteringActionType, FilteringFormRendererComponent, FilteringFormRendererContext, FilteringFormRendererDefDirective, ForOfDirective, FormGroupComponent, FormsModule, GENERIC_FILE_TYPE, GLOBAL_CONTEXT_AUTO_REFRESH, GainsightService, GenericFileIconPipe, GeoService, GetGroupIconPipe, GlobalConfigService, GridDataSource, GroupFragment, GroupService, GroupedFilterChips, GuideDocsComponent, GuideHrefDirective, HOOK_ACTION, HOOK_ACTION_BAR, HOOK_BREADCRUMB, HOOK_COMPONENTS, HOOK_CURRENT_APPLICATION, HOOK_CURRENT_TENANT, HOOK_CURRENT_USER, HOOK_DOCS, HOOK_DYNAMIC_PROVIDER_CONFIG, HOOK_NAVIGATOR_NODES, HOOK_OPTIONS, HOOK_PATTERN_MESSAGES, HOOK_PLUGIN, HOOK_PREVIEW, HOOK_QUERY_PARAM, HOOK_QUERY_PARAM_BOTTOM_DRAWER, HOOK_QUERY_PARAM_MODAL, HOOK_ROUTE, HOOK_SEARCH, HOOK_SKIP_APP_KEY_HEADER, HOOK_STEPPER, HOOK_TABS, HOOK_VERSION, HOOK_WIZARD, HeaderBarComponent, HeaderCellRendererDefDirective, HeaderModule, HeaderService, HelpComponent, HelpModule, HighlightComponent, HookProviderTypes, HumanizeAppNamePipe, HumanizePipe, HumanizeValidationMessagePipe, I18nModule, INTERVAL_OPTIONS, IconDirective, IconPanelComponent, IfAllowedDirective, InjectionType, InputGroupEditableComponent, InputGroupListComponent, InputGroupListContainerDirective, InterAppService, IntersectionObserverService, IntervalBasedReload, InventorySearchService, IpRangeInputListComponent, JsonValidationPrettifierDirective, LANGUAGES, LAST_DAY, LAST_HOUR, LAST_MINUTE, LAST_MONTH, LAST_WEEK, LOCALE_PATH, LegacyGridConfigMapperService, LegendFieldWrapper, ListDisplaySwitchComponent, ListDisplaySwitchModule, ListGroupComponent, ListGroupModule, ListItemActionComponent, ListItemBodyComponent, ListItemCheckboxComponent, ListItemCollapseComponent, ListItemComponent, ListItemDragHandleComponent, ListItemFooterComponent, ListItemIconComponent, ListItemRadioComponent, ListItemTimelineComponent, LoadMoreComponent, LoadingComponent, LoadingMessageComponent, MAX_PAGE_SIZE, MESSAGES_CORE_I18N, MOChunkLoaderService, ManagedObjectRealtimeService, ManagedObjectType, MapFunctionPipe, MarkdownToHtmlPipe, MaxValidationDirective, MeasurementRealtimeService, MessageBannerService, MessageDirective, MessagesComponent, MinValidationDirective, MissingTranslationCustomHandler, MoNamePipe, ModalComponent, ModalModule, ModalSelectionMode, ModalService, NEEDED_ROLE_FOR_SETUP, NEW_DASHBOARD_ROUTER_STATE_PROP, NULL_VALUE_PLACEHOLDER, NUMBER_FORMAT_REGEXP, NameTransformPipe, NavigatorBottomModule, NavigatorIconComponent, NavigatorModule, NavigatorNode, NavigatorNodeComponent, NavigatorNodeRoot, NavigatorOutletComponent, NavigatorService, NavigatorTopModule, NewPasswordComponent, NumberPipe, OperationBulkRealtimeService, OperationRealtimeService, OperationResultComponent, OptionsService, OutletDirective, PREVIEW_FEATURE_PROVIDERS, PRODUCT_EXPERIENCE_EVENT_SOURCE, PX_ACTIONS, PX_EVENT_NAME, PackageType, PasswordCheckListComponent, PasswordConfirm, PasswordConfirmModalComponent, PasswordInputComponent, PasswordService, PasswordStrengthCheckerService, PasswordStrengthComponent, PasswordStrengthService, PasswordValidationDirective, PasswordValidationService, PatternMessagesService, Permissions, PhoneValidationDirective, PlatformDetailsService, PluginLoadedPipe, PluginsExportScopes, PluginsLoaderService, PluginsModule, PluginsResolveService, PluginsService, PopoverConfirmComponent, PreviewFeatureButtonComponent, PreviewFeatureShowNotification, PreviewService, ProductExperienceDirective, ProductExperienceModule, ProgressBarComponent, PropertiesListComponent, PropertiesListModule, PropertyValueTransformService, ProviderConfigurationComponent, ProviderConfigurationModule, ProviderConfigurationNodeFactory, ProviderConfigurationRouteFactory, ProviderConfigurationService, ProviderDefinitionsService, PushStatus, PushStatusLabels, QUERY_PARAM_HANDLER_PROVIDERS, QueryParamBottomDrawerFactory, QueryParamBottomDrawerStateService, QueryParamHandlerService, QueryParamModalFactory, QueryParamModalStateService, QuickLinkComponent, QuickLinkModule, RELOAD_QUERY_PARAM, RESOLVING_COMPONENT_WAIT_TIME, RadioFilterMapper, RangeComponent, RangeDirective, RangeDisplayComponent, RangeDisplayModule, RealtimeButtonComponent, RealtimeControlComponent, RealtimeMessage, RealtimeModule, RealtimeService, RealtimeSubjectService, RelativeTimePipe, RequiredInputPlaceholderDirective, ResizableGridComponent, ResolverServerError, RouterModule, RouterService, RouterTabsResolver, SETUP_FINISHED_STEP_ID, SHOW_PREVIEW_FEATURES, SearchComponent, SearchFilters, SearchInputComponent, SearchOutletComponent, SearchResultEmptyComponent, SearchService, SelectComponent, SelectFilterMapper, SelectItemDirective, SelectKeyboardService, SelectLegacyComponent, SelectModalComponent, SelectModalFilterPipe, SelectModalModule, SelectModule, SelectedItemsComponent, SelectedItemsDirective, SendStatus, SendStatusLabels, ServiceRegistry, SetupCompletedComponent, SetupComponent, SetupModule, SetupService, SetupState, SetupStepperFactory, ShortenUserNamePipe, ShouldShowMoPipe, ShowIfFilterPipe, SimpleJsonPathValidatorDirective, SimplifiedAuthService, SkipLinkDirective, SplitViewAlertsComponent, SplitViewComponent, SplitViewDetailsActionsComponent, SplitViewDetailsComponent, SplitViewExtraHeaderComponent, SplitViewFooterComponent, SplitViewHeaderActionsComponent, SplitViewListComponent, SplitViewListItemDirective, SplitViewSelectionService, StateService, Status, StepperModule, StepperOutletComponent, StepperService, Steppers, StringFilterMapper, StringifyObjectPipe, StripHtmlPipe, SupportedApps, TabComponent, TabsModule, TabsOutletComponent, TabsService, TabsetAriaDirective, TenantUiService, TextAreaRowHeightDirective, TextareaAutoresizeDirective, ThemeSwitcherService, TimeIntervalComponent, TimePickerComponent, TimePickerModule, TitleComponent, TitleOutletComponent, TotpChallengeComponent, TotpSetupComponent, TranslateService, TreeNodeCellRendererComponent, TreeNodeColumn, TreeNodeHeaderCellRendererComponent, TypeaheadComponent, TypeaheadFilterMapper, UiSettingsComponent, UiSettingsModule, UniqueInCollectionByPathValidationDirective, UserEditComponent, UserEditModalComponent, UserEngagementsService, UserMenuItemComponent, UserMenuOutletComponent, UserMenuService, UserModule, UserNameInitialsPipe, UserPreferencesConfigurationStrategy, UserPreferencesService, UserPreferencesStorageInventory, UserPreferencesStorageLocal, UserTotpRevokeComponent, UserTotpSetupComponent, VERSION_MODULE_CONFIG, ValidationPattern, VersionListComponent, VersionModule, VersionService, ViewContext, ViewContextServices, VirtualScrollListenerDirective, VirtualScrollWindowDirective, VirtualScrollWindowStrategy, VirtualScrollerWrapperComponent, VisibleControlsPipe, WIDGET_CONFIGURATION_GRID_SIZE, WIDGET_TYPE_VALUES, WILDCARD_SEARCH_FEATURE_KEY, WebSDKVersionFactory, WidgetActionWrapperComponent, WidgetGlobalAutoRefreshService, WidgetTimeContextActionBarPriority, WidgetTimeContextComponent, WidgetTimeContextDateRangeService, WidgetTimeContextMediatorService, WidgetsDashboardComponent, WidgetsDashboardEventService, WizardBodyComponent, WizardComponent, WizardFooterComponent, WizardHeaderComponent, WizardModalService, WizardModule, WizardOutletComponent, WizardService, ZipService, _virtualScrollWindowStrategyFactory, alertOnError, allEntriesAreEqual, asyncValidateArrayElements, colorValidator, deviceAvailabilityIconMap, extraRoutes, fromFactories, fromTrigger, fromTriggerOnce, getActivatedRoute, getAngularLocalesLanguageString, getBasicInputArrayFormFieldConfig, getDictionaryWithTrimmedKeys, getInjectedHooks, gettext, globalAutoRefreshLoading, hookAction, hookActionBar, hookBreadcrumb, hookComponent, hookCurrentApplication, hookCurrentTenant, hookCurrentUser, hookDataGridActionControls, hookDocs, hookDrawer, hookDynamicProviderConfig, hookFilterMapper, hookGeneric, hookNavigator, hookOptions, hookPatternMessages, hookPlugin, hookPreview, hookQueryParam, hookQueryParamBottomDrawer, hookQueryParamModal, hookRoute, hookSearch, hookService, hookStepper, hookTab, hookUserMenu, hookVersion, hookWidget, hookWizard, internalApps, isBinaryFile, isEagerDynamicComponents, isExtensionFactory, isLazyDynamicComponents, isPromise, languagesFactory, loadLocale, localeId, localePathFactory, memoize, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, provideBootstrapMetadata, provideCommonPipes, provideCommonServices, provideDefaultOptionsAppInitializer, provideI18n, provideLanguageSelectorAppInitializer, providePluginsLoaderServiceAppInitializer, provideSkipAppKeyHeader, provideTranslationServiceInstance, ratiosByColumnTypes, removeContextIndicators, removeDuplicatesIds, resolveInjectedFactories, retryWithDelay, runGuardsOnParamsOrReloadChange, scaleWidgetDimensions, simpleJsonPathValidator, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, throttle, toObservable, toObservableOfArrays, tooltips, trimTranslationKey, uniqueInCollectionByPathValidator, validateArrayElements, validateInternationalPhoneNumber, viewContextRoutes, wrapperLegendFieldConfig };
41340
41438
  //# sourceMappingURL=c8y-ngx-components.mjs.map