ardhrizk-ngx-daterangepicker-bootstrap
Version:
Date Range Picker - Forced to Angular 16 and Bootstrap 5
430 lines • 54.4 kB
JavaScript
import { Directive, EventEmitter, forwardRef, HostBinding, HostListener, Input, Output, reflectComponentType } from '@angular/core';
import { NG_VALUE_ACCESSOR } from "@angular/forms";
import dayjs from 'dayjs';
import { NgxDaterangepickerBootstrapComponent } from "./ngx-daterangepicker-bootstrap.component";
import * as i0 from "@angular/core";
import * as i1 from "./ngx-daterangepicker-locale.service";
export class NgxDaterangepickerBootstrapDirective {
set startKey(value) {
if (value !== null) {
this._startKey = value;
}
else {
this._startKey = 'startDate';
}
}
set endKey(value) {
if (value !== null) {
this._endKey = value;
}
else {
this._endKey = 'endDate';
}
}
set locale(value) {
this._locale = { ...this._localeService.config, ...value };
}
get disabled() {
return this._disabled;
}
get locale() {
return this._locale;
}
get value() {
return this._value || null;
}
set value(val) {
this._value = val;
this._onChange(val);
this._changeDetectorRef.markForCheck();
}
constructor(viewContainerRef, injector, applicationRef, differs, elementRef, _changeDetectorRef, _el, _renderer, _localeService) {
this.viewContainerRef = viewContainerRef;
this.injector = injector;
this.applicationRef = applicationRef;
this.differs = differs;
this.elementRef = elementRef;
this._changeDetectorRef = _changeDetectorRef;
this._el = _el;
this._renderer = _renderer;
this._localeService = _localeService;
this._onChange = Function.prototype;
this._onTouched = Function.prototype;
this._locale = {};
this.dateLimit = null;
this.showCancel = false;
this.lockStartDate = false;
this.closeOnAutoApply = true;
this.timePicker = false;
this.timePicker24Hour = false;
this.timePickerIncrement = 1;
this.timePickerSeconds = false;
this.formlyCustomField = false; // if you use ngx-formly and create custom field this library
this.change = new EventEmitter();
this.rangeClicked = new EventEmitter();
this.datesUpdated = new EventEmitter();
this.startDateChanged = new EventEmitter();
this.endDateChanged = new EventEmitter();
this.clearClicked = new EventEmitter();
this.notForChangesProperty = [
'locale',
'endKey',
'startKey'
];
this.endKey = 'endDate';
this.startKey = 'startDate';
this.drops = 'down';
this.opens = 'right';
viewContainerRef.clear();
this.daterangepickerRef = this.viewContainerRef.createComponent(NgxDaterangepickerBootstrapComponent, { injector: this.injector });
this.daterangepickerElement = this.daterangepickerRef.hostView.rootNodes[0];
CSS.supports('display', 'contents') // unwrap or hide daterangepickerElement from DOM body, to fix clickOutside
? this.daterangepickerElement.classList.add('unwrap', 'on')
: this.daterangepickerElement.classList.add('unwrap', 'off');
document.body.appendChild(this.daterangepickerElement); // add daterangepickerElement to DOM body, to fix position top left issues
this.daterangepicker = this.daterangepickerRef.instance;
this.daterangepicker.inline = false; // set inline to false for all directive usage
}
ngOnInit() {
this.daterangepicker.rangeClicked.asObservable().subscribe((range) => {
this.rangeClicked.emit(range);
});
this.daterangepicker.datesUpdated.asObservable().subscribe((range) => {
this.datesUpdated.emit(range);
});
this.daterangepicker.startDateChanged.asObservable().subscribe((itemChanged) => {
this.startDateChanged.emit(itemChanged);
});
this.daterangepicker.endDateChanged.asObservable().subscribe((itemChanged) => {
this.endDateChanged.emit(itemChanged);
});
this.daterangepicker.clearClicked.asObservable().subscribe(() => {
this.clearClicked.emit();
});
this.daterangepicker.choosedDate.asObservable().subscribe((change) => {
if (change) {
const value = {};
value[this._startKey] = change.startDate;
value[this._endKey] = change.endDate;
this.value = value;
this.change.emit(value);
if (typeof change.chosenLabel === 'string') {
this._el.nativeElement.value = change.chosenLabel;
}
}
});
this.pickerResizeObserver();
this.daterangepicker.firstMonthDayClass = this.firstMonthDayClass;
this.daterangepicker.lastMonthDayClass = this.lastMonthDayClass;
this.daterangepicker.emptyWeekRowClass = this.emptyWeekRowClass;
this.daterangepicker.emptyWeekColumnClass = this.emptyWeekColumnClass;
this.daterangepicker.firstDayOfNextMonthClass = this.firstDayOfNextMonthClass;
this.daterangepicker.lastDayOfPreviousMonthClass = this.lastDayOfPreviousMonthClass;
this.daterangepicker.drops = this.drops;
this.daterangepicker.opens = this.opens;
this.localeDiffer = this.differs.find(this.locale).create();
this.daterangepicker.closeOnAutoApply = this.closeOnAutoApply;
if (this.localeDiffer) {
const changes = this.localeDiffer.diff(this.locale);
if (changes) {
this.daterangepicker.updateLocale(this.locale);
}
}
}
ngOnDestroy() {
this._resizeObserver?.unobserve(this.daterangepicker.pickerContainer.nativeElement);
const reflectComponent = reflectComponentType(NgxDaterangepickerBootstrapComponent);
const selector = document.querySelector(reflectComponent.selector);
if (selector !== null)
document.body.removeChild(selector);
this.applicationRef.detachView(this.daterangepickerRef.hostView);
this.daterangepickerRef.destroy();
}
ngAfterViewInit() {
if (this.formlyCustomField)
this.writeValue(this.locale); // If you use ngx-formly custom field, remove [(ngModel)]
// from the input and set [formlyCustomField]='true' instead, to avoid Expression has changed after it was checked.
}
ngOnChanges(changes) {
for (const change in changes) {
if (changes.hasOwnProperty(change)) {
if (this.notForChangesProperty.indexOf(change) === -1) {
this.daterangepicker[change] = changes[change].currentValue;
}
}
}
}
onBlur() {
this._onTouched();
}
open(event) {
if (this.disabled)
return;
this.daterangepicker.show(event);
if (this.daterangepicker.isShown)
this.setPosition();
}
hide(e) {
this.daterangepicker.hide(e);
}
toggle(e) {
this.daterangepicker.isShown ? this.hide(e) : this.open(e);
}
clear() {
this.daterangepicker.clear();
}
writeValue(value) {
this.setValue(value);
}
registerOnChange(fn) {
this._onChange = fn;
}
registerOnTouched(fn) {
this._onTouched = fn;
}
setDisabledState(state) {
this._disabled = state;
}
setValue(val) {
if (val) {
this.value = val;
if (val[this._startKey]) {
this.daterangepicker.setStartDate(val[this._startKey]);
}
if (val[this._endKey]) {
this.daterangepicker.setEndDate(val[this._endKey]);
}
this.daterangepicker.calculateChosenLabel();
if (this.daterangepicker.chosenLabel) {
this._el.nativeElement.value = this.daterangepicker.chosenLabel;
}
}
else {
this.daterangepicker.clear();
}
}
ngAfterViewChecked() {
if (this.daterangepicker.isShown)
this.setPosition();
}
onWindowResize() {
if (this.daterangepicker.isShown)
this.setPosition();
}
pickerResizeObserver() {
this._resizeObserver = new ResizeObserver(() => {
// if (this.daterangepicker.isShown) this.setPosition();
});
this._resizeObserver.observe(this.daterangepicker.pickerContainer.nativeElement);
}
/**
* Set position of the calendar, this works as expected only if you add daterangepickerElement to DOM body
*/
setPosition() {
const pickerContainer = this.daterangepicker.pickerContainer.nativeElement;
const inputOffset = this.getOffset(this._el.nativeElement);
let containerTop;
let containerBottom;
if (this.drops && this.drops === 'down') {
containerTop = inputOffset.top + inputOffset.height + 'px';
containerBottom = 'auto';
}
if (this.drops && this.drops === 'up') {
containerTop = 'auto';
containerBottom = window.innerHeight - inputOffset.top + 'px';
}
let style;
if (this.opens === 'right') {
style = {
top: containerTop,
right: 'auto',
bottom: containerBottom,
left: inputOffset.left + 'px',
};
}
if (this.opens === 'center') {
style = {
top: containerTop,
right: 'auto',
bottom: containerBottom,
left: inputOffset.left + (inputOffset.width - pickerContainer.offsetWidth) / 2 + 'px',
};
}
if (this.opens === 'left') {
style = {
top: containerTop,
right: window.innerWidth - (inputOffset.left + inputOffset.width) + 'px',
bottom: containerBottom,
left: 'auto',
};
}
if (style) {
/* inset: top right bottom left */
this._renderer.setStyle(pickerContainer, 'top', style.top);
this._renderer.setStyle(pickerContainer, 'right', style.right);
this._renderer.setStyle(pickerContainer, 'bottom', style.bottom);
this._renderer.setStyle(pickerContainer, 'left', style.left);
}
}
getOffset(element) {
const rect = element.getBoundingClientRect();
return {
top: rect.top + window.scrollY,
left: rect.left + window.scrollX,
height: rect.height,
width: rect.width,
};
}
inputChanged(e) {
if (e.target.tagName.toLowerCase() !== 'input')
return;
if (!e.target.value.length)
return;
const dateString = e.target.value.split(this.daterangepicker.locale.separator);
let start = null, end = null;
if (dateString.length === 2) {
start = dayjs(dateString[0], this.daterangepicker.locale.format);
end = dayjs(dateString[1], this.daterangepicker.locale.format);
}
if (this.singleDatePicker || start === null || end === null) {
start = dayjs(e.target.value, this.daterangepicker.locale.format);
end = start;
}
if (!start.isValid() || !end.isValid())
return;
this.daterangepicker.setStartDate(start);
this.daterangepicker.setEndDate(end);
this.daterangepicker.updateView();
}
/**
* For click outside of the calendar's container
* @param event event object
*/
outsideClick(event) {
if (!event.target || event.target.classList.contains('ngx-daterangepicker-action'))
return;
if (!this.elementRef.nativeElement.contains(event.target))
this.hide();
}
}
NgxDaterangepickerBootstrapDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.2", ngImport: i0, type: NgxDaterangepickerBootstrapDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.Injector }, { token: i0.ApplicationRef }, { token: i0.KeyValueDiffers }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.NgxDaterangepickerLocaleService }], target: i0.ɵɵFactoryTarget.Directive });
NgxDaterangepickerBootstrapDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.2", type: NgxDaterangepickerBootstrapDirective, selector: "input[ngxDaterangepickerBootstrap]", inputs: { minDate: "minDate", maxDate: "maxDate", autoApply: "autoApply", alwaysShowCalendars: "alwaysShowCalendars", showCustomRangeLabel: "showCustomRangeLabel", linkedCalendars: "linkedCalendars", dateLimit: "dateLimit", singleDatePicker: "singleDatePicker", showWeekNumbers: "showWeekNumbers", showISOWeekNumbers: "showISOWeekNumbers", showDropdowns: "showDropdowns", isInvalidDate: "isInvalidDate", isCustomDate: "isCustomDate", isTooltipDate: "isTooltipDate", showClearButton: "showClearButton", customRangeDirection: "customRangeDirection", ranges: "ranges", opens: "opens", drops: "drops", lastMonthDayClass: "lastMonthDayClass", emptyWeekRowClass: "emptyWeekRowClass", emptyWeekColumnClass: "emptyWeekColumnClass", firstDayOfNextMonthClass: "firstDayOfNextMonthClass", lastDayOfPreviousMonthClass: "lastDayOfPreviousMonthClass", keepCalendarOpeningWithRange: "keepCalendarOpeningWithRange", showRangeLabelOnInput: "showRangeLabelOnInput", showCancel: "showCancel", lockStartDate: "lockStartDate", closeOnAutoApply: "closeOnAutoApply", timePicker: "timePicker", timePicker24Hour: "timePicker24Hour", timePickerIncrement: "timePickerIncrement", timePickerSeconds: "timePickerSeconds", formlyCustomField: "formlyCustomField", startKey: "startKey", endKey: "endKey", locale: "locale" }, outputs: { change: "change", rangeClicked: "rangeClicked", datesUpdated: "datesUpdated", startDateChanged: "startDateChanged", endDateChanged: "endDateChanged", clearClicked: "clearClicked" }, host: { listeners: { "click": "open()", "keyup.esc": "hide()", "blur": "onBlur()", "keyup": "inputChanged($event)", "window:resize": "onWindowResize($event)", "document:click": "outsideClick($event)" }, properties: { "disabled": "this.disabled" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgxDaterangepickerBootstrapDirective), multi: true
}
], usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.2", ngImport: i0, type: NgxDaterangepickerBootstrapDirective, decorators: [{
type: Directive,
args: [{
selector: 'input[ngxDaterangepickerBootstrap]',
host: {
'(click)': 'open()',
'(keyup.esc)': 'hide()',
'(blur)': 'onBlur()',
'(keyup)': 'inputChanged($event)'
},
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgxDaterangepickerBootstrapDirective), multi: true
}
]
}]
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.Injector }, { type: i0.ApplicationRef }, { type: i0.KeyValueDiffers }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.NgxDaterangepickerLocaleService }]; }, propDecorators: { minDate: [{
type: Input
}], maxDate: [{
type: Input
}], autoApply: [{
type: Input
}], alwaysShowCalendars: [{
type: Input
}], showCustomRangeLabel: [{
type: Input
}], linkedCalendars: [{
type: Input
}], dateLimit: [{
type: Input
}], singleDatePicker: [{
type: Input
}], showWeekNumbers: [{
type: Input
}], showISOWeekNumbers: [{
type: Input
}], showDropdowns: [{
type: Input
}], isInvalidDate: [{
type: Input
}], isCustomDate: [{
type: Input
}], isTooltipDate: [{
type: Input
}], showClearButton: [{
type: Input
}], customRangeDirection: [{
type: Input
}], ranges: [{
type: Input
}], opens: [{
type: Input
}], drops: [{
type: Input
}], lastMonthDayClass: [{
type: Input
}], emptyWeekRowClass: [{
type: Input
}], emptyWeekColumnClass: [{
type: Input
}], firstDayOfNextMonthClass: [{
type: Input
}], lastDayOfPreviousMonthClass: [{
type: Input
}], keepCalendarOpeningWithRange: [{
type: Input
}], showRangeLabelOnInput: [{
type: Input
}], showCancel: [{
type: Input
}], lockStartDate: [{
type: Input
}], closeOnAutoApply: [{
type: Input
}], timePicker: [{
type: Input
}], timePicker24Hour: [{
type: Input
}], timePickerIncrement: [{
type: Input
}], timePickerSeconds: [{
type: Input
}], formlyCustomField: [{
type: Input
}], startKey: [{
type: Input
}], endKey: [{
type: Input
}], locale: [{
type: Input
}], disabled: [{
type: HostBinding,
args: ['disabled']
}], change: [{
type: Output
}], rangeClicked: [{
type: Output
}], datesUpdated: [{
type: Output
}], startDateChanged: [{
type: Output
}], endDateChanged: [{
type: Output
}], clearClicked: [{
type: Output
}], onWindowResize: [{
type: HostListener,
args: ['window:resize', ['$event']]
}], outsideClick: [{
type: HostListener,
args: ['document:click', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWRhdGVyYW5nZXBpY2tlci1ib290c3RyYXAuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRhdGVyYW5nZXBpY2tlci1ib290c3RyYXAvc3JjL2xpYi9uZ3gtZGF0ZXJhbmdlcGlja2VyLWJvb3RzdHJhcC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQU1MLFNBQVMsRUFHVCxZQUFZLEVBQ1osVUFBVSxFQUNWLFdBQVcsRUFDWCxZQUFZLEVBRVosS0FBSyxFQU1MLE1BQU0sRUFDTixvQkFBb0IsRUFJckIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDakQsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sRUFBQyxvQ0FBb0MsRUFBQyxNQUFNLDJDQUEyQyxDQUFDOzs7QUFtQi9GLE1BQU0sT0FBTyxvQ0FBb0M7SUFvRC9DLElBQWEsUUFBUSxDQUFDLEtBQVU7UUFDOUIsSUFBSSxLQUFLLEtBQUssSUFBSSxFQUFFO1lBQ2xCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1NBQ3hCO2FBQU07WUFDTCxJQUFJLENBQUMsU0FBUyxHQUFHLFdBQVcsQ0FBQztTQUM5QjtJQUNILENBQUM7SUFFRCxJQUFhLE1BQU0sQ0FBQyxLQUFVO1FBQzVCLElBQUksS0FBSyxLQUFLLElBQUksRUFBRTtZQUNsQixJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztTQUN0QjthQUFNO1lBQ0wsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUM7U0FDMUI7SUFDSCxDQUFDO0lBRUQsSUFBYSxNQUFNLENBQUMsS0FBSztRQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLEVBQUMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxHQUFHLEtBQUssRUFBQyxDQUFD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QkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csb0JBQW9CO3NCQUE1QixLQUFLO2dCQUNHLHdCQUF3QjtzQkFBaEMsS0FBSztnQkFDRywyQkFBMkI7c0JBQW5DLEtBQUs7Z0JBQ0csNEJBQTRCO3NCQUFwQyxLQUFLO2dCQUNHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLG1CQUFtQjtzQkFBM0IsS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUVPLFFBQVE7c0JBQXBCLEtBQUs7Z0JBUU8sTUFBTTtzQkFBbEIsS0FBSztnQkFRTyxNQUFNO3NCQUFsQixLQUFLO2dCQUl1QixRQUFRO3NCQUFwQyxXQUFXO3VCQUFDLFVBQVU7Z0JBUWIsTUFBTTtzQkFBZixNQUFNO2dCQUNHLFlBQVk7c0JBQXJCLE1BQU07Z0JBQ0csWUFBWTtzQkFBckIsTUFBTTtnQkFDRyxnQkFBZ0I7c0JBQXpCLE1BQU07Z0JBQ0csY0FBYztzQkFBdkIsTUFBTTtnQkFDRyxZQUFZO3NCQUFyQixNQUFNO2dCQThLUCxjQUFjO3NCQURiLFlBQVk7dUJBQUMsZUFBZSxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQWdHekMsWUFBWTtzQkFEWCxZQUFZO3VCQUFDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3Q2hlY2tlZCxcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQXBwbGljYXRpb25SZWYsXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnRSZWYsXG4gIERpcmVjdGl2ZSxcbiAgRWxlbWVudFJlZixcbiAgRW1iZWRkZWRWaWV3UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGZvcndhcmRSZWYsXG4gIEhvc3RCaW5kaW5nLFxuICBIb3N0TGlzdGVuZXIsXG4gIEluamVjdG9yLFxuICBJbnB1dCxcbiAgS2V5VmFsdWVEaWZmZXIsXG4gIEtleVZhbHVlRGlmZmVycyxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICByZWZsZWN0Q29tcG9uZW50VHlwZSxcbiAgUmVuZGVyZXIyLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBWaWV3Q29udGFpbmVyUmVmXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtOR19WQUxVRV9BQ0NFU1NPUn0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XG5pbXBvcnQgZGF5anMgZnJvbSAnZGF5anMnO1xuaW1wb3J0IHtOZ3hEYXRlcmFuZ2VwaWNrZXJCb290c3RyYXBDb21wb25lbnR9IGZyb20gXCIuL25neC1kYXRlcmFuZ2VwaWNrZXItYm9vdHN0cmFwLmNvbXBvbmVudFwiO1xuaW1wb3J0IHtMb2NhbGVDb25maWd9IGZyb20gXCIuL25neC1kYXRlcmFuZ2VwaWNrZXItbG9jYWxlLmNvbmZpZ1wiO1xuaW1wb3J0IHtOZ3hEYXRlcmFuZ2VwaWNrZXJMb2NhbGVTZXJ2aWNlfSBmcm9tIFwiLi9uZ3gtZGF0ZXJhbmdlcGlja2VyLWxvY2FsZS5zZXJ2aWNlXCI7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ2lucHV0W25neERhdGVyYW5nZXBpY2tlckJvb3RzdHJhcF0nLFxuICBob3N0OiB7XG4gICAgJyhjbGljayknOiAnb3BlbigpJyxcbiAgICAnKGtleXVwLmVzYyknOiAnaGlkZSgpJyxcbiAgICAnKGJsdXIpJzogJ29uQmx1cigpJyxcbiAgICAnKGtleXVwKSc6ICdpbnB1dENoYW5nZWQoJGV2ZW50KSdcbiAgfSxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBOZ3hEYXRlcmFuZ2VwaWNrZXJCb290c3RyYXBEaXJlY3RpdmUpLCBtdWx0aTogdHJ1ZVxuICAgIH1cbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hEYXRlcmFuZ2VwaWNrZXJCb290c3RyYXBEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgT25DaGFuZ2VzLCBBZnRlclZpZXdJbml0LCBBZnRlclZpZXdDaGVja2VkIHtcblxuICBwdWJsaWMgJGV2ZW50OiBhbnk7XG4gIHB1YmxpYyBkYXRlcmFuZ2VwaWNrZXI6IE5neERhdGVyYW5nZXBpY2tlckJvb3RzdHJhcENvbXBvbmVudCB8IGFueTtcbiAgcHJpdmF0ZSBkYXRlcmFuZ2VwaWNrZXJSZWY6IENvbXBvbmVudFJlZjxhbnk+O1xuICBwcml2YXRlIHJlYWRvbmx5IGRhdGVyYW5nZXBpY2tlckVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICBwcml2YXRlIGxvY2FsZURpZmZlcj86IEtleVZhbHVlRGlmZmVyPHN0cmluZywgYW55PjtcbiAgcHJpdmF0ZSBmaXJzdE1vbnRoRGF5Q2xhc3M/OiBzdHJpbmc7XG4gIHByaXZhdGUgX29uQ2hhbmdlID0gRnVuY3Rpb24ucHJvdG90eXBlO1xuICBwcml2YXRlIF9vblRvdWNoZWQgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG4gIHByaXZhdGUgX2Rpc2FibGVkPzogYm9vbGVhbjtcbiAgcHJpdmF0ZSBfdmFsdWU6IGFueTtcbiAgcHJpdmF0ZSBfc3RhcnRLZXkhOiBzdHJpbmc7XG4gIHByaXZhdGUgX2VuZEtleSE6IHN0cmluZztcbiAgcHJpdmF0ZSBfbG9jYWxlOiBMb2NhbGVDb25maWcgPSB7fTtcbiAgcHJpdmF0ZSBfcmVzaXplT2JzZXJ2ZXI/OiBSZXNpemVPYnNlcnZlcjtcblxuICBASW5wdXQoKSBtaW5EYXRlPzogZGF5anMuRGF5anM7XG4gIEBJbnB1dCgpIG1heERhdGU/OiBkYXlqcy5EYXlqcztcbiAgQElucHV0KCkgYXV0b0FwcGx5PzogYm9vbGVhbjtcbiAgQElucHV0KCkgYWx3YXlzU2hvd0NhbGVuZGFycz86IGJvb2xlYW47XG4gIEBJbnB1dCgpIHNob3dDdXN0b21SYW5nZUxhYmVsPzogYm9vbGVhbjtcbiAgQElucHV0KCkgbGlua2VkQ2FsZW5kYXJzPzogYm9vbGVhbjtcbiAgQElucHV0KCkgZGF0ZUxpbWl0OiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgQElucHV0KCkgc2luZ2xlRGF0ZVBpY2tlcj86IGJvb2xlYW47XG4gIEBJbnB1dCgpIHNob3dXZWVrTnVtYmVycz86IGJvb2xlYW47XG4gIEBJbnB1dCgpIHNob3dJU09XZWVrTnVtYmVycz86IGJvb2xlYW47XG4gIEBJbnB1dCgpIHNob3dEcm9wZG93bnM/OiBib29sZWFuO1xuICBASW5wdXQoKSBpc0ludmFsaWREYXRlPzogRnVuY3Rpb247XG4gIEBJbnB1dCgpIGlzQ3VzdG9tRGF0ZT86IEZ1bmN0aW9uO1xuICBASW5wdXQoKSBpc1Rvb2x0aXBEYXRlPzogRnVuY3Rpb247XG4gIEBJbnB1dCgpIHNob3dDbGVhckJ1dHRvbj86IGJvb2xlYW47XG4gIEBJbnB1dCgpIGN1c3RvbVJhbmdlRGlyZWN0aW9uPzogYm9vbGVhbjtcbiAgQElucHV0KCkgcmFuZ2VzOiBhbnk7XG4gIEBJbnB1dCgpIG9wZW5zOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGRyb3BzOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGxhc3RNb250aERheUNsYXNzPzogc3RyaW5nO1xuICBASW5wdXQoKSBlbXB0eVdlZWtSb3dDbGFzcz86IHN0cmluZztcbiAgQElucHV0KCkgZW1wdHlXZWVrQ29sdW1uQ2xhc3M/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIGZpcnN0RGF5T2ZOZXh0TW9udGhDbGFzcz86IHN0cmluZztcbiAgQElucHV0KCkgbGFzdERheU9mUHJldmlvdXNNb250aENsYXNzPzogc3RyaW5nO1xuICBASW5wdXQoKSBrZWVwQ2FsZW5kYXJPcGVuaW5nV2l0aFJhbmdlPzogYm9vbGVhbjtcbiAgQElucHV0KCkgc2hvd1JhbmdlTGFiZWxPbklucHV0PzogYm9vbGVhbjtcbiAgQElucHV0KCkgc2hvd0NhbmNlbDogQm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBsb2NrU3RhcnREYXRlOiBCb29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIGNsb3NlT25BdXRvQXBwbHkgPSB0cnVlO1xuICBASW5wdXQoKSB0aW1lUGlja2VyOiBCb29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIHRpbWVQaWNrZXIyNEhvdXI6IEJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgdGltZVBpY2tlckluY3JlbWVudDogTnVtYmVyID0gMTtcbiAgQElucHV0KCkgdGltZVBpY2tlclNlY29uZHM6IEJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgZm9ybWx5Q3VzdG9tRmllbGQ6IEJvb2xlYW4gPSBmYWxzZTsgLy8gaWYgeW91IHVzZSBuZ3gtZm9ybWx5IGFuZCBjcmVhdGUgY3VzdG9tIGZpZWxkIHRoaXMgbGlicmFyeVxuXG4gIEBJbnB1dCgpIHNldCBzdGFydEtleSh2YWx1ZTogYW55KSB7XG4gICAgaWYgKHZhbHVlICE9PSBudWxsKSB7XG4gICAgICB0aGlzLl9zdGFydEtleSA9IHZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9zdGFydEtleSA9ICdzdGFydERhdGUnO1xuICAgIH1cbiAgfVxuXG4gIEBJbnB1dCgpIHNldCBlbmRLZXkodmFsdWU6IGFueSkge1xuICAgIGlmICh2YWx1ZSAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5fZW5kS2V5ID0gdmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2VuZEtleSA9ICdlbmREYXRlJztcbiAgICB9XG4gIH1cblxuICBASW5wdXQoKSBzZXQgbG9jYWxlKHZhbHVlKSB7XG4gICAgdGhpcy5fbG9jYWxlID0gey4uLnRoaXMuX2xvY2FsZVNlcnZpY2UuY29uZmlnLCAuLi52YWx1ZX07XG4gIH1cblxuICBASG9zdEJpbmRpbmcoJ2Rpc2FibGVkJykgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLl9kaXNhYmxlZDtcbiAgfVxuXG4gIGdldCBsb2NhbGUoKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5fbG9jYWxlO1xuICB9XG5cbiAgQE91dHB1dCgpIGNoYW5nZTogRXZlbnRFbWl0dGVyPE9iamVjdD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSByYW5nZUNsaWNrZWQ6IEV2ZW50RW1pdHRlcjxPYmplY3Q+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgZGF0ZXNVcGRhdGVkOiBFdmVudEVtaXR0ZXI8T2JqZWN0PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHN0YXJ0RGF0ZUNoYW5nZWQ6IEV2ZW50RW1pdHRlcjxPYmplY3Q+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgZW5kRGF0ZUNoYW5nZWQ6IEV2ZW50RW1pdHRlcjxPYmplY3Q+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgY2xlYXJDbGlja2VkOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgbm90Rm9yQ2hhbmdlc1Byb3BlcnR5OiBBcnJheTxzdHJpbmc+ID0gW1xuICAgICdsb2NhbGUnLFxuICAgICdlbmRLZXknLFxuICAgICdzdGFydEtleSdcbiAgXTtcblxuICBnZXQgdmFsdWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbHVlIHx8IG51bGw7XG4gIH1cblxuICBzZXQgdmFsdWUodmFsKSB7XG4gICAgdGhpcy5fdmFsdWUgPSB2YWw7XG4gICAgdGhpcy5fb25DaGFuZ2UodmFsKTtcbiAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZixcbiAgICAgICAgICAgICAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgICAgICAgICAgIHByaXZhdGUgYXBwbGljYXRpb25SZWY6IEFwcGxpY2F0aW9uUmVmLFxuICAgICAgICAgICAgICBwcml2YXRlIGRpZmZlcnM6IEtleVZhbHVlRGlmZmVycyxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgICAgICAgICAgICBwcml2YXRlIF9jaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgICAgICAgICAgIHByaXZhdGUgX2VsOiBFbGVtZW50UmVmLFxuICAgICAgICAgICAgICBwcml2YXRlIF9yZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgICAgICAgICAgICBwcml2YXRlIF9sb2NhbGVTZXJ2aWNlOiBOZ3hEYXRlcmFuZ2VwaWNrZXJMb2NhbGVTZXJ2aWNlKSB7XG4gICAgdGhpcy5lbmRLZXkgPSAnZW5kRGF0ZSc7XG4gICAgdGhpcy5zdGFydEtleSA9ICdzdGFydERhdGUnO1xuICAgIHRoaXMuZHJvcHMgPSAnZG93bic7XG4gICAgdGhpcy5vcGVucyA9ICdyaWdodCc7XG4gICAgdmlld0NvbnRhaW5lclJlZi5jbGVhcigpO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyUmVmID0gdGhpcy52aWV3Q29udGFpbmVyUmVmLmNyZWF0ZUNvbXBvbmVudChOZ3hEYXRlcmFuZ2VwaWNrZXJCb290c3RyYXBDb21wb25lbnQsIHtpbmplY3RvcjogdGhpcy5pbmplY3Rvcn0pO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyRWxlbWVudCA9ICh0aGlzLmRhdGVyYW5nZXBpY2tlclJlZi5ob3N0VmlldyBhcyBFbWJlZGRlZFZpZXdSZWY8YW55Pikucm9vdE5vZGVzWzBdIGFzIEhUTUxFbGVtZW50O1xuICAgIENTUy5zdXBwb3J0cygnZGlzcGxheScsICdjb250ZW50cycpIC8vIHVud3JhcCBvciBoaWRlIGRhdGVyYW5nZXBpY2tlckVsZW1lbnQgZnJvbSBET00gYm9keSwgdG8gZml4IGNsaWNrT3V0c2lkZVxuICAgICAgPyB0aGlzLmRhdGVyYW5nZXBpY2tlckVsZW1lbnQuY2xhc3NMaXN0LmFkZCgndW53cmFwJywgJ29uJylcbiAgICAgIDogdGhpcy5kYXRlcmFuZ2VwaWNrZXJFbGVtZW50LmNsYXNzTGlzdC5hZGQoJ3Vud3JhcCcsICdvZmYnKTtcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuZGF0ZXJhbmdlcGlja2VyRWxlbWVudCk7IC8vIGFkZCBkYXRlcmFuZ2VwaWNrZXJFbGVtZW50IHRvIERPTSBib2R5LCB0byBmaXggcG9zaXRpb24gdG9wIGxlZnQgaXNzdWVzXG4gICAgdGhpcy5kYXRlcmFuZ2VwaWNrZXIgPSAoPE5neERhdGVyYW5nZXBpY2tlckJvb3RzdHJhcENvbXBvbmVudD50aGlzLmRhdGVyYW5nZXBpY2tlclJlZi5pbnN0YW5jZSk7XG4gICAgdGhpcy5kYXRlcmFuZ2VwaWNrZXIuaW5saW5lID0gZmFsc2U7IC8vIHNldCBpbmxpbmUgdG8gZmFsc2UgZm9yIGFsbCBkaXJlY3RpdmUgdXNhZ2VcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyLnJhbmdlQ2xpY2tlZC5hc09ic2VydmFibGUoKS5zdWJzY3JpYmUoKHJhbmdlOiBhbnkpID0+IHtcbiAgICAgIHRoaXMucmFuZ2VDbGlja2VkLmVtaXQocmFuZ2UpO1xuICAgIH0pO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyLmRhdGVzVXBkYXRlZC5hc09ic2VydmFibGUoKS5zdWJzY3JpYmUoKHJhbmdlOiBhbnkpID0+IHtcbiAgICAgIHRoaXMuZGF0ZXNVcGRhdGVkLmVtaXQocmFuZ2UpO1xuICAgIH0pO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyLnN0YXJ0RGF0ZUNoYW5nZWQuYXNPYnNlcnZhYmxlKCkuc3Vic2NyaWJlKChpdGVtQ2hhbmdlZDogYW55KSA9PiB7XG4gICAgICB0aGlzLnN0YXJ0RGF0ZUNoYW5nZWQuZW1pdChpdGVtQ2hhbmdlZCk7XG4gICAgfSk7XG4gICAgdGhpcy5kYXRlcmFuZ2VwaWNrZXIuZW5kRGF0ZUNoYW5nZWQuYXNPYnNlcnZhYmxlKCkuc3Vic2NyaWJlKChpdGVtQ2hhbmdlZDogYW55KSA9PiB7XG4gICAgICB0aGlzLmVuZERhdGVDaGFuZ2VkLmVtaXQoaXRlbUNoYW5nZWQpO1xuICAgIH0pO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyLmNsZWFyQ2xpY2tlZC5hc09ic2VydmFibGUoKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5jbGVhckNsaWNrZWQuZW1pdCgpO1xuICAgIH0pO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyLmNob29zZWREYXRlLmFzT2JzZXJ2YWJsZSgpLnN1YnNjcmliZSgoY2hhbmdlOiBhbnkpID0+IHtcbiAgICAgIGlmIChjaGFuZ2UpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB7fSBhcyBhbnk7XG4gICAgICAgIHZhbHVlW3RoaXMuX3N0YXJ0S2V5XSA9IGNoYW5nZS5zdGFydERhdGU7XG4gICAgICAgIHZhbHVlW3RoaXMuX2VuZEtleV0gPSBjaGFuZ2UuZW5kRGF0ZTtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLmNoYW5nZS5lbWl0KHZhbHVlKTtcbiAgICAgICAgaWYgKHR5cGVvZiBjaGFuZ2UuY2hvc2VuTGFiZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhpcy5fZWwubmF0aXZlRWxlbWVudC52YWx1ZSA9IGNoYW5nZS5jaG9zZW5MYWJlbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMucGlja2VyUmVzaXplT2JzZXJ2ZXIoKTtcbiAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5maXJzdE1vbnRoRGF5Q2xhc3MgPSB0aGlzLmZpcnN0TW9udGhEYXlDbGFzcztcbiAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5sYXN0TW9udGhEYXlDbGFzcyA9IHRoaXMubGFzdE1vbnRoRGF5Q2xhc3M7XG4gICAgdGhpcy5kYXRlcmFuZ2VwaWNrZXIuZW1wdHlXZWVrUm93Q2xhc3MgPSB0aGlzLmVtcHR5V2Vla1Jvd0NsYXNzO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyLmVtcHR5V2Vla0NvbHVtbkNsYXNzID0gdGhpcy5lbXB0eVdlZWtDb2x1bW5DbGFzcztcbiAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5maXJzdERheU9mTmV4dE1vbnRoQ2xhc3MgPSB0aGlzLmZpcnN0RGF5T2ZOZXh0TW9udGhDbGFzcztcbiAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5sYXN0RGF5T2ZQcmV2aW91c01vbnRoQ2xhc3MgPSB0aGlzLmxhc3REYXlPZlByZXZpb3VzTW9udGhDbGFzcztcbiAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5kcm9wcyA9IHRoaXMuZHJvcHM7XG4gICAgdGhpcy5kYXRlcmFuZ2VwaWNrZXIub3BlbnMgPSB0aGlzLm9wZW5zO1xuICAgIHRoaXMubG9jYWxlRGlmZmVyID0gdGhpcy5kaWZmZXJzLmZpbmQodGhpcy5sb2NhbGUpLmNyZWF0ZSgpO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyLmNsb3NlT25BdXRvQXBwbHkgPSB0aGlzLmNsb3NlT25BdXRvQXBwbHk7XG4gICAgaWYgKHRoaXMubG9jYWxlRGlmZmVyKSB7XG4gICAgICBjb25zdCBjaGFuZ2VzID0gdGhpcy5sb2NhbGVEaWZmZXIuZGlmZih0aGlzLmxvY2FsZSk7XG4gICAgICBpZiAoY2hhbmdlcykge1xuICAgICAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci51cGRhdGVMb2NhbGUodGhpcy5sb2NhbGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuX3Jlc2l6ZU9ic2VydmVyPy51bm9ic2VydmUodGhpcy5kYXRlcmFuZ2VwaWNrZXIucGlja2VyQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQpO1xuICAgIGNvbnN0IHJlZmxlY3RDb21wb25lbnQgPSByZWZsZWN0Q29tcG9uZW50VHlwZShOZ3hEYXRlcmFuZ2VwaWNrZXJCb290c3RyYXBDb21wb25lbnQpO1xuICAgIGNvbnN0IHNlbGVjdG9yID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihyZWZsZWN0Q29tcG9uZW50IS5zZWxlY3Rvcik7XG4gICAgaWYgKHNlbGVjdG9yICE9PSBudWxsKSBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKHNlbGVjdG9yKTtcbiAgICB0aGlzLmFwcGxpY2F0aW9uUmVmLmRldGFjaFZpZXcodGhpcy5kYXRlcmFuZ2VwaWNrZXJSZWYuaG9zdFZpZXcpO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyUmVmLmRlc3Ryb3koKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5mb3JtbHlDdXN0b21GaWVsZCkgdGhpcy53cml0ZVZhbHVlKHRoaXMubG9jYWxlKTsgLy8gSWYgeW91IHVzZSBuZ3gtZm9ybWx5IGN1c3RvbSBmaWVsZCwgcmVtb3ZlIFsobmdNb2RlbCldXG4gICAgLy8gZnJvbSB0aGUgaW5wdXQgYW5kIHNldCBbZm9ybWx5Q3VzdG9tRmllbGRdPSd0cnVlJyBpbnN0ZWFkLCB0byBhdm9pZCBFeHByZXNzaW9uIGhhcyBjaGFuZ2VkIGFmdGVyIGl0IHdhcyBjaGVja2VkLlxuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGZvciAoY29uc3QgY2hhbmdlIGluIGNoYW5nZXMpIHtcbiAgICAgIGlmIChjaGFuZ2VzLmhhc093blByb3BlcnR5KGNoYW5nZSkpIHtcbiAgICAgICAgaWYgKHRoaXMubm90Rm9yQ2hhbmdlc1Byb3BlcnR5LmluZGV4T2YoY2hhbmdlKSA9PT0gLTEpIHtcbiAgICAgICAgICB0aGlzLmRhdGVyYW5nZXBpY2tlcltjaGFuZ2VdID0gY2hhbmdlc1tjaGFuZ2VdLmN1cnJlbnRWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG9uQmx1cigpIHtcbiAgICB0aGlzLl9vblRvdWNoZWQoKTtcbiAgfVxuXG4gIG9wZW4oZXZlbnQ/OiBhbnkpIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkgcmV0dXJuO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyLnNob3coZXZlbnQpO1xuICAgIGlmICh0aGlzLmRhdGVyYW5nZXBpY2tlci5pc1Nob3duKSB0aGlzLnNldFBvc2l0aW9uKCk7XG4gIH1cblxuICBoaWRlKGU/OiBhbnkpIHtcbiAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5oaWRlKGUpO1xuICB9XG5cbiAgdG9nZ2xlKGU/OiBhbnkpIHtcbiAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5pc1Nob3duID8gdGhpcy5oaWRlKGUpIDogdGhpcy5vcGVuKGUpO1xuICB9XG5cbiAgY2xlYXIoKSB7XG4gICAgdGhpcy5kYXRlcmFuZ2VwaWNrZXIuY2xlYXIoKTtcbiAgfVxuXG4gIHdyaXRlVmFsdWUodmFsdWU6IGFueSkge1xuICAgIHRoaXMuc2V0VmFsdWUodmFsdWUpO1xuICB9XG5cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogYW55KSB7XG4gICAgdGhpcy5fb25DaGFuZ2UgPSBmbjtcbiAgfVxuXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpIHtcbiAgICB0aGlzLl9vblRvdWNoZWQgPSBmbjtcbiAgfVxuXG4gIHNldERpc2FibGVkU3RhdGUoc3RhdGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLl9kaXNhYmxlZCA9IHN0YXRlO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRWYWx1ZSh2YWw6IGFueSkge1xuICAgIGlmICh2YWwpIHtcbiAgICAgIHRoaXMudmFsdWUgPSB2YWw7XG4gICAgICBpZiAodmFsW3RoaXMuX3N0YXJ0S2V5XSkge1xuICAgICAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5zZXRTdGFydERhdGUodmFsW3RoaXMuX3N0YXJ0S2V5XSk7XG4gICAgICB9XG4gICAgICBpZiAodmFsW3RoaXMuX2VuZEtleV0pIHtcbiAgICAgICAgdGhpcy5kYXRlcmFuZ2VwaWNrZXIuc2V0RW5kRGF0ZSh2YWxbdGhpcy5fZW5kS2V5XSk7XG4gICAgICB9XG4gICAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5jYWxjdWxhdGVDaG9zZW5MYWJlbCgpO1xuICAgICAgaWYgKHRoaXMuZGF0ZXJhbmdlcGlja2VyLmNob3NlbkxhYmVsKSB7XG4gICAgICAgIHRoaXMuX2VsLm5hdGl2ZUVsZW1lbnQudmFsdWUgPSB0aGlzLmRhdGVyYW5nZXBpY2tlci5jaG9zZW5MYWJlbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kYXRlcmFuZ2VwaWNrZXIuY2xlYXIoKTtcbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyVmlld0NoZWNrZWQoKSB7XG4gICAgaWYgKHRoaXMuZGF0ZXJhbmdlcGlja2VyLmlzU2hvd24pIHRoaXMuc2V0UG9zaXRpb24oKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnLCBbJyRldmVudCddKVxuICBvbldpbmRvd1Jlc2l6ZSgpIHtcbiAgICBpZiAodGhpcy5kYXRlcmFuZ2VwaWNrZXIuaXNTaG93bikgdGhpcy5zZXRQb3NpdGlvbigpO1xuICB9XG5cbiAgcGlja2VyUmVzaXplT2JzZXJ2ZXIoKSB7XG4gICAgdGhpcy5fcmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4ge1xuICAgICAgLy8gaWYgKHRoaXMuZGF0ZXJhbmdlcGlja2VyLmlzU2hvd24pIHRoaXMuc2V0UG9zaXRpb24oKTtcbiAgICB9KTtcbiAgICB0aGlzLl9yZXNpemVPYnNlcnZlci5vYnNlcnZlKHRoaXMuZGF0ZXJhbmdlcGlja2VyLnBpY2tlckNvbnRhaW5lci5uYXRpdmVFbGVtZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgcG9zaXRpb24gb2YgdGhlIGNhbGVuZGFyLCB0aGlzIHdvcmtzIGFzIGV4cGVjdGVkIG9ubHkgaWYgeW91IGFkZCBkYXRlcmFuZ2VwaWNrZXJFbGVtZW50IHRvIERPTSBib2R5XG4gICAqL1xuICBzZXRQb3NpdGlvbigpIHtcbiAgICBjb25zdCBwaWNrZXJDb250YWluZXIgPSB0aGlzLmRhdGVyYW5nZXBpY2tlci5waWNrZXJDb250YWluZXIubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCBpbnB1dE9mZnNldCA9IHRoaXMuZ2V0T2Zmc2V0KHRoaXMuX2VsLm5hdGl2ZUVsZW1lbnQpO1xuICAgIGxldCBjb250YWluZXJUb3A7XG4gICAgbGV0IGNvbnRhaW5lckJvdHRvbTtcbiAgICBpZiAodGhpcy5kcm9wcyAmJiB0aGlzLmRyb3BzID09PSAnZG93bicpIHtcbiAgICAgIGNvbnRhaW5lclRvcCA9IGlucHV0T2Zmc2V0LnRvcCArIGlucHV0T2Zmc2V0LmhlaWdodCArICdweCc7XG4gICAgICBjb250YWluZXJCb3R0b20gPSAnYXV0bydcbiAgICB9XG4gICAgaWYgKHRoaXMuZHJvcHMgJiYgdGhpcy5kcm9wcyA9PT0gJ3VwJykge1xuICAgICAgY29udGFpbmVyVG9wID0gJ2F1dG8nXG4gICAgICBjb250YWluZXJCb3R0b20gPSB3aW5kb3cuaW5uZXJIZWlnaHQgLSBpbnB1dE9mZnNldC50b3AgKyAncHgnO1xuICAgIH1cbiAgICBsZXQgc3R5bGU7XG4gICAgaWYgKHRoaXMub3BlbnMgPT09ICdyaWdodCcpIHtcbiAgICAgIHN0eWxlID0ge1xuICAgICAgICB0b3A6IGNvbnRhaW5lclRvcCxcbiAgICAgICAgcmlnaHQ6ICdhdXRvJyxcbiAgICAgICAgYm90dG9tOiBjb250YWluZXJCb3R0b20sXG4gICAgICAgIGxlZnQ6IGlucHV0T2Zmc2V0LmxlZnQgKyAncHgnLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKHRoaXMub3BlbnMgPT09ICdjZW50ZXInKSB7XG4gICAgICBzdHlsZSA9IHtcbiAgICAgICAgdG9wOiBjb250YWluZXJUb3AsXG4gICAgICAgIHJpZ2h0OiAnYXV0bycsXG4gICAgICAgIGJvdHRvbTogY29udGFpbmVyQm90dG9tLFxuICAgICAgICBsZWZ0OiBpbnB1dE9mZnNldC5sZWZ0ICsgKGlucHV0T2Zmc2V0LndpZHRoIC0gcGlja2VyQ29udGFpbmVyLm9mZnNldFdpZHRoKSAvIDIgKyAncHgnLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKHRoaXMub3BlbnMgPT09ICdsZWZ0Jykge1xuICAgICAgc3R5bGUgPSB7XG4gICAgICAgIHRvcDogY29udGFpbmVyVG9wLFxuICAgICAgICByaWdodDogd2luZG93LmlubmVyV2lkdGggLSAoaW5wdXRPZmZzZXQubGVmdCArIGlucHV0T2Zmc2V0LndpZHRoKSArICdweCcsXG4gICAgICAgIGJvdHRvbTogY29udGFpbmVyQm90dG9tLFxuICAgICAgICBsZWZ0OiAnYXV0bycsXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAoc3R5bGUpIHtcbiAgICAgIC8qIGluc2V0OiB0b3AgcmlnaHQgYm90dG9tIGxlZnQgKi9cbiAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHBpY2tlckNvbnRhaW5lciwgJ3RvcCcsIHN0eWxlLnRvcCk7XG4gICAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZShwaWNrZXJDb250YWluZXIsICdyaWdodCcsIHN0eWxlLnJpZ2h0KTtcbiAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHBpY2tlckNvbnRhaW5lciwgJ2JvdHRvbScsIHN0eWxlLmJvdHRvbSk7XG4gICAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZShwaWNrZXJDb250YWluZXIsICdsZWZ0Jywgc3R5bGUubGVmdCk7XG4gICAgfVxuICB9XG5cbiAgZ2V0T2Zmc2V0KGVsZW1lbnQ6IGFueSkge1xuICAgIGNvbnN0IHJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHJldHVybiB7XG4gICAgICB0b3A6IHJlY3QudG9wICsgd2luZG93LnNjcm9sbFksXG4gICAgICBsZWZ0OiByZWN0LmxlZnQgKyB3aW5kb3cuc2Nyb2xsWCxcbiAgICAgIGhlaWdodDogcmVjdC5oZWlnaHQsXG4gICAgICB3aWR0aDogcmVjdC53aWR0aCxcbiAgICB9O1xuICB9XG5cbiAgaW5wdXRDaGFuZ2VkKGU6IGFueSkge1xuICAgIGlmIChlLnRhcmdldC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgIT09ICdpbnB1dCcpIHJldHVybjtcbiAgICBpZiAoIWUudGFyZ2V0LnZhbHVlLmxlbmd0aCkgcmV0dXJuO1xuICAgIGNvbnN0IGRhdGVTdHJpbmcgPSBlLnRhcmdldC52YWx1ZS5zcGxpdCh0aGlzLmRhdGVyYW5nZXBpY2tlci5sb2NhbGUuc2VwYXJhdG9yKTtcbiAgICBsZXQgc3RhcnQgPSBudWxsLCBlbmQgPSBudWxsO1xuICAgIGlmIChkYXRlU3RyaW5nLmxlbmd0aCA9PT0gMikge1xuICAgICAgc3RhcnQgPSBkYXlqcyhkYXRlU3RyaW5nWzBdLCB0aGlzLmRhdGVyYW5nZXBpY2tlci5sb2NhbGUuZm9ybWF0KTtcbiAgICAgIGVuZCA9IGRheWpzKGRhdGVTdHJpbmdbMV0sIHRoaXMuZGF0ZXJhbmdlcGlja2VyLmxvY2FsZS5mb3JtYXQpO1xuICAgIH1cbiAgICBpZiAodGhpcy5zaW5nbGVEYXRlUGlja2VyIHx8IHN0YXJ0ID09PSBudWxsIHx8IGVuZCA9PT0gbnVsbCkge1xuICAgICAgc3RhcnQgPSBkYXlqcyhlLnRhcmdldC52YWx1ZSwgdGhpcy5kYXRlcmFuZ2VwaWNrZXIubG9jYWxlLmZvcm1hdCk7XG4gICAgICBlbmQgPSBzdGFydDtcbiAgICB9XG4gICAgaWYgKCFzdGFydC5pc1ZhbGlkKCkgfHwgIWVuZC5pc1ZhbGlkKCkpIHJldHVybjtcbiAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci5zZXRTdGFydERhdGUoc3RhcnQpO1xuICAgIHRoaXMuZGF0ZXJhbmdlcGlja2VyLnNldEVuZERhdGUoZW5kKTtcbiAgICB0aGlzLmRhdGVyYW5nZXBpY2tlci51cGRhdGVWaWV3KCk7XG4gIH1cblxuICAvKipcbiAgICogRm9yIGNsaWNrIG91dHNpZGUgb2YgdGhlIGNhbGVuZGFyJ3MgY29udGFpbmVyXG4gICAqIEBwYXJhbSBldmVudCBldmVudCBvYmplY3RcbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNsaWNrJywgWyckZXZlbnQnXSlcbiAgb3V0c2lkZUNsaWNrKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICBpZiAoIWV2ZW50LnRhcmdldCB8fCBldmVudC50YXJnZXQuY2xhc3NMaXN0LmNvbnRhaW5zKCduZ3gtZGF0ZXJhbmdlcGlja2VyLWFjdGlvbicpKSByZXR1cm47XG4gICAgaWYgKCF0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jb250YWlucyhldmVudC50YXJnZXQpKSB0aGlzLmhpZGUoKTtcbiAgfVxuXG59XG4iXX0=