@firestitch/filter
Version:
1,533 lines (1,528 loc) • 105 kB
JavaScript
import { FormsModule } from '@angular/forms';
import { MatIconModule, MatInputModule, MatSelectModule, MatChipsModule, MatAutocompleteModule, MatButtonModule, MatCheckboxModule, MAT_LABEL_GLOBAL_OPTIONS } from '@angular/material';
import { FlexLayoutModule } from '@angular/flex-layout';
import { FsDatePickerModule } from '@firestitch/datepicker';
import { FsChipModule } from '@firestitch/chip';
import { FsLabelModule } from '@firestitch/label';
import { Location, CommonModule } from '@angular/common';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { FsStore, FsStoreModule } from '@firestitch/store';
import { __decorate, __metadata } from 'tslib';
import { Alias, Model } from 'tsmodels';
import { isObservable } from 'rxjs/internal/util/isObservable';
import { isDate, isValid, parse, format, isAfter, subMinutes } from 'date-fns';
import { Subject } from 'rxjs';
import { isEmpty, list, filter, remove, FsCommonModule } from '@firestitch/common';
import { isFunction, isObject, toString, clone, isString, cloneDeep } from 'lodash-es';
import { take, takeUntil, debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
import { Component, EventEmitter, Input, ViewChild, ViewEncapsulation, HostListener, ChangeDetectionStrategy, ChangeDetectorRef, IterableDiffers, Output, KeyValueDiffers, Pipe, NgModule } from '@angular/core';
import { toUTC, simpleFormat, format as format$1 } from '@firestitch/date';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @enum {string} */
const ItemType = {
Text: 'text',
Select: 'select',
Range: 'range',
Date: 'date',
DateTime: 'datetime',
DateRange: 'daterange',
DateTimeRange: 'datetimerange',
AutoComplete: 'autocomplete',
AutoCompleteChips: 'autocompletechips',
Checkbox: 'checkbox',
Chips: 'chips',
};
class FsFilterConfigItem extends Model {
/**
* @param {?=} data
* @param {?=} _config
* @param {?=} _route
* @param {?=} _persists
*/
constructor(data = {}, _config, _route, _persists) {
super();
this._config = _config;
this._route = _route;
this._persists = _persists;
this.initialLoading = false;
this.valueChanged = false;
this._pendingValues = false;
this._fromJSON(data);
}
/**
* @return {?}
*/
get hasPendingValues() {
return this._pendingValues;
}
/**
* @return {?}
*/
get model() {
return this._model;
}
/**
* @param {?} val
* @return {?}
*/
set model(val) {
this._model = val;
this._tmpModel = val;
this.checkIfValueChanged();
}
/**
* @return {?}
*/
get tmpModel() {
return this._tmpModel;
}
/**
* @param {?} val
* @return {?}
*/
set tmpModel(val) {
this._tmpModel = val;
}
/**
* @param {?} data
* @return {?}
*/
_fromJSON(data) {
super._fromJSON(data);
if (this.name && isObject(this.name)) {
this.names = this.name;
this.name = Object.keys(this.names).join('-');
}
if (this._config.persist) {
/** @type {?} */
const persisted = this._persists[this._config.persist.name].data;
if (persisted[this.name]) {
this.parseAndSetValue(persisted[this.name]);
}
}
if (isFunction(data.values) &&
this.type !== ItemType.AutoComplete &&
this.type !== ItemType.AutoCompleteChips) {
this.values = data.values();
if (isObservable(this.values)) {
this._pendingValues = true;
}
else {
/** @type {?} */
const values = Array.isArray(this.values) ? ((/** @type {?} */ (this.values))).slice() : this.values;
this.sanitizeItem(values);
}
}
else {
/** @type {?} */
const values = Array.isArray(data.values) ? data.values.slice() : data.values;
this.sanitizeItem(values);
}
}
/**
* @param {?} values
* @return {?}
*/
sanitizeItem(values) {
switch (this.type) {
case ItemType.Text:
break;
case ItemType.Select:
{
this.sanitizeSelectItem(values);
}
break;
case ItemType.Chips:
{
this.sanitizeChipsItem(values);
}
break;
case ItemType.Range:
{
this.sanitizeRange();
}
break;
case ItemType.Checkbox:
{
this.sanitizeCheckbox();
}
break;
}
if (this.model === undefined) {
if (this.type == 'checkbox') {
this.model = this.checked == this.defaultValue;
}
else {
this.model = this.defaultValue;
}
}
if (this.model === undefined) {
if (this.type == 'checkbox') {
this.model = false;
}
else if (this.type == 'select') {
if (this.multiple) {
if (!Array.isArray(this.defaultValue)) {
this.model = [];
}
}
else {
if (this.defaultValue === undefined) {
this.model = '__all';
}
}
}
else if (this.type == ItemType.AutoCompleteChips || this.type == ItemType.Chips) {
this.model = [];
}
}
}
/**
* @param {?} values
* @return {?}
*/
sanitizeSelectItem(values) {
this.values = values;
this.groups = null;
// let data = [];
// if (this.nested) {
// // generate a list of values from objects that have not been nested.
// if (!this.multiple) {
// data.push({value: '__all', name: 'All', depth: 0});
// }
//
// Array.prototype.push.apply(data, this.walkSelectNestedValues(filter, null, this.values));
// } else {
//
// data = this.walkSelectValues(filter, this.values);
// }
// this.values = data;
if (this.isolate) {
for (const index in this.values) {
if (this.values.hasOwnProperty(index)) {
if (!this.values[index]) {
continue;
}
if (this.values[index].value == this.isolate.value) {
this.values.splice(index, 1);
}
}
}
if (Array.isArray(this.model)) {
if (this.model.length == this.values.length) {
this.model = null;
this.isolate.enabled = false;
}
else if (this.model[0] == this.isolate.value) {
this.isolate.enabled = true;
}
}
}
}
/**
* @param {?} values
* @return {?}
*/
sanitizeChipsItem(values) {
this.values = values;
this.groups = null;
if (this.model && Array.isArray(this.model)) {
if (Number.isInteger(this.model[0])) {
this.model = this.model.map((/**
* @param {?} id
* @return {?}
*/
(id) => {
return this.values.find((/**
* @param {?} value
* @return {?}
*/
(value) => value.value === id));
}));
}
}
}
/**
* @return {?}
*/
sanitizeCheckbox() {
this.checked = this.checked ? toString(this.checked) : true;
this.unchecked = this.unchecked ? toString(this.unchecked) : false;
this.defaultValue = this.defaultValue === undefined ? this.unchecked : toString(this.defaultValue);
}
/**
* @param {?} value
* @return {?}
*/
updateValue(value) {
switch (this.type) {
case ItemType.Select:
{
if (value === '__all' || value === null) {
this.model = value;
return;
}
/** @type {?} */
let valueExists = null;
/** @type {?} */
let isolated = null;
if (this.multiple) {
isolated = this.isolate && Array.isArray(value) && value[0] === this.isolate.value;
valueExists = Array.isArray(this.values)
? value.every((/**
* @param {?} val
* @return {?}
*/
(val) => {
return this.values.find((/**
* @param {?} valueItem
* @return {?}
*/
(valueItem) => valueItem.value === val));
}))
|| isolated
: false;
}
else {
valueExists = Array.isArray(this.values)
? this.values.some((/**
* @param {?} valueItem
* @return {?}
*/
(valueItem) => valueItem.value === value))
: false;
}
if (valueExists) {
this.model = value;
if (this.isolate) {
this.isolate.enabled = isolated;
}
return;
}
}
break;
case ItemType.Range:
{
this.model = isObject(value) ? Object.assign({}, this.model, value) : {};
}
break;
case ItemType.Chips:
{
this.model = [];
}
break;
case ItemType.Date:
case ItemType.DateTime:
{
this.model = value;
}
break;
case ItemType.AutoCompleteChips:
{
if (Array.isArray(value)) {
this.model.push(...value);
}
else if (isObject(value)) {
this.model.push(value);
}
else {
this.model = [];
}
}
break;
default: {
this.model = value;
}
}
}
/**
* @return {?}
*/
loadRemoteValues() {
if (!this.initialLoading && this.hasPendingValues) {
this.initialLoading = true;
this.values
.pipe(take(1), takeUntil(this._config.destroy$))
.subscribe((/**
* @param {?} values
* @return {?}
*/
(values) => {
this._pendingValues = false;
this.sanitizeItem(values);
this.initialLoading = false;
}));
}
}
/**
* @return {?}
*/
clear() {
this.valueChanged = false;
this.model = undefined;
switch (this.type) {
case ItemType.AutoComplete:
{
this.model = null;
this.tmpModel = null;
this.search = '';
}
break;
case ItemType.AutoCompleteChips:
case ItemType.Chips:
{
this.model = [];
this.tmpModel = [];
this.search = '';
}
break;
case ItemType.Checkbox:
{
this.model = false;
this.tmpModel = false;
}
break;
case ItemType.Select:
{
if (this.multiple) {
this.model = [];
this.tmpModel = [];
}
else {
this.model = Array.isArray(this.values) && this.values.some((/**
* @param {?} val
* @return {?}
*/
(val) => val.value === '__all'))
? '__all'
: null;
this.tmpModel = this.model;
}
if (this.isolate) {
this.isolate.enabled = false;
}
}
break;
case ItemType.Range:
{
this.model = {};
this.tmpModel = {};
}
break;
case ItemType.Text:
{
this.model = '';
this.tmpModel = '';
}
break;
case ItemType.Date:
case ItemType.DateTime:
{
this.model = null;
this.tmpModel = null;
}
break;
}
}
/**
* @return {?}
*/
checkIfValueChanged() {
switch (this.type) {
case ItemType.AutoCompleteChips:
{
this.valueChanged = this.model && this.model.length;
}
break;
case ItemType.Checkbox:
{
this.valueChanged = this.model && this.model !== false;
}
break;
case ItemType.Select:
{
if (this.multiple) {
this.valueChanged = this.model && this.model.length;
}
else {
/** @type {?} */
const hasAllOption = Array.isArray(this.values) && this.values.some((/**
* @param {?} val
* @return {?}
*/
(val) => val.value === '__all'));
if (hasAllOption && this.model && this.model !== '__all') {
this.valueChanged = true;
}
else {
this.valueChanged = !!this.model;
}
}
}
break;
case ItemType.Range:
{
if (this.model && Object.keys(this.model).length > 0) {
this.valueChanged = true;
}
}
break;
case ItemType.Text:
{
this.valueChanged = this.model && this.model !== '';
}
break;
case ItemType.AutoComplete:
case ItemType.Date:
case ItemType.DateTime:
{
this.valueChanged = !!this.model;
}
break;
default: {
this.valueChanged = false;
}
}
}
/**
* @param {?} value
* @return {?}
*/
parseAndSetValue(value) {
if (value) {
if (this.type === ItemType.DateRange || this.type === ItemType.DateTimeRange) {
value.from = value.from ? toUTC(value.from) : null;
value.to = value.to ? toUTC(value.to) : null;
}
else if (this.type === ItemType.Date ||
this.type === ItemType.DateTime) {
if (!isDate(value) || !isValid(value)) {
value = parse(value, 'yyyy-MM-dd\'T\'HH:mm:ssxxxxx', new Date());
}
}
else if (this.type === ItemType.Checkbox && this.checked !== undefined) {
value = value == this.checked;
}
else if (this.type === ItemType.Select && this.multiple) {
value = clone(value);
}
else if (this.type === ItemType.Select || this.type === ItemType.AutoComplete) {
value = +value;
}
}
this.model = value;
}
/**
* @private
* @return {?}
*/
sanitizeRange() {
if (!this.placeholder) {
this.placeholder = ['Min', 'Max'];
}
if (!this.model) {
this.model = {};
}
}
}
__decorate([
Alias(),
__metadata("design:type", String)
], FsFilterConfigItem.prototype, "name", void 0);
__decorate([
Alias(),
__metadata("design:type", String)
], FsFilterConfigItem.prototype, "type", void 0);
__decorate([
Alias(),
__metadata("design:type", String)
], FsFilterConfigItem.prototype, "label", void 0);
__decorate([
Alias(),
__metadata("design:type", String)
], FsFilterConfigItem.prototype, "chipLabel", void 0);
__decorate([
Alias(),
__metadata("design:type", String)
], FsFilterConfigItem.prototype, "children", void 0);
__decorate([
Alias(),
__metadata("design:type", Boolean)
], FsFilterConfigItem.prototype, "multiple", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "groups", void 0);
__decorate([
Alias(),
__metadata("design:type", Boolean)
], FsFilterConfigItem.prototype, "wait", void 0);
__decorate([
Alias(),
__metadata("design:type", String)
], FsFilterConfigItem.prototype, "query", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "values", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "values$", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "selectedValue", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "isolate", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "names", void 0);
__decorate([
Alias(),
__metadata("design:type", Boolean)
], FsFilterConfigItem.prototype, "primary", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "search", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "unchecked", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "checked", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "alias", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "placeholder", void 0);
__decorate([
Alias(),
__metadata("design:type", Function)
], FsFilterConfigItem.prototype, "change", void 0);
__decorate([
Alias('default'),
__metadata("design:type", Object)
], FsFilterConfigItem.prototype, "defaultValue", void 0);
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const SORT_BY_FIELD = 'system_sort_by';
/** @type {?} */
const SORT_DIRECTION_FIELD = 'system_sort_direction';
class FsFilterConfig extends Model {
/**
* @param {?=} data
*/
constructor(data = {}) {
super();
this.load = true;
this.persist = false;
this.inline = false;
this.autofocus = false;
this.chips = false;
this.sortValues = null;
this.sort = null;
this.sortDirection = null;
this.queryParam = false;
this.namespace = 'filter';
this.items = [];
this.sortByItem = null;
this.sortDirectionItem = null;
this.searchInput = null;
this.singleTextFilter = false;
this._filtersNames = [];
this._destroy$ = new Subject();
this._fromJSON(data);
}
/**
* @return {?}
*/
get destroy$() {
return this._destroy$.asObservable();
}
/**
* @param {?} items
* @param {?} route
* @param {?} persists
* @return {?}
*/
initItems(items, route, persists) {
if (items && Array.isArray(items)) {
this.items = items.map((/**
* @param {?} item
* @return {?}
*/
(item) => {
if (item && item.name && this._filtersNames.indexOf(item.name) === -1) {
this._filtersNames.push(item.name);
return new FsFilterConfigItem(item, this, route, persists);
}
else {
throw Error('Filter init error. Items name must be uniq.');
}
}));
}
this.initSorting(route, persists);
this.searchInput = this.items.find((/**
* @param {?} item
* @return {?}
*/
(item) => item.type === ItemType.Text));
if (this.items.length === 1 && this.items[0].type === ItemType.Text) {
this.singleTextFilter = true;
}
}
/**
* @param {?} route
* @param {?} persists
* @return {?}
*/
initSorting(route, persists) {
if (this.sortValues) {
/** @type {?} */
const sortByItem = {
name: SORT_BY_FIELD,
type: ItemType.Select,
label: 'Sort By',
values: this.sortValues
};
if (this.sort && this.sort.value) {
sortByItem['default'] = this.sort.value;
}
this.sortByItem = new FsFilterConfigItem(sortByItem, this, route, persists);
/** @type {?} */
const sortDirectionItem = {
name: SORT_DIRECTION_FIELD,
type: ItemType.Select,
label: 'Sort Direction',
values: [
{ name: 'Ascending', value: 'asc' },
{ name: 'Descending', value: 'desc' }
]
};
if (this.sort && this.sort.direction) {
sortDirectionItem['default'] = this.sort.direction;
}
this.sortDirectionItem = new FsFilterConfigItem(sortDirectionItem, this, route, persists);
}
}
/**
* @return {?}
*/
updateModelValues() {
this.items.forEach((/**
* @param {?} filter
* @return {?}
*/
(filter$$1) => {
filter$$1.model = clone(filter$$1.tmpModel);
}));
if (this.sortByItem) {
this.sortByItem.model = clone(this.sortByItem.tmpModel);
}
if (this.sortDirectionItem) {
this.sortDirectionItem.model = clone(this.sortDirectionItem.tmpModel);
}
}
/**
* @param {?=} opts
* @return {?}
*/
gets(opts = {}) {
/** @type {?} */
const query = {};
for (const filter$$1 of this.items) {
/** @type {?} */
let value = clone(filter$$1.model);
if (filter$$1.type == ItemType.Select) {
if (filter$$1.multiple) {
if (filter$$1.isolate) {
if (!Array.isArray(filter$$1.model) || !filter$$1.model.length) {
value = list(filter$$1.values, 'value');
}
}
if (filter$$1.model && filter$$1.model.indexOf('__all') > -1) {
value = null;
}
}
else {
if (filter$$1.isolate) {
if (filter$$1.model == '__all') {
value = list(filter$$1.values, 'value');
}
}
else {
if (filter$$1.model == '__all') {
value = null;
}
}
}
}
else if (filter$$1.type == ItemType.AutoCompleteChips || filter$$1.type === ItemType.Chips) {
if (Array.isArray(filter$$1.model) && filter$$1.model.length && !opts.expand) {
value = list(filter$$1.model, 'value');
}
}
else if (filter$$1.type == ItemType.Checkbox) {
value = filter$$1.model ? filter$$1.checked : filter$$1.unchecked;
}
// @TODO
if (isEmpty(value, { zero: true })) {
continue;
}
if (filter$$1.type == ItemType.Date || filter$$1.type == ItemType.DateTime) {
if (value && isValid(value) && isDate(value)) {
value = simpleFormat(value);
}
}
else if (filter$$1.type == ItemType.DateRange || filter$$1.type == ItemType.DateTimeRange) {
/** @type {?} */
const from = value.from;
/** @type {?} */
const to = value.to;
value = {};
if (from) {
value.from = format(from, 'yyyy-MM-dd\THH:mm:ssxxxxx');
}
if (to) {
value.to = format(to, 'yyyy-MM-dd\THH:mm:ssxxxxx');
}
}
else if (filter$$1.type == ItemType.AutoComplete) {
if (isEmpty(filter$$1.model.value, { zero: true })) {
continue;
}
value = opts.expand ? filter$$1.model : filter$$1.model.value;
}
if (isObject(filter$$1.names) && opts.names !== false) {
for (const key in filter$$1.names) {
if (value[filter$$1.names[key]]) {
query[key] = value[filter$$1.names[key]];
}
}
}
else {
query[filter$$1.name] = value;
}
}
if (opts.flatten) {
for (const name in query) {
if (Array.isArray(query[name])) {
query[name] = query[name].join(',');
}
}
}
return query;
}
/**
* @return {?}
*/
getSort() {
/** @type {?} */
let sortBy = this.getSortByValue();
sortBy = sortBy === '__all' ? null : sortBy;
/** @type {?} */
let sortDirection = this.getSortDirectionValue();
sortDirection = sortDirection === '__all' ? null : sortDirection;
return {
value: sortBy,
direction: sortDirection,
};
}
/**
* @return {?}
*/
getSortByValue() {
return this.sortByItem ? this.sortByItem.model : null;
}
/**
* @return {?}
*/
getSortDirectionValue() {
return this.sortDirectionItem ? this.sortDirectionItem.model : null;
}
/**
* @param {?} sort
* @return {?}
*/
updateSort(sort) {
if (sort.sortBy) {
this.sortByItem.model = sort.sortBy;
}
if (sort.sortDirection) {
this.sortDirectionItem.model = sort.sortDirection;
}
}
/**
* @return {?}
*/
getFilledItems() {
return this.items.reduce((/**
* @param {?} acc
* @param {?} filter
* @return {?}
*/
(acc, filter$$1) => {
switch (filter$$1.type) {
case ItemType.Select:
{
/** @type {?} */
const multipleIsoldated = filter$$1.multiple
&& filter$$1.isolate
&& Array.isArray(filter$$1.model)
&& !!filter$$1.model.length
&& filter$$1.model.indexOf('__all') === -1;
/** @type {?} */
const multipleHasSelectedValues = filter$$1.multiple
&& Array.isArray(filter$$1.model)
&& filter$$1.model.length
&& filter$$1.model.indexOf('__all') === -1;
/** @type {?} */
const selectedValues = !filter$$1.multiple && filter$$1.model && filter$$1.model !== '__all';
if (multipleIsoldated || multipleHasSelectedValues || selectedValues) {
acc.push(filter$$1);
}
}
break;
case ItemType.AutoCompleteChips:
{
if (Array.isArray(filter$$1.model) && filter$$1.model.length) {
acc.push(filter$$1);
}
}
break;
case ItemType.Checkbox:
{
if (filter$$1.model) {
acc.push(filter$$1);
}
}
break;
case ItemType.DateRange:
case ItemType.DateTimeRange:
{
if (filter$$1.model.from || filter$$1.model.to) {
acc.push(filter$$1);
}
}
break;
default: {
if (filter$$1.model &&
filter$$1 !== this.searchInput &&
(!isEmpty(filter$$1.model, { zero: true }) || !isEmpty(filter$$1.model.value, { zero: true }))) {
acc.push(filter$$1);
}
}
}
return acc;
}), []);
}
/**
* @return {?}
*/
filtersClear() {
for (const filter$$1 of this.items) {
filter$$1.clear();
}
if (this.sortByItem) {
if (this.sort) {
this.sortByItem.model = this.sort.value;
}
else {
this.sortByItem.clear();
}
}
if (this.sortDirectionItem) {
if (this.sort) {
this.sortDirectionItem.model = this.sort.direction;
}
else {
this.sortDirectionItem.clear();
}
}
}
/**
* @return {?}
*/
loadValuesForPendingItems() {
this.items
.filter((/**
* @param {?} item
* @return {?}
*/
(item) => item.hasPendingValues))
.forEach((/**
* @param {?} item
* @return {?}
*/
(item) => item.loadRemoteValues()));
}
/**
* @return {?}
*/
destroy() {
this._destroy$.next();
this._destroy$.complete();
}
}
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfig.prototype, "load", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfig.prototype, "persist", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfig.prototype, "inline", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfig.prototype, "autofocus", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfig.prototype, "chips", void 0);
__decorate([
Alias('sorts'),
__metadata("design:type", Array)
], FsFilterConfig.prototype, "sortValues", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfig.prototype, "sort", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfig.prototype, "sortDirection", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfig.prototype, "queryParam", void 0);
__decorate([
Alias(),
__metadata("design:type", Object)
], FsFilterConfig.prototype, "namespace", void 0);
__decorate([
Alias(),
__metadata("design:type", Function)
], FsFilterConfig.prototype, "init", void 0);
__decorate([
Alias(),
__metadata("design:type", Function)
], FsFilterConfig.prototype, "change", void 0);
__decorate([
Alias(),
__metadata("design:type", Function)
], FsFilterConfig.prototype, "reload", void 0);
__decorate([
Alias(),
__metadata("design:type", Function)
], FsFilterConfig.prototype, "sortChange", void 0);
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?} obj1
* @param {?} obj2
* @return {?}
*/
function objectsAreEquals(obj1, obj2) {
/** @type {?} */
const oldKeys = Object.keys(obj1);
/** @type {?} */
const currKeys = Object.keys(obj2);
if (oldKeys.length !== currKeys.length) {
return false;
}
for (const key in obj1) {
if (obj1.hasOwnProperty(key)) {
/** @type {?} */
const oldItem = obj1[key];
/** @type {?} */
const currItem = obj2[key];
/** @type {?} */
const isArrays = Array.isArray(oldItem) && Array.isArray(currItem);
/** @type {?} */
const isObjects = isObject(oldItem) && isObject(currItem);
if (isArrays && !arraysAreEquals(oldItem, currItem)) {
return false;
}
else if (isObjects && !objectsAreEquals(oldItem, currItem)) {
return false;
}
else if (!isArrays && !isObjects && oldItem !== currItem) {
return false;
}
}
}
return true;
}
/**
* @param {?} arr1
* @param {?} arr2
* @return {?}
*/
function arraysAreEquals(arr1, arr2) {
if (arr1.length !== arr2.length) {
return false;
}
for (const el of arr1) {
if (arr2.indexOf(el) === -1) {
return false;
}
}
return true;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class QueryParams {
/**
* @param {?} _router
* @param {?} _route
* @param {?} _filterItems
*/
constructor(_router, _route, _filterItems) {
this._router = _router;
this._route = _route;
this._filterItems = _filterItems;
this._queryKeys = [];
this._queryParamsToFilter(this._route.snapshot.queryParams, this._filterItems);
}
/**
* Update query with filter values
* @param {?} filterParams
* @return {?}
*/
updateQueryParams(filterParams) {
// transform selected filter values to query string
/** @type {?} */
const newParams = this._filterToQueryParams(filterParams, this._filterItems);
// Remove empty keys
this._clearKeys(newParams);
// Store query keys
this._queryKeys = Object.keys(newParams);
// Update query
this._router.navigate([], {
relativeTo: this._route,
queryParams: newParams,
queryParamsHandling: 'merge'
}).then((/**
* @return {?}
*/
() => { }));
}
/**
* Transformation for selected filter values to query string
* @private
* @param {?} params
* @param {?} items
* @return {?}
*/
_filterToQueryParams(params, items) {
// selected filter keys
/** @type {?} */
const filterKeys = Object.keys(params);
return filterKeys.reduce((/**
* @param {?} acc
* @param {?} filterKey
* @return {?}
*/
(acc, filterKey) => {
// looking filter item
/** @type {?} */
const filterItem = items.find((/**
* @param {?} item
* @return {?}
*/
(item) => item.name === filterKey));
if (filterItem) {
if (filterItem.type === ItemType.Range) {
acc[filterKey] = [params[filterKey].min, params[filterKey].max].join(',');
}
else if (filterItem.type === ItemType.Select && filterItem.multiple && filterItem.model.length > 0) {
acc[filterKey] = filterItem.model.join(',');
}
else if (filterItem.type === ItemType.AutoComplete) {
acc[filterKey] = [filterItem.model.value, filterItem.model.name].join(',');
}
else if (filterItem.type === ItemType.AutoCompleteChips) {
acc[filterKey] = filterItem.model.map((/**
* @param {?} item
* @return {?}
*/
(item) => [item.value, item.name].join(','))).join(';');
}
else {
acc[filterKey] = params[filterKey];
}
}
return acc;
}), {});
}
/**
* Parse query and update filter values
* @private
* @param {?} params
* @param {?} items
* @return {?}
*/
_queryParamsToFilter(params, items) {
this._queryKeys = Object.keys(params);
return this._queryKeys.forEach((/**
* @param {?} queryKey
* @return {?}
*/
(queryKey) => {
/** @type {?} */
const filterItem = items.find((/**
* @param {?} item
* @return {?}
*/
(item) => item.name === queryKey));
if (filterItem) {
if (filterItem.type === ItemType.Select && filterItem.multiple) {
/** @type {?} */
const values = params[queryKey]
.split(',');
filterItem.parseAndSetValue(values);
}
else if (filterItem.type === ItemType.Range) {
if (params[queryKey] && isString(params[queryKey])) {
/** @type {?} */
const filterParts = params[queryKey].split(',');
filterItem.model = {
min: filterParts[0],
max: filterParts[1]
};
}
}
else if (filterItem.type === ItemType.Chips) {
/** @type {?} */
const chipIds = params[queryKey]
.split(',')
.map((/**
* @param {?} value
* @return {?}
*/
(value) => +value));
filterItem.parseAndSetValue(chipIds);
}
else if (filterItem.type === ItemType.Checkbox) {
filterItem.parseAndSetValue(params[queryKey] === 'true');
}
else if (filterItem.type === ItemType.AutoComplete) {
/** @type {?} */
const filterParts = params[queryKey].split(',');
filterItem.model = {
name: filterParts[1],
value: +filterParts[0]
};
}
else if (filterItem.type === ItemType.AutoCompleteChips) {
/** @type {?} */
const filterParts = params[queryKey].split(';');
filterItem.model = filterParts.reduce((/**
* @param {?} acc
* @param {?} value
* @return {?}
*/
(acc, value) => {
/** @type {?} */
const chipParts = value.split(',');
acc.push({
name: chipParts[1],
value: +chipParts[0],
});
return acc;
}), []);
}
else {
filterItem.parseAndSetValue(params[queryKey]);
}
}
}));
}
/**
* @private
* @param {?} params
* @return {?}
*/
_clearKeys(params) {
this._queryKeys.forEach((/**
* @param {?} key
* @return {?}
*/
(key) => {
if (!params[key]) {
params[key] = null;
}
}));
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class FilterComponent {
/**
* @param {?} _store
* @param {?} _location
* @param {?} _route
* @param {?} _router
*/
constructor(_store, _location, _route, _router) {
this._store = _store;
this._location = _location;
this._route = _route;
this._router = _router;
this.filter = null;
this.sortUpdate = null;
this.showSortBy = true;
this.showFilterInput = true;
this.changedFilters = [];
this.searchText = '';
this.persists = null;
this.activeFiltersCount = 0;
this.activeFiltersWithInputCount = 0;
this.showFilterMenu = false;
this.modelChanged = new EventEmitter();
this._searchTextInput = null;
this._firstOpen = true;
this._query = {};
this._sort = {};
}
/**
* @param {?} event
* @return {?}
*/
keyEvent(event) {
if (event.code === 'Escape' && this.showFilterMenu) {
this.changeVisibility(false);
}
}
/**
* @param {?} value
* @return {?}
*/
set searchTextInput(value) {
this._searchTextInput = value;
}
/**
* @return {?}
*/
ngOnInit() {
this.config = new FsFilterConfig(this.filter);
this.restorePersistValues();
this.config.initItems(this.filter.items, this._route, this.persists);
if (this.config.queryParam) {
this._queryParams = new QueryParams(this._router, this._route, this.config.items);
}
// Set search input value after restore from STORE
this.updateSearchText();
// Count active filters after restore
this.updateFilledCounter();
this.watchSearchInput();
if (this.sortUpdate) {
this.sortUpdate
.pipe(takeUntil(this.config.destroy$))
.subscribe((/**
* @param {?} data
* @return {?}
*/
(data) => {
this.config.updateSort(data);
}));
}
if (this.config.init) {
this.fireInitCallback();
}
// Avoid ngChanges error
setTimeout((/**
* @return {?}
*/
() => {
if (this._searchTextInput && this.config.autofocus) {
this._searchTextInput.nativeElement.focus();
}
}));
}
/**
* @return {?}
*/
ngOnDestroy() {
if (this.config) {
this.config.destroy();
}
}
/**
*
* Do update value of some field
*
*
* To update text value just pass new text value
*
* public updateSelectValue(val) {
* this.filterEl.updateValues({ keyword: val });
* }
*
* To update select or observable select you could pass suitable value
*
* public updateSelectValue(val: number) {
* this.filterEl.updateValues({ simple_select: val }, { observable_select: val });
* }
*
* To update checkbox value just pass true/false as value
*
* public updateCheckox(val: boolean) {
* this.filterEl.updateValues({ checkbox: val });
* }
*
* To update range value just pass object with min&max object or just with one of targets
*
* Ex.: { min: 10, max 15 }, { min: 5 }, { max 5 }
*
* public updateRange(val) {
* this.filterEl.updateValues({ range: val });
* }
*
* To update autocomplete just pass object with name/value fields
*
* Ex.: { name: 'John Doe', value: 1 }
*
* public updateAutocomplete(val) {
* this.filterEl.updateValues({ autocomplete_user_id: val });
* }
*
* To update autocompletechips just pass:
*
* 1) object with name/value fields - will be appended to existing set of values
*
* { name: 'John Doe', value: 1 }
*
* 2) array of objects - will be appended to existing set of values
*
* [{ name: 'John Doe', value: 1 }, { name: 'Darya Filipova', value: 2 }]
*
* 3) null - clear existing set of values
*
* public updateAutocomplete(val) {
* this.filterEl.updateValues({ autocompletechips_user_id: val });
* }
*
* @param {?} values
* @param {?=} changeEvent
* @return {?}
*/
updateValues(values, changeEvent = true) {
Object.keys(values).forEach((/**
* @param {?} key
* @return {?}
*/
(key) => {
/** @type {?} */
const filterItem = this.config.items.find((/**
* @param {?} item
* @return {?}
*/
(item) => item.name === key));
if (!filterItem) {
return;
}
filterItem.updateValue(values[key]);
if (filterItem === this.config.searchInput) {
this.updateSearchText();
}
}));
this.updateFilledCounter();
if (changeEvent) {
this.filterChange();
}
}
/**
* @return {?}
*/
watchSearchInput() {
this.modelChanged
.pipe(distinctUntilChanged(), debounceTime(500), takeUntil(this.config.destroy$))
.subscribe((/**
* @param {?} value
* @return {?}
*/
(value) => {
this.config.searchInput.model = value;
this.filterChange();
}));
}
/**
* @param {?} text
* @return {?}
*/
modelChange(text) {
this.modelChanged.next(text);
}
/**
* @param {?} event
* @return {?}
*/
backdropClick(event) {
this.switchFilterVisibility(event);
}
/**
* @return {?}
*/
done() {
this.changeVisibility(false);
}
/**
* @param {?=} event
* @return {?}
*/
switchFilterVisibility(event = null) {
if (event) {
event.stopPropagation();
}
this.changeVisibility(!this.showFilterMenu);
}
/**
* @param {?} event
* @return {?}
*/
filterInputClick(event) {
if (['Enter', 'NumpadEnter', 'Escape'].indexOf(event.code) >= 0) {
return this.changeVisibility(false);
}
this.changeVisibility(true);
}
/**
* @param {?} state
* @return {?}
*/
changeVisibility(state) {
this.showFilterMenu = state;
if (this._firstOpen) {
this.config.loadValuesForPendingItems();
this._firstOpen = false;
}
if (this.showFilterMenu) {
wind