UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

141 lines 30.1 kB
import { Component } from '@angular/core'; import { ActivatedRoute, Router, RouterOutlet } from '@angular/router'; import { AlertService, AppStateService, CoreModule, gettext } from '@c8y/ngx-components'; import { BehaviorSubject, firstValueFrom } from 'rxjs'; import { map, distinctUntilChanged, switchMap } from 'rxjs/operators'; import { cloneDeep } from 'lodash-es'; import { ApplyBrandingLocallyService, StoreBrandingService } from '@c8y/ngx-components/branding/shared/data'; import { FormControl } from '@angular/forms'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import * as i0 from "@angular/core"; import * as i1 from "@angular/router"; import * as i2 from "@c8y/ngx-components/branding/shared/data"; import * as i3 from "@c8y/ngx-components"; import * as i4 from "@angular/common"; export class EditBrandingRouterOutletComponent { constructor(activatedRoute, store, router, alert, applyBrandingService, appState) { this.activatedRoute = activatedRoute; this.store = store; this.router = router; this.alert = alert; this.applyBrandingService = applyBrandingService; this.appState = appState; this.formControl = new FormControl(undefined); this.newBranding = new BehaviorSubject(null); this.currentlyDisplayedComponent = new BehaviorSubject(null); this.isGlobalBranding$ = this.activatedRoute.data.pipe(map(({ tags }) => { return tags?.includes('latest'); })); this.tabName$ = this.currentlyDisplayedComponent.pipe(switchMap(() => this.activatedRoute.firstChild.data), map(data => data.tabName)); this.brandingName$ = this.activatedRoute.params.pipe(map(params => params.name)); this.formControl.addValidators(control => { try { JSON.parse(control.value); return null; } catch (e) { return { invalidJson: true }; } }); this.fallbackBranding$ = this.activatedRoute.data.pipe(map(data => data.fallbackBranding)); this.activatedRoute.data .pipe(takeUntilDestroyed(), distinctUntilChanged()) .subscribe(({ branding }) => { this.applyBrandingService.applyBranding(branding); this.formControl.setValue(JSON.stringify(branding, null, 2)); }); this.currentlyDisplayedComponent.pipe(takeUntilDestroyed()).subscribe(component => { if (!component) { return; } this.formControl.clearAsyncValidators(); component.registerOnChange(value => this.onBrandingVarChanges(value)); component.writeValue(this.formControl.value); if (component.validate) { this.formControl.addAsyncValidators(form => component.validate(form)); if (component.registerOnValidatorChange) { component.registerOnValidatorChange(() => this.formControl.updateValueAndValidity()); } } this.formControl.updateValueAndValidity(); }); } ngOnDestroy() { this.applyBrandingService.resetBranding(); } routeActivated(event) { this.currentlyDisplayedComponent.next(event); } async saveBranding() { try { const currentBranding = this.newBranding.value; const tagsOfCurrentVersion = await firstValueFrom(this.activatedRoute.data.pipe(map(data => data.tags))); const currentBrandingName = this.activatedRoute.snapshot.params.name; const { variants } = await this.store.loadBrandingVariants(); const currentBrandingObj = variants.find(v => v.tags.includes(currentBrandingName)); const currentVersion = currentBrandingObj.version; await this.store.saveExistingBranding(currentBranding, currentVersion, tagsOfCurrentVersion); this.router.navigate(['../../', currentBrandingName, this.activatedRoute.snapshot.routeConfig.path], { relativeTo: this.activatedRoute, replaceUrl: true }); this.alert.success(gettext('Branding saved. To apply this branding, refresh any open window that might be affected.')); } catch (e) { this.alert.addServerFailure(e, 'danger'); console.warn(e); } } cancel() { this.router.navigate(['branding-editor']); } async openPreview() { const name = this.activatedRoute.snapshot.params.name; this.store.openPreviewForBranding(name); } async markAsActive() { const currentBrandingName = this.activatedRoute.snapshot.params.name; const { variants } = await this.store.loadBrandingVariants(); const currentBrandingObj = variants.find(v => v.tags.includes(currentBrandingName)); await this.store.markAsActive(currentBrandingObj); } async onBrandingVarChanges(value) { this.formControl.setValue(value); try { const parsedValue = JSON.parse(value); const fallbackBranding = cloneDeep(await firstValueFrom(this.fallbackBranding$)); this.cleanUpObjects(parsedValue); this.cleanUpObjects(parsedValue.brandingCssVars); for (const key in fallbackBranding) { if (parsedValue[key] === undefined) { parsedValue[key] = fallbackBranding[key]; } if (typeof parsedValue[key] === 'object' && typeof fallbackBranding[key] === 'object') { parsedValue[key] = Object.assign(fallbackBranding[key], parsedValue[key]); } } this.applyBrandingService.applyBranding(parsedValue); this.newBranding.next(parsedValue); } catch (e) { // not valid JSON; } } cleanUpObjects(value) { if (!value) { return; } Object.keys(value).forEach(key => { if (value[key] === null || value[key] === '') { delete value[key]; } }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditBrandingRouterOutletComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.StoreBrandingService }, { token: i1.Router }, { token: i3.AlertService }, { token: i2.ApplyBrandingLocallyService }, { token: i3.AppStateService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: EditBrandingRouterOutletComponent, isStandalone: true, selector: "c8y-edit-branding-router-outlet", ngImport: i0, template: "<c8y-title>{{ brandingName$ | async }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'palette'\"\n [label]=\"'Branding' | translate\"\n [path]=\"'/branding-editor'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'cog'\"\n [label]=\"brandingName$ | async\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<div class=\"card card--fullpage content-fullpage\">\n <div class=\"card-header separator\">\n <div class=\"card-title\">{{ brandingName$ | async }} \u2014 {{ tabName$ | async | translate }}</div>\n </div>\n <router-outlet\n class=\"d-contents\"\n (activate)=\"routeActivated($event)\"\n ></router-outlet>\n\n <div class=\"card-footer separator\">\n <!-- footer content -->\n <button\n class=\"btn btn-default\"\n data-cy=\"branding-cancel\"\n (click)=\"cancel()\"\n translate\n >\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n data-cy=\"branding-save\"\n [disabled]=\"formControl.invalid\"\n (click)=\"saveBranding()\"\n translate\n >\n Save\n </button>\n <button\n class=\"btn btn-default\"\n data-cy=\"branding-save-as\"\n [disabled]=\"formControl.invalid\"\n (click)=\"openPreview()\"\n translate\n >\n Open preview\n </button>\n <button\n class=\"btn btn-default\"\n data-cy=\"branding-set-as-latest\"\n (click)=\"markAsActive()\"\n [disabled]=\"isGlobalBranding$ | async\"\n translate\n >\n Set as global\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i3.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i3.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i3.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "component", type: i3.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditBrandingRouterOutletComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-edit-branding-router-outlet', standalone: true, imports: [RouterOutlet, CoreModule], template: "<c8y-title>{{ brandingName$ | async }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'palette'\"\n [label]=\"'Branding' | translate\"\n [path]=\"'/branding-editor'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'cog'\"\n [label]=\"brandingName$ | async\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<div class=\"card card--fullpage content-fullpage\">\n <div class=\"card-header separator\">\n <div class=\"card-title\">{{ brandingName$ | async }} \u2014 {{ tabName$ | async | translate }}</div>\n </div>\n <router-outlet\n class=\"d-contents\"\n (activate)=\"routeActivated($event)\"\n ></router-outlet>\n\n <div class=\"card-footer separator\">\n <!-- footer content -->\n <button\n class=\"btn btn-default\"\n data-cy=\"branding-cancel\"\n (click)=\"cancel()\"\n translate\n >\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n data-cy=\"branding-save\"\n [disabled]=\"formControl.invalid\"\n (click)=\"saveBranding()\"\n translate\n >\n Save\n </button>\n <button\n class=\"btn btn-default\"\n data-cy=\"branding-save-as\"\n [disabled]=\"formControl.invalid\"\n (click)=\"openPreview()\"\n translate\n >\n Open preview\n </button>\n <button\n class=\"btn btn-default\"\n data-cy=\"branding-set-as-latest\"\n (click)=\"markAsActive()\"\n [disabled]=\"isGlobalBranding$ | async\"\n translate\n >\n Set as global\n </button>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: i2.StoreBrandingService }, { type: i1.Router }, { type: i3.AlertService }, { type: i2.ApplyBrandingLocallyService }, { type: i3.AppStateService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRpdC1icmFuZGluZy1yb3V0ZXItb3V0bGV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2JyYW5kaW5nL3NoYXJlZC9sYXp5L2VkaXQtYnJhbmRpbmctcm91dGVyLW91dGxldC9lZGl0LWJyYW5kaW5nLXJvdXRlci1vdXRsZXQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vYnJhbmRpbmcvc2hhcmVkL2xhenkvZWRpdC1icmFuZGluZy1yb3V0ZXItb3V0bGV0L2VkaXQtYnJhbmRpbmctcm91dGVyLW91dGxldC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFhLE1BQU0sZUFBZSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN6RixPQUFPLEVBQUUsZUFBZSxFQUFjLGNBQWMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNuRSxPQUFPLEVBQUUsR0FBRyxFQUFFLG9CQUFvQixFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDdEMsT0FBTyxFQUNMLDJCQUEyQixFQUUzQixvQkFBb0IsRUFDckIsTUFBTSwwQ0FBMEMsQ0FBQztBQUNsRCxPQUFPLEVBQXdDLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ25GLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDOzs7Ozs7QUFRaEUsTUFBTSxPQUFPLGlDQUFpQztJQVc1QyxZQUNVLGNBQThCLEVBQzlCLEtBQTJCLEVBQzNCLE1BQWMsRUFDZCxLQUFtQixFQUNuQixvQkFBaUQsRUFDakQsUUFBeUI7UUFMekIsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQzlCLFVBQUssR0FBTCxLQUFLLENBQXNCO1FBQzNCLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxVQUFLLEdBQUwsS0FBSyxDQUFjO1FBQ25CLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBNkI7UUFDakQsYUFBUSxHQUFSLFFBQVEsQ0FBaUI7UUFmbkMsZ0JBQVcsR0FBRyxJQUFJLFdBQVcsQ0FBUyxTQUFTLENBQUMsQ0FBQztRQUl6QyxnQkFBVyxHQUFHLElBQUksZUFBZSxDQUFzQixJQUFJLENBQUMsQ0FBQztRQUM3RCxnQ0FBMkIsR0FBRyxJQUFJLGVBQWUsQ0FFdkQsSUFBSSxDQUFDLENBQUM7UUFVTixJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUNwRCxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUU7WUFDZixPQUFPLElBQUksRUFBRSxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbEMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztRQUNGLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FDbkQsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUNwRCxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQzFCLENBQUM7UUFDRixJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNqRixJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUN2QyxJQUFJLENBQUM7Z0JBQ0gsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQzFCLE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztZQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ1gsT0FBTyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUMvQixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7UUFDM0YsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJO2FBQ3JCLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLG9CQUFvQixFQUFFLENBQUM7YUFDbEQsU0FBUyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFO1lBQzFCLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDbEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDL0QsQ0FBQyxDQUFDLENBQUM7UUFDTCxJQUFJLENBQUMsMkJBQTJCLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLEVBQUU7WUFDaEYsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNmLE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1lBQ3hDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ3RFLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM3QyxJQUFJLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDdkIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDdEUsSUFBSSxTQUFTLENBQUMseUJBQXlCLEVBQUUsQ0FBQztvQkFDeEMsU0FBUyxDQUFDLHlCQUF5QixDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO2dCQUN2RixDQUFDO1lBQ0gsQ0FBQztZQUVELElBQUksQ0FBQyxXQUFXLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztRQUM1QyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzVDLENBQUM7SUFFRCxjQUFjLENBQUMsS0FBcUQ7UUFDbEUsSUFBSSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRUQsS0FBSyxDQUFDLFlBQVk7UUFDaEIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDL0MsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLGNBQWMsQ0FDL0MsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUN0RCxDQUFDO1lBRUYsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1lBQ3JFLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztZQUM3RCxNQUFNLGtCQUFrQixHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUM7WUFDcEYsTUFBTSxjQUFjLEdBQUcsa0JBQWtCLENBQUMsT0FBTyxDQUFDO1lBQ2xELE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxlQUFlLEVBQUUsY0FBYyxFQUFFLG9CQUFvQixDQUFDLENBQUM7WUFDN0YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQ2xCLENBQUMsUUFBUSxFQUFFLG1CQUFtQixFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFDOUU7Z0JBQ0UsVUFBVSxFQUFFLElBQUksQ0FBQyxjQUFjO2dCQUMvQixVQUFVLEVBQUUsSUFBSTthQUNqQixDQUNGLENBQUM7WUFDRixJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FDaEIsT0FBTyxDQUNMLHlGQUF5RixDQUMxRixDQUNGLENBQUM7UUFDSixDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3pDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEIsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNO1FBQ0osSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVELEtBQUssQ0FBQyxXQUFXO1FBQ2YsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztRQUN0RCxJQUFJLENBQUMsS0FBSyxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRCxLQUFLLENBQUMsWUFBWTtRQUNoQixNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFDckUsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQzdELE1BQU0sa0JBQWtCLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQztRQUNwRixNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxLQUFhO1FBQ3RDLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRWpDLElBQUksQ0FBQztZQUNILE1BQU0sV0FBVyxHQUF3QixJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzNELE1BQU0sZ0JBQWdCLEdBQXdCLFNBQVMsQ0FDckQsTUFBTSxjQUFjLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQzdDLENBQUM7WUFDRixJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ2pELEtBQUssTUFBTSxHQUFHLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztnQkFDbkMsSUFBSSxXQUFXLENBQUMsR0FBRyxDQUFDLEtBQUssU0FBUyxFQUFFLENBQUM7b0JBQ25DLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDM0MsQ0FBQztnQkFFRCxJQUFJLE9BQU8sV0FBVyxDQUFDLEdBQUcsQ0FBQyxLQUFLLFFBQVEsSUFBSSxPQUFPLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUN0RixXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsRUFBRSxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDNUUsQ0FBQztZQUNILENBQUM7WUFDRCxJQUFJLENBQUMsb0JBQW9CLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3JELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1gsa0JBQWtCO1FBQ3BCLENBQUM7SUFDSCxDQUFDO0lBRU8sY0FBYyxDQUFDLEtBQTBCO1FBQy9DLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDL0IsSUFBSSxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSSxJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDN0MsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDcEIsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzsrR0F2SlUsaUNBQWlDO21HQUFqQyxpQ0FBaUMsMkZDcEI5QywraURBOERBLDRDRDVDWSxZQUFZLDBKQUFFLFVBQVU7OzRGQUV2QixpQ0FBaUM7a0JBTjdDLFNBQVM7K0JBQ0UsaUNBQWlDLGNBRS9CLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxVQUFVLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIFJvdXRlciwgUm91dGVyT3V0bGV0IH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEFsZXJ0U2VydmljZSwgQXBwU3RhdGVTZXJ2aWNlLCBDb3JlTW9kdWxlLCBnZXR0ZXh0IH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cyc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUsIGZpcnN0VmFsdWVGcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAsIGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBjbG9uZURlZXAgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHtcbiAgQXBwbHlCcmFuZGluZ0xvY2FsbHlTZXJ2aWNlLFxuICBCcmFuZGluZ09wdGlvbnNKc29uLFxuICBTdG9yZUJyYW5kaW5nU2VydmljZVxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL2JyYW5kaW5nL3NoYXJlZC9kYXRhJztcbmltcG9ydCB7IEFzeW5jVmFsaWRhdG9yLCBDb250cm9sVmFsdWVBY2Nlc3NvciwgRm9ybUNvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1lZGl0LWJyYW5kaW5nLXJvdXRlci1vdXRsZXQnLFxuICB0ZW1wbGF0ZVVybDogJy4vZWRpdC1icmFuZGluZy1yb3V0ZXItb3V0bGV0LmNvbXBvbmVudC5odG1sJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1JvdXRlck91dGxldCwgQ29yZU1vZHVsZV1cbn0pXG5leHBvcnQgY2xhc3MgRWRpdEJyYW5kaW5nUm91dGVyT3V0bGV0Q29tcG9uZW50IGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgYnJhbmRpbmdOYW1lJDogT2JzZXJ2YWJsZTxzdHJpbmc+O1xuICBmb3JtQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbDxzdHJpbmc+KHVuZGVmaW5lZCk7XG4gIGZhbGxiYWNrQnJhbmRpbmckOiBPYnNlcnZhYmxlPEJyYW5kaW5nT3B0aW9uc0pzb24+O1xuICB0YWJOYW1lJDogT2JzZXJ2YWJsZTxzdHJpbmc+O1xuICBpc0dsb2JhbEJyYW5kaW5nJDogT2JzZXJ2YWJsZTxib29sZWFuPjtcbiAgcHJpdmF0ZSBuZXdCcmFuZGluZyA9IG5ldyBCZWhhdmlvclN1YmplY3Q8QnJhbmRpbmdPcHRpb25zSnNvbj4obnVsbCk7XG4gIHByaXZhdGUgY3VycmVudGx5RGlzcGxheWVkQ29tcG9uZW50ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxcbiAgICAoQ29udHJvbFZhbHVlQWNjZXNzb3IgJiBQYXJ0aWFsPEFzeW5jVmFsaWRhdG9yPikgfCBudWxsXG4gID4obnVsbCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBhY3RpdmF0ZWRSb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICAgcHJpdmF0ZSBzdG9yZTogU3RvcmVCcmFuZGluZ1NlcnZpY2UsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcbiAgICBwcml2YXRlIGFsZXJ0OiBBbGVydFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBhcHBseUJyYW5kaW5nU2VydmljZTogQXBwbHlCcmFuZGluZ0xvY2FsbHlTZXJ2aWNlLFxuICAgIHByaXZhdGUgYXBwU3RhdGU6IEFwcFN0YXRlU2VydmljZVxuICApIHtcbiAgICB0aGlzLmlzR2xvYmFsQnJhbmRpbmckID0gdGhpcy5hY3RpdmF0ZWRSb3V0ZS5kYXRhLnBpcGUoXG4gICAgICBtYXAoKHsgdGFncyB9KSA9PiB7XG4gICAgICAgIHJldHVybiB0YWdzPy5pbmNsdWRlcygnbGF0ZXN0Jyk7XG4gICAgICB9KVxuICAgICk7XG4gICAgdGhpcy50YWJOYW1lJCA9IHRoaXMuY3VycmVudGx5RGlzcGxheWVkQ29tcG9uZW50LnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5hY3RpdmF0ZWRSb3V0ZS5maXJzdENoaWxkLmRhdGEpLFxuICAgICAgbWFwKGRhdGEgPT4gZGF0YS50YWJOYW1lKVxuICAgICk7XG4gICAgdGhpcy5icmFuZGluZ05hbWUkID0gdGhpcy5hY3RpdmF0ZWRSb3V0ZS5wYXJhbXMucGlwZShtYXAocGFyYW1zID0+IHBhcmFtcy5uYW1lKSk7XG4gICAgdGhpcy5mb3JtQ29udHJvbC5hZGRWYWxpZGF0b3JzKGNvbnRyb2wgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgSlNPTi5wYXJzZShjb250cm9sLnZhbHVlKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiB7IGludmFsaWRKc29uOiB0cnVlIH07XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5mYWxsYmFja0JyYW5kaW5nJCA9IHRoaXMuYWN0aXZhdGVkUm91dGUuZGF0YS5waXBlKG1hcChkYXRhID0+IGRhdGEuZmFsbGJhY2tCcmFuZGluZykpO1xuICAgIHRoaXMuYWN0aXZhdGVkUm91dGUuZGF0YVxuICAgICAgLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKCksIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCkpXG4gICAgICAuc3Vic2NyaWJlKCh7IGJyYW5kaW5nIH0pID0+IHtcbiAgICAgICAgdGhpcy5hcHBseUJyYW5kaW5nU2VydmljZS5hcHBseUJyYW5kaW5nKGJyYW5kaW5nKTtcbiAgICAgICAgdGhpcy5mb3JtQ29udHJvbC5zZXRWYWx1ZShKU09OLnN0cmluZ2lmeShicmFuZGluZywgbnVsbCwgMikpO1xuICAgICAgfSk7XG4gICAgdGhpcy5jdXJyZW50bHlEaXNwbGF5ZWRDb21wb25lbnQucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQoKSkuc3Vic2NyaWJlKGNvbXBvbmVudCA9PiB7XG4gICAgICBpZiAoIWNvbXBvbmVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aGlzLmZvcm1Db250cm9sLmNsZWFyQXN5bmNWYWxpZGF0b3JzKCk7XG4gICAgICBjb21wb25lbnQucmVnaXN0ZXJPbkNoYW5nZSh2YWx1ZSA9PiB0aGlzLm9uQnJhbmRpbmdWYXJDaGFuZ2VzKHZhbHVlKSk7XG4gICAgICBjb21wb25lbnQud3JpdGVWYWx1ZSh0aGlzLmZvcm1Db250cm9sLnZhbHVlKTtcbiAgICAgIGlmIChjb21wb25lbnQudmFsaWRhdGUpIHtcbiAgICAgICAgdGhpcy5mb3JtQ29udHJvbC5hZGRBc3luY1ZhbGlkYXRvcnMoZm9ybSA9PiBjb21wb25lbnQudmFsaWRhdGUoZm9ybSkpO1xuICAgICAgICBpZiAoY29tcG9uZW50LnJlZ2lzdGVyT25WYWxpZGF0b3JDaGFuZ2UpIHtcbiAgICAgICAgICBjb21wb25lbnQucmVnaXN0ZXJPblZhbGlkYXRvckNoYW5nZSgoKSA9PiB0aGlzLmZvcm1Db250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5mb3JtQ29udHJvbC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XG4gICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmFwcGx5QnJhbmRpbmdTZXJ2aWNlLnJlc2V0QnJhbmRpbmcoKTtcbiAgfVxuXG4gIHJvdXRlQWN0aXZhdGVkKGV2ZW50OiBDb250cm9sVmFsdWVBY2Nlc3NvciAmIFBhcnRpYWw8QXN5bmNWYWxpZGF0b3I+KSB7XG4gICAgdGhpcy5jdXJyZW50bHlEaXNwbGF5ZWRDb21wb25lbnQubmV4dChldmVudCk7XG4gIH1cblxuICBhc3luYyBzYXZlQnJhbmRpbmcoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGN1cnJlbnRCcmFuZGluZyA9IHRoaXMubmV3QnJhbmRpbmcudmFsdWU7XG4gICAgICBjb25zdCB0YWdzT2ZDdXJyZW50VmVyc2lvbiA9IGF3YWl0IGZpcnN0VmFsdWVGcm9tKFxuICAgICAgICB0aGlzLmFjdGl2YXRlZFJvdXRlLmRhdGEucGlwZShtYXAoZGF0YSA9PiBkYXRhLnRhZ3MpKVxuICAgICAgKTtcblxuICAgICAgY29uc3QgY3VycmVudEJyYW5kaW5nTmFtZSA9IHRoaXMuYWN0aXZhdGVkUm91dGUuc25hcHNob3QucGFyYW1zLm5hbWU7XG4gICAgICBjb25zdCB7IHZhcmlhbnRzIH0gPSBhd2FpdCB0aGlzLnN0b3JlLmxvYWRCcmFuZGluZ1ZhcmlhbnRzKCk7XG4gICAgICBjb25zdCBjdXJyZW50QnJhbmRpbmdPYmogPSB2YXJpYW50cy5maW5kKHYgPT4gdi50YWdzLmluY2x1ZGVzKGN1cnJlbnRCcmFuZGluZ05hbWUpKTtcbiAgICAgIGNvbnN0IGN1cnJlbnRWZXJzaW9uID0gY3VycmVudEJyYW5kaW5nT2JqLnZlcnNpb247XG4gICAgICBhd2FpdCB0aGlzLnN0b3JlLnNhdmVFeGlzdGluZ0JyYW5kaW5nKGN1cnJlbnRCcmFuZGluZywgY3VycmVudFZlcnNpb24sIHRhZ3NPZkN1cnJlbnRWZXJzaW9uKTtcbiAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFxuICAgICAgICBbJy4uLy4uLycsIGN1cnJlbnRCcmFuZGluZ05hbWUsIHRoaXMuYWN0aXZhdGVkUm91dGUuc25hcHNob3Qucm91dGVDb25maWcucGF0aF0sXG4gICAgICAgIHtcbiAgICAgICAgICByZWxhdGl2ZVRvOiB0aGlzLmFjdGl2YXRlZFJvdXRlLFxuICAgICAgICAgIHJlcGxhY2VVcmw6IHRydWVcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICAgIHRoaXMuYWxlcnQuc3VjY2VzcyhcbiAgICAgICAgZ2V0dGV4dChcbiAgICAgICAgICAnQnJhbmRpbmcgc2F2ZWQuIFRvIGFwcGx5IHRoaXMgYnJhbmRpbmcsIHJlZnJlc2ggYW55IG9wZW4gd2luZG93IHRoYXQgbWlnaHQgYmUgYWZmZWN0ZWQuJ1xuICAgICAgICApXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuYWxlcnQuYWRkU2VydmVyRmFpbHVyZShlLCAnZGFuZ2VyJyk7XG4gICAgICBjb25zb2xlLndhcm4oZSk7XG4gICAgfVxuICB9XG5cbiAgY2FuY2VsKCkge1xuICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnYnJhbmRpbmctZWRpdG9yJ10pO1xuICB9XG5cbiAgYXN5bmMgb3BlblByZXZpZXcoKSB7XG4gICAgY29uc3QgbmFtZSA9IHRoaXMuYWN0aXZhdGVkUm91dGUuc25hcHNob3QucGFyYW1zLm5hbWU7XG4gICAgdGhpcy5zdG9yZS5vcGVuUHJldmlld0ZvckJyYW5kaW5nKG5hbWUpO1xuICB9XG5cbiAgYXN5bmMgbWFya0FzQWN0aXZlKCkge1xuICAgIGNvbnN0IGN1cnJlbnRCcmFuZGluZ05hbWUgPSB0aGlzLmFjdGl2YXRlZFJvdXRlLnNuYXBzaG90LnBhcmFtcy5uYW1lO1xuICAgIGNvbnN0IHsgdmFyaWFudHMgfSA9IGF3YWl0IHRoaXMuc3RvcmUubG9hZEJyYW5kaW5nVmFyaWFudHMoKTtcbiAgICBjb25zdCBjdXJyZW50QnJhbmRpbmdPYmogPSB2YXJpYW50cy5maW5kKHYgPT4gdi50YWdzLmluY2x1ZGVzKGN1cnJlbnRCcmFuZGluZ05hbWUpKTtcbiAgICBhd2FpdCB0aGlzLnN0b3JlLm1hcmtBc0FjdGl2ZShjdXJyZW50QnJhbmRpbmdPYmopO1xuICB9XG5cbiAgYXN5bmMgb25CcmFuZGluZ1ZhckNoYW5nZXModmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuZm9ybUNvbnRyb2wuc2V0VmFsdWUodmFsdWUpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBhcnNlZFZhbHVlOiBCcmFuZGluZ09wdGlvbnNKc29uID0gSlNPTi5wYXJzZSh2YWx1ZSk7XG4gICAgICBjb25zdCBmYWxsYmFja0JyYW5kaW5nOiBCcmFuZGluZ09wdGlvbnNKc29uID0gY2xvbmVEZWVwKFxuICAgICAgICBhd2FpdCBmaXJzdFZhbHVlRnJvbSh0aGlzLmZhbGxiYWNrQnJhbmRpbmckKVxuICAgICAgKTtcbiAgICAgIHRoaXMuY2xlYW5VcE9iamVjdHMocGFyc2VkVmFsdWUpO1xuICAgICAgdGhpcy5jbGVhblVwT2JqZWN0cyhwYXJzZWRWYWx1ZS5icmFuZGluZ0Nzc1ZhcnMpO1xuICAgICAgZm9yIChjb25zdCBrZXkgaW4gZmFsbGJhY2tCcmFuZGluZykge1xuICAgICAgICBpZiAocGFyc2VkVmFsdWVba2V5XSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcGFyc2VkVmFsdWVba2V5XSA9IGZhbGxiYWNrQnJhbmRpbmdba2V5XTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgcGFyc2VkVmFsdWVba2V5XSA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIGZhbGxiYWNrQnJhbmRpbmdba2V5XSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBwYXJzZWRWYWx1ZVtrZXldID0gT2JqZWN0LmFzc2lnbihmYWxsYmFja0JyYW5kaW5nW2tleV0sIHBhcnNlZFZhbHVlW2tleV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLmFwcGx5QnJhbmRpbmdTZXJ2aWNlLmFwcGx5QnJhbmRpbmcocGFyc2VkVmFsdWUpO1xuICAgICAgdGhpcy5uZXdCcmFuZGluZy5uZXh0KHBhcnNlZFZhbHVlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBub3QgdmFsaWQgSlNPTjtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNsZWFuVXBPYmplY3RzKHZhbHVlOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSB7XG4gICAgaWYgKCF2YWx1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBPYmplY3Qua2V5cyh2YWx1ZSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgaWYgKHZhbHVlW2tleV0gPT09IG51bGwgfHwgdmFsdWVba2V5XSA9PT0gJycpIHtcbiAgICAgICAgZGVsZXRlIHZhbHVlW2tleV07XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cbiIsIjxjOHktdGl0bGU+e3sgYnJhbmRpbmdOYW1lJCB8IGFzeW5jIH19PC9jOHktdGl0bGU+XG5cbjxjOHktYnJlYWRjcnVtYj5cbiAgPGM4eS1icmVhZGNydW1iLWl0ZW1cbiAgICBbaWNvbl09XCIncGFsZXR0ZSdcIlxuICAgIFtsYWJlbF09XCInQnJhbmRpbmcnIHwgdHJhbnNsYXRlXCJcbiAgICBbcGF0aF09XCInL2JyYW5kaW5nLWVkaXRvcidcIlxuICA+PC9jOHktYnJlYWRjcnVtYi1pdGVtPlxuICA8Yzh5LWJyZWFkY3J1bWItaXRlbVxuICAgIFtpY29uXT1cIidjb2cnXCJcbiAgICBbbGFiZWxdPVwiYnJhbmRpbmdOYW1lJCB8IGFzeW5jXCJcbiAgPjwvYzh5LWJyZWFkY3J1bWItaXRlbT5cbjwvYzh5LWJyZWFkY3J1bWI+XG5cbjxkaXYgY2xhc3M9XCJjYXJkIGNhcmQtLWZ1bGxwYWdlIGNvbnRlbnQtZnVsbHBhZ2VcIj5cbiAgPGRpdiBjbGFzcz1cImNhcmQtaGVhZGVyIHNlcGFyYXRvclwiPlxuICAgIDxkaXYgY2xhc3M9XCJjYXJkLXRpdGxlXCI+e3sgYnJhbmRpbmdOYW1lJCB8IGFzeW5jIH19IOKAlCB7eyB0YWJOYW1lJCB8IGFzeW5jIHwgdHJhbnNsYXRlIH19PC9kaXY+XG4gIDwvZGl2PlxuICA8cm91dGVyLW91dGxldFxuICAgIGNsYXNzPVwiZC1jb250ZW50c1wiXG4gICAgKGFjdGl2YXRlKT1cInJvdXRlQWN0aXZhdGVkKCRldmVudClcIlxuICA+PC9yb3V0ZXItb3V0bGV0PlxuXG4gIDxkaXYgY2xhc3M9XCJjYXJkLWZvb3RlciBzZXBhcmF0b3JcIj5cbiAgICA8IS0tIGZvb3RlciBjb250ZW50IC0tPlxuICAgIDxidXR0b25cbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0XCJcbiAgICAgIGRhdGEtY3k9XCJicmFuZGluZy1jYW5jZWxcIlxuICAgICAgKGNsaWNrKT1cImNhbmNlbCgpXCJcbiAgICAgIHRyYW5zbGF0ZVxuICAgID5cbiAgICAgIENhbmNlbFxuICAgIDwvYnV0dG9uPlxuICAgIDxidXR0b25cbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5XCJcbiAgICAgIGRhdGEtY3k9XCJicmFuZGluZy1zYXZlXCJcbiAgICAgIFtkaXNhYmxlZF09XCJmb3JtQ29udHJvbC5pbnZhbGlkXCJcbiAgICAgIChjbGljayk9XCJzYXZlQnJhbmRpbmcoKVwiXG4gICAgICB0cmFuc2xhdGVcbiAgICA+XG4gICAgICBTYXZlXG4gICAgPC9idXR0b24+XG4gICAgPGJ1dHRvblxuICAgICAgY2xhc3M9XCJidG4gYnRuLWRlZmF1bHRcIlxuICAgICAgZGF0YS1jeT1cImJyYW5kaW5nLXNhdmUtYXNcIlxuICAgICAgW2Rpc2FibGVkXT1cImZvcm1Db250cm9sLmludmFsaWRcIlxuICAgICAgKGNsaWNrKT1cIm9wZW5QcmV2aWV3KClcIlxuICAgICAgdHJhbnNsYXRlXG4gICAgPlxuICAgICAgT3BlbiBwcmV2aWV3XG4gICAgPC9idXR0b24+XG4gICAgPGJ1dHRvblxuICAgICAgY2xhc3M9XCJidG4gYnRuLWRlZmF1bHRcIlxuICAgICAgZGF0YS1jeT1cImJyYW5kaW5nLXNldC1hcy1sYXRlc3RcIlxuICAgICAgKGNsaWNrKT1cIm1hcmtBc0FjdGl2ZSgpXCJcbiAgICAgIFtkaXNhYmxlZF09XCJpc0dsb2JhbEJyYW5kaW5nJCB8IGFzeW5jXCJcbiAgICAgIHRyYW5zbGF0ZVxuICAgID5cbiAgICAgIFNldCBhcyBnbG9iYWxcbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==