moh-common-lib
Version:
A library of Angular components, services, and styles for B.C. Government Ministry of Health (MoH).
289 lines • 23.8 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, Input, ChangeDetectorRef, Output, EventEmitter, Optional, Self } from '@angular/core';
import { Subject, of } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap, catchError } from 'rxjs/operators';
import { Base } from '../../models/base';
import { GeocoderService } from '../../services/geocoder.service';
import { CANADA } from '../country/country.component';
import { BRITISH_COLUMBIA } from '../province/province.component';
import { Address } from '../../models/address.model';
import { NgControl } from '@angular/forms';
/**
* @deprecated Please use `address-validator` component instead.
*
* For TemplateForms, pass in an Address and recieve an Address
* \@example
* <common-geocoder-input
* label='Physical Address'
* [(ngModel)]="myAddress">
* </common-geocoder-input>
*
* \@note
* For ReactiveForms, pass in a string and recieve a string. If you need the
* Address object you can use (select) in addition.
*
* \@example
* <common-geocoder-input
* label='Physical Address'
* formControlName="address"
* (select)="getAddressObject($event)">
* </common-geocoder-input>
*/
export class GeocoderInputComponent extends Base {
/**
* @param {?} controlDir
* @param {?} geocoderService
* @param {?} cd
*/
constructor(controlDir, geocoderService, cd) {
super();
this.controlDir = controlDir;
this.geocoderService = geocoderService;
this.cd = cd;
this.label = 'Address Lookup';
this.addressChange = new EventEmitter();
this.select = new EventEmitter();
this.maxlength = '255';
/**
* Is the Geocoder API request still in progress?
*/
this.isTypeaheadLoading = false;
/**
* Geocoder API has returned and has no results, an empty array.
*/
this.hasNoResults = false;
this.hasError = false;
/**
* Similar to this.address, but we can null it when user is searching for new addresses
*/
this.selectedAddress = false;
// Result from GeoCoderService address lookup
/**
* The subject that triggers on user text input and gets typeaheadList$ to update.
*/
this.searchText$ = new Subject();
this._onChange = (/**
* @param {?} _
* @return {?}
*/
(_) => { });
this._onTouched = (/**
* @param {?=} _
* @return {?}
*/
(_) => { });
if (controlDir) {
controlDir.valueAccessor = this;
}
}
/**
* @return {?}
*/
ngOnInit() {
this.typeaheadList$ = this.searchText$.pipe(debounceTime(500), distinctUntilChanged(),
// Trigger the network request, get results
switchMap((/**
* @param {?} searchPhrase
* @return {?}
*/
searchPhrase => this.geocoderService.lookup(searchPhrase))), catchError((/**
* @param {?} err
* @return {?}
*/
err => this.onError(err))));
}
/**
* @param {?} err
* @return {?}
*/
onError(err) {
this.hasError = true;
// Empty array simulates no result response, nothing for typeahead to iterate over
return of([]);
}
/**
* @param {?} val
* @return {?}
*/
onLoading(val) {
this.isTypeaheadLoading = val;
}
// Note - this will fire after an onError as well
/**
* @param {?} val
* @return {?}
*/
onNoResults(val) {
// If we have results, the error has resolved (e.g. network has re-connected)
if (val === false) {
this.hasError = false;
}
this.hasNoResults = val;
}
/**
* @param {?} event
* @return {?}
*/
onSelect(event) {
/** @type {?} */
const data = event.item;
// Output string to FormControl. If street is more than the max length shorten
/** @type {?} */
const stripped = this.stripStringToMaxLength(data.street);
/** @type {?} */
const addr = new Address();
addr.city = data.city;
// GeoCoder is only for BC, Canada, values can be set.
addr.country = CANADA; // Default country is Canda
addr.province = BRITISH_COLUMBIA; // Default province is BC
addr.street = stripped;
// Save and emit Address for (select)
this.selectedAddress = true;
this.select.emit(addr);
this._onChange(stripped);
}
/**
* @param {?} event
* @return {?}
*/
onKeyUp(event) {
// Filter out 'enter' and other similar keyboard events that can trigger
// when user is selecting a typeahead option instead of entering new text.
// Without this filter, we do another HTTP request + force disiplay the UI
// for now reason
if (event.keyCode === 13 || event.keyCode === 9) { // enter & tab
return;
}
// Clear out selection
this.selectedAddress = false;
this.searchText$.next(this.search);
}
/**
* @param {?} event
* @return {?}
*/
onBlur(event) {
this._onTouched();
this._onChange(this.search);
}
/**
* @param {?} value
* @return {?}
*/
writeValue(value) {
if (value !== undefined) {
this.search = value;
}
}
// Register change function
/**
* @param {?} fn
* @return {?}
*/
registerOnChange(fn) {
this._onChange = fn;
}
// Register touched function
/**
* @param {?} fn
* @return {?}
*/
registerOnTouched(fn) {
this._onTouched = fn;
}
/**
* @private
* @param {?} str
* @return {?}
*/
stripStringToMaxLength(str) {
/** @type {?} */
const maxlength = parseInt(this.maxlength, 10);
return str.slice(0, maxlength);
}
}
GeocoderInputComponent.decorators = [
{ type: Component, args: [{
selector: 'common-geocoder-input',
template: "\r\n<label for=\"geocoder_{{label}}\" class='text-nowrap'>{{label}}\r\n <span class=\"geocoder-status\">\r\n <ng-container *ngIf=\"isTypeaheadLoading; else statusContainer\"> — Loading\r\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\r\n </ng-container>\r\n </span>\r\n\r\n <ng-template #statusContainer>\r\n <ng-template *ngIf=\"selectedAddress; then addressSelected; else error;\"></ng-template>\r\n </ng-template>\r\n</label>\r\n<input class=\"form-control\"\r\n type=\"text\"\r\n id=\"geocoder_{{label}}\"\r\n name=\"geocoder_{{label}}\"\r\n [(ngModel)]='search'\r\n (keyup)='onKeyUp($event)'\r\n [typeahead]='typeaheadList$'\r\n [typeaheadIsFirstItemActive]=\"false\"\r\n [typeaheadSelectFirstItem]=\"false\"\r\n (typeaheadLoading)=\"onLoading($event)\"\r\n (typeaheadOnSelect)=\"onSelect($event)\"\r\n (typeaheadNoResults)=\"onNoResults($event)\"\r\n (blur)=\"onBlur($event)\"\r\n [attr.maxlength]='maxlength'\r\n typeaheadOptionField='fullAddress'\r\n typeaheadMinLength='3'\r\n autocomplete=\"off\"\r\n spellcheck=\"false\"\r\n />\r\n <!-- Intentionally using 'nope' for autocomplete as it is invalid and forces false - https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion -->\r\n\r\n\r\n<ng-template #addressSelected>\r\n <span> — Selected\r\n <i class=\"fa fa-check fa-fw text-success\"></i>\r\n </span>\r\n</ng-template>\r\n\r\n<ng-template #noResults>\r\n <span *ngIf=\"hasNoResults\"> — No Results\r\n <i class=\"fa fa-times fa-fw text-warning\"></i>\r\n </span>\r\n</ng-template>\r\n\r\n\r\n<ng-template #error>\r\n <span *ngIf='hasError; else noResults'> — Error\r\n <i class=\"fa fa-exclamation-triangle fa-fw text-danger\"></i>\r\n </span>\r\n</ng-template>\r\n",
styles: [""]
}] }
];
/** @nocollapse */
GeocoderInputComponent.ctorParameters = () => [
{ type: NgControl, decorators: [{ type: Optional }, { type: Self }] },
{ type: GeocoderService },
{ type: ChangeDetectorRef }
];
GeocoderInputComponent.propDecorators = {
label: [{ type: Input }],
address: [{ type: Input }],
addressChange: [{ type: Output }],
select: [{ type: Output }],
maxlength: [{ type: Input }]
};
if (false) {
/** @type {?} */
GeocoderInputComponent.prototype.label;
/** @type {?} */
GeocoderInputComponent.prototype.address;
/** @type {?} */
GeocoderInputComponent.prototype.addressChange;
/** @type {?} */
GeocoderInputComponent.prototype.select;
/** @type {?} */
GeocoderInputComponent.prototype.maxlength;
/**
* The string in the box the user has typed
* @type {?}
*/
GeocoderInputComponent.prototype.search;
/**
* Is the Geocoder API request still in progress?
* @type {?}
*/
GeocoderInputComponent.prototype.isTypeaheadLoading;
/**
* Geocoder API has returned and has no results, an empty array.
* @type {?}
*/
GeocoderInputComponent.prototype.hasNoResults;
/** @type {?} */
GeocoderInputComponent.prototype.hasError;
/**
* Similar to this.address, but we can null it when user is searching for new addresses
* @type {?}
*/
GeocoderInputComponent.prototype.selectedAddress;
/**
* The list of results, from API, that is passed to the typeahead list
* @type {?}
*/
GeocoderInputComponent.prototype.typeaheadList$;
/**
* The subject that triggers on user text input and gets typeaheadList$ to update.
* @type {?}
* @private
*/
GeocoderInputComponent.prototype.searchText$;
/** @type {?} */
GeocoderInputComponent.prototype._onChange;
/** @type {?} */
GeocoderInputComponent.prototype._onTouched;
/** @type {?} */
GeocoderInputComponent.prototype.controlDir;
/**
* @type {?}
* @private
*/
GeocoderInputComponent.prototype.geocoderService;
/**
* @type {?}
* @private
*/
GeocoderInputComponent.prototype.cd;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvY29kZXItaW5wdXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbW9oLWNvbW1vbi1saWIvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9nZW9jb2Rlci1pbnB1dC9nZW9jb2Rlci1pbnB1dC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVUsS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNsSCxPQUFPLEVBQUUsT0FBTyxFQUFjLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzRixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDekMsT0FBTyxFQUFFLGVBQWUsRUFBb0IsTUFBTSxpQ0FBaUMsQ0FBQztBQUNwRixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDbEUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxTQUFTLEVBQXdCLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE2QmpFLE1BQU0sT0FBTyxzQkFBdUIsU0FBUSxJQUFJOzs7Ozs7SUEyQjlDLFlBQXVDLFVBQXFCLEVBQVUsZUFBZ0MsRUFBVSxFQUFxQjtRQUNuSSxLQUFLLEVBQUUsQ0FBQztRQUQ2QixlQUFVLEdBQVYsVUFBVSxDQUFXO1FBQVUsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBQVUsT0FBRSxHQUFGLEVBQUUsQ0FBbUI7UUF6QjVILFVBQUssR0FBVyxnQkFBZ0Is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LDhDQUFxQzs7SUFDckMsMENBQWlDOzs7OztJQUdqQyxpREFBd0M7Ozs7O0lBRXhDLGdEQUFzRDs7Ozs7O0lBRXRELDZDQUE0Qzs7SUFFNUMsMkNBQTJCOztJQUMzQiw0Q0FBNkI7O0lBRWpCLDRDQUFnRDs7Ozs7SUFBRSxpREFBd0M7Ozs7O0lBQUUsb0NBQTZCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBDaGFuZ2VEZXRlY3RvclJlZiwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIE9wdGlvbmFsLCBTZWxmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFN1YmplY3QsIE9ic2VydmFibGUsIG9mIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IGRlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbENoYW5nZWQsIHN3aXRjaE1hcCwgY2F0Y2hFcnJvciB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgVHlwZWFoZWFkTWF0Y2ggfSBmcm9tICduZ3gtYm9vdHN0cmFwL3R5cGVhaGVhZCc7XHJcbmltcG9ydCB7IEJhc2UgfSBmcm9tICcuLi8uLi9tb2RlbHMvYmFzZSc7XHJcbmltcG9ydCB7IEdlb2NvZGVyU2VydmljZSwgR2VvQWRkcmVzc1Jlc3VsdCB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2dlb2NvZGVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBDQU5BREEgfSBmcm9tICcuLi9jb3VudHJ5L2NvdW50cnkuY29tcG9uZW50JztcclxuaW1wb3J0IHsgQlJJVElTSF9DT0xVTUJJQSB9IGZyb20gJy4uL3Byb3ZpbmNlL3Byb3ZpbmNlLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IEFkZHJlc3MgfSBmcm9tICcuLi8uLi9tb2RlbHMvYWRkcmVzcy5tb2RlbCc7XHJcbmltcG9ydCB7IE5nQ29udHJvbCwgQ29udHJvbFZhbHVlQWNjZXNzb3IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcblxyXG5cclxuLyoqXHJcbiAqIEBkZXByZWNhdGVkIFBsZWFzZSB1c2UgYGFkZHJlc3MtdmFsaWRhdG9yYCBjb21wb25lbnQgaW5zdGVhZC5cclxuICpcclxuICogRm9yIFRlbXBsYXRlRm9ybXMsIHBhc3MgaW4gYW4gQWRkcmVzcyBhbmQgcmVjaWV2ZSBhbiBBZGRyZXNzXHJcbiAqIEBleGFtcGxlXHJcbiAqICAgICAgICAgICA8Y29tbW9uLWdlb2NvZGVyLWlucHV0XHJcbiAqICAgICAgICAgICAgICAgbGFiZWw9J1BoeXNpY2FsIEFkZHJlc3MnXHJcbiAqICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJteUFkZHJlc3NcIj5cclxuICogICAgICAgICAgIDwvY29tbW9uLWdlb2NvZGVyLWlucHV0PlxyXG4gKlxyXG4gKiBAbm90ZVxyXG4gKiBGb3IgUmVhY3RpdmVGb3JtcywgcGFzcyBpbiBhIHN0cmluZyBhbmQgcmVjaWV2ZSBhIHN0cmluZy4gIElmIHlvdSBuZWVkIHRoZVxyXG4gKiBBZGRyZXNzIG9iamVjdCB5b3UgY2FuIHVzZSAoc2VsZWN0KSBpbiBhZGRpdGlvbi5cclxuICpcclxuICogQGV4YW1wbGVcclxuICogICAgICAgICAgIDxjb21tb24tZ2VvY29kZXItaW5wdXRcclxuICogICAgICAgICAgICAgIGxhYmVsPSdQaHlzaWNhbCBBZGRyZXNzJ1xyXG4gKiAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiYWRkcmVzc1wiXHJcbiAqICAgICAgICAgICAgICAoc2VsZWN0KT1cImdldEFkZHJlc3NPYmplY3QoJGV2ZW50KVwiPlxyXG4gKiAgICAgICAgICA8L2NvbW1vbi1nZW9jb2Rlci1pbnB1dD5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnY29tbW9uLWdlb2NvZGVyLWlucHV0JyxcclxuICB0ZW1wbGF0ZVVybDogJy4vZ2VvY29kZXItaW5wdXQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2dlb2NvZGVyLWlucHV0LmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIEdlb2NvZGVySW5wdXRDb21wb25lbnQgZXh0ZW5kcyBCYXNlIGltcGxlbWVudHMgT25Jbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciB7XHJcblxyXG4gIEBJbnB1dCgpIGxhYmVsOiBzdHJpbmcgPSAnQWRkcmVzcyBMb29rdXAnO1xyXG4gIEBJbnB1dCgpIGFkZHJlc3M6IHN0cmluZztcclxuICBAT3V0cHV0KCkgYWRkcmVzc0NoYW5nZTogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuICBAT3V0cHV0KCkgc2VsZWN0OiBFdmVudEVtaXR0ZXI8QWRkcmVzcz4gPSBuZXcgRXZlbnRFbWl0dGVyPEFkZHJlc3M+KCk7XHJcblxyXG4gIEBJbnB1dCgpIG1heGxlbmd0aDogc3RyaW5nID0gJzI1NSc7XHJcblxyXG4gIC8qKiBUaGUgc3RyaW5nIGluIHRoZSBib3ggdGhlIHVzZXIgaGFzIHR5cGVkICovXHJcbiAgcHVibGljIHNlYXJjaDogc3RyaW5nO1xyXG4gIC8qKiBJcyB0aGUgR2VvY29kZXIgQVBJIHJlcXVlc3Qgc3RpbGwgaW4gcHJvZ3Jlc3M/ICovXHJcbiAgcHVibGljIGlzVHlwZWFoZWFkTG9hZGluZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIC8qKiBHZW9jb2RlciBBUEkgaGFzIHJldHVybmVkIGFuZCBoYXMgbm8gcmVzdWx0cywgYW4gZW1wdHkgYXJyYXkuICovXHJcbiAgcHVibGljIGhhc05vUmVzdWx0czogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIHB1YmxpYyBoYXNFcnJvcjogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKiogU2ltaWxhciB0byB0aGlzLmFkZHJlc3MsIGJ1dCB3ZSBjYW4gbnVsbCBpdCB3aGVuIHVzZXIgaXMgc2VhcmNoaW5nIGZvciBuZXcgYWRkcmVzc2VzICovXHJcbiAgcHVibGljIHNlbGVjdGVkQWRkcmVzczogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIC8qKiBUaGUgbGlzdCBvZiByZXN1bHRzLCBmcm9tIEFQSSwgdGhhdCBpcyBwYXNzZWQgdG8gdGhlIHR5cGVhaGVhZCBsaXN0ICovXHJcbiAgcHVibGljIHR5cGVhaGVhZExpc3QkOiBPYnNlcnZhYmxlPEdlb0FkZHJlc3NSZXN1bHRbXT47IC8vIFJlc3VsdCBmcm9tIEdlb0NvZGVyU2VydmljZSBhZGRyZXNzIGxvb2t1cFxyXG4gIC8qKiBUaGUgc3ViamVjdCB0aGF0IHRyaWdnZXJzIG9uIHVzZXIgdGV4dCBpbnB1dCBhbmQgZ2V0cyB0eXBlYWhlYWRMaXN0JCB0byB1cGRhdGUuICAqL1xyXG4gIHByaXZhdGUgc2VhcmNoVGV4dCQgPSBuZXcgU3ViamVjdDxzdHJpbmc+KCk7XHJcblxyXG4gIF9vbkNoYW5nZSA9IChfOiBhbnkpID0+IHt9O1xyXG4gIF9vblRvdWNoZWQgPSAoXz86IGFueSkgPT4ge307XHJcblxyXG4gIGNvbnN0cnVjdG9yKEBPcHRpb25hbCgpIEBTZWxmKCkgcHVibGljIGNvbnRyb2xEaXI6IE5nQ29udHJvbCwgcHJpdmF0ZSBnZW9jb2RlclNlcnZpY2U6IEdlb2NvZGVyU2VydmljZSwgcHJpdmF0ZSBjZDogQ2hhbmdlRGV0ZWN0b3JSZWYpIHtcclxuICAgIHN1cGVyKCk7XHJcbiAgICBpZiAoIGNvbnRyb2xEaXIgKSB7XHJcbiAgICAgIGNvbnRyb2xEaXIudmFsdWVBY2Nlc3NvciA9IHRoaXM7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIHRoaXMudHlwZWFoZWFkTGlzdCQgPSB0aGlzLnNlYXJjaFRleHQkLnBpcGUoXHJcbiAgICAgIGRlYm91bmNlVGltZSg1MDApLFxyXG4gICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLFxyXG4gICAgICAvLyBUcmlnZ2VyIHRoZSBuZXR3b3JrIHJlcXVlc3QsIGdldCByZXN1bHRzXHJcbiAgICAgIHN3aXRjaE1hcChzZWFyY2hQaHJhc2UgPT4gdGhpcy5nZW9jb2RlclNlcnZpY2UubG9va3VwKHNlYXJjaFBocmFzZSkpLFxyXG4gICAgICBjYXRjaEVycm9yKGVyciA9PiB0aGlzLm9uRXJyb3IoZXJyKSlcclxuICAgICk7XHJcblxyXG4gIH1cclxuXHJcbiAgb25FcnJvcihlcnIpOiBPYnNlcnZhYmxlPEdlb0FkZHJlc3NSZXN1bHRbXT4ge1xyXG5cclxuICAgIHRoaXMuaGFzRXJyb3IgPSB0cnVlO1xyXG4gICAgLy8gRW1wdHkgYXJyYXkgc2ltdWxhdGVzIG5vIHJlc3VsdCByZXNwb25zZSwgbm90aGluZyBmb3IgdHlwZWFoZWFkIHRvIGl0ZXJhdGUgb3ZlclxyXG4gICAgcmV0dXJuIG9mKFtdKTtcclxuICB9XHJcblxyXG4gIG9uTG9hZGluZyh2YWw6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRoaXMuaXNUeXBlYWhlYWRMb2FkaW5nID0gdmFsO1xyXG4gIH1cclxuXHJcbiAgLy8gTm90ZSAtIHRoaXMgd2lsbCBmaXJlIGFmdGVyIGFuIG9uRXJyb3IgYXMgd2VsbFxyXG4gIG9uTm9SZXN1bHRzKHZhbDogYm9vbGVhbik6IHZvaWQge1xyXG5cclxuICAgIC8vIElmIHdlIGhhdmUgcmVzdWx0cywgdGhlIGVycm9yIGhhcyByZXNvbHZlZCAoZS5nLiBuZXR3b3JrIGhhcyByZS1jb25uZWN0ZWQpXHJcbiAgICBpZiAodmFsID09PSBmYWxzZSkge1xyXG4gICAgICB0aGlzLmhhc0Vycm9yID0gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5oYXNOb1Jlc3VsdHMgPSB2YWw7XHJcbiAgfVxyXG5cclxuICBvblNlbGVjdChldmVudDogVHlwZWFoZWFkTWF0Y2gpOiB2b2lkIHtcclxuXHJcbiAgICBjb25zdCBkYXRhOiBHZW9BZGRyZXNzUmVzdWx0ID0gZXZlbnQuaXRlbTtcclxuXHJcbiAgICAvLyBPdXRwdXQgc3RyaW5nIHRvIEZvcm1Db250cm9sLiBJZiBzdHJlZXQgaXMgbW9yZSB0aGFuIHRoZSBtYXggbGVuZ3RoIHNob3J0ZW5cclxuICAgIGNvbnN0IHN0cmlwcGVkID0gdGhpcy5zdHJpcFN0cmluZ1RvTWF4TGVuZ3RoKGRhdGEuc3RyZWV0KTtcclxuXHJcbiAgICBjb25zdCBhZGRyID0gbmV3IEFkZHJlc3MoKTtcclxuICAgIGFkZHIuY2l0eSA9IGRhdGEuY2l0eTtcclxuICAgIC8vIEdlb0NvZGVyIGlzIG9ubHkgZm9yIEJDLCBDYW5hZGEsIHZhbHVlcyBjYW4gYmUgc2V0LlxyXG4gICAgYWRkci5jb3VudHJ5ID0gQ0FOQURBOyAvLyBEZWZhdWx0IGNvdW50cnkgaXMgQ2FuZGFcclxuICAgIGFkZHIucHJvdmluY2UgPSBCUklUSVNIX0NPTFVNQklBOyAgLy8gRGVmYXVsdCBwcm92aW5jZSBpcyBCQ1xyXG4gICAgYWRkci5zdHJlZXQgPSBzdHJpcHBlZDtcclxuICAgIC8vIFNhdmUgYW5kIGVtaXQgQWRkcmVzcyBmb3IgKHNlbGVjdClcclxuICAgIHRoaXMuc2VsZWN0ZWRBZGRyZXNzID0gdHJ1ZTtcclxuICAgIHRoaXMuc2VsZWN0LmVtaXQoYWRkcik7XHJcblxyXG4gICAgdGhpcy5fb25DaGFuZ2Uoc3RyaXBwZWQpO1xyXG4gIH1cclxuXHJcbiAgb25LZXlVcChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xyXG4gICAgLy8gRmlsdGVyIG91dCAnZW50ZXInIGFuZCBvdGhlciBzaW1pbGFyIGtleWJvYXJkIGV2ZW50cyB0aGF0IGNhbiB0cmlnZ2VyXHJcbiAgICAvLyB3aGVuIHVzZXIgaXMgc2VsZWN0aW5nIGEgdHlwZWFoZWFkIG9wdGlvbiBpbnN0ZWFkIG9mIGVudGVyaW5nIG5ldyB0ZXh0LlxyXG4gICAgLy8gV2l0aG91dCB0aGlzIGZpbHRlciwgd2UgZG8gYW5vdGhlciBIVFRQIHJlcXVlc3QgKyBmb3JjZSBkaXNpcGxheSB0aGUgVUlcclxuICAgIC8vIGZvciBub3cgcmVhc29uXHJcbiAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0gMTMgfHwgZXZlbnQua2V5Q29kZSA9PT0gOSkgeyAgLy8gZW50ZXIgJiB0YWJcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgLy8gQ2xlYXIgb3V0IHNlbGVjdGlvblxyXG4gICAgdGhpcy5zZWxlY3RlZEFkZHJlc3MgPSBmYWxzZTtcclxuICAgIHRoaXMuc2VhcmNoVGV4dCQubmV4dCh0aGlzLnNlYXJjaCk7XHJcbiAgfVxyXG5cclxuICBvbkJsdXIoZXZlbnQpOiB2b2lkIHtcclxuICAgIHRoaXMuX29uVG91Y2hlZCgpO1xyXG4gICAgdGhpcy5fb25DaGFuZ2UodGhpcy5zZWFyY2gpO1xyXG4gIH1cclxuXHJcblxyXG4gIHdyaXRlVmFsdWUoIHZhbHVlOiBhbnkgKTogdm9pZCB7XHJcbiAgICBpZiAoIHZhbHVlICAhPT0gdW5kZWZpbmVkICkge1xyXG4gICAgICB0aGlzLnNlYXJjaCA9IHZhbHVlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gUmVnaXN0ZXIgY2hhbmdlIGZ1bmN0aW9uXHJcbiAgcmVnaXN0ZXJPbkNoYW5nZSggZm46IGFueSApOiB2b2lkIHtcclxuICAgIHRoaXMuX29uQ2hhbmdlID0gZm47XHJcbiAgfVxyXG5cclxuICAvLyBSZWdpc3RlciB0b3VjaGVkIGZ1bmN0aW9uXHJcbiAgcmVnaXN0ZXJPblRvdWNoZWQoIGZuOiBhbnkgKTogdm9pZCB7XHJcbiAgICB0aGlzLl9vblRvdWNoZWQgPSBmbjtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc3RyaXBTdHJpbmdUb01heExlbmd0aChzdHI6IHN0cmluZykge1xyXG4gICAgY29uc3QgbWF4bGVuZ3RoID0gcGFyc2VJbnQodGhpcy5tYXhsZW5ndGgsIDEwKTtcclxuICAgIHJldHVybiBzdHIuc2xpY2UoMCwgbWF4bGVuZ3RoKTtcclxuICB9XHJcblxyXG59XHJcbiJdfQ==