@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
548 lines • 54.1 kB
JavaScript
var IgxDialogComponent_1;
import { __decorate, __metadata, __param } from "tslib";
import { useAnimation } from '@angular/animations';
import { CommonModule } from '@angular/common';
import { Component, ElementRef, EventEmitter, HostBinding, Input, NgModule, OnDestroy, OnInit, Optional, Output, ViewChild, AfterContentInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { IgxNavigationService, IToggleView } from '../core/navigation';
import { IgxButtonModule } from '../directives/button/button.directive';
import { IgxRippleModule } from '../directives/ripple/ripple.directive';
import { IgxDialogActionsDirective, IgxDialogTitleDirective } from './dialog.directives';
import { IgxToggleModule, IgxToggleDirective } from '../directives/toggle/toggle.directive';
import { GlobalPositionStrategy, NoOpScrollStrategy } from '../services';
import { slideInBottom, slideOutTop } from '../animations/slide/index';
import { IgxFocusModule } from '../directives/focus/focus.directive';
let DIALOG_ID = 0;
/**
* **Ignite UI for Angular Dialog Window** -
* [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/dialog.html)
*
* The Ignite UI Dialog Window presents a dialog window to the user which can simply display messages or display
* more complicated visuals such as a user sign-in form. It also provides a right and left button
* which can be used for custom actions.
*
* Example:
* ```html
* <button (click)="form.open()">Show Dialog</button>
* <igx-dialog #form title="Sign In" rightButtonLabel="OK">
* <div>
* <input type="text" igxInput/>
* <label igxLabel>Username</label>
* </div>
* <div>
* <input type="password" igxInput/>
* <label igxLabel>Password</label>
* </div>
* </igx-dialog>
* ```
*/
let IgxDialogComponent = IgxDialogComponent_1 = class IgxDialogComponent {
constructor(elementRef, navService) {
this.elementRef = elementRef;
this.navService = navService;
/**
* An @Input property that sets the value of the `id` attribute. If not provided it will be automatically generated.
*```html
*<igx-dialog [id]="'igx-dialog-56'" #alert title="Notification" leftButtonLabel="OK" (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.id = `igx-dialog-${DIALOG_ID++}`;
/**
* An @Input property controlling the `title` of the dialog.
*```html
*<igx-dialog title="Notification" #alert leftButtonLabel="OK" (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.title = '';
/**
* An @Input property controlling the `message` of the dialog.
*```html
*<igx-dialog message="Your email was sent!" #alert leftButtonLabel="OK" (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.message = '';
/**
* An @Input property to set the `label` of the left button of the dialog.
*```html
*<igx-dialog leftButtonLabel="OKAY" #alert title="Notification" (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.leftButtonLabel = '';
/**
* An @Input property to set the left button `type`. The types are `flat`, `raised` and `fab`.
* The `flat` type button is a rectangle and doesn't have a shadow. <br>
* The `raised` type button is also a rectangle but has a shadow. <br>
* The `fab` type button is a circle with a shadow. <br>
* The default value is `flat`.
*```html
*<igx-dialog leftButtonType="raised" leftButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.leftButtonType = 'flat';
/**
* An @Input property to set the left button color. The property accepts all valid CSS color property values.
*```html
*<igx-dialog leftButtonColor="yellow" leftButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.leftButtonColor = '';
/**
* An @Input property to set the left button `background-color`. The property accepts all valid CSS color property values.
*```html
*<igx-dialog leftButtonBackgroundColor="black" leftButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.leftButtonBackgroundColor = '';
/**
* An @Input property to set the left button `ripple`. The `ripple` animates a click/tap to a component as a series of fading waves.
* The property accepts all valid CSS color property values.
*```html
*<igx-dialog leftButtonRipple="green" leftButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.leftButtonRipple = '';
/**
* An @Input property to set the `label` of the right button of the dialog.
*```html
*<igx-dialog rightButtonLabel="OKAY" #alert title="Notification" (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.rightButtonLabel = '';
/**
* An @Input property to set the right button `type`. The types are `flat`, `raised` and `fab`.
* The `flat` type button is a rectangle and doesn't have a shadow. <br>
* The `raised` type button is also a rectangle but has a shadow. <br>
* The `fab` type button is a circle with a shadow. <br>
* The default value is `flat`.
*```html
*<igx-dialog rightButtonType="fab" rightButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.rightButtonType = 'flat';
/**
* An @Input property to set the right button `color`. The property accepts all valid CSS color property values.
*```html
*<igx-dialog rightButtonColor="yellow" rightButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.rightButtonColor = '';
/**
* An @Input property to set the right button `background-color`. The property accepts all valid CSS color property values.
*```html
*<igx-dialog rightButtonBackgroundColor="black" rightButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.rightButtonBackgroundColor = '';
/**
* An @Input property to set the right button `ripple`.
*```html
*<igx-dialog rightButtonRipple="green" rightButtonLabel="OKAY" #alert (onLeftButtonSelect)="alert.close()"></igx-dialog>
*```
*/
this.rightButtonRipple = '';
/**
* An event that is emitted when the dialog is opened.
*```html
*<igx-dialog (onOpen)="onDialogOpenHandler($event)" (onLeftButtonSelect)="dialog.close()" rightButtonLabel="OK">
*</igx-dialog>
*```
*/
this.onOpen = new EventEmitter();
/**
* An event that is emitted when the dialog is closed.
*```html
*<igx-dialog (onClose)="onDialogCloseHandler($event)" title="Confirmation" leftButtonLabel="Cancel" rightButtonLabel="OK">
*</igx-dialog>
*```
*/
this.onClose = new EventEmitter();
/**
* An event that is emitted when the left button is clicked.
*```html
*<igx-dialog (onLeftButtonSelect)="onDialogOKSelected($event)" #dialog leftButtonLabel="OK" rightButtonLabel="Cancel">
*</igx-dialog>
*```
*/
this.onLeftButtonSelect = new EventEmitter();
/**
* An event that is emitted when the right button is clicked.
* ```html
*<igx-dialog (onRightButtonSelect)="onDialogOKSelected($event)"
*#dialog title="Confirmation" (onLeftButtonSelect)="dialog.close()" rightButtonLabel="OK"
*rightButtonRipple="#4CAF50" closeOnOutsideSelect="true">
*</igx-dialog>
*```
*/
this.onRightButtonSelect = new EventEmitter();
this._positionSettings = {
openAnimation: useAnimation(slideInBottom, { params: { fromPosition: 'translateY(100%)' } }),
closeAnimation: useAnimation(slideOutTop, { params: { toPosition: 'translateY(-100%)' } })
};
this._closeOnOutsideSelect = false;
this._isModal = true;
this.destroy$ = new Subject();
/**
* The default `tabindex` attribute for the component
*
* @hidden
*/
this.tabindex = -1;
this._titleId = IgxDialogComponent_1.NEXT_ID++ + '_title';
this._overlayDefaultSettings = {
positionStrategy: new GlobalPositionStrategy(this._positionSettings),
scrollStrategy: new NoOpScrollStrategy(),
modal: this.isModal,
closeOnOutsideClick: this.closeOnOutsideSelect
};
}
get isModal() {
return this._isModal;
}
set isModal(val) {
this._overlayDefaultSettings.modal = val;
this._isModal = val;
}
/**
* An @Input property that allows you to enable the "close on click outside the dialog". By default it's disabled.
*```html
*<igx-dialog closeOnOutsideSelect="true" leftButtonLabel="Cancel" (onLeftButtonSelect)="dialog.close()"
*rightButtonLabel="OK" rightButtonRipple="#4CAF50" (onRightButtonSelect)="onDialogOKSelected($event)">
*</igx-dialog>
*```
*/
get closeOnOutsideSelect() {
return this._closeOnOutsideSelect;
}
set closeOnOutsideSelect(val) {
this._overlayDefaultSettings.closeOnOutsideClick = val;
this._closeOnOutsideSelect = val;
}
/**
* Get the position and animation settings used by the dialog.
* ```typescript
* @ViewChild('alert', { static: true }) public alert: IgxDialogComponent;
* let currentPosition: PositionSettings = this.alert.positionSettings
* ```
*/
get positionSettings() {
return this._positionSettings;
}
/**
* Set the position and animation settings used by the dialog.
* ```typescript
* import { slideInLeft, slideOutRight } from 'igniteui-angular';
* ...
* @ViewChild('alert', { static: true }) public alert: IgxDialogComponent;
* public newPositionSettings: PositionSettings = {
* openAnimation: useAnimation(slideInTop, { params: { duration: '2000ms' } }),
* closeAnimation: useAnimation(slideOutBottom, { params: { duration: '2000ms'} }),
* horizontalDirection: HorizontalAlignment.Left,
* verticalDirection: VerticalAlignment.Middle,
* horizontalStartPoint: HorizontalAlignment.Left,
* verticalStartPoint: VerticalAlignment.Middle,
* minSize: { height: 100, width: 100 }
* };
* this.alert.positionSettings = this.newPositionSettings;
* ```
*/
set positionSettings(settings) {
this._positionSettings = settings;
this._overlayDefaultSettings.positionStrategy = new GlobalPositionStrategy(this._positionSettings);
}
/**
* @hidden
*/
get element() {
return this.elementRef.nativeElement;
}
/**
* Returns the value of state. Possible state values are "open" or "close".
*```typescript
*@ViewChild("MyDialog")
*public dialog: IgxDialogComponent;
*ngAfterViewInit() {
* let dialogState = this.dialog.state;
*}
*```
*/
get state() {
return this.isOpen ? 'open' : 'close';
}
/**
* Returns whether the dialog is visible to the end user.
*```typescript
*@ViewChild("MyDialog")
*public dialog: IgxDialogComponent;
*ngAfterViewInit() {
* let dialogOpen = this.dialog.isOpen;
*}
* ```
*/
get isOpen() {
return !this.toggleRef.collapsed;
}
get isCollapsed() {
return this.toggleRef.collapsed;
}
/**
*Returns the value of the role of the dialog. The valid values are `dialog`, `alertdialog`, `alert`.
*```typescript
*@ViewChild("MyDialog")
*public dialog: IgxDialogComponent;
*ngAfterViewInit() {
* let dialogRole = this.dialog.role;
*}
* ```
*/
get role() {
if (this.leftButtonLabel !== '' && this.rightButtonLabel !== '') {
return 'dialog';
}
else if (this.leftButtonLabel !== '' ||
this.rightButtonLabel !== '') {
return 'alertdialog';
}
else {
return 'alert';
}
}
/**
*Returns the value of the title id.
*```typescript
*@ViewChild("MyDialog")
*public dialog: IgxDialogComponent;
*ngAfterViewInit() {
* let dialogTitle = this.dialog.titleId;
*}
* ```
*/
get titleId() {
return this._titleId;
}
ngAfterContentInit() {
this.toggleRef.onClosing.pipe(takeUntil(this.destroy$)).subscribe(() => this.emitCloseFromDialog());
}
emitCloseFromDialog() {
this.onClose.emit({ dialog: this, event: null });
}
/**
* A method that opens the dialog.
* @memberOf {@link IgxDialogComponent}
*```html
*<button (click)="dialog.open() igxButton="raised" igxButtonColor="white" igxRipple="white">Trigger Dialog</button>
*<igx-dialog #dialog></igx-dialog>
*```
*/
open(overlaySettings = this._overlayDefaultSettings) {
this.toggleRef.open(overlaySettings);
this.onOpen.emit({ dialog: this, event: null });
if (!this.leftButtonLabel && !this.rightButtonLabel) {
this.toggleRef.element.focus();
}
}
/**
*A method that that closes the dialog.
*@memberOf {@link IgxDialogComponent}
*```html
*<button (click)="dialog.close() igxButton="raised" igxButtonColor="white" igxRipple="white">Trigger Dialog</button>
*<igx-dialog #dialog></igx-dialog>
*```
*/
close() {
// `onClose` will emit from `toggleRef.onClosing` subscription
this.toggleRef.close();
}
/**
* A method that opens/closes the dialog.
*@memberOf {@link IgxDialogComponent}
*```html
*<button (click)="dialog.toggle() igxButton="raised" igxButtonColor="white" igxRipple="white">Trigger Dialog</button>
*<igx-dialog #dialog></igx-dialog>
*```
*/
toggle() {
this.isOpen ? this.close() : this.open();
}
/**
* @hidden
*/
onDialogSelected(event) {
event.stopPropagation();
if (this.isOpen &&
this.closeOnOutsideSelect &&
event.target.classList.contains(IgxDialogComponent_1.DIALOG_CLASS)) {
this.close();
}
}
/**
* @hidden
*/
onInternalLeftButtonSelect(event) {
this.onLeftButtonSelect.emit({ dialog: this, event });
}
/**
* @hidden
*/
onInternalRightButtonSelect(event) {
this.onRightButtonSelect.emit({ dialog: this, event });
}
/**
* @hidden
*/
ngOnInit() {
if (this.navService && this.id) {
this.navService.add(this.id, this);
}
}
/**
* @hidden
*/
ngOnDestroy() {
if (this.navService && this.id) {
this.navService.remove(this.id);
}
}
};
IgxDialogComponent.NEXT_ID = 1;
IgxDialogComponent.DIALOG_CLASS = 'igx-dialog';
IgxDialogComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: IgxNavigationService, decorators: [{ type: Optional }] }
];
__decorate([
ViewChild(IgxToggleDirective, { static: true }),
__metadata("design:type", IgxToggleDirective)
], IgxDialogComponent.prototype, "toggleRef", void 0);
__decorate([
HostBinding('attr.id'),
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "id", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean),
__metadata("design:paramtypes", [Boolean])
], IgxDialogComponent.prototype, "isModal", null);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "title", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "message", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "leftButtonLabel", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "leftButtonType", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "leftButtonColor", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "leftButtonBackgroundColor", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "leftButtonRipple", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "rightButtonLabel", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "rightButtonType", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "rightButtonColor", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "rightButtonBackgroundColor", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "rightButtonRipple", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean),
__metadata("design:paramtypes", [Boolean])
], IgxDialogComponent.prototype, "closeOnOutsideSelect", null);
__decorate([
Input(),
__metadata("design:type", Object),
__metadata("design:paramtypes", [Object])
], IgxDialogComponent.prototype, "positionSettings", null);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "onOpen", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "onClose", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "onLeftButtonSelect", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "onRightButtonSelect", void 0);
__decorate([
HostBinding('attr.tabindex'),
__metadata("design:type", Object)
], IgxDialogComponent.prototype, "tabindex", void 0);
__decorate([
Input(),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxDialogComponent.prototype, "isOpen", null);
__decorate([
HostBinding('class.igx-dialog--hidden'),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxDialogComponent.prototype, "isCollapsed", null);
__decorate([
Input(),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxDialogComponent.prototype, "role", null);
__decorate([
Input(),
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], IgxDialogComponent.prototype, "titleId", null);
IgxDialogComponent = IgxDialogComponent_1 = __decorate([
Component({
selector: 'igx-dialog',
template: "<div tabindex=\"0\" #dialog class=\"igx-dialog\" igxToggle (click)=\"onDialogSelected($event)\">\n <div #dialogWindow class=\"igx-dialog__window\" [attr.role]=\"role\" [attr.aria-labelledby]=\"titleId\">\n\n <div *ngIf=\"title\" [attr.id]=\"titleId\" class=\"igx-dialog__window-title\">\n {{ title }}\n </div>\n <ng-content *ngIf=\"!title\" select=\"igx-dialog-title,[igxDialogTitle]\"></ng-content>\n\n <div class=\"igx-dialog__window-content\" *ngIf=\"message\">{{ message }}</div>\n <ng-content *ngIf=\"!message\"></ng-content>\n\n <div *ngIf=\"leftButtonLabel || rightButtonLabel\" class=\"igx-dialog__window-actions\">\n <button *ngIf=\"leftButtonLabel\" type=\"button\" [igxFocus]=\"isOpen\" igxButton=\"{{ leftButtonType }}\" igxButtonColor=\"{{ leftButtonColor }}\" igxButtonBackground=\"{{ leftButtonBackgroundColor }}\"\n igxRipple=\"{{ leftButtonRipple }}\" (click)=\"onInternalLeftButtonSelect($event)\">\n {{ leftButtonLabel }}\n </button>\n <button *ngIf=\"rightButtonLabel\" type=\"button\" [igxFocus]=\"isOpen\" igxButton=\"{{ rightButtonType }}\" igxButtonColor=\"{{ rightButtonColor }}\" igxButtonBackground=\"{{ rightButtonBackgroundColor }}\"\n igxRipple=\"{{ rightButtonRipple }}\" (click)=\"onInternalRightButtonSelect($event)\">\n {{ rightButtonLabel }}\n </button>\n </div>\n <ng-content *ngIf=\"!leftButtonLabel && !rightButtonLabel\" select=\"igx-dialog-actions,[igxDialogActions]\"></ng-content>\n\n </div>\n</div>\n"
}),
__param(1, Optional()),
__metadata("design:paramtypes", [ElementRef,
IgxNavigationService])
], IgxDialogComponent);
export { IgxDialogComponent };
/**
* @hidden
*/
let IgxDialogModule = class IgxDialogModule {
};
IgxDialogModule = __decorate([
NgModule({
declarations: [IgxDialogComponent, IgxDialogTitleDirective, IgxDialogActionsDirective],
exports: [IgxDialogComponent, IgxDialogTitleDirective, IgxDialogActionsDirective],
imports: [CommonModule, IgxToggleModule, IgxButtonModule, IgxRippleModule, IgxFocusModule]
})
], IgxDialogModule);
export { IgxDialogModule };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlhbG9nLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2lnbml0ZXVpLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZGlhbG9nL2RpYWxvZy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFDSCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixXQUFXLEVBQ1gsS0FBSyxFQUNMLFFBQVEsRUFDUixTQUFTLEVBQ1QsTUFBTSxFQUNOLFFBQVEsRUFDUixNQUFNLEVBQ04sU0FBUyxFQUNULGdCQUFnQixFQUNuQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsV0FBVyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDdkUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUN4RSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN6RixPQUFPLEVBQUUsZUFBZSxFQUFFLGtCQUFrQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDNUYsT0FBTyxFQUFtQixzQkFBc0IsRUFBRSxrQkFBa0IsRUFBb0IsTUFBTSxhQUFhLENBQUM7QUFDNUcsT0FBTyxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN2RSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFHckUsSUFBSSxTQUFTLEdBQUcs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QUFhRDtJQURDLEtBQUssRUFBRTs7OzhDQVlQO0FBYUQ7SUFEQyxLQUFLLEVBQUU7OztpREFHUDtBQWhWUSxrQkFBa0I7SUFKOUIsU0FBUyxDQUFDO1FBQ1AsUUFBUSxFQUFFLFlBQVk7UUFDdEIsaW1EQUE0QztLQUMvQyxDQUFDO0lBcVZPLFdBQUEsUUFBUSxFQUFFLENBQUE7cUNBRFMsVUFBVTtRQUNFLG9CQUFvQjtHQXBWL0Msa0JBQWtCLENBZ2M5QjtTQWhjWSxrQkFBa0I7QUF1Yy9COztHQUVHO0FBTUgsSUFBYSxlQUFlLEdBQTVCLE1BQWEsZUFBZTtDQUFJLENBQUE7QUFBbkIsZUFBZTtJQUwzQixRQUFRLENBQUM7UUFDTixZQUFZLEVBQUUsQ0FBQyxrQkFBa0IsRUFBRSx1QkFBdUIsRUFBRSx5QkFBeUIsQ0FBQztRQUN0RixPQUFPLEVBQUUsQ0FBQyxrQkFBa0IsRUFBRSx1QkFBdUIsRUFBRSx5QkFBeUIsQ0FBQztRQUNqRixPQUFPLEVBQUUsQ0FBQyxZQUFZLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsY0FBYyxDQUFDO0tBQzdGLENBQUM7R0FDVyxlQUFlLENBQUk7U0FBbkIsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZUFuaW1hdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIEhvc3RCaW5kaW5nLFxuICAgIElucHV0LFxuICAgIE5nTW9kdWxlLFxuICAgIE9uRGVzdHJveSxcbiAgICBPbkluaXQsXG4gICAgT3B0aW9uYWwsXG4gICAgT3V0cHV0LFxuICAgIFZpZXdDaGlsZCxcbiAgICBBZnRlckNvbnRlbnRJbml0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgSWd4TmF2aWdhdGlvblNlcnZpY2UsIElUb2dnbGVWaWV3IH0gZnJvbSAnLi4vY29yZS9uYXZpZ2F0aW9uJztcbmltcG9ydCB7IElneEJ1dHRvbk1vZHVsZSB9IGZyb20gJy4uL2RpcmVjdGl2ZXMvYnV0dG9uL2J1dHRvbi5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSWd4UmlwcGxlTW9kdWxlIH0gZnJvbSAnLi4vZGlyZWN0aXZlcy9yaXBwbGUvcmlwcGxlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBJZ3hEaWFsb2dBY3Rpb25zRGlyZWN0aXZlLCBJZ3hEaWFsb2dUaXRsZURpcmVjdGl2ZSB9IGZyb20gJy4vZGlhbG9nLmRpcmVjdGl2ZXMnO1xuaW1wb3J0IHsgSWd4VG9nZ2xlTW9kdWxlLCBJZ3hUb2dnbGVEaXJlY3RpdmUgfSBmcm9tICcuLi9kaXJlY3RpdmVzL3RvZ2dsZS90b2dnbGUuZGlyZWN0aXZlJztcbmltcG9ydCB7IE92ZXJsYXlTZXR0aW5ncywgR2xvYmFsUG9zaXRpb25TdHJhdGVneSwgTm9PcFNjcm9sbFN0cmF0ZWd5LCBQb3NpdGlvblNldHRpbmdzIH0gZnJvbSAnLi4vc2VydmljZXMnO1xuaW1wb3J0IHsgc2xpZGVJbkJvdHRvbSwgc2xpZGVPdXRUb3AgfSBmcm9tICcuLi9hbmltYXRpb25zL3NsaWRlL2luZGV4JztcbmltcG9ydCB7IElneEZvY3VzTW9kdWxlIH0gZnJvbSAnLi4vZGlyZWN0aXZlcy9mb2N1cy9mb2N1cy5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSUJhc2VFdmVudEFyZ3MgfSBmcm9tICcuLi9jb3JlL3V0aWxzJztcblxubGV0IERJQUxPR19JRCA9IDA7XG4vKipcbiAqICoqSWduaXRlIFVJIGZvciBBbmd1bGFyIERpYWxvZyBXaW5kb3cqKiAtXG4gKiBbRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuaW5mcmFnaXN0aWNzLmNvbS9wcm9kdWN0cy9pZ25pdGUtdWktYW5ndWxhci9hbmd1bGFyL2NvbXBvbmVudHMvZGlhbG9nLmh0bWwpXG4gKlxuICogVGhlIElnbml0ZSBVSSBEaWFsb2cgV2luZG93IHByZXNlbnRzIGEgZGlhbG9nIHdpbmRvdyB0byB0aGUgdXNlciB3aGljaCBjYW4gc2ltcGx5IGRpc3BsYXkgbWVzc2FnZXMgb3IgZGlzcGxheVxuICogbW9yZSBjb21wbGljYXRlZCB2aXN1YWxzIHN1Y2ggYXMgYSB1c2VyIHNpZ24taW4gZm9ybS4gIEl0IGFsc28gcHJvdmlkZXMgYSByaWdodCBhbmQgbGVmdCBidXR0b25cbiAqIHdoaWNoIGNhbiBiZSB1c2VkIGZvciBjdXN0b20gYWN0aW9ucy5cbiAqXG4gKiBFeGFtcGxlOlxuICogYGBgaHRtbFxuICogPGJ1dHRvbiAoY2xpY2spPVwiZm9ybS5vcGVuKClcIj5TaG93IERpYWxvZzwvYnV0dG9uPlxuICogPGlneC1kaWFsb2cgI2Zvcm0gdGl0bGU9XCJTaWduIEluXCIgcmlnaHRCdXR0b25MYWJlbD1cIk9LXCI+XG4gKiAgIDxkaXY+XG4gKiAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgaWd4SW5wdXQvPlxuICogICAgIDxsYWJlbCBpZ3hMYWJlbD5Vc2VybmFtZTwvbGFiZWw+XG4gKiAgIDwvZGl2PlxuICogICA8ZGl2PlxuICogICAgIDxpbnB1dCB0eXBlPVwicGFzc3dvcmRcIiBpZ3hJbnB1dC8+XG4gKiAgICAgPGxhYmVsIGlneExhYmVsPlBhc3N3b3JkPC9sYWJlbD5cbiAqICAgPC9kaXY+XG4gKiA8L2lneC1kaWFsb2c+XG4gKiBgYGBcbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdpZ3gtZGlhbG9nJyxcbiAgICB0ZW1wbGF0ZVVybDogJ2RpYWxvZy1jb250ZW50LmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBJZ3hEaWFsb2dDb21wb25lbnQgaW1wbGVtZW50cyBJVG9nZ2xlVmlldywgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyQ29udGVudEluaXQge1xuICAgIHByaXZhdGUgc3RhdGljIE5FWFRfSUQgPSAxO1xuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IERJQUxPR19DTEFTUyA9ICdpZ3gtZGlhbG9nJztcblxuICAgIEBWaWV3Q2hpbGQoSWd4VG9nZ2xlRGlyZWN0aXZlLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHB1YmxpYyB0b2dnbGVSZWY6IElneFRvZ2dsZURpcmVjdGl2ZTtcblxuICAgIC8qKlxuICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgc2V0cyB0aGUgdmFsdWUgb2YgdGhlIGBpZGAgYXR0cmlidXRlLiBJZiBub3QgcHJvdmlkZWQgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZC5cbiAgICAqYGBgaHRtbFxuICAgICo8aWd4LWRpYWxvZyBbaWRdPVwiJ2lneC1kaWFsb2ctNTYnXCIgI2FsZXJ0IHRpdGxlPVwiTm90aWZpY2F0aW9uXCIgbGVmdEJ1dHRvbkxhYmVsPVwiT0tcIiAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgKmBgYFxuICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLmlkJylcbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZCA9IGBpZ3gtZGlhbG9nLSR7RElBTE9HX0lEKyt9YDtcblxuICAgIEBJbnB1dCgpXG4gICAgZ2V0IGlzTW9kYWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc01vZGFsO1xuICAgIH1cblxuICAgIHNldCBpc01vZGFsKHZhbDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9vdmVybGF5RGVmYXVsdFNldHRpbmdzLm1vZGFsID0gdmFsO1xuICAgICAgICB0aGlzLl9pc01vZGFsID0gdmFsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICogQW4gQElucHV0IHByb3BlcnR5IGNvbnRyb2xsaW5nIHRoZSBgdGl0bGVgIG9mIHRoZSBkaWFsb2cuXG4gICAgKmBgYGh0bWxcbiAgICAqPGlneC1kaWFsb2cgdGl0bGU9XCJOb3RpZmljYXRpb25cIiAjYWxlcnQgbGVmdEJ1dHRvbkxhYmVsPVwiT0tcIiAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgKmBgYFxuICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgdGl0bGUgPSAnJztcblxuICAgIC8qKlxuICAgICAqICBBbiBASW5wdXQgcHJvcGVydHkgY29udHJvbGxpbmcgdGhlIGBtZXNzYWdlYCBvZiB0aGUgZGlhbG9nLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgbWVzc2FnZT1cIllvdXIgZW1haWwgd2FzIHNlbnQhXCIgI2FsZXJ0IGxlZnRCdXR0b25MYWJlbD1cIk9LXCIgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJhbGVydC5jbG9zZSgpXCI+PC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbWVzc2FnZSA9ICcnO1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRvIHNldCB0aGUgYGxhYmVsYCBvZiB0aGUgbGVmdCBidXR0b24gb2YgdGhlIGRpYWxvZy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIGxlZnRCdXR0b25MYWJlbD1cIk9LQVlcIiAjYWxlcnQgdGl0bGU9XCJOb3RpZmljYXRpb25cIiAgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJhbGVydC5jbG9zZSgpXCI+PC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbGVmdEJ1dHRvbkxhYmVsID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSBsZWZ0IGJ1dHRvbiBgdHlwZWAuIFRoZSB0eXBlcyBhcmUgYGZsYXRgLCBgcmFpc2VkYCBhbmQgYGZhYmAuXG4gICAgICogVGhlIGBmbGF0YCB0eXBlIGJ1dHRvbiBpcyBhIHJlY3RhbmdsZSBhbmQgZG9lc24ndCBoYXZlIGEgc2hhZG93LiA8YnI+XG4gICAgICogVGhlIGByYWlzZWRgIHR5cGUgYnV0dG9uIGlzIGFsc28gYSByZWN0YW5nbGUgYnV0IGhhcyBhIHNoYWRvdy4gPGJyPlxuICAgICAqIFRoZSBgZmFiYCB0eXBlIGJ1dHRvbiBpcyBhIGNpcmNsZSB3aXRoIGEgc2hhZG93LiA8YnI+XG4gICAgICogVGhlIGRlZmF1bHQgdmFsdWUgaXMgYGZsYXRgLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgbGVmdEJ1dHRvblR5cGU9XCJyYWlzZWRcIiBsZWZ0QnV0dG9uTGFiZWw9XCJPS0FZXCIgI2FsZXJ0IChvbkxlZnRCdXR0b25TZWxlY3QpPVwiYWxlcnQuY2xvc2UoKVwiPjwvaWd4LWRpYWxvZz5cbiAgICAgKmBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGxlZnRCdXR0b25UeXBlID0gJ2ZsYXQnO1xuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0byBzZXQgdGhlIGxlZnQgYnV0dG9uIGNvbG9yLiBUaGUgcHJvcGVydHkgYWNjZXB0cyBhbGwgdmFsaWQgQ1NTIGNvbG9yIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIGxlZnRCdXR0b25Db2xvcj1cInllbGxvd1wiIGxlZnRCdXR0b25MYWJlbD1cIk9LQVlcIiAjYWxlcnQgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJhbGVydC5jbG9zZSgpXCI+PC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbGVmdEJ1dHRvbkNvbG9yID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSBsZWZ0IGJ1dHRvbiBgYmFja2dyb3VuZC1jb2xvcmAuIFRoZSBwcm9wZXJ0eSBhY2NlcHRzIGFsbCB2YWxpZCBDU1MgY29sb3IgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgbGVmdEJ1dHRvbkJhY2tncm91bmRDb2xvcj1cImJsYWNrXCIgbGVmdEJ1dHRvbkxhYmVsPVwiT0tBWVwiICNhbGVydCAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBsZWZ0QnV0dG9uQmFja2dyb3VuZENvbG9yID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSBsZWZ0IGJ1dHRvbiBgcmlwcGxlYC4gVGhlIGByaXBwbGVgIGFuaW1hdGVzIGEgY2xpY2svdGFwIHRvIGEgY29tcG9uZW50IGFzIGEgc2VyaWVzIG9mIGZhZGluZyB3YXZlcy5cbiAgICAgKiBUaGUgcHJvcGVydHkgYWNjZXB0cyBhbGwgdmFsaWQgQ1NTIGNvbG9yIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIGxlZnRCdXR0b25SaXBwbGU9XCJncmVlblwiIGxlZnRCdXR0b25MYWJlbD1cIk9LQVlcIiAjYWxlcnQgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJhbGVydC5jbG9zZSgpXCI+PC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbGVmdEJ1dHRvblJpcHBsZSA9ICcnO1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRvIHNldCB0aGUgYGxhYmVsYCBvZiB0aGUgcmlnaHQgYnV0dG9uIG9mIHRoZSBkaWFsb2cuXG4gICAgICpgYGBodG1sXG4gICAgICo8aWd4LWRpYWxvZyByaWdodEJ1dHRvbkxhYmVsPVwiT0tBWVwiICNhbGVydCB0aXRsZT1cIk5vdGlmaWNhdGlvblwiICAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyByaWdodEJ1dHRvbkxhYmVsID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSByaWdodCBidXR0b24gYHR5cGVgLiBUaGUgdHlwZXMgYXJlIGBmbGF0YCwgYHJhaXNlZGAgYW5kIGBmYWJgLlxuICAgICAqIFRoZSBgZmxhdGAgdHlwZSBidXR0b24gaXMgYSByZWN0YW5nbGUgYW5kIGRvZXNuJ3QgaGF2ZSBhIHNoYWRvdy4gPGJyPlxuICAgICAqIFRoZSBgcmFpc2VkYCB0eXBlIGJ1dHRvbiBpcyBhbHNvIGEgcmVjdGFuZ2xlIGJ1dCBoYXMgYSBzaGFkb3cuIDxicj5cbiAgICAgKiBUaGUgYGZhYmAgdHlwZSBidXR0b24gaXMgYSBjaXJjbGUgd2l0aCBhIHNoYWRvdy4gPGJyPlxuICAgICAqIFRoZSBkZWZhdWx0IHZhbHVlIGlzIGBmbGF0YC5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIHJpZ2h0QnV0dG9uVHlwZT1cImZhYlwiIHJpZ2h0QnV0dG9uTGFiZWw9XCJPS0FZXCIgI2FsZXJ0IChvbkxlZnRCdXR0b25TZWxlY3QpPVwiYWxlcnQuY2xvc2UoKVwiPjwvaWd4LWRpYWxvZz5cbiAgICAgKmBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHJpZ2h0QnV0dG9uVHlwZSA9ICdmbGF0JztcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0byBzZXQgdGhlIHJpZ2h0IGJ1dHRvbiBgY29sb3JgLiBUaGUgcHJvcGVydHkgYWNjZXB0cyBhbGwgdmFsaWQgQ1NTIGNvbG9yIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIHJpZ2h0QnV0dG9uQ29sb3I9XCJ5ZWxsb3dcIiByaWdodEJ1dHRvbkxhYmVsPVwiT0tBWVwiICNhbGVydCAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyByaWdodEJ1dHRvbkNvbG9yID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdG8gc2V0IHRoZSByaWdodCBidXR0b24gYGJhY2tncm91bmQtY29sb3JgLiBUaGUgcHJvcGVydHkgYWNjZXB0cyBhbGwgdmFsaWQgQ1NTIGNvbG9yIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIHJpZ2h0QnV0dG9uQmFja2dyb3VuZENvbG9yPVwiYmxhY2tcIiByaWdodEJ1dHRvbkxhYmVsPVwiT0tBWVwiICNhbGVydCAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImFsZXJ0LmNsb3NlKClcIj48L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyByaWdodEJ1dHRvbkJhY2tncm91bmRDb2xvciA9ICcnO1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRvIHNldCB0aGUgcmlnaHQgYnV0dG9uIGByaXBwbGVgLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgcmlnaHRCdXR0b25SaXBwbGU9XCJncmVlblwiIHJpZ2h0QnV0dG9uTGFiZWw9XCJPS0FZXCIgI2FsZXJ0IChvbkxlZnRCdXR0b25TZWxlY3QpPVwiYWxlcnQuY2xvc2UoKVwiPjwvaWd4LWRpYWxvZz5cbiAgICAgKmBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHJpZ2h0QnV0dG9uUmlwcGxlID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBhbGxvd3MgeW91IHRvIGVuYWJsZSB0aGUgXCJjbG9zZSBvbiBjbGljayBvdXRzaWRlIHRoZSBkaWFsb2dcIi4gQnkgZGVmYXVsdCBpdCdzIGRpc2FibGVkLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgY2xvc2VPbk91dHNpZGVTZWxlY3Q9XCJ0cnVlXCIgbGVmdEJ1dHRvbkxhYmVsPVwiQ2FuY2VsXCIgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJkaWFsb2cuY2xvc2UoKVwiXG4gICAgICpyaWdodEJ1dHRvbkxhYmVsPVwiT0tcIiByaWdodEJ1dHRvblJpcHBsZT1cIiM0Q0FGNTBcIiAob25SaWdodEJ1dHRvblNlbGVjdCk9XCJvbkRpYWxvZ09LU2VsZWN0ZWQoJGV2ZW50KVwiPlxuICAgICAqPC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBnZXQgY2xvc2VPbk91dHNpZGVTZWxlY3QoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jbG9zZU9uT3V0c2lkZVNlbGVjdDtcbiAgICB9XG5cbiAgICBzZXQgY2xvc2VPbk91dHNpZGVTZWxlY3QodmFsOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuX292ZXJsYXlEZWZhdWx0U2V0dGluZ3MuY2xvc2VPbk91dHNpZGVDbGljayA9IHZhbDtcbiAgICAgICAgdGhpcy5fY2xvc2VPbk91dHNpZGVTZWxlY3QgPSB2YWw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBwb3NpdGlvbiBhbmQgYW5pbWF0aW9uIHNldHRpbmdzIHVzZWQgYnkgdGhlIGRpYWxvZy5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogQFZpZXdDaGlsZCgnYWxlcnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBwdWJsaWMgYWxlcnQ6IElneERpYWxvZ0NvbXBvbmVudDtcbiAgICAgKiBsZXQgY3VycmVudFBvc2l0aW9uOiBQb3NpdGlvblNldHRpbmdzID0gdGhpcy5hbGVydC5wb3NpdGlvblNldHRpbmdzXG4gICAgICogYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZ2V0IHBvc2l0aW9uU2V0dGluZ3MoKTogUG9zaXRpb25TZXR0aW5ncyB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wb3NpdGlvblNldHRpbmdzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgcG9zaXRpb24gYW5kIGFuaW1hdGlvbiBzZXR0aW5ncyB1c2VkIGJ5IHRoZSBkaWFsb2cuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGltcG9ydCB7IHNsaWRlSW5MZWZ0LCBzbGlkZU91dFJpZ2h0IH0gZnJvbSAnaWduaXRldWktYW5ndWxhcic7XG4gICAgICogLi4uXG4gICAgICogQFZpZXdDaGlsZCgnYWxlcnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBwdWJsaWMgYWxlcnQ6IElneERpYWxvZ0NvbXBvbmVudDtcbiAgICAgKiAgcHVibGljIG5ld1Bvc2l0aW9uU2V0dGluZ3M6IFBvc2l0aW9uU2V0dGluZ3MgPSB7XG4gICAgICogICAgICBvcGVuQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oc2xpZGVJblRvcCwgeyBwYXJhbXM6IHsgZHVyYXRpb246ICcyMDAwbXMnIH0gfSksXG4gICAgICogICAgICBjbG9zZUFuaW1hdGlvbjogdXNlQW5pbWF0aW9uKHNsaWRlT3V0Qm90dG9tLCB7IHBhcmFtczogeyBkdXJhdGlvbjogJzIwMDBtcyd9IH0pLFxuICAgICAqICAgICAgaG9yaXpvbnRhbERpcmVjdGlvbjogSG9yaXpvbnRhbEFsaWdubWVudC5MZWZ0LFxuICAgICAqICAgICAgdmVydGljYWxEaXJlY3Rpb246IFZlcnRpY2FsQWxpZ25tZW50Lk1pZGRsZSxcbiAgICAgKiAgICAgIGhvcml6b250YWxTdGFydFBvaW50OiBIb3Jpem9udGFsQWxpZ25tZW50LkxlZnQsXG4gICAgICogICAgICB2ZXJ0aWNhbFN0YXJ0UG9pbnQ6IFZlcnRpY2FsQWxpZ25tZW50Lk1pZGRsZSxcbiAgICAgKiAgICAgIG1pblNpemU6IHsgaGVpZ2h0OiAxMDAsIHdpZHRoOiAxMDAgfVxuICAgICAqICB9O1xuICAgICAqIHRoaXMuYWxlcnQucG9zaXRpb25TZXR0aW5ncyA9IHRoaXMubmV3UG9zaXRpb25TZXR0aW5ncztcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0IHBvc2l0aW9uU2V0dGluZ3Moc2V0dGluZ3M6IFBvc2l0aW9uU2V0dGluZ3MpIHtcbiAgICAgICAgdGhpcy5fcG9zaXRpb25TZXR0aW5ncyA9IHNldHRpbmdzO1xuICAgICAgICB0aGlzLl9vdmVybGF5RGVmYXVsdFNldHRpbmdzLnBvc2l0aW9uU3RyYXRlZ3kgPSBuZXcgR2xvYmFsUG9zaXRpb25TdHJhdGVneSh0aGlzLl9wb3NpdGlvblNldHRpbmdzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiB0aGUgZGlhbG9nIGlzIG9wZW5lZC5cbiAgICAgKmBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIChvbk9wZW4pPVwib25EaWFsb2dPcGVuSGFuZGxlcigkZXZlbnQpXCIgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJkaWFsb2cuY2xvc2UoKVwiIHJpZ2h0QnV0dG9uTGFiZWw9XCJPS1wiPlxuICAgICAqPC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uT3BlbiA9IG5ldyBFdmVudEVtaXR0ZXI8SURpYWxvZ0V2ZW50QXJncz4oKTtcblxuICAgIC8qKlxuICAgICAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCB3aGVuIHRoZSBkaWFsb2cgaXMgY2xvc2VkLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgKG9uQ2xvc2UpPVwib25EaWFsb2dDbG9zZUhhbmRsZXIoJGV2ZW50KVwiIHRpdGxlPVwiQ29uZmlybWF0aW9uXCIgbGVmdEJ1dHRvbkxhYmVsPVwiQ2FuY2VsXCIgcmlnaHRCdXR0b25MYWJlbD1cIk9LXCI+XG4gICAgICo8L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25DbG9zZSA9IG5ldyBFdmVudEVtaXR0ZXI8SURpYWxvZ0V2ZW50QXJncz4oKTtcblxuICAgIC8qKlxuICAgICAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCB3aGVuIHRoZSBsZWZ0IGJ1dHRvbiBpcyBjbGlja2VkLlxuICAgICAqYGBgaHRtbFxuICAgICAqPGlneC1kaWFsb2cgKG9uTGVmdEJ1dHRvblNlbGVjdCk9XCJvbkRpYWxvZ09LU2VsZWN0ZWQoJGV2ZW50KVwiICNkaWFsb2cgbGVmdEJ1dHRvbkxhYmVsPVwiT0tcIiByaWdodEJ1dHRvbkxhYmVsPVwiQ2FuY2VsXCI+XG4gICAgICo8L2lneC1kaWFsb2c+XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25MZWZ0QnV0dG9uU2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjxJRGlhbG9nRXZlbnRBcmdzPigpO1xuXG4gICAgLyoqXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gdGhlIHJpZ2h0IGJ1dHRvbiBpcyBjbGlja2VkLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKjxpZ3gtZGlhbG9nIChvblJpZ2h0QnV0dG9uU2VsZWN0KT1cIm9uRGlhbG9nT0tTZWxlY3RlZCgkZXZlbnQpXCJcbiAgICAgKiNkaWFsb2cgdGl0bGU9XCJDb25maXJtYXRpb25cIiAob25MZWZ0QnV0dG9uU2VsZWN0KT1cImRpYWxvZy5jbG9zZSgpXCIgcmlnaHRCdXR0b25MYWJlbD1cIk9LXCJcbiAgICAgKnJpZ2h0QnV0dG9uUmlwcGxlPVwiIzRDQUY1MFwiIGNsb3NlT25PdXRzaWRlU2VsZWN0PVwidHJ1ZVwiPlxuICAgICAqPC9pZ3gtZGlhbG9nPlxuICAgICAqYGBgXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uUmlnaHRCdXR0b25TZWxlY3QgPSBuZXcgRXZlbnRFbWl0dGVyPElEaWFsb2dFdmVudEFyZ3M+KCk7XG5cbiAgICBwcml2YXRlIF9wb3NpdGlvblNldHRpbmdzOiBQb3NpdGlvblNldHRpbmdzID0ge1xuICAgICAgICBvcGVuQW5pbWF0aW9uOiB1c2VBbmltYXRpb24oc2xpZGVJbkJvdHRvbSwgeyBwYXJhbXM6IHsgZnJvbVBvc2l0aW9uOiAndHJhbnNsYXRlWSgxMDAlKScgfSB9KSxcbiAgICAgICAgY2xvc2VBbmltYXRpb246IHVzZUFuaW1hdGlvbihzbGlkZU91dFRvcCwgeyBwYXJhbXM6IHsgdG9Qb3NpdGlvbjogJ3RyYW5zbGF0ZVkoLTEwMCUpJyB9IH0pXG4gICAgfTtcblxuICAgIHByaXZhdGUgX292ZXJsYXlEZWZhdWx0U2V0dGluZ3M6IE92ZXJsYXlTZXR0aW5ncztcbiAgICBwcml2YXRlIF9jbG9zZU9uT3V0c2lkZVNlbGVjdCA9IGZhbHNlO1xuICAgIHByaXZhdGUgX2lzTW9kYWwgPSB0cnVlO1xuICAgIHByb3RlY3RlZCBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PGJvb2xlYW4+KCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGdldCBlbGVtZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGRlZmF1bHQgYHRhYmluZGV4YCBhdHRyaWJ1dGUgZm9yIHRoZSBjb21wb25lbnRcbiAgICAgKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBASG9zdEJpbmRpbmcoJ2F0dHIudGFiaW5kZXgnKVxuICAgIHB1YmxpYyB0YWJpbmRleCA9IC0xO1xuXG4gICAgcHJpdmF0ZSBfdGl0bGVJZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdmFsdWUgb2Ygc3RhdGUuIFBvc3NpYmxlIHN0YXRlIHZhbHVlcyBhcmUgXCJvcGVuXCIgb3IgXCJjbG9zZVwiLlxuICAgICAqYGBgdHlwZXNjcmlwdFxuICAgICAqQFZpZXdDaGlsZChcIk15RGlhbG9nXCIpXG4gICAgICpwdWJsaWMgZGlhbG9nOiBJZ3hEaWFsb2dDb21wb25lbnQ7XG4gICAgICpuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgICogICAgbGV0IGRpYWxvZ1N0YXRlID0gdGhpcy5kaWFsb2cuc3RhdGU7XG4gICAgICp9XG4gICAgICpgYGBcbiAgICAgKi9cbiAgICBnZXQgc3RhdGUoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNPcGVuID8gJ29wZW4nIDogJ2Nsb3NlJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIGRpYWxvZyBpcyB2aXNpYmxlIHRvIHRoZSBlbmQgdXNlci5cbiAgICAgKmBgYHR5cGVzY3JpcHRcbiAgICAgKkBWaWV3Q2hpbGQoXCJNeURpYWxvZ1wiKVxuICAgICAqcHVibGljIGRpYWxvZzogSWd4RGlhbG9nQ29tcG9uZW50O1xuICAgICAqbmdBZnRlclZpZXdJbml0KCkge1xuICAgICAqICAgIGxldCBkaWFsb2dPcGVuID0gdGhpcy5kaWFsb2cuaXNPcGVuO1xuICAgICAqfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgZ2V0IGlzT3BlbigpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLnRvZ2dsZVJlZi5jb2xsYXBzZWQ7XG4gICAgfVxuXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5pZ3gtZGlhbG9nLS1oaWRkZW4nKVxuICAgIGdldCBpc0NvbGxhcHNlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudG9nZ2xlUmVmLmNvbGxhcHNlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKlJldHVybnMgdGhlIHZhbHVlIG9mIHRoZSByb2xlIG9mIHRoZSBkaWFsb2cuIFRoZSB2YWxpZCB2YWx1ZXMgYXJlIGBkaWFsb2dgLCBgYWxlcnRkaWFsb2dgLCBgYWxlcnRgLlxuICAgICAqYGBgdHlwZXNjcmlwdFxuICAgICAqQFZpZXdDaGlsZChcIk15RGlhbG9nXCIpXG4gICAgICpwdWJsaWMgZGlhbG9nOiBJZ3hEaWFsb2dDb21wb25lbnQ7XG4gICAgICpuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgICogICAgbGV0IGRpYWxvZ1JvbGUgPSB0aGlzLmRpYWxvZy5yb2xlO1xuICAgICAqfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgZ2V0IHJvbGUoKSB7XG4gICAgICAgIGlmICh0aGlzLmxlZnRCdXR0b25MYWJlbCAhPT0gJycgJiYgdGhpcy5yaWdodEJ1dHRvbkxhYmVsICE9PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuICdkaWFsb2cnO1xuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgdGhpcy5sZWZ0QnV0dG9uTGFiZWwgIT09ICcnIHx8XG4gICAgICAgICAgICB0aGlzLnJpZ2h0QnV0dG9uTGFiZWwgIT09ICcnXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuICdhbGVydGRpYWxvZyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ2FsZXJ0JztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqUmV0dXJucyB0aGUgdmFsdWUgb2YgdGhlIHRpdGxlIGlkLlxuICAgICAqYGBgdHlwZXNjcmlwdFxuICAgICAqQFZpZXdDaGlsZChcIk15RGlhbG9nXCIpXG4gICAgICpwdWJsaWMgZGlhbG9nOiBJZ3hEaWFsb2dDb21wb25lbnQ7XG4gICAgICpuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgICogICAgbGV0IGRpYWxvZ1RpdGxlID0gdGhpcy5kaWFsb2cudGl0bGVJZDtcbiAgICAgKn1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCB0aXRsZUlkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdGl0bGVJZDtcbiAgICB9XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgICAgICBAT3B0aW9uYWwoKSBwcml2YXRlIG5hdlNlcnZpY2U6IElneE5hdmlnYXRpb25TZXJ2aWNlXG4gICAgKSB7XG4gICAgICAgIHRoaXMuX3RpdGxlSWQgPSBJZ3hEaWFsb2dDb21wb25lbnQuTkVYVF9JRCsrICsgJ190aXRsZSc7XG5cbiAgICAgICAgdGhpcy5fb3ZlcmxheURlZmF1bHRTZXR0aW5ncyA9IHtcbiAgICAgICAgICAgIHBvc2l0aW9uU3RyYXRlZ3k6IG5ldyBHbG9iYWxQb3NpdGlvblN0cmF0ZWd5KHRoaXMuX3Bvc2l0aW9uU2V0dGluZ3MpLFxuICAgICAgICAgICAgc2Nyb2xsU3RyYXRlZ3k6IG5ldyBOb09wU2Nyb2xsU3RyYXRlZ3koKSxcbiAgICAgICAgICAgIG1vZGFsOiB0aGlzLmlzTW9kYWwsXG4gICAgICAgICAgICBjbG9zZU9uT3V0c2lkZUNsaWNrOiB0aGlzLmNsb3NlT25PdXRzaWRlU2VsZWN0XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgICAgICB0aGlzLnRvZ2dsZVJlZi5vbkNsb3NpbmcucGlwZSh0YWtlVW50aWwodGhpcy5kZX