moh-common-lib
Version:
A library of Angular components, services, and styles for B.C. Government Ministry of Health (MoH).
389 lines • 32.3 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import * as tslib_1 from "tslib";
import { Component, Input, Output, EventEmitter, ViewChild, forwardRef } from '@angular/core';
import { NgxMyDatePickerDirective } from 'ngx-mydatepicker';
import { NgForm, ControlContainer, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Base } from '../../models/base';
/**
* Component NPM package dependencies:
* a) moment
*
* This component reports the following errors.
* required
* dayOutOfRange
* yearDistantPast
* yearDistantFuture
* noFutureDatesAllowed
* invalidValue
*
* These messages can be changed by updated messages using the errorMessages interface/
* Ex. { required: 'This field is required', invalidValue: '{label} is invalid' }
* @record
*/
export function DateErrorMsg() { }
if (false) {
/** @type {?|undefined} */
DateErrorMsg.prototype.required;
/** @type {?|undefined} */
DateErrorMsg.prototype.dayOutOfRange;
/** @type {?|undefined} */
DateErrorMsg.prototype.yearDistantPast;
/** @type {?|undefined} */
DateErrorMsg.prototype.yearDistantFuture;
/** @type {?|undefined} */
DateErrorMsg.prototype.noPastDatesAllowed;
/** @type {?|undefined} */
DateErrorMsg.prototype.noFutureDatesAllowed;
/** @type {?|undefined} */
DateErrorMsg.prototype.invalidValue;
}
/**
* PRIME datepicker component. Largely a wrapper for ngx-mydatepicker
* https://github.com/kekeh/ngx-mydatepicker
*
* NOTE - YOU MUST INCLUDE NGX-MYDATEPICKER IN YOUR PARENT APPLICATION TO USE
* THIS COMPONENT! This is due to some poor implementation in ngx-mydatepicker.
* Make sure to use the same version that this library uses.
*/
var DatepickerComponent = /** @class */ (function (_super) {
tslib_1.__extends(DatepickerComponent, _super);
function DatepickerComponent() {
var _this = _super.call(this) || this;
/**
* Component size can be reduced, see Datepickersizes for options
*/
_this.size = DatepickerSizes.DEFAULT;
_this.dateChange = new EventEmitter();
_this.required = false;
/**
* Control visibility of the clear 'x' button on the mini datepicker.
*
* **'visible'** is default, button exists
*
* **'none'** means the element does not exist
*
* **'invisible'** means the element takes up space but is not visible / cannot be
* used.
*
* Invisible is useful when you want to make sure a datepicker is the same
* size as a visible one.
*/
_this.clearButton = 'visible';
/**
* Format for how to display the date to the user.
*/
_this.dateFormat = 'yyyy/mm/dd';
// Make enum accessible in HTML
_this.DatepickerSizes = DatepickerSizes;
_this._onChange = (/**
* @param {?} _
* @return {?}
*/
function (_) { });
_this._onTouched = (/**
* @return {?}
*/
function () { });
return _this;
}
/**
* @param {?} date
* @return {?}
*/
DatepickerComponent.prototype.convertDateToSimpleDate = /**
* @param {?} date
* @return {?}
*/
function (date) {
if (date === null || date === undefined) {
return null;
}
return {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
};
};
/**
* @param {?} date
* @return {?}
*/
DatepickerComponent.prototype.convertSimpleDateToDate = /**
* @param {?} date
* @return {?}
*/
function (date) {
// When ngx-mydatepicker is cleared, it returns {year: 0, month: 0, day: 0}
if (date.year === 0) {
return null;
}
return new Date(date.year, date.month - 1, date.day);
};
/**
* @param {?} x
* @return {?}
*/
DatepickerComponent.prototype.isDate = /**
* @param {?} x
* @return {?}
*/
function (x) {
if (!x) {
return false;
}
return x.getDate !== undefined;
};
/**
* @return {?}
*/
DatepickerComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
if (!this.errorMessages) {
this.errorMessages = {
required: this.labelText + ' is required.',
dayOutOfRange: 'Invalid ' + this.labelText + '.',
yearDistantPast: 'Invalid ' + this.labelText + '.',
yearDistantFuture: 'Invalid ' + this.labelText + '.',
noFutureDatesAllowed: 'Invalid ' + this.labelText + '.',
invalidValue: 'Invalid ' + this.labelText + '.'
};
}
this.datepickerOptions = {
dateFormat: this.dateFormat,
sunHighlight: false,
appendSelectorToBody: true,
};
if (this.size === DatepickerSizes.MINI) {
// Set width/height to 4/5 of default
this.datepickerOptions.selectorHeight = '185px';
this.datepickerOptions.selectorWidth = '201px';
}
if (this.isDate(this.disableSince)) {
this.datepickerOptions.disableSince = this.convertDateToSimpleDate(this.disableSince);
}
if (this.isDate(this.disableUntil)) {
this.datepickerOptions.disableUntil = this.convertDateToSimpleDate(this.disableSince);
}
if (this.onlyFutureDates) {
/** @type {?} */
var today = new Date();
this.datepickerOptions.disableUntil = this.convertDateToSimpleDate(today);
}
if (this.date) {
// Even if jsdate winds up being undefined, even defining this.model will
// set the input as non-empty and it'll satisfy the 'required' validation.
// So, we only add the model if there's actual data.
this.model = {
jsdate: this.date
};
}
};
/**
* @param {?} changes
* @return {?}
*/
DatepickerComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
// Parent component has passed in null, so we have to manually clear the input. This leads to 2 change detection cycles.
// We could refactor it down to one, but the performance hit is minimal for such a simple component.
if (this.date === null) {
this.clearDate();
this._onChange(null);
this._onTouched();
}
};
/**
* @param {?} event
* @return {?}
*/
DatepickerComponent.prototype.onDateChanged = /**
* @param {?} event
* @return {?}
*/
function (event) {
if (event.jsdate || event.jsdate === null) {
// Always emit a Date (or null)
this.dateChange.emit(event.jsdate);
this._onChange(event.jsdate);
this._onTouched();
}
};
/**
* @return {?}
*/
DatepickerComponent.prototype.clearDate = /**
* @return {?}
*/
function () {
if (this.ngxdp) {
// We don't need to emit here, because by changing date we'll trigger onDateChanged automatically.
this.date = null;
this.ngxdp.clearDate();
}
};
/**
* @param {?} fn
* @return {?}
*/
DatepickerComponent.prototype.registerOnChange = /**
* @param {?} fn
* @return {?}
*/
function (fn) {
this._onChange = fn;
};
/**
* @param {?} fn
* @return {?}
*/
DatepickerComponent.prototype.registerOnTouched = /**
* @param {?} fn
* @return {?}
*/
function (fn) {
this._onTouched = fn;
};
/**
* @param {?} obj
* @return {?}
*/
DatepickerComponent.prototype.writeValue = /**
* @param {?} obj
* @return {?}
*/
function (obj) {
this.model = {
jsdate: obj
};
};
DatepickerComponent.decorators = [
{ type: Component, args: [{
selector: 'common-datepicker',
template: "<div>\r\n <label><span>{{labelText}}</span>\r\n <div class=\"input-group\">\r\n\r\n <input class=\"form-control\" placeholder=\"YYYY/MM/DD\"\r\n ngx-mydatepicker name=\"datepicker-{{labelText}}-{{objectId}}\"\r\n [(ngModel)]=\"model\"\r\n [options]=\"datepickerOptions\"\r\n #dp=\"ngx-mydatepicker\"\r\n #dateEl='ngModel'\r\n (dateChanged)=\"onDateChanged($event)\"\r\n [required]='required'\r\n [disabled]=\"disabled\"\r\n autocomplete=\"off\"/>\r\n\r\n <span class=\"input-group-append float-label-append\">\r\n <button type=\"button\" class=\"btn btn-default\" (click)=\"dp.toggleCalendar()\">\r\n <i class=\"fa fa-calendar\"></i>\r\n </button>\r\n </span>\r\n </div>\r\n </label>\r\n</div>\r\n\r\n<!-- InvalidDateFormat comes from ngxmydatepicker, so we have a little less control over it. -->\r\n<div *ngIf=\"!disabled && dateEl.touched\"\r\n role=\"alert\"\r\n class='error-container'\r\n aria-live=\"assertive\">\r\n <div class=\"text-danger\"\r\n *ngIf=\"(dateEl?.errors?.required) && errorMessages?.required && !dateEl?.errors?.invalidDateFormat\">\r\n {{errorMessages.required}}\r\n </div>\r\n <!-- ngx-mydatepicker has it's own errors and we can't easily add our own, so we have reduced error messages. -->\r\n <!-- <div class=\"text-danger\"\r\n *ngIf=\"dateEl?.errors?.dayOutOfRange && errorMessages?.dayOutOfRange\">\r\n {{errorMessages.dayOutOfRange}}\r\n </div>\r\n <div class=\"text-danger\"\r\n *ngIf=\"dateEl?.errors?.yearDistantPast && errorMessages?.yearDistantPast\">\r\n {{errorMessages.yearDistantPast}}\r\n </div>\r\n <div class=\"text-danger\"\r\n *ngIf=\"dateEl?.errors?.yearDistantFuture && errorMessages?.yearDistantFuture\">\r\n {{errorMessages.yearDistantFuture}}\r\n </div>\r\n <div class=\"text-danger\"\r\n *ngIf=\"dateEl?.errors?.noPastDatesAllowed && errorMessages?.noPastDatesAllowed\">\r\n {{errorMessages.noPastDatesAllowed}}\r\n </div>\r\n\r\n <div class=\"text-danger\"\r\n *ngIf=\"dateEl?.errors?.noFutureDatesAllowed && errorMessages?.noFutureDatesAllowed\">\r\n {{errorMessages.noFutureDatesAllowed}}\r\n </div> -->\r\n <div class=\"text-danger\"\r\n *ngIf=\"(dateEl?.errors?.invalidValue || dateEl?.errors?.invalidDateFormat) && errorMessages?.invalidValue\">\r\n {{errorMessages.invalidValue}}\r\n </div>\r\n</div>\r\n",
/* Re-use the same ngForm that it's parent is using. The component will show
* up in its parents `this.form`, and will auto-update `this.form.valid`
*/
viewProviders: [{ provide: ControlContainer, useExisting: forwardRef((/**
* @return {?}
*/
function () { return NgForm; })) }],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef((/**
* @return {?}
*/
function () { return DatepickerComponent; }))
}
],
styles: [".datepicker--mini{display:flex;flex-wrap:nowrap}.datepicker--mini:not(.hide-clear)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.datepicker--mini .input-group-append .btn{padding:0 .5rem}.input-group-append{z-index:0}.float-label-append{margin-bottom:calc(.5rem + 2px)}.has-float-label{flex-basis:calc(100% - 36px)}input::-ms-clear{display:none}"]
}] }
];
/** @nocollapse */
DatepickerComponent.ctorParameters = function () { return []; };
DatepickerComponent.propDecorators = {
size: [{ type: Input }],
date: [{ type: Input }],
dateChange: [{ type: Output }],
disabled: [{ type: Input }],
labelText: [{ type: Input }],
required: [{ type: Input }],
disableUntil: [{ type: Input }],
disableSince: [{ type: Input }],
onlyFutureDates: [{ type: Input }],
clearButton: [{ type: Input }],
dateFormat: [{ type: Input }],
errorMessages: [{ type: Input }],
ngxdp: [{ type: ViewChild, args: ['dp',] }]
};
return DatepickerComponent;
}(Base));
export { DatepickerComponent };
if (false) {
/**
* Component size can be reduced, see Datepickersizes for options
* @type {?}
*/
DatepickerComponent.prototype.size;
/** @type {?} */
DatepickerComponent.prototype.date;
/** @type {?} */
DatepickerComponent.prototype.dateChange;
/** @type {?} */
DatepickerComponent.prototype.disabled;
/** @type {?} */
DatepickerComponent.prototype.labelText;
/** @type {?} */
DatepickerComponent.prototype.required;
/**
* Dates **before** disableUntil will not be valid selections. Maps to a ngx-mydatepicker option, but we convert IMyDate to Date
* @type {?}
*/
DatepickerComponent.prototype.disableUntil;
/**
* Dates **after** disableSince will not be valid selections. Maps to a ngx-mydatepicker option, but we convert IMyDate to Date
* @type {?}
*/
DatepickerComponent.prototype.disableSince;
/**
* Equivalent to setting disableBefore to tomorrow.
* @type {?}
*/
DatepickerComponent.prototype.onlyFutureDates;
/**
* Control visibility of the clear 'x' button on the mini datepicker.
*
* **'visible'** is default, button exists
*
* **'none'** means the element does not exist
*
* **'invisible'** means the element takes up space but is not visible / cannot be
* used.
*
* Invisible is useful when you want to make sure a datepicker is the same
* size as a visible one.
* @type {?}
*/
DatepickerComponent.prototype.clearButton;
/**
* Format for how to display the date to the user.
* @type {?}
*/
DatepickerComponent.prototype.dateFormat;
/** @type {?} */
DatepickerComponent.prototype.errorMessages;
/**
* Datetime model used to interface with ngx-datepicker.
* @type {?}
*/
DatepickerComponent.prototype.model;
/** @type {?} */
DatepickerComponent.prototype.DatepickerSizes;
/** @type {?} */
DatepickerComponent.prototype.ngxdp;
/**
* Default options for wrapped ngx-datepicker.
* @type {?}
*/
DatepickerComponent.prototype.datepickerOptions;
/** @type {?} */
DatepickerComponent.prototype._onChange;
/** @type {?} */
DatepickerComponent.prototype._onTouched;
}
/** @enum {string} */
var DatepickerSizes = {
MINI: 'mini',
DEFAULT: 'default',
};
export { DatepickerSizes };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9tb2gtY29tbW9uLWxpYi8iLCJzb3VyY2VzIjpbImxpYi9jb21wb25lbnRzL2RhdGVwaWNrZXIvZGF0ZXBpY2tlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFpQixTQUFTLEVBQWEsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hJLE9BQU8sRUFBNEIsd0JBQXdCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN0RixPQUFPLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixFQUFFLGlCQUFpQixFQUF3QixNQUFNLGdCQUFnQixDQUFDO0FBQ25HLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFrQnpDLGtDQVFDOzs7SUFQQyxnQ0FBa0I7O0lBQ2xCLHFDQUF1Qjs7SUFDdkIsdUNBQXlCOztJQUN6Qix5Q0FBMkI7O0lBQzNCLDBDQUE0Qjs7SUFDNUIsNENBQThCOztJQUM5QixvQ0FBc0I7Ozs7Ozs7Ozs7QUFZeEI7SUFnQnlDLCtDQUFJO0lBeUQzQztRQUFBLFlBQ0UsaUJBQU8sU0FDUDs7OztRQXpETyxVQUFJLEdBQW9CLGVBQWUsQ0FBQyxPQUFPLENBQUM7UUFFL0MsZ0JBQVUsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBSXZDLGNBQVEsR0FBWSxLQUFLLENBQUM7Ozs7Ozs7Ozs7Ozs7O1FBeUIxQixpQkFBVyxHQUFxQyxTQUFTLENBQUM7Ozs7UUFLMUQsZ0JBQVUsR0FBVyxZQUFZLENBQUM7O1FBUzNDLHFCQUFlLEdBQTJCLGVBQWUsQ0FBQztRQU9uRCxlQUFTOzs7O1FBQUcsVUFBQyxDQUFNLElBQU0sQ0FBQyxFQUFDO1FBQzNCLGdCQUFVOzs7UUFBRyxjQUFPLENBQUMsRUFBQzs7SUFJNUIsQ0FBQzs7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QUFrQzs7SUFDbEMseUNBQTZCOzs7O0lBMEg3QixNQUFPLE1BQU07SUFDYixTQUFVLFNBQVMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBTaW1wbGVDaGFuZ2VzLCBWaWV3Q2hpbGQsIE9uQ2hhbmdlcywgZm9yd2FyZFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBJTmd4TXlEcE9wdGlvbnMsIElNeURhdGUsIE5neE15RGF0ZVBpY2tlckRpcmVjdGl2ZSB9IGZyb20gJ25neC1teWRhdGVwaWNrZXInO1xyXG5pbXBvcnQgeyBOZ0Zvcm0sIENvbnRyb2xDb250YWluZXIsIE5HX1ZBTFVFX0FDQ0VTU09SLCBDb250cm9sVmFsdWVBY2Nlc3NvciB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgQmFzZSB9IGZyb20gJy4uLy4uL21vZGVscy9iYXNlJztcclxuXHJcbi8qKlxyXG4gKiBDb21wb25lbnQgTlBNIHBhY2thZ2UgZGVwZW5kZW5jaWVzOlxyXG4gKiBhKSBtb21lbnRcclxuICpcclxuICogVGhpcyBjb21wb25lbnQgcmVwb3J0cyB0aGUgZm9sbG93aW5nIGVycm9ycy5cclxuICogICAgcmVxdWlyZWRcclxuICogICAgZGF5T3V0T2ZSYW5nZVxyXG4gKiAgICB5ZWFyRGlzdGFudFBhc3RcclxuICogICAgeWVhckRpc3RhbnRGdXR1cmVcclxuICogICAgbm9GdXR1cmVEYXRlc0FsbG93ZWRcclxuICogICAgaW52YWxpZFZhbHVlXHJcbiAqXHJcbiAqICBUaGVzZSBtZXNzYWdlcyBjYW4gYmUgY2hhbmdlZCBieSB1cGRhdGVkIG1lc3NhZ2VzIHVzaW5nIHRoZSBlcnJvck1lc3NhZ2VzIGludGVyZmFjZS9cclxuICogIEV4LiB7IHJlcXVpcmVkOiAnVGhpcyBmaWVsZCBpcyByZXF1aXJlZCcsIGludmFsaWRWYWx1ZTogJ3tsYWJlbH0gaXMgaW52YWxpZCcgfVxyXG4gKi9cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgRGF0ZUVycm9yTXNnIHsgLy8gVE9ETzogUmVtb3ZlIC0gcG9zc2libGUgYnJlYWtpbmcgY2hhbmdlIC0gY3VycmVudGx5IGRhdGVwaWNrZXIgdXNlcyBpdFxyXG4gIHJlcXVpcmVkPzogc3RyaW5nO1xyXG4gIGRheU91dE9mUmFuZ2U/OiBzdHJpbmc7XHJcbiAgeWVhckRpc3RhbnRQYXN0Pzogc3RyaW5nO1xyXG4gIHllYXJEaXN0YW50RnV0dXJlPzogc3RyaW5nO1xyXG4gIG5vUGFzdERhdGVzQWxsb3dlZD86IHN0cmluZztcclxuICBub0Z1dHVyZURhdGVzQWxsb3dlZD86IHN0cmluZztcclxuICBpbnZhbGlkVmFsdWU/OiBzdHJpbmc7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogUFJJTUUgZGF0ZXBpY2tlciBjb21wb25lbnQuIExhcmdlbHkgYSB3cmFwcGVyIGZvciBuZ3gtbXlkYXRlcGlja2VyXHJcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9rZWtlaC9uZ3gtbXlkYXRlcGlja2VyXHJcbiAqXHJcbiAqIE5PVEUgLSBZT1UgTVVTVCBJTkNMVURFIE5HWC1NWURBVEVQSUNLRVIgSU4gWU9VUiBQQVJFTlQgQVBQTElDQVRJT04gVE8gVVNFXHJcbiAqIFRISVMgQ09NUE9ORU5UISAgVGhpcyBpcyBkdWUgdG8gc29tZSBwb29yIGltcGxlbWVudGF0aW9uIGluIG5neC1teWRhdGVwaWNrZXIuXHJcbiAqIE1ha2Ugc3VyZSB0byB1c2UgdGhlIHNhbWUgdmVyc2lvbiB0aGF0IHRoaXMgbGlicmFyeSB1c2VzLlxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdjb21tb24tZGF0ZXBpY2tlcicsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2RhdGVwaWNrZXIuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2RhdGVwaWNrZXIuY29tcG9uZW50LnNjc3MnXSxcclxuICAvKiBSZS11c2UgdGhlIHNhbWUgbmdGb3JtIHRoYXQgaXQncyBwYXJlbnQgaXMgdXNpbmcuIFRoZSBjb21wb25lbnQgd2lsbCBzaG93XHJcbiAgICogdXAgaW4gaXRzIHBhcmVudHMgYHRoaXMuZm9ybWAsIGFuZCB3aWxsIGF1dG8tdXBkYXRlIGB0aGlzLmZvcm0udmFsaWRgXHJcbiAgICovXHJcbiAgdmlld1Byb3ZpZGVyczogWyB7IHByb3ZpZGU6IENvbnRyb2xDb250YWluZXIsIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE5nRm9ybSApIH0gXSxcclxuICBwcm92aWRlcnM6IFtcclxuICAgIHtcclxuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXHJcbiAgICAgIG11bHRpOiB0cnVlLFxyXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBEYXRlcGlja2VyQ29tcG9uZW50KVxyXG4gICAgfVxyXG4gIF1cclxufSlcclxuZXhwb3J0IGNsYXNzIERhdGVwaWNrZXJDb21wb25lbnQgZXh0ZW5kcyBCYXNlIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcclxuICAvKiogQ29tcG9uZW50IHNpemUgY2FuIGJlIHJlZHVjZWQsIHNlZSBEYXRlcGlja2Vyc2l6ZXMgZm9yIG9wdGlvbnMgKi9cclxuICBASW5wdXQoKSBzaXplOiBEYXRlcGlja2VyU2l6ZXMgPSBEYXRlcGlja2VyU2l6ZXMuREVGQVVMVDtcclxuICBASW5wdXQoKSBkYXRlOiBEYXRlO1xyXG4gIEBPdXRwdXQoKSBkYXRlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlPigpO1xyXG4gIEBJbnB1dCgpIGRpc2FibGVkOiBib29sZWFuO1xyXG4gIEBJbnB1dCgpIGxhYmVsVGV4dDogc3RyaW5nO1xyXG5cclxuICBASW5wdXQoKSByZXF1aXJlZDogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuXHJcbiAgLyoqIERhdGVzICoqYmVmb3JlKiogZGlzYWJsZVVudGlsIHdpbGwgbm90IGJlIHZhbGlkIHNlbGVjdGlvbnMuICBNYXBzIHRvIGEgbmd4LW15ZGF0ZXBpY2tlciBvcHRpb24sIGJ1dCB3ZSBjb252ZXJ0IElNeURhdGUgdG8gRGF0ZSAgKi9cclxuICBASW5wdXQoKSBkaXNhYmxlVW50aWw6IERhdGU7XHJcblxyXG4gIC8qKiBEYXRlcyAqKmFmdGVyKiogZGlzYWJsZVNpbmNlIHdpbGwgbm90IGJlIHZhbGlkIHNlbGVjdGlvbnMuICBNYXBzIHRvIGEgbmd4LW15ZGF0ZXBpY2tlciBvcHRpb24sIGJ1dCB3ZSBjb252ZXJ0IElNeURhdGUgdG8gRGF0ZSAqL1xyXG4gIEBJbnB1dCgpIGRpc2FibGVTaW5jZTogRGF0ZTtcclxuXHJcbiAgLyoqIEVxdWl2YWxlbnQgdG8gc2V0dGluZyBkaXNhYmxlQmVmb3JlIHRvIHRvbW9ycm93LiAqL1xyXG4gIEBJbnB1dCgpIG9ubHlGdXR1cmVEYXRlczogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogQ29udHJvbCB2aXNpYmlsaXR5IG9mIHRoZSBjbGVhciAneCcgYnV0dG9uIG9uIHRoZSBtaW5pIGRhdGVwaWNrZXIuXHJcbiAgICpcclxuICAgKiAqKid2aXNpYmxlJyoqIGlzIGRlZmF1bHQsIGJ1dHRvbiBleGlzdHNcclxuICAgKlxyXG4gICAqICoqJ25vbmUnKiogbWVhbnMgdGhlIGVsZW1lbnQgZG9lcyBub3QgZXhpc3RcclxuICAgKlxyXG4gICAqICoqJ2ludmlzaWJsZScqKiBtZWFucyB0aGUgZWxlbWVudCB0YWtlcyB1cCBzcGFjZSBidXQgaXMgbm90IHZpc2libGUgLyBjYW5ub3QgYmVcclxuICAgKiB1c2VkLlxyXG4gICAqXHJcbiAgICogSW52aXNpYmxlIGlzIHVzZWZ1bCB3aGVuIHlvdSB3YW50IHRvIG1ha2Ugc3VyZSBhIGRhdGVwaWNrZXIgaXMgdGhlIHNhbWVcclxuICAgKiBzaXplIGFzIGEgdmlzaWJsZSBvbmUuXHJcbiAgICovXHJcbiAgQElucHV0KCkgY2xlYXJCdXR0b246ICd2aXNpYmxlJyB8ICdpbnZpc2libGUnIHwgJ25vbmUnID0gJ3Zpc2libGUnO1xyXG5cclxuXHJcblxyXG4gIC8qKiBGb3JtYXQgZm9yIGhvdyB0byBkaXNwbGF5IHRoZSBkYXRlIHRvIHRoZSB1c2VyLiAqL1xyXG4gIEBJbnB1dCgpIGRhdGVGb3JtYXQ6IHN0cmluZyA9ICd5eXl5L21tL2RkJztcclxuXHJcbiAgQElucHV0KCkgZXJyb3JNZXNzYWdlczogRGF0ZUVycm9yTXNnO1xyXG5cclxuICAvKiogRGF0ZXRpbWUgbW9kZWwgdXNlZCB0byBpbnRlcmZhY2Ugd2l0aCBuZ3gtZGF0ZXBpY2tlci4gKi9cclxuICAvLyBtb2RlbDogYW55O1xyXG4gIG1vZGVsOiBhbnk7XHJcblxyXG4gIC8vIE1ha2UgZW51bSBhY2Nlc3NpYmxlIGluIEhUTUxcclxuICBEYXRlcGlja2VyU2l6ZXM6IHR5cGVvZiBEYXRlcGlja2VyU2l6ZXMgPSBEYXRlcGlja2VyU2l6ZXM7XHJcblxyXG4gIEBWaWV3Q2hpbGQoJ2RwJykgbmd4ZHA6IE5neE15RGF0ZVBpY2tlckRpcmVjdGl2ZTtcclxuXHJcbiAgLyoqIERlZmF1bHQgb3B0aW9ucyBmb3Igd3JhcHBlZCBuZ3gtZGF0ZXBpY2tlci4gKi9cclxuICBkYXRlcGlja2VyT3B0aW9uczogSU5neE15RHBPcHRpb25zO1xyXG5cclxuICBwdWJsaWMgX29uQ2hhbmdlID0gKF86IGFueSkgPT4ge307XHJcbiAgcHVibGljIF9vblRvdWNoZWQgPSAoKSA9PiB7fTtcclxuXHJcbiAgY29uc3RydWN0b3IoKSB7XHJcbiAgICBzdXBlcigpO1xyXG4gICB9XHJcblxyXG4gIGNvbnZlcnREYXRlVG9TaW1wbGVEYXRlKGRhdGU6IERhdGUpOiBJTXlEYXRlIHtcclxuICAgIGlmIChkYXRlID09PSBudWxsIHx8IGRhdGUgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgeWVhcjogZGF0ZS5nZXRGdWxsWWVhcigpLFxyXG4gICAgICBtb250aDogZGF0ZS5nZXRNb250aCgpICsgMSxcclxuICAgICAgZGF5OiBkYXRlLmdldERhdGUoKSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBjb252ZXJ0U2ltcGxlRGF0ZVRvRGF0ZShkYXRlOiBJTXlEYXRlKTogRGF0ZSB7XHJcbiAgICAvLyBXaGVuIG5neC1teWRhdGVwaWNrZXIgaXMgY2xlYXJlZCwgaXQgcmV0dXJucyB7eWVhcjogMCwgbW9udGg6IDAsIGRheTogMH1cclxuICAgIGlmIChkYXRlLnllYXIgPT09IDApIHtcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbmV3IERhdGUoZGF0ZS55ZWFyLCBkYXRlLm1vbnRoIC0gMSwgZGF0ZS5kYXkpO1xyXG4gIH1cclxuXHJcbiAgaXNEYXRlKHg6IGFueSk6IHggaXMgRGF0ZSB7XHJcbiAgICBpZiAoIXgpIHsgcmV0dXJuIGZhbHNlOyB9XHJcbiAgICByZXR1cm4geC5nZXREYXRlICE9PSB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIGlmICghdGhpcy5lcnJvck1lc3NhZ2VzKSB7XHJcbiAgICAgIHRoaXMuZXJyb3JNZXNzYWdlcyA9IHtcclxuICAgICAgICByZXF1aXJlZDogdGhpcy5sYWJlbFRleHQgKyAnIGlzIHJlcXVpcmVkLicsXHJcbiAgICAgICAgZGF5T3V0T2ZSYW5nZTogJ0ludmFsaWQgJyArIHRoaXMubGFiZWxUZXh0ICsgJy4nLFxyXG4gICAgICAgIHllYXJEaXN0YW50UGFzdDogJ0ludmFsaWQgJyArIHRoaXMubGFiZWxUZXh0ICsgJy4nLFxyXG4gICAgICAgIHllYXJEaXN0YW50RnV0dXJlOiAnSW52YWxpZCAnICsgdGhpcy5sYWJlbFRleHQgKyAnLicsXHJcbiAgICAgICAgbm9GdXR1cmVEYXRlc0FsbG93ZWQ6ICdJbnZhbGlkICcgKyB0aGlzLmxhYmVsVGV4dCArICcuJyxcclxuICAgICAgICBpbnZhbGlkVmFsdWU6ICdJbnZhbGlkICcgKyB0aGlzLmxhYmVsVGV4dCArICcuJ1xyXG4gICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuZGF0ZXBpY2tlck9wdGlvbnMgPSB7XHJcbiAgICAgIGRhdGVGb3JtYXQ6IHRoaXMuZGF0ZUZvcm1hdCxcclxuICAgICAgc3VuSGlnaGxpZ2h0OiBmYWxzZSxcclxuICAgICAgYXBwZW5kU2VsZWN0b3JUb0JvZHk6IHRydWUsXHJcbiAgICB9O1xyXG5cclxuICAgIGlmICh0aGlzLnNpemUgPT09IERhdGVwaWNrZXJTaXplcy5NSU5JKSB7XHJcbiAgICAgIC8vIFNldCB3aWR0aC9oZWlnaHQgdG8gNC81IG9mIGRlZmF1bHRcclxuICAgICAgdGhpcy5kYXRlcGlja2VyT3B0aW9ucy5zZWxlY3RvckhlaWdodCA9ICcxODVweCc7XHJcbiAgICAgIHRoaXMuZGF0ZXBpY2tlck9wdGlvbnMuc2VsZWN0b3JXaWR0aCA9ICcyMDFweCc7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuaXNEYXRlKHRoaXMuZGlzYWJsZVNpbmNlKSkge1xyXG4gICAgICB0aGlzLmRhdGVwaWNrZXJPcHRpb25zLmRpc2FibGVTaW5jZSA9IHRoaXMuY29udmVydERhdGVUb1NpbXBsZURhdGUodGhpcy5kaXNhYmxlU2luY2UpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmlzRGF0ZSh0aGlzLmRpc2FibGVVbnRpbCkpIHtcclxuICAgICAgdGhpcy5kYXRlcGlja2VyT3B0aW9ucy5kaXNhYmxlVW50aWwgPSB0aGlzLmNvbnZlcnREYXRlVG9TaW1wbGVEYXRlKHRoaXMuZGlzYWJsZVNpbmNlKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5vbmx5RnV0dXJlRGF0ZXMpIHtcclxuICAgICAgY29uc3QgdG9kYXkgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICB0aGlzLmRhdGVwaWNrZXJPcHRpb25zLmRpc2FibGVVbnRpbCA9IHRoaXMuY29udmVydERhdGVUb1NpbXBsZURhdGUodG9kYXkpO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICBpZiAodGhpcy5kYXRlKSB7XHJcbiAgICAgIC8vIEV2ZW4gaWYganNkYXRlIHdpbmRzIHVwIGJlaW5nIHVuZGVmaW5lZCwgZXZlbiBkZWZpbmluZyB0aGlzLm1vZGVsIHdpbGxcclxuICAgICAgLy8gc2V0IHRoZSBpbnB1dCBhcyBub24tZW1wdHkgYW5kIGl0J2xsIHNhdGlzZnkgdGhlICdyZXF1aXJlZCcgdmFsaWRhdGlvbi5cclxuICAgICAgLy8gU28sIHdlIG9ubHkgYWRkIHRoZSBtb2RlbCBpZiB0aGVyZSdzIGFjdHVhbCBkYXRhLlxyXG4gICAgICB0aGlzLm1vZGVsID0ge1xyXG4gICAgICAgIGpzZGF0ZTogdGhpcy5kYXRlXHJcbiAgICAgIH07XHJcbiAgICB9XHJcblxyXG5cclxuICB9XHJcblxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XHJcbiAgICAvLyBQYXJlbnQgY29tcG9uZW50IGhhcyBwYXNzZWQgaW4gbnVsbCwgc28gd2UgaGF2ZSB0byBtYW51YWxseSBjbGVhciB0aGUgaW5wdXQuIFRoaXMgbGVhZHMgdG8gMiBjaGFuZ2UgZGV0ZWN0aW9uIGN5Y2xlcy5cclxuICAgIC8vIFdlIGNvdWxkIHJlZmFjdG9yIGl0IGRvd24gdG8gb25lLCBidXQgdGhlIHBlcmZvcm1hbmNlIGhpdCBpcyBtaW5pbWFsIGZvciBzdWNoIGEgc2ltcGxlIGNvbXBvbmVudC5cclxuICAgIGlmICh0aGlzLmRhdGUgPT09IG51bGwpIHtcclxuICAgICAgdGhpcy5jbGVhckRhdGUoKTtcclxuICAgICAgdGhpcy5fb25DaGFuZ2UobnVsbCk7XHJcbiAgICAgIHRoaXMuX29uVG91Y2hlZCgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25EYXRlQ2hhbmdlZChldmVudCk6IHZvaWQge1xyXG4gICAgaWYgKGV2ZW50LmpzZGF0ZSB8fCBldmVudC5qc2RhdGUgPT09IG51bGwpIHtcclxuICAgICAgLy8gQWx3YXlzIGVtaXQgYSBEYXRlIChvciBudWxsKVxyXG4gICAgICB0aGlzLmRhdGVDaGFuZ2UuZW1pdChldmVudC5qc2RhdGUpO1xyXG4gICAgICB0aGlzLl9vbkNoYW5nZShldmVudC5qc2RhdGUpO1xyXG4gICAgICB0aGlzLl9vblRvdWNoZWQoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNsZWFyRGF0ZSgpIHtcclxuICAgIGlmICh0aGlzLm5neGRwKSB7XHJcbiAgICAgIC8vIFdlIGRvbid0IG5lZWQgdG8gZW1pdCBoZXJlLCBiZWNhdXNlIGJ5IGNoYW5naW5nIGRhdGUgd2UnbGwgdHJpZ2dlciBvbkRhdGVDaGFuZ2VkIGF1dG9tYXRpY2FsbHkuXHJcbiAgICAgIHRoaXMuZGF0ZSA9IG51bGw7XHJcbiAgICAgIHRoaXMubmd4ZHAuY2xlYXJEYXRlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMuX29uQ2hhbmdlID0gZm47XHJcbiAgfVxyXG5cclxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLl9vblRvdWNoZWQgPSBmbjtcclxuICB9XHJcblxyXG4gIHdyaXRlVmFsdWUob2JqOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMubW9kZWwgPSB7XHJcbiAgICAgIGpzZGF0ZTogb2JqXHJcbiAgICB9O1xyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGVudW0gRGF0ZXBpY2tlclNpemVzIHtcclxuICBNSU5JID0gJ21pbmknLFxyXG4gIERFRkFVTFQgPSAnZGVmYXVsdCdcclxufVxyXG4iXX0=