@c8y/ngx-components 1024.15.1 → 1024.15.13

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 (40) hide show
  1. package/fesm2022/c8y-ngx-components-asset-properties.mjs +2 -2
  2. package/fesm2022/c8y-ngx-components-asset-properties.mjs.map +1 -1
  3. package/fesm2022/{c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-DreEjPAV.mjs → c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-CFZO0ZaS.mjs} +3 -3
  4. package/fesm2022/{c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-DreEjPAV.mjs.map → c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-CFZO0ZaS.mjs.map} +1 -1
  5. package/fesm2022/{c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-B2z2tGM7.mjs → c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-1mnvr3pp.mjs} +2 -2
  6. package/fesm2022/{c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-B2z2tGM7.mjs.map → c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-1mnvr3pp.mjs.map} +1 -1
  7. package/fesm2022/{c8y-ngx-components-computed-asset-properties-last-measurement-config.component-CwWLXBUt.mjs → c8y-ngx-components-computed-asset-properties-last-measurement-config.component-Dq4w0MQH.mjs} +4 -4
  8. package/fesm2022/{c8y-ngx-components-computed-asset-properties-last-measurement-config.component-CwWLXBUt.mjs.map → c8y-ngx-components-computed-asset-properties-last-measurement-config.component-Dq4w0MQH.mjs.map} +1 -1
  9. package/fesm2022/c8y-ngx-components-computed-asset-properties.mjs +1 -1
  10. package/fesm2022/c8y-ngx-components-context-dashboard.mjs +3 -0
  11. package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  12. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +10 -6
  13. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
  14. package/fesm2022/c8y-ngx-components-global-context.mjs +4 -4
  15. package/fesm2022/c8y-ngx-components-global-context.mjs.map +1 -1
  16. package/fesm2022/c8y-ngx-components-icon-selector.mjs +23 -11
  17. package/fesm2022/c8y-ngx-components-icon-selector.mjs.map +1 -1
  18. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +24 -2
  19. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
  20. package/fesm2022/c8y-ngx-components.mjs +39 -9
  21. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  22. package/locales/de.po +19 -15
  23. package/locales/es.po +3 -0
  24. package/locales/fr.po +4 -1
  25. package/locales/ja_JP.po +294 -283
  26. package/locales/ko.po +3 -0
  27. package/locales/locales.pot +3 -0
  28. package/locales/nl.po +3 -0
  29. package/locales/pl.po +3 -0
  30. package/locales/pt_BR.po +3 -0
  31. package/locales/zh_CN.po +3 -0
  32. package/locales/zh_TW.po +3 -0
  33. package/package.json +1 -1
  34. package/types/c8y-ngx-components-context-dashboard.d.ts.map +1 -1
  35. package/types/c8y-ngx-components-icon-selector.d.ts +7 -1
  36. package/types/c8y-ngx-components-icon-selector.d.ts.map +1 -1
  37. package/types/c8y-ngx-components-widgets-implementations-asset-table.d.ts +1 -0
  38. package/types/c8y-ngx-components-widgets-implementations-asset-table.d.ts.map +1 -1
  39. package/types/c8y-ngx-components.d.ts +22 -4
  40. package/types/c8y-ngx-components.d.ts.map +1 -1
@@ -14621,13 +14621,20 @@ class UserMenuService extends ExtensionPointForPlugins {
14621
14621
  /**
14622
14622
  * Returns the current state.
14623
14623
  * @readonly
14624
- * @returns The current set of actions.
14624
+ * @returns The set of items added imperatively via `add`. Items registered
14625
+ * through `hookUserMenu` or an `ExtensionFactory` are not part of this set.
14625
14626
  */
14626
14627
  get state() {
14627
14628
  return this.state$.value;
14628
14629
  }
14629
14630
  /**
14630
- * Adds a new item to the search in the header.
14631
+ * Adds an item to the user menu in the right drawer.
14632
+ *
14633
+ * Prefer `hookUserMenu` for items known at build time. Use this method when the
14634
+ * item is only known at runtime, for example when it depends on a resolved
14635
+ * permission or on an AngularJS service reached through the upgrade bridge.
14636
+ *
14637
+ * Items are ordered by descending `priority`, so a higher `priority` is shown first.
14631
14638
  * @param item The item to add.
14632
14639
  */
14633
14640
  add(item) {
@@ -14635,7 +14642,10 @@ class UserMenuService extends ExtensionPointForPlugins {
14635
14642
  this.emitNewState();
14636
14643
  }
14637
14644
  /**
14638
- * Removes an search from the header.
14645
+ * Removes an item from the user menu in the right drawer.
14646
+ *
14647
+ * Only items previously added via `add` can be removed, and the same object
14648
+ * reference that was passed to `add` must be passed here.
14639
14649
  * @param item The item to remove.
14640
14650
  */
14641
14651
  remove(item) {
@@ -15978,6 +15988,15 @@ class ConfirmModalComponent {
15978
15988
  this.code = this.generateRandomCode();
15979
15989
  }
15980
15990
  }
15991
+ /**
15992
+ * Moves focus to the dialog once it is rendered, landing on the cancel button
15993
+ * (`cdkFocusInitial`) so that keyboard and screen reader users start on the least
15994
+ * destructive action. `ngx-bootstrap` focuses the dialog container itself, which happens
15995
+ * before this, hence focusing when the trap is ready rather than immediately.
15996
+ */
15997
+ ngAfterViewInit() {
15998
+ this.focusTrap?.focusTrap.focusInitialElementWhenReady();
15999
+ }
15981
16000
  get classIcon() {
15982
16001
  return `dlt-c8y-icon-${statusIcons[this.status]}`;
15983
16002
  }
@@ -16006,11 +16025,19 @@ class ConfirmModalComponent {
16006
16025
  return Array.from({ length: 5 }, () => chars.charAt(Math.floor(Math.random() * chars.length))).join('');
16007
16026
  }
16008
16027
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ConfirmModalComponent, deps: [{ token: i1$6.BsModalRef }], target: i0.ɵɵFactoryTarget.Component }); }
16009
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: ConfirmModalComponent, isStandalone: true, selector: "c8y-confirm-modal", inputs: { title: "title", body: "body", confirmOptions: "confirmOptions", status: "status", requireCodeVerification: "requireCodeVerification", labels: "labels" }, ngImport: i0, template: "<div\n class=\"c8y-prompt alert\"\n [ngClass]=\"[classAlert]\"\n data-cy=\"prompt-alert\"\n>\n @if (title) {\n <h3 class=\"m-b-16 d-flex a-i-center\">\n <i\n class=\"dlt-c8y-icon\"\n [ngClass]=\"[classIcon]\"\n ></i>\n <span id=\"modal-title\">{{ title | translate }}</span>\n </h3>\n }\n <div id=\"modal-body\">\n @if (!isHtml(body)) {\n <p class=\"text-break-word m-b-16\">\n {{ body | translate }}\n </p>\n }\n @if (isHtml(body)) {\n <div\n class=\"text-break-word m-b-16\"\n [innerHTML]=\"body | translate\"\n ></div>\n }\n @for (co of confirmOptions | showIfFilter | async | keyvalue; track co) {\n <div class=\"c8y-checkbox plain m-b-8\">\n <label\n class=\"c8y-checkbox\"\n [title]=\"co.value.text | translate\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"co.value.checked\"\n (change)=\"co.value.checked = !co.value.checked\"\n [disabled]=\"confirmOptions[co.value.disabledByKey]?.checked\"\n />\n <span></span>\n <span>{{ co.value.text | translate }}</span>\n </label>\n </div>\n }\n @if (requireCodeVerification) {\n <p class=\"text-break-word m-b-16\">\n <code>{{ code }}</code>\n </p>\n <form (submit)=\"$event.preventDefault()\">\n <div class=\"form-group\">\n <label for=\"confirmString\">\n {{ 'Confirm:' | translate }}\n </label>\n <input\n class=\"form-control\"\n id=\"confirmString\"\n placeholder=\"{{ 'Type here' | translate }}\"\n name=\"confirmString\"\n type=\"text\"\n autocomplete=\"off\"\n [(ngModel)]=\"confirmString\"\n />\n </div>\n </form>\n }\n <ng-content></ng-content>\n </div>\n <div class=\"alert-footer\">\n @if (labels.cancel !== null) {\n <button\n class=\"btn btn-default\"\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n (click)=\"dismiss()\"\n data-cy=\"c8y-confirm-modal--cancel\"\n >\n {{ labels.cancel | translate }}\n </button>\n }\n <button\n class=\"btn btn-primary m-t-xs-8\"\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n (click)=\"close()\"\n data-cy=\"c8y-confirm-modal--ok\"\n [disabled]=\"isOkButtonDisabled\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: ShowIfFilterPipe, name: "showIfFilter" }] }); }
16028
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: ConfirmModalComponent, isStandalone: true, selector: "c8y-confirm-modal", inputs: { title: "title", body: "body", confirmOptions: "confirmOptions", status: "status", requireCodeVerification: "requireCodeVerification", labels: "labels" }, viewQueries: [{ propertyName: "focusTrap", first: true, predicate: CdkTrapFocus, descendants: true }], ngImport: i0, template: "<div\n class=\"c8y-prompt alert\"\n cdkTrapFocus\n [ngClass]=\"[classAlert]\"\n data-cy=\"prompt-alert\"\n>\n @if (title) {\n <h3 class=\"m-b-16 d-flex a-i-center\">\n <i\n class=\"dlt-c8y-icon\"\n [ngClass]=\"[classIcon]\"\n ></i>\n <span id=\"modal-title\">{{ title | translate }}</span>\n </h3>\n }\n <div id=\"modal-body\">\n @if (!isHtml(body)) {\n <p class=\"text-break-word m-b-16\">\n {{ body | translate }}\n </p>\n }\n @if (isHtml(body)) {\n <div\n class=\"text-break-word m-b-16\"\n [innerHTML]=\"body | translate\"\n ></div>\n }\n @for (co of confirmOptions | showIfFilter | async | keyvalue; track co) {\n <div class=\"c8y-checkbox plain m-b-8\">\n <label\n class=\"c8y-checkbox\"\n [title]=\"co.value.text | translate\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"co.value.checked\"\n (change)=\"co.value.checked = !co.value.checked\"\n [disabled]=\"confirmOptions[co.value.disabledByKey]?.checked\"\n />\n <span></span>\n <span>{{ co.value.text | translate }}</span>\n </label>\n </div>\n }\n @if (requireCodeVerification) {\n <p class=\"text-break-word m-b-16\">\n <code>{{ code }}</code>\n </p>\n <form (submit)=\"$event.preventDefault()\">\n <div class=\"form-group\">\n <label for=\"confirmString\">\n {{ 'Confirm:' | translate }}\n </label>\n <input\n class=\"form-control\"\n id=\"confirmString\"\n placeholder=\"{{ 'Type here' | translate }}\"\n name=\"confirmString\"\n type=\"text\"\n autocomplete=\"off\"\n [(ngModel)]=\"confirmString\"\n />\n </div>\n </form>\n }\n <ng-content></ng-content>\n </div>\n <div class=\"alert-footer\">\n @if (labels.cancel !== null) {\n <button\n class=\"btn btn-default\"\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n cdkFocusInitial\n (click)=\"dismiss()\"\n data-cy=\"c8y-confirm-modal--cancel\"\n >\n {{ labels.cancel | translate }}\n </button>\n }\n <button\n class=\"btn btn-primary m-t-xs-8\"\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n (click)=\"close()\"\n data-cy=\"c8y-confirm-modal--ok\"\n [disabled]=\"isOkButtonDisabled\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: ShowIfFilterPipe, name: "showIfFilter" }] }); }
16010
16029
  }
16011
16030
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ConfirmModalComponent, decorators: [{
16012
16031
  type: Component,
16013
- args: [{ selector: 'c8y-confirm-modal', standalone: true, imports: [NgClass, C8yTranslatePipe, AsyncPipe, KeyValuePipe, ShowIfFilterPipe, FormsModule$1], template: "<div\n class=\"c8y-prompt alert\"\n [ngClass]=\"[classAlert]\"\n data-cy=\"prompt-alert\"\n>\n @if (title) {\n <h3 class=\"m-b-16 d-flex a-i-center\">\n <i\n class=\"dlt-c8y-icon\"\n [ngClass]=\"[classIcon]\"\n ></i>\n <span id=\"modal-title\">{{ title | translate }}</span>\n </h3>\n }\n <div id=\"modal-body\">\n @if (!isHtml(body)) {\n <p class=\"text-break-word m-b-16\">\n {{ body | translate }}\n </p>\n }\n @if (isHtml(body)) {\n <div\n class=\"text-break-word m-b-16\"\n [innerHTML]=\"body | translate\"\n ></div>\n }\n @for (co of confirmOptions | showIfFilter | async | keyvalue; track co) {\n <div class=\"c8y-checkbox plain m-b-8\">\n <label\n class=\"c8y-checkbox\"\n [title]=\"co.value.text | translate\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"co.value.checked\"\n (change)=\"co.value.checked = !co.value.checked\"\n [disabled]=\"confirmOptions[co.value.disabledByKey]?.checked\"\n />\n <span></span>\n <span>{{ co.value.text | translate }}</span>\n </label>\n </div>\n }\n @if (requireCodeVerification) {\n <p class=\"text-break-word m-b-16\">\n <code>{{ code }}</code>\n </p>\n <form (submit)=\"$event.preventDefault()\">\n <div class=\"form-group\">\n <label for=\"confirmString\">\n {{ 'Confirm:' | translate }}\n </label>\n <input\n class=\"form-control\"\n id=\"confirmString\"\n placeholder=\"{{ 'Type here' | translate }}\"\n name=\"confirmString\"\n type=\"text\"\n autocomplete=\"off\"\n [(ngModel)]=\"confirmString\"\n />\n </div>\n </form>\n }\n <ng-content></ng-content>\n </div>\n <div class=\"alert-footer\">\n @if (labels.cancel !== null) {\n <button\n class=\"btn btn-default\"\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n (click)=\"dismiss()\"\n data-cy=\"c8y-confirm-modal--cancel\"\n >\n {{ labels.cancel | translate }}\n </button>\n }\n <button\n class=\"btn btn-primary m-t-xs-8\"\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n (click)=\"close()\"\n data-cy=\"c8y-confirm-modal--ok\"\n [disabled]=\"isOkButtonDisabled\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n" }]
16032
+ args: [{ selector: 'c8y-confirm-modal', standalone: true, imports: [
16033
+ NgClass,
16034
+ C8yTranslatePipe,
16035
+ AsyncPipe,
16036
+ KeyValuePipe,
16037
+ ShowIfFilterPipe,
16038
+ FormsModule$1,
16039
+ CdkTrapFocus
16040
+ ], template: "<div\n class=\"c8y-prompt alert\"\n cdkTrapFocus\n [ngClass]=\"[classAlert]\"\n data-cy=\"prompt-alert\"\n>\n @if (title) {\n <h3 class=\"m-b-16 d-flex a-i-center\">\n <i\n class=\"dlt-c8y-icon\"\n [ngClass]=\"[classIcon]\"\n ></i>\n <span id=\"modal-title\">{{ title | translate }}</span>\n </h3>\n }\n <div id=\"modal-body\">\n @if (!isHtml(body)) {\n <p class=\"text-break-word m-b-16\">\n {{ body | translate }}\n </p>\n }\n @if (isHtml(body)) {\n <div\n class=\"text-break-word m-b-16\"\n [innerHTML]=\"body | translate\"\n ></div>\n }\n @for (co of confirmOptions | showIfFilter | async | keyvalue; track co) {\n <div class=\"c8y-checkbox plain m-b-8\">\n <label\n class=\"c8y-checkbox\"\n [title]=\"co.value.text | translate\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"co.value.checked\"\n (change)=\"co.value.checked = !co.value.checked\"\n [disabled]=\"confirmOptions[co.value.disabledByKey]?.checked\"\n />\n <span></span>\n <span>{{ co.value.text | translate }}</span>\n </label>\n </div>\n }\n @if (requireCodeVerification) {\n <p class=\"text-break-word m-b-16\">\n <code>{{ code }}</code>\n </p>\n <form (submit)=\"$event.preventDefault()\">\n <div class=\"form-group\">\n <label for=\"confirmString\">\n {{ 'Confirm:' | translate }}\n </label>\n <input\n class=\"form-control\"\n id=\"confirmString\"\n placeholder=\"{{ 'Type here' | translate }}\"\n name=\"confirmString\"\n type=\"text\"\n autocomplete=\"off\"\n [(ngModel)]=\"confirmString\"\n />\n </div>\n </form>\n }\n <ng-content></ng-content>\n </div>\n <div class=\"alert-footer\">\n @if (labels.cancel !== null) {\n <button\n class=\"btn btn-default\"\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n cdkFocusInitial\n (click)=\"dismiss()\"\n data-cy=\"c8y-confirm-modal--cancel\"\n >\n {{ labels.cancel | translate }}\n </button>\n }\n <button\n class=\"btn btn-primary m-t-xs-8\"\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n (click)=\"close()\"\n data-cy=\"c8y-confirm-modal--ok\"\n [disabled]=\"isOkButtonDisabled\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n" }]
16014
16041
  }], ctorParameters: () => [{ type: i1$6.BsModalRef }], propDecorators: { title: [{
16015
16042
  type: Input
16016
16043
  }], body: [{
@@ -16023,6 +16050,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
16023
16050
  type: Input
16024
16051
  }], labels: [{
16025
16052
  type: Input
16053
+ }], focusTrap: [{
16054
+ type: ViewChild,
16055
+ args: [CdkTrapFocus]
16026
16056
  }] } });
16027
16057
 
16028
16058
  class CookieBannerPreferencesModalComponent {
@@ -36351,7 +36381,7 @@ class DataGridComponent {
36351
36381
  try {
36352
36382
  return matchesFn(route, context);
36353
36383
  }
36354
- catch (e) {
36384
+ catch {
36355
36385
  return false;
36356
36386
  }
36357
36387
  }
@@ -36362,7 +36392,7 @@ class DataGridComponent {
36362
36392
  provide: PRODUCT_EXPERIENCE_EVENT_SOURCE,
36363
36393
  useExisting: forwardRef(() => DataGridComponent)
36364
36394
  }
36365
- ], 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 dropdown\n #ddFilters=\"bs-dropdown\"\n [cdkTrapFocus]=\"ddFilters.isOpen\"\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 dropdown\n #ddConfigureColumns=\"bs-dropdown\"\n [cdkTrapFocus]=\"ddConfigureColumns.isOpen\"\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 dropdown\n #gridHeaderDropdown=\"bs-dropdown\"\n [cdkTrapFocus]=\"gridHeaderDropdown.isOpen\"\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: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { 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" }] }); }
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" }] }); }
36366
36396
  }
36367
36397
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: DataGridComponent, decorators: [{
36368
36398
  type: Component,
@@ -36376,7 +36406,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
36376
36406
  LoadingComponent,
36377
36407
  C8yTranslateDirective,
36378
36408
  BsDropdownModule,
36379
- CdkTrapFocus,
36409
+ DropdownFocusTrapDirective,
36380
36410
  IconDirective,
36381
36411
  PopoverModule,
36382
36412
  ProductExperienceDirective,
@@ -36412,7 +36442,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
36412
36442
  GroupedFilterChips,
36413
36443
  VisibleControlsPipe,
36414
36444
  HumanizePipe
36415
- ], 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 dropdown\n #ddFilters=\"bs-dropdown\"\n [cdkTrapFocus]=\"ddFilters.isOpen\"\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 dropdown\n #ddConfigureColumns=\"bs-dropdown\"\n [cdkTrapFocus]=\"ddConfigureColumns.isOpen\"\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 dropdown\n #gridHeaderDropdown=\"bs-dropdown\"\n [cdkTrapFocus]=\"gridHeaderDropdown.isOpen\"\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" }]
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" }]
36416
36446
  }], ctorParameters: () => [{ type: undefined, decorators: [{
36417
36447
  type: Optional
36418
36448
  }, {