@hxui/angular
Version:
* * *
643 lines • 63.9 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
import { Component, Input, Output, ElementRef, EventEmitter, forwardRef, NgZone, ComponentFactoryResolver, ViewContainerRef, Optional } from '@angular/core';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
import { Overlay, ScrollDispatcher } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { Subject } from 'rxjs/index';
import { DatepickerComponent } from './datepicker.component';
import { take, takeUntil } from 'rxjs/operators';
import { Directionality } from '@angular/cdk/bidi';
import { DatepickerConfig } from './datepicker.config';
export class DatepickerFormComponent {
/**
* @param {?} _elementRef
* @param {?} _viewContainerRef
* @param {?} overlay
* @param {?} _ngZone
* @param {?} _scrollDispatcher
* @param {?} _componentFactoryResolver
* @param {?} _config
* @param {?} _dir
*/
constructor(_elementRef, _viewContainerRef, overlay, _ngZone, _scrollDispatcher, _componentFactoryResolver, _config, _dir) {
this._elementRef = _elementRef;
this._viewContainerRef = _viewContainerRef;
this.overlay = overlay;
this._ngZone = _ngZone;
this._scrollDispatcher = _scrollDispatcher;
this._componentFactoryResolver = _componentFactoryResolver;
this._config = _config;
this._dir = _dir;
this._destroyed = new Subject();
this.disabled = false;
this.readonly = false;
this.required = false;
this.defaultToPresentDate = true;
this.allowPreviousDates = true;
this.allowFutureDates = true;
this.dateFormat = 'dd/MM/y';
this.placeholder = 'Date';
this.helpText = 'Please select a date';
this.icon = 'hx-icon icon-calendar';
this.iconPlacement = 'right';
this.placement = 'bottom';
this.showDelay = this._config.showDelay;
this.hideDelay = this._config.hideDelay;
this.from = '';
this.to = '';
this.interval = false;
this.dueDateInterval = '0 day(s)'; // '1 week(s)' | '2 month(s)' | '3 year(s)'
// '1 week(s)' | '2 month(s)' | '3 year(s)'
this.onDateChange = new EventEmitter();
this.visible = false;
this.dateValidators = new Array();
this.onChanged = new Array();
this.onTouched = new Array();
this.onDateSelectEvent = (inputDate) => {
this._hide();
this.setDate(inputDate);
};
// get input reference
this._elementHtmlCollection = this._elementRef.nativeElement.getElementsByTagName('input');
}
/**
* Dispose the tooltip when destroyed.
* @return {?}
*/
ngOnDestroy() {
if (this._overlayRef) {
this._overlayRef.dispose();
this._calendarInstance = null;
}
this._destroyed.next();
this._destroyed.complete();
}
/**
* @return {?}
*/
ngOnInit() {
// set element ref which will be used for dropdown positioning
this._elementHtmlRef = this._elementHtmlCollection.item(0);
/** @type {?} */
const date = new Date();
this.presentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
if (this.defaultToPresentDate) {
setTimeout(() => {
this.setDate(this.presentDate);
});
}
// Close to the minimum and maxium possible dates, but still normalisable
// http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1
/** @type {?} */
const from = this.parseDate(this.from) || new Date(-8630000000000000);
/** @type {?} */
const to = this.parseDate(this.to) || new Date(8630000000000000);
if (!!this.from || !!this.to) {
this.validateDateRange = this.createDateRangeValidator(from, to);
this.dateValidators.push(this.validateDateRange.bind(this));
}
if (!this.allowPreviousDates) {
this.dateValidators.push(this.validateIsNotBeforeDate.bind(this));
}
if (!this.allowFutureDates) {
this.dateValidators.push(this.validateIsNotAfterDate.bind(this));
}
}
/**
* @param {?} date
* @return {?}
*/
setDate(date) {
this.date = date;
this.onDateChange.emit(date);
this.propogateChange(date);
}
/**
* @param {?} inputDate
* @return {?}
*/
onChange(inputDate) {
/** @type {?} */
const date = this.parseDate(inputDate);
if (inputDate === '') {
this.setDate(null);
}
else if (!!date) {
this.setDate(date);
}
else {
this.propogateChange(inputDate);
}
}
/**
* @return {?}
*/
onFocus() {
this._show();
this.propogateTouched();
}
/**
* @param {?} inputDate
* @return {?}
*/
onTab(inputDate) {
this.onChange(inputDate);
this._hide();
this.propogateTouched();
}
/**
* @param {?} inputDate
* @return {?}
*/
parseDate(inputDate) {
// Since Date.Parse() only acceps m/d/y dates, we have to swap the day and month
/** @type {?} */
const dateArray = inputDate.split(/[.,\/ -]/);
if (dateArray.length === 3 && dateArray[2].length !== 0) {
/** @type {?} */
const day = dateArray.shift();
dateArray.splice(1, 0, day);
/** @type {?} */
const parseInput = Date.parse(dateArray.join('/'));
if (!isNaN(parseInput)) {
return new Date(parseInput);
}
}
return null;
}
/**
* @param {?} date
* @return {?}
*/
validateIsNotBeforeDate(date) {
/** @type {?} */
const normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
return normalisedDate.getTime() <= this.presentDate.getTime();
}
/**
* @param {?} date
* @return {?}
*/
validateIsNotAfterDate(date) {
/** @type {?} */
const normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
return normalisedDate.getTime() >= this.presentDate.getTime();
}
/**
* @param {?} from
* @param {?} to
* @return {?}
*/
createDateRangeValidator(from, to) {
/** @type {?} */
const normalisedFromDate = new Date(from.getFullYear(), from.getMonth(), from.getDate());
/** @type {?} */
const normalisedToDate = new Date(to.getFullYear(), to.getMonth(), to.getDate());
return (date) => {
/** @type {?} */
const normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
return !(normalisedFromDate.getTime() <= normalisedDate.getTime() &&
normalisedDate.getTime() <= normalisedToDate.getTime());
};
}
/**
* @param {?} value
* @return {?}
*/
writeValue(value) {
if (value !== this.date) {
this.setDate(value);
}
}
/**
* @param {?} fn
* @return {?}
*/
registerOnChange(fn) {
this.onChanged.push(fn);
}
/**
* @param {?} fn
* @return {?}
*/
registerOnTouched(fn) {
this.onTouched.push(fn);
}
/**
* @return {?}
*/
propogateTouched() {
this.onTouched.forEach(fn => fn());
}
/**
* @param {?} value
* @return {?}
*/
propogateChange(value) {
this.onChanged.forEach(fn => fn(value));
}
/**
* @param {?} control
* @return {?}
*/
validate(control) {
/** @type {?} */
const date = Date.parse(control.value);
if (!this.required && (control.value === null || control.value === undefined)) {
this.isValid = true;
return null;
}
if (isNaN(date)) {
this.isValid = false;
return {
dateParseError: {
valid: false
}
};
}
if (!this.allowPreviousDates && this.validateIsNotBeforeDate(this.date)) {
this.isValid = false;
return {
previousDateError: {
valid: false
}
};
}
if (!this.allowFutureDates && this.validateIsNotAfterDate(this.date)) {
this.isValid = false;
return {
futureDateError: {
valid: false
}
};
}
if (this.validateDateRange && this.validateDateRange(this.date)) {
this.isValid = false;
return {
dateRangeError: {
valid: false
}
};
}
if (this.required && !this.date) {
this.isValid = false;
return {
dateRequiredError: {
valid: false
}
};
}
this.isValid = true;
return null;
}
/**
* @param {?=} delay
* @return {?}
*/
_show(delay = this.showDelay) {
if (this.disabled) {
return;
}
/** @type {?} */
const overlayRef = this._createOverlay();
this._detach();
this._portal = this._portal || new ComponentPortal(DatepickerComponent, this._viewContainerRef);
this._calendarInstance = overlayRef.attach(this._portal).instance;
this._calendarInstance.afterHidden()
.pipe(takeUntil(this._destroyed))
.subscribe(() => this._detach());
this._updateTooltipContent();
(/** @type {?} */ (this._calendarInstance)).show(delay);
}
/**
* @param {?=} delay
* @return {?}
*/
_hide(delay = this.hideDelay) {
if (this._calendarInstance) {
this._calendarInstance.hide(delay);
}
}
/**
* @return {?}
*/
_createOverlay() {
if (this._overlayRef) {
return this._overlayRef;
}
/** @type {?} */
const positionStrategy = this.overlay.position()
.flexibleConnectedTo((/** @type {?} */ (this._elementHtmlRef)))
.withTransformOriginOn('.hxa-datepicker-control')
.withFlexibleDimensions(false);
this._overlayRef = this.overlay.create({
positionStrategy: positionStrategy,
panelClass: 'hxa-datepicker-calendar',
hasBackdrop: true,
backdropClass: 'cdk-overlay-transparent-backdrop',
scrollStrategy: this.overlay.scrollStrategies.reposition()
});
this._updatePosition();
this._overlayRef.detachments()
.pipe(takeUntil(this._destroyed))
.subscribe(() => this._detach());
this._overlayRef.backdropClick().
subscribe(() => this._hide());
/** @type {?} */
const position = (/** @type {?} */ (this._overlayRef.getConfig().positionStrategy));
position.positionChanges
.pipe(takeUntil(this._destroyed))
.subscribe((pos) => {
if (pos.connectionPair.originX === 'start') {
this.placement = 'left';
}
else if (pos.connectionPair.originX === 'end') {
this.placement = 'right';
}
this._updateTooltipContent();
});
return this._overlayRef;
}
/**
* @return {?}
*/
_updatePosition() {
/** @type {?} */
const position = (/** @type {?} */ ((/** @type {?} */ (this._overlayRef)).getConfig().positionStrategy));
/** @type {?} */
const origin = this._getOrigin();
/** @type {?} */
const overlay = this._getOverlayPosition();
position.withPositions([
Object.assign({}, origin.main, overlay.main),
Object.assign({}, origin.fallback, overlay.fallback)
]);
}
/**
* Returns the origin position and a fallback position based on the user's position preference.
* The fallback position is the inverse of the origin (e.g. `'bottom' -> 'top'`).
* @return {?}
*/
_getOrigin() {
/** @type {?} */
const placement = this.placement;
/** @type {?} */
let originPlacement;
if (placement === 'top' || placement === 'bottom') {
originPlacement = { originX: 'start', originY: placement === 'top' ? 'top' : 'bottom' };
}
else if (placement === 'left') {
originPlacement = { originX: 'start', originY: 'center' };
}
else if (placement === 'right') {
originPlacement = { originX: 'end', originY: 'center' };
}
else {
console.error('Position error', placement);
}
const { x, y } = this._invertPosition(originPlacement.originX, originPlacement.originY);
return {
main: originPlacement,
fallback: { originX: x, originY: y }
};
}
/**
* Returns the overlay position and a fallback position based on the user's preference
* @return {?}
*/
_getOverlayPosition() {
/** @type {?} */
const placement = this.placement;
/** @type {?} */
let overlayPlacement;
if (placement === 'top') {
overlayPlacement = { overlayX: 'start', overlayY: 'bottom' };
}
else if (placement === 'bottom') {
overlayPlacement = { overlayX: 'start', overlayY: 'top' };
}
else if (placement === 'left') {
overlayPlacement = { overlayX: 'end', overlayY: 'center' };
}
else if (placement === 'right') {
overlayPlacement = { overlayX: 'start', overlayY: 'center' };
}
else {
console.error('Could not find a position', placement);
}
const { x, y } = this._invertPosition(overlayPlacement.overlayX, overlayPlacement.overlayY);
return {
main: overlayPlacement,
fallback: { overlayX: x, overlayY: y }
};
}
/**
* @param {?} x
* @param {?} y
* @return {?}
*/
_invertPosition(x, y) {
if (this.placement === 'top' || this.placement === 'bottom') {
if (y === 'top') {
y = 'bottom';
}
else if (y === 'bottom') {
y = 'top';
}
}
else {
if (x === 'end') {
x = 'start';
}
else if (x === 'start') {
x = 'end';
}
}
return { x, y };
}
/**
* @return {?}
*/
_detach() {
if (this._overlayRef && this._overlayRef.hasAttached()) {
this._overlayRef.detach();
}
this._calendarInstance = null;
}
/**
* Updates the tooltip content and repositions the overlay according to the new content length
* @return {?}
*/
_updateTooltipContent() {
// Must wait for the content to be painted to the tooltip so that the overlay can properly
// calculate the correct positioning based on the size of its contents.
if (this._calendarInstance) {
this._calendarInstance.selectedDate = this.date;
this._calendarInstance.placement = this.placement;
this._calendarInstance.validators = this.dateValidators;
this._calendarInstance.onDateSelected = this.onDateSelectEvent;
this._calendarInstance.allowInterval = this.interval;
this._calendarInstance.selectedDueDateInterval = this.dueDateInterval;
this._ngZone.onMicrotaskEmpty.asObservable().pipe(take(1), takeUntil(this._destroyed)).subscribe(() => {
if (this._calendarInstance) {
(/** @type {?} */ (this._overlayRef)).updatePosition();
}
});
}
}
}
DatepickerFormComponent.decorators = [
{ type: Component, args: [{
selector: 'hxa-datepicker-input, hxa-datepicker-form',
template: `<div class="hx-input-group hxa-datepicker-form">
<i class="{{icon}}" *ngIf="iconPlacement === 'left'"></i>
<div class="hx-input-control hxa-datepicker-control" [ngClass]="{'is-danger': !isValid && datePickerForm.touched}">
<input class="hx-input" type="text" #datePickerForm="ngModel"
[required]="required ? true : null"
[disabled]="disabled"
[readonly]="readonly ? true : null"
[ngModel]="date | date:dateFormat"
(change)="onChange(datePickerForm.value)"
(focus)="onFocus()"
(keydown.Tab)="onTab(datePickerForm.value)">
<label class="hx-label" *ngIf="placeholder">{{placeholder}} <sup *ngIf="required">*</sup></label>
<div class="hx-help">{{helpText}}</div>
</div>
<i class="{{icon}}" *ngIf="iconPlacement === 'right'"></i>
</div>
`,
styles: [`.hxa-datepicker-form{position:relative;max-width:19rem}.hxa-datepicker-control{margin:0}.hxa-datepicker-calendar{position:absolute;z-index:99;left:0;max-width:19rem}.hxa-datepicker-calendar-top{bottom:100%}.hxa-datepicker-calendar-bottom{top:70%}.hxa-datepicker-calendar hxa-datepicker{max-width:19rem}.hxa-datepicker-help{font-size:.75rem;margin-top:.25rem;color:#63605f}.hxa-datepicker-form input[readonly]~.hx-label{top:-.5rem;font-size:.75rem;color:#41b987}hxa-datepicker{border:1px solid #d3d3d3;max-width:19rem}`],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DatepickerFormComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => DatepickerFormComponent),
multi: true,
}]
},] },
];
/** @nocollapse */
DatepickerFormComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: ViewContainerRef },
{ type: Overlay },
{ type: NgZone },
{ type: ScrollDispatcher },
{ type: ComponentFactoryResolver },
{ type: DatepickerConfig },
{ type: Directionality, decorators: [{ type: Optional }] }
];
DatepickerFormComponent.propDecorators = {
disabled: [{ type: Input }],
readonly: [{ type: Input }],
required: [{ type: Input }],
defaultToPresentDate: [{ type: Input }],
allowPreviousDates: [{ type: Input }],
allowFutureDates: [{ type: Input }],
dateFormat: [{ type: Input }],
placeholder: [{ type: Input }],
helpText: [{ type: Input }],
icon: [{ type: Input }],
iconPlacement: [{ type: Input }],
placement: [{ type: Input }],
showDelay: [{ type: Input }],
hideDelay: [{ type: Input }],
from: [{ type: Input }],
to: [{ type: Input }],
interval: [{ type: Input }],
dueDateInterval: [{ type: Input }],
onDateChange: [{ type: Output }]
};
if (false) {
/** @type {?} */
DatepickerFormComponent.prototype._overlayRef;
/** @type {?} */
DatepickerFormComponent.prototype._calendarInstance;
/** @type {?} */
DatepickerFormComponent.prototype._portal;
/** @type {?} */
DatepickerFormComponent.prototype._destroyed;
/** @type {?} */
DatepickerFormComponent.prototype.disabled;
/** @type {?} */
DatepickerFormComponent.prototype.readonly;
/** @type {?} */
DatepickerFormComponent.prototype.required;
/** @type {?} */
DatepickerFormComponent.prototype.defaultToPresentDate;
/** @type {?} */
DatepickerFormComponent.prototype.allowPreviousDates;
/** @type {?} */
DatepickerFormComponent.prototype.allowFutureDates;
/** @type {?} */
DatepickerFormComponent.prototype.dateFormat;
/** @type {?} */
DatepickerFormComponent.prototype.placeholder;
/** @type {?} */
DatepickerFormComponent.prototype.helpText;
/** @type {?} */
DatepickerFormComponent.prototype.icon;
/** @type {?} */
DatepickerFormComponent.prototype.iconPlacement;
/** @type {?} */
DatepickerFormComponent.prototype.placement;
/** @type {?} */
DatepickerFormComponent.prototype.showDelay;
/** @type {?} */
DatepickerFormComponent.prototype.hideDelay;
/** @type {?} */
DatepickerFormComponent.prototype.from;
/** @type {?} */
DatepickerFormComponent.prototype.to;
/** @type {?} */
DatepickerFormComponent.prototype.interval;
/** @type {?} */
DatepickerFormComponent.prototype.dueDateInterval;
/** @type {?} */
DatepickerFormComponent.prototype.onDateChange;
/** @type {?} */
DatepickerFormComponent.prototype.date;
/** @type {?} */
DatepickerFormComponent.prototype.visible;
/** @type {?} */
DatepickerFormComponent.prototype.presentDate;
/** @type {?} */
DatepickerFormComponent.prototype.isValid;
/** @type {?} */
DatepickerFormComponent.prototype.dateValidators;
/** @type {?} */
DatepickerFormComponent.prototype.onChanged;
/** @type {?} */
DatepickerFormComponent.prototype.onTouched;
/** @type {?} */
DatepickerFormComponent.prototype.validateDateRange;
/** @type {?} */
DatepickerFormComponent.prototype._elementHtmlRef;
/** @type {?} */
DatepickerFormComponent.prototype._elementHtmlCollection;
/** @type {?} */
DatepickerFormComponent.prototype.onDateSelectEvent;
/** @type {?} */
DatepickerFormComponent.prototype._elementRef;
/** @type {?} */
DatepickerFormComponent.prototype._viewContainerRef;
/** @type {?} */
DatepickerFormComponent.prototype.overlay;
/** @type {?} */
DatepickerFormComponent.prototype._ngZone;
/** @type {?} */
DatepickerFormComponent.prototype._scrollDispatcher;
/** @type {?} */
DatepickerFormComponent.prototype._componentFactoryResolver;
/** @type {?} */
DatepickerFormComponent.prototype._config;
/** @type {?} */
DatepickerFormComponent.prototype._dir;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci1mb3JtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BoeHVpL2FuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZGF0ZXBpY2tlci9kYXRlcGlja2VyLWZvcm0uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQVUsVUFBVSxFQUFnQixZQUFZLEVBQUUsVUFBVSxFQUN6RSxNQUFNLEVBQUUsd0JBQXdCLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxFQUN4RSxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsYUFBYSxFQUFvRCxNQUFNLGdCQUFnQixDQUFDO0FBQ3BILE9BQU8sRUFHcUIsT0FBTyxFQUNqQyxnQkFBZ0IsRUFDakIsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLFlBQVksQ0FBQztBQUNuQyxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUMzRCxPQUFPLEVBQUMsSUFBSSxFQUFFLFNBQVMsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQy9DLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUNqRCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQWlDckQsTUFBTSxPQUFPLHVCQUF1Qjs7Ozs7Ozs7Ozs7SUE0RWxDLFlBQW9CLFdBQXVCLEVBQ3ZCLGlCQUFtQyxFQUNwQyxPQUFnQixFQUNmLE9BQWUsRUFDZixpQkFBbUMsRUFDbkMseUJBQW1ELEVBQ25ELE9BQXlCLEVBQ2IsSUFBb0I7UUFQaEMsZ0JBQVcsR0FBWCxXQUFXLENBQVk7UUFDdkIsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFrQjtRQUNwQyxZQUFPLEdB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QWdCO1lBRGhCLGNBQWMsdUJBcUhQLFFBQVE7Ozt1QkE1RXBCLEtBQUs7dUJBR0wsS0FBSzt1QkFHTCxLQUFLO21DQUdMLEtBQUs7aUNBR0wsS0FBSzsrQkFHTCxLQUFLO3lCQUdMLEtBQUs7MEJBR0wsS0FBSzt1QkFHTCxLQUFLO21CQUdMLEtBQUs7NEJBR0wsS0FBSzt3QkFHTCxLQUFLO3dCQUdMLEtBQUs7d0JBR0wsS0FBSzttQkFHTCxLQUFLO2lCQUdMLEtBQUs7dUJBR0wsS0FBSzs4QkFHTCxLQUFLOzJCQUdMLE1BQU07Ozs7SUEzRFAsOENBQStCOztJQUMvQixvREFBOEM7O0lBQzlDLDBDQUFzRDs7SUFDdEQsNkNBQTRDOztJQUU1QywyQ0FDaUI7O0lBRWpCLDJDQUNpQjs7SUFFakIsMkNBQ2lCOztJQUVqQix1REFDNEI7O0lBRTVCLHFEQUMwQjs7SUFFMUIsbURBQ3dCOztJQUV4Qiw2Q0FDdUI7O0lBRXZCLDhDQUNxQjs7SUFFckIsMkNBQ2tDOztJQUVsQyx1Q0FDK0I7O0lBRS9CLGdEQUN3Qjs7SUFFeEIsNENBQzBEOztJQUUxRCw0Q0FDbUM7O0lBRW5DLDRDQUNtQzs7SUFFbkMsdUNBQ1U7O0lBRVYscUNBQ1E7O0lBRVIsMkNBQ2lCOztJQUVqQixrREFDNkI7O0lBRTdCLCtDQUM0RDs7SUFFNUQsdUNBQWtCOztJQUNsQiwwQ0FBdUI7O0lBQ3ZCLDhDQUF5Qjs7SUFDekIsMENBQXdCOztJQUN4QixpREFBNkQ7O0lBQzdELDRDQUF1RDs7SUFDdkQsNENBQTRDOztJQUU1QyxvREFBbUQ7O0lBQ25ELGtEQUFpQzs7SUFDakMseURBQStDOztJQWtFL0Msb0RBR0M7O0lBbkVXLDhDQUErQjs7SUFDL0Isb0RBQTJDOztJQUMzQywwQ0FBdUI7O0lBQ3ZCLDBDQUF1Qjs7SUFDdkIsb0RBQTJDOztJQUMzQyw0REFBMkQ7O0lBQzNELDBDQUFpQzs7SUFDakMsdUNBQXdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIE9uSW5pdCwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsXHJcbiAgT25EZXN0cm95LCBOZ1pvbmUsIENvbXBvbmVudEZhY3RvcnlSZXNvbHZlciwgVmlld0NvbnRhaW5lclJlZiwgT3B0aW9uYWwsIFZpZXdDaGlsZCwgQ29udGVudENoaWxkXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IE5HX1ZBTFVFX0FDQ0VTU09SLCBOR19WQUxJREFUT1JTLCBDb250cm9sVmFsdWVBY2Nlc3NvciwgVmFsaWRhdG9yLCBBYnN0cmFjdENvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7XHJcbiAgRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5LFxyXG4gIEhvcml6b250YWxDb25uZWN0aW9uUG9zLFxyXG4gIE9yaWdpbkNvbm5lY3Rpb25Qb3NpdGlvbiwgT3ZlcmxheSwgT3ZlcmxheUNvbm5lY3Rpb25Qb3NpdGlvbiwgT3ZlcmxheVJlZixcclxuICBTY3JvbGxEaXNwYXRjaGVyLCBWZXJ0aWNhbENvbm5lY3Rpb25Qb3NcclxufSBmcm9tICdAYW5ndWxhci9jZGsvb3ZlcmxheSc7XHJcbmltcG9ydCB7Q29tcG9uZW50UG9ydGFsfSBmcm9tICdAYW5ndWxhci9jZGsvcG9ydGFsJztcclxuaW1wb3J0IHtTdWJqZWN0fSBmcm9tICdyeGpzL2luZGV4JztcclxuaW1wb3J0IHtEYXRlcGlja2VyQ29tcG9uZW50fSBmcm9tICcuL2RhdGVwaWNrZXIuY29tcG9uZW50JztcclxuaW1wb3J0IHt0YWtlLCB0YWtlVW50aWx9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHtEaXJlY3Rpb25hbGl0eX0gZnJvbSAnQGFuZ3VsYXIvY2RrL2JpZGknO1xyXG5pbXBvcnQge0RhdGVwaWNrZXJDb25maWd9IGZyb20gJy4vZGF0ZXBpY2tlci5jb25maWcnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdoeGEtZGF0ZXBpY2tlci1pbnB1dCwgaHhhLWRhdGVwaWNrZXItZm9ybScsXHJcbiAgdGVtcGxhdGU6IGA8ZGl2IGNsYXNzPVwiaHgtaW5wdXQtZ3JvdXAgaHhhLWRhdGVwaWNrZXItZm9ybVwiPlxyXG4gIDxpIGNsYXNzPVwie3tpY29ufX1cIiAqbmdJZj1cImljb25QbGFjZW1lbnQgPT09ICdsZWZ0J1wiPjwvaT5cclxuICA8ZGl2IGNsYXNzPVwiaHgtaW5wdXQtY29udHJvbCBoeGEtZGF0ZXBpY2tlci1jb250cm9sXCIgW25nQ2xhc3NdPVwieydpcy1kYW5nZXInOiAhaXNWYWxpZCAmJiBkYXRlUGlja2VyRm9ybS50b3VjaGVkfVwiPlxyXG4gICAgPGlucHV0IGNsYXNzPVwiaHgtaW5wdXRcIiB0eXBlPVwidGV4dFwiICNkYXRlUGlja2VyRm9ybT1cIm5nTW9kZWxcIlxyXG4gICAgICBbcmVxdWlyZWRdPVwicmVxdWlyZWQgPyB0cnVlIDogbnVsbFwiXHJcbiAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXHJcbiAgICAgIFtyZWFkb25seV09XCJyZWFkb25seSA/IHRydWUgOiBudWxsXCJcclxuICAgICAgW25nTW9kZWxdPVwiZGF0ZSB8IGRhdGU6ZGF0ZUZvcm1hdFwiXHJcbiAgICAgIChjaGFuZ2UpPVwib25DaGFuZ2UoZGF0ZVBpY2tlckZvcm0udmFsdWUpXCJcclxuICAgICAgKGZvY3VzKT1cIm9uRm9jdXMoKVwiXHJcbiAgICAgIChrZXlkb3duLlRhYik9XCJvblRhYihkYXRlUGlja2VyRm9ybS52YWx1ZSlcIj5cclxuICAgIDxsYWJlbCBjbGFzcz1cImh4LWxhYmVsXCIgKm5nSWY9XCJwbGFjZWhvbGRlclwiPnt7cGxhY2Vob2xkZXJ9fSA8c3VwICpuZ0lmPVwicmVxdWlyZWRcIj4qPC9zdXA+PC9sYWJlbD5cclxuICAgIDxkaXYgY2xhc3M9XCJoeC1oZWxwXCI+e3toZWxwVGV4dH19PC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGkgY2xhc3M9XCJ7e2ljb259fVwiICpuZ0lmPVwiaWNvblBsYWNlbWVudCA9PT0gJ3JpZ2h0J1wiPjwvaT5cclxuPC9kaXY+XHJcbmAsXHJcbiAgc3R5bGVzOiBbYC5oeGEtZGF0ZXBpY2tlci1mb3Jte3Bvc2l0aW9uOnJlbGF0aXZlO21heC13aWR0aDoxOXJlbX0uaHhhLWRhdGVwaWNrZXItY29udHJvbHttYXJnaW46MH0uaHhhLWRhdGVwaWNrZXItY2FsZW5kYXJ7cG9zaXRpb246YWJzb2x1dGU7ei1pbmRleDo5OTtsZWZ0OjA7bWF4LXdpZHRoOjE5cmVtfS5oeGEtZGF0ZXBpY2tlci1jYWxlbmRhci10b3B7Ym90dG9tOjEwMCV9Lmh4YS1kYXRlcGlja2VyLWNhbGVuZGFyLWJvdHRvbXt0b3A6NzAlfS5oeGEtZGF0ZXBpY2tlci1jYWxlbmRhciBoeGEtZGF0ZXBpY2tlcnttYXgtd2lkdGg6MTlyZW19Lmh4YS1kYXRlcGlja2VyLWhlbHB7Zm9udC1zaXplOi43NXJlbTttYXJnaW4tdG9wOi4yNXJlbTtjb2xvcjojNjM2MDVmfS5oeGEtZGF0ZXBpY2tlci1mb3JtIGlucHV0W3JlYWRvbmx5XX4uaHgtbGFiZWx7dG9wOi0uNXJlbTtmb250LXNpemU6Ljc1cmVtO2NvbG9yOiM0MWI5ODd9aHhhLWRhdGVwaWNrZXJ7Ym9yZGVyOjFweCBzb2xpZCAjZDNkM2QzO21heC13aWR0aDoxOXJlbX1gXSxcclxuICBwcm92aWRlcnM6IFt7XHJcbiAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERhdGVwaWNrZXJGb3JtQ29tcG9uZW50KSxcclxuICAgIG11bHRpOiB0cnVlXHJcbiAgfSxcclxuICB7XHJcbiAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxyXG4gICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gRGF0ZXBpY2tlckZvcm1Db21wb25lbnQpLFxyXG4gICAgbXVsdGk6IHRydWUsXHJcbiAgfV1cclxufSlcclxuZXhwb3J0IGNsYXNzIERhdGVwaWNrZXJGb3JtQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciwgVmFsaWRhdG9yLCBPbkRlc3Ryb3kge1xyXG5cclxuICBfb3ZlcmxheVJlZjogT3ZlcmxheVJlZiB8IG51bGw7XHJcbiAgX2NhbGVuZGFySW5zdGFuY2U6IERhdGVwaWNrZXJDb21wb25lbnQgfCBudWxsO1xyXG4gIHByaXZhdGUgX3BvcnRhbDogQ29tcG9uZW50UG9ydGFsPERhdGVwaWNrZXJDb21wb25lbnQ+O1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3llZCA9IG5ldyBTdWJqZWN0KCk7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZGlzYWJsZWQgPSBmYWxzZTtcclxuXHJcbiAgQElucHV0KClcclxuICByZWFkb25seSA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIHJlcXVpcmVkID0gZmFsc2U7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZGVmYXVsdFRvUHJlc2VudERhdGUgPSB0cnVlO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGFsbG93UHJldmlvdXNEYXRlcyA9IHRydWU7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgYWxsb3dGdXR1cmVEYXRlcyA9IHRydWU7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZGF0ZUZvcm1hdCA9ICdkZC9NTS95JztcclxuXHJcbiAgQElucHV0KClcclxuICBwbGFjZWhvbGRlciA9ICdEYXRlJztcclxuXHJcbiAgQElucHV0KClcclxuICBoZWxwVGV4dCA9ICdQbGVhc2Ugc2VsZWN0IGEgZGF0ZSc7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgaWNvbiA9ICdoeC1pY29uIGljb24tY2FsZW5kYXInO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGljb25QbGFjZW1lbnQgPSAncmlnaHQnO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIHBsYWNlbWVudDogJ3RvcCcgfCAnYm90dG9tJyB8ICdsZWZ0JyB8ICdyaWdodCcgPSAnYm90dG9tJztcclxuXHJcbiAgQElucHV0KClcclxuICBzaG93RGVsYXkgPSB0aGlzLl9jb25maWcuc2hvd0RlbGF5O1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGhpZGVEZWxheSA9IHRoaXMuX2NvbmZpZy5oaWRlRGVsYXk7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZnJvbSA9ICcnO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIHRvID0gJyc7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgaW50ZXJ2YWwgPSBmYWxzZTtcclxuXHJcbiAgQElucHV0KClcclxuICBkdWVEYXRlSW50ZXJ2YWwgPSAnMCBkYXkocyknOyAvLyAnMSB3ZWVrKHMpJyB8ICcyIG1vbnRoKHMpJyB8ICczIHllYXIocyknXHJcblxyXG4gIEBPdXRwdXQoKVxyXG4gIG9uRGF0ZUNoYW5nZTogRXZlbnRFbWl0dGVyPERhdGU+ID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlPigpO1xyXG5cclxuICBwdWJsaWMgZGF0ZTogRGF0ZTtcclxuICBwdWJsaWMgdmlzaWJsZSA9IGZhbHNlO1xyXG4gIHB1YmxpYyBwcmVzZW50RGF0ZTogRGF0ZTtcclxuICBwdWJsaWMgaXNWYWxpZDogYm9vbGVhbjtcclxuICBwdWJsaWMgZGF0ZVZhbGlkYXRvcnMgPSBuZXcgQXJyYXk8KGRhdGU6IERhdGUpID0+IGJvb2xlYW4+KCk7XHJcbiAgcHJpdmF0ZSBvbkNoYW5nZWQgPSBuZXcgQXJyYXk8KHZhbHVlOiBEYXRlKSA9PiB2b2lkPigpO1xyXG4gIHByaXZhdGUgb25Ub3VjaGVkID0gbmV3IEFycmF5PCgpID0+IHZvaWQ+KCk7XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVEYXRlUmFuZ2U6IChkYXRlOiBEYXRlKSA9PiBib29sZWFuO1xyXG4gIHByaXZhdGUgX2VsZW1lbnRIdG1sUmVmOiBFbGVtZW50O1xyXG4gIHByaXZhdGUgX2VsZW1lbnRIdG1sQ29sbGVjdGlvbjogSFRNTENvbGxlY3Rpb247XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX2VsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXHJcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZixcclxuICAgICAgICAgICAgICBwdWJsaWMgb3ZlcmxheTogT3ZlcmxheSxcclxuICAgICAgICAgICAgICBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZSxcclxuICAgICAgICAgICAgICBwcml2YXRlIF9zY3JvbGxEaXNwYXRjaGVyOiBTY3JvbGxEaXNwYXRjaGVyLFxyXG4gICAgICAgICAgICAgIHByaXZhdGUgX2NvbXBvbmVudEZhY3RvcnlSZXNvbHZlcjogQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxyXG4gICAgICAgICAgICAgIHByaXZhdGUgX2NvbmZpZzogRGF0ZXBpY2tlckNvbmZpZyxcclxuICAgICAgICAgICAgICBAT3B0aW9uYWwoKSBwcml2YXRlIF9kaXI6IERpcmVjdGlvbmFsaXR5KSB7XHJcblxyXG4gICAgLy8gZ2V0IGlucHV0IHJlZmVyZW5jZVxyXG4gICAgdGhpcy5fZWxlbWVudEh0bWxDb2xsZWN0aW9uID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpbnB1dCcpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGlzcG9zZSB0aGUgdG9vbHRpcCB3aGVuIGRlc3Ryb3llZC5cclxuICAgKi9cclxuICBuZ09uRGVzdHJveSgpIHtcclxuICAgIGlmICh0aGlzLl9vdmVybGF5UmVmKSB7XHJcbiAgICAgIHRoaXMuX292ZXJsYXlSZWYuZGlzcG9zZSgpO1xyXG4gICAgICB0aGlzLl9jYWxlbmRhckluc3RhbmNlID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLl9kZXN0cm95ZWQubmV4dCgpO1xyXG4gICAgdGhpcy5fZGVzdHJveWVkLmNvbXBsZXRlKCk7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuXHJcbiAgICAvLyBzZXQgZWxlbWVudCByZWYgd2hpY2ggd2lsbCBiZSB1c2VkIGZvciBkcm9wZG93biBwb3NpdGlvbmluZ1xyXG4gICAgdGhpcy5fZWxlbWVudEh0bWxSZWYgPSB0aGlzLl9lbGVtZW50SHRtbENvbGxlY3Rpb24uaXRlbSgwKTtcclxuXHJcbiAgICBjb25zdCBkYXRlOiBEYXRlID0gbmV3IERhdGUoKTtcclxuICAgIHRoaXMucHJlc2VudERhdGUgPSBuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIGRhdGUuZ2V0TW9udGgoKSwgZGF0ZS5nZXREYXRlKCkpO1xyXG5cclxuICAgIGlmICh0aGlzLmRlZmF1bHRUb1ByZXNlbnREYXRlKSB7XHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMuc2V0RGF0ZSh0aGlzLnByZXNlbnREYXRlKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2xvc2UgdG8gdGhlIG1pbmltdW0gYW5kIG1heGl1bSBwb3NzaWJsZSBkYXRlcywgYnV0IHN0aWxsIG5vcm1hbGlzYWJsZVxyXG4gICAgLy8gaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNS4xLyNzZWMtMTUuOS4xLjFcclxuICAgIGNvbnN0IGZyb20gPSB0aGlzLnBhcnNlRGF0ZSh0aGlzLmZyb20pIHx8IG5ldyBEYXRlKC04NjMwMDAwMDAwMDAwMDAwKTtcclxuICAgIGNvbnN0IHRvID0gdGhpcy5wYXJzZURhdGUodGhpcy50bykgfHwgbmV3IERhdGUoODYzMDAwMDAwMDAwMDAwMCk7XHJcblxyXG4gICAgaWYgKCEhdGhpcy5mcm9tIHx8ICEhdGhpcy50bykge1xyXG4gICAgICB0aGlzLnZhbGlkYXRlRGF0ZVJhbmdlID0gdGhpcy5jcmVhdGVEYXRlUmFuZ2VWYWxpZGF0b3IoZnJvbSwgdG8pO1xyXG4gICAgICB0aGlzLmRhdGVWYWxpZGF0b3JzLnB1c2godGhpcy52YWxpZGF0ZURhdGVSYW5nZS5iaW5kKHRoaXMpKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIXRoaXMuYWxsb3dQcmV2aW91c0RhdGVzKSB7XHJcbiAgICAgIHRoaXMuZGF0ZVZhbGlkYXRvcnMucHVzaCh0aGlzLnZhbGlkYXRlSXNOb3RCZWZvcmVEYXRlLmJpbmQodGhpcykpO1xyXG4gICAgfVxyXG4gICAgaWYgKCF0aGlzLmFsbG93RnV0dXJlRGF0ZXMpIHtcclxuICAgICAgdGhpcy5kYXRlVmFsaWRhdG9ycy5wdXNoKHRoaXMudmFsaWRhdGVJc05vdEFmdGVyRGF0ZS5iaW5kKHRoaXMpKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBzZXREYXRlKGRhdGU6IERhdGUpOiB2b2lkIHtcclxuICAgIHRoaXMuZGF0ZSA9IGRhdGU7XHJcbiAgICB0aGlzLm9uRGF0ZUNoYW5nZS5lbWl0KGRhdGUpO1xyXG4gICAgdGhpcy5wcm9wb2dhdGVDaGFuZ2UoZGF0ZSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25EYXRlU2VsZWN0RXZlbnQgPSAoaW5wdXREYXRlOiBEYXRlKTogdm9pZCA9PiB7XHJcbiAgICB0aGlzLl9oaWRlKCk7XHJcbiAgICB0aGlzLnNldERhdGUoaW5wdXREYXRlKTtc