UNPKG

moh-common-lib

Version:

A library of Angular components, services, and styles for B.C. Government Ministry of Health (MoH).

236 lines 22.2 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, Input, Output, EventEmitter, HostListener, forwardRef } from '@angular/core'; import { Base } from '../../models/base'; import { ControlContainer, NgForm } from '@angular/forms'; import * as zxcvbn_ from 'zxcvbn'; // Awkward necessary workaround due to bug in build tools // https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207 /** @type {?} */ const zxcvbn = zxcvbn_; /** * Interface for passing in error messages * Example: * errorMessages = { * required: this.componentLabel + ' is required.', * minLength: this.componentLabel + ' must be ' + this.minLen + ' characters.', * criteria: this.componentLabel + ' does not meet password criteria.' * } * @record */ export function PasswordErrorMsg() { } if (false) { /** @type {?|undefined} */ PasswordErrorMsg.prototype.required; /** @type {?|undefined} */ PasswordErrorMsg.prototype.minLength; /** @type {?|undefined} */ PasswordErrorMsg.prototype.criteria; } /** * PasswordComponent is a text input for a user's password. It includes: * * - A password strength bar * - Minimum length validations * * Note - if your application has requirements to check things like username is not * present in password, we recommend doing this in the (passwordChange) callback. * * \@example * <common-password componentLabel="{{newPwdLabel}}" * [showPasswordStrength]="true" * [minLen]="pwdMinLen" * [pwdCriteria]="pwdValidChars" * [password]="data.password" * (passwordChange)="setNewPassword($event)"></common-password> * * @export */ export class PasswordComponent extends Base { constructor() { super(); // Inputs for the component this.label = 'Password'; this.isRequired = true; this.isDisabled = false; this.minLen = '8'; this.maxLen = '32'; this.showPasswordStrength = false; this.objectID = 'password_' + this.objectId; // Output from the component this.passwordChange = new EventEmitter(); this.blurEvent = new EventEmitter(); // Flag for the fa-eye to show or hide password this.hideValue = true; this.strengthPercentage = 0; // default messages this.requiredMsgSeg = ' is required.'; this.minLenMsgSeg1 = ' must be at least '; this.minLenMsgSeg2 = ' characters in length.'; this.criteriaMsg = ' contains invalid characters.'; } /** * @return {?} */ ngOnInit() { // Set default messages this.errMsg = { required: this.label + this.requiredMsgSeg, minLength: this.label + this.minLenMsgSeg1 + this.minLen + this.minLenMsgSeg2, criteria: this.label + this.criteriaMsg }; // Replace default message if provided if (this.errorMessages) { if (this.errorMessages.required) { this.errMsg.required = this.errorMessages.required; } if (this.errorMessages.minLength) { this.errMsg.minLength = this.errorMessages.minLength; } if (this.errorMessages.criteria) { this.errMsg.criteria = this.errorMessages.criteria; } } } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (changes.password && this.password) { // Check strength of password this.pswdStrength = this.getPasswordStrength(this.password); this.strengthPercentage = ((this.pswdStrength + 1) / 5) * 100; } } /** * Passes the value entered back to the calling component * @param {?} password value the was entered by * @return {?} */ setPassword(password) { this.passwordChange.emit(password); } /** * @param {?} $event * @return {?} */ onInputBlur($event) { this.blurEvent.emit(event); } // Prevent user from pasting data into the text box /** * @param {?} event * @return {?} */ onPaste(event) { return false; } /** * Get the strength of the password * 0 = too guessable: risky password. (guesses < 10^3) * 1 = very guessable: protection from throttled online attacks. (guesses < 10^6) * 2 = somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8) * 3 = safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10) * 4 = very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10) * * https://github.com/dropbox/zxcvbn * @private * @param {?} password * @return {?} */ getPasswordStrength(password) { // Password strength feedback /** @type {?} */ const pswdFeedback = zxcvbn(password); return pswdFeedback.score; } } PasswordComponent.decorators = [ { type: Component, args: [{ selector: 'common-password', template: "<label class=\"control-label\" for=\"{{objectID}}\">{{label}}</label>\r\n<input #pswdRef=\"ngModel\"\r\n type=\"{{hideValue? 'password': 'text'}}\"\r\n class=\"form-control password-field\"\r\n name=\"{{objectID}}\"\r\n id=\"{{objectID}}\"\r\n [ngModel]=\"password\"\r\n (ngModelChange)=\"setPassword($event)\"\r\n (blur)=\"onInputBlur($event)\"\r\n [pattern]=\"pwdCriteria\"\r\n [required]=\"isRequired\"\r\n [minlength]=\"minLen\"\r\n [maxlength]=\"maxLen\"\r\n [disabled]=\"isDisabled\"\r\n autocomplete=\"off\"/>\r\n<span class=\"fa fa-fw {{hideValue? 'fa-eye' : 'fa-eye-slash'}} password-field-icon\"\r\n (click)='hideValue = !hideValue'></span>\r\n<div *ngIf='password && showPasswordStrength'>\r\n<!-- The progress bar -->\r\n <div class=\"progress password-strength-bar\" >\r\n <div class=\"progress-bar {{pswdStrength >= 4? 'bg-success' : (pswdStrength >= 3? 'bg-warning' : 'bg-danger')}}\"\r\n role=\"progressbar\"\r\n [style.width]='strengthPercentage + \"%\"'\r\n [attr.aria-valuenow]=\"strengthPercentage\"\r\n aria-valuemin=\"0\"\r\n aria-valuemax=\"100\">\r\n </div>\r\n </div>\r\n <span class=\"password-progress-label {{pswdStrength >= 4? 'text-success' : (pswdStrength >= 3? 'text-warning' : 'text-danger')}}\"></span>\r\n</div>\r\n<!-- Error messages for component -->\r\n<div *ngIf=\"!pswdRef.disabled && (pswdRef.touched || pswdRef.dirty)\"\r\n role=\"alert\"\r\n class='error-container'\r\n aria-live=\"assertive\">\r\n <div class=\"text-danger\" *ngIf=\"pswdRef?.errors?.required\">\r\n {{errMsg.required}}\r\n </div>\r\n <div class=\"text-danger\" *ngIf=\"pswdRef?.errors?.minlength\">\r\n {{errMsg.minLength}}\r\n </div>\r\n <div class=\"text-danger\" *ngIf=\"pswdRef?.errors?.pattern && !pswdRef?.errors?.minlength\">\r\n {{errMsg.criteria}}\r\n </div>\r\n</div>\r\n\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 {?} */ () => NgForm)) }], styles: [".password-field-icon{float:right;margin-left:-25px;margin-top:-25px;margin-right:.5rem;position:relative;z-index:2}.password-field{padding-right:2rem}.password-strength-bar{min-width:0;max-width:75%;height:.5rem;margin-top:1em}.password-progress-label{float:right;margin-left:-15px;margin-top:-15px;position:relative;z-index:2}.password-strength-bar+.text-success::after{content:'Good'}.password-strength-bar+.text-warning::after{content:'OK'}.password-strength-bar+.text-danger::after{content:'Bad'}input{width:100%}input[type=password]::-ms-clear,input[type=password]::-ms-reveal{display:none}"] }] } ]; /** @nocollapse */ PasswordComponent.ctorParameters = () => []; PasswordComponent.propDecorators = { label: [{ type: Input }], isRequired: [{ type: Input }], isDisabled: [{ type: Input }], password: [{ type: Input }], pwdCriteria: [{ type: Input }], minLen: [{ type: Input }], maxLen: [{ type: Input }], errorMessages: [{ type: Input }], showPasswordStrength: [{ type: Input }], objectID: [{ type: Input }], passwordChange: [{ type: Output }], blurEvent: [{ type: Output }], onPaste: [{ type: HostListener, args: ['document:paste', ['$event'],] }] }; if (false) { /** @type {?} */ PasswordComponent.prototype.label; /** @type {?} */ PasswordComponent.prototype.isRequired; /** @type {?} */ PasswordComponent.prototype.isDisabled; /** @type {?} */ PasswordComponent.prototype.password; /** @type {?} */ PasswordComponent.prototype.pwdCriteria; /** @type {?} */ PasswordComponent.prototype.minLen; /** @type {?} */ PasswordComponent.prototype.maxLen; /** @type {?} */ PasswordComponent.prototype.errorMessages; /** @type {?} */ PasswordComponent.prototype.showPasswordStrength; /** @type {?} */ PasswordComponent.prototype.objectID; /** @type {?} */ PasswordComponent.prototype.passwordChange; /** @type {?} */ PasswordComponent.prototype.blurEvent; /** @type {?} */ PasswordComponent.prototype.hideValue; /** @type {?} */ PasswordComponent.prototype.pswdStrength; /** @type {?} */ PasswordComponent.prototype.strengthPercentage; /** @type {?} */ PasswordComponent.prototype.errMsg; /** * @type {?} * @private */ PasswordComponent.prototype.requiredMsgSeg; /** * @type {?} * @private */ PasswordComponent.prototype.minLenMsgSeg1; /** * @type {?} * @private */ PasswordComponent.prototype.minLenMsgSeg2; /** * @type {?} * @private */ PasswordComponent.prototype.criteriaMsg; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFzc3dvcmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbW9oLWNvbW1vbi1saWIvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9wYXNzd29yZC9wYXNzd29yZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVUsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFhLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwSCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDekMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzFELE9BQU8sS0FBSyxPQUFPLE1BQU0sUUFBUSxDQUFDOzs7O01BRzVCLE1BQU0sR0FBRyxPQUFPOzs7Ozs7Ozs7OztBQWV0QixzQ0FJQzs7O0lBSEMsb0NBQWtCOztJQUNsQixxQ0FBbUI7O0lBQ25CLG9DQUFrQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBOEJwQixNQUFNLE9BQU8saUJBQWtCLFNBQVEsSUFBSTtJQWlDekM7UUFDRSxLQUFLLEVBQUUsQ0FBQzs7UUEvQkQsVUFBSyxHQUFXLFVBQVUsQ0FBQztRQUMzQixlQUFVLEdBQVksSUFBSSxDQUFDO1FBQzNCLGVBQVUsR0FBWSxLQUFLLENBQUM7UUFHNUIsV0FBTSxHQUFZLEdBQUcsQ0FBQztRQUN0QixXQUFNLEdBQVksSUFBSSxDQUFDO1FBRXZCLHlCQUFvQixHQUFZLEtBQUssQ0FBQztRQUN0QyxhQUFRLEdBQVcsV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7O1FBSTlDLG1CQUFjLEdBQXlCLElBQUksWUFBWSxFQUFVLENBQUM7UUFDbEUsY0FBUyxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7O1FBR2xDLGNBQVMsR0FBRyxJQUFJLENBQUM7UUFFakIsdUJBQWtCLEdBQUcsQ0FBQyxDQUFDOztRQUt0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Q0FBMEI7O0lBQzFCLHdDQUFzQzs7SUFDdEMsbUNBQStCOztJQUMvQixtQ0FBZ0M7O0lBQ2hDLDBDQUF5Qzs7SUFDekMsaURBQStDOztJQUMvQyxxQ0FBd0Q7O0lBSXhELDJDQUE0RTs7SUFDNUUsc0NBQXlDOztJQUd6QyxzQ0FBd0I7O0lBQ3hCLHlDQUE0Qjs7SUFDNUIsK0NBQThCOztJQUU5QixtQ0FBZ0M7Ozs7O0lBR2hDLDJDQUFpRDs7Ozs7SUFDakQsMENBQXFEOzs7OztJQUNyRCwwQ0FBeUQ7Ozs7O0lBQ3pELHdDQUE4RCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIEhvc3RMaXN0ZW5lciwgT25DaGFuZ2VzLCBmb3J3YXJkUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEJhc2UgfSBmcm9tICcuLi8uLi9tb2RlbHMvYmFzZSc7XHJcbmltcG9ydCB7IENvbnRyb2xDb250YWluZXIsIE5nRm9ybSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0ICogYXMgenhjdmJuXyBmcm9tICd6eGN2Ym4nO1xyXG4vLyBBd2t3YXJkIG5lY2Vzc2FyeSB3b3JrYXJvdW5kIGR1ZSB0byBidWcgaW4gYnVpbGQgdG9vbHNcclxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2p2YW5kZW1vL2dlbmVyYXRvci1hbmd1bGFyMi1saWJyYXJ5L2lzc3Vlcy8yMjEjaXNzdWVjb21tZW50LTM1NTk0NTIwN1xyXG5jb25zdCB6eGN2Ym4gPSB6eGN2Ym5fO1xyXG5cclxuXHJcbi8qKlxyXG4gKiBUT0RPOiAgQ29udmVydCB0byBjdXN0b20gZm9ybSBjb250cm9sIC0gcmVtb3ZlIG5nRm9ybVxyXG4gKi9cclxuLyoqXHJcbiAqIEludGVyZmFjZSBmb3IgcGFzc2luZyBpbiBlcnJvciBtZXNzYWdlc1xyXG4gKiBFeGFtcGxlOlxyXG4gKiAgZXJyb3JNZXNzYWdlcyA9IHtcclxuICogICAgICAgcmVxdWlyZWQ6IHRoaXMuY29tcG9uZW50TGFiZWwgKyAnIGlzIHJlcXVpcmVkLicsXHJcbiAqICAgICAgIG1pbkxlbmd0aDogdGhpcy5jb21wb25lbnRMYWJlbCArICcgbXVzdCBiZSAnICsgdGhpcy5taW5MZW4gKyAnIGNoYXJhY3RlcnMuJyxcclxuICogICAgICAgY3JpdGVyaWE6IHRoaXMuY29tcG9uZW50TGFiZWwgKyAnIGRvZXMgbm90IG1lZXQgcGFzc3dvcmQgY3JpdGVyaWEuJ1xyXG4gKiAgICAgfVxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBQYXNzd29yZEVycm9yTXNnIHtcclxuICByZXF1aXJlZD86IHN0cmluZztcclxuICBtaW5MZW5ndGg/OiBzdHJpbmc7XHJcbiAgY3JpdGVyaWE/OiBzdHJpbmc7XHJcbn1cclxuLyoqXHJcbiAqIFBhc3N3b3JkQ29tcG9uZW50IGlzIGEgdGV4dCBpbnB1dCBmb3IgYSB1c2VyJ3MgcGFzc3dvcmQuIEl0IGluY2x1ZGVzOlxyXG4gKlxyXG4gKiAtIEEgcGFzc3dvcmQgc3RyZW5ndGggYmFyXHJcbiAqIC0gTWluaW11bSBsZW5ndGggdmFsaWRhdGlvbnNcclxuICpcclxuICogTm90ZSAtIGlmIHlvdXIgYXBwbGljYXRpb24gaGFzIHJlcXVpcmVtZW50cyB0byBjaGVjayB0aGluZ3MgbGlrZSB1c2VybmFtZSBpcyBub3RcclxuICogcHJlc2VudCBpbiBwYXNzd29yZCwgd2UgcmVjb21tZW5kIGRvaW5nIHRoaXMgaW4gdGhlIChwYXNzd29yZENoYW5nZSkgY2FsbGJhY2suXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqICAgICAgIDxjb21tb24tcGFzc3dvcmQgY29tcG9uZW50TGFiZWw9XCJ7e25ld1B3ZExhYmVsfX1cIlxyXG4gKiAgICAgICAgICAgICAgICAgICAgICBbc2hvd1Bhc3N3b3JkU3RyZW5ndGhdPVwidHJ1ZVwiXHJcbiAqICAgICAgICAgICAgICAgICAgICAgIFttaW5MZW5dPVwicHdkTWluTGVuXCJcclxuICogICAgICAgICAgICAgICAgICAgICAgW3B3ZENyaXRlcmlhXT1cInB3ZFZhbGlkQ2hhcnNcIlxyXG4gKiAgICAgICAgICAgICAgICAgICAgICBbcGFzc3dvcmRdPVwiZGF0YS5wYXNzd29yZFwiXHJcbiAqICAgICAgICAgICAgICAgICAgICAgIChwYXNzd29yZENoYW5nZSk9XCJzZXROZXdQYXNzd29yZCgkZXZlbnQpXCI+PC9jb21tb24tcGFzc3dvcmQ+XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnY29tbW9uLXBhc3N3b3JkJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vcGFzc3dvcmQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3Bhc3N3b3JkLmNvbXBvbmVudC5zY3NzJ10sXHJcbiAgLyogUmUtdXNlIHRoZSBzYW1lIG5nRm9ybSB0aGF0IGl0J3MgcGFyZW50IGlzIHVzaW5nLiBUaGUgY29tcG9uZW50IHdpbGwgc2hvd1xyXG4gICAqIHVwIGluIGl0cyBwYXJlbnRzIGB0aGlzLmZvcm1gLCBhbmQgd2lsbCBhdXRvLXVwZGF0ZSBgdGhpcy5mb3JtLnZhbGlkYFxyXG4gICAqL1xyXG4gIHZpZXdQcm92aWRlcnM6IFsgeyBwcm92aWRlOiBDb250cm9sQ29udGFpbmVyLCB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBOZ0Zvcm0gKSB9IF1cclxufSlcclxuZXhwb3J0IGNsYXNzIFBhc3N3b3JkQ29tcG9uZW50IGV4dGVuZHMgQmFzZSBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcclxuXHJcbiAgLy8gSW5wdXRzIGZvciB0aGUgY29tcG9uZW50XHJcbiAgQElucHV0KCkgbGFiZWw6IHN0cmluZyA9ICdQYXNzd29yZCc7XHJcbiAgQElucHV0KCkgaXNSZXF1aXJlZDogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KCkgaXNEaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHBhc3N3b3JkOiBzdHJpbmc7XHJcbiAgQElucHV0KCkgcHdkQ3JpdGVyaWE6IHN0cmluZyB8IFJlZ0V4cDtcclxuICBASW5wdXQoKSBtaW5MZW46IHN0cmluZyAgPSAnOCc7XHJcbiAgQElucHV0KCkgbWF4TGVuOiBzdHJpbmcgID0gJzMyJztcclxuICBASW5wdXQoKSBlcnJvck1lc3NhZ2VzOiBQYXNzd29yZEVycm9yTXNnO1xyXG4gIEBJbnB1dCgpIHNob3dQYXNzd29yZFN0cmVuZ3RoOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgb2JqZWN0SUQ6IHN0cmluZyA9ICdwYXNzd29yZF8nICsgdGhpcy5vYmplY3RJZDtcclxuXHJcblxyXG4gIC8vIE91dHB1dCBmcm9tIHRoZSBjb21wb25lbnRcclxuICBAT3V0cHV0KCkgcGFzc3dvcmRDaGFuZ2U6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XHJcbiAgQE91dHB1dCgpIGJsdXJFdmVudCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuXHJcbiAgLy8gRmxhZyBmb3IgdGhlIGZhLWV5ZSB0byBzaG93IG9yIGhpZGUgcGFzc3dvcmRcclxuICBwdWJsaWMgaGlkZVZhbHVlID0gdHJ1ZTtcclxuICBwdWJsaWMgcHN3ZFN0cmVuZ3RoOiBudW1iZXI7XHJcbiAgcHVibGljIHN0cmVuZ3RoUGVyY2VudGFnZSA9IDA7XHJcblxyXG4gIHB1YmxpYyBlcnJNc2c6IFBhc3N3b3JkRXJyb3JNc2c7XHJcblxyXG4gIC8vIGRlZmF1bHQgbWVzc2FnZXNcclxuICBwcml2YXRlIHJlcXVpcmVkTXNnU2VnOiBzdHJpbmcgPSAnIGlzIHJlcXVpcmVkLic7XHJcbiAgcHJpdmF0ZSBtaW5MZW5Nc2dTZWcxOiBzdHJpbmcgPSAnIG11c3QgYmUgYXQgbGVhc3QgJztcclxuICBwcml2YXRlIG1pbkxlbk1zZ1NlZzI6IHN0cmluZyA9ICcgY2hhcmFjdGVycyBpbiBsZW5ndGguJztcclxuICBwcml2YXRlIGNyaXRlcmlhTXNnOiBzdHJpbmcgPSAnIGNvbnRhaW5zIGludmFsaWQgY2hhcmFjdGVycy4nO1xyXG5cclxuXHJcbiAgY29uc3RydWN0b3IoKSB7XHJcbiAgICBzdXBlcigpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcblxyXG4gICAgLy8gU2V0IGRlZmF1bHQgbWVzc2FnZXNcclxuICAgIHRoaXMuZXJyTXNnID0gICAge1xyXG4gICAgICByZXF1aXJlZDogdGhpcy5sYWJlbCArIHRoaXMucmVxdWlyZWRNc2dTZWcsXHJcbiAgICAgIG1pbkxlbmd0aDogdGhpcy5sYWJlbCArIHRoaXMubWluTGVuTXNnU2VnMSArIHRoaXMubWluTGVuICsgdGhpcy5taW5MZW5Nc2dTZWcyLFxyXG4gICAgICBjcml0ZXJpYTogdGhpcy5sYWJlbCArIHRoaXMuY3JpdGVyaWFNc2dcclxuICAgIH07XHJcblxyXG4gICAgLy8gUmVwbGFjZSBkZWZhdWx0IG1lc3NhZ2UgaWYgcHJvdmlkZWRcclxuICAgIGlmICggdGhpcy5lcnJvck1lc3NhZ2VzICkge1xyXG5cclxuICAgICAgaWYgKCB0aGlzLmVycm9yTWVzc2FnZXMucmVxdWlyZWQgKSB7XHJcbiAgICAgICAgdGhpcy5lcnJNc2cucmVxdWlyZWQgPSB0aGlzLmVycm9yTWVzc2FnZXMucmVxdWlyZWQ7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICggdGhpcy5lcnJvck1lc3NhZ2VzLm1pbkxlbmd0aCApIHtcclxuICAgICAgICB0aGlzLmVyck1zZy5taW5MZW5ndGggPSB0aGlzLmVycm9yTWVzc2FnZXMubWluTGVuZ3RoO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoIHRoaXMuZXJyb3JNZXNzYWdlcy5jcml0ZXJpYSApIHtcclxuICAgICAgICB0aGlzLmVyck1zZy5jcml0ZXJpYSA9IHRoaXMuZXJyb3JNZXNzYWdlcy5jcml0ZXJpYTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlcykge1xyXG4gICAgaWYgKGNoYW5nZXMucGFzc3dvcmQgJiYgdGhpcy5wYXNzd29yZCkge1xyXG5cclxuICAgICAgLy8gQ2hlY2sgc3RyZW5ndGggb2YgcGFzc3dvcmRcclxuICAgICAgdGhpcy5wc3dkU3RyZW5ndGggPSB0aGlzLmdldFBhc3N3b3JkU3RyZW5ndGgoIHRoaXMucGFzc3dvcmQgKTtcclxuICAgICAgdGhpcy5zdHJlbmd0aFBlcmNlbnRhZ2UgPSAoKHRoaXMucHN3ZFN0cmVuZ3RoICsgMSkgLyA1ICkgKiAxMDA7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQYXNzZXMgdGhlIHZhbHVlIGVudGVyZWQgYmFjayB0byB0aGUgY2FsbGluZyBjb21wb25lbnRcclxuICAgKiBAcGFyYW0gcGFzc3dvcmQgdmFsdWUgdGhlIHdhcyBlbnRlcmVkIGJ5XHJcbiAgICovXHJcbiAgc2V0UGFzc3dvcmQoIHBhc3N3b3JkOiBzdHJpbmcgKSB7XHJcbiAgICB0aGlzLnBhc3N3b3JkQ2hhbmdlLmVtaXQoIHBhc3N3b3JkICk7XHJcbiAgfVxyXG5cclxuICBvbklucHV0Qmx1cigkZXZlbnQpIHtcclxuICAgIHRoaXMuYmx1ckV2ZW50LmVtaXQoIGV2ZW50ICk7XHJcbiAgfVxyXG5cclxuICAvLyBQcmV2ZW50IHVzZXIgZnJvbSBwYXN0aW5nIGRhdGEgaW50byB0aGUgdGV4dCBib3hcclxuICBASG9zdExpc3RlbmVyKCAnZG9jdW1lbnQ6cGFzdGUnLCBbJyRldmVudCddIClcclxuICBvblBhc3RlKCBldmVudCApIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IHRoZSBzdHJlbmd0aCBvZiB0aGUgcGFzc3dvcmRcclxuXHJcbiAgICogICAgMCA9IHRvbyBndWVzc2FibGU6IHJpc2t5IHBhc3N3b3JkLiAoZ3Vlc3NlcyA8IDEwXjMpXHJcbiAgICogICAgMSA9IHZlcnkgZ3Vlc3NhYmxlOiBwcm90ZWN0aW9uIGZyb20gdGhyb3R0bGVkIG9ubGluZSBhdHRhY2tzLiAoZ3Vlc3NlcyA8IDEwXjYpXHJcbiAgICogICAgMiA9IHNvbWV3aGF0IGd1ZXNzYWJsZTogcHJvdGVjdGlvbiBmcm9tIHVudGhyb3R0bGVkIG9ubGluZSBhdHRhY2tzLiAoZ3Vlc3NlcyA8IDEwXjgpXHJcbiAgICogICAgMyA9IHNhZmVseSB1bmd1ZXNzYWJsZTogbW9kZXJhdGUgcHJvdGVjdGlvbiBmcm9tIG9mZmxpbmUgc2xvdy1oYXNoIHNjZW5hcmlvLiAoZ3Vlc3NlcyA8IDEwXjEwKVxyXG4gICAqICAgIDQgPSB2ZXJ5IHVuZ3Vlc3NhYmxlOiBzdHJvbmcgcHJvdGVjdGlvbiBmcm9tIG9mZmxpbmUgc2xvdy1oYXNoIHNjZW5hcmlvLiAoZ3Vlc3NlcyA+PSAxMF4xMClcclxuICAgKlxyXG4gICAqICBodHRwczovL2dpdGh1Yi5jb20vZHJvcGJveC96eGN2Ym5cclxuICAgKi9cclxuICBwcml2YXRlIGdldFBhc3N3b3JkU3RyZW5ndGgoIHBhc3N3b3JkOiBzdHJpbmcgKTogbnVtYmVyIHtcclxuICAgIC8vIFBhc3N3b3JkIHN0cmVuZ3RoIGZlZWRiYWNrXHJcbiAgICBjb25zdCBwc3dkRmVlZGJhY2sgPSB6eGN2Ym4oIHBhc3N3b3JkICk7XHJcbiAgICByZXR1cm4gcHN3ZEZlZWRiYWNrLnNjb3JlO1xyXG4gIH1cclxufVxyXG4iXX0=