UNPKG

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
/** * @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=