UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

158 lines 27 kB
import { DestroyRef, Injectable, Injector } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivationEnd, ActivationStart, ChildActivationEnd, PRIMARY_OUTLET, Router } from '@angular/router'; import { ApiService } from '@c8y/ngx-components/api'; import { NEVER, Subject, merge } from 'rxjs'; import { filter, map, switchMap } from 'rxjs/operators'; import { TabsService } from '../tabs/tabs.service'; import { RouterTabsResolver } from './router-tabs.resolver'; import { ViewContext } from './router.model'; import { ViewContextServices } from './view-context.service'; import * as i0 from "@angular/core"; import * as i1 from "./router-tabs.resolver"; import * as i2 from "../tabs/tabs.service"; import * as i3 from "@angular/router"; import * as i4 from "@c8y/ngx-components/api"; /** * A service which is injected into the context route component to handle the context data. */ export class ScopedContextRouteService { constructor(tabsResolver, tabsService, router, apiService, injector, destroyRef) { this.tabsResolver = tabsResolver; this.tabsService = tabsService; this.router = router; this.apiService = apiService; this.injector = injector; this.destroyRef = destroyRef; this.lastAddedTabs = []; this.refreshTrigger$ = new Subject(); this.ID_REGEX = /([0-9]+)/; } /** * Indicates that the data is loading * @returns An boolean observable which indicates if the data is loading. */ isLoading$() { return this.router.events.pipe(filter(e => (e instanceof ActivationStart || e instanceof ChildActivationEnd) && e.snapshot.routeConfig?.rootContext === this.currentContext), map(e => e instanceof ActivationStart), takeUntilDestroyed(this.destroyRef)); } /** * Initializes the context route. * @param route The current activated route. */ init(route) { this.currentContext = route.routeConfig.rootContext; if (!this.currentContext) { throw new Error(`${ScopedContextRouteService.name} should not be used on a route without a rootContext`); } this.router.events .pipe(filter(event => event instanceof ActivationEnd && this.needsRedirect(event)), switchMap((event) => this.tabsResolver.resolve(event.snapshot)), takeUntilDestroyed(this.destroyRef)) .subscribe((tabs) => this.redirectToFirstTabOnActivationEnd(tabs)); merge(this.updatedContext(route), this.refreshTrigger$, route.data) .pipe(switchMap(() => this.tabsResolver.resolve(route.snapshot)), takeUntilDestroyed(this.destroyRef)) .subscribe(tabs => this.updateTabs(tabs)); } /** * Destroys the service. */ ngOnDestroy() { this.lastAddedTabs.forEach(t => this.tabsService.remove(t)); } /** * Refreshes the context. */ refreshContext() { this.refreshTrigger$.next(); } redirectToFirstTabOnActivationEnd(tabs) { if (!tabs.length) { return; } const tab = this.tabsService.sortTabs(tabs)[0]; const currentQueryParams = this.router.routerState.snapshot.root.queryParams; const queryParamsString = new URLSearchParams(currentQueryParams).toString(); const queryParamsSuffix = queryParamsString ? `?${queryParamsString}` : ''; const currentContextId = (this.router.url.match(this.ID_REGEX) || []).shift(); const tabPathId = (tab.path.match(this.ID_REGEX) || []).shift(); if (currentContextId === tabPathId) { this.router.navigateByUrl(`${tab.path}${queryParamsSuffix}`, { replaceUrl: true }); } } /** * Sets an API hook to refresh the contextData on changes. * @param activatedRoute The current activated route. */ updatedContext(route) { const { data } = route.snapshot; const serviceInstance = ViewContextServices.contextToService(data.context); if (serviceInstance) { const service = this.injector.get(serviceInstance); const detailsUrlRegex = service .getDetailUrl(data.contextData) .replace(/\d+/g, '?\\d*'); const contextRegex = new RegExp(detailsUrlRegex, 'i'); const childrenRegex = new RegExp(`${detailsUrlRegex}/child`, 'i'); const filterResponse = ({ url, method }) => { const contextChanged = contextRegex.test(url) && ['POST', 'PUT'].includes(method); const childrenAffected = childrenRegex.test(url) && ['POST', 'DELETE'].includes(method); return contextChanged || childrenAffected; }; return this.apiService.hookResponse(filterResponse); } return NEVER; } updateTabs(tabs = []) { this.lastAddedTabs.forEach(t => this.tabsService.remove(t)); this.lastAddedTabs = tabs; tabs.forEach(t => this.tabsService.add(t)); this.redirectToFirstTabOnUpdateTabs(); } redirectToFirstTabOnUpdateTabs() { const currentQueryParams = this.router.routerState.snapshot.root.queryParams; const queryParamsString = new URLSearchParams(currentQueryParams).toString(); const queryParamsSuffix = queryParamsString ? `?${queryParamsString}` : ''; const currentContextId = (this.router.url.match(this.ID_REGEX) || []).shift(); if (this.needsRedirectLegacy()) { this.tabsService.firstTab$ .pipe(filter((tab) => typeof tab?.path === 'string')) .subscribe((tab) => { const tabPathId = (tab.path.match(this.ID_REGEX) || []).shift(); if (currentContextId === tabPathId) { this.router.navigateByUrl(`${tab.path}${queryParamsSuffix}`, { replaceUrl: true }); } }); } } needsRedirectLegacy() { const tree = this.router.parseUrl(this.router.url); const groups = tree.root.children[PRIMARY_OUTLET]; const context = this.getMatchingContextRoute(this.router.url); if (!context) { return groups.segments.length === 2; } return context.split('/').length === groups.segments.length; } needsRedirect(event) { const contextRoute = event.snapshot.routeConfig; if (!contextRoute.rootContext) { return false; } const contextRouteFromUrl = this.getMatchingContextRoute(this.router.url); return contextRoute.rootContext === contextRouteFromUrl; } getMatchingContextRoute(url) { const viewContexts = Object.values(ViewContext); // replace all :id placeholders with a regex matcher for a number const regexMatchers = viewContexts.map(context => `^/${context.replace(/:id/g, '([0-9]+)')}(\\?.*)?$`); const matchingRegexContext = regexMatchers.find(context => new RegExp(context).test(url)); return matchingRegexContext ? viewContexts[regexMatchers.indexOf(matchingRegexContext)] : null; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ScopedContextRouteService, deps: [{ token: i1.RouterTabsResolver }, { token: i2.TabsService }, { token: i3.Router }, { token: i4.ApiService }, { token: i0.Injector }, { token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ScopedContextRouteService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ScopedContextRouteService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.RouterTabsResolver }, { type: i2.TabsService }, { type: i3.Router }, { type: i4.ApiService }, { type: i0.Injector }, { type: i0.DestroyRef }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NvcGVkLWNvbnRleHQtcm91dGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2NvcmUvcm91dGVyL3Njb3BlZC1jb250ZXh0LXJvdXRlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFtQixNQUFNLGVBQWUsQ0FBQztBQUNsRixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNoRSxPQUFPLEVBRUwsYUFBYSxFQUNiLGVBQWUsRUFDZixrQkFBa0IsRUFDbEIsY0FBYyxFQUNkLE1BQU0sRUFHUCxNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBVyxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsS0FBSyxFQUFjLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDekQsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzVELE9BQU8sRUFBRSxXQUFXLEVBQXdCLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7Ozs7OztBQUU3RDs7R0FFRztBQUVILE1BQU0sT0FBTyx5QkFBeUI7SUFVcEMsWUFDVSxZQUFnQyxFQUNoQyxXQUF3QixFQUN4QixNQUFjLEVBQ2QsVUFBc0IsRUFDdEIsUUFBa0IsRUFDbEIsVUFBc0I7UUFMdEIsaUJBQVksR0FBWixZQUFZLENBQW9CO1FBQ2hDLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxl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TyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLFdBQVcsQ0FDL0QsQ0FBQztRQUNGLE1BQU0sb0JBQW9CLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzFGLE9BQU8sb0JBQW9CLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ2pHLENBQUM7K0dBNUtVLHlCQUF5QjttSEFBekIseUJBQXlCOzs0RkFBekIseUJBQXlCO2tCQURyQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGVzdHJveVJlZiwgSW5qZWN0YWJsZSwgSW5qZWN0b3IsIE9uRGVzdHJveSwgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHtcbiAgQWN0aXZhdGVkUm91dGUsXG4gIEFjdGl2YXRpb25FbmQsXG4gIEFjdGl2YXRpb25TdGFydCxcbiAgQ2hpbGRBY3RpdmF0aW9uRW5kLFxuICBQUklNQVJZX09VVExFVCxcbiAgUm91dGVyLFxuICBVcmxTZWdtZW50R3JvdXAsXG4gIFVybFRyZWVcbn0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEFwaUNhbGwsIEFwaVNlcnZpY2UgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL2FwaSc7XG5pbXBvcnQgeyBORVZFUiwgT2JzZXJ2YWJsZSwgU3ViamVjdCwgbWVyZ2UgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGZpbHRlciwgbWFwLCBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBUYWIsIFRhYldpdGhUZW1wbGF0ZSB9IGZyb20gJy4uL3RhYnMvdGFiLm1vZGVsJztcbmltcG9ydCB7IFRhYnNTZXJ2aWNlIH0gZnJvbSAnLi4vdGFicy90YWJzLnNlcnZpY2UnO1xuaW1wb3J0IHsgUm91dGVyVGFic1Jlc29sdmVyIH0gZnJvbSAnLi9yb3V0ZXItdGFicy5yZXNvbHZlcic7XG5pbXBvcnQgeyBWaWV3Q29udGV4dCwgVmlld0NvbnRleHRSb290Um91dGUgfSBmcm9tICcuL3JvdXRlci5tb2RlbCc7XG5pbXBvcnQgeyBWaWV3Q29udGV4dFNlcnZpY2VzIH0gZnJvbSAnLi92aWV3LWNvbnRleHQuc2VydmljZSc7XG5cbi8qKlxuICogQSBzZXJ2aWNlIHdoaWNoIGlzIGluamVjdGVkIGludG8gdGhlIGNvbnRleHQgcm91dGUgY29tcG9uZW50IHRvIGhhbmRsZSB0aGUgY29udGV4dCBkYXRhLlxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgU2NvcGVkQ29udGV4dFJvdXRlU2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgbGFzdEFkZGVkVGFicyA9IFtdO1xuICBwcml2YXRlIHJlZnJlc2hUcmlnZ2VyJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByaXZhdGUgSURfUkVHRVggPSAvKFswLTldKykvO1xuXG4gIC8qKlxuICAgKiBUaGUgY29udGV4dCB1c2VkIGJ5IHRoaXMgc2VydmljZS5cbiAgICovXG4gIHByaXZhdGUgY3VycmVudENvbnRleHQ6IFZpZXdDb250ZXh0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgdGFic1Jlc29sdmVyOiBSb3V0ZXJUYWJzUmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSB0YWJzU2VydmljZTogVGFic1NlcnZpY2UsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcbiAgICBwcml2YXRlIGFwaVNlcnZpY2U6IEFwaVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgcHJpdmF0ZSBkZXN0cm95UmVmOiBEZXN0cm95UmVmXG4gICkge31cblxuICAvKipcbiAgICogSW5kaWNhdGVzIHRoYXQgdGhlIGRhdGEgaXMgbG9hZGluZ1xuICAgKiBAcmV0dXJucyBBbiBib29sZWFuIG9ic2VydmFibGUgd2hpY2ggaW5kaWNhdGVzIGlmIHRoZSBkYXRhIGlzIGxvYWRpbmcuXG4gICAqL1xuICBpc0xvYWRpbmckKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLnJvdXRlci5ldmVudHMucGlwZShcbiAgICAgIGZpbHRlcihcbiAgICAgICAgZSA9PlxuICAgICAgICAgIChlIGluc3RhbmNlb2YgQWN0aXZhdGlvblN0YXJ0IHx8IGUgaW5zdGFuY2VvZiBDaGlsZEFjdGl2YXRpb25FbmQpICYmXG4gICAgICAgICAgKGUuc25hcHNob3Qucm91dGVDb25maWcgYXMgVmlld0NvbnRleHRSb290Um91dGUpPy5yb290Q29udGV4dCA9PT0gdGhpcy5jdXJyZW50Q29udGV4dFxuICAgICAgKSxcbiAgICAgIG1hcChlID0+IGUgaW5zdGFuY2VvZiBBY3RpdmF0aW9uU3RhcnQpLFxuICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZilcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSBjb250ZXh0IHJvdXRlLlxuICAgKiBAcGFyYW0gcm91dGUgVGhlIGN1cnJlbnQgYWN0aXZhdGVkIHJvdXRlLlxuICAgKi9cbiAgaW5pdChyb3V0ZTogQWN0aXZhdGVkUm91dGUpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRDb250ZXh0ID0gKHJvdXRlLnJvdXRlQ29uZmlnIGFzIFZpZXdDb250ZXh0Um9vdFJvdXRlKS5yb290Q29udGV4dDtcbiAgICBpZiAoIXRoaXMuY3VycmVudENvbnRleHQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7U2NvcGVkQ29udGV4dFJvdXRlU2VydmljZS5uYW1lfSBzaG91bGQgbm90IGJlIHVzZWQgb24gYSByb3V0ZSB3aXRob3V0IGEgcm9vdENvbnRleHRgXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMucm91dGVyLmV2ZW50c1xuICAgICAgLnBpcGUoXG4gICAgICAgIGZpbHRlcihldmVudCA9PiBldmVudCBpbnN0YW5jZW9mIEFjdGl2YXRpb25FbmQgJiYgdGhpcy5uZWVkc1JlZGlyZWN0KGV2ZW50KSksXG4gICAgICAgIHN3aXRjaE1hcCgoZXZlbnQ6IEFjdGl2YXRpb25FbmQpID0+IHRoaXMudGFic1Jlc29sdmVyLnJlc29sdmUoZXZlbnQuc25hcHNob3QpKSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZilcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKHRhYnM6IFRhYltdKSA9PiB0aGlzLnJlZGlyZWN0VG9GaXJzdFRhYk9uQWN0aXZhdGlvbkVuZCh0YWJzKSk7XG5cbiAgICBtZXJnZSh0aGlzLnVwZGF0ZWRDb250ZXh0KHJvdXRlKSwgdGhpcy5yZWZyZXNoVHJpZ2dlciQsIHJvdXRlLmRhdGEpXG4gICAgICAucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMudGFic1Jlc29sdmVyLnJlc29sdmUocm91dGUuc25hcHNob3QpKSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZilcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUodGFicyA9PiB0aGlzLnVwZGF0ZVRhYnModGFicykpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlc3Ryb3lzIHRoZSBzZXJ2aWNlLlxuICAgKi9cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5sYXN0QWRkZWRUYWJzLmZvckVhY2godCA9PiB0aGlzLnRhYnNTZXJ2aWNlLnJlbW92ZSh0KSk7XG4gIH1cblxuICAvKipcbiAgICogUmVmcmVzaGVzIHRoZSBjb250ZXh0LlxuICAgKi9cbiAgcmVmcmVzaENvbnRleHQoKSB7XG4gICAgdGhpcy5yZWZyZXNoVHJpZ2dlciQubmV4dCgpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWRpcmVjdFRvRmlyc3RUYWJPbkFjdGl2YXRpb25FbmQodGFiczogVGFiW10pIHtcbiAgICBpZiAoIXRhYnMubGVuZ3RoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHRhYiA9IHRoaXMudGFic1NlcnZpY2Uuc29ydFRhYnModGFicylbMF07XG4gICAgY29uc3QgY3VycmVudFF1ZXJ5UGFyYW1zID0gdGhpcy5yb3V0ZXIucm91dGVyU3RhdGUuc25hcHNob3Qucm9vdC5xdWVyeVBhcmFtcztcbiAgICBjb25zdCBxdWVyeVBhcmFtc1N0cmluZyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoY3VycmVudFF1ZXJ5UGFyYW1zKS50b1N0cmluZygpO1xuICAgIGNvbnN0IHF1ZXJ5UGFyYW1zU3VmZml4ID0gcXVlcnlQYXJhbXNTdHJpbmcgPyBgPyR7cXVlcnlQYXJhbXNTdHJpbmd9YCA6ICcnO1xuICAgIGNvbnN0IGN1cnJlbnRDb250ZXh0SWQgPSAodGhpcy5yb3V0ZXIudXJsLm1hdGNoKHRoaXMuSURfUkVHRVgpIHx8IFtdKS5zaGlmdCgpO1xuICAgIGNvbnN0IHRhYlBhdGhJZCA9ICh0YWIucGF0aC5tYXRjaCh0aGlzLklEX1JFR0VYKSB8fCBbXSkuc2hpZnQoKTtcbiAgICBpZiAoY3VycmVudENvbnRleHRJZCA9PT0gdGFiUGF0aElkKSB7XG4gICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZUJ5VXJsKGAke3RhYi5wYXRofSR7cXVlcnlQYXJhbXNTdWZmaXh9YCwge1xuICAgICAgICByZXBsYWNlVXJsOiB0cnVlXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhbiBBUEkgaG9vayB0byByZWZyZXNoIHRoZSBjb250ZXh0RGF0YSBvbiBjaGFuZ2VzLlxuICAgKiBAcGFyYW0gYWN0aXZhdGVkUm91dGUgVGhlIGN1cnJlbnQgYWN0aXZhdGVkIHJvdXRlLlxuICAgKi9cbiAgcHJpdmF0ZSB1cGRhdGVkQ29udGV4dChyb3V0ZTogQWN0aXZhdGVkUm91dGUpOiBPYnNlcnZhYmxlPEFwaUNhbGw+IHtcbiAgICBjb25zdCB7IGRhdGEgfSA9IHJvdXRlLnNuYXBzaG90O1xuICAgIGNvbnN0IHNlcnZpY2VJbnN0YW5jZSA9IFZpZXdDb250ZXh0U2VydmljZXMuY29udGV4dFRvU2VydmljZShkYXRhLmNvbnRleHQpO1xuICAgIGlmIChzZXJ2aWNlSW5zdGFuY2UpIHtcbiAgICAgIGNvbnN0IHNlcnZpY2UgPSB0aGlzLmluamVjdG9yLmdldChcbiAgICAgICAgc2VydmljZUluc3RhbmNlIGFzIFR5cGU8SW5zdGFuY2VUeXBlPHR5cGVvZiBzZXJ2aWNlSW5zdGFuY2U+PlxuICAgICAgKTtcbiAgICAgIGNvbnN0IGRldGFpbHNVcmxSZWdleCA9IChzZXJ2aWNlIGFzIHR5cGVvZiBzZXJ2aWNlICYgeyBnZXREZXRhaWxVcmw/OiAoLi4uYXJncykgPT4gc3RyaW5nIH0pXG4gICAgICAgIC5nZXREZXRhaWxVcmwoZGF0YS5jb250ZXh0RGF0YSlcbiAgICAgICAgLnJlcGxhY2UoL1xcZCsvZywgJz9cXFxcZConKTtcbiAgICAgIGNvbnN0IGNvbnRleHRSZWdleCA9IG5ldyBSZWdFeHAoZGV0YWlsc1VybFJlZ2V4LCAnaScpO1xuICAgICAgY29uc3QgY2hpbGRyZW5SZWdleCA9IG5ldyBSZWdFeHAoYCR7ZGV0YWlsc1VybFJlZ2V4fS9jaGlsZGAsICdpJyk7XG4gICAgICBjb25zdCBmaWx0ZXJSZXNwb25zZSA9ICh7IHVybCwgbWV0aG9kIH0pID0+IHtcbiAgICAgICAgY29uc3QgY29udGV4dENoYW5nZWQgPSBjb250ZXh0UmVnZXgudGVzdCh1cmwpICYmIFsnUE9TVCcsICdQVVQnXS5pbmNsdWRlcyhtZXRob2QpO1xuICAgICAgICBjb25zdCBjaGlsZHJlbkFmZmVjdGVkID0gY2hpbGRyZW5SZWdleC50ZXN0KHVybCkgJiYgWydQT1NUJywgJ0RFTEVURSddLmluY2x1ZGVzKG1ldGhvZCk7XG4gICAgICAgIHJldHVybiBjb250ZXh0Q2hhbmdlZCB8fCBjaGlsZHJlbkFmZmVjdGVkO1xuICAgICAgfTtcbiAgICAgIHJldHVybiB0aGlzLmFwaVNlcnZpY2UuaG9va1Jlc3BvbnNlKGZpbHRlclJlc3BvbnNlKTtcbiAgICB9XG4gICAgcmV0dXJuIE5FVkVSO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVUYWJzKHRhYnMgPSBbXSkge1xuICAgIHRoaXMubGFzdEFkZGVkVGFicy5mb3JFYWNoKHQgPT4gdGhpcy50YWJzU2VydmljZS5yZW1vdmUodCkpO1xuICAgIHRoaXMubGFzdEFkZGVkVGFicyA9IHRhYnM7XG4gICAgdGFicy5mb3JFYWNoKHQgPT4gdGhpcy50YWJzU2VydmljZS5hZGQodCkpO1xuICAgIHRoaXMucmVkaXJlY3RUb0ZpcnN0VGFiT25VcGRhdGVUYWJzKCk7XG4gIH1cblxuICBwcml2YXRlIHJlZGlyZWN0VG9GaXJzdFRhYk9uVXBkYXRlVGFicygpIHtcbiAgICBjb25zdCBjdXJyZW50UXVlcnlQYXJhbXMgPSB0aGlzLnJvdXRlci5yb3V0ZXJTdGF0ZS5zbmFwc2hvdC5yb290LnF1ZXJ5UGFyYW1zO1xuICAgIGNvbnN0IHF1ZXJ5UGFyYW1zU3RyaW5nID0gbmV3IFVSTFNlYXJjaFBhcmFtcyhjdXJyZW50UXVlcnlQYXJhbXMpLnRvU3RyaW5nKCk7XG4gICAgY29uc3QgcXVlcnlQYXJhbXNTdWZmaXggPSBxdWVyeVBhcmFtc1N0cmluZyA/IGA/JHtxdWVyeVBhcmFtc1N0cmluZ31gIDogJyc7XG4gICAgY29uc3QgY3VycmVudENvbnRleHRJZCA9ICh0aGlzLnJvdXRlci51cmwubWF0Y2godGhpcy5JRF9SRUdFWCkgfHwgW10pLnNoaWZ0KCk7XG4gICAgaWYgKHRoaXMubmVlZHNSZWRpcmVjdExlZ2FjeSgpKSB7XG4gICAgICB0aGlzLnRhYnNTZXJ2aWNlLmZpcnN0VGFiJFxuICAgICAgICAucGlwZShmaWx0ZXIoKHRhYjogVGFiKSA9PiB0eXBlb2YgdGFiPy5wYXRoID09PSAnc3RyaW5nJykpXG4gICAgICAgIC5zdWJzY3JpYmUoKHRhYjogVGFiV2l0aFRlbXBsYXRlPHN0cmluZz4pID0+IHtcbiAgICAgICAgICBjb25zdCB0YWJQYXRoSWQgPSAodGFiLnBhdGgubWF0Y2godGhpcy5JRF9SRUdFWCkgfHwgW10pLnNoaWZ0KCk7XG4gICAgICAgICAgaWYgKGN1cnJlbnRDb250ZXh0SWQgPT09IHRhYlBhdGhJZCkge1xuICAgICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGVCeVVybChgJHt0YWIucGF0aH0ke3F1ZXJ5UGFyYW1zU3VmZml4fWAsIHsgcmVwbGFjZVVybDogdHJ1ZSB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbmVlZHNSZWRpcmVjdExlZ2FjeSgpOiBib29sZWFuIHtcbiAgICBjb25zdCB0cmVlOiBVcmxUcmVlID0gdGhpcy5yb3V0ZXIucGFyc2VVcmwodGhpcy5yb3V0ZXIudXJsKTtcbiAgICBjb25zdCBncm91cHM6IFVybFNlZ21lbnRHcm91cCA9IHRyZWUucm9vdC5jaGlsZHJlbltQUklNQVJZX09VVExFVF07XG5cbiAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5nZXRNYXRjaGluZ0NvbnRleHRSb3V0ZSh0aGlzLnJvdXRlci51cmwpO1xuICAgIGlmICghY29udGV4dCkge1xuICAgICAgcmV0dXJuIGdyb3Vwcy5zZWdtZW50cy5sZW5ndGggPT09IDI7XG4gICAgfVxuICAgIHJldHVybiBjb250ZXh0LnNwbGl0KCcvJykubGVuZ3RoID09PSBncm91cHMuc2VnbWVudHMubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSBuZWVkc1JlZGlyZWN0KGV2ZW50OiBBY3RpdmF0aW9uRW5kKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY29udGV4dFJvdXRlOiBWaWV3Q29udGV4dFJvb3RSb3V0ZSA9IGV2ZW50LnNuYXBzaG90LnJvdXRlQ29uZmlnIGFzIFZpZXdDb250ZXh0Um9vdFJvdXRlO1xuICAgIGlmICghY29udGV4dFJvdXRlLnJvb3RDb250ZXh0KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IGNvbnRleHRSb3V0ZUZyb21VcmwgPSB0aGlzLmdldE1hdGNoaW5nQ29udGV4dFJvdXRlKHRoaXMucm91dGVyLnVybCk7XG4gICAgcmV0dXJuIGNvbnRleHRSb3V0ZS5yb290Q29udGV4dCA9PT0gY29udGV4dFJvdXRlRnJvbVVybDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0TWF0Y2hpbmdDb250ZXh0Um91dGUodXJsOiBzdHJpbmcpOiBWaWV3Q29udGV4dCB7XG4gICAgY29uc3Qgdmlld0NvbnRleHRzID0gT2JqZWN0LnZhbHVlcyhWaWV3Q29udGV4dCk7XG4gICAgLy8gcmVwbGFjZSBhbGwgOmlkIHBsYWNlaG9sZGVycyB3aXRoIGEgcmVnZXggbWF0Y2hlciBmb3IgYSBudW1iZXJcbiAgICBjb25zdCByZWdleE1hdGNoZXJzID0gdmlld0NvbnRleHRzLm1hcChcbiAgICAgIGNvbnRleHQgPT4gYF4vJHtjb250ZXh0LnJlcGxhY2UoLzppZC9nLCAnKFswLTldKyknKX0oXFxcXD8uKik/JGBcbiAgICApO1xuICAgIGNvbnN0IG1hdGNoaW5nUmVnZXhDb250ZXh0ID0gcmVnZXhNYXRjaGVycy5maW5kKGNvbnRleHQgPT4gbmV3IFJlZ0V4cChjb250ZXh0KS50ZXN0KHVybCkpO1xuICAgIHJldHVybiBtYXRjaGluZ1JlZ2V4Q29udGV4dCA/IHZpZXdDb250ZXh0c1tyZWdleE1hdGNoZXJzLmluZGV4T2YobWF0Y2hpbmdSZWdleENvbnRleHQpXSA6IG51bGw7XG4gIH1cbn1cbiJdfQ==