@recursyve/nice-data-filter-kit 14.3.0 → 14.3.1

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 (31) hide show
  1. package/esm2020/lib/components/nice-filter-view/components/advanced-filters/advanced-filters.component.mjs +19 -3
  2. package/esm2020/lib/components/nice-filter-view/components/advanced-filters/advanced-filters.module.mjs +8 -5
  3. package/esm2020/lib/components/nice-filter-view/components/advanced-filters/button/advanced-filters-button.component.mjs +6 -6
  4. package/esm2020/lib/components/nice-filter-view/components/advanced-filters/models/icons.model.mjs +4 -1
  5. package/esm2020/lib/components/nice-filter-view/components/advanced-filters/providers/async-typeahead.provider.mjs +32 -0
  6. package/esm2020/lib/components/nice-filter-view/components/advanced-filters/rule/components/select/select-filter.component.mjs +12 -43
  7. package/esm2020/lib/components/nice-filter-view/components/export-buttons/export-buttons.component.mjs +10 -7
  8. package/esm2020/lib/components/nice-filter-view/directives/query-params.directive.mjs +17 -10
  9. package/esm2020/lib/components/nice-filter-view/nice-base-filter-view.component.mjs +46 -12
  10. package/esm2020/lib/directive/selectable-list/providers/selectable-list-content.service.mjs +11 -1
  11. package/esm2020/lib/directive/selectable-list/selectable-list-checkbox.directive.mjs +10 -2
  12. package/esm2020/lib/directive/selectable-list/selectable-list.directive.mjs +55 -12
  13. package/esm2020/lib/directive/selectable-list/store/selectable-list-state.service.mjs +45 -16
  14. package/esm2020/lib/directive/selectable-list/store/selectable-list.service.mjs +10 -6
  15. package/fesm2015/recursyve-nice-data-filter-kit.mjs +248 -103
  16. package/fesm2015/recursyve-nice-data-filter-kit.mjs.map +1 -1
  17. package/fesm2020/recursyve-nice-data-filter-kit.mjs +243 -99
  18. package/fesm2020/recursyve-nice-data-filter-kit.mjs.map +1 -1
  19. package/lib/components/nice-filter-view/components/advanced-filters/advanced-filters.module.d.ts +1 -1
  20. package/lib/components/nice-filter-view/components/advanced-filters/button/advanced-filters-button.component.d.ts +3 -3
  21. package/lib/components/nice-filter-view/components/advanced-filters/models/icons.model.d.ts +1 -0
  22. package/lib/components/nice-filter-view/components/advanced-filters/providers/async-typeahead.provider.d.ts +18 -0
  23. package/lib/components/nice-filter-view/components/advanced-filters/rule/components/select/select-filter.component.d.ts +3 -11
  24. package/lib/components/nice-filter-view/components/export-buttons/export-buttons.component.d.ts +2 -1
  25. package/lib/components/nice-filter-view/directives/query-params.directive.d.ts +2 -1
  26. package/lib/components/nice-filter-view/nice-base-filter-view.component.d.ts +7 -0
  27. package/lib/directive/selectable-list/providers/selectable-list-content.service.d.ts +5 -0
  28. package/lib/directive/selectable-list/selectable-list.directive.d.ts +13 -4
  29. package/lib/directive/selectable-list/store/selectable-list-state.service.d.ts +12 -2
  30. package/lib/directive/selectable-list/store/selectable-list.service.d.ts +5 -2
  31. package/package.json +1 -1
@@ -2,11 +2,11 @@ import { plainToInstance } from 'class-transformer';
2
2
  import { map, takeUntil, debounceTime, switchMap, distinctUntilChanged } from 'rxjs/operators';
3
3
  import { HttpParams } from '@angular/common/http';
4
4
  import * as i5 from '@recursyve/nice-ui-kit.v2';
5
- import { isNullOrUndefined, ObjectUtils, FileUtils, ArrayUtils, ExportBottomSheetComponent, NiceLoadingSpinnerModule, NiceTypeaheadModule, NiceExportBottomSheetModule } from '@recursyve/nice-ui-kit.v2';
5
+ import { isNullOrUndefined, ObjectUtils, FileUtils, ArrayUtils, ExportBottomSheetComponent, NiceLoadingSpinnerModule, NiceTypeaheadModule, NiceExportBottomSheetModule, NiceAsyncTypeaheadProvider, NICE_ASYNC_TYPEAHEAD_PROVIDER, NiceAsyncTypeaheadModule } from '@recursyve/nice-ui-kit.v2';
6
6
  import * as i0 from '@angular/core';
7
7
  import { Directive, Input, NgModule, Injectable, Inject, InjectionToken, Optional, Pipe, EventEmitter, Component, ViewEncapsulation, ChangeDetectionStrategy, Output, HostListener, forwardRef, TemplateRef, ContentChild, ContentChildren, ViewChild, QueryList } from '@angular/core';
8
8
  import { Store, StoreConfig, Query, arrayAdd, arrayUpsert, arrayRemove, EntityStore, QueryEntity, EntityActions } from '@datorama/akita';
9
- import { combineLatest, Subject, firstValueFrom, of, startWith, tap } from 'rxjs';
9
+ import { combineLatest, Subject, firstValueFrom, of, lastValueFrom, startWith, tap, distinct, take } from 'rxjs';
10
10
  import { __decorate, __metadata } from 'tslib';
11
11
  import * as i2 from '@angular/router';
12
12
  import { RouterModule } from '@angular/router';
@@ -3219,6 +3219,8 @@ AdvancedFiltersUtils.doubleInputOperators = [
3219
3219
  FilterOperatorTypes.NotBetween
3220
3220
  ];
3221
3221
 
3222
+ const ADVANCED_FILTER_ICONS = new InjectionToken("advanced_filter_icons");
3223
+
3222
3224
  class NiceFilterGroupIconPipe {
3223
3225
  constructor(service) {
3224
3226
  this.service = service;
@@ -3371,20 +3373,18 @@ class NiceAdvancedFiltersButtonComponent {
3371
3373
  this.service.updateSubState("showAdvancedFilters", true);
3372
3374
  }
3373
3375
  }
3374
- NiceAdvancedFiltersButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedFiltersButtonComponent, deps: [{ token: FILTER_VIEW_ICONS, optional: true }, { token: NiceFilterViewQuery }, { token: NiceFilterViewService }], target: i0.ɵɵFactoryTarget.Component });
3375
- NiceAdvancedFiltersButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.3", type: NiceAdvancedFiltersButtonComponent, selector: "nice-advanced-filters-button", ngImport: i0, template: "<div class=\"relative\">\n <ng-container *ngIf=\"(hasParameters$ | async) && (shouldShowAdvancedFilters$ | async) !== true\">\n <div class=\"absolute top-2 right-2 w-1 h-1 rounded bg-accent\"></div>\n\n <button mat-icon-button (click)=\"clickToggleShowAdvancedFilters()\">\n <mat-icon [svgIcon]=\"icons.queryBuilder.svgIcon\">{{ icons.queryBuilder.matIcon }}</mat-icon>\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"shouldShowAdvancedFilters$ | async\">\n <button mat-icon-button (click)=\"clickToggleShowAdvancedFilters()\">\n <mat-icon [svgIcon]=\"icons.close.svgIcon\">{{ icons.close.matIcon }}</mat-icon>\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"(hasParameters$ | async) !== true && (shouldShowAdvancedFilters$ | async) !== true\">\n <button mat-icon-button niceAdvancedFiltersTrigger (advancedFilterSelected)=\"onSelectedFilter($event)\">\n <mat-icon>filter_list</mat-icon>\n </button>\n </ng-container>\n</div>\n", styles: ["nice-advanced-filters-button{width:40px;height:40px}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: AdvancedFiltersTriggerDirective, selector: "[niceAdvancedFiltersTrigger]", inputs: ["position"], outputs: ["advancedFilterSelected"], exportAs: ["niceAdvancedFiltersTrigger"] }, { kind: "pipe", type: i2$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3376
+ NiceAdvancedFiltersButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedFiltersButtonComponent, deps: [{ token: ADVANCED_FILTER_ICONS, optional: true }, { token: NiceFilterViewQuery }, { token: NiceFilterViewService }], target: i0.ɵɵFactoryTarget.Component });
3377
+ NiceAdvancedFiltersButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.3", type: NiceAdvancedFiltersButtonComponent, selector: "nice-advanced-filters-button", ngImport: i0, template: "<div class=\"relative\">\n <ng-container *ngIf=\"(hasParameters$ | async) && (shouldShowAdvancedFilters$ | async) !== true\">\n <div class=\"absolute top-2 right-2 w-1 h-1 rounded bg-accent\"></div>\n\n <button mat-icon-button (click)=\"clickToggleShowAdvancedFilters()\">\n <mat-icon [svgIcon]=\"icons.queryBuilder.svgIcon\">{{ icons.queryBuilder.matIcon }}</mat-icon>\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"shouldShowAdvancedFilters$ | async\">\n <button mat-icon-button (click)=\"clickToggleShowAdvancedFilters()\">\n <mat-icon [svgIcon]=\"icons.close.svgIcon\">{{ icons.close.matIcon }}</mat-icon>\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"(hasParameters$ | async) !== true && (shouldShowAdvancedFilters$ | async) !== true\">\n <button mat-icon-button niceAdvancedFiltersTrigger (advancedFilterSelected)=\"onSelectedFilter($event)\">\n <mat-icon [svgIcon]=\"icons.queryBuilder.svgIcon\">{{ icons.queryBuilder.matIcon }}</mat-icon>\n </button>\n </ng-container>\n</div>\n", styles: ["nice-advanced-filters-button{width:40px;height:40px}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: AdvancedFiltersTriggerDirective, selector: "[niceAdvancedFiltersTrigger]", inputs: ["position"], outputs: ["advancedFilterSelected"], exportAs: ["niceAdvancedFiltersTrigger"] }, { kind: "pipe", type: i2$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3376
3378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedFiltersButtonComponent, decorators: [{
3377
3379
  type: Component,
3378
- args: [{ selector: "nice-advanced-filters-button", encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"relative\">\n <ng-container *ngIf=\"(hasParameters$ | async) && (shouldShowAdvancedFilters$ | async) !== true\">\n <div class=\"absolute top-2 right-2 w-1 h-1 rounded bg-accent\"></div>\n\n <button mat-icon-button (click)=\"clickToggleShowAdvancedFilters()\">\n <mat-icon [svgIcon]=\"icons.queryBuilder.svgIcon\">{{ icons.queryBuilder.matIcon }}</mat-icon>\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"shouldShowAdvancedFilters$ | async\">\n <button mat-icon-button (click)=\"clickToggleShowAdvancedFilters()\">\n <mat-icon [svgIcon]=\"icons.close.svgIcon\">{{ icons.close.matIcon }}</mat-icon>\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"(hasParameters$ | async) !== true && (shouldShowAdvancedFilters$ | async) !== true\">\n <button mat-icon-button niceAdvancedFiltersTrigger (advancedFilterSelected)=\"onSelectedFilter($event)\">\n <mat-icon>filter_list</mat-icon>\n </button>\n </ng-container>\n</div>\n", styles: ["nice-advanced-filters-button{width:40px;height:40px}\n"] }]
3380
+ args: [{ selector: "nice-advanced-filters-button", encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"relative\">\n <ng-container *ngIf=\"(hasParameters$ | async) && (shouldShowAdvancedFilters$ | async) !== true\">\n <div class=\"absolute top-2 right-2 w-1 h-1 rounded bg-accent\"></div>\n\n <button mat-icon-button (click)=\"clickToggleShowAdvancedFilters()\">\n <mat-icon [svgIcon]=\"icons.queryBuilder.svgIcon\">{{ icons.queryBuilder.matIcon }}</mat-icon>\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"shouldShowAdvancedFilters$ | async\">\n <button mat-icon-button (click)=\"clickToggleShowAdvancedFilters()\">\n <mat-icon [svgIcon]=\"icons.close.svgIcon\">{{ icons.close.matIcon }}</mat-icon>\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"(hasParameters$ | async) !== true && (shouldShowAdvancedFilters$ | async) !== true\">\n <button mat-icon-button niceAdvancedFiltersTrigger (advancedFilterSelected)=\"onSelectedFilter($event)\">\n <mat-icon [svgIcon]=\"icons.queryBuilder.svgIcon\">{{ icons.queryBuilder.matIcon }}</mat-icon>\n </button>\n </ng-container>\n</div>\n", styles: ["nice-advanced-filters-button{width:40px;height:40px}\n"] }]
3379
3381
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
3380
3382
  type: Optional
3381
3383
  }, {
3382
3384
  type: Inject,
3383
- args: [FILTER_VIEW_ICONS]
3385
+ args: [ADVANCED_FILTER_ICONS]
3384
3386
  }] }, { type: NiceFilterViewQuery }, { type: NiceFilterViewService }]; } });
3385
3387
 
3386
- const ADVANCED_FILTER_ICONS = new InjectionToken("advanced_filter_icons");
3387
-
3388
3388
  class FilterFormValues {
3389
3389
  }
3390
3390
  __decorate([
@@ -3508,6 +3508,32 @@ __decorate([
3508
3508
  __metadata("design:type", String)
3509
3509
  ], AdvancedFiltersForm.prototype, "condition", void 0);
3510
3510
 
3511
+ class AdvancedFiltersAsyncTypeaheadProvider extends NiceAsyncTypeaheadProvider {
3512
+ constructor(filterService) {
3513
+ super();
3514
+ this.filterService = filterService;
3515
+ this.resource = "advancedFilter";
3516
+ }
3517
+ getById(id, options) {
3518
+ return lastValueFrom(this.filterService.searchFilterResourceValue(options.filterConfig, id));
3519
+ }
3520
+ async search(searchQuery, page, options) {
3521
+ const res = await lastValueFrom(this.filterService.searchFilterValue(options.filterConfig, searchQuery));
3522
+ return {
3523
+ items: res,
3524
+ nextPage: null
3525
+ };
3526
+ }
3527
+ format(item) {
3528
+ return item.name;
3529
+ }
3530
+ }
3531
+ AdvancedFiltersAsyncTypeaheadProvider.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: AdvancedFiltersAsyncTypeaheadProvider, deps: [{ token: NiceFilterService }], target: i0.ɵɵFactoryTarget.Injectable });
3532
+ AdvancedFiltersAsyncTypeaheadProvider.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: AdvancedFiltersAsyncTypeaheadProvider });
3533
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: AdvancedFiltersAsyncTypeaheadProvider, decorators: [{
3534
+ type: Injectable
3535
+ }], ctorParameters: function () { return [{ type: NiceFilterService }]; } });
3536
+
3511
3537
  class FilterComponent {
3512
3538
  constructor() {
3513
3539
  this.propagateChanges = (_) => { };
@@ -3610,26 +3636,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImpor
3610
3636
  }] } });
3611
3637
 
3612
3638
  class NiceAdvancedSelectFilterComponent extends FilterComponent {
3613
- constructor(filterService) {
3614
- super();
3615
- this.filterService = filterService;
3639
+ constructor() {
3640
+ super(...arguments);
3616
3641
  this.values = [];
3617
- this.search$ = new Subject();
3618
3642
  }
3619
3643
  async ngOnInit() {
3620
3644
  if (!this.filterConfig.lazyLoading) {
3621
3645
  this.values = this.filterConfig.values;
3622
3646
  }
3623
- this.searchSub$ = this.search$
3624
- .pipe(debounceTime(300), switchMap(value => {
3625
- if (this.filterConfig.lazyLoading) {
3626
- return this.filterService.searchFilterValue(this.filterConfig, value);
3627
- }
3628
- return of(this.filterConfig.values);
3629
- }))
3630
- .subscribe(values => {
3631
- this.values = values;
3632
- });
3633
3647
  }
3634
3648
  ngOnChanges(changes) {
3635
3649
  if ("filterConfig" in changes) {
@@ -3641,34 +3655,21 @@ class NiceAdvancedSelectFilterComponent extends FilterComponent {
3641
3655
  }
3642
3656
  }
3643
3657
  }
3644
- async searchValue() {
3645
- if (this.value && !this.values.find(v => v.id === this.value)) {
3646
- const value = await this.filterService
3647
- .searchFilterResourceValue(this.filterConfig, this.value)
3648
- .toPromise();
3649
- this.values = [...this.values, value];
3650
- }
3651
- }
3652
3658
  onValueChange(value) {
3653
3659
  super.onValueChange(value);
3654
- this.searchValue();
3655
- }
3656
- ngOnDestroy() {
3657
- this.searchSub$.unsubscribe();
3658
3660
  }
3659
3661
  writeValue(value) {
3660
3662
  super.writeValue(value);
3661
- this.searchValue();
3662
3663
  }
3663
3664
  }
3664
- NiceAdvancedSelectFilterComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedSelectFilterComponent, deps: [{ token: NiceFilterService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3665
+ NiceAdvancedSelectFilterComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedSelectFilterComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3665
3666
  NiceAdvancedSelectFilterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.3", type: NiceAdvancedSelectFilterComponent, selector: "nice-advanced-select-filter", inputs: { filterConfig: "filterConfig" }, providers: [
3666
3667
  {
3667
3668
  provide: NG_VALUE_ACCESSOR,
3668
3669
  useExisting: forwardRef(() => NiceAdvancedSelectFilterComponent),
3669
3670
  multi: true
3670
3671
  }
3671
- ], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<mat-form-field appearance=\"outline\" class=\"flex-auto\">\n <nice-typeahead *ngIf=\"!filterConfig.lazyLoading\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n [items]=\"values\"\n bindValue=\"id\"\n bindLabel=\"name\"\n ></nice-typeahead>\n\n <nice-typeahead *ngIf=\"filterConfig.lazyLoading\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n [items]=\"values\"\n [typeahead]=\"search$\"\n bindValue=\"id\"\n bindLabel=\"name\"\n ></nice-typeahead>\n</mat-form-field>\n", dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.NiceTypeaheadComponent, selector: "nice-typeahead", inputs: ["items", "labelFormatFn", "required", "disabled", "placeholder", "emptyPlaceholder", "allowNotFoundItems", "panelClass", "bindValue", "bindLabel", "typeahead", "page$", "loading", "loadingPage", "searchFn", "optionTemplate"], outputs: ["change"] }], encapsulation: i0.ViewEncapsulation.None });
3672
+ ], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<mat-form-field appearance=\"outline\" class=\"flex-auto\">\n <nice-typeahead\n *ngIf=\"!filterConfig.lazyLoading\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n [items]=\"values\"\n bindValue=\"id\"\n bindLabel=\"name\"\n ></nice-typeahead>\n\n <nice-async-typeahead\n *ngIf=\"filterConfig.lazyLoading\"\n resource=\"advancedFilter\"\n [searchOptions]=\"{ filterConfig }\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n ></nice-async-typeahead>\n</mat-form-field>\n", dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.NiceTypeaheadComponent, selector: "nice-typeahead", inputs: ["items", "labelFormatFn", "required", "disabled", "placeholder", "emptyPlaceholder", "allowNotFoundItems", "panelClass", "bindValue", "bindLabel", "typeahead", "page$", "loading", "loadingPage", "searchFn", "optionTemplate"], outputs: ["change"] }, { kind: "component", type: i5.NiceAsyncTypeaheadComponent, selector: "nice-async-typeahead", inputs: ["resource", "searchOptions", "preloadResource", "allowNotFoundItems", "panelClass", "bindValue", "bindLabel", "placeholder", "emptyPlaceholder", "optionTemplate", "filterFn", "labelFormatFn", "disabled", "value", "required"], outputs: ["entityRemoved", "selected"] }], encapsulation: i0.ViewEncapsulation.None });
3672
3673
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedSelectFilterComponent, decorators: [{
3673
3674
  type: Component,
3674
3675
  args: [{ selector: "nice-advanced-select-filter", encapsulation: ViewEncapsulation.None, providers: [
@@ -3677,10 +3678,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImpor
3677
3678
  useExisting: forwardRef(() => NiceAdvancedSelectFilterComponent),
3678
3679
  multi: true
3679
3680
  }
3680
- ], template: "<mat-form-field appearance=\"outline\" class=\"flex-auto\">\n <nice-typeahead *ngIf=\"!filterConfig.lazyLoading\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n [items]=\"values\"\n bindValue=\"id\"\n bindLabel=\"name\"\n ></nice-typeahead>\n\n <nice-typeahead *ngIf=\"filterConfig.lazyLoading\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n [items]=\"values\"\n [typeahead]=\"search$\"\n bindValue=\"id\"\n bindLabel=\"name\"\n ></nice-typeahead>\n</mat-form-field>\n" }]
3681
- }], ctorParameters: function () { return [{ type: NiceFilterService, decorators: [{
3682
- type: Optional
3683
- }] }]; }, propDecorators: { filterConfig: [{
3681
+ ], template: "<mat-form-field appearance=\"outline\" class=\"flex-auto\">\n <nice-typeahead\n *ngIf=\"!filterConfig.lazyLoading\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n [items]=\"values\"\n bindValue=\"id\"\n bindLabel=\"name\"\n ></nice-typeahead>\n\n <nice-async-typeahead\n *ngIf=\"filterConfig.lazyLoading\"\n resource=\"advancedFilter\"\n [searchOptions]=\"{ filterConfig }\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n ></nice-async-typeahead>\n</mat-form-field>\n" }]
3682
+ }], propDecorators: { filterConfig: [{
3684
3683
  type: Input
3685
3684
  }] } });
3686
3685
 
@@ -3791,10 +3790,24 @@ class NiceAdvancedFiltersComponent {
3791
3790
  }
3792
3791
  }
3793
3792
  NiceAdvancedFiltersComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedFiltersComponent, deps: [{ token: ADVANCED_FILTER_ICONS, optional: true }, { token: i1$3.GeneratedFormGroup }, { token: NiceFilterViewQuery }, { token: NiceFilterViewService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3794
- NiceAdvancedFiltersComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.3", type: NiceAdvancedFiltersComponent, selector: "nice-advanced-filters", providers: [NgxFormGeneratorProvider.forFeature([AdvancedFiltersForm])], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" [formGroup]=\"formGroup\">\n <div class=\"advanced-filter-title\">{{ \"components.nice_advanced_filters.title\" | translate }}</div>\n\n <div class=\"flex flex-row gap-12\">\n <div class=\"advanced-filter-condition\">{{ \"components.nice_advanced_filters.conditions.should_match\" | translate }}</div>\n\n <mat-radio-group formControlName=\"condition\">\n <mat-radio-button value=\"and\"><span class=\"ml-4 mr-8\">{{ \"components.nice_advanced_filters.conditions.every\" | translate }}</span></mat-radio-button>\n <mat-radio-button value=\"or\"><span class=\"ml-4 mr-8\">{{ \"components.nice_advanced_filters.conditions.some\" | translate }}</span></mat-radio-button>\n </mat-radio-group>\n </div>\n\n <div class=\"flex flex-col gap-4\" formArrayName=\"rules\" *ngFor=\"let _ of rulesFormArray.controls; let i = index\">\n <nice-advanced-rule [filterConfigs]=\"config$ | async\" [formGroupName]=\"i\" (remove)=\"onClickDeleteRule(i)\"></nice-advanced-rule>\n </div>\n\n <div>\n <button class=\"add-condition\" mat-stroked-button color=\"accent\" niceAdvancedFiltersTrigger position=\"topRight\" (advancedFilterSelected)=\"onClickAddRule($event)\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.add.svgIcon\">{{ icons.add.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.add_condition\" | translate }}</div>\n </div>\n </button>\n </div>\n\n <div class=\"flex gap-6 justify-end pt-4\">\n <button class=\"close-button\" mat-button color=\"accent\" (click)=\"onClose()\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.close.svgIcon\">{{ icons.close.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.close\" | translate }}</div>\n </div>\n </button>\n\n <button class=\"refresh-button\" mat-flat-button color=\"accent\" (click)=\"onRefresh()\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.refresh.svgIcon\">{{ icons.refresh.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.refresh\" | translate }}</div>\n </div>\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: i3$3.MatRadioGroup, selector: "mat-radio-group", exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$3.MatRadioButton, selector: "mat-radio-button", inputs: ["disableRipple", "tabIndex"], exportAs: ["matRadioButton"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: NiceAdvancedRuleComponent, selector: "nice-advanced-rule", inputs: ["filterConfigs"], outputs: ["remove"] }, { kind: "directive", type: AdvancedFiltersTriggerDirective, selector: "[niceAdvancedFiltersTrigger]", inputs: ["position"], outputs: ["advancedFilterSelected"], exportAs: ["niceAdvancedFiltersTrigger"] }, { kind: "pipe", type: i2$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3793
+ NiceAdvancedFiltersComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.3", type: NiceAdvancedFiltersComponent, selector: "nice-advanced-filters", providers: [
3794
+ NgxFormGeneratorProvider.forFeature([AdvancedFiltersForm]),
3795
+ {
3796
+ provide: NICE_ASYNC_TYPEAHEAD_PROVIDER,
3797
+ useClass: AdvancedFiltersAsyncTypeaheadProvider,
3798
+ multi: true
3799
+ }
3800
+ ], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" [formGroup]=\"formGroup\">\n <div class=\"advanced-filter-title\">{{ \"components.nice_advanced_filters.title\" | translate }}</div>\n\n <div class=\"flex flex-row gap-12\">\n <div class=\"advanced-filter-condition\">{{ \"components.nice_advanced_filters.conditions.should_match\" | translate }}</div>\n\n <mat-radio-group formControlName=\"condition\">\n <mat-radio-button value=\"and\"><span class=\"ml-4 mr-8\">{{ \"components.nice_advanced_filters.conditions.every\" | translate }}</span></mat-radio-button>\n <mat-radio-button value=\"or\"><span class=\"ml-4 mr-8\">{{ \"components.nice_advanced_filters.conditions.some\" | translate }}</span></mat-radio-button>\n </mat-radio-group>\n </div>\n\n <div class=\"flex flex-col gap-4\" formArrayName=\"rules\" *ngFor=\"let _ of rulesFormArray.controls; let i = index\">\n <nice-advanced-rule [filterConfigs]=\"config$ | async\" [formGroupName]=\"i\" (remove)=\"onClickDeleteRule(i)\"></nice-advanced-rule>\n </div>\n\n <div>\n <button class=\"add-condition\" mat-stroked-button color=\"accent\" niceAdvancedFiltersTrigger position=\"topRight\" (advancedFilterSelected)=\"onClickAddRule($event)\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.add.svgIcon\">{{ icons.add.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.add_condition\" | translate }}</div>\n </div>\n </button>\n </div>\n\n <div class=\"flex gap-6 justify-end pt-4\">\n <button class=\"close-button\" mat-button color=\"accent\" (click)=\"onClose()\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.close.svgIcon\">{{ icons.close.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.close\" | translate }}</div>\n </div>\n </button>\n\n <button class=\"refresh-button\" mat-flat-button color=\"accent\" (click)=\"onRefresh()\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.refresh.svgIcon\">{{ icons.refresh.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.refresh\" | translate }}</div>\n </div>\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: i3$3.MatRadioGroup, selector: "mat-radio-group", exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$3.MatRadioButton, selector: "mat-radio-button", inputs: ["disableRipple", "tabIndex"], exportAs: ["matRadioButton"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: NiceAdvancedRuleComponent, selector: "nice-advanced-rule", inputs: ["filterConfigs"], outputs: ["remove"] }, { kind: "directive", type: AdvancedFiltersTriggerDirective, selector: "[niceAdvancedFiltersTrigger]", inputs: ["position"], outputs: ["advancedFilterSelected"], exportAs: ["niceAdvancedFiltersTrigger"] }, { kind: "pipe", type: i2$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3795
3801
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedFiltersComponent, decorators: [{
3796
3802
  type: Component,
3797
- args: [{ selector: "nice-advanced-filters", encapsulation: ViewEncapsulation.None, providers: [NgxFormGeneratorProvider.forFeature([AdvancedFiltersForm])], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex flex-col gap-4\" [formGroup]=\"formGroup\">\n <div class=\"advanced-filter-title\">{{ \"components.nice_advanced_filters.title\" | translate }}</div>\n\n <div class=\"flex flex-row gap-12\">\n <div class=\"advanced-filter-condition\">{{ \"components.nice_advanced_filters.conditions.should_match\" | translate }}</div>\n\n <mat-radio-group formControlName=\"condition\">\n <mat-radio-button value=\"and\"><span class=\"ml-4 mr-8\">{{ \"components.nice_advanced_filters.conditions.every\" | translate }}</span></mat-radio-button>\n <mat-radio-button value=\"or\"><span class=\"ml-4 mr-8\">{{ \"components.nice_advanced_filters.conditions.some\" | translate }}</span></mat-radio-button>\n </mat-radio-group>\n </div>\n\n <div class=\"flex flex-col gap-4\" formArrayName=\"rules\" *ngFor=\"let _ of rulesFormArray.controls; let i = index\">\n <nice-advanced-rule [filterConfigs]=\"config$ | async\" [formGroupName]=\"i\" (remove)=\"onClickDeleteRule(i)\"></nice-advanced-rule>\n </div>\n\n <div>\n <button class=\"add-condition\" mat-stroked-button color=\"accent\" niceAdvancedFiltersTrigger position=\"topRight\" (advancedFilterSelected)=\"onClickAddRule($event)\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.add.svgIcon\">{{ icons.add.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.add_condition\" | translate }}</div>\n </div>\n </button>\n </div>\n\n <div class=\"flex gap-6 justify-end pt-4\">\n <button class=\"close-button\" mat-button color=\"accent\" (click)=\"onClose()\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.close.svgIcon\">{{ icons.close.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.close\" | translate }}</div>\n </div>\n </button>\n\n <button class=\"refresh-button\" mat-flat-button color=\"accent\" (click)=\"onRefresh()\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.refresh.svgIcon\">{{ icons.refresh.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.refresh\" | translate }}</div>\n </div>\n </button>\n </div>\n</div>\n" }]
3803
+ args: [{ selector: "nice-advanced-filters", encapsulation: ViewEncapsulation.None, providers: [
3804
+ NgxFormGeneratorProvider.forFeature([AdvancedFiltersForm]),
3805
+ {
3806
+ provide: NICE_ASYNC_TYPEAHEAD_PROVIDER,
3807
+ useClass: AdvancedFiltersAsyncTypeaheadProvider,
3808
+ multi: true
3809
+ }
3810
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex flex-col gap-4\" [formGroup]=\"formGroup\">\n <div class=\"advanced-filter-title\">{{ \"components.nice_advanced_filters.title\" | translate }}</div>\n\n <div class=\"flex flex-row gap-12\">\n <div class=\"advanced-filter-condition\">{{ \"components.nice_advanced_filters.conditions.should_match\" | translate }}</div>\n\n <mat-radio-group formControlName=\"condition\">\n <mat-radio-button value=\"and\"><span class=\"ml-4 mr-8\">{{ \"components.nice_advanced_filters.conditions.every\" | translate }}</span></mat-radio-button>\n <mat-radio-button value=\"or\"><span class=\"ml-4 mr-8\">{{ \"components.nice_advanced_filters.conditions.some\" | translate }}</span></mat-radio-button>\n </mat-radio-group>\n </div>\n\n <div class=\"flex flex-col gap-4\" formArrayName=\"rules\" *ngFor=\"let _ of rulesFormArray.controls; let i = index\">\n <nice-advanced-rule [filterConfigs]=\"config$ | async\" [formGroupName]=\"i\" (remove)=\"onClickDeleteRule(i)\"></nice-advanced-rule>\n </div>\n\n <div>\n <button class=\"add-condition\" mat-stroked-button color=\"accent\" niceAdvancedFiltersTrigger position=\"topRight\" (advancedFilterSelected)=\"onClickAddRule($event)\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.add.svgIcon\">{{ icons.add.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.add_condition\" | translate }}</div>\n </div>\n </button>\n </div>\n\n <div class=\"flex gap-6 justify-end pt-4\">\n <button class=\"close-button\" mat-button color=\"accent\" (click)=\"onClose()\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.close.svgIcon\">{{ icons.close.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.close\" | translate }}</div>\n </div>\n </button>\n\n <button class=\"refresh-button\" mat-flat-button color=\"accent\" (click)=\"onRefresh()\">\n <div class=\"flex items-center gap-4\">\n <mat-icon [svgIcon]=\"icons.refresh.svgIcon\">{{ icons.refresh.matIcon }}</mat-icon>\n\n <div>{{ \"components.nice_advanced_filters.refresh\" | translate }}</div>\n </div>\n </button>\n </div>\n</div>\n" }]
3798
3811
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
3799
3812
  type: Optional
3800
3813
  }, {
@@ -3820,6 +3833,9 @@ const defaultIcons = {
3820
3833
  },
3821
3834
  datePicker: {
3822
3835
  matIcon: "today"
3836
+ },
3837
+ queryBuilder: {
3838
+ matIcon: "filter_list"
3823
3839
  }
3824
3840
  };
3825
3841
 
@@ -3872,7 +3888,8 @@ NiceAdvancedFiltersModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0
3872
3888
  TranslateModule,
3873
3889
  MatDatepickerModule,
3874
3890
  NiceTypeaheadModule,
3875
- NgxMaskModule], exports: [NiceAdvancedFiltersComponent, NiceAdvancedFiltersButtonComponent, AdvancedFiltersTriggerDirective] });
3891
+ NgxMaskModule,
3892
+ NiceAsyncTypeaheadModule], exports: [NiceAdvancedFiltersComponent, NiceAdvancedFiltersButtonComponent, AdvancedFiltersTriggerDirective] });
3876
3893
  NiceAdvancedFiltersModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedFiltersModule, imports: [CommonModule,
3877
3894
  ReactiveFormsModule,
3878
3895
  MatRadioModule,
@@ -3891,7 +3908,8 @@ NiceAdvancedFiltersModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0
3891
3908
  TranslateModule,
3892
3909
  MatDatepickerModule,
3893
3910
  NiceTypeaheadModule,
3894
- NgxMaskModule] });
3911
+ NgxMaskModule,
3912
+ NiceAsyncTypeaheadModule] });
3895
3913
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceAdvancedFiltersModule, decorators: [{
3896
3914
  type: NgModule,
3897
3915
  args: [{
@@ -3914,7 +3932,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImpor
3914
3932
  TranslateModule,
3915
3933
  MatDatepickerModule,
3916
3934
  NiceTypeaheadModule,
3917
- NgxMaskModule
3935
+ NgxMaskModule,
3936
+ NiceAsyncTypeaheadModule
3918
3937
  ],
3919
3938
  declarations: [
3920
3939
  NiceAdvancedFiltersComponent,
@@ -3971,6 +3990,7 @@ class NiceFilterExportButtonsComponent {
3971
3990
  this.bottomSheet = bottomSheet;
3972
3991
  this.customExport = [];
3973
3992
  this.downloadFileName = "data";
3993
+ this.canPrint = true;
3974
3994
  this.loading$ = this.query.selectLoading();
3975
3995
  }
3976
3996
  clickExport() {
@@ -4016,10 +4036,10 @@ class NiceFilterExportButtonsComponent {
4016
4036
  }
4017
4037
  }
4018
4038
  NiceFilterExportButtonsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceFilterExportButtonsComponent, deps: [{ token: FILTER_VIEW_ICONS }, { token: EXPORTS_SETTINGS }, { token: NiceFilterViewQuery }, { token: NiceFilterViewService }, { token: i3$4.MatBottomSheet }], target: i0.ɵɵFactoryTarget.Component });
4019
- NiceFilterExportButtonsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.3", type: NiceFilterExportButtonsComponent, selector: "nice-filter-export-buttons, div[nice-filter-export-buttons]", inputs: { customExport: "customExport", downloadFileName: "downloadFileName" }, ngImport: i0, template: "<button\n (click)=\"clickPrint()\"\n [disabled]=\"loading$ | async\"\n [matTooltip]=\"'general.print' | translate\"\n class=\"export-button\"\n mat-mini-fab\n>\n <mat-icon [svgIcon]=\"icons.print.svgIcon\">{{ icons.print.matIcon }}</mat-icon>\n</button>\n\n<button\n (click)=\"clickExport()\"\n [disabled]=\"loading$ | async\"\n [matTooltip]=\"'general.export' | translate\"\n class=\"export-button\"\n mat-mini-fab\n>\n <mat-icon [svgIcon]=\"icons.download.svgIcon\">{{ icons.download.matIcon }}</mat-icon>\n</button>\n", styles: [""], dependencies: [{ kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i8.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }, { kind: "pipe", type: i2$1.AsyncPipe, name: "async" }], encapsulation: i0.ViewEncapsulation.None });
4039
+ NiceFilterExportButtonsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.3", type: NiceFilterExportButtonsComponent, selector: "nice-filter-export-buttons, div[nice-filter-export-buttons]", inputs: { customExport: "customExport", downloadFileName: "downloadFileName", canPrint: "canPrint" }, ngImport: i0, template: "<button\n *ngIf=\"canPrint\"\n (click)=\"clickPrint()\"\n [disabled]=\"loading$ | async\"\n [matTooltip]=\"'general.print' | translate\"\n class=\"export-button\"\n mat-mini-fab\n>\n <mat-icon [svgIcon]=\"icons.print.svgIcon\">{{ icons.print.matIcon }}</mat-icon>\n</button>\n\n<button\n (click)=\"clickExport()\"\n [disabled]=\"loading$ | async\"\n [matTooltip]=\"'general.export' | translate\"\n class=\"export-button\"\n mat-mini-fab\n>\n <mat-icon [svgIcon]=\"icons.download.svgIcon\">{{ icons.download.matIcon }}</mat-icon>\n</button>\n", styles: [""], dependencies: [{ kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i8.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }, { kind: "pipe", type: i2$1.AsyncPipe, name: "async" }], encapsulation: i0.ViewEncapsulation.None });
4020
4040
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceFilterExportButtonsComponent, decorators: [{
4021
4041
  type: Component,
4022
- args: [{ selector: "nice-filter-export-buttons, div[nice-filter-export-buttons]", encapsulation: ViewEncapsulation.None, template: "<button\n (click)=\"clickPrint()\"\n [disabled]=\"loading$ | async\"\n [matTooltip]=\"'general.print' | translate\"\n class=\"export-button\"\n mat-mini-fab\n>\n <mat-icon [svgIcon]=\"icons.print.svgIcon\">{{ icons.print.matIcon }}</mat-icon>\n</button>\n\n<button\n (click)=\"clickExport()\"\n [disabled]=\"loading$ | async\"\n [matTooltip]=\"'general.export' | translate\"\n class=\"export-button\"\n mat-mini-fab\n>\n <mat-icon [svgIcon]=\"icons.download.svgIcon\">{{ icons.download.matIcon }}</mat-icon>\n</button>\n" }]
4042
+ args: [{ selector: "nice-filter-export-buttons, div[nice-filter-export-buttons]", encapsulation: ViewEncapsulation.None, template: "<button\n *ngIf=\"canPrint\"\n (click)=\"clickPrint()\"\n [disabled]=\"loading$ | async\"\n [matTooltip]=\"'general.print' | translate\"\n class=\"export-button\"\n mat-mini-fab\n>\n <mat-icon [svgIcon]=\"icons.print.svgIcon\">{{ icons.print.matIcon }}</mat-icon>\n</button>\n\n<button\n (click)=\"clickExport()\"\n [disabled]=\"loading$ | async\"\n [matTooltip]=\"'general.export' | translate\"\n class=\"export-button\"\n mat-mini-fab\n>\n <mat-icon [svgIcon]=\"icons.download.svgIcon\">{{ icons.download.matIcon }}</mat-icon>\n</button>\n" }]
4023
4043
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
4024
4044
  type: Inject,
4025
4045
  args: [FILTER_VIEW_ICONS]
@@ -4030,6 +4050,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImpor
4030
4050
  type: Input
4031
4051
  }], downloadFileName: [{
4032
4052
  type: Input
4053
+ }], canPrint: [{
4054
+ type: Input
4033
4055
  }] } });
4034
4056
 
4035
4057
  class NiceFilterExportDirective {
@@ -4238,7 +4260,10 @@ class NiceFilterQueryParamsDirective {
4238
4260
  this.router = router;
4239
4261
  this.init = new EventEmitter();
4240
4262
  this.unsubscribeAll$ = new Subject();
4241
- this.initialized = false;
4263
+ this._initialized = false;
4264
+ }
4265
+ get initialized() {
4266
+ return this._initialized;
4242
4267
  }
4243
4268
  ngOnInit() {
4244
4269
  this.query.selectFilterParameters().pipe(takeUntil(this.unsubscribeAll$)).subscribe((parameters) => {
@@ -4267,13 +4292,18 @@ class NiceFilterQueryParamsDirective {
4267
4292
  });
4268
4293
  }
4269
4294
  loadQueryParams() {
4270
- this.route.queryParams
4271
- .pipe(takeUntil(this.unsubscribeAll$), map((params) => {
4295
+ combineLatest([
4296
+ this.route.queryParams.pipe(map((params) => params.start), distinct()),
4297
+ this.route.queryParams.pipe(map((params) => params.length), distinct()),
4298
+ this.route.queryParams.pipe(map((params) => params.order), distinct()),
4299
+ this.route.queryParams.pipe(map((params) => params.search), distinct()),
4300
+ this.route.queryParams.pipe(map((params) => params.rules), distinct()),
4301
+ ]).pipe(takeUntil(this.unsubscribeAll$), map(() => {
4302
+ const params = this.route.snapshot.queryParams;
4272
4303
  return {
4273
4304
  params: QueryParamsUtils.extractFilterParameters(params)
4274
4305
  };
4275
- }))
4276
- .subscribe(({ params }) => {
4306
+ })).subscribe(({ params }) => {
4277
4307
  if (!QueryParamsUtils.hasFilterParameters(params) || Object.keys(params).length === 0) {
4278
4308
  params = { ...this.query.getValue().filterParameters };
4279
4309
  }
@@ -4282,10 +4312,9 @@ class NiceFilterQueryParamsDirective {
4282
4312
  !filterResult) {
4283
4313
  this.service.setParameters(params, false);
4284
4314
  }
4285
- if (!this.initialized) {
4286
- this.initialized = true;
4315
+ if (!this._initialized) {
4316
+ this._initialized = true;
4287
4317
  this.init.emit();
4288
- this.service.filter();
4289
4318
  }
4290
4319
  });
4291
4320
  }
@@ -4332,16 +4361,8 @@ class NiceBaseFilterViewComponent {
4332
4361
  if (mode) {
4333
4362
  this.filterViewService.setMode(mode);
4334
4363
  }
4335
- const { autoLoad: defaultAutoLoad } = this.filterViewQuery.getValue();
4336
- if (autoLoad && defaultAutoLoad) {
4337
- this.filterViewService.filter();
4338
- }
4339
- else {
4340
- this.filterViewService.setAutoLoad(autoLoad);
4341
- }
4342
- if (loadConfig) {
4343
- this.filterViewService.loadConfig(configQueryParams);
4344
- }
4364
+ this.autoLoad(autoLoad);
4365
+ this.loadConfig(loadConfig, configQueryParams);
4345
4366
  this.filterViewLoading$ = this.filterViewQuery.selectLoading();
4346
4367
  }
4347
4368
  /**
@@ -4395,9 +4416,38 @@ class NiceBaseFilterViewComponent {
4395
4416
  removeRule(id, reload = true) {
4396
4417
  this.filterViewService.removeRule(id, reload);
4397
4418
  }
4419
+ autoLoad(autoLoad) {
4420
+ const { autoLoad: defaultAutoLoad } = this.filterViewQuery.getValue();
4421
+ if (!this.queryParams) {
4422
+ if (autoLoad && defaultAutoLoad) {
4423
+ this.filterViewService.filter();
4424
+ }
4425
+ else {
4426
+ this.filterViewService.setAutoLoad(autoLoad);
4427
+ }
4428
+ return;
4429
+ }
4430
+ if (!autoLoad && defaultAutoLoad) {
4431
+ this.filterViewService.setAutoLoad(autoLoad);
4432
+ return;
4433
+ }
4434
+ this.queryParams.init.pipe(take(1)).subscribe(() => this.loadData());
4435
+ }
4436
+ loadConfig(loadConfig, configQueryParams) {
4437
+ if (loadConfig === true) {
4438
+ this.filterViewService.loadConfig(configQueryParams);
4439
+ return;
4440
+ }
4441
+ if (loadConfig === false) {
4442
+ return;
4443
+ }
4444
+ if (this.advancedFiltersButton || this.advancedFilters) {
4445
+ this.filterViewService.loadConfig(configQueryParams);
4446
+ }
4447
+ }
4398
4448
  }
4399
4449
  NiceBaseFilterViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceBaseFilterViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4400
- NiceBaseFilterViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.3", type: NiceBaseFilterViewComponent, selector: "ng-component", viewQueries: [{ propertyName: "filterViewService", first: true, predicate: NiceFilterViewComponent, descendants: true, read: NiceFilterViewService, static: true }, { propertyName: "filterViewQuery", first: true, predicate: NiceFilterViewComponent, descendants: true, read: NiceFilterViewQuery, static: true }], ngImport: i0, template: ``, isInline: true });
4450
+ NiceBaseFilterViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.3", type: NiceBaseFilterViewComponent, selector: "ng-component", viewQueries: [{ propertyName: "filterViewService", first: true, predicate: NiceFilterViewComponent, descendants: true, read: NiceFilterViewService, static: true }, { propertyName: "filterViewQuery", first: true, predicate: NiceFilterViewComponent, descendants: true, read: NiceFilterViewQuery, static: true }, { propertyName: "queryParams", first: true, predicate: NiceFilterQueryParamsDirective, descendants: true, static: true }, { propertyName: "advancedFiltersButton", first: true, predicate: NiceAdvancedFiltersButtonComponent, descendants: true, static: true }, { propertyName: "advancedFilters", first: true, predicate: NiceAdvancedFiltersComponent, descendants: true, static: true }], ngImport: i0, template: ``, isInline: true });
4401
4451
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceBaseFilterViewComponent, decorators: [{
4402
4452
  type: Component,
4403
4453
  args: [{
@@ -4409,6 +4459,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImpor
4409
4459
  }], filterViewQuery: [{
4410
4460
  type: ViewChild,
4411
4461
  args: [NiceFilterViewComponent, { read: NiceFilterViewQuery, static: true }]
4462
+ }], queryParams: [{
4463
+ type: ViewChild,
4464
+ args: [NiceFilterQueryParamsDirective, { static: true }]
4465
+ }], advancedFiltersButton: [{
4466
+ type: ViewChild,
4467
+ args: [NiceAdvancedFiltersButtonComponent, { static: true }]
4468
+ }], advancedFilters: [{
4469
+ type: ViewChild,
4470
+ args: [NiceAdvancedFiltersComponent, { static: true }]
4412
4471
  }] } });
4413
4472
 
4414
4473
  class NiceFilterViewModule {
@@ -4573,8 +4632,10 @@ class SelectableListStateQuery extends QueryEntity {
4573
4632
  }
4574
4633
 
4575
4634
  class SelectableListStateService {
4576
- constructor(store, preloadService, options) {
4635
+ constructor(store, route, router, preloadService, options) {
4577
4636
  this.store = store;
4637
+ this.route = route;
4638
+ this.router = router;
4578
4639
  this.preloadService = preloadService;
4579
4640
  this.options = options;
4580
4641
  }
@@ -4611,34 +4672,44 @@ class SelectableListStateService {
4611
4672
  this.store.update((state) => ({
4612
4673
  unselectedEntity: arrayRemove(state.unselectedEntity, id)
4613
4674
  }));
4614
- if (!this.preloadService) {
4615
- this.store.add({
4616
- [this.idKey]: id,
4617
- loaded: false
4675
+ this.store.add({
4676
+ [this.idKey]: id,
4677
+ loaded: false
4678
+ });
4679
+ if (this.preloadService) {
4680
+ const entity = await this.preloadService.loadEntityById(id);
4681
+ this.store.upsert(id, {
4682
+ ...entity,
4683
+ loaded: true
4618
4684
  });
4619
4685
  }
4620
- const entity = await this.preloadService.loadEntityById(id);
4621
- return this.store.add({
4622
- ...entity,
4623
- loaded: true
4624
- });
4686
+ }
4687
+ async selectMany(ids, active) {
4688
+ this.store.add(ids.map((id) => ({
4689
+ [this.idKey]: id,
4690
+ loaded: false
4691
+ })));
4692
+ if (active) {
4693
+ this.store.setActive(active);
4694
+ await this.loadEntities(true);
4695
+ }
4625
4696
  }
4626
4697
  async selectEntity(entity) {
4627
4698
  this.store.update((state) => ({
4628
4699
  unselectedEntity: arrayRemove(state.unselectedEntity, entity[this.idKey])
4629
4700
  }));
4630
- if (!this.preloadService) {
4631
- return this.store.upsert(entity[this.idKey], { ...entity, loaded: true });
4701
+ this.store.upsert(entity[this.idKey], { ...entity, loaded: true });
4702
+ if (this.preloadService) {
4703
+ const preloadedEntity = await this.preloadService.reloadEntity(entity);
4704
+ this.store.upsert(preloadedEntity[this.idKey], { ...preloadedEntity, loaded: true });
4632
4705
  }
4633
- const preloadedEntity = await this.preloadService.reloadEntity(entity);
4634
- return this.store.upsert(preloadedEntity[this.idKey], { ...preloadedEntity, loaded: true });
4635
4706
  }
4636
4707
  async selectManyEntities(entities) {
4637
4708
  if (!this.preloadService) {
4638
4709
  return this.store.upsertMany(entities.map((entity) => ({ ...entity, loaded: true })));
4639
4710
  }
4640
4711
  const preloadedEntities = await this.preloadService.reloadEntities(entities);
4641
- return this.store.upsertMany(preloadedEntities.map((preloadedEntity) => ({ ...preloadedEntity, loaded: true })));
4712
+ this.store.upsertMany(preloadedEntities.map((preloadedEntity) => ({ ...preloadedEntity, loaded: true })));
4642
4713
  }
4643
4714
  unselectAll() {
4644
4715
  this.store.set([]);
@@ -4662,6 +4733,9 @@ class SelectableListStateService {
4662
4733
  unselectManyEntities(entities) {
4663
4734
  this.store.remove(entities.map((entity) => entity[this.idKey]));
4664
4735
  }
4736
+ updateEntity(entity) {
4737
+ this.store.update(entity[this.idKey], entity);
4738
+ }
4665
4739
  async setEntities(ids, activeId) {
4666
4740
  this.store.update({
4667
4741
  unselectedEntity: [],
@@ -4674,6 +4748,7 @@ class SelectableListStateService {
4674
4748
  if (activeId) {
4675
4749
  this.store.setActive(activeId);
4676
4750
  }
4751
+ await this.loadEntities(true);
4677
4752
  }
4678
4753
  async next() {
4679
4754
  const { ids, active } = this.store.getValue();
@@ -4750,11 +4825,26 @@ class SelectableListStateService {
4750
4825
  }
4751
4826
  return toLoad;
4752
4827
  }
4828
+ generateQueryParams() {
4829
+ const { ids, active } = this.store.getValue();
4830
+ return {
4831
+ selection: ids.length ? ids : null,
4832
+ selected: active ?? null
4833
+ };
4834
+ }
4835
+ setQueryParams() {
4836
+ this.router.navigate([], {
4837
+ queryParams: this.generateQueryParams(),
4838
+ queryParamsHandling: "merge"
4839
+ });
4840
+ }
4753
4841
  }
4754
4842
 
4755
4843
  class SelectableListService {
4756
- constructor(providers) {
4844
+ constructor(providers, route, router) {
4757
4845
  this.providers = providers;
4846
+ this.route = route;
4847
+ this.router = router;
4758
4848
  this.stores = new Map();
4759
4849
  }
4760
4850
  createState(name, options) {
@@ -4771,10 +4861,10 @@ class SelectableListService {
4771
4861
  const provider = this.providers?.find((p) => p.state === stateName);
4772
4862
  const state = this.getState(stateName);
4773
4863
  if (state) {
4774
- return new SelectableListStateService(state.store, provider, options);
4864
+ return new SelectableListStateService(state.store, this.route, this.router, provider, options);
4775
4865
  }
4776
4866
  const newState = this.createState(stateName, options);
4777
- return new SelectableListStateService(newState.store, provider, options);
4867
+ return new SelectableListStateService(newState.store, this.route, this.router, provider, options);
4778
4868
  }
4779
4869
  query(stateName) {
4780
4870
  const state = this.getState(stateName);
@@ -4784,7 +4874,7 @@ class SelectableListService {
4784
4874
  return state.query;
4785
4875
  }
4786
4876
  }
4787
- SelectableListService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: SelectableListService, deps: [{ token: NICE_PRELOAD_SELECTED_ENTITIES_PROVIDER, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
4877
+ SelectableListService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: SelectableListService, deps: [{ token: NICE_PRELOAD_SELECTED_ENTITIES_PROVIDER, optional: true }, { token: i2.ActivatedRoute }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Injectable });
4788
4878
  SelectableListService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: SelectableListService, providedIn: "root" });
4789
4879
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: SelectableListService, decorators: [{
4790
4880
  type: Injectable,
@@ -4794,12 +4884,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImpor
4794
4884
  }, {
4795
4885
  type: Inject,
4796
4886
  args: [NICE_PRELOAD_SELECTED_ENTITIES_PROVIDER]
4797
- }] }]; } });
4887
+ }] }, { type: i2.ActivatedRoute }, { type: i2.Router }]; } });
4798
4888
 
4799
4889
  class SelectableListContentService {
4800
4890
  constructor() {
4801
4891
  this._state = null;
4802
4892
  this._checkboxes = new QueryList();
4893
+ this.defaultOptions = { idKey: "id", preloadWindow: 2 };
4894
+ }
4895
+ get options() {
4896
+ return this._options ?? this.defaultOptions;
4803
4897
  }
4804
4898
  get state() {
4805
4899
  return this._state;
@@ -4807,6 +4901,12 @@ class SelectableListContentService {
4807
4901
  get checkboxes() {
4808
4902
  return this._checkboxes;
4809
4903
  }
4904
+ setOptions(options) {
4905
+ this._options = {
4906
+ ...this.defaultOptions,
4907
+ ...options
4908
+ };
4909
+ }
4810
4910
  setState(state) {
4811
4911
  this._state = state;
4812
4912
  }
@@ -4848,6 +4948,7 @@ class NiceSelectableListCheckboxDirective {
4848
4948
  ngOnDestroy() {
4849
4949
  this.unsubscribeAll$.next();
4850
4950
  this.unsubscribeAll$.complete();
4951
+ this.initialized = false;
4851
4952
  }
4852
4953
  ngDoCheck() {
4853
4954
  if (this.selectPage && !this.initialized) {
@@ -4902,12 +5003,19 @@ class NiceSelectableListCheckboxDirective {
4902
5003
  });
4903
5004
  }
4904
5005
  updateCheckboxState() {
5006
+ const count = this.selectableListStateQuery.getCount();
4905
5007
  const checkboxes = this.service.checkboxes.filter((checkbox) => !checkbox.selectPage);
4906
5008
  if (!checkboxes.length) {
5009
+ if (!count) {
5010
+ this.checkbox.indeterminate = false;
5011
+ this.checkbox.checked = false;
5012
+ return;
5013
+ }
5014
+ this.checkbox.indeterminate = true;
5015
+ this.checkbox.checked = false;
4907
5016
  return;
4908
5017
  }
4909
5018
  this.initialized = true;
4910
- const count = this.selectableListStateQuery.getCount();
4911
5019
  if (!count) {
4912
5020
  this.checkbox.indeterminate = false;
4913
5021
  this.checkbox.checked = false;
@@ -4978,31 +5086,67 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImpor
4978
5086
 
4979
5087
  // tslint:disable-next-line:directive-class-suffix
4980
5088
  class NiceSelectableListDirective {
4981
- constructor(service) {
5089
+ constructor(service, selectableListService, route) {
4982
5090
  this.service = service;
4983
- this.defaultOptions = { idKey: "id", preloadWindow: 2 };
5091
+ this.selectableListService = selectableListService;
5092
+ this.route = route;
5093
+ this.unsubscribeAll$ = new Subject();
5094
+ this.unsubscribeQuerySub$ = new Subject();
4984
5095
  }
4985
5096
  ngOnInit() {
4986
- if (!this.options) {
4987
- this.options = { ...this.defaultOptions };
4988
- }
5097
+ combineLatest([
5098
+ this.route.queryParams.pipe(map((params) => params.selection), distinct()),
5099
+ this.route.queryParams.pipe(map((params) => params.selected), distinct())
5100
+ ]).pipe(takeUntil(this.unsubscribeAll$)).subscribe(([selection, selected]) => {
5101
+ if (!selection) {
5102
+ this.stateService.setQueryParams();
5103
+ return;
5104
+ }
5105
+ const newSelection = typeof selection === "string" ? [+selection] : selection.map((s) => +s);
5106
+ const newSelected = selected ? +selected : null;
5107
+ const { ids, active } = this.stateQuery.getValue();
5108
+ if (!ids.length || !ids.every((id) => newSelection.includes(id))) {
5109
+ this.stateService.setEntities(newSelection, newSelected);
5110
+ return;
5111
+ }
5112
+ if (newSelected && active !== newSelected) {
5113
+ this.stateService.setActive(newSelected);
5114
+ }
5115
+ });
5116
+ }
5117
+ ngOnDestroy() {
5118
+ this.unsubscribeAll$.next();
5119
+ this.unsubscribeAll$.complete();
5120
+ this.unsubscribeQuerySub$.next();
5121
+ this.unsubscribeQuerySub$.complete();
4989
5122
  }
4990
5123
  ngOnChanges(changes) {
4991
5124
  if ("options" in changes) {
4992
- this.options = {
4993
- ...this.defaultOptions,
4994
- ...changes.options.currentValue
4995
- };
5125
+ this.service.setOptions(this.options);
4996
5126
  }
4997
5127
  if ("state" in changes) {
4998
5128
  this.service.setState(this.state);
5129
+ this.stateService = this.selectableListService.withState(this.state);
5130
+ this.stateQuery = this.selectableListService.query(this.state);
5131
+ this.listenOnStateChanges();
4999
5132
  }
5000
5133
  }
5001
5134
  ngAfterContentInit() {
5002
5135
  this.service.setCheckboxes(this.checkboxes);
5003
5136
  }
5137
+ listenOnStateChanges() {
5138
+ this.unsubscribeQuerySub$.next();
5139
+ this.stateQuery.selectEntityAction([
5140
+ EntityActions.Add,
5141
+ EntityActions.Remove,
5142
+ EntityActions.Set
5143
+ ]).pipe(takeUntil(this.unsubscribeQuerySub$)).subscribe(() => {
5144
+ this.stateService.setQueryParams();
5145
+ });
5146
+ this.stateQuery.selectActiveId().pipe(takeUntil(this.unsubscribeQuerySub$)).subscribe(() => this.stateService.setQueryParams());
5147
+ }
5004
5148
  }
5005
- NiceSelectableListDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceSelectableListDirective, deps: [{ token: SelectableListContentService }], target: i0.ɵɵFactoryTarget.Directive });
5149
+ NiceSelectableListDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceSelectableListDirective, deps: [{ token: SelectableListContentService }, { token: SelectableListService }, { token: i2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Directive });
5006
5150
  NiceSelectableListDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.3", type: NiceSelectableListDirective, selector: "[niceSelectableList]", inputs: { state: "state", options: "options" }, providers: [SelectableListContentService], queries: [{ propertyName: "checkboxes", predicate: NiceSelectableListCheckboxDirective, descendants: true }], usesOnChanges: true, ngImport: i0 });
5007
5151
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImport: i0, type: NiceSelectableListDirective, decorators: [{
5008
5152
  type: Directive,
@@ -5010,7 +5154,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.3", ngImpor
5010
5154
  selector: "[niceSelectableList]",
5011
5155
  providers: [SelectableListContentService]
5012
5156
  }]
5013
- }], ctorParameters: function () { return [{ type: SelectableListContentService }]; }, propDecorators: { state: [{
5157
+ }], ctorParameters: function () { return [{ type: SelectableListContentService }, { type: SelectableListService }, { type: i2.ActivatedRoute }]; }, propDecorators: { state: [{
5014
5158
  type: Input
5015
5159
  }], options: [{
5016
5160
  type: Input