@firestitch/filter 9.8.7 → 9.9.3
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.
- package/app/components/filter/filter.component.d.ts +1 -0
- package/app/interfaces/items/base.interface.d.ts +3 -1
- package/app/models/items/base-item.d.ts +6 -2
- package/app/services/items-store.service.d.ts +5 -0
- package/bundles/firestitch-filter.umd.js +107 -31
- package/bundles/firestitch-filter.umd.js.map +1 -1
- package/bundles/firestitch-filter.umd.min.js +2 -2
- package/bundles/firestitch-filter.umd.min.js.map +1 -1
- package/esm2015/app/components/filter/filter.component.js +14 -21
- package/esm2015/app/interfaces/items/base.interface.js +1 -1
- package/esm2015/app/models/items/base-item.js +30 -8
- package/esm2015/app/services/external-params-controller.service.js +12 -6
- package/esm2015/app/services/items-store.service.js +38 -5
- package/esm2015/public_api.js +1 -1
- package/esm5/app/components/filter/filter.component.js +22 -22
- package/esm5/app/interfaces/items/base.interface.js +1 -1
- package/esm5/app/models/items/base-item.js +39 -8
- package/esm5/app/services/external-params-controller.service.js +12 -6
- package/esm5/app/services/items-store.service.js +44 -5
- package/esm5/public_api.js +1 -1
- package/fesm2015/firestitch-filter.js +87 -33
- package/fesm2015/firestitch-filter.js.map +1 -1
- package/fesm5/firestitch-filter.js +109 -33
- package/fesm5/firestitch-filter.js.map +1 -1
- package/firestitch-filter.metadata.json +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +5 -4
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { __decorate, __metadata, __param } from 'tslib';
|
|
2
2
|
import { Injectable, Optional, Inject, Component, ChangeDetectionStrategy, InjectionToken, ChangeDetectorRef, HostListener, Input, Injector, Directive, EventEmitter, NgZone, Output, ContentChild, TemplateRef, ViewChild, ElementRef, HostBinding, ViewEncapsulation, KeyValueDiffers, Pipe, Self, NgModule } from '@angular/core';
|
|
3
3
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
|
4
|
-
import { BehaviorSubject, Subject, isObservable, of, fromEvent, merge, timer
|
|
5
|
-
import {
|
|
4
|
+
import { BehaviorSubject, Subject, isObservable, forkJoin, combineLatest, of, fromEvent, merge, timer } from 'rxjs';
|
|
5
|
+
import { tap, finalize, take, takeUntil, debounceTime, filter as filter$1, distinctUntilChanged, switchMap, skip, map, mapTo, startWith, delay } from 'rxjs/operators';
|
|
6
6
|
import { isFunction, clone, isObject, isString, toString, pickBy } from 'lodash-es';
|
|
7
7
|
import { Model, Alias } from 'tsmodels';
|
|
8
8
|
import { filter, isEmpty, getNormalizedPath, list, remove, FsCommonModule } from '@firestitch/common';
|
|
@@ -68,8 +68,9 @@ function findValue(values, value, children) {
|
|
|
68
68
|
class BaseItem {
|
|
69
69
|
constructor(itemConfig, _additionalConfig) {
|
|
70
70
|
this._additionalConfig = _additionalConfig;
|
|
71
|
-
|
|
71
|
+
// protected _initialized = false;
|
|
72
72
|
this._pendingValues = false;
|
|
73
|
+
this._pendingDefaultValue = false;
|
|
73
74
|
this._loading$ = new BehaviorSubject(false);
|
|
74
75
|
this._value$ = new BehaviorSubject(null);
|
|
75
76
|
this._valueChange$ = new Subject();
|
|
@@ -126,6 +127,9 @@ class BaseItem {
|
|
|
126
127
|
get hasPendingValues() {
|
|
127
128
|
return this._pendingValues;
|
|
128
129
|
}
|
|
130
|
+
get hasPendingDefaultValue() {
|
|
131
|
+
return this._pendingDefaultValue;
|
|
132
|
+
}
|
|
129
133
|
get model() {
|
|
130
134
|
return this._model;
|
|
131
135
|
}
|
|
@@ -163,6 +167,9 @@ class BaseItem {
|
|
|
163
167
|
set loading(value) {
|
|
164
168
|
this._loading$.next(value);
|
|
165
169
|
}
|
|
170
|
+
get _initialized() {
|
|
171
|
+
return !this._pendingDefaultValue && !this._pendingValues;
|
|
172
|
+
}
|
|
166
173
|
valueChanged() {
|
|
167
174
|
this._value$.next(this.value);
|
|
168
175
|
if (this.change) {
|
|
@@ -187,8 +194,18 @@ class BaseItem {
|
|
|
187
194
|
get persistanceObject() {
|
|
188
195
|
return this.queryObject;
|
|
189
196
|
}
|
|
197
|
+
loadDefaultValue() {
|
|
198
|
+
this._pendingDefaultValue = true;
|
|
199
|
+
return this.defaultValueFn()
|
|
200
|
+
.pipe(tap((value) => {
|
|
201
|
+
this.defaultValue = value;
|
|
202
|
+
this._initDefaultModel();
|
|
203
|
+
}), finalize(() => {
|
|
204
|
+
this._pendingDefaultValue = false;
|
|
205
|
+
}));
|
|
206
|
+
}
|
|
190
207
|
initValues(persistedValue) {
|
|
191
|
-
this._initialized = false;
|
|
208
|
+
// this._initialized = false;
|
|
192
209
|
this.persistedValue = persistedValue;
|
|
193
210
|
this._initDefaultModel();
|
|
194
211
|
const isAutocomplete = this.type === ItemType.AutoComplete || this.type === ItemType.AutoCompleteChips;
|
|
@@ -201,12 +218,12 @@ class BaseItem {
|
|
|
201
218
|
this.values = valuesResult;
|
|
202
219
|
// Move to some other place
|
|
203
220
|
this._init();
|
|
204
|
-
this._initialized = true;
|
|
221
|
+
// this._initialized = true;
|
|
205
222
|
}
|
|
206
223
|
}
|
|
207
224
|
else {
|
|
208
225
|
this._init();
|
|
209
|
-
this._initialized = true;
|
|
226
|
+
// this._initialized = true;
|
|
210
227
|
}
|
|
211
228
|
}
|
|
212
229
|
loadAsyncValues(reload = true) {
|
|
@@ -220,7 +237,7 @@ class BaseItem {
|
|
|
220
237
|
this.loading = false;
|
|
221
238
|
this._init();
|
|
222
239
|
this._validateModel();
|
|
223
|
-
this._initialized = true;
|
|
240
|
+
// this._initialized = true;
|
|
224
241
|
});
|
|
225
242
|
}
|
|
226
243
|
}
|
|
@@ -250,7 +267,12 @@ class BaseItem {
|
|
|
250
267
|
this.name = item.name;
|
|
251
268
|
this.label = item.label;
|
|
252
269
|
this.chipLabel = item.chipLabel;
|
|
253
|
-
|
|
270
|
+
if (typeof item.default === 'function') {
|
|
271
|
+
this.defaultValueFn = item.default;
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
this.defaultValue = item.default;
|
|
275
|
+
}
|
|
254
276
|
this.change = item.change;
|
|
255
277
|
this.hide = item.hide;
|
|
256
278
|
this.clearAllowed = (_a = item.clear) !== null && _a !== void 0 ? _a : true;
|
|
@@ -1190,12 +1212,15 @@ let FsFilterItemsStore = class FsFilterItemsStore {
|
|
|
1190
1212
|
this.sortByItem = null;
|
|
1191
1213
|
this.sortDirectionItem = null;
|
|
1192
1214
|
this.keywordItem = null;
|
|
1215
|
+
this._ready$ = new BehaviorSubject(false);
|
|
1193
1216
|
this._items = [];
|
|
1194
1217
|
this._visibleItems$ = new BehaviorSubject([]);
|
|
1195
1218
|
this._itemsByName = new Map();
|
|
1196
1219
|
this._itemsValuesLoaded = false;
|
|
1197
1220
|
this._hasKeyword = false;
|
|
1198
1221
|
this._itemsChange$ = new Subject();
|
|
1222
|
+
this._destroy$ = new Subject();
|
|
1223
|
+
this._lazyInit();
|
|
1199
1224
|
}
|
|
1200
1225
|
get items() {
|
|
1201
1226
|
return this._items;
|
|
@@ -1215,8 +1240,13 @@ let FsFilterItemsStore = class FsFilterItemsStore {
|
|
|
1215
1240
|
get itemsChange$() {
|
|
1216
1241
|
return this._itemsChange$.pipe(debounceTime(30));
|
|
1217
1242
|
}
|
|
1243
|
+
get ready$() {
|
|
1244
|
+
return this._ready$.asObservable();
|
|
1245
|
+
}
|
|
1218
1246
|
ngOnDestroy() {
|
|
1219
1247
|
this.destroyItems();
|
|
1248
|
+
this._destroy$.next();
|
|
1249
|
+
this._destroy$.complete();
|
|
1220
1250
|
}
|
|
1221
1251
|
setConfig(config) {
|
|
1222
1252
|
this._itemsByName.clear();
|
|
@@ -1230,8 +1260,6 @@ let FsFilterItemsStore = class FsFilterItemsStore {
|
|
|
1230
1260
|
this._itemsValuesLoaded = false;
|
|
1231
1261
|
if (Array.isArray(items)) {
|
|
1232
1262
|
this._createItems(items);
|
|
1233
|
-
this.updateVisibleItems();
|
|
1234
|
-
this._setKeywordItem();
|
|
1235
1263
|
}
|
|
1236
1264
|
}
|
|
1237
1265
|
filtersClear() {
|
|
@@ -1270,6 +1298,24 @@ let FsFilterItemsStore = class FsFilterItemsStore {
|
|
|
1270
1298
|
.filter((item) => item.hasPendingValues)
|
|
1271
1299
|
.forEach((item) => item.loadAsyncValues());
|
|
1272
1300
|
}
|
|
1301
|
+
loadAsyncDefaults() {
|
|
1302
|
+
const pendingItems = this.items
|
|
1303
|
+
.filter((item) => {
|
|
1304
|
+
return item.defaultValueFn
|
|
1305
|
+
&& (item.persistedValue === null || item.persistedValue === undefined);
|
|
1306
|
+
});
|
|
1307
|
+
if (pendingItems.length > 0) {
|
|
1308
|
+
forkJoin(pendingItems
|
|
1309
|
+
.map((item) => item.loadDefaultValue()))
|
|
1310
|
+
.pipe(finalize(() => {
|
|
1311
|
+
this._ready$.next(true);
|
|
1312
|
+
}), takeUntil(this._destroy$))
|
|
1313
|
+
.subscribe();
|
|
1314
|
+
}
|
|
1315
|
+
else {
|
|
1316
|
+
this._ready$.next(true);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1273
1319
|
getSort() {
|
|
1274
1320
|
let sortBy = this.getSortByValue();
|
|
1275
1321
|
sortBy = sortBy === '__all' ? null : sortBy;
|
|
@@ -1324,6 +1370,7 @@ let FsFilterItemsStore = class FsFilterItemsStore {
|
|
|
1324
1370
|
item.initValues(p[item.name]);
|
|
1325
1371
|
});
|
|
1326
1372
|
this._createSortingItems(p);
|
|
1373
|
+
this.loadAsyncDefaults();
|
|
1327
1374
|
this._subscribeToItemsChanges();
|
|
1328
1375
|
}
|
|
1329
1376
|
updateItemsWithValues(values) {
|
|
@@ -1410,6 +1457,14 @@ let FsFilterItemsStore = class FsFilterItemsStore {
|
|
|
1410
1457
|
});
|
|
1411
1458
|
}
|
|
1412
1459
|
}
|
|
1460
|
+
_lazyInit() {
|
|
1461
|
+
this.ready$
|
|
1462
|
+
.pipe(filter$1((state) => state), takeUntil(this._destroy$))
|
|
1463
|
+
.subscribe(() => {
|
|
1464
|
+
this.updateVisibleItems();
|
|
1465
|
+
this._setKeywordItem();
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1413
1468
|
_createSortingItems(p) {
|
|
1414
1469
|
var _a;
|
|
1415
1470
|
if (((_a = this._config.sortValues) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
@@ -1948,8 +2003,10 @@ let ExternalParamsController = class ExternalParamsController {
|
|
|
1948
2003
|
this._initSavedFilters();
|
|
1949
2004
|
this._pending$.next(true);
|
|
1950
2005
|
if (this._savedFilters.enabled) {
|
|
1951
|
-
|
|
1952
|
-
.
|
|
2006
|
+
combineLatest([
|
|
2007
|
+
this._itemsStore.ready$,
|
|
2008
|
+
this._savedFilters.load(),
|
|
2009
|
+
])
|
|
1953
2010
|
.pipe(takeUntil(this._destroy$))
|
|
1954
2011
|
.subscribe(() => {
|
|
1955
2012
|
this._savedFilters.updateActiveFilter();
|
|
@@ -1959,8 +2016,12 @@ let ExternalParamsController = class ExternalParamsController {
|
|
|
1959
2016
|
});
|
|
1960
2017
|
}
|
|
1961
2018
|
else {
|
|
1962
|
-
this.
|
|
1963
|
-
|
|
2019
|
+
this._itemsStore.ready$
|
|
2020
|
+
.pipe(takeUntil(this._destroy$))
|
|
2021
|
+
.subscribe(() => {
|
|
2022
|
+
this._initItemsValues();
|
|
2023
|
+
this._pending$.next(false);
|
|
2024
|
+
});
|
|
1964
2025
|
}
|
|
1965
2026
|
this._listenItemsChange();
|
|
1966
2027
|
}
|
|
@@ -2654,6 +2715,9 @@ let FilterComponent = class FilterComponent {
|
|
|
2654
2715
|
get visibleItems() {
|
|
2655
2716
|
return this._filterItems.visibleItems;
|
|
2656
2717
|
}
|
|
2718
|
+
get itemsReady$() {
|
|
2719
|
+
return this._filterItems.ready$;
|
|
2720
|
+
}
|
|
2657
2721
|
get hasFilterChips$() {
|
|
2658
2722
|
return this._hasFilterChips$.asObservable();
|
|
2659
2723
|
}
|
|
@@ -2685,21 +2749,6 @@ let FilterComponent = class FilterComponent {
|
|
|
2685
2749
|
this.focus();
|
|
2686
2750
|
}
|
|
2687
2751
|
});
|
|
2688
|
-
if (this.config.init) {
|
|
2689
|
-
if (this._externalParams.pending) {
|
|
2690
|
-
this._externalParams
|
|
2691
|
-
.pending$
|
|
2692
|
-
.pipe(filter$1((pending) => {
|
|
2693
|
-
return !pending;
|
|
2694
|
-
}), takeUntil(this._destroy$))
|
|
2695
|
-
.subscribe(() => {
|
|
2696
|
-
this.init();
|
|
2697
|
-
});
|
|
2698
|
-
}
|
|
2699
|
-
else {
|
|
2700
|
-
this.init();
|
|
2701
|
-
}
|
|
2702
|
-
}
|
|
2703
2752
|
this._listenInternalItemsChange();
|
|
2704
2753
|
this._initOverlay();
|
|
2705
2754
|
}
|
|
@@ -3088,10 +3137,15 @@ let FilterComponent = class FilterComponent {
|
|
|
3088
3137
|
}
|
|
3089
3138
|
// We may need some time to recieve external params and after that ready can be emitted
|
|
3090
3139
|
_listenWhenFilterReady() {
|
|
3091
|
-
|
|
3092
|
-
.pending
|
|
3093
|
-
|
|
3140
|
+
combineLatest([
|
|
3141
|
+
this._externalParams.pending$,
|
|
3142
|
+
this.itemsReady$,
|
|
3143
|
+
])
|
|
3144
|
+
.pipe(filter$1(([pendingParams, itemsReady]) => !pendingParams && itemsReady), takeUntil(this._destroy$))
|
|
3094
3145
|
.subscribe(() => {
|
|
3146
|
+
if (this.config.init) {
|
|
3147
|
+
this.init();
|
|
3148
|
+
}
|
|
3095
3149
|
this.ready.emit();
|
|
3096
3150
|
});
|
|
3097
3151
|
}
|
|
@@ -3168,7 +3222,7 @@ __decorate([
|
|
|
3168
3222
|
FilterComponent = __decorate([
|
|
3169
3223
|
Component({
|
|
3170
3224
|
selector: 'fs-filter',
|
|
3171
|
-
template: "<ng-container *ngIf=\"hasKeyword; else noKeywordFilter\">\n <div class=\"filter-search-container\">\n <div class=\"filter-input-field\">\n <form autocomplete=\"off\" role=\"presentation\" *ngIf=\"keywordVisible$ | async\">\n <mat-form-field floatLabel=\"never\">\n <span matPrefix>\n <mat-icon matPrefix>search</mat-icon>\n </span>\n\n <input\n #searchTextInput\n matInput\n [formControl]=\"searchText\"\n [placeholder]=\"searchPlaceholder\"\n name=\"filter-input\"\n (click)=\"filterInputEvent($event)\"\n class=\"filter-input\">\n\n <a matSuffix\n *ngIf=\"searchText.value && showFilterInput && config.clear\"\n (click)=\"clearSearchText($event)\"\n href=\"javascript:void(0)\"\n class=\"clear\">\n <mat-icon>clear</mat-icon>\n </a>\n\n <a matSuffix\n (click)=\"reload($event)\"\n class=\"reload\"\n *ngIf=\"config.reload\">\n <mat-icon>refresh</mat-icon>\n </a>\n </mat-form-field>\n </form>\n </div>\n <ng-container *ngTemplateOutlet=\"filterActions\"></ng-container>\n </div>\n <div class=\"status-actions\" *ngIf=\"keywordVisible$ | async\">\n <ng-container *ngTemplateOutlet=\"statusBarContainer\"></ng-container>\n <ng-container *ngTemplateOutlet=\"filterChips\"></ng-container>\n </div>\n</ng-container>\n\n<ng-template #noKeywordFilter>\n <div class=\"filter-searchless-container\">\n <div class=\"status-actions\">\n <ng-container *ngTemplateOutlet=\"statusBarContainer\"></ng-container>\n <ng-container *ngTemplateOutlet=\"filterChips\"></ng-container>\n </div>\n <ng-container *ngTemplateOutlet=\"filterActions\"></ng-container>\n </div>\n</ng-template>\n\n\n<ng-template #filterActions>\n <div class=\"filter-actions\">\n <ng-container *ngIf=\"hasVisibleItemOrSorting && filtersBtnVisible$ | async
|
|
3225
|
+
template: "<ng-container *ngIf=\"hasKeyword; else noKeywordFilter\">\n <div class=\"filter-search-container\">\n <div class=\"filter-input-field\">\n <form autocomplete=\"off\" role=\"presentation\" *ngIf=\"keywordVisible$ | async\">\n <mat-form-field floatLabel=\"never\">\n <span matPrefix>\n <mat-icon matPrefix>search</mat-icon>\n </span>\n\n <input\n #searchTextInput\n matInput\n [formControl]=\"searchText\"\n [placeholder]=\"searchPlaceholder\"\n name=\"filter-input\"\n (click)=\"filterInputEvent($event)\"\n class=\"filter-input\">\n\n <a matSuffix\n *ngIf=\"searchText.value && showFilterInput && config.clear\"\n (click)=\"clearSearchText($event)\"\n href=\"javascript:void(0)\"\n class=\"clear\">\n <mat-icon>clear</mat-icon>\n </a>\n\n <a matSuffix\n (click)=\"reload($event)\"\n class=\"reload\"\n *ngIf=\"config.reload\">\n <mat-icon>refresh</mat-icon>\n </a>\n </mat-form-field>\n </form>\n </div>\n <ng-container *ngTemplateOutlet=\"filterActions\"></ng-container>\n </div>\n <div class=\"status-actions\" *ngIf=\"keywordVisible$ | async\">\n <ng-container *ngTemplateOutlet=\"statusBarContainer\"></ng-container>\n <ng-container *ngTemplateOutlet=\"filterChips\"></ng-container>\n </div>\n</ng-container>\n\n<ng-template #noKeywordFilter>\n <div class=\"filter-searchless-container\">\n <div class=\"status-actions\">\n <ng-container *ngTemplateOutlet=\"statusBarContainer\"></ng-container>\n <ng-container *ngTemplateOutlet=\"filterChips\"></ng-container>\n </div>\n <ng-container *ngTemplateOutlet=\"filterActions\"></ng-container>\n </div>\n</ng-template>\n\n\n<ng-template #filterActions>\n <div class=\"filter-actions\">\n <ng-container *ngIf=\"hasVisibleItemOrSorting && filtersBtnVisible$ | async\">\n <button\n mat-button\n class=\"filters-button\"\n [ngClass]=\"{\n 'mat-raised-button': config.button.style == 'raised',\n 'mat-button': config.button.style == 'basic',\n 'mat-icon-button': config.button.style == 'icon'\n }\"\n (click)=\"changeVisibilityClick(!showFilterMenu, $event)\"\n type=\"button\"\n [color]=\"config.button.color\">\n <mat-icon *ngIf=\"config.button.icon\">{{config.button.icon}}</mat-icon>\n {{ config.button.label }}\n </button>\n </ng-container>\n\n <fs-filter-actions\n *ngIf=\"actionsVisible$ | async\"\n [actions]=\"actions$ | async\"\n [kebabActions]=\"menuActions$ | async\">\n </fs-filter-actions>\n </div>\n</ng-template>\n\n<ng-template #filterChips>\n <fs-filter-chips\n *ngIf=\"config.chips && hasFilterChips$ | async\"\n class=\"filter-chips\"\n [filters]=\"items\">\n </fs-filter-chips>\n</ng-template>\n\n<ng-template #statusBarContainer>\n <div class=\"status-bar\" *ngIf=\"statusBar\">\n <small><ng-container *ngTemplateOutlet=\"statusBar\"></ng-container></small>\n </div>\n</ng-template>\n",
|
|
3172
3226
|
encapsulation: ViewEncapsulation.None,
|
|
3173
3227
|
providers: [
|
|
3174
3228
|
FsFilterOverlayService,
|