@universis/common
Version:
Universis - common directives and services
510 lines • 60.8 kB
JavaScript
import { Component, Input, ElementRef, ViewEncapsulation, Renderer2 } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ButtonTypes } from './ButtonTypes';
import * as i0 from "@angular/core";
import * as i1 from "@angular/router";
import * as i2 from "@angular/common";
import * as i3 from "@ngx-translate/core";
export class RouterModalComponent {
constructor(_element, _activatedRoute, _router, _renderer) {
this._element = _element;
this._activatedRoute = _activatedRoute;
this._router = _router;
this._renderer = _renderer;
this.componentModalChanges = null;
this.componentButtonChanges = null;
this.waiting = false;
this.modalTitle = '';
// these properties are here as inputs in order to have a way to customize text and class of each button
this.okButtonText = ButtonTypes.ok.buttonText;
this.okButtonClass = ButtonTypes.ok.buttonClass;
this.cancelButtonText = ButtonTypes.cancel.buttonText;
this.cancelButtonClass = ButtonTypes.cancel.buttonClass;
this.yesButtonText = ButtonTypes.yes.buttonText;
this.yesButtonClass = ButtonTypes.yes.buttonClass;
this.noButtonText = ButtonTypes.no.buttonText;
this.noButtonClass = ButtonTypes.no.buttonClass;
this.abortButtonText = ButtonTypes.abort.buttonText;
this.abortButtonClass = ButtonTypes.abort.buttonClass;
this.retryButtonText = ButtonTypes.retry.buttonText;
this.retryButtonClass = ButtonTypes.retry.buttonClass;
this.ignoreButtonText = ButtonTypes.ignore.buttonText;
this.ignoreButtonClass = ButtonTypes.ignore.buttonClass;
this.previousButtonText = ButtonTypes.previous.buttonText;
this.previousButtonClass = ButtonTypes.previous.buttonClass;
this.nextButtonText = ButtonTypes.next.buttonText;
this.nextButtonClass = ButtonTypes.next.buttonClass;
// default instance buttons
this.instanceButtons = {
ok: null,
cancel: null,
yes: null,
no: null,
abort: null,
retry: null,
ignore: null,
previous: null,
next: null
};
}
async cancel() {
try {
if (this.componentReference) {
// set waiting
this.waiting = true;
// if component has cancel() method
if (typeof this.componentReference.cancel === 'function') {
// do cancel
await this.componentReference.cancel();
}
else {
await this._router.navigate(['../'], { relativeTo: this._activatedRoute });
}
// unset waiting
this.waiting = false;
}
}
catch (err) {
this.waiting = false;
}
}
async ok() {
try {
if (this.componentReference) {
// set waiting
this.waiting = true;
if (typeof this.componentReference.ok === 'function') {
// do submit
await this.componentReference.ok();
}
else {
await this._router.navigate(['../'], { relativeTo: this._activatedRoute });
}
// unset waiting
this.waiting = false;
}
}
catch (err) {
this.waiting = false;
}
}
async abort() {
try {
if (this.componentReference) {
// set waiting
this.waiting = true;
if (typeof this.componentReference.abort === 'function') {
// do submit
await this.componentReference.abort();
}
else {
await this._router.navigate(['../'], { relativeTo: this._activatedRoute });
}
// unset waiting
this.waiting = false;
}
}
catch (err) {
this.waiting = false;
}
}
async retry() {
try {
if (this.componentReference) {
// set waiting
this.waiting = true;
if (typeof this.componentReference.retry === 'function') {
// do submit
await this.componentReference.retry();
}
else {
await this._router.navigate(['../'], { relativeTo: this._activatedRoute });
}
// unset waiting
this.waiting = false;
}
}
catch (err) {
this.waiting = false;
}
}
async ignore() {
try {
if (this.componentReference) {
// set waiting
this.waiting = true;
if (typeof this.componentReference.ignore === 'function') {
// do submit
await this.componentReference.ignore();
}
else {
await this._router.navigate(['../'], { relativeTo: this._activatedRoute });
}
// unset waiting
this.waiting = false;
}
}
catch (err) {
this.waiting = false;
}
}
async previous() {
try {
if (this.componentReference) {
// set waiting
this.waiting = true;
if (typeof this.componentReference.previous === 'function') {
// do submit
await this.componentReference.previous();
}
else {
await this._router.navigate(['../'], { relativeTo: this._activatedRoute });
}
// unset waiting
this.waiting = false;
}
}
catch (err) {
this.waiting = false;
}
}
async next() {
try {
if (this.componentReference) {
// set waiting
this.waiting = true;
if (typeof this.componentReference.next === 'function') {
// do submit
await this.componentReference.next();
}
else {
await this._router.navigate(['../'], { relativeTo: this._activatedRoute });
}
// unset waiting
this.waiting = false;
}
}
catch (err) {
this.waiting = false;
}
}
async yes() {
try {
if (this.componentReference) {
// set waiting
this.waiting = true;
if (typeof this.componentReference.yes === 'function') {
// do submit
await this.componentReference.yes();
}
else {
await this._router.navigate(['../'], { relativeTo: this._activatedRoute });
}
// unset waiting
this.waiting = false;
}
}
catch (err) {
this.waiting = false;
}
}
async no() {
try {
if (this.componentReference) {
// set waiting
this.waiting = true;
if (typeof this.componentReference.no === 'function') {
// do submit
await this.componentReference.no();
}
else {
await this._router.navigate(['../'], { relativeTo: this._activatedRoute });
}
// unset waiting
this.waiting = false;
}
}
catch (err) {
this.waiting = false;
}
}
onActivate(event) {
this.componentReference = event;
// get router outlet component
if (this.componentReference) {
if (this.componentReference.buttonChanges) {
// subscribe for any button changes
this.componentButtonChanges = this.componentReference.buttonChanges
.subscribe((buttonChange) => {
if (buttonChange) {
// assign button changes
Object.assign(this.instanceButtons, buttonChange);
}
});
}
if (this.componentReference.modalChanges) {
// get modal changes
this.componentModalChanges = this.componentReference.modalChanges.subscribe((modalChanges) => {
this.modalInstanceTitle = modalChanges.modalTitle;
if (modalChanges.modalClass) {
this.modalInstanceClass = modalChanges.modalClass;
}
});
}
// get title
this.modalInstanceTitle = this.componentReference.modalTitle;
// get class
this.modalInstanceClass = this.componentReference.modalClass;
// hold this to validate buttons
let hasAtLeastOneButton = false;
this.instanceButtons = {
ok: null,
cancel: null,
yes: null,
no: null,
abort: null,
retry: null,
ignore: null,
previous: null,
next: null
};
// enumerate button types
Object.keys(ButtonTypes).forEach(key => {
// search if component has a method with the same name
if (typeof this.componentReference[key] === 'function') {
// enable button
this.instanceButtons[key] = Object.assign({}, ButtonTypes[key]);
hasAtLeastOneButton = true;
const buttonTextProperty = `${key}ButtonText`;
if (this.componentReference.hasOwnProperty(buttonTextProperty)) {
this.instanceButtons[key].buttonText = this.componentReference[buttonTextProperty];
}
else {
// get property from this component
this.instanceButtons[key].buttonText = this[buttonTextProperty];
}
const buttonClassProperty = `${key}ButtonClass`;
if (this.componentReference.hasOwnProperty(buttonClassProperty)) {
this.instanceButtons[key].buttonClass = this.componentReference[buttonClassProperty];
}
else {
// get property from this component
this.instanceButtons[key].buttonClass = this[buttonClassProperty];
}
}
});
if (!hasAtLeastOneButton) {
// there are no buttons, so add only ok
this.instanceButtons.ok = Object.assign({}, ButtonTypes.ok);
}
}
const backdropElement = this._element.nativeElement.querySelector('.modal-backdrop');
this._element.nativeElement.querySelector('.bd-modal').classList.remove('d-none');
this._renderer.addClass(document.body, 'overflow-hidden');
this._renderer.addClass(document.body, 'pr-3');
// add large modal default styles
// this operation adds scrolling to modal container
// in cases where modal overflows the height of the container
const modalElement = this._element.nativeElement.querySelector('.modal');
if (modalElement) {
modalElement.style.setProperty('overflow-x', 'hidden');
modalElement.style.setProperty('overflow-y', 'auto');
}
if (backdropElement) {
// remove d-none
backdropElement.classList.remove('d-none');
// add show
backdropElement.classList.add('show');
}
return false;
}
// noinspection JSUnusedLocalSymbols
onDeactivate(event) {
if (this.componentModalChanges) {
this.componentModalChanges.unsubscribe();
this.componentModalChanges = null;
}
if (this.componentButtonChanges) {
this.componentButtonChanges.unsubscribe();
this.componentButtonChanges = null;
}
// restore properties
this.modalInstanceTitle = this.modalTitle;
this.modalInstanceClass = this.modalClass;
this.componentReference = null;
const backdropElement = this._element.nativeElement.querySelector('.modal-backdrop');
this._element.nativeElement.querySelector('.bd-modal').classList.add('d-none');
this._renderer.removeClass(document.body, 'overflow-hidden');
this._renderer.removeClass(document.body, 'pr-3');
if (backdropElement) {
// remove show
backdropElement.classList.remove('show');
// add d-none
backdropElement.classList.add('d-none');
}
return false;
}
}
RouterModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RouterModalComponent, deps: [{ token: i0.ElementRef }, { token: i1.ActivatedRoute }, { token: i1.Router }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
RouterModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: RouterModalComponent, selector: "router-modal", inputs: { modalTitle: "modalTitle", modalClass: "modalClass", okButtonText: "okButtonText", okButtonClass: "okButtonClass", cancelButtonText: "cancelButtonText", cancelButtonClass: "cancelButtonClass", yesButtonText: "yesButtonText", yesButtonClass: "yesButtonClass", noButtonText: "noButtonText", noButtonClass: "noButtonClass", abortButtonText: "abortButtonText", abortButtonClass: "abortButtonClass", retryButtonText: "retryButtonText", retryButtonClass: "retryButtonClass", ignoreButtonText: "ignoreButtonText", ignoreButtonClass: "ignoreButtonClass", previousButtonText: "previousButtonText", previousButtonClass: "previousButtonClass", nextButtonText: "nextButtonText", nextButtonClass: "nextButtonClass" }, ngImport: i0, template: `
<div class="bd-modal d-none">
<div class="modal-backdrop fade d-none"></div>
<div class="modal" tabindex="-1" role="dialog" [ngClass]="{ 'modal-waiting': waiting }">
<div class="modal-dialog" [ngClass]="modalInstanceClass" role="document">
<div class="modal-content">
<div class="modal-header" *ngIf="modalInstanceTitle">
<h5 class="modal-title">{{modalInstanceTitle | translate}}</h5>
<button *ngIf="instanceButtons.cancel" [disabled]="waiting || instanceButtons.cancel.buttonDisabled" (click)="cancel()"
type="button" class="close" data-dismiss="modal" aria-label="Cancel">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<router-outlet (activate)="onActivate($event)" (deactivate)="onDeactivate($event)" name="modal"></router-outlet>
</div>
<div class="modal-footer justify-content-end">
<button *ngIf="instanceButtons.previous" [disabled]="waiting || instanceButtons.previous.buttonDisabled" (click)="previous()"
type="button" [ngClass]="instanceButtons.previous.buttonClass">
{{instanceButtons.previous.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.ok" [disabled]="waiting || instanceButtons.ok.buttonDisabled" (click)="ok()"
type="button" [ngClass]="instanceButtons.ok.buttonClass">
{{instanceButtons.ok.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.yes" [disabled]="waiting || instanceButtons.yes.buttonDisabled"
(click)="yes()" type="button" [ngClass]="instanceButtons.yes.buttonClass">
{{instanceButtons.yes.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.no" [disabled]="waiting || instanceButtons.no.buttonDisabled"
(click)="no()" type="button" [ngClass]="instanceButtons.no.buttonClass">
{{instanceButtons.no.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.next" [disabled]="waiting || instanceButtons.next.buttonDisabled" (click)="next()"
type="button" [ngClass]="instanceButtons.next.buttonClass">
{{instanceButtons.next.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.cancel" [disabled]="waiting || instanceButtons.cancel.buttonDisabled"
(click)="cancel()" type="button" [ngClass]="instanceButtons.cancel.buttonClass" data-dismiss="modal">
{{instanceButtons.cancel.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.abort" [disabled]="waiting || instanceButtons.abort.buttonDisabled"
(click)="abort()" type="button" [ngClass]="instanceButtons.abort.buttonClass">
{{instanceButtons.abort.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.retry" [disabled]="waiting || instanceButtons.retry.buttonDisabled"
(click)="retry()" type="button" [ngClass]="instanceButtons.retry.buttonClass">
{{instanceButtons.retry.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.ignore" [disabled]="waiting || instanceButtons.ignore.buttonDisabled"
(click)="ignore()" type="button" [ngClass]="instanceButtons.ignore.buttonClass" data-dismiss="modal">
{{instanceButtons.ignore.buttonText | translate}}
</button>
</div>
</div>
</div>
</div>
</div>
`, isInline: true, styles: [".bd-modal .modal{position:fixed;right:auto;bottom:auto;z-index:1045;display:block}.bd-modal .modal .modal-body{margin-top:0;margin-bottom:0}.bd-modal .modal.modal-waiting{opacity:.6}\n"], dependencies: [{ kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RouterModalComponent, decorators: [{
type: Component,
args: [{ selector: 'router-modal', template: `
<div class="bd-modal d-none">
<div class="modal-backdrop fade d-none"></div>
<div class="modal" tabindex="-1" role="dialog" [ngClass]="{ 'modal-waiting': waiting }">
<div class="modal-dialog" [ngClass]="modalInstanceClass" role="document">
<div class="modal-content">
<div class="modal-header" *ngIf="modalInstanceTitle">
<h5 class="modal-title">{{modalInstanceTitle | translate}}</h5>
<button *ngIf="instanceButtons.cancel" [disabled]="waiting || instanceButtons.cancel.buttonDisabled" (click)="cancel()"
type="button" class="close" data-dismiss="modal" aria-label="Cancel">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<router-outlet (activate)="onActivate($event)" (deactivate)="onDeactivate($event)" name="modal"></router-outlet>
</div>
<div class="modal-footer justify-content-end">
<button *ngIf="instanceButtons.previous" [disabled]="waiting || instanceButtons.previous.buttonDisabled" (click)="previous()"
type="button" [ngClass]="instanceButtons.previous.buttonClass">
{{instanceButtons.previous.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.ok" [disabled]="waiting || instanceButtons.ok.buttonDisabled" (click)="ok()"
type="button" [ngClass]="instanceButtons.ok.buttonClass">
{{instanceButtons.ok.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.yes" [disabled]="waiting || instanceButtons.yes.buttonDisabled"
(click)="yes()" type="button" [ngClass]="instanceButtons.yes.buttonClass">
{{instanceButtons.yes.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.no" [disabled]="waiting || instanceButtons.no.buttonDisabled"
(click)="no()" type="button" [ngClass]="instanceButtons.no.buttonClass">
{{instanceButtons.no.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.next" [disabled]="waiting || instanceButtons.next.buttonDisabled" (click)="next()"
type="button" [ngClass]="instanceButtons.next.buttonClass">
{{instanceButtons.next.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.cancel" [disabled]="waiting || instanceButtons.cancel.buttonDisabled"
(click)="cancel()" type="button" [ngClass]="instanceButtons.cancel.buttonClass" data-dismiss="modal">
{{instanceButtons.cancel.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.abort" [disabled]="waiting || instanceButtons.abort.buttonDisabled"
(click)="abort()" type="button" [ngClass]="instanceButtons.abort.buttonClass">
{{instanceButtons.abort.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.retry" [disabled]="waiting || instanceButtons.retry.buttonDisabled"
(click)="retry()" type="button" [ngClass]="instanceButtons.retry.buttonClass">
{{instanceButtons.retry.buttonText | translate}}
</button>
<button *ngIf="instanceButtons.ignore" [disabled]="waiting || instanceButtons.ignore.buttonDisabled"
(click)="ignore()" type="button" [ngClass]="instanceButtons.ignore.buttonClass" data-dismiss="modal">
{{instanceButtons.ignore.buttonText | translate}}
</button>
</div>
</div>
</div>
</div>
</div>
`, encapsulation: ViewEncapsulation.None, styles: [".bd-modal .modal{position:fixed;right:auto;bottom:auto;z-index:1045;display:block}.bd-modal .modal .modal-body{margin-top:0;margin-bottom:0}.bd-modal .modal.modal-waiting{opacity:.6}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.ActivatedRoute }, { type: i1.Router }, { type: i0.Renderer2 }]; }, propDecorators: { modalTitle: [{
type: Input
}], modalClass: [{
type: Input
}], okButtonText: [{
type: Input
}], okButtonClass: [{
type: Input
}], cancelButtonText: [{
type: Input
}], cancelButtonClass: [{
type: Input
}], yesButtonText: [{
type: Input
}], yesButtonClass: [{
type: Input
}], noButtonText: [{
type: Input
}], noButtonClass: [{
type: Input
}], abortButtonText: [{
type: Input
}], abortButtonClass: [{
type: Input
}], retryButtonText: [{
type: Input
}], retryButtonClass: [{
type: Input
}], ignoreButtonText: [{
type: Input
}], ignoreButtonClass: [{
type: Input
}], previousButtonText: [{
type: Input
}], previousButtonClass: [{
type: Input
}], nextButtonText: [{
type: Input
}], nextButtonClass: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUm91dGVyTW9kYWxDb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9yb3V0aW5nL3NyYy9Sb3V0ZXJNb2RhbENvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsU0FBUyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsaUJBQWlCLEVBQWdCLFNBQVMsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN2RyxPQUFPLEVBQUMsY0FBYyxFQUFFLE1BQU0sRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRXZELE9BQU8sRUFBRSxXQUFXLEVBQWMsTUFBTSxlQUFlLENBQUM7Ozs7O0FBeUZ4RCxNQUFNLE9BQU8sb0JBQW9CO0lBaUUvQixZQUFvQixRQUFvQixFQUN0QixlQUErQixFQUMvQixPQUFlLEVBQ2YsU0FBb0I7UUFIbEIsYUFBUSxHQUFSLFFBQVEsQ0FBWTtRQUN0QixvQkFBZSxHQUFmLGVBQWUsQ0FBZ0I7UUFDL0IsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUNmLGNBQVMsR0FBVCxTQUFTLENBQVc7UUFqRTlCLDBCQUFxQixHQUF3QixJQUFJLENBQUM7UUFDbEQsMkJBQXNCLEdBQXdCLElBQUksQ0FBQztRQUNwRCxZQUFPLEdBQUcsS0FBSyxDQUFDO1FBQ2QsZUFBVSxHQUFHLEVBQUUsQ0FBQztRQUd6Qix3R0FBd0c7UUFFL0YsaUJBQVksR0FBRyxXQUFXLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQztRQUN6QyxrQkFBYSxHQUFHLFdBQVcsQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDO1FBRTNDLHFCQUFnQixHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDO1FBQ2pELHNCQUFpQixHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDO1FBRW5ELGtCQUFhLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUU7UUFDNUMsbUJBQWMsR0FBRyxXQUFXLENBQUMsR0FBRyxD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YixlQUFlLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUN6QztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQzs7a0hBMVdVLG9CQUFvQjtzR0FBcEIsb0JBQW9CLDh2QkE3RXJCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMERUOzRGQW1CVSxvQkFBb0I7a0JBaEZoQyxTQUFTOytCQUVFLGNBQWMsWUFDZDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBEVCxpQkFpQmMsaUJBQWlCLENBQUMsSUFBSTsyS0FRNUIsVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUlHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFFRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBQ0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUVHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBRUcsZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBRUcsZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBRUcsZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFFRyxrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBQ0csbUJBQW1CO3NCQUEzQixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29tcG9uZW50LCBJbnB1dCwgRWxlbWVudFJlZiwgVmlld0VuY2Fwc3VsYXRpb24sIEV2ZW50RW1pdHRlciwgUmVuZGVyZXIyfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7QWN0aXZhdGVkUm91dGUsIFJvdXRlcn0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7U3Vic2NyaXB0aW9ufSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEJ1dHRvblR5cGVzLCBCdXR0b25UeXBlIH0gZnJvbSAnLi9CdXR0b25UeXBlcyc7XG5pbXBvcnQgeyBNb2RhbENoYW5nZXMgfSBmcm9tICcuL1JvdXRlck1vZGFsJztcblxuZXhwb3J0IGRlY2xhcmUgaW50ZXJmYWNlIFJvdXRlck1vZGFsT3V0bGV0Q29tcG9uZW50IHtcbiAgbW9kYWxUaXRsZTogc3RyaW5nO1xuICBtb2RhbENsYXNzOiBzdHJpbmc7XG4gIHN0YXR1c0NoYW5nZXM6IEV2ZW50RW1pdHRlcjxhbnk+O1xufVxuXG5AQ29tcG9uZW50KHtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxuICBzZWxlY3RvcjogJ3JvdXRlci1tb2RhbCcsXG4gIHRlbXBsYXRlOiBgXG4gIDxkaXYgY2xhc3M9XCJiZC1tb2RhbCBkLW5vbmVcIj5cbiAgICA8ZGl2IGNsYXNzPVwibW9kYWwtYmFja2Ryb3AgZmFkZSBkLW5vbmVcIj48L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibW9kYWxcIiB0YWJpbmRleD1cIi0xXCIgcm9sZT1cImRpYWxvZ1wiIFtuZ0NsYXNzXT1cInsgJ21vZGFsLXdhaXRpbmcnOiB3YWl0aW5nIH1cIj5cbiAgICA8ZGl2IGNsYXNzPVwibW9kYWwtZGlhbG9nXCIgW25nQ2xhc3NdPVwibW9kYWxJbnN0YW5jZUNsYXNzXCIgcm9sZT1cImRvY3VtZW50XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwibW9kYWwtY29udGVudFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibW9kYWwtaGVhZGVyXCIgKm5nSWY9XCJtb2RhbEluc3RhbmNlVGl0bGVcIj5cbiAgICAgICAgICA8aDUgY2xhc3M9XCJtb2RhbC10aXRsZVwiPnt7bW9kYWxJbnN0YW5jZVRpdGxlIHwgdHJhbnNsYXRlfX08L2g1PlxuICAgICAgICAgIDxidXR0b24gKm5nSWY9XCJpbnN0YW5jZUJ1dHRvbnMuY2FuY2VsXCIgW2Rpc2FibGVkXT1cIndhaXRpbmcgfHwgaW5zdGFuY2VCdXR0b25zLmNhbmNlbC5idXR0b25EaXNhYmxlZFwiIChjbGljayk9XCJjYW5jZWwoKVwiXG4gICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJjbG9zZVwiIGRhdGEtZGlzbWlzcz1cIm1vZGFsXCIgYXJpYS1sYWJlbD1cIkNhbmNlbFwiPlxuICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+JnRpbWVzOzwvc3Bhbj5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1ib2R5XCI+XG4gICAgICAgICAgPHJvdXRlci1vdXRsZXQgKGFjdGl2YXRlKT1cIm9uQWN0aXZhdGUoJGV2ZW50KVwiIChkZWFjdGl2YXRlKT1cIm9uRGVhY3RpdmF0ZSgkZXZlbnQpXCIgbmFtZT1cIm1vZGFsXCI+PC9yb3V0ZXItb3V0bGV0PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1vZGFsLWZvb3RlciBqdXN0aWZ5LWNvbnRlbnQtZW5kXCI+XG4gICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImluc3RhbmNlQnV0dG9ucy5wcmV2aW91c1wiIFtkaXNhYmxlZF09XCJ3YWl0aW5nIHx8IGluc3RhbmNlQnV0dG9ucy5wcmV2aW91cy5idXR0b25EaXNhYmxlZFwiIChjbGljayk9XCJwcmV2aW91cygpXCJcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIiBbbmdDbGFzc109XCJpbnN0YW5jZUJ1dHRvbnMucHJldmlvdXMuYnV0dG9uQ2xhc3NcIj5cbiAgICAgICAgICAgIHt7aW5zdGFuY2VCdXR0b25zLnByZXZpb3VzLmJ1dHRvblRleHQgfCB0cmFuc2xhdGV9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gKm5nSWY9XCJpbnN0YW5jZUJ1dHRvbnMub2tcIiBbZGlzYWJsZWRdPVwid2FpdGluZyB8fCBpbnN0YW5jZUJ1dHRvbnMub2suYnV0dG9uRGlzYWJsZWRcIiAoY2xpY2spPVwib2soKVwiXG4gICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCIgW25nQ2xhc3NdPVwiaW5zdGFuY2VCdXR0b25zLm9rLmJ1dHRvbkNsYXNzXCI+XG4gICAgICAgICAgICB7e2luc3RhbmNlQnV0dG9ucy5vay5idXR0b25UZXh0IHwgdHJhbnNsYXRlfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uICpuZ0lmPVwiaW5zdGFuY2VCdXR0b25zLnllc1wiIFtkaXNhYmxlZF09XCJ3YWl0aW5nIHx8IGluc3RhbmNlQnV0dG9ucy55ZXMuYnV0dG9uRGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInllcygpXCIgdHlwZT1cImJ1dHRvblwiIFtuZ0NsYXNzXT1cImluc3RhbmNlQnV0dG9ucy55ZXMuYnV0dG9uQ2xhc3NcIj5cbiAgICAgICAgICAgIHt7aW5zdGFuY2VCdXR0b25zLnllcy5idXR0b25UZXh0IHwgdHJhbnNsYXRlfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uICpuZ0lmPVwiaW5zdGFuY2VCdXR0b25zLm5vXCIgW2Rpc2FibGVkXT1cIndhaXRpbmcgfHwgaW5zdGFuY2VCdXR0b25zLm5vLmJ1dHRvbkRpc2FibGVkXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJubygpXCIgdHlwZT1cImJ1dHRvblwiIFtuZ0NsYXNzXT1cImluc3RhbmNlQnV0dG9ucy5uby5idXR0b25DbGFzc1wiPlxuICAgICAgICAgICAge3tpbnN0YW5jZUJ1dHRvbnMubm8uYnV0dG9uVGV4dCB8IHRyYW5zbGF0ZX19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImluc3RhbmNlQnV0dG9ucy5uZXh0XCIgW2Rpc2FibGVkXT1cIndhaXRpbmcgfHwgaW5zdGFuY2VCdXR0b25zLm5leHQuYnV0dG9uRGlzYWJsZWRcIiAoY2xpY2spPVwibmV4dCgpXCJcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIiBbbmdDbGFzc109XCJpbnN0YW5jZUJ1dHRvbnMubmV4dC5idXR0b25DbGFzc1wiPlxuICAgICAgICAgICAge3tpbnN0YW5jZUJ1dHRvbnMubmV4dC5idXR0b25UZXh0IHwgdHJhbnNsYXRlfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uICpuZ0lmPVwiaW5zdGFuY2VCdXR0b25zLmNhbmNlbFwiIFtkaXNhYmxlZF09XCJ3YWl0aW5nIHx8IGluc3RhbmNlQnV0dG9ucy5jYW5jZWwuYnV0dG9uRGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImNhbmNlbCgpXCIgdHlwZT1cImJ1dHRvblwiIFtuZ0NsYXNzXT1cImluc3RhbmNlQnV0dG9ucy5jYW5jZWwuYnV0dG9uQ2xhc3NcIiBkYXRhLWRpc21pc3M9XCJtb2RhbFwiPlxuICAgICAgICAgICAge3tpbnN0YW5jZUJ1dHRvbnMuY2FuY2VsLmJ1dHRvblRleHQgfCB0cmFuc2xhdGV9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gKm5nSWY9XCJpbnN0YW5jZUJ1dHRvbnMuYWJvcnRcIiBbZGlzYWJsZWRdPVwid2FpdGluZyB8fCBpbnN0YW5jZUJ1dHRvbnMuYWJvcnQuYnV0dG9uRGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImFib3J0KClcIiB0eXBlPVwiYnV0dG9uXCIgW25nQ2xhc3NdPVwiaW5zdGFuY2VCdXR0b25zLmFib3J0LmJ1dHRvbkNsYXNzXCI+XG4gICAgICAgICAgICB7e2luc3RhbmNlQnV0dG9ucy5hYm9ydC5idXR0b25UZXh0IHwgdHJhbnNsYXRlfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uICpuZ0lmPVwiaW5zdGFuY2VCdXR0b25zLnJldHJ5XCIgW2Rpc2FibGVkXT1cIndhaXRpbmcgfHwgaW5zdGFuY2VCdXR0b25zLnJldHJ5LmJ1dHRvbkRpc2FibGVkXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJyZXRyeSgpXCIgdHlwZT1cImJ1dHRvblwiIFtuZ0NsYXNzXT1cImluc3RhbmNlQnV0dG9ucy5yZXRyeS5idXR0b25DbGFzc1wiPlxuICAgICAgICAgICAge3tpbnN0YW5jZUJ1dHRvbnMucmV0cnkuYnV0dG9uVGV4dCB8IHRyYW5zbGF0ZX19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImluc3RhbmNlQnV0dG9ucy5pZ25vcmVcIiBbZGlzYWJsZWRdPVwid2FpdGluZyB8fCBpbnN0YW5jZUJ1dHRvbnMuaWdub3JlLmJ1dHRvbkRpc2FibGVkXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJpZ25vcmUoKVwiIHR5cGU9XCJidXR0b25cIiBbbmdDbGFzc109XCJpbnN0YW5jZUJ1dHRvbnMuaWdub3JlLmJ1dHRvbkNsYXNzXCIgZGF0YS1kaXNtaXNzPVwibW9kYWxcIj5cbiAgICAgICAgICAgIHt7aW5zdGFuY2VCdXR0b25zLmlnbm9yZS5idXR0b25UZXh0IHwgdHJhbnNsYXRlfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDwvZGl2PlxuICBgLFxuICBzdHlsZXM6IFtgXG4gICAgLmJkLW1vZGFsIC5tb2RhbCB7XG4gICAgICAgIHBvc2l0aW9uOiBmaXhlZDtcbiAgICAgICAgcmlnaHQ6IGF1dG87XG4gICAgICAgIGJvdHRvbTogYXV0bztcbiAgICAgICAgei1pbmRleDogMTA0NTtcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgICAgIH1cbiAgICAgICAgLmJkLW1vZGFsIC5tb2RhbCAubW9kYWwtYm9keSB7XG4gICAgICAgICAgICAgICAgbWFyZ2luLXRvcDogMDtcbiAgICAgICAgICAgICAgICBtYXJnaW4tYm90dG9tOiAwO1xuICAgICAgICAgIH1cbiAgICAgICAgLmJkLW1vZGFsIC5tb2RhbC5tb2RhbC13YWl0aW5nIHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDAuNjtcbiAgICAgICAgICB9XG4gIGBdLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lXG59KVxuZXhwb3J0IGNsYXNzIFJvdXRlck1vZGFsQ29tcG9uZW50IHtcblxuICBwcml2YXRlIGNvbXBvbmVudFJlZmVyZW5jZTogYW55O1xuICBwcml2YXRlIGNvbXBvbmVudE1vZGFsQ2hhbmdlczogU3Vic2NyaXB0aW9uIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgY29tcG9uZW50QnV0dG9uQ2hhbmdlczogU3Vic2NyaXB0aW9uIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyB3YWl0aW5nID0gZmFsc2U7XG4gIEBJbnB1dCgpIG1vZGFsVGl0bGUgPSAnJztcbiAgQElucHV0KCkgbW9kYWxDbGFzczogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8vIHRoZXNlIHByb3BlcnRpZXMgYXJlIGhlcmUgYXMgaW5wdXRzIGluIG9yZGVyIHRvIGhhdmUgYSB3YXkgdG8gY3VzdG9taXplIHRleHQgYW5kIGNsYXNzIG9mIGVhY2ggYnV0dG9uXG5cbiAgQElucHV0KCkgb2tCdXR0b25UZXh0ID0gQnV0dG9uVHlwZXMub2suYnV0dG9uVGV4dDtcbiAgQElucHV0KCkgb2tCdXR0b25DbGFzcyA9IEJ1dHRvblR5cGVzLm9rLmJ1dHRvbkNsYXNzO1xuXG4gIEBJbnB1dCgpIGNhbmNlbEJ1dHRvblRleHQgPSBCdXR0b25UeXBlcy5jYW5jZWwuYnV0dG9uVGV4dDtcbiAgQElucHV0KCkgY2FuY2VsQnV0dG9uQ2xhc3MgPSBCdXR0b25UeXBlcy5jYW5jZWwuYnV0dG9uQ2xhc3M7XG5cbiAgQElucHV0KCkgeWVzQnV0dG9uVGV4dCA9IEJ1dHRvblR5cGVzLnllcy5idXR0b25UZXh0IDtcbiAgQElucHV0KCkgeWVzQnV0dG9uQ2xhc3MgPSBCdXR0b25UeXBlcy55ZXMuYnV0dG9uQ2xhc3M7XG5cbiAgQElucHV0KCkgbm9CdXR0b25UZXh0ID0gQnV0dG9uVHlwZXMubm8uYnV0dG9uVGV4dCA7XG4gIEBJbnB1dCgpIG5vQnV0dG9uQ2xhc3MgPSBCdXR0b25UeXBlcy5uby5idXR0b25DbGFzcztcblxuICBASW5wdXQoKSBhYm9ydEJ1dHRvblRleHQgPSBCdXR0b25UeXBlcy5hYm9ydC5idXR0b25UZXh0O1xuICBASW5wdXQoKSBhYm9ydEJ1dHRvbkNsYXNzID0gQnV0dG9uVHlwZXMuYWJvcnQuYnV0dG9uQ2xhc3M7XG5cbiAgQElucHV0KCkgcmV0cnlCdXR0b25UZXh0ID0gQnV0dG9uVHlwZXMucmV0cnkuYnV0dG9uVGV4dDtcbiAgQElucHV0KCkgcmV0cnlCdXR0b25DbGFzcyA9IEJ1dHRvblR5cGVzLnJldHJ5LmJ1dHRvbkNsYXNzO1xuXG4gIEBJbnB1dCgpIGlnbm9yZUJ1dHRvblRleHQgPSBCdXR0b25UeXBlcy5pZ25vcmUuYnV0dG9uVGV4dDtcbiAgQElucHV0KCkgaWdub3JlQnV0dG9uQ2xhc3MgPSBCdXR0b25UeXBlcy5pZ25vcmUuYnV0dG9uQ2xhc3M7XG5cbiAgQElucHV0KCkgcHJldmlvdXNCdXR0b25UZXh0ID0gQnV0dG9uVHlwZXMucHJldmlvdXMuYnV0dG9uVGV4dDtcbiAgQElucHV0KCkgcHJldmlvdXNCdXR0b25DbGFzcyA9IEJ1dHRvblR5cGVzLnByZXZpb3VzLmJ1dHRvbkNsYXNzO1xuXG4gIEBJbnB1dCgpIG5leHRCdXR0b25UZXh0ID0gQnV0dG9uVHlwZXMubmV4dC5idXR0b25UZXh0O1xuICBASW5wdXQoKSBuZXh0QnV0dG9uQ2xhc3MgPSBCdXR0b25UeXBlcy5uZXh0LmJ1dHRvbkNsYXNzO1xuXG4gIHB1YmxpYyBtb2RhbEluc3RhbmNlVGl0bGU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgcHVibGljIG1vZGFsSW5zdGFuY2VDbGFzczogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8vIGRlZmF1bHQgaW5zdGFuY2UgYnV0dG9uc1xuXG4gIHB1YmxpYyBpbnN0YW5jZUJ1dHRvbnM6IHtcbiAgICBvazogQnV0dG9uVHlwZSB8IG51bGwsXG4gICAgY2FuY2VsOiBCdXR0b25UeXBlIHwgbnVsbCxcbiAgICB5ZXM6IEJ1dHRvblR5cGUgfCBudWxsLFxuICAgIG5vOiBCdXR0b25UeXBlIHwgbnVsbCxcbiAgICBhYm9ydDogQnV0dG9uVHlwZSB8IG51bGwsXG4gICAgcmV0cnk6IEJ1dHRvblR5cGUgfCBudWxsLFxuICAgIGlnbm9yZTogQnV0dG9uVHlwZSB8IG51bGwsXG4gICAgcHJldmlvdXM6IEJ1dHRvblR5cGUgfCBudWxsLFxuICAgIG5leHQ6IEJ1dHRvblR5cGUgfCBudWxsXG4gIH0gPSB7XG4gICAgb2s6IG51bGwsXG4gICAgY2FuY2VsOiBudWxsLFxuICAgIHllczogbnVsbCxcbiAgICBubzogbnVsbCxcbiAgICBhYm9ydDogbnVsbCxcbiAgICByZXRyeTogbnVsbCxcbiAgICBpZ25vcmU6IG51bGwsXG4gICAgcHJldmlvdXM6IG51bGwsXG4gICAgbmV4dDogbnVsbFxuICB9O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX2VsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgICAgICAgICBwcml2YXRlIF9hY3RpdmF0ZWRSb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICAgICAgICAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlcixcbiAgICAgICAgICAgIHByaXZhdGUgX3JlbmRlcmVyOiBSZW5kZXJlcjIpIHtcblxuICB9XG5cbiAgYXN5bmMgY2FuY2VsKCkge1xuICAgIHRyeSB7XG4gICAgICBpZiAodGhpcy5jb21wb25lbnRSZWZlcmVuY2UpIHtcblxuICAgICAgICAvLyBzZXQgd2FpdGluZ1xuICAgICAgICB0aGlzLndhaXRpbmcgPSB0cnVlO1xuICAgICAgICAvLyBpZiBjb21wb25lbnQgaGFzIGNhbmNlbCgpIG1ldGhvZFxuICAgICAgICBpZiAodHlwZW9mIHRoaXMuY29tcG9uZW50UmVmZXJlbmNlLmNhbmNlbCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIC8vIGRvIGNhbmNlbFxuICAgICAgICAgIGF3YWl0IHRoaXMuY29tcG9uZW50UmVmZXJlbmNlLmNhbmNlbCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGF3YWl0IHRoaXMuX3JvdXRlci5uYXZpZ2F0ZShbJy4uLyddLCB7IHJlbGF0aXZlVG86IHRoaXMuX2FjdGl2YXRlZFJvdXRlIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIHVuc2V0IHdhaXRpbmdcbiAgICAgICAgdGhpcy53YWl0aW5nID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLndhaXRpbmcgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBvaygpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHRoaXMuY29tcG9uZW50UmVmZXJlbmNlKSB7XG4gICAgICAgIC8vIHNldCB3YWl0aW5nXG4gICAgICAgIHRoaXMud2FpdGluZyA9IHRydWU7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5jb21wb25lbnRSZWZlcmVuY2Uub2sgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAvLyBkbyBzdWJtaXRcbiAgICAgICAgICBhd2FpdCB0aGlzLmNvbXBvbmVudFJlZmVyZW5jZS5vaygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGF3YWl0IHRoaXMuX3JvdXRlci5uYXZpZ2F0ZShbJy4uLyddLCB7IHJlbGF0aXZlVG86IHRoaXMuX2FjdGl2YXRlZFJvdXRlIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIHVuc2V0IHdhaXRpbmdcbiAgICAgICAgdGhpcy53YWl0aW5nID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLndhaXRpbmcgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBhYm9ydCgpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHRoaXMuY29tcG9uZW50UmVmZXJlbmNlKSB7XG4gICAgICAgIC8vIHNldCB3YWl0aW5nXG4gICAgICAgIHRoaXMud2FpdGluZyA9IHRydWU7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5jb21wb25lbnRSZWZlcmVuY2UuYWJvcnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAvLyBkbyBzdWJtaXRcbiAgICAgICAgICBhd2FpdCB0aGlzLmNvbXBvbmVudFJlZmVyZW5jZS5hYm9ydCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGF3YWl0