UNPKG

@rangertechnologies/ngnxt

Version:

This library was used for creating dymanic UI based on the input JSON/data

234 lines 40.7 kB
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core'; // VD 21DEC23 - dependent field change import { ChangeWrapper } from '../../model/changeWrapper'; import { CommonModule } from '@angular/common'; import { I18nPipe } from '../../i18n.pipe'; import { GoogleMapsModule } from '@angular/google-maps'; import { FormsModule } from '@angular/forms'; import { NxtInput } from '../nxt-input/nxt-input.component'; import * as i0 from "@angular/core"; import * as i1 from "../../i18n.service"; import * as i2 from "@angular/common"; import * as i3 from "@angular/google-maps"; export class PickLocationComponent { i18nService; ngZone; cdr; latitude = null; longitude = null; zoom = 10; geoCoder; // public formGroup: FormGroup; searchElementRef; showModal = false; address; // VD 21DEC23 - dependent field change question; mode = 'edit'; // New mode input locationSelected = new EventEmitter(); navigatorGeolocation; markerPosition; center; markerOptions; apiKey; // HA10012024 declared Api key to src constructor( // private mapsAPILoader: MapsAPILoader, i18nService, ngZone, cdr) { this.i18nService = i18nService; this.ngZone = ngZone; this.cdr = cdr; } ngOnInit() { // HA-11-01-2024 Changed the map Call from constructor to ngOnInit as it was giving undefined values in the outsourced if (this.apiKey) { this.loadGoogleMapsScript().then(() => { this.geoCoder = new google.maps.Geocoder(); this.markerOptions = new google.maps.Marker({ draggable: true, animation: google.maps.Animation.DROP }); this.initAutocomplete(); this.onMarkerDragEnd(); }); } } // RS 23JAN2025 ngOnChanges(changes) { if (changes['mode']) { this.mode = changes['mode'].currentValue; } if (changes['address'] && changes['address'].currentValue !== changes['address'].previousValue) { // Ensure latitude & longitude update when the address changes if (this.address) { this.geoCoder.geocode({ address: this.address }, (results, status) => { if (status === 'OK' && results[0]?.geometry?.location) { this.latitude = results[0].geometry.location.lat(); this.longitude = results[0].geometry.location.lng(); this.markerPosition = { lat: this.latitude, lng: this.longitude }; this.center = { lat: this.latitude, lng: this.longitude }; this.zoom = 18; this.cdr.detectChanges(); // Force Angular to update the UI } }); } else { // Reset if no address is provided this.latitude = null; this.longitude = null; this.markerPosition = null; this.center = null; this.cdr.detectChanges(); // FORCE UI UPDATE } } } setInputRef(ref) { this.searchElementRef = ref; this.initAutocomplete(); // SKS11JUN25 Now that input ref is ready, initialize autocomplete } // HA09012024 is to avoid google is undefined error loadGoogleMapsScript() { const script = document.createElement('script'); script.type = 'text/javascript'; // HA10012024 Assigned Api key to src script.src = `https://maps.googleapis.com/maps/api/js?key=${this.apiKey}&libraries=geometry,places`; script.async = true; script.defer = true; document.body.appendChild(script); return new Promise((resolve, reject) => { script.onload = () => { resolve(); }; script.onerror = (error) => { reject(error); }; }); } initAutocomplete() { if (this.geoCoder) { const autocomplete = new google.maps.places.Autocomplete(this.searchElementRef?.nativeElement, { types: [] }); autocomplete.addListener('place_changed', () => { this.ngZone.run(() => { const place = autocomplete.getPlace(); if (place.geometry === undefined || place.geometry === null) { return; } this.latitude = place.geometry.location.lat(); this.longitude = place.geometry.location.lng(); this.zoom = 18; this.address = place.formatted_address; // VD 21DEC23 - dependent field change let change = new ChangeWrapper(); // RS 09DEC24 Changed keys change.fromQuestionId = this.question.id; let addObj = {}; addObj['address'] = this.address; addObj['latitude'] = this.latitude; addObj['longitude'] = this.longitude; change.valueObj = addObj; this.locationSelected.emit(change); }); }); } } onMarkerDragEnd() { google.maps.event.addListener(this.markerOptions, 'dragend', (event) => { console.log('dragable working', event); this.latitude = event.latLng.lat(); this.longitude = event.latLng.lng(); this.getAddress(this.latitude, this.longitude); }); } onMapClick(event) { console.log('onMapClick', event); this.latitude = event.latLng.lat(); this.longitude = event.latLng.lng(); this.getAddress(this.latitude, this.longitude); } setCurrentLocation() { if ('geolocation' in navigator) { navigator.geolocation.getCurrentPosition((position) => { this.latitude = position.coords.latitude; this.longitude = position.coords.longitude; this.markerPosition = { lat: this.latitude, lng: this.longitude }; this.center = { lat: this.latitude, lng: this.longitude }; this.zoom = 8; this.getAddress(this.latitude, this.longitude); }); } } getAddress(latitude, longitude) { if (this.geoCoder) { this.geoCoder.geocode({ location: { lat: latitude, lng: longitude } }, (results, status) => { console.log('results', results); console.log('status', status); if (status === 'OK') { if (results[0]) { // this.zoom = 18; this.address = results[0].formatted_address; // VD 21DEC23 - dependent field change let change = new ChangeWrapper(); // RS 09DEC24 Changed keys change.fromQuestionId = this.question.id; let addObj1 = {}; addObj1['address'] = this.address; addObj1['latitude'] = latitude; addObj1['longitude'] = longitude; change.valueObj = addObj1; this.locationSelected.emit(change); } else { console.log('No results found'); } } else { console.log('Geocoder failed due to: ' + status); } }); } } openMap() { this.showModal = true; if (!this.address) { this.latitude = this.longitude = null; } if (!(this.latitude && this.longitude)) { this.setCurrentLocation(); } else { this.markerPosition = { lat: this.latitude, lng: this.longitude }; this.center = { lat: this.latitude, lng: this.longitude }; this.zoom = 8; } } closeModal() { this.showModal = false; } removeCharacters(questionText) { let updatedText = questionText?.replace(/<[^>]*>/g, ''); return updatedText; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PickLocationComponent, deps: [{ token: i1.I18nService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PickLocationComponent, isStandalone: true, selector: "app-pick-location", inputs: { address: "address", question: "question", mode: "mode", apiKey: "apiKey" }, outputs: { locationSelected: "locationSelected" }, viewQueries: [{ propertyName: "searchElementRef", first: true, predicate: ["search"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div>\n <nxt-input [type]=\"'location'\" [mode]=\"mode\" [value]=\"address\"\n [labelFont]=\"question.font\" [label]=\"removeCharacters(question?.questionText)\" [labelColor]=\"question.fontColor\"\n [labelSize]=\"question.fontSize\" [inputValueSize]=\"question.fontSize\" [labelWeight]=\"question.fontWeight\"\n [inputWeight]=\"question.fontWeight\" [showLabel]=\"question.style?.showLabel\" inputBorder=\"none\" svgHeight=\"20px\"\n svgWidth=\"20px\" [placeholder]=\"question.question\" [required]=\"question.isOptional\" inputBgColor=\"#F5F5F5\"\n [inputId]=\"question.trackingId\" [errorMessages]=\"{ required: 'This field is required' }\"\n [inputIconLeftSrc]=\"question.iconLeftSrc\" (nativeInputRef)=\"setInputRef($event)\">\n </nxt-input>\n <a *ngIf=\"mode === 'edit' && !question.isReadOnly\" (click)=\"openMap()\" style=\"color:#48B7FF;position:relative;top:5px;cursor: pointer;\">\n {{ 'pickLocation' | i18n:i18nService.currentLanguage }}</a>\n</div>\n\n<div class=\"map-overlay\" *ngIf=\"showModal\">\n <div class=\"map-modal\">\n <div class=\"map-modal-content\">\n <div class=\"map-modal-header\">\n <!-- HA 19DEC23 For translation -->\n <h4>{{ 'pickYourLocation' | i18n:i18nService.currentLanguage }}</h4>\n <button class=\"close-button\" (click)=\"closeModal()\">X</button>\n </div>\n <google-map [zoom]=\"zoom\" [center]=\"center\" (mapClick)=\"onMapClick($event)\">\n <map-marker [position]=\"markerPosition\" [options]=\"markerOptions\"></map-marker>\n </google-map>\n </div>\n </div>\n</div>", styles: ["google-map .map-container{width:auto!important}.map-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000}.map-modal{width:600px;background-color:#fff;border-radius:5px;box-shadow:0 2px 4px #0003}.map-modal-header{display:flex;align-items:center;justify-content:space-between;padding:0 0 10px;background-color:#fff;border-bottom:2px solid #e5e5e5}.map-modal-header h3{margin:0}.map-modal-content{padding:20px}.close-button{border:none;cursor:pointer;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: I18nPipe, name: "i18n" }, { kind: "ngmodule", type: GoogleMapsModule }, { kind: "component", type: i3.GoogleMap, selector: "google-map", inputs: ["height", "width", "mapId", "mapTypeId", "center", "zoom", "options"], outputs: ["mapInitialized", "authFailure", "boundsChanged", "centerChanged", "mapClick", "mapDblclick", "mapDrag", "mapDragend", "mapDragstart", "headingChanged", "idle", "maptypeidChanged", "mapMousemove", "mapMouseout", "mapMouseover", "projectionChanged", "mapRightclick", "tilesloaded", "tiltChanged", "zoomChanged"], exportAs: ["googleMap"] }, { kind: "directive", type: i3.MapMarker, selector: "map-marker", inputs: ["title", "position", "label", "clickable", "options", "icon", "visible"], outputs: ["animationChanged", "mapClick", "clickableChanged", "cursorChanged", "mapDblclick", "mapDrag", "mapDragend", "draggableChanged", "mapDragstart", "flatChanged", "iconChanged", "mapMousedown", "mapMouseout", "mapMouseover", "mapMouseup", "positionChanged", "mapRightclick", "shapeChanged", "titleChanged", "visibleChanged", "zindexChanged", "markerInitialized"], exportAs: ["mapMarker"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: NxtInput, selector: "nxt-input", inputs: ["label", "labelFont", "labelWeight", "inputWeight", "labelSize", "inputValueSize", "labelColor", "showLabel", "svgHeight", "svgWidth", "type", "inputIconRightSrc", "inputIconLeftSrc", "required", "minLength", "pattern", "errorMessages", "maxLength", "placeholder", "inputBgColor", "inputBorder", "placeholderColor", "placeholderFont", "placeholderWeight", "placeholderSize", "inputTextColor", "inputHeight", "inputWidth", "inputId", "inputBorderSize", "inputConfig", "confPassVal", "confPass", "mode", "value", "question", "showSuggestion", "ariaOwns", "ariaHasPopup", "isLoading", "options", "minDate", "maxDate", "rows", "size"], outputs: ["valueChange", "inputValue", "onBlur", "onFocus", "toggleEmit", "clearInputEmit", "nativeInputRef"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PickLocationComponent, decorators: [{ type: Component, args: [{ selector: 'app-pick-location', standalone: true, imports: [ CommonModule, I18nPipe, GoogleMapsModule, FormsModule, NxtInput ], template: "<div>\n <nxt-input [type]=\"'location'\" [mode]=\"mode\" [value]=\"address\"\n [labelFont]=\"question.font\" [label]=\"removeCharacters(question?.questionText)\" [labelColor]=\"question.fontColor\"\n [labelSize]=\"question.fontSize\" [inputValueSize]=\"question.fontSize\" [labelWeight]=\"question.fontWeight\"\n [inputWeight]=\"question.fontWeight\" [showLabel]=\"question.style?.showLabel\" inputBorder=\"none\" svgHeight=\"20px\"\n svgWidth=\"20px\" [placeholder]=\"question.question\" [required]=\"question.isOptional\" inputBgColor=\"#F5F5F5\"\n [inputId]=\"question.trackingId\" [errorMessages]=\"{ required: 'This field is required' }\"\n [inputIconLeftSrc]=\"question.iconLeftSrc\" (nativeInputRef)=\"setInputRef($event)\">\n </nxt-input>\n <a *ngIf=\"mode === 'edit' && !question.isReadOnly\" (click)=\"openMap()\" style=\"color:#48B7FF;position:relative;top:5px;cursor: pointer;\">\n {{ 'pickLocation' | i18n:i18nService.currentLanguage }}</a>\n</div>\n\n<div class=\"map-overlay\" *ngIf=\"showModal\">\n <div class=\"map-modal\">\n <div class=\"map-modal-content\">\n <div class=\"map-modal-header\">\n <!-- HA 19DEC23 For translation -->\n <h4>{{ 'pickYourLocation' | i18n:i18nService.currentLanguage }}</h4>\n <button class=\"close-button\" (click)=\"closeModal()\">X</button>\n </div>\n <google-map [zoom]=\"zoom\" [center]=\"center\" (mapClick)=\"onMapClick($event)\">\n <map-marker [position]=\"markerPosition\" [options]=\"markerOptions\"></map-marker>\n </google-map>\n </div>\n </div>\n</div>", styles: ["google-map .map-container{width:auto!important}.map-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000}.map-modal{width:600px;background-color:#fff;border-radius:5px;box-shadow:0 2px 4px #0003}.map-modal-header{display:flex;align-items:center;justify-content:space-between;padding:0 0 10px;background-color:#fff;border-bottom:2px solid #e5e5e5}.map-modal-header h3{margin:0}.map-modal-content{padding:20px}.close-button{border:none;cursor:pointer;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2}\n"] }] }], ctorParameters: () => [{ type: i1.I18nService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }], propDecorators: { searchElementRef: [{ type: ViewChild, args: ['search', { static: true }] }], address: [{ type: Input }], question: [{ type: Input }], mode: [{ type: Input }], locationSelected: [{ type: Output }], apiKey: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGljay1sb2NhdGlvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9ueHQtYXBwL3NyYy9saWIvY29tcG9uZW50cy9waWNrLWxvY2F0aW9uL3BpY2stbG9jYXRpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbnh0LWFwcC9zcmMvbGliL2NvbXBvbmVudHMvcGljay1sb2NhdGlvbi9waWNrLWxvY2F0aW9uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQWMsWUFBWSxFQUFFLEtBQUssRUFBOEMsTUFBTSxFQUFpQixTQUFTLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFHbkssc0NBQXNDO0FBQ3ZDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUUxRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7Ozs7O0FBWTVELE1BQU0sT0FBTyxxQkFBcUI7SUFzQnhCO0lBQ0U7SUFDQTtJQXZCVixRQUFRLEdBQUcsSUFBSSxDQUFDO0lBQ2hCLFNBQVMsR0FBRyxJQUFJLENBQUM7SUFDakIsSUFBSSxHQUFXLEVBQUUsQ0FBQztJQUNWLFFBQVEsQ0FBQztJQUNsQiwrQkFBK0I7SUFFdkIsZ0JBQWdCLENBQStCO0lBQ3RELFNBQVMsR0FBWSxLQUFLLENBQUM7SUFDbEIsT0FBTyxDQUFRO0lBQ3ZCLHNDQUFzQztJQUM5QixRQUFRLENBQUs7SUFDYixJQUFJ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b21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5wdXQsQ2hhbmdlRGV0ZWN0b3JSZWYsIE5nTW9kdWxlLCBOZ1pvbmUsIE9uSW5pdCwgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBWaWV3Q2hpbGQsIE9uQ2hhbmdlcyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuLy8gSEEgMTlERUMyMyBpbXBvcnRlZCB0cmFuc2xhdGlvbiBzZXJ2aWNlXG5pbXBvcnQgeyBJMThuU2VydmljZSB9IGZyb20gJy4uLy4uL2kxOG4uc2VydmljZSc7XG4gLy8gVkQgMjFERUMyMyAtIGRlcGVuZGVudCBmaWVsZCBjaGFuZ2VcbmltcG9ydCB7IENoYW5nZVdyYXBwZXIgfSBmcm9tICcuLi8uLi9tb2RlbC9jaGFuZ2VXcmFwcGVyJztcbmltcG9ydCB7IFF1ZXN0aW9uIH0gZnJvbSAnLi4vLi4vd3JhcHBlcic7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgSTE4blBpcGUgfSBmcm9tICcuLi8uLi9pMThuLnBpcGUnO1xuaW1wb3J0IHsgR29vZ2xlTWFwc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2dvb2dsZS1tYXBzJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgTnh0SW5wdXQgfSBmcm9tICcuLi9ueHQtaW5wdXQvbnh0LWlucHV0LmNvbXBvbmVudCc7XG5kZWNsYXJlIHZhciAkOiBhbnk7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1waWNrLWxvY2F0aW9uJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSwgSTE4blBpcGUsIEdvb2dsZU1hcHNNb2R1bGUsIEZvcm1zTW9kdWxlLCBOeHRJbnB1dFxuICBdLFxuICB0ZW1wbGF0ZVVybDogJy4vcGljay1sb2NhdGlvbi5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3BpY2stbG9jYXRpb24uY29tcG9uZW50LmNzcyddXG59KVxuZXhwb3J0IGNsYXNzIFBpY2tMb2NhdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCAsT25DaGFuZ2VzIHtcbiAgbGF0aXR1ZGUgPSBudWxsO1xuICBsb25naXR1ZGUgPSBudWxsO1xuICB6b29tOiBudW1iZXIgPSAxMDtcbiAgcHJpdmF0ZSBnZW9Db2RlcjtcbiAvLyBwdWJsaWMgZm9ybUdyb3VwOiBGb3JtR3JvdXA7XG4gIEBWaWV3Q2hpbGQoJ3NlYXJjaCcsIHsgc3RhdGljOiB0cnVlIH0pXG4gIHB1YmxpYyBzZWFyY2hFbGVtZW50UmVmOiBFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+O1xuICBzaG93TW9kYWw6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgYWRkcmVzczpzdHJpbmc7XG4gICAvLyBWRCAyMURFQzIzIC0gZGVwZW5kZW50IGZpZWxkIGNoYW5nZVxuICBASW5wdXQoKSBxdWVzdGlvbjogYW55XG4gIEBJbnB1dCgpIG1vZGU6ICd2aWV3JyB8ICdlZGl0JyB8ICdwcmludCcgPSAnZWRpdCc7IC8vIE5ldyBtb2RlIGlucHV0XG4gIEBPdXRwdXQoKSBsb2NhdGlvblNlbGVjdGVkOiBFdmVudEVtaXR0ZXI8Q2hhbmdlV3JhcHBlcj4gPSBuZXcgRXZlbnRFbWl0dGVyPENoYW5nZVdyYXBwZXI+KCk7XG4gIG5hdmlnYXRvckdlb2xvY2F0aW9uOiBhbnk7XG4gIG1hcmtlclBvc2l0aW9uOiB7IGxhdDogYW55OyBsbmc6IGFueTsgfTtcbiAgY2VudGVyOiB7IGxhdDogYW55OyBsbmc6IGFueTsgfTtcbiAgbWFya2VyT3B0aW9uczphbnk7XG4gIEBJbnB1dCgpIGFwaUtleTogYW55OyAvLyBIQTEwMDEyMDI0IGRlY2xhcmVkIEFwaSBrZXkgdG8gc3JjXG5cbiAgY29uc3RydWN0b3IoXG4gICAvLyBwcml2YXRlIG1hcHNBUElMb2FkZXI6IE1hcHNBUElMb2FkZXIsXG4gICBwdWJsaWMgaTE4blNlcnZpY2U6IEkxOG5TZXJ2aWNlLFxuICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmUsXG4gICAgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmXG4gICkge31cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBIQS0xMS0wMS0yMDI0IENoYW5nZWQgdGhlIG1hcCBDYWxsIGZyb20gY29uc3RydWN0b3IgdG8gbmdPbkluaXQgYXMgaXQgd2FzIGdpdmluZyB1bmRlZmluZWQgdmFsdWVzIGluIHRoZSBvdXRzb3VyY2VkXG4gICAgaWYodGhpcy5hcGlLZXkpe1xuICAgICAgdGhpcy5sb2FkR29vZ2xlTWFwc1NjcmlwdCgpLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLmdlb0NvZGVyID0gbmV3IGdvb2dsZS5tYXBzLkdlb2NvZGVyKCk7XG4gICAgICAgIHRoaXMubWFya2VyT3B0aW9ucyA9IG5ldyBnb29nbGUubWFwcy5NYXJrZXIgKHtcbiAgICAgICAgICBkcmFnZ2FibGU6IHRydWUsXG4gICAgICAgICAgYW5pbWF0aW9uOiBnb29nbGUubWFwcy5BbmltYXRpb24uRFJPUFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5pbml0QXV0b2NvbXBsZXRlKCk7XG4gICAgICAgIHRoaXMub25NYXJrZXJEcmFnRW5kKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbi8vIFJTIDIzSkFOMjAyNVxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXNbJ21vZGUnXSkge1xuICAgICAgdGhpcy5tb2RlID0gY2hhbmdlc1snbW9kZSddLmN1cnJlbnRWYWx1ZTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXNbJ2FkZHJlc3MnXSAmJiBjaGFuZ2VzWydhZGRyZXNzJ10uY3VycmVudFZhbHVlICE9PSBjaGFuZ2VzWydhZGRyZXNzJ10ucHJldmlvdXNWYWx1ZSkge1xuICAgICAgLy8gRW5zdXJlIGxhdGl0dWRlICYgbG9uZ2l0dWRlIHVwZGF0ZSB3aGVuIHRoZSBhZGRyZXNzIGNoYW5nZXNcbiAgICAgIGlmICh0aGlzLmFkZHJlc3MpIHtcbiAgICAgICAgdGhpcy5nZW9Db2Rlci5nZW9jb2RlKHsgYWRkcmVzczogdGhpcy5hZGRyZXNzIH0sIChyZXN1bHRzLCBzdGF0dXMpID0+IHtcbiAgICAgICAgICBpZiAoc3RhdHVzID09PSAnT0snICYmIHJlc3VsdHNbMF0/Lmdlb21ldHJ5Py5sb2NhdGlvbikge1xuICAgICAgICAgICAgdGhpcy5sYXRpdHVkZSA9IHJlc3VsdHNbMF0uZ2VvbWV0cnkubG9jYXRpb24ubGF0KCk7XG4gICAgICAgICAgICB0aGlzLmxvbmdpdHVkZSA9IHJlc3VsdHNbMF0uZ2VvbWV0cnkubG9jYXRpb24ubG5nKCk7XG4gICAgICAgICAgICB0aGlzLm1hcmtlclBvc2l0aW9uID0geyBsYXQ6IHRoaXMubGF0aXR1ZGUsIGxuZzogdGhpcy5sb25naXR1ZGUgfTtcbiAgICAgICAgICAgIHRoaXMuY2VudGVyID0geyBsYXQ6IHRoaXMubGF0aXR1ZGUsIGxuZzogdGhpcy5sb25naXR1ZGUgfTtcbiAgICAgICAgICAgIHRoaXMuem9vbSA9IDE4O1xuICAgICAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpOyAgLy8gRm9yY2UgQW5ndWxhciB0byB1cGRhdGUgdGhlIFVJXG5cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUmVzZXQgaWYgbm8gYWRkcmVzcyBpcyBwcm92aWRlZFxuICAgICAgICB0aGlzLmxhdGl0dWRlID0gbnVsbDtcbiAgICAgICAgdGhpcy5sb25naXR1ZGUgPSBudWxsO1xuICAgICAgICB0aGlzLm1hcmtlclBvc2l0aW9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5jZW50ZXIgPSBudWxsO1xuICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7ICAvLyBGT1JDRSBVSSBVUERBVEVcblxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNldElucHV0UmVmKHJlZjogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50Pikge1xuICAgIHRoaXMuc2VhcmNoRWxlbWVudFJlZiA9IHJlZjtcbiAgICB0aGlzLmluaXRBdXRvY29tcGxldGUoKTsgLy8gU0tTMTFKVU4yNSBOb3cgdGhhdCBpbnB1dCByZWYgaXMgcmVhZHksIGluaXRpYWxpemUgYXV0b2NvbXBsZXRlXG4gIH1cblxuXG5cbiAgLy8gSEEwOTAxMjAyNCBpcyB0byBhdm9pZCBnb29nbGUgaXMgdW5kZWZpbmVkIGVycm9yXG4gIHByaXZhdGUgbG9hZEdvb2dsZU1hcHNTY3JpcHQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG4gICAgc2NyaXB0LnR5cGUgPSAndGV4dC9qYXZhc2NyaXB0JztcbiAgICAvLyBIQTEwMDEyMDI0IEFzc2lnbmVkIEFwaSBrZXkgdG8gc3JjXG4gICAgc2NyaXB0LnNyYyA9IGBodHRwczovL21hcHMuZ29vZ2xlYXBpcy5jb20vbWFwcy9hcGkvanM/a2V5PSR7dGhpcy5hcGlLZXl9JmxpYnJhcmllcz1nZW9tZXRyeSxwbGFjZXNgO1xuICAgIHNjcmlwdC5hc3luYyA9IHRydWU7XG4gICAgc2NyaXB0LmRlZmVyID0gdHJ1ZTtcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHNjcmlwdCk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgc2NyaXB0Lm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfTtcbiAgICAgIHNjcmlwdC5vbmVycm9yID0gKGVycm9yOiBhbnkpID0+IHtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICBpbml0QXV0b2NvbXBsZXRlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmdlb0NvZGVyKSB7XG4gICAgICBjb25zdCBhdXRvY29tcGxldGUgPSBuZXcgZ29vZ2xlLm1hcHMucGxhY2VzLkF1dG9jb21wbGV0ZSh0aGlzLnNlYXJjaEVsZW1lbnRSZWY/Lm5hdGl2ZUVsZW1lbnQsIHtcbiAgICAgICAgdHlwZXM6IFtdXG4gICAgICB9KTtcbiAgICAgIGF1dG9jb21wbGV0ZS5hZGRMaXN0ZW5lcigncGxhY2VfY2hhbmdlZCcsICgpID0+IHtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICBjb25zdCBwbGFjZTogZ29vZ2xlLm1hcHMucGxhY2VzLlBsYWNlUmVzdWx0ID0gYXV0b2NvbXBsZXRlLmdldFBsYWNlKCk7XG5cbiAgICAgICAgICBpZiAocGxhY2UuZ2VvbWV0cnkgPT09IHVuZGVmaW5lZCB8fCBwbGFjZS5nZW9tZXRyeSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmxhdGl0dWRlID0gcGxhY2UuZ2VvbWV0cnkubG9jYXRpb24ubGF0KCk7XG4gICAgICAgICAgdGhpcy5sb25naXR1ZGUgPSBwbGFjZS5nZW9tZXRyeS5sb2NhdGlvbi5sbmcoKTtcbiAgICAgICAgICB0aGlzLnpvb20gPSAxODtcbiAgICAgICAgICB0aGlzLmFkZHJlc3MgPSBwbGFjZS5mb3JtYXR0ZWRfYWRkcmVzcztcbiAgICAgICAgICAvLyBWRCAyMURFQzIzIC0gZGVwZW5kZW50IGZpZWxkIGNoYW5nZVxuICAgICAgICAgIGxldCBjaGFuZ2UgPSBuZXcgQ2hhbmdlV3JhcHBlcigpO1xuICAgICAgICAgIC8vIFJTIDA5REVDMjQgQ2hhbmdlZCBrZXlzXG4gICAgICAgICAgY2hhbmdlLmZyb21RdWVzdGlvbklkID0gdGhpcy5xdWVzdGlvbi5pZDtcbiAgICAgICAgICBsZXQgYWRkT2JqID0ge307XG4gICAgICAgICAgYWRkT2JqWydhZGRyZXNzJ10gPSB0aGlzLmFkZHJlc3M7XG4gICAgICAgICAgYWRkT2JqWydsYXRpdHVkZSddID0gdGhpcy5sYXRpdHVkZTtcbiAgICAgICAgICBhZGRPYmpbJ2xvbmdpdHVkZSddID0gdGhpcy5sb25naXR1ZGU7XG4gICAgICAgICAgY2hhbmdlLnZhbHVlT2JqID0gYWRkT2JqO1xuICAgICAgICAgdGhpcy5sb2NhdGlvblNlbGVjdGVkLmVtaXQoY2hhbmdlKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBvbk1hcmtlckRyYWdFbmQoKTogdm9pZCB7XG4gICAgZ29vZ2xlLm1hcHMuZXZlbnQuYWRkTGlzdGVuZXIodGhpcy5tYXJrZXJPcHRpb25zLCAnZHJhZ2VuZCcsIChldmVudCkgPT4ge1xuICAgICAgY29uc29sZS5sb2coJ2RyYWdhYmxlIHdvcmtpbmcnLGV2ZW50KTtcbiAgICAgIHRoaXMubGF0aXR1ZGUgPSBldmVudC5sYXRMbmcubGF0KCk7XG4gICAgICB0aGlzLmxvbmdpdHVkZSA9IGV2ZW50LmxhdExuZy5sbmcoKTtcbiAgICAgIHRoaXMuZ2V0QWRkcmVzcyh0aGlzLmxhdGl0dWRlLCB0aGlzLmxvbmdpdHVkZSk7XG4gIH0pO1xuICB9XG5cbiAgb25NYXBDbGljayhldmVudDogZ29vZ2xlLm1hcHMuTWFwTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGNvbnNvbGUubG9nKCdvbk1hcENsaWNrJyxldmVudCk7XG4gICAgdGhpcy5sYXRpdHVkZSA9IGV2ZW50LmxhdExuZy5sYXQoKTtcbiAgICB0aGlzLmxvbmdpdHVkZSA9IGV2ZW50LmxhdExuZy5sbmcoKTtcbiAgICB0aGlzLmdldEFkZHJlc3ModGhpcy5sYXRpdHVkZSwgdGhpcy5sb25naXR1ZGUpO1xuICB9XG5cblxuICBwcml2YXRlIHNldEN1cnJlbnRMb2NhdGlvbigpIHtcbiAgICBpZiAoJ2dlb2xvY2F0aW9uJyBpbiBuYXZpZ2F0b3IpIHtcbiAgICAgIG5hdmlnYXRvci5nZW9sb2NhdGlvbi5nZXRDdXJyZW50UG9zaXRpb24oKHBvc2l0aW9uKSA9PiB7XG4gICAgICAgIHRoaXMubGF0aXR1ZGUgPSBwb3NpdGlvbi5jb29yZHMubGF0aXR1ZGU7XG4gICAgICAgIHRoaXMubG9uZ2l0dWRlID0gcG9zaXRpb24uY29vcmRzLmxvbmdpdHVkZTtcbiAgICAgICAgdGhpcy5tYXJrZXJQb3NpdGlvbiA9IHsgbGF0OiB0aGlzLmxhdGl0dWRlLCBsbmc6IHRoaXMubG9uZ2l0dWRlIH07XG4gICAgICAgIHRoaXMuY2VudGVyID0geyBsYXQ6IHRoaXMubGF0aXR1ZGUsIGxuZzogdGhpcy5sb25naXR1ZGUgfTtcbiAgICAgICAgdGhpcy56b29tID0gODtcbiAgICAgICAgdGhpcy5nZXRBZGRyZXNzKHRoaXMubGF0aXR1ZGUsIHRoaXMubG9uZ2l0dWRlKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG5cbiAgZ2V0QWRkcmVzcyhsYXRpdHVkZTogbnVtYmVyLCBsb25naXR1ZGU6IG51bWJlcikge1xuICAgIGlmICh0aGlzLmdlb0NvZGVyKSB7XG4gICAgICB0aGlzLmdlb0NvZGVyLmdlb2NvZGUoeyBsb2NhdGlvbjogeyBsYXQ6IGxhdGl0dWRlLCBsbmc6IGxvbmdpdHVkZSB9IH0sIChyZXN1bHRzLCBzdGF0dXMpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ3Jlc3VsdHMnLHJlc3VsdHMpO1xuICAgICAgICBjb25zb2xlLmxvZygnc3RhdHVzJyxzdGF0dXMpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSAnT0snKSB7XG4gICAgICAgICAgaWYgKHJlc3VsdHNbMF0pIHtcbiAgICAgICAgICAgLy8gdGhpcy56b29tID0gMTg7XG4gICAgICAgICAgICB0aGlzLmFkZHJlc3MgPSByZXN1bHRzWzBdLmZvcm1hdHRlZF9hZGRyZXNzO1xuICAgICAgICAgICAgIC8vIFZEIDIxREVDMjMgLSBkZXBlbmRlbnQgZmllbGQgY2hhbmdlXG4gICAgICAgICAgICBsZXQgY2hhbmdlID0gbmV3IENoYW5nZVdyYXBwZXIoKTtcbiAgICAgICAgICAgIC8vIFJTIDA5REVDMjQgQ2hhbmdlZCBrZXlzXG4gICAgICAgICAgICBjaGFuZ2UuZnJvbVF1ZXN0aW9uSWQgPSB0aGlzLnF1ZXN0aW9uLmlkO1xuICAgICAgICAgICAgbGV0IGFkZE9iajEgPSB7fTtcbiAgICAgICAgICAgIGFkZE9iajFbJ2FkZHJlc3MnXSA9IHRoaXMuYWRkcmVzcztcbiAgICAgICAgICAgIGFkZE9iajFbJ2xhdGl0dWRlJ10gPSBsYXRpdHVkZTtcbiAgICAgICAgICAgIGFkZE9iajFbJ2xvbmdpdHVkZSddID0gbG9uZ2l0dWRlO1xuICAgICAgICAgICAgY2hhbmdlLnZhbHVlT2JqID0gYWRkT2JqMTtcbiAgICAgICAgICAgIHRoaXMubG9jYXRpb25TZWxlY3RlZC5lbWl0KGNoYW5nZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdObyByZXN1bHRzIGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdHZW9jb2RlciBmYWlsZWQgZHVlIHRvOiAnICsgc3RhdHVzKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgb3Blbk1hcCgpIHtcbiAgICB0aGlzLnNob3dNb2RhbCA9IHRydWU7XG4gICAgaWYoIXRoaXMuYWRkcmVzcyl7XG4gICAgICB0aGlzLmxhdGl0dWRlID0gdGhpcy5sb25naXR1ZGUgPSBudWxsO1xuICAgIH1cbiAgICBpZiAoISh0aGlzLmxhdGl0dWRlICYmIHRoaXMubG9uZ2l0dWRlKSkge1xuICAgICAgdGhpcy5zZXRDdXJyZW50TG9jYXRpb24oKTtcbiAgICB9ZWxzZXtcbiAgICAgIHRoaXMubWFya2VyUG9zaXRpb24gPSB7IGxhdDogdGhpcy5sYXRpdHVkZSwgbG5nOiB0aGlzLmxvbmdpdHVkZSB9O1xuICAgICAgdGhpcy5jZW50ZXIgPSB7IGxhdDogdGhpcy5sYXRpdHVkZSwgbG5nOiB0aGlzLmxvbmdpdHVkZSB9O1xuICAgICAgdGhpcy56b29tID0gODtcbiAgICB9XG4gIH1cblxuICBjbG9zZU1vZGFsKCkge1xuICAgIHRoaXMuc2hvd01vZGFsID0gZmFsc2U7XG4gIH1cbiAgcmVtb3ZlQ2hhcmFjdGVycyhxdWVzdGlvblRleHQ6c3RyaW5nKXtcbiAgICBsZXQgdXBkYXRlZFRleHQgPSBxdWVzdGlvblRleHQ/LnJlcGxhY2UoLzxbXj5dKj4vZywgJycpO1xuICAgIHJldHVybiB1cGRhdGVkVGV4dDtcbiAgfVxuXG59XG5cbiIsIjxkaXY+XG4gIDxueHQtaW5wdXQgW3R5cGVdPVwiJ2xvY2F0aW9uJ1wiIFttb2RlXT1cIm1vZGVcIiBbdmFsdWVdPVwiYWRkcmVzc1wiXG4gICAgW2xhYmVsRm9udF09XCJxdWVzdGlvbi5mb250XCIgW2xhYmVsXT1cInJlbW92ZUNoYXJhY3RlcnMocXVlc3Rpb24/LnF1ZXN0aW9uVGV4dClcIiBbbGFiZWxDb2xvcl09XCJxdWVzdGlvbi5mb250Q29sb3JcIlxuICAgIFtsYWJlbFNpemVdPVwicXVlc3Rpb24uZm9udFNpemVcIiBbaW5wdXRWYWx1ZVNpemVdPVwicXVlc3Rpb24uZm9udFNpemVcIiBbbGFiZWxXZWlnaHRdPVwicXVlc3Rpb24uZm9udFdlaWdodFwiXG4gICAgW2lucHV0V2VpZ2h0XT1cInF1ZXN0aW9uLmZvbnRXZWlnaHRcIiBbc2hvd0xhYmVsXT1cInF1ZXN0aW9uLnN0eWxlPy5zaG93TGFiZWxcIiBpbnB1dEJvcmRlcj1cIm5vbmVcIiBzdmdIZWlnaHQ9XCIyMHB4XCJcbiAgICBzdmdXaWR0aD1cIjIwcHhcIiBbcGxhY2Vob2xkZXJdPVwicXVlc3Rpb24ucXVlc3Rpb25cIiBbcmVxdWlyZWRdPVwicXVlc3Rpb24uaXNPcHRpb25hbFwiIGlucHV0QmdDb2xvcj1cIiNGNUY1RjVcIlxuICAgIFtpbnB1dElkXT1cInF1ZXN0aW9uLnRyYWNraW5nSWRcIiBbZXJyb3JNZXNzYWdlc109XCJ7IHJlcXVpcmVkOiAnVGhpcyBmaWVsZCBpcyByZXF1aXJlZCcgfVwiXG4gICAgW2lucHV0SWNvbkxlZnRTcmNdPVwicXVlc3Rpb24uaWNvbkxlZnRTcmNcIiAobmF0aXZlSW5wdXRSZWYpPVwic2V0SW5wdXRSZWYoJGV2ZW50KVwiPlxuICA8L254dC1pbnB1dD5cbiAgPGEgKm5nSWY9XCJtb2RlID09PSAnZWRpdCcgJiYgIXF1ZXN0aW9uLmlzUmVhZE9ubHlcIiAoY2xpY2spPVwib3Blbk1hcCgpXCIgc3R5bGU9XCJjb2xvcjojNDhCN0ZGO3Bvc2l0aW9uOnJlbGF0aXZlO3RvcDo1cHg7Y3Vyc29yOiBwb2ludGVyO1wiPlxuICAgIHt7ICdwaWNrTG9jYXRpb24nIHwgaTE4bjppMThuU2VydmljZS5jdXJyZW50TGFuZ3VhZ2UgfX08L2E+XG48L2Rpdj5cblxuPGRpdiBjbGFzcz1cIm1hcC1vdmVybGF5XCIgKm5nSWY9XCJzaG93TW9kYWxcIj5cbiAgPGRpdiBjbGFzcz1cIm1hcC1tb2RhbFwiPlxuICAgIDxkaXYgY2xhc3M9XCJtYXAtbW9kYWwtY29udGVudFwiPlxuICAgICAgPGRpdiBjbGFzcz1cIm1hcC1tb2RhbC1oZWFkZXJcIj5cbiAgICAgICAgPCEtLSBIQSAxOURFQzIzIEZvciB0cmFuc2xhdGlvbiAtLT5cbiAgICAgICAgPGg0Pnt7ICdwaWNrWW91ckxvY2F0aW9uJyB8IGkxOG46aTE4blNlcnZpY2UuY3VycmVudExhbmd1YWdlIH19PC9oND5cbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImNsb3NlLWJ1dHRvblwiIChjbGljayk9XCJjbG9zZU1vZGFsKClcIj5YPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxnb29nbGUtbWFwIFt6b29tXT1cInpvb21cIiBbY2VudGVyXT1cImNlbnRlclwiIChtYXBDbGljayk9XCJvbk1hcENsaWNrKCRldmVudClcIj5cbiAgICAgICAgPG1hcC1tYXJrZXIgW3Bvc2l0aW9uXT1cIm1hcmtlclBvc2l0aW9uXCIgW29wdGlvbnNdPVwibWFya2VyT3B0aW9uc1wiPjwvbWFwLW1hcmtlcj5cbiAgICAgIDwvZ29vZ2xlLW1hcD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj4iXX0=