UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

233 lines 31 kB
import { inject, Injectable, signal } from '@angular/core'; import { BehaviorSubject, Subject } from 'rxjs'; import { distinctUntilChanged, filter, map, skip, switchMap, tap } from 'rxjs/operators'; import { DEFAULT_INTERVAL_STATE, DEFAULT_INTERVAL_VALUE, GLOBAL_CONTEXT_AUTO_REFRESH } from './widget-auto-refresh-context.model'; import { ActivatedRoute, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router'; import * as i0 from "@angular/core"; export class WidgetGlobalAutoRefreshService { constructor() { /** * A BehaviorSubject that tracks the number of loading operations in progress. * Initialized with a count of 0. */ this.loadingCount$ = new BehaviorSubject(0); /** * An Observable that emits a boolean indicating whether any widgets with global refresh option are currently loading. * The value is true if the loading count is non-zero, and false if the loading count is zero. * Uses distinctUntilChanged() to emit only when the boolean value changes. */ this.isLoadingWidgets$ = this.loadingCount$.pipe(distinctUntilChanged(), map(count => count !== 0)); /** * Object containing behavior subjects for managing auto-refresh settings. */ this.autoRefreshSettings = { /** * BehaviorSubject that emits the current state of auto-refresh button. * Defaults to DEFAULT_INTERVAL_STATE. */ isEnabled$: new BehaviorSubject(DEFAULT_INTERVAL_STATE), /** * BehaviorSubject that emits the current auto-refresh interval value. * Defaults to DEFAULT_INTERVAL_VALUE. */ refreshInterval$: new BehaviorSubject(DEFAULT_INTERVAL_VALUE), /** * BehaviorSubject that emits whether auto-refresh has been manually disabled by the user. * Defaults to false. */ userDisabledManually$: new BehaviorSubject(false) }; /** * Object containing subjects for managing countdown actions. */ this.countdownActions = { /** * Subject used to stop the countdown. */ stop$: new Subject(), /** * Subject used to reset the countdown. */ reset$: new Subject(), /** * Subject that emits when the countdown has ended. */ countdownEnded$: new Subject() }; /** * Subject that emits when a dashboard save operation is triggered. */ this.onDashboardSave$ = new Subject(); /** * A signal representing the number of widgets with the global auto-refresh option enabled. */ this.globalRefreshWidgetsCount = signal(0); /** * Tracks the navigation state. * * The signal returns a boolean indicating whether a navigation operation is currently in progress. * It initializes with a default value of `false` and can be toggled to `true` during navigation events from `handleNavigationInProgress$`. */ this.navigationInProgress = signal(false); this.router = inject(Router); this.activatedRoute = inject(ActivatedRoute); } /** * Increments the loading count by 1. */ incrementLoading() { this.loadingCount$.next(this.loadingCount$.value + 1); } /** * Decrements the loading count by 1. */ decrementLoading() { this.loadingCount$.next(this.loadingCount$.value - 1); } /** * Retrieves an observable that emits the value of a Global Auto Refresh query parameter * whenever it changes. The query parameter being tracked is determined by * `GlobalAutoRefreshName.GLOBAL_CONTEXT_AUTO_REFRESH`. * * @returns An observable that emits the parsed value of the `GLOBAL_CONTEXT_AUTO_REFRESH` query parameter. */ getQueryParamChangeValue$() { return this.activatedRoute.queryParams.pipe(map(params => params[GLOBAL_CONTEXT_AUTO_REFRESH]), map(this.parseGlobalAutoRefreshParam)); } /** * Monitors router navigation events and updates the navigation progress state. * * @returns An Observable that emits router events of types NavigationStart, NavigationEnd, * NavigationCancel, and NavigationError. */ handleNavigationInProgress$() { return this.router.events.pipe(filter(event => event instanceof NavigationStart || event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError), tap(e => this.navigationInProgress.set(e instanceof NavigationStart))); } /** * Sets the global auto-refresh query parameter in the current route. * * @param queryParams - An object representing the query parameters to set for the global auto-refresh option. * The existing query parameters will be merged with these. */ async setAutoRefreshQueryParam(queryParams) { if (this.navigationInProgress()) { return; } this.navigationInProgress.set(true); await this.router.navigate([], { relativeTo: this.activatedRoute, queryParams, queryParamsHandling: 'merge' }); this.navigationInProgress.set(false); } /** * Handles changes to the edit mode and updates the isEnabled$ variable. * * - If auto-refresh was manually disabled by the user (`userDisabledManually$` is `true`), auto-refresh will remain disabled regardless of the edit mode state. * - If auto-refresh was not manually disabled, it will be disabled when entering edit mode and enabled when exiting edit mode. * * @param editMode - A boolean indicating the current state of edit mode (`true` if edit mode is active, `false` otherwise). */ onEditModeChange(editMode) { if (this.autoRefreshSettings.userDisabledManually$.getValue()) { this.autoRefreshSettings.isEnabled$.next(false); return; } this.autoRefreshSettings.isEnabled$.next(!editMode); } /** * Returns an Observable that triggers the countdown reset action when loading completes. * * This method creates an Observable that: * - Skips a specified number of initial emissions from `isLoadingWidgets$` based on the `skipInitialBehaviorSubjectEmission$` method. * - Filters out emissions where the loading state is true. * - On emission where the loading state is false, it triggers a countdown reset action. * */ resetCountdownOnLoadingComplete$() { return switchMap(() => this.isLoadingWidgets$.pipe(tap(isLoading => isLoading && this.countdownActions.stop$.next()), filter(loading => !loading), tap(() => this.resetCountdown()))); } /** * Resets the service's settings and parameters to their default values. */ resetServiceToDefaults() { setTimeout(() => !this.navigationInProgress() && this.clearQueryParam()); this.autoRefreshSettings.refreshInterval$.next(DEFAULT_INTERVAL_VALUE); this.autoRefreshSettings.userDisabledManually$.next(false); setTimeout(() => { this.autoRefreshSettings.isEnabled$.next(DEFAULT_INTERVAL_STATE); this.resetLoadingToZero(); this.navigationInProgress.set(false); }); } /** * Resets the countdown timer by emitting a reset action after a short delay. */ resetCountdown() { queueMicrotask(() => this.countdownActions.reset$.next()); } /** * Initializes the auto-refresh countdown logic based on the widget loading state and edit mode. * * This method returns an observable that monitors the widget loading state and triggers specific actions * related to the countdown process. It performs the following steps: * * 1. Skips the initial loading state emitted by `isLoadingWidgets$`. * 2. Stops the countdown if the widgets are currently loading. * 3. Filters out cases where widgets are loading or the application is in edit mode. * 4. Resets the countdown when widgets are not loading and the application is not in edit mode. * * @param editMode$ - A `BehaviorSubject` representing whether the application is currently in edit mode. * * @returns An `Observable<boolean>` that emits the loading state of the widgets after the initialization steps. */ initializeAutoRefreshCountdownLoading$(editMode$) { return this.isLoadingWidgets$.pipe(skip(1), tap(isLoading => isLoading && this.countdownActions.stop$.next()), filter(isWidgetsLoading => !isWidgetsLoading && !editMode$.getValue()), tap(() => this.resetCountdown())); } /** * Parses a string representation of global auto-refresh parameter into a boolean or null. * * Converts the provided `globalAutoRefresh` string into a boolean value or null based on its content: * - Returns `true` if `globalAutoRefresh` is 'true'. * - Returns `false` if `globalAutoRefresh` is 'false'. * - Returns `null` if `globalAutoRefresh` is neither 'true' nor 'false'. * * @param globalAutoRefresh - The string representation of the global auto-refresh parameter. * * @returns A boolean value corresponding to the parsed global auto-refresh state, or null if the input is not 'true' or 'false'. */ parseGlobalAutoRefreshParam(globalAutoRefresh) { return globalAutoRefresh === 'false' ? false : globalAutoRefresh === 'true' ? true : null; } /** * Resets the loading count to zero. */ resetLoadingToZero() { this.loadingCount$.next(0); } /** * Clears the global auto-refresh query parameter by navigating to the current route with the parameter set to null. * */ clearQueryParam() { const queryParams = { globalContextAutoRefresh: null }; this.router.navigate([], { relativeTo: this.activatedRoute, queryParams, queryParamsHandling: 'merge' }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WidgetGlobalAutoRefreshService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WidgetGlobalAutoRefreshService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WidgetGlobalAutoRefreshService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2lkZ2V0LWdsb2JhbC1hdXRvLXJlZnJlc2guc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2NvcmUvZGFzaGJvYXJkL3dpZGdldC1hdXRvLXJlZnJlc2gtY29udGV4dC93aWRnZXQtZ2xvYmFsLWF1dG8tcmVmcmVzaC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZUFBZSxFQUF3QyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RixPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLHNCQUFzQixFQUN0QiwyQkFBMkIsRUFFNUIsTUFBTSxxQ0FBcUMsQ0FBQztBQUM3QyxPQUFPLEVBQ0wsY0FBYyxFQUVkLGdCQUFnQixFQUNoQixhQUFhLEVBQ2IsZUFBZSxFQUNmLGVBQWUsRUFDZixNQUFNLEVBQ1AsTUFBTSxpQkFBaUIsQ0FBQzs7QUFHekIsTUFBTSxPQUFPLDhCQUE4QjtJQUQzQztRQUVFOzs7V0FHRztRQUNLLGtCQUFhLEdBQUcsSUFBSSxlQUFlLENBQVMsQ0FBQyxDQUFDLENBQUM7UUFFdkQ7Ozs7V0FJRztRQUNLLHNCQUFpQixHQUF3QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FDdEUsb0JBQW9CLEVBQUUsRUFDdEIsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUMxQixDQUFDO1FBRUY7O1dBRUc7UUFDSCx3QkFBbUIsR0FBRztZQUNwQjs7O2VBR0c7WUFDSCxVQUFVLEVBQUUsSUFBSSxlQUFlLENBQVUsc0JBQXNCLENBQUM7WUFD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QUMsQ0FBQztJQUNMLENBQUM7K0dBdlFVLDhCQUE4QjttSEFBOUIsOEJBQThCLGNBRGpCLE1BQU07OzRGQUNuQiw4QkFBOEI7a0JBRDFDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBJbmplY3RhYmxlLCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgTW9ub1R5cGVPcGVyYXRvckZ1bmN0aW9uLCBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgZmlsdGVyLCBtYXAsIHNraXAsIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9JTlRFUlZBTF9TVEFURSxcbiAgREVGQVVMVF9JTlRFUlZBTF9WQUxVRSxcbiAgR0xPQkFMX0NPTlRFWFRfQVVUT19SRUZSRVNILFxuICBHbG9iYWxBdXRvUmVmcmVzaFF1ZXJ5UGFyYW1cbn0gZnJvbSAnLi93aWRnZXQtYXV0by1yZWZyZXNoLWNvbnRleHQubW9kZWwnO1xuaW1wb3J0IHtcbiAgQWN0aXZhdGVkUm91dGUsXG4gIEV2ZW50LFxuICBOYXZpZ2F0aW9uQ2FuY2VsLFxuICBOYXZpZ2F0aW9uRW5kLFxuICBOYXZpZ2F0aW9uRXJyb3IsXG4gIE5hdmlnYXRpb25TdGFydCxcbiAgUm91dGVyXG59IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgV2lkZ2V0R2xvYmFsQXV0b1JlZnJlc2hTZXJ2aWNlIHtcbiAgLyoqXG4gICAqIEEgQmVoYXZpb3JTdWJqZWN0IHRoYXQgdHJhY2tzIHRoZSBudW1iZXIgb2YgbG9hZGluZyBvcGVyYXRpb25zIGluIHByb2dyZXNzLlxuICAgKiBJbml0aWFsaXplZCB3aXRoIGEgY291bnQgb2YgMC5cbiAgICovXG4gIHByaXZhdGUgbG9hZGluZ0NvdW50JCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyPigwKTtcblxuICAvKipcbiAgICogQW4gT2JzZXJ2YWJsZSB0aGF0IGVtaXRzIGEgYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgYW55IHdpZGdldHMgd2l0aCBnbG9iYWwgcmVmcmVzaCBvcHRpb24gYXJlIGN1cnJlbnRseSBsb2FkaW5nLlxuICAgKiBUaGUgdmFsdWUgaXMgdHJ1ZSBpZiB0aGUgbG9hZGluZyBjb3VudCBpcyBub24temVybywgYW5kIGZhbHNlIGlmIHRoZSBsb2FkaW5nIGNvdW50IGlzIHplcm8uXG4gICAqIFVzZXMgZGlzdGluY3RVbnRpbENoYW5nZWQoKSB0byBlbWl0IG9ubHkgd2hlbiB0aGUgYm9vbGVhbiB2YWx1ZSBjaGFuZ2VzLlxuICAgKi9cbiAgcHJpdmF0ZSBpc0xvYWRpbmdXaWRnZXRzJDogT2JzZXJ2YWJsZTxib29sZWFuPiA9IHRoaXMubG9hZGluZ0NvdW50JC5waXBlKFxuICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgbWFwKGNvdW50ID0+IGNvdW50ICE9PSAwKVxuICApO1xuXG4gIC8qKlxuICAgKiBPYmplY3QgY29udGFpbmluZyBiZWhhdmlvciBzdWJqZWN0cyBmb3IgbWFuYWdpbmcgYXV0by1yZWZyZXNoIHNldHRpbmdzLlxuICAgKi9cbiAgYXV0b1JlZnJlc2hTZXR0aW5ncyA9IHtcbiAgICAvKipcbiAgICAgKiBCZWhhdmlvclN1YmplY3QgdGhhdCBlbWl0cyB0aGUgY3VycmVudCBzdGF0ZSBvZiBhdXRvLXJlZnJlc2ggYnV0dG9uLlxuICAgICAqIERlZmF1bHRzIHRvIERFRkFVTFRfSU5URVJWQUxfU1RBVEUuXG4gICAgICovXG4gICAgaXNFbmFibGVkJDogbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihERUZBVUxUX0lOVEVSVkFMX1NUQVRFKSxcbiAgICAvKipcbiAgICAgKiBCZWhhdmlvclN1YmplY3QgdGhhdCBlbWl0cyB0aGUgY3VycmVudCBhdXRvLXJlZnJlc2ggaW50ZXJ2YWwgdmFsdWUuXG4gICAgICogRGVmYXVsdHMgdG8gREVGQVVMVF9JTlRFUlZBTF9WQUxVRS5cbiAgICAgKi9cbiAgICByZWZyZXNoSW50ZXJ2YWwkOiBuZXcgQmVoYXZpb3JTdWJqZWN0PG51bWJlcj4oREVGQVVMVF9JTlRFUlZBTF9WQUxVRSksXG4gICAgLyoqXG4gICAgICogQmVoYXZpb3JTdWJqZWN0IHRoYXQgZW1pdHMgd2hldGhlciBhdXRvLXJlZnJlc2ggaGFzIGJlZW4gbWFudWFsbHkgZGlzYWJsZWQgYnkgdGhlIHVzZXIuXG4gICAgICogRGVmYXVsdHMgdG8gZmFsc2UuXG4gICAgICovXG4gICAgdXNlckRpc2FibGVkTWFudWFsbHkkOiBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKVxuICB9O1xuXG4gIC8qKlxuICAgKiBPYmplY3QgY29udGFpbmluZyBzdWJqZWN0cyBmb3IgbWFuYWdpbmcgY291bnRkb3duIGFjdGlvbnMuXG4gICAqL1xuICBjb3VudGRvd25BY3Rpb25zID0ge1xuICAgIC8qKlxuICAgICAqIFN1YmplY3QgdXNlZCB0byBzdG9wIHRoZSBjb3VudGRvd24uXG4gICAgICovXG4gICAgc3RvcCQ6IG5ldyBTdWJqZWN0PHZvaWQ+KCksXG4gICAgLyoqXG4gICAgICogU3ViamVjdCB1c2VkIHRvIHJlc2V0IHRoZSBjb3VudGRvd24uXG4gICAgICovXG4gICAgcmVzZXQkOiBuZXcgU3ViamVjdDx2b2lkPigpLFxuICAgIC8qKlxuICAgICAqIFN1YmplY3QgdGhhdCBlbWl0cyB3aGVuIHRoZSBjb3VudGRvd24gaGFzIGVuZGVkLlxuICAgICAqL1xuICAgIGNvdW50ZG93bkVuZGVkJDogbmV3IFN1YmplY3Q8dm9pZD4oKVxuICB9O1xuXG4gIC8qKlxuICAgKiBTdWJqZWN0IHRoYXQgZW1pdHMgd2hlbiBhIGRhc2hib2FyZCBzYXZlIG9wZXJhdGlvbiBpcyB0cmlnZ2VyZWQuXG4gICAqL1xuICBvbkRhc2hib2FyZFNhdmUkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKipcbiAgICogQSBzaWduYWwgcmVwcmVzZW50aW5nIHRoZSBudW1iZXIgb2Ygd2lkZ2V0cyB3aXRoIHRoZSBnbG9iYWwgYXV0by1yZWZyZXNoIG9wdGlvbiBlbmFibGVkLlxuICAgKi9cbiAgZ2xvYmFsUmVmcmVzaFdpZGdldHNDb3VudCA9IHNpZ25hbCgwKTtcblxuICAvKipcbiAgICogVHJhY2tzIHRoZSBuYXZpZ2F0aW9uIHN0YXRlLlxuICAgKlxuICAgKiBUaGUgc2lnbmFsIHJldHVybnMgYSBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciBhIG5hdmlnYXRpb24gb3BlcmF0aW9uIGlzIGN1cnJlbnRseSBpbiBwcm9ncmVzcy5cbiAgICogSXQgaW5pdGlhbGl6ZXMgd2l0aCBhIGRlZmF1bHQgdmFsdWUgb2YgYGZhbHNlYCBhbmQgY2FuIGJlIHRvZ2dsZWQgdG8gYHRydWVgIGR1cmluZyBuYXZpZ2F0aW9uIGV2ZW50cyBmcm9tIGBoYW5kbGVOYXZpZ2F0aW9uSW5Qcm9ncmVzcyRgLlxuICAgKi9cbiAgcHJpdmF0ZSBuYXZpZ2F0aW9uSW5Qcm9ncmVzcyA9IHNpZ25hbChmYWxzZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgcHJpdmF0ZSByZWFkb25seSBhY3RpdmF0ZWRSb3V0ZSA9IGluamVjdChBY3RpdmF0ZWRSb3V0ZSk7XG5cbiAgLyoqXG4gICAqIEluY3JlbWVudHMgdGhlIGxvYWRpbmcgY291bnQgYnkgMS5cbiAgICovXG4gIGluY3JlbWVudExvYWRpbmcoKTogdm9pZCB7XG4gICAgdGhpcy5sb2FkaW5nQ291bnQkLm5leHQodGhpcy5sb2FkaW5nQ291bnQkLnZhbHVlICsgMSk7XG4gIH1cblxuICAvKipcbiAgICogRGVjcmVtZW50cyB0aGUgbG9hZGluZyBjb3VudCBieSAxLlxuICAgKi9cbiAgZGVjcmVtZW50TG9hZGluZygpOiB2b2lkIHtcbiAgICB0aGlzLmxvYWRpbmdDb3VudCQubmV4dCh0aGlzLmxvYWRpbmdDb3VudCQudmFsdWUgLSAxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYW4gb2JzZXJ2YWJsZSB0aGF0IGVtaXRzIHRoZSB2YWx1ZSBvZiBhIEdsb2JhbCBBdXRvIFJlZnJlc2ggcXVlcnkgcGFyYW1ldGVyXG4gICAqIHdoZW5ldmVyIGl0IGNoYW5nZXMuIFRoZSBxdWVyeSBwYXJhbWV0ZXIgYmVpbmcgdHJhY2tlZCBpcyBkZXRlcm1pbmVkIGJ5XG4gICAqIGBHbG9iYWxBdXRvUmVmcmVzaE5hbWUuR0xPQkFMX0NPTlRFWFRfQVVUT19SRUZSRVNIYC5cbiAgICpcbiAgICogQHJldHVybnMgQW4gb2JzZXJ2YWJsZSB0aGF0IGVtaXRzIHRoZSBwYXJzZWQgdmFsdWUgb2YgdGhlIGBHTE9CQUxfQ09OVEVYVF9BVVRPX1JFRlJFU0hgIHF1ZXJ5IHBhcmFtZXRlci5cbiAgICovXG4gIGdldFF1ZXJ5UGFyYW1DaGFuZ2VWYWx1ZSQoKTogT2JzZXJ2YWJsZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLmFjdGl2YXRlZFJvdXRlLnF1ZXJ5UGFyYW1zLnBpcGUoXG4gICAgICBtYXAocGFyYW1zID0+IHBhcmFtc1tHTE9CQUxfQ09OVEVYVF9BVVRPX1JFRlJFU0hdKSxcbiAgICAgIG1hcCh0aGlzLnBhcnNlR2xvYmFsQXV0b1JlZnJlc2hQYXJhbSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vbml0b3JzIHJvdXRlciBuYXZpZ2F0aW9uIGV2ZW50cyBhbmQgdXBkYXRlcyB0aGUgbmF2aWdhdGlvbiBwcm9ncmVzcyBzdGF0ZS5cbiAgICpcbiAgICogQHJldHVybnMgQW4gT2JzZXJ2YWJsZSB0aGF0IGVtaXRzIHJvdXRlciBldmVudHMgb2YgdHlwZXMgTmF2aWdhdGlvblN0YXJ0LCBOYXZpZ2F0aW9uRW5kLFxuICAgKiAgICAgICAgICBOYXZpZ2F0aW9uQ2FuY2VsLCBhbmQgTmF2aWdhdGlvbkVycm9yLlxuICAgKi9cbiAgaGFuZGxlTmF2aWdhdGlvbkluUHJvZ3Jlc3MkKCk6IE9ic2VydmFibGU8RXZlbnQ+IHtcbiAgICByZXR1cm4gdGhpcy5yb3V0ZXIuZXZlbnRzLnBpcGUoXG4gICAgICBmaWx0ZXIoXG4gICAgICAgIGV2ZW50ID0+XG4gICAgICAgICAgZXZlbnQgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uU3RhcnQgfHxcbiAgICAgICAgICBldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25FbmQgfHxcbiAgICAgICAgICBldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25DYW5jZWwgfHxcbiAgICAgICAgICBldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25FcnJvclxuICAgICAgKSxcbiAgICAgIHRhcChlID0+IHRoaXMubmF2aWdhdGlvbkluUHJvZ3Jlc3Muc2V0KGUgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uU3RhcnQpKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgZ2xvYmFsIGF1dG8tcmVmcmVzaCBxdWVyeSBwYXJhbWV0ZXIgaW4gdGhlIGN1cnJlbnQgcm91dGUuXG4gICAqXG4gICAqIEBwYXJhbSBxdWVyeVBhcmFtcyAtIEFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIHF1ZXJ5IHBhcmFtZXRlcnMgdG8gc2V0IGZvciB0aGUgZ2xvYmFsIGF1dG8tcmVmcmVzaCBvcHRpb24uXG4gICAqICAgICAgICAgICAgICAgICAgICAgIFRoZSBleGlzdGluZyBxdWVyeSBwYXJhbWV0ZXJzIHdpbGwgYmUgbWVyZ2VkIHdpdGggdGhlc2UuXG4gICAqL1xuICBhc3luYyBzZXRBdXRvUmVmcmVzaFF1ZXJ5UGFyYW0ocXVlcnlQYXJhbXM6IEdsb2JhbEF1dG9SZWZyZXNoUXVlcnlQYXJhbSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm5hdmlnYXRpb25JblByb2dyZXNzKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLm5hdmlnYXRpb25JblByb2dyZXNzLnNldCh0cnVlKTtcbiAgICBhd2FpdCB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbXSwge1xuICAgICAgcmVsYXRpdmVUbzogdGhpcy5hY3RpdmF0ZWRSb3V0ZSxcbiAgICAgIHF1ZXJ5UGFyYW1zLFxuICAgICAgcXVlcnlQYXJhbXNIYW5kbGluZzogJ21lcmdlJ1xuICAgIH0pO1xuICAgIHRoaXMubmF2aWdhdGlvbkluUHJvZ3Jlc3Muc2V0KGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIGNoYW5nZXMgdG8gdGhlIGVkaXQgbW9kZSBhbmQgdXBkYXRlcyB0aGUgaXNFbmFibGVkJCB2YXJpYWJsZS5cbiAgICpcbiAgICogLSBJZiBhdXRvLXJlZnJlc2ggd2FzIG1hbnVhbGx5IGRpc2FibGVkIGJ5IHRoZSB1c2VyIChgdXNlckRpc2FibGVkTWFudWFsbHkkYCBpcyBgdHJ1ZWApLCBhdXRvLXJlZnJlc2ggd2lsbCByZW1haW4gZGlzYWJsZWQgcmVnYXJkbGVzcyBvZiB0aGUgZWRpdCBtb2RlIHN0YXRlLlxuICAgKiAtIElmIGF1dG8tcmVmcmVzaCB3YXMgbm90IG1hbnVhbGx5IGRpc2FibGVkLCBpdCB3aWxsIGJlIGRpc2FibGVkIHdoZW4gZW50ZXJpbmcgZWRpdCBtb2RlIGFuZCBlbmFibGVkIHdoZW4gZXhpdGluZyBlZGl0IG1vZGUuXG4gICAqXG4gICAqIEBwYXJhbSBlZGl0TW9kZSAtIEEgYm9vbGVhbiBpbmRpY2F0aW5nIHRoZSBjdXJyZW50IHN0YXRlIG9mIGVkaXQgbW9kZSAoYHRydWVgIGlmIGVkaXQgbW9kZSBpcyBhY3RpdmUsIGBmYWxzZWAgb3RoZXJ3aXNlKS5cbiAgICovXG4gIG9uRWRpdE1vZGVDaGFuZ2UoZWRpdE1vZGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5hdXRvUmVmcmVzaFNldHRpbmdzLnVzZXJEaXNhYmxlZE1hbnVhbGx5JC5nZXRWYWx1ZSgpKSB7XG4gICAgICB0aGlzLmF1dG9SZWZyZXNoU2V0dGluZ3MuaXNFbmFibGVkJC5uZXh0KGZhbHNlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5hdXRvUmVmcmVzaFNldHRpbmdzLmlzRW5hYmxlZCQubmV4dCghZWRpdE1vZGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gT2JzZXJ2YWJsZSB0aGF0IHRyaWdnZXJzIHRoZSBjb3VudGRvd24gcmVzZXQgYWN0aW9uIHdoZW4gbG9hZGluZyBjb21wbGV0ZXMuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGNyZWF0ZXMgYW4gT2JzZXJ2YWJsZSB0aGF0OlxuICAgKiAtIFNraXBzIGEgc3BlY2lmaWVkIG51bWJlciBvZiBpbml0aWFsIGVtaXNzaW9ucyBmcm9tIGBpc0xvYWRpbmdXaWRnZXRzJGAgYmFzZWQgb24gdGhlIGBza2lwSW5pdGlhbEJlaGF2aW9yU3ViamVjdEVtaXNzaW9uJGAgbWV0aG9kLlxuICAgKiAtIEZpbHRlcnMgb3V0IGVtaXNzaW9ucyB3aGVyZSB0aGUgbG9hZGluZyBzdGF0ZSBpcyB0cnVlLlxuICAgKiAtIE9uIGVtaXNzaW9uIHdoZXJlIHRoZSBsb2FkaW5nIHN0YXRlIGlzIGZhbHNlLCBpdCB0cmlnZ2VycyBhIGNvdW50ZG93biByZXNldCBhY3Rpb24uXG4gICAqXG4gICAqL1xuICByZXNldENvdW50ZG93bk9uTG9hZGluZ0NvbXBsZXRlJCgpOiBNb25vVHlwZU9wZXJhdG9yRnVuY3Rpb248YW55PiB7XG4gICAgcmV0dXJuIHN3aXRjaE1hcCgoKSA9PlxuICAgICAgdGhpcy5pc0xvYWRpbmdXaWRnZXRzJC5waXBlKFxuICAgICAgICB0YXAoaXNMb2FkaW5nID0+IGlzTG9hZGluZyAmJiB0aGlzLmNvdW50ZG93bkFjdGlvbnMuc3RvcCQubmV4dCgpKSxcbiAgICAgICAgZmlsdGVyKGxvYWRpbmcgPT4gIWxvYWRpbmcpLFxuICAgICAgICB0YXAoKCkgPT4gdGhpcy5yZXNldENvdW50ZG93bigpKVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBzZXJ2aWNlJ3Mgc2V0dGluZ3MgYW5kIHBhcmFtZXRlcnMgdG8gdGhlaXIgZGVmYXVsdCB2YWx1ZXMuXG4gICAqL1xuICByZXNldFNlcnZpY2VUb0RlZmF1bHRzKCk6IHZvaWQge1xuICAgIHNldFRpbWVvdXQoKCkgPT4gIXRoaXMubmF2aWdhdGlvbkluUHJvZ3Jlc3MoKSAmJiB0aGlzLmNsZWFyUXVlcnlQYXJhbSgpKTtcblxuICAgIHRoaXMuYXV0b1JlZnJlc2hTZXR0aW5ncy5yZWZyZXNoSW50ZXJ2YWwkLm5leHQoREVGQVVMVF9JTlRFUlZBTF9WQUxVRSk7XG4gICAgdGhpcy5hdXRvUmVmcmVzaFNldHRpbmdzLnVzZXJEaXNhYmxlZE1hbnVhbGx5JC5uZXh0KGZhbHNlKTtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5hdXRvUmVmcmVzaFNldHRpbmdzLmlzRW5hYmxlZCQubmV4dChERUZBVUxUX0lOVEVSVkFMX1NUQVRFKTtcbiAgICAgIHRoaXMucmVzZXRMb2FkaW5nVG9aZXJvKCk7XG4gICAgICB0aGlzLm5hdmlnYXRpb25JblByb2dyZXNzLnNldChmYWxzZSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBjb3VudGRvd24gdGltZXIgYnkgZW1pdHRpbmcgYSByZXNldCBhY3Rpb24gYWZ0ZXIgYSBzaG9ydCBkZWxheS5cbiAgICovXG4gIHJlc2V0Q291bnRkb3duKCk6IHZvaWQge1xuICAgIHF1ZXVlTWljcm90YXNrKCgpID0+IHRoaXMuY291bnRkb3duQWN0aW9ucy5yZXNldCQubmV4dCgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplcyB0aGUgYXV0by1yZWZyZXNoIGNvdW50ZG93biBsb2dpYyBiYXNlZCBvbiB0aGUgd2lkZ2V0IGxvYWRpbmcgc3RhdGUgYW5kIGVkaXQgbW9kZS5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhbiBvYnNlcnZhYmxlIHRoYXQgbW9uaXRvcnMgdGhlIHdpZGdldCBsb2FkaW5nIHN0YXRlIGFuZCB0cmlnZ2VycyBzcGVjaWZpYyBhY3Rpb25zXG4gICAqIHJlbGF0ZWQgdG8gdGhlIGNvdW50ZG93biBwcm9jZXNzLiBJdCBwZXJmb3JtcyB0aGUgZm9sbG93aW5nIHN0ZXBzOlxuICAgKlxuICAgKiAxLiBTa2lwcyB0aGUgaW5pdGlhbCBsb2FkaW5nIHN0YXRlIGVtaXR0ZWQgYnkgYGlzTG9hZGluZ1dpZGdldHMkYC5cbiAgICogMi4gU3RvcHMgdGhlIGNvdW50ZG93biBpZiB0aGUgd2lkZ2V0cyBhcmUgY3VycmVudGx5IGxvYWRpbmcuXG4gICAqIDMuIEZpbHRlcnMgb3V0IGNhc2VzIHdoZXJlIHdpZGdldHMgYXJlIGxvYWRpbmcgb3IgdGhlIGFwcGxpY2F0aW9uIGlzIGluIGVkaXQgbW9kZS5cbiAgICogNC4gUmVzZXRzIHRoZSBjb3VudGRvd24gd2hlbiB3aWRnZXRzIGFyZSBub3QgbG9hZGluZyBhbmQgdGhlIGFwcGxpY2F0aW9uIGlzIG5vdCBpbiBlZGl0IG1vZGUuXG4gICAqXG4gICAqIEBwYXJhbSBlZGl0TW9kZSQgLSBBIGBCZWhhdmlvclN1YmplY3RgIHJlcHJlc2VudGluZyB3aGV0aGVyIHRoZSBhcHBsaWNhdGlvbiBpcyBjdXJyZW50bHkgaW4gZWRpdCBtb2RlLlxuICAgKlxuICAgKiBAcmV0dXJucyBBbiBgT2JzZXJ2YWJsZTxib29sZWFuPmAgdGhhdCBlbWl0cyB0aGUgbG9hZGluZyBzdGF0ZSBvZiB0aGUgd2lkZ2V0cyBhZnRlciB0aGUgaW5pdGlhbGl6YXRpb24gc3RlcHMuXG4gICAqL1xuICBpbml0aWFsaXplQXV0b1JlZnJlc2hDb3VudGRvd25Mb2FkaW5nJChlZGl0TW9kZSQ6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPik6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmlzTG9hZGluZ1dpZGdldHMkLnBpcGUoXG4gICAgICBza2lwKDEpLFxuICAgICAgdGFwKGlzTG9hZGluZyA9PiBpc0xvYWRpbmcgJiYgdGhpcy5jb3VudGRvd25BY3Rpb25zLnN0b3AkLm5leHQoKSksXG4gICAgICBmaWx0ZXIoaXNXaWRnZXRzTG9hZGluZyA9PiAhaXNXaWRnZXRzTG9hZGluZyAmJiAhZWRpdE1vZGUkLmdldFZhbHVlKCkpLFxuICAgICAgdGFwKCgpID0+IHRoaXMucmVzZXRDb3VudGRvd24oKSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlcyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBnbG9iYWwgYXV0by1yZWZyZXNoIHBhcmFtZXRlciBpbnRvIGEgYm9vbGVhbiBvciBudWxsLlxuICAgKlxuICAgKiBDb252ZXJ0cyB0aGUgcHJvdmlkZWQgYGdsb2JhbEF1dG9SZWZyZXNoYCBzdHJpbmcgaW50byBhIGJvb2xlYW4gdmFsdWUgb3IgbnVsbCBiYXNlZCBvbiBpdHMgY29udGVudDpcbiAgICogLSBSZXR1cm5zIGB0cnVlYCBpZiBgZ2xvYmFsQXV0b1JlZnJlc2hgIGlzICd0cnVlJy5cbiAgICogLSBSZXR1cm5zIGBmYWxzZWAgaWYgYGdsb2JhbEF1dG9SZWZyZXNoYCBpcyAnZmFsc2UnLlxuICAgKiAtIFJldHVybnMgYG51bGxgIGlmIGBnbG9iYWxBdXRvUmVmcmVzaGAgaXMgbmVpdGhlciAndHJ1ZScgbm9yICdmYWxzZScuXG4gICAqXG4gICAqIEBwYXJhbSBnbG9iYWxBdXRvUmVmcmVzaCAtIFRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdsb2JhbCBhdXRvLXJlZnJlc2ggcGFyYW1ldGVyLlxuICAgKlxuICAgKiBAcmV0dXJucyBBIGJvb2xlYW4gdmFsdWUgY29ycmVzcG9uZGluZyB0byB0aGUgcGFyc2VkIGdsb2JhbCBhdXRvLXJlZnJlc2ggc3RhdGUsIG9yIG51bGwgaWYgdGhlIGlucHV0IGlzIG5vdCAndHJ1ZScgb3IgJ2ZhbHNlJy5cbiAgICovXG4gIHByaXZhdGUgcGFyc2VHbG9iYWxBdXRvUmVmcmVzaFBhcmFtKGdsb2JhbEF1dG9SZWZyZXNoOiBzdHJpbmcpOiBib29sZWFuIHwgbnVsbCB7XG4gICAgcmV0dXJuIGdsb2JhbEF1dG9SZWZyZXNoID09PSAnZmFsc2UnID8gZmFsc2UgOiBnbG9iYWxBdXRvUmVmcmVzaCA9PT0gJ3RydWUnID8gdHJ1ZSA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBsb2FkaW5nIGNvdW50IHRvIHplcm8uXG4gICAqL1xuICBwcml2YXRlIHJlc2V0TG9hZGluZ1RvWmVybygpOiB2b2lkIHtcbiAgICB0aGlzLmxvYWRpbmdDb3VudCQubmV4dCgwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhcnMgdGhlIGdsb2JhbCBhdXRvLXJlZnJlc2ggcXVlcnkgcGFyYW1ldGVyIGJ5IG5hdmlnYXRpbmcgdG8gdGhlIGN1cnJlbnQgcm91dGUgd2l0aCB0aGUgcGFyYW1ldGVyIHNldCB0byBudWxsLlxuICAgKlxuICAgKi9cbiAgcHJpdmF0ZSBjbGVhclF1ZXJ5UGFyYW0oKTogdm9pZCB7XG4gICAgY29uc3QgcXVlcnlQYXJhbXM6IEdsb2JhbEF1dG9SZWZyZXNoUXVlcnlQYXJhbSA9IHtcbiAgICAgIGdsb2JhbENvbnRleHRBdXRvUmVmcmVzaDogbnVsbFxuICAgIH07XG5cbiAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbXSwge1xuICAgICAgcmVsYXRpdmVUbzogdGhpcy5hY3RpdmF0ZWRSb3V0ZSxcbiAgICAgIHF1ZXJ5UGFyYW1zLFxuICAgICAgcXVlcnlQYXJhbXNIYW5kbGluZzogJ21lcmdlJ1xuICAgIH0pO1xuICB9XG59XG4iXX0=