UNPKG

@firestitch/filter

Version:
703 lines 60.7 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, EventEmitter, Input, ViewChild, ViewEncapsulation, HostListener, ApplicationRef, Injector } from '@angular/core'; import { Location } from '@angular/common'; import { ActivatedRoute, Router } from '@angular/router'; import { FsStore } from '@firestitch/store'; import { cloneDeep } from 'lodash-es'; import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'; import { isAfter, subMinutes } from 'date-fns'; import { FsFilterConfig } from '../../models/filter-config'; import { ItemType } from '../../models/filter-item'; import { objectsAreEquals } from '../../helpers/compare'; import { QueryParams } from '../../models/query-params'; import { FsDocumentScrollService } from '@firestitch/scroll'; import { FsFilterOverlayService } from '../../services/filter-overlay.service'; import { Subject } from 'rxjs'; export class FilterComponent { /** * @param {?} _store * @param {?} _location * @param {?} _route * @param {?} _router * @param {?} _appRef * @param {?} _injector * @param {?} _documentScrollService * @param {?} _filterOverlay */ constructor(_store, _location, _route, _router, _appRef, _injector, _documentScrollService, _filterOverlay) { this._store = _store; this._location = _location; this._route = _route; this._router = _router; this._appRef = _appRef; this._injector = _injector; this._documentScrollService = _documentScrollService; this._filterOverlay = _filterOverlay; this._config = 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.windowDesktop = false; this._searchTextInput = null; this._firstOpen = true; this._query = {}; this._sort = {}; this._destroy$ = new Subject(); this.updateWindowWidth(); this._filterOverlay.attach$ .pipe(takeUntil(this._destroy$)) .subscribe((/** * @return {?} */ () => { this.showFilterMenu = true; })); this._filterOverlay.detach$ .pipe(takeUntil(this._destroy$)) .subscribe((/** * @return {?} */ () => { this.updateFilledCounter(); this.showFilterMenu = false; })); } /** * @param {?} config * @return {?} */ set setConfig(config) { this.config = config; } /** * @param {?} config * @return {?} */ set setFilter(config) { this.config = config; } /** * @param {?} event * @return {?} */ keyEvent(event) { if (event.code === 'Escape' && this.showFilterMenu) { this.changeVisibility(false); } } /** * @return {?} */ updateWindowWidth() { this.windowDesktop = window.innerWidth > 1200; } /** * @param {?} value * @return {?} */ set searchTextInput(value) { this._searchTextInput = value; } /** * @param {?} config * @return {?} */ set config(config) { this._config = new FsFilterConfig(config); this.restorePersistValues(); this.config.initItems(config.items, this._route, this.persists); this._searchTextItem = this.config.items.find((/** * @param {?} item * @return {?} */ (item) => item.type === ItemType.Keyword)); this.searchText = this._searchTextItem.model; if (this.config.queryParam) { this._queryParams = new QueryParams(this._router, this._route, this.config.items); } // Count active filters after restore this.updateFilledCounter(); this.storePersistValues(); } /** * @return {?} */ get config() { return this._config; } /** * @return {?} */ ngOnInit() { // Avoid ngChanges error setTimeout((/** * @return {?} */ () => { this.focus(); })); 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.init(); } } /** * @return {?} */ focus() { if (this._searchTextInput && this.config.autofocus) { this._searchTextInput.nativeElement.focus(); } } /** * @return {?} */ ngOnDestroy() { this.destroyFilterDrawer(); this._destroy$.next(); this._destroy$.complete(); 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]); })); this.updateFilledCounter(); if (changeEvent) { this.filterChange(); } } /** * @param {?} text * @return {?} */ modelChange(text) { this.modelChanged.next(text); } /** * @return {?} */ hide() { this.changeVisibility(false); } /** * @return {?} */ show() { this.changeVisibility(true); } /** * @param {?} value * @param {?=} event * @return {?} */ changeVisibilityClick(value, event = null) { if (event) { event.stopPropagation(); } this.changeVisibility(value); } /** * @param {?} event * @return {?} */ filterInputEvent(event) { if (!this.windowDesktop) { return; } if (['Enter', 'NumpadEnter', 'Escape'].indexOf(event.code) >= 0) { this.changeVisibility(false); if (this._searchTextInput) { this._searchTextInput.nativeElement.blur(); } } else { this.changeVisibility(true); } } /** * @param {?} state * @return {?} */ changeVisibility(state) { if (state === this.showFilterMenu) { return; } if (!state) { return this.destroyFilterDrawer(); } /** @type {?} */ const notTextItem = this.config.items.find((/** * @param {?} item * @param {?} index * @return {?} */ (item, index) => { return item.type !== ItemType.Keyword; })); if (!notTextItem) { return; } this._filterOverlay.open(this._injector, { items: this.config.items, showSortBy: 'showSortBy', sortBy: this.config.sortByItem, sortDirection: this.config.sortDirectionItem, filterChanged: this.filterChange.bind(this), search: this.search.bind(this), done: this.hide.bind(this), clear: this.clear.bind(this) }); if (this._firstOpen) { this.config.loadValuesForPendingItems(); this._firstOpen = false; } } /** * @param {?} event * @return {?} */ clearSearchText(event) { event.stopPropagation(); this.searchText = ''; this.modelChanged.next(''); } /** * @return {?} */ init() { this._query = this.config.gets({ flatten: true }); this._sort = this.config.getSort(); this.config.init(this._query, this.config.getSort()); } /** * @param {?=} event * @return {?} */ clear(event = null) { if (event) { event.stopPropagation(); } this.searchText = ''; this.changedFilters = []; this.config.filtersClear(); this.activeFiltersCount = 0; this.activeFiltersWithInputCount = 0; this.filterChange(); this.changeVisibility(false); } /** * Close filter window and do change callback * @param {?} event * @return {?} */ search(event) { this.changeVisibilityClick(false, event); this.filterChange(); } /** * @param {?=} event * @return {?} */ reload(event = null) { if (event) { event.stopPropagation(); } /** @type {?} */ const query = this.config.gets({ flatten: true }); if (this.config.reload) { this.config.reload(cloneDeep(query), this.config.getSort()); } } /** * Reset filter * @param {?} item * @return {?} */ resetFilter(item) { /** @type {?} */ const index = this.changedFilters.indexOf(item); if (index > -1) { this.changedFilters.splice(index, 1); item.clear(); } this.change(); } /** * Call change callback and apply new filter values * @return {?} */ change() { this.config.updateModelValues(); /** @type {?} */ const query = this.config.gets({ flatten: true }); /** @type {?} */ const sort = this.config.getSort(); /** @type {?} */ const sortingChanged = ((!sort || !this._sort) && sort !== this._sort) || (sort && this._sort && !objectsAreEquals(this._sort, sort)); if (sortingChanged) { this._sort = sort; if (this.config.sortChange) { this.config.sortChange(cloneDeep(query), sort); } } // This should be an option or a done with an wrapping helper function // because it restricts functionality ie. reload //const queryChanged = !objectsAreEquals(this._query, query); //if (queryChanged) { this._query = query; this.storePersistValues(); this.updateFilledCounter(); if (this.config.change) { this.config.change(cloneDeep(query), sort); } if (this.config.queryParam) { this._queryParams.updateQueryParams(query); } } /** * Do update count of filled filters * @private * @return {?} */ updateFilledCounter() { this.changedFilters = this.config.getFilledItems(); this.changedFilters .filter((/** * @param {?} item * @return {?} */ (item) => item.hasPendingValues)) .forEach((/** * @param {?} item * @return {?} */ (item) => item.loadValues(false))); this.activeFiltersWithInputCount = this.changedFilters .filter((/** * @param {?} item * @return {?} */ (item) => item.type !== ItemType.Keyword)) .length; } /** * Store updated filter data into localstorage * @private * @param {?=} changedItem * @return {?} */ filterChange(changedItem = null) { if (changedItem) { changedItem.checkIfValueChanged(); } this.storePersistValues(); this.change(); } /** * @private * @return {?} */ destroyFilterDrawer() { this._filterOverlay.close(); } /** * @private * @return {?} */ watchSearchInput() { this.modelChanged .pipe(distinctUntilChanged(), debounceTime(500), takeUntil(this.config.destroy$)) .subscribe((/** * @param {?} value * @return {?} */ (value) => { if (this._searchTextItem) { this._searchTextItem.model = value; } this.filterChange(); })); } /** * Restoring values from local storage * @private * @return {?} */ restorePersistValues() { this.persists = this._store.get(this.config.namespace + '-persist', {}); if (this.persists === undefined) { this.persists = {}; } if (this.config.persist) { if (typeof this.config.persist.persist !== 'object') { this.config.persist = { name: this.config.persist }; } if (!this.config.persist.name) { this.config.persist.name = this._location.path(); } if (!this.persists[this.config.persist.name] || !this.persists[this.config.persist.name].data) { this.persists[this.config.persist.name] = { data: {}, date: new Date() }; } if (this.config.persist.timeout) { /** @type {?} */ const date = new Date(this.persists[this.config.persist.name].date); if (isAfter(subMinutes(date, this.config.persist.timeout), new Date())) { this.persists[this.config.persist.name] = { data: {}, date: new Date() }; } } } } /** * Store values to local storage * @private * @return {?} */ storePersistValues() { if (this.config.persist) { this.persists[this.config.persist.name] = { data: this.config.gets({ expand: true, names: false }), date: new Date() }; this._store.set(this.config.namespace + '-persist', this.persists, {}); } } } FilterComponent.decorators = [ { type: Component, args: [{ selector: 'fs-filter', template: "<div class=\"fs-filter\"\n *ngIf=\"config?.items?.length\"\n [ngClass]=\"{\n 'filters-open': showFilterMenu,\n 'no-input': !showFilterInput,\n 'window-desktop': windowDesktop,\n 'keyword-filter': config.keywordFilter\n }\">\n <div fxLayou=\"row\" fxLayoutAlign=\"start center\" class=\"menu-filter\" fxFlex=\"1 1 0\">\n <div class=\"menu-filter-input\" fxFlex=\"grow\">\n <div class=\"main-filter-bar\" fxLayout=\"row\" fxLayoutAlign=\"start center\">\n <form autocomplete=\"off\" role=\"presentation\">\n <mat-form-field\n class=\"filter-input-field\"\n (click)=\"($event)\"\n floatLabel=\"never\">\n <span matPrefix>\n <mat-icon\n matPrefix\n (click)=\"changeVisibilityClick(true, $event)\">search</mat-icon>\n </span>\n\n <input matInput\n [(ngModel)]=\"searchText\"\n name=\"filter-input\"\n #searchTextInput\n (keydown)=\"filterInputEvent($event)\"\n (click)=\"filterInputEvent($event)\"\n class=\"filter-input\"\n (ngModelChange)=\"modelChange(searchText)\">\n\n <mat-placeholder>Search</mat-placeholder>\n <a matSuffix\n *ngIf=\"searchText && showFilterInput\"\n (click)=\"clearSearchText($event)\"\n href=\"javascript:void(0)\"\n class=\"clear\">\n <mat-icon>clear</mat-icon>\n </a>\n <a matSuffix\n (click)=\"reload($event)\"\n href=\"javascript:void(0)\"\n class=\"reload\"\n *ngIf=\"config.reload\">\n <mat-icon>refresh</mat-icon>\n </a>\n <a (click)=\"changeVisibilityClick(true, $event)\"\n matSuffix\n href=\"javascript:void(0)\"\n class=\"filter\"\n *ngIf=\"config.nonKeywordFilters\">\n <mat-icon>filter_list</mat-icon>\n </a>\n <span class=\"active-filters-counter\"\n matSuffix\n (click)=\"changeVisibilityClick(true,$event)\"\n *ngIf=\"!config.chips && activeFiltersCount > 0\">\n {{ activeFiltersCount }}\n </span>\n <span class=\"active-filters-counter\"\n matSuffix\n (click)=\"changeVisibilityClick(true,$event)\"\n *ngIf=\"!config.chips && activeFiltersWithInputCount > 0\">\n {{ activeFiltersWithInputCount }}\n </span>\n </mat-form-field>\n </form>\n </div>\n </div>\n </div>\n <fs-filter-chips\n class=\"filter-chips\"\n *ngIf=\"config.chips\"\n [filters]=\"changedFilters\"\n (remove)=\"resetFilter($event)\"\n [ngClass]=\"{ 'has-filter-chips': activeFiltersWithInputCount }\">\n </fs-filter-chips>\n</div>\n", encapsulation: ViewEncapsulation.None, providers: [ FsFilterOverlayService, ], styles: [".fs-filter{flex-direction:column;box-sizing:border-box;place-content:stretch flex-start;align-items:stretch;max-width:100%;position:relative;margin-bottom:20px}.fs-filter .title{display:none}.fs-filter.no-input .filter-input-field .mat-input-infix,.fs-filter.no-input .filter-input-field .mat-input-prefix,.fs-filter.no-input .filter-input-field .mat-input-underline{display:none!important}.fs-filter .results{min-height:90px;position:relative;overflow-x:auto;overflow-y:hidden}.fs-filter .status{position:relative}.fs-filter .status .progress-infinite{position:absolute;top:0;width:100%}.fs-filter .filter-chips{display:block}.fs-filter .menu-filter{position:relative}.fs-filter .menu-filter .search{top:8px;position:absolute;margin-left:1px;left:0}.fs-filter .menu-filter .search mat-icon{-webkit-transform:scale(.9);transform:scale(.9)}.fs-filter .menu-filter .menu-filter-input{width:100%}.fs-filter .menu-filter .menu-filter-input .main-filter-bar{height:40px}.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-input-infix{padding-bottom:.3em}.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-prefix,.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-suffix{align-self:flex-end;display:flex;align-items:center;white-space:nowrap}.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-prefix a,.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-prefix mat-icon,.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-suffix a,.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-suffix mat-icon{cursor:pointer;color:initial}.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-prefix a:hover,.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-prefix mat-icon:hover,.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-suffix a:hover,.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-suffix mat-icon:hover{color:inherit}.fs-filter .menu-filter .menu-filter-input .main-filter-bar .mat-form-field-infix{width:auto}.fs-filter .infinite-records{color:#999;font-size:13px;margin-left:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}.fs-filter .infinite-records .order-toggle{cursor:pointer;padding-left:4px}.fs-filter.keyword-filter .filter-input-field .filter{display:none}.fs-filter.keyword-filter .filter-input-field .mat-form-field-infix,.fs-filter.keyword-filter .filter-input-field .mat-form-field-prefix,.fs-filter.keyword-filter .filter-input-field .mat-form-field-underline{visibility:visible}.main-filter-bar{overflow:hidden}.main-filter-bar .filter-input-field,.main-filter-bar form{width:100%}.main-filter-bar .filter-input-field .mat-form-field-infix,.main-filter-bar .filter-input-field .mat-form-field-prefix,.main-filter-bar .filter-input-field .mat-form-field-underline{visibility:hidden}.main-filter-bar .filter-input-field .mat-form-field-underline{bottom:auto}.main-filter-bar .filter-input-field .mat-form-field-infix{border-top:0}.main-filter-bar .filter-input-field .mat-form-field-wrapper{padding-bottom:0}.main-filter-bar .filter-input-field .mat-form-field-flex{align-items:center}.active-filters-counter{min-width:22px;line-height:22px;height:22px;-webkit-transform:scale(.65);transform:scale(.65);font-size:116%;margin-left:-2px;background:#ccc;border-radius:50%;text-align:center;padding:3px;color:#fff;cursor:pointer}.active-filters-counter.with-input{display:none}@media screen and (max-width:1199px){.main-filter-bar .filter-input-field .filter{display:block!important}}@media screen and (min-width:1200px){body.fs-filter-open{margin-right:350px}.fs-filter-backdrop{display:none}}body.fs-filter-open::-webkit-scrollbar{width:0;background:0 0}"] }] } ]; /** @nocollapse */ FilterComponent.ctorParameters = () => [ { type: FsStore }, { type: Location }, { type: ActivatedRoute }, { type: Router }, { type: ApplicationRef }, { type: Injector }, { type: FsDocumentScrollService }, { type: FsFilterOverlayService } ]; FilterComponent.propDecorators = { setConfig: [{ type: Input, args: ['config',] }], setFilter: [{ type: Input, args: ['filter',] }], sortUpdate: [{ type: Input }], showSortBy: [{ type: Input }], showFilterInput: [{ type: Input }], keyEvent: [{ type: HostListener, args: ['window:keyup', ['$event'],] }], updateWindowWidth: [{ type: HostListener, args: ['window:resize',] }], searchTextInput: [{ type: ViewChild, args: ['searchTextInput',] }] }; if (false) { /** * @type {?} * @protected */ FilterComponent.prototype._config; /** @type {?} */ FilterComponent.prototype.sortUpdate; /** @type {?} */ FilterComponent.prototype.showSortBy; /** @type {?} */ FilterComponent.prototype.showFilterInput; /** @type {?} */ FilterComponent.prototype.changedFilters; /** @type {?} */ FilterComponent.prototype.searchText; /** @type {?} */ FilterComponent.prototype.persists; /** @type {?} */ FilterComponent.prototype.activeFiltersCount; /** @type {?} */ FilterComponent.prototype.activeFiltersWithInputCount; /** @type {?} */ FilterComponent.prototype.showFilterMenu; /** @type {?} */ FilterComponent.prototype.modelChanged; /** @type {?} */ FilterComponent.prototype.windowDesktop; /** * @type {?} * @private */ FilterComponent.prototype._filterDrawerRef; /** * @type {?} * @private */ FilterComponent.prototype._searchTextItem; /** * @type {?} * @private */ FilterComponent.prototype._searchTextInput; /** * @type {?} * @private */ FilterComponent.prototype._firstOpen; /** * @type {?} * @private */ FilterComponent.prototype._query; /** * @type {?} * @private */ FilterComponent.prototype._queryParams; /** * @type {?} * @private */ FilterComponent.prototype._sort; /** * @type {?} * @private */ FilterComponent.prototype._destroy$; /** * @type {?} * @private */ FilterComponent.prototype._store; /** * @type {?} * @private */ FilterComponent.prototype._location; /** * @type {?} * @private */ FilterComponent.prototype._route; /** * @type {?} * @private */ FilterComponent.prototype._router; /** * @type {?} * @private */ FilterComponent.prototype._appRef; /** * @type {?} * @private */ FilterComponent.prototype._injector; /** * @type {?} * @private */ FilterComponent.prototype._documentScrollService; /** * @type {?} * @private */ FilterComponent.prototype._filterOverlay; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BmaXJlc3RpdGNoL2ZpbHRlci8iLCJzb3VyY2VzIjpbImFwcC9jb21wb25lbnRzL2ZpbHRlci9maWx0ZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULFlBQVksRUFDWixLQUFLLEVBR0wsU0FBUyxFQUNULGlCQUFpQixFQUNqQixZQUFZLEVBQ1osY0FBYyxFQUNkLFFBQVEsRUFDVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFNUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRS9DLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEVBQXNCLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM3RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUMvRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBWS9CLE1BQU0sT0FBTyxlQUFl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QVksU0FBQyxlQUFlOzhCQUs1QixTQUFTLFNBQUMsaUJBQWlCOzs7Ozs7O0lBMUI1QixrQ0FBeUM7O0lBVXpDLHFDQUFxRDs7SUFDckQscUNBQXVDOztJQUN2QywwQ0FBdUM7O0lBbUJ2Qyx5Q0FBMkI7O0lBQzNCLHFDQUF1Qjs7SUFDdkIsbUNBQXVCOztJQUN2Qiw2Q0FBOEI7O0lBQzlCLHNEQUF1Qzs7SUFDdkMseUNBQThCOztJQUM5Qix1Q0FBeUM7O0lBQ3pDLHdDQUE2Qjs7Ozs7SUFFN0IsMkNBQXlCOzs7OztJQUN6QiwwQ0FBNEM7Ozs7O0lBQzVDLDJDQUE0Qzs7Ozs7SUFDNUMscUNBQTBCOzs7OztJQUMxQixpQ0FBb0I7Ozs7O0lBQ3BCLHVDQUFrQzs7Ozs7SUFDbEMsZ0NBQW1COzs7OztJQUNuQixvQ0FBa0M7Ozs7O0lBR2hDLGlDQUF1Qjs7Ozs7SUFDdkIsb0NBQTJCOzs7OztJQUMzQixpQ0FBOEI7Ozs7O0lBQzlCLGtDQUF1Qjs7Ozs7SUFDdkIsa0NBQStCOzs7OztJQUMvQixvQ0FBMkI7Ozs7O0lBQzNCLGlEQUF1RDs7Ozs7SUFDdkQseUNBQThDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgVmlld0NoaWxkLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgSG9zdExpc3RlbmVyLFxuICBBcHBsaWNhdGlvblJlZixcbiAgSW5qZWN0b3Jcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMb2NhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcblxuaW1wb3J0IHsgRnNTdG9yZSB9IGZyb20gJ0BmaXJlc3RpdGNoL3N0b3JlJztcblxuaW1wb3J0IHsgY2xvbmVEZWVwIH0gZnJvbSAnbG9kYXNoLWVzJztcbmltcG9ydCB7IGRlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbENoYW5nZWQsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IGlzQWZ0ZXIsIHN1Yk1pbnV0ZXMgfSBmcm9tICdkYXRlLWZucyc7XG5cbmltcG9ydCB7IEZzRmlsdGVyQ29uZmlnIH0gZnJvbSAnLi4vLi4vbW9kZWxzL2ZpbHRlci1jb25maWcnO1xuaW1wb3J0IHsgRnNGaWx0ZXJDb25maWdJdGVtLCBJdGVtVHlwZSB9IGZyb20gJy4uLy4uL21vZGVscy9maWx0ZXItaXRlbSc7XG5pbXBvcnQgeyBvYmplY3RzQXJlRXF1YWxzIH0gZnJvbSAnLi4vLi4vaGVscGVycy9jb21wYXJlJztcbmltcG9ydCB7IFF1ZXJ5UGFyYW1zIH0gZnJvbSAnLi4vLi4vbW9kZWxzL3F1ZXJ5LXBhcmFtcyc7XG5pbXBvcnQgeyBGc0RvY3VtZW50U2Nyb2xsU2VydmljZSB9IGZyb20gJ0BmaXJlc3RpdGNoL3Njcm9sbCc7XG5pbXBvcnQgeyBGc0ZpbHRlck92ZXJsYXlTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZmlsdGVyLW92ZXJsYXkuc2VydmljZSc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZnMtZmlsdGVyJyxcbiAgc3R5bGVVcmxzOiBbICcuL2ZpbHRlci5jb21wb25lbnQuc2NzcycgXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2ZpbHRlci5jb21wb25lbnQuaHRtbCcsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHByb3ZpZGVyczogW1xuICAgIEZzRmlsdGVyT3ZlcmxheVNlcnZpY2UsXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgRmlsdGVyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuXG4gIHByb3RlY3RlZCBfY29uZmlnOiBGc0ZpbHRlckNvbmZpZyA9IG51bGw7XG5cbiAgQElucHV0KCdjb25maWcnKSBzZXQgc2V0Q29uZmlnKGNvbmZpZykge1xuICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICB9XG5cbiAgQElucHV0KCdmaWx0ZXInKSBzZXQgc2V0RmlsdGVyKGNvbmZpZykge1xuICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICB9XG5cbiAgQElucHV0KCkgcHVibGljIHNvcnRVcGRhdGU6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbnVsbDtcbiAgQElucHV0KCkgcHVibGljIHNob3dTb3J0Qnk6IGFueSA9IHRydWU7XG4gIEBJbnB1dCgpIHB1YmxpYyBzaG93RmlsdGVySW5wdXQgPSB0cnVlO1xuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXl1cCcsIFsnJGV2ZW50J10pXG4gIGtleUV2ZW50KGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgaWYgKGV2ZW50LmNvZGUgPT09ICdFc2NhcGUnICYmIHRoaXMuc2hvd0ZpbHRlck1lbnUpIHtcbiAgICAgIHRoaXMuY2hhbmdlVmlzaWJpbGl0eShmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OnJlc2l6ZScpXG4gIHVwZGF0ZVdpbmRvd1dpZHRoKCkge1xuICAgIHRoaXMud2luZG93RGVza3RvcCA9IHdpbmRvdy5pbm5lcldpZHRoID4gMTIwMDtcbiAgfVxuXG4gIEBWaWV3Q2hpbGQoJ3NlYXJjaFRleHRJbnB1dCcpXG4gIHNldCBzZWFyY2hUZXh0SW5wdXQodmFsdWUpIHtcbiAgICB0aGlzLl9zZWFyY2hUZXh0SW5wdXQgPSB2YWx1ZTtcbiAgfVxuXG4gIHB1YmxpYyBjaGFuZ2VkRmlsdGVycyA9IFtdO1xuICBwdWJsaWMgc2VhcmNoVGV4dCA9ICcnO1xuICBwdWJsaWMgcGVyc2lzdHMgPSBudWxsO1xuICBwdWJsaWMgYWN0aXZlRmlsdGVyc0NvdW50ID0gMDtcbiAgcHVibGljIGFjdGl2ZUZpbHRlcnNXaXRoSW5wdXRDb3VudCA9IDA7XG4gIHB1YmxpYyBzaG93RmlsdGVyTWVudSA9IGZhbHNlO1xuICBwdWJsaWMgbW9kZWxDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBwdWJsaWMgd2luZG93RGVza3RvcCA9IGZhbHNlO1xuXG4gIHByaXZhdGUgX2ZpbHRlckRyYXdlclJlZjtcbiAgcHJpdmF0ZSBfc2VhcmNoVGV4dEl0ZW06IEZzRmlsdGVyQ29uZmlnSXRlbTtcbiAgcHJpdmF0ZSBfc2VhcmNoVGV4dElucHV0OiBFbGVtZW50UmVmID0gbnVsbDtcbiAgcHJpdmF0ZSBfZmlyc3RPcGVuID0gdHJ1ZTtcbiAgcHJpdmF0ZSBfcXVlcnkgPSB7fTtcbiAgcHJpdmF0ZSBfcXVlcnlQYXJhbXM6IFF1ZXJ5UGFyYW1zO1xuICBwcml2YXRlIF9zb3J0ID0ge307XG4gIHByaXZhdGUgX2Rlc3Ryb3kkID0gbmV3IFN1YmplY3QoKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9zdG9yZTogRnNTdG9yZSxcbiAgICBwcml2YXRlIF9sb2NhdGlvbjogTG9jYXRpb24sXG4gICAgcHJpdmF0ZSBfcm91dGU6IEFjdGl2YXRlZFJvdXRlLFxuICAgIHByaXZhdGUgX3JvdXRlcjogUm91dGVyLFxuICAgIHByaXZhdGUgX2FwcFJlZjogQXBwbGljYXRpb25SZWYsXG4gICAgcHJpdmF0ZSBfaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIHByaXZhdGUgX2RvY3VtZW50U2Nyb2xsU2VydmljZTogRnNEb2N1bWVudFNjcm9sbFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBfZmlsdGVyT3ZlcmxheTogRnNGaWx0ZXJPdmVybGF5U2VydmljZSxcbiAgKSB7XG4gICAgdGhpcy51cGRhdGVXaW5kb3dXaWR0aCgpO1xuXG4gICAgdGhpcy5fZmlsdGVyT3ZlcmxheS5hdHRhY2gkXG4gICAgLnBpcGUoXG4gICAgIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JClcbiAgICApXG4gICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLnNob3dGaWx0ZXJNZW51ID0gdHJ1ZTtcbiAgICB9KTtcblxuICAgIHRoaXMuX2ZpbHRlck92ZXJsYXkuZGV0YWNoJFxuICAgIC5waXBlKFxuICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKVxuICAgIClcbiAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIHRoaXMudXBkYXRlRmlsbGVkQ291bnRlcigpO1xuICAgICAgdGhpcy5zaG93RmlsdGVyTWVudSA9IGZhbHNlO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHNldCBjb25maWcoY29uZmlnKSB7XG4gICAgdGhpcy5fY29uZmlnID0gbmV3IEZzRmlsdGVyQ29uZmlnKGNvbmZpZyk7XG4gICAgdGhpcy5yZXN0b3JlUGVyc2lzdFZhbHVlcygpO1xuICAgIHRoaXMuY29uZmlnLmluaXRJdGVtcyhjb25maWcuaXRlbXMsIHRoaXMuX3JvdXRlLCB0aGlzLnBlcnNpc3RzKTtcblxuICAgIHRoaXMuX3NlYXJjaFRleHRJdGVtID0gdGhpcy5jb25maWcuaXRlbXMuZmluZCgoaXRlbSkgPT4gaXRlbS50eXBlID09PSBJdGVtVHlwZS5LZXl3b3JkKTtcbiAgICB0aGlzLnNlYXJjaFRleHQgPSB0aGlzLl9zZWFyY2hUZXh0SXRlbS5tb2RlbDtcblxuICAgIGlmICh0aGlzLmNvbmZpZy5xdWVyeVBhcmFtKSB7XG4gICAgICB0aGlzLl9xdWVyeVBhcmFtcyA9IG5ldyBRdWVyeVBhcmFtcyh0aGlzLl9yb3V0ZXIsIHRoaXMuX3JvdXRlLCB0aGlzLmNvbmZpZy5pdGVtcyk7XG4gICAgfVxuXG4gICAgLy8gQ291bnQgYWN0aXZlIGZpbHRlcnMgYWZ0ZXIgcmVzdG9yZVxuICAgIHRoaXMudXBkYXRlRmlsbGVkQ291bnRlcigpO1xuXG4gICAgdGhpcy5zdG9yZVBlcnNpc3RWYWx1ZXMoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgY29uZmlnKCkge1xuICAgIHJldHVybiB0aGlzLl9jb25maWc7XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKSB7XG5cbiAgICAvLyBBdm9pZCBuZ0NoYW5nZXMgZXJyb3JcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuZm9jdXMoKTtcbiAgICB9KTtcblxuICAgIHRoaXMud2F0Y2hTZWFyY2hJbnB1dCgpO1xuXG4gICAgaWYgKHRoaXMuc29ydFVwZGF0ZSkge1xuICAgICAgdGhpcy5zb3J0VXBkYXRlXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIHRha2VVbnRpbCh0aGlzLmNvbmZpZy5kZXN0cm95JCksXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgoZGF0YSkgPT4ge1xuICAgICAgICAgIHRoaXMuY29uZmlnLnVwZGF0ZVNvcnQoZGF0YSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZy5pbml0KSB7XG4gICAgICB0aGlzLmluaXQoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZm9jdXMoKSB7XG4gICAgaWYgKHRoaXMuX3NlYXJjaFRleHRJbnB1dCAmJiB0aGlzLmNvbmZpZy5hdXRvZm9jdXMpIHtcbiAgICAgIHRoaXMuX3NlYXJjaFRleHRJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG5nT25EZXN0cm95KCkge1xuXG4gICAgdGhpcy5kZXN0cm95RmlsdGVyRHJhd2VyKCk7XG4gICAgdGhpcy5fZGVzdHJveSQubmV4dCgpO1xuICAgIHRoaXMuX2Rlc3Ryb3kkLmNvbXBsZXRlKCk7XG5cbiAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgIHRoaXMuY29uZmlnLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogRG8gdXBkYXRlIHZhbHVlIG9mIHNvbWUgZmllbGRcbiAgICpcbiAgICogQHBhcmFtIHthbnl9IHZhbHVlcyAtIHZhbHVlcyBmb3IgdXBkYXRlXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gY2hhbmdlRXZlbnQgLSBzaG91bGQgY2hhbmdlIGV2ZW50IHRvIGJlIGZpcmVkXG4gICAqXG4gICAqIFRvIHVwZGF0ZSB0ZXh0IHZhbHVlIGp1c3QgcGFzcyBuZXcgdGV4dCB2YWx1ZVxuICAgKlxuICAgKiBwdWJsaWMgdXBkYXRlU2VsZWN0VmFsdWUodmFsKSB7XG4gICAqICAgdGhpcy5maWx0ZXJFbC51cGRhdGVWYWx1ZXMoeyBrZXl3b3JkOiB2YWwgfSk7XG4gICAqIH1cbiAgICpcbiAgICogVG8gdXBkYXRlIHNlbGVjdCBvciBvYnNlcnZhYmxlIHNlbGVjdCB5b3UgY291bGQgcGFzcyBzdWl0YWJsZSB2YWx1ZVxuICAgKlxuICAgKiBwdWJsaWMgdXBkYXRlU2VsZWN0VmFsdWUodmFsOiBudW1iZXIpIHtcbiAgICogICB0aGlzLmZpbHRlckVsLnVwZGF0ZVZhbHVlcyh7IHNpbXBsZV9zZWxlY3Q6IHZhbCB9LCB7IG9ic2VydmFibGVfc2VsZWN0OiB2YWwgfSk7XG4gICAqIH1cbiAgICpcbiAgICogVG8gdXBkYXRlIGNoZWNrYm94IHZhbHVlIGp1c3QgcGFzcyB0cnVlL2ZhbHNlIGFzIHZhbHVlXG4gICAqXG4gICAqIHB1YmxpYyB1cGRhdGVDaGVja294KHZhbDogYm9vbGVhbikge1xuICAgKiAgIHRoaXMuZmlsdGVyRWwudXBkYXRlVmFsdWVzKHsgY2hlY2tib3g6IHZhbCB9KTtcbiAgICogfVxuICAgKlxuICAgKiBUbyB1cGRhdGUgcmFuZ2UgdmFsdWUganVzdCBwYXNzIG9iamVjd