UNPKG

@spartacus/storefront

Version:

Spartacus Storefront is a package that you can include in your application, which allows you to add default storefront features.

208 lines 52.6 kB
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, } from '@angular/core'; import { Validators } from '@angular/forms'; import { GlobalMessageType, } from '@spartacus/core'; import { BehaviorSubject, combineLatest } from 'rxjs'; import { map, switchMap, take, tap } from 'rxjs/operators'; import { sortTitles } from '../../../../shared/utils/forms/title-utils'; import { SuggestedAddressDialogComponent } from './suggested-addresses-dialog/suggested-addresses-dialog.component'; import * as i0 from "@angular/core"; import * as i1 from "@angular/forms"; import * as i2 from "@spartacus/core"; import * as i3 from "../../../../shared/components/modal/index"; import * as i4 from "@ng-select/ng-select"; import * as i5 from "../../../../shared/components/form/form-errors/form-errors.component"; import * as i6 from "@angular/common"; export class AddressFormComponent { constructor(fb, userService, userAddressService, globalMessageService, modalService, translation) { this.fb = fb; this.userService = userService; this.userAddressService = userAddressService; this.globalMessageService = globalMessageService; this.modalService = modalService; this.translation = translation; this.selectedCountry$ = new BehaviorSubject(''); this.setAsDefaultField = true; this.showCancelBtn = true; this.submitAddress = new EventEmitter(); this.backToAddress = new EventEmitter(); this.addressForm = this.fb.group({ country: this.fb.group({ isocode: [null, Validators.required], }), titleCode: [''], firstName: ['', Validators.required], lastName: ['', Validators.required], line1: ['', Validators.required], line2: [''], town: ['', Validators.required], region: this.fb.group({ isocode: [null, Validators.required], }), postalCode: ['', Validators.required], phone: '', defaultAddress: [false], }); } ngOnInit() { // Fetching countries this.countries$ = this.userAddressService.getDeliveryCountries().pipe(tap((countries) => { if (Object.keys(countries).length === 0) { this.userAddressService.loadDeliveryCountries(); } })); // Fetching titles this.titles$ = this.getTitles(); // Fetching regions this.regions$ = this.selectedCountry$.pipe(switchMap((country) => this.userAddressService.getRegions(country)), tap((regions) => { const regionControl = this.addressForm.get('region.isocode'); if (regions && regions.length > 0) { regionControl.enable(); } else { regionControl.disable(); } })); if (this.addressData && Object.keys(this.addressData).length !== 0) { this.addressForm.patchValue(this.addressData); this.countrySelected(this.addressData.country); if (this.addressData.region) { this.regionSelected(this.addressData.region); } } this.addresses$ = this.userAddressService.getAddresses(); } getTitles() { return combineLatest([ this.translation.translate('addressForm.defaultTitle'), this.userService.getTitles(), ]).pipe(map(([noneTitleText, titles]) => { const noneTitle = { code: '', name: noneTitleText }; titles.sort(sortTitles); return [noneTitle, ...titles]; })); } handleAddressVerificationResults(results) { if (results.decision === 'ACCEPT') { this.submitAddress.emit(this.addressForm.value); } else if (results.decision === 'REJECT') { // TODO: Workaround: allow server for decide is titleCode mandatory (if yes, provide personalized message) if (results.errors.errors.some((error) => error.subject === 'titleCode')) { this.globalMessageService.add({ key: 'addressForm.titleRequired' }, GlobalMessageType.MSG_TYPE_ERROR); } else { this.globalMessageService.add({ key: 'addressForm.invalidAddress' }, GlobalMessageType.MSG_TYPE_ERROR); } } else if (results.decision === 'REVIEW') { this.openSuggestedAddress(results); } } countrySelected(country) { var _a, _b; (_b = (_a = this.addressForm.get('country')) === null || _a === void 0 ? void 0 : _a.get('isocode')) === null || _b === void 0 ? void 0 : _b.setValue(country.isocode); this.selectedCountry$.next(country.isocode); } regionSelected(region) { var _a, _b; (_b = (_a = this.addressForm.get('region')) === null || _a === void 0 ? void 0 : _a.get('isocode')) === null || _b === void 0 ? void 0 : _b.setValue(region.isocode); } toggleDefaultAddress() { this.addressForm['controls'].defaultAddress.setValue(this.addressForm.value.defaultAddress); } back() { this.backToAddress.emit(); } verifyAddress() { if (this.addressForm.valid) { if (this.addressForm.get('region').value.isocode) { this.regionsSub = this.regions$.pipe(take(1)).subscribe((regions) => { const obj = regions.find((region) => region.isocode === this.addressForm.controls['region'].value.isocode); Object.assign(this.addressForm.value.region, { isocodeShort: obj.isocodeShort, }); }); } if (this.addressForm.dirty) { this.userAddressService .verifyAddress(this.addressForm.value) .subscribe((result) => { this.handleAddressVerificationResults(result); }); } else { // address form value not changed // ignore duplicate address this.submitAddress.emit(undefined); } } else { this.addressForm.markAllAsTouched(); } } openSuggestedAddress(results) { if (!this.suggestedAddressModalRef) { this.suggestedAddressModalRef = this.modalService.open(SuggestedAddressDialogComponent, { centered: true, size: 'lg' }); this.suggestedAddressModalRef.componentInstance.enteredAddress = this.addressForm.value; this.suggestedAddressModalRef.componentInstance.suggestedAddresses = results.suggestedAddresses; this.suggestedAddressModalRef.result .then((address) => { if (address) { address = Object.assign({ titleCode: this.addressForm.value.titleCode, phone: this.addressForm.value.phone, selected: true, }, address); this.submitAddress.emit(address); } this.suggestedAddressModalRef = null; }) .catch(() => { // this callback is called when modal is closed with Esc key or clicking backdrop const address = Object.assign({ selected: true, }, this.addressForm.value); this.submitAddress.emit(address); this.suggestedAddressModalRef = null; }); } } ngOnDestroy() { if (this.addressVerifySub) { this.addressVerifySub.unsubscribe(); } if (this.regionsSub) { this.regionsSub.unsubscribe(); } } } AddressFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: AddressFormComponent, deps: [{ token: i1.FormBuilder }, { token: i2.UserService }, { token: i2.UserAddressService }, { token: i2.GlobalMessageService }, { token: i3.ModalService }, { token: i2.TranslationService }], target: i0.ɵɵFactoryTarget.Component }); AddressFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.0.5", type: AddressFormComponent, selector: "cx-address-form", inputs: { addressData: "addressData", actionBtnLabel: "actionBtnLabel", cancelBtnLabel: "cancelBtnLabel", setAsDefaultField: "setAsDefaultField", showTitleCode: "showTitleCode", showCancelBtn: "showCancelBtn" }, outputs: { submitAddress: "submitAddress", backToAddress: "backToAddress" }, ngImport: i0, template: "<form (ngSubmit)=\"verifyAddress()\" [formGroup]=\"addressForm\">\n <div class=\"row\">\n <div class=\"col-md-12 col-lg-9\">\n <div class=\"form-group\" formGroupName=\"country\">\n <ng-container *ngIf=\"countries$ | async as countries\">\n <div *ngIf=\"countries.length !== 0\">\n <label>\n <span class=\"label-content required\">{{\n 'addressForm.country' | cxTranslate\n }}</span>\n <ng-select\n aria-required=\"true\"\n class=\"country-select\"\n formControlName=\"isocode\"\n [searchable]=\"true\"\n [clearable]=\"false\"\n [items]=\"countries\"\n bindLabel=\"name\"\n bindValue=\"isocode\"\n placeholder=\"{{ 'addressForm.selectOne' | cxTranslate }}\"\n (change)=\"countrySelected($event)\"\n >\n </ng-select>\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"addressForm.get('country.isocode')\"\n ></cx-form-errors>\n </label>\n </div>\n </ng-container>\n </div>\n <div class=\"form-group\" *ngIf=\"showTitleCode\">\n <ng-container *ngIf=\"titles$ | async as titles\">\n <div *ngIf=\"titles.length !== 0\">\n <label>\n <span class=\"label-content required\">{{\n 'addressForm.title' | cxTranslate\n }}</span>\n <ng-select\n formControlName=\"titleCode\"\n [searchable]=\"true\"\n [clearable]=\"false\"\n [items]=\"titles\"\n bindLabel=\"name\"\n bindValue=\"code\"\n [placeholder]=\"'addressForm.title' | cxTranslate\"\n >\n </ng-select>\n </label>\n </div>\n </ng-container>\n </div>\n <div class=\"form-group\">\n <label>\n <span class=\"label-content required\">{{\n 'addressForm.firstName.label' | cxTranslate\n }}</span>\n <input\n aria-required=\"true\"\n class=\"form-control\"\n type=\"text\"\n placeholder=\"{{\n 'addressForm.firstName.placeholder' | cxTranslate\n }}\"\n formControlName=\"firstName\"\n />\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"addressForm.get('firstName')\"\n ></cx-form-errors>\n </label>\n </div>\n <div class=\"form-group\">\n <label>\n <span class=\"label-content required\">{{\n 'addressForm.lastName.label' | cxTranslate\n }}</span>\n <input\n aria-required=\"true\"\n type=\"text\"\n class=\"form-control\"\n placeholder=\"{{ 'addressForm.lastName.placeholder' | cxTranslate }}\"\n formControlName=\"lastName\"\n />\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"addressForm.get('lastName')\"\n ></cx-form-errors>\n </label>\n </div>\n <div class=\"form-group\">\n <label>\n <span class=\"label-content required\">{{\n 'addressForm.address1' | cxTranslate\n }}</span>\n <input\n aria-required=\"true\"\n type=\"text\"\n class=\"form-control\"\n placeholder=\"{{ 'addressForm.streetAddress' | cxTranslate }}\"\n formControlName=\"line1\"\n />\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"addressForm.get('line1')\"\n ></cx-form-errors>\n </label>\n </div>\n <div class=\"form-group\">\n <label>\n <span class=\"label-content\">{{\n 'addressForm.address2' | cxTranslate\n }}</span>\n <input\n type=\"text\"\n class=\"form-control\"\n placeholder=\"{{ 'addressForm.aptSuite' | cxTranslate }}\"\n formControlName=\"line2\"\n />\n </label>\n </div>\n <div class=\"row\">\n <div class=\"form-group col-md-6\">\n <label>\n <span class=\"label-content required\">{{\n 'addressForm.city.label' | cxTranslate\n }}</span>\n <input\n aria-required=\"true\"\n type=\"text\"\n class=\"form-control\"\n placeholder=\"{{ 'addressForm.city.placeholder' | cxTranslate }}\"\n formControlName=\"town\"\n />\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"addressForm.get('town')\"\n ></cx-form-errors>\n </label>\n </div>\n <div class=\"form-group col-md-6\">\n <label>\n <span class=\"label-content required\">{{\n 'addressForm.zipCode.label' | cxTranslate\n }}</span>\n <input\n aria-required=\"true\"\n type=\"text\"\n class=\"form-control\"\n placeholder=\"{{\n 'addressForm.zipCode.placeholder' | cxTranslate\n }}\"\n formControlName=\"postalCode\"\n />\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"addressForm.get('postalCode')\"\n ></cx-form-errors>\n </label>\n </div>\n <ng-container\n *ngIf=\"regions$ | async as regions\"\n formGroupName=\"region\"\n >\n <ng-container *ngIf=\"regions.length !== 0\">\n <div class=\"form-group col-md-6\">\n <label>\n <span class=\"label-content required\">{{\n 'addressForm.state' | cxTranslate\n }}</span>\n <ng-select\n aria-required=\"true\"\n class=\"region-select\"\n formControlName=\"isocode\"\n [searchable]=\"true\"\n [clearable]=\"false\"\n [items]=\"regions\"\n bindLabel=\"{{ regions[0].name ? 'name' : 'isocode' }}\"\n bindValue=\"{{ regions[0].name ? 'isocode' : 'region' }}\"\n placeholder=\"{{ 'addressForm.selectOne' | cxTranslate }}\"\n >\n </ng-select>\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"addressForm.get('region.isocode')\"\n ></cx-form-errors>\n </label>\n </div>\n </ng-container>\n </ng-container>\n </div>\n <div class=\"form-group\">\n <label>\n <span class=\"label-content\">{{\n 'addressForm.phoneNumber.label' | cxTranslate\n }}</span>\n <input\n type=\"tel\"\n class=\"form-control\"\n placeholder=\"{{\n 'addressForm.phoneNumber.placeholder' | cxTranslate\n }}\"\n formControlName=\"phone\"\n />\n </label>\n </div>\n <div\n class=\"form-group\"\n *ngIf=\"(addresses$ | async).length && setAsDefaultField\"\n >\n <div class=\"form-check\">\n <label>\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n formControlName=\"defaultAddress\"\n (change)=\"toggleDefaultAddress()\"\n />\n <span class=\"form-check-label\">{{\n 'addressForm.setAsDefault' | cxTranslate\n }}</span>\n </label>\n </div>\n </div>\n </div>\n </div>\n <div class=\"cx-address-form-btns row\">\n <div class=\"col-md-12 col-lg-6\" *ngIf=\"showCancelBtn\">\n <button class=\"btn btn-block btn-action\" (click)=\"back()\">\n {{ cancelBtnLabel || ('addressForm.chooseAddress' | cxTranslate) }}\n </button>\n </div>\n <div class=\"col-md-12 col-lg-6\">\n <button class=\"btn btn-block btn-primary\" type=\"submit\">\n {{ actionBtnLabel || ('common.continue' | cxTranslate) }}\n </button>\n </div>\n </div>\n</form>\n", components: [{ type: i4.NgSelectComponent, selector: "ng-select", inputs: ["markFirst", "dropdownPosition", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "bufferAmount", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "bindLabel", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "virtualScroll", "openOnEnter", "appendTo", "bindValue", "appearance", "maxSelectedItems", "groupBy", "groupValue", "tabIndex", "typeahead"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { type: i5.FormErrorsComponent, selector: "cx-form-errors", inputs: ["prefix", "translationParams", "control"] }], directives: [{ type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }], pipes: { "async": i6.AsyncPipe, "cxTranslate": i2.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: AddressFormComponent, decorators: [{ type: Component, args: [{ selector: 'cx-address-form', templateUrl: './address-form.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }] }], ctorParameters: function () { return [{ type: i1.FormBuilder }, { type: i2.UserService }, { type: i2.UserAddressService }, { type: i2.GlobalMessageService }, { type: i3.ModalService }, { type: i2.TranslationService }]; }, propDecorators: { addressData: [{ type: Input }], actionBtnLabel: [{ type: Input }], cancelBtnLabel: [{ type: Input }], setAsDefaultField: [{ type: Input }], showTitleCode: [{ type: Input }], showCancelBtn: [{ type: Input }], submitAddress: [{ type: Output }], backToAddress: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRkcmVzcy1mb3JtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0b3JlZnJvbnRsaWIvY21zLWNvbXBvbmVudHMvbXlhY2NvdW50L2FkZHJlc3MtYm9vay9hZGRyZXNzLWZvcm0vYWRkcmVzcy1mb3JtLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0b3JlZnJvbnRsaWIvY21zLWNvbXBvbmVudHMvbXlhY2NvdW50L2FkZHJlc3MtYm9vay9hZGRyZXNzLWZvcm0vYWRkcmVzcy1mb3JtLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBR0wsTUFBTSxHQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBMEIsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDcEUsT0FBTyxFQU1MLGlCQUFpQixHQU1sQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUE0QixNQUFNLE1BQU0sQ0FBQztBQUNoRixPQUFPLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFLM0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxNQUFNLG1FQUFtRSxDQUFDOzs7Ozs7OztBQU9wSCxNQUFNLE9BQU8sb0JBQW9CO0lBcUQvQixZQUNZLEVBQWUsRUFDZixXQUF3QixFQUN4QixrQkFBc0MsRUFDdEMsb0JBQTBDLEVBQzFDLFlBQTBCLEVBQzFCLFdBQStCO1FBTC9CLE9BQUUsR0FBRixFQUFFLENBQWE7UUFDZixnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN4Qix1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QUFNLENBQUMsTUFBTSxDQUMzQjtvQkFDRSxRQUFRLEVBQUUsSUFBSTtpQkFDZixFQUNELElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUN2QixDQUFDO2dCQUNGLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUNqQyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsSUFBSSxDQUFDO1lBQ3ZDLENBQUMsQ0FBQyxDQUFDO1NBQ047SUFDSCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFO1lBQ3pCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztTQUNyQztRQUVELElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNuQixJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQy9CO0lBQ0gsQ0FBQzs7aUhBM09VLG9CQUFvQjtxR0FBcEIsb0JBQW9CLHdWQ3JDakMscS9RQXNQQTsyRkRqTmEsb0JBQW9CO2tCQUxoQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxpQkFBaUI7b0JBQzNCLFdBQVcsRUFBRSwrQkFBK0I7b0JBQzVDLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO2lCQUNoRDs0UEFTQyxXQUFXO3NCQURWLEtBQUs7Z0JBSU4sY0FBYztzQkFEYixLQUFLO2dCQUlOLGNBQWM7c0JBRGIsS0FBSztnQkFJTixpQkFBaUI7c0JBRGhCLEtBQUs7Z0JBSU4sYUFBYTtzQkFEWixLQUFLO2dCQUlOLGFBQWE7c0JBRFosS0FBSztnQkFJTixhQUFhO3NCQURaLE1BQU07Z0JBSVAsYUFBYTtzQkFEWixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQnVpbGRlciwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHtcbiAgQWRkcmVzcyxcbiAgQWRkcmVzc1ZhbGlkYXRpb24sXG4gIENvdW50cnksXG4gIEVycm9yTW9kZWwsXG4gIEdsb2JhbE1lc3NhZ2VTZXJ2aWNlLFxuICBHbG9iYWxNZXNzYWdlVHlwZSxcbiAgUmVnaW9uLFxuICBUaXRsZSxcbiAgVHJhbnNsYXRpb25TZXJ2aWNlLFxuICBVc2VyQWRkcmVzc1NlcnZpY2UsXG4gIFVzZXJTZXJ2aWNlLFxufSBmcm9tICdAc3BhcnRhY3VzL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBjb21iaW5lTGF0ZXN0LCBPYnNlcnZhYmxlLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgc3dpdGNoTWFwLCB0YWtlLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge1xuICBNb2RhbFJlZixcbiAgTW9kYWxTZXJ2aWNlLFxufSBmcm9tICcuLi8uLi8uLi8uLi9zaGFyZWQvY29tcG9uZW50cy9tb2RhbC9pbmRleCc7XG5pbXBvcnQgeyBzb3J0VGl0bGVzIH0gZnJvbSAnLi4vLi4vLi4vLi4vc2hhcmVkL3V0aWxzL2Zvcm1zL3RpdGxlLXV0aWxzJztcbmltcG9ydCB7IFN1Z2dlc3RlZEFkZHJlc3NEaWFsb2dDb21wb25lbnQgfSBmcm9tICcuL3N1Z2dlc3RlZC1hZGRyZXNzZXMtZGlhbG9nL3N1Z2dlc3RlZC1hZGRyZXNzZXMtZGlhbG9nLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2N4LWFkZHJlc3MtZm9ybScsXG4gIHRlbXBsYXRlVXJsOiAnLi9hZGRyZXNzLWZvcm0uY29tcG9uZW50Lmh0bWwnLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgQWRkcmVzc0Zvcm1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIGNvdW50cmllcyQ6IE9ic2VydmFibGU8Q291bnRyeVtdPjtcbiAgdGl0bGVzJDogT2JzZXJ2YWJsZTxUaXRsZVtdPjtcbiAgcmVnaW9ucyQ6IE9ic2VydmFibGU8UmVnaW9uW10+O1xuICBzZWxlY3RlZENvdW50cnkkOiBCZWhhdmlvclN1YmplY3Q8c3RyaW5nPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nPignJyk7XG4gIGFkZHJlc3NlcyQ6IE9ic2VydmFibGU8QWRkcmVzc1tdPjtcblxuICBASW5wdXQoKVxuICBhZGRyZXNzRGF0YTogQWRkcmVzcztcblxuICBASW5wdXQoKVxuICBhY3Rpb25CdG5MYWJlbDogc3RyaW5nO1xuXG4gIEBJbnB1dCgpXG4gIGNhbmNlbEJ0bkxhYmVsOiBzdHJpbmc7XG5cbiAgQElucHV0KClcbiAgc2V0QXNEZWZhdWx0RmllbGQgPSB0cnVlO1xuXG4gIEBJbnB1dCgpXG4gIHNob3dUaXRsZUNvZGU6IGJvb2xlYW47XG5cbiAgQElucHV0KClcbiAgc2hvd0NhbmNlbEJ0biA9IHRydWU7XG5cbiAgQE91dHB1dCgpXG4gIHN1Ym1pdEFkZHJlc3MgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBAT3V0cHV0KClcbiAgYmFja1RvQWRkcmVzcyA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIGFkZHJlc3NWZXJpZnlTdWI6IFN1YnNjcmlwdGlvbjtcbiAgcmVnaW9uc1N1YjogU3Vic2NyaXB0aW9uO1xuICBzdWdnZXN0ZWRBZGRyZXNzTW9kYWxSZWY6IE1vZGFsUmVmO1xuXG4gIGFkZHJlc3NGb3JtOiBGb3JtR3JvdXAgPSB0aGlzLmZiLmdyb3VwKHtcbiAgICBjb3VudHJ5OiB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIGlzb2NvZGU6IFtudWxsLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICB9KSxcbiAgICB0aXRsZUNvZGU6IFsnJ10sXG4gICAgZmlyc3ROYW1lOiBbJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgIGxhc3ROYW1lOiBbJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgIGxpbmUxOiBbJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgIGxpbmUyOiBbJyddLFxuICAgIHRvd246IFsnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgcmVnaW9uOiB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIGlzb2NvZGU6IFtudWxsLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICB9KSxcbiAgICBwb3N0YWxDb2RlOiBbJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgIHBob25lOiAnJyxcbiAgICBkZWZhdWx0QWRkcmVzczogW2ZhbHNlXSxcbiAgfSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIGZiOiBGb3JtQnVpbGRlcixcbiAgICBwcm90ZWN0ZWQgdXNlclNlcnZpY2U6IFVzZXJTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCB1c2VyQWRkcmVzc1NlcnZpY2U6IFVzZXJBZGRyZXNzU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgZ2xvYmFsTWVzc2FnZVNlcnZpY2U6IEdsb2JhbE1lc3NhZ2VTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBtb2RhbFNlcnZpY2U6IE1vZGFsU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgdHJhbnNsYXRpb246IFRyYW5zbGF0aW9uU2VydmljZVxuICApIHt9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgLy8gRmV0Y2hpbmcgY291bnRyaWVzXG4gICAgdGhpcy5jb3VudHJpZXMkID0gdGhpcy51c2VyQWRkcmVzc1NlcnZpY2UuZ2V0RGVsaXZlcnlDb3VudHJpZXMoKS5waXBlKFxuICAgICAgdGFwKChjb3VudHJpZXM6IENvdW50cnlbXSkgPT4ge1xuICAgICAgICBpZiAoT2JqZWN0LmtleXMoY291bnRyaWVzKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLnVzZXJBZGRyZXNzU2VydmljZS5sb2FkRGVsaXZlcnlDb3VudHJpZXMoKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gRmV0Y2hpbmcgdGl0bGVzXG4gICAgdGhpcy50aXRsZXMkID0gdGhpcy5nZXRUaXRsZXMoKTtcblxuICAgIC8vIEZldGNoaW5nIHJlZ2lvbnNcbiAgICB0aGlzLnJlZ2lvbnMkID0gdGhpcy5zZWxlY3RlZENvdW50cnkkLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKGNvdW50cnkpID0+IHRoaXMudXNlckFkZHJlc3NTZXJ2aWNlLmdldFJlZ2lvbnMoY291bnRyeSkpLFxuICAgICAgdGFwKChyZWdpb25zOiBSZWdpb25bXSkgPT4ge1xuICAgICAgICBjb25zdCByZWdpb25Db250cm9sID0gdGhpcy5hZGRyZXNzRm9ybS5nZXQoJ3JlZ2lvbi5pc29jb2RlJyk7XG4gICAgICAgIGlmIChyZWdpb25zICYmIHJlZ2lvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHJlZ2lvbkNvbnRyb2wuZW5hYmxlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVnaW9uQ29udHJvbC5kaXNhYmxlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcblxuICAgIGlmICh0aGlzLmFkZHJlc3NEYXRhICYmIE9iamVjdC5rZXlzKHRoaXMuYWRkcmVzc0RhdGEpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgdGhpcy5hZGRyZXNzRm9ybS5wYXRjaFZhbHVlKHRoaXMuYWRkcmVzc0RhdGEpO1xuXG4gICAgICB0aGlzLmNvdW50cnlTZWxlY3RlZCh0aGlzLmFkZHJlc3NEYXRhLmNvdW50cnkpO1xuICAgICAgaWYgKHRoaXMuYWRkcmVzc0RhdGEucmVnaW9uKSB7XG4gICAgICAgIHRoaXMucmVnaW9uU2VsZWN0ZWQodGhpcy5hZGRyZXNzRGF0YS5yZWdpb24pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuYWRkcmVzc2VzJCA9IHRoaXMudXNlckFkZHJlc3NTZXJ2aWNlLmdldEFkZHJlc3NlcygpO1xuICB9XG5cbiAgZ2V0VGl0bGVzKCk6IE9ic2VydmFibGU8VGl0bGVbXT4ge1xuICAgIHJldHVybiBjb21iaW5lTGF0ZXN0KFtcbiAgICAgIHRoaXMudHJhbnNsYXRpb24udHJhbnNsYXRlKCdhZGRyZXNzRm9ybS5kZWZhdWx0VGl0bGUnKSxcbiAgICAgIHRoaXMudXNlclNlcnZpY2UuZ2V0VGl0bGVzKCksXG4gICAgXSkucGlwZShcbiAgICAgIG1hcCgoW25vbmVUaXRsZVRleHQsIHRpdGxlc10pID0+IHtcbiAgICAgICAgY29uc3Qgbm9uZVRpdGxlID0geyBjb2RlOiAnJywgbmFtZTogbm9uZVRpdGxlVGV4dCB9O1xuICAgICAgICB0aXRsZXMuc29ydChzb3J0VGl0bGVzKTtcbiAgICAgICAgcmV0dXJuIFtub25lVGl0bGUsIC4uLnRpdGxlc107XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlQWRkcmVzc1ZlcmlmaWNhdGlvblJlc3VsdHMocmVzdWx0czogQWRkcmVzc1ZhbGlkYXRpb24pIHtcbiAgICBpZiAocmVzdWx0cy5kZWNpc2lvbiA9PT0gJ0FDQ0VQVCcpIHtcbiAgICAgIHRoaXMuc3VibWl0QWRkcmVzcy5lbWl0KHRoaXMuYWRkcmVzc0Zvcm0udmFsdWUpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0cy5kZWNpc2lvbiA9PT0gJ1JFSkVDVCcpIHtcbiAgICAgIC8vIFRPRE86IFdvcmthcm91bmQ6IGFsbG93IHNlcnZlciBmb3IgZGVjaWRlIGlzIHRpdGxlQ29kZSBtYW5kYXRvcnkgKGlmIHllcywgcHJvdmlkZSBwZXJzb25hbGl6ZWQgbWVzc2FnZSlcbiAgICAgIGlmIChcbiAgICAgICAgcmVzdWx0cy5lcnJvcnMuZXJyb3JzLnNvbWUoXG4gICAgICAgICAgKGVycm9yOiBFcnJvck1vZGVsKSA9PiBlcnJvci5zdWJqZWN0ID09PSAndGl0bGVDb2RlJ1xuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgdGhpcy5nbG9iYWxNZXNzYWdlU2VydmljZS5hZGQoXG4gICAgICAgICAgeyBrZXk6ICdhZGRyZXNzRm9ybS50aXRsZVJlcXVpcmVkJyB9LFxuICAgICAgICAgIEdsb2JhbE1lc3NhZ2VUeXBlLk1TR19UWVBFX0VSUk9SXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmdsb2JhbE1lc3NhZ2VTZXJ2aWNlLmFkZChcbiAgICAgICAgICB7IGtleTogJ2FkZHJlc3NGb3JtLmludmFsaWRBZGRyZXNzJyB9LFxuICAgICAgICAgIEdsb2JhbE1lc3NhZ2VUeXBlLk1TR19UWVBFX0VSUk9SXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChyZXN1bHRzLmRlY2lzaW9uID09PSAnUkVWSUVXJykge1xuICAgICAgdGhpcy5vcGVuU3VnZ2VzdGVkQWRkcmVzcyhyZXN1bHRzKTtcbiAgICB9XG4gIH1cblxuICBjb3VudHJ5U2VsZWN0ZWQoY291bnRyeTogQ291bnRyeSk6IHZvaWQge1xuICAgIHRoaXMuYWRkcmVzc0Zvcm0uZ2V0KCdjb3VudHJ5Jyk/LmdldCgnaXNvY29kZScpPy5zZXRWYWx1ZShjb3VudHJ5Lmlzb2NvZGUpO1xuICAgIHRoaXMuc2VsZWN0ZWRDb3VudHJ5JC5uZXh0KGNvdW50cnkuaXNvY29kZSk7XG4gIH1cblxuICByZWdpb25TZWxlY3RlZChyZWdpb246IFJlZ2lvbik6IHZvaWQge1xuICAgIHRoaXMuYWRkcmVzc0Zvcm0uZ2V0KCdyZWdpb24nKT8uZ2V0KCdpc29jb2RlJyk/LnNldFZhbHVlKHJlZ2lvbi5pc29jb2RlKTtcbiAgfVxuXG4gIHRvZ2dsZURlZmF1bHRBZGRyZXNzKCk6IHZvaWQge1xuICAgIHRoaXMuYWRkcmVzc0Zvcm1bJ2NvbnRyb2xzJ10uZGVmYXVsdEFkZHJlc3Muc2V0VmFsdWUoXG4gICAgICB0aGlzLmFkZHJlc3NGb3JtLnZhbHVlLmRlZmF1bHRBZGRyZXNzXG4gICAgKTtcbiAgfVxuXG4gIGJhY2soKTogdm9pZCB7XG4gICAgdGhpcy5iYWNrVG9BZGRyZXNzLmVtaXQoKTtcbiAgfVxuXG4gIHZlcmlmeUFkZHJlc3MoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYWRkcmVzc0Zvcm0udmFsaWQpIHtcbiAgICAgIGlmICh0aGlzLmFkZHJlc3NGb3JtLmdldCgncmVnaW9uJykudmFsdWUuaXNvY29kZSkge1xuICAgICAgICB0aGlzLnJlZ2lvbnNTdWIgPSB0aGlzLnJlZ2lvbnMkLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKChyZWdpb25zKSA9PiB7XG4gICAgICAgICAgY29uc3Qgb2JqID0gcmVnaW9ucy5maW5kKFxuICAgICAgICAgICAgKHJlZ2lvbikgPT5cbiAgICAgICAgICAgICAgcmVnaW9uLmlzb2NvZGUgPT09XG4gICAgICAgICAgICAgIHRoaXMuYWRkcmVzc0Zvcm0uY29udHJvbHNbJ3JlZ2lvbiddLnZhbHVlLmlzb2NvZGVcbiAgICAgICAgICApO1xuICAgICAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5hZGRyZXNzRm9ybS52YWx1ZS5yZWdpb24sIHtcbiAgICAgICAgICAgIGlzb2NvZGVTaG9ydDogb2JqLmlzb2NvZGVTaG9ydCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmFkZHJlc3NGb3JtLmRpcnR5KSB7XG4gICAgICAgIHRoaXMudXNlckFkZHJlc3NTZXJ2aWNlXG4gICAgICAgICAgLnZlcmlmeUFkZHJlc3ModGhpcy5hZGRyZXNzRm9ybS52YWx1ZSlcbiAgICAgICAgICAuc3Vic2NyaWJlKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlQWRkcmVzc1ZlcmlmaWNhdGlvblJlc3VsdHMocmVzdWx0KTtcbiAgICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGFkZHJlc3MgZm9ybSB2YWx1ZSBub3QgY2hhbmdlZFxuICAgICAgICAvLyBpZ25vcmUgZHVwbGljYXRlIGFkZHJlc3NcbiAgICAgICAgdGhpcy5zdWJtaXRBZGRyZXNzLmVtaXQodW5kZWZpbmVkKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5hZGRyZXNzRm9ybS5tYXJrQWxsQXNUb3VjaGVkKCk7XG4gICAgfVxuICB9XG5cbiAgb3BlblN1Z2dlc3RlZEFkZHJlc3MocmVzdWx0czogQWRkcmVzc1ZhbGlkYXRpb24pOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc3VnZ2VzdGVkQWRkcmVzc01vZGFsUmVmKSB7XG4gICAgICB0aGlzLnN1Z2dlc3RlZEFkZHJlc3NNb2RhbFJlZiA9IHRoaXMubW9kYWxTZXJ2aWNlLm9wZW4oXG4gICAgICAgIFN1Z2dlc3RlZEFkZHJlc3NEaWFsb2dDb21wb25lbnQsXG4gICAgICAgIHsgY2VudGVyZWQ6IHRydWUsIHNpemU6ICdsZycgfVxuICAgICAgKTtcbiAgICAgIHRoaXMuc3VnZ2VzdGVkQWRkcmVzc01vZGFsUmVmLmNvbXBvbmVudEluc3RhbmNlLmVudGVyZWRBZGRyZXNzID1cbiAgICAgICAgdGhpcy5hZGRyZXNzRm9ybS52YWx1ZTtcbiAgICAgIHRoaXMuc3VnZ2VzdGVkQWRkcmVzc01vZGFsUmVmLmNvbXBvbmVudEluc3RhbmNlLnN1Z2dlc3RlZEFkZHJlc3NlcyA9XG4gICAgICAgIHJlc3VsdHMuc3VnZ2VzdGVkQWRkcmVzc2VzO1xuICAgICAgdGhpcy5zdWdnZXN0ZWRBZGRyZXNzTW9kYWxSZWYucmVzdWx0XG4gICAgICAgIC50aGVuKChhZGRyZXNzKSA9PiB7XG4gICAgICAgICAgaWYgKGFkZHJlc3MpIHtcbiAgICAgICAgICAgIGFkZHJlc3MgPSBPYmplY3QuYXNzaWduKFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdGl0bGVDb2RlOiB0aGlzLmFkZHJlc3NGb3JtLnZhbHVlLnRpdGxlQ29kZSxcbiAgICAgICAgICAgICAgICBwaG9uZTogdGhpcy5hZGRyZXNzRm9ybS52YWx1ZS5waG9uZSxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgYWRkcmVzc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuc3VibWl0QWRkcmVzcy5lbWl0KGFkZHJlc3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLnN1Z2dlc3RlZEFkZHJlc3NNb2RhbFJlZiA9IG51bGw7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgLy8gdGhpcyAgY2FsbGJhY2sgaXMgY2FsbGVkIHdoZW4gbW9kYWwgaXMgY2xvc2VkIHdpdGggRXNjIGtleSBvciBjbGlja2luZyBiYWNrZHJvcFxuICAgICAgICAgIGNvbnN0IGFkZHJlc3MgPSBPYmplY3QuYXNzaWduKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBzZWxlY3RlZDogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aGlzLmFkZHJlc3NGb3JtLnZhbHVlXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLnN1Ym1pdEFkZHJlc3MuZW1pdChhZGRyZXNzKTtcbiAgICAgICAgICB0aGlzLnN1Z2dlc3RlZEFkZHJlc3NNb2RhbFJlZiA9IG51bGw7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIGlmICh0aGlzLmFkZHJlc3NWZXJpZnlTdWIpIHtcbiAgICAgIHRoaXMuYWRkcmVzc1ZlcmlmeVN1Yi51bnN1YnNjcmliZSgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnJlZ2lvbnNTdWIpIHtcbiAgICAgIHRoaXMucmVnaW9uc1N1Yi51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgfVxufVxuIiwiPGZvcm0gKG5nU3VibWl0KT1cInZlcmlmeUFkZHJlc3MoKVwiIFtmb3JtR3JvdXBdPVwiYWRkcmVzc0Zvcm1cIj5cbiAgPGRpdiBjbGFzcz1cInJvd1wiPlxuICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtMTIgY29sLWxnLTlcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCIgZm9ybUdyb3VwTmFtZT1cImNvdW50cnlcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImNvdW50cmllcyQgfCBhc3luYyBhcyBjb3VudHJpZXNcIj5cbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwiY291bnRyaWVzLmxlbmd0aCAhPT0gMFwiPlxuICAgICAgICAgICAgPGxhYmVsPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsLWNvbnRlbnQgcmVxdWlyZWRcIj57e1xuICAgICAgICAgICAgICAgICdhZGRyZXNzRm9ybS5jb3VudHJ5JyB8IGN4VHJhbnNsYXRlXG4gICAgICAgICAgICAgIH19PC9zcGFuPlxuICAgICAgICAgICAgICA8bmctc2VsZWN0XG4gICAgICAgICAgICAgICAgYXJpYS1yZXF1aXJlZD1cInRydWVcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwiY291bnRyeS1zZWxlY3RcIlxuICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImlzb2NvZGVcIlxuICAgICAgICAgICAgICAgIFtzZWFyY2hhYmxlXT1cInRydWVcIlxuICAgICAgICAgICAgICAgIFtjbGVhcmFibGVdPVwiZmFsc2VcIlxuICAgICAgICAgICAgICAgIFtpdGVtc109XCJjb3VudHJpZXNcIlxuICAgICAgICAgICAgICAgIGJpbmRMYWJlbD1cIm5hbWVcIlxuICAgICAgICAgICAgICAgIGJpbmRWYWx1ZT1cImlzb2NvZGVcIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ2FkZHJlc3NGb3JtLnNlbGVjdE9uZScgfCBjeFRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJjb3VudHJ5U2VsZWN0ZWQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPC9uZy1zZWxlY3Q+XG4gICAgICAgICAgICAgIDxjeC1mb3JtLWVycm9yc1xuICAgICAgICAgICAgICAgIGFyaWEtbGl2ZT1cImFzc2VydGl2ZVwiXG4gICAgICAgICAgICAgICAgYXJpYS1hdG9taWM9XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICBbY29udHJvbF09XCJhZGRyZXNzRm9ybS5nZXQoJ2NvdW50cnkuaXNvY29kZScpXCJcbiAgICAgICAgICAgICAgPjwvY3gtZm9ybS1lcnJvcnM+XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIiAqbmdJZj1cInNob3dUaXRsZUNvZGVcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRpdGxlcyQgfCBhc3luYyBhcyB0aXRsZXNcIj5cbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwidGl0bGVzLmxlbmd0aCAhPT0gMFwiPlxuICAgICAgICAgICAgPGxhYmVsPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsLWNvbnRlbnQgcmVxdWlyZWRcIj57e1xuICAgICAgICAgICAgICAgICdhZGRyZXNzRm9ybS50aXRsZScgfCBjeFRyYW5zbGF0ZVxuICAgICAgICAgICAgICB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPG5nLXNlbGVjdFxuICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInRpdGxlQ29kZVwiXG4gICAgICAgICAgICAgICAgW3NlYXJjaGFibGVdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgW2NsZWFyYWJsZV09XCJmYWxzZVwiXG4gICAgICAgICAgICAgICAgW2l0ZW1zXT1cInRpdGxlc1wiXG4gICAgICAgICAgICAgICAgYmluZExhYmVsPVwibmFtZVwiXG4gICAgICAgICAgICAgICAgYmluZFZhbHVlPVwiY29kZVwiXG4gICAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIidhZGRyZXNzRm9ybS50aXRsZScgfCBjeFRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPC9uZy1zZWxlY3Q+XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgPGxhYmVsPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWwtY29udGVudCByZXF1aXJlZFwiPnt7XG4gICAgICAgICAgICAnYWRkcmVzc0Zvcm0uZmlyc3ROYW1lLmxhYmVsJyB8IGN4VHJhbnNsYXRlXG4gICAgICAgICAgfX08L3NwYW4+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBhcmlhLXJlcXVpcmVkPVwidHJ1ZVwiXG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7XG4gICAgICAgICAgICAgICdhZGRyZXNzRm9ybS5maXJzdE5hbWUucGxhY2Vob2xkZXInIHwgY3hUcmFuc2xhdGVcbiAgICAgICAgICAgIH19XCJcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImZpcnN0TmFtZVwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8Y3gtZm9ybS1lcnJvcnNcbiAgICAgICAgICAgIGFyaWEtbGl2ZT1cImFzc2VydGl2ZVwiXG4gICAgICAgICAgICBhcmlhLWF0b21pYz1cInRydWVcIlxuICAgICAgICAgICAgW2NvbnRyb2xdPVwiYWRkcmVzc0Zvcm0uZ2V0KCdmaXJzdE5hbWUnKVwiXG4gICAgICAgICAgPjwvY3gtZm9ybS1lcnJvcnM+XG4gICAgICAgIDwvbGFiZWw+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICAgIDxsYWJlbD5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsLWNvbnRlbnQgcmVxdWlyZWRcIj57e1xuICAgICAgICAgICAgJ2FkZHJlc3NGb3JtLmxhc3ROYW1lLmxhYmVsJyB8IGN4VHJhbnNsYXRlXG4gICAgICAgICAgfX08L3NwYW4+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBhcmlhLXJlcXVpcmVkPVwidHJ1ZVwiXG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7ICdhZGRyZXNzRm9ybS5sYXN0TmFtZS5wbGFjZWhvbGRlcicgfCBjeFRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJsYXN0TmFtZVwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8Y3gtZm9ybS1lcnJvcnNcbiAgICAgICAgICAgIGFyaWEtbGl2ZT1cImFzc2VydGl2ZVwiXG4gICAgICAgICAgICBhcmlhLWF0b21pYz1cInRydWVcIlxuICAgICAgICAgICAgW2NvbnRyb2xdPVwiYWRkcmVzc0Zvcm0uZ2V0KCdsYXN0TmFtZScpXCJcbiAgICAgICAgICA+PC9jeC1mb3JtLWVycm9ycz5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgPGxhYmVsPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWwtY29udGVudCByZXF1aXJlZFwiPnt7XG4gICAgICAgICAgICAnYWRkcmVzc0Zvcm0uYWRkcmVzczEnIHwgY3hUcmFuc2xhdGVcbiAgICAgICAgICB9fTwvc3Bhbj5cbiAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgIGFyaWEtcmVxdWlyZWQ9XCJ0cnVlXCJcbiAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ2FkZHJlc3NGb3JtLnN0cmVldEFkZHJlc3MnIHwgY3hUcmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibGluZTFcIlxuICAgICAgICAgIC8+XG4gICAgICAgICAgPGN4LWZvcm0tZXJyb3JzXG4gICAgICAgICAgICBhcmlhLWxpdmU9XCJhc3NlcnRpdmVcIlxuICAgICAgICAgICAgYXJpYS1hdG9taWM9XCJ0cnVlXCJcbiAgICAgICAgICAgIFtjb250cm9sXT1cImFkZHJlc3NGb3JtLmdldCgnbGluZTEnKVwiXG4gICAgICAgICAgPjwvY3gtZm9ybS1lcnJvcnM+XG4gICAgICAgIDwvbGFiZWw+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICAgIDxsYWJlbD5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsLWNvbnRlbnRcIj57e1xuICAgICAgICAgICAgJ2FkZHJlc3NGb3JtLmFkZHJlc3MyJyB8IGN4VHJhbnNsYXRlXG4gICAgICAgICAgfX08L3NwYW4+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7ICdhZGRyZXNzRm9ybS5hcHRTdWl0ZScgfCBjeFRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJsaW5lMlwiXG4gICAgICAgICAgLz5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cInJvd1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCBjb2wtbWQtNlwiPlxuICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWwtY29udGVudCByZXF1aXJlZFwiPnt7XG4gICAgICAgICAgICAgICdhZGRyZXNzRm9ybS5jaXR5LmxhYmVsJyB8IGN4VHJhbnNsYXRlXG4gICAgICAgICAgICB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBhcmlhLXJlcXVpcmVkPVwidHJ1ZVwiXG4gICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7ICdhZGRyZXNzRm9ybS5jaXR5LnBsYWNlaG9sZGVyJyB8IGN4VHJhbnNsYXRlIH19XCJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwidG93blwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPGN4LWZvcm0tZXJyb3JzXG4gICAgICAgICAgICAgIGFyaWEtbGl2ZT1cImFzc2VydGl2ZVwiXG4gICAgICAgICAgICAgIGFyaWEtYXRvbWljPVwidHJ1ZVwiXG4gICAgICAgICAgICAgIFtjb250cm9sXT1cImFkZHJlc3NGb3JtLmdldCgndG93bicpXCJcbiAgICAgICAgICAgID48L2N4LWZvcm0tZXJyb3JzPlxuICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCBjb2wtbWQtNlwiPlxuICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWwtY29udGVudCByZXF1aXJlZFwiPnt7XG4gICAgICAgICAgICAgICdhZGRyZXNzRm9ybS56aXBDb2RlLmxhYmVsJyB8IGN4VHJhbnNsYXRlXG4gICAgICAgICAgICB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBhcmlhLXJlcXVpcmVkPVwidHJ1ZVwiXG4gICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7XG4gICAgICAgICAgICAgICAgJ2FkZHJlc3NGb3JtLnppcENvZGUucGxhY2Vob2xkZXInIHwgY3hUcmFuc2xhdGVcbiAgICAgICAgICAgICAgfX1cIlxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJwb3N0YWxDb2RlXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8Y3gtZm9ybS1lcnJvcnNcbiAgICAgICAgICAgICAgYXJpYS1saXZlPVwiYXNzZXJ0aXZlXCJcbiAgICAgICAgICAgICAgYXJpYS1hdG9taWM9XCJ0cnVlXCJcbiAgICAgICAgICAgICAgW2NvbnRyb2xdPVwiYWRkcmVzc0Zvcm0uZ2V0KCdwb3N0YWxDb2RlJylcIlxuICAgICAgICAgICAgPjwvY3gtZm9ybS1lcnJvcnM+XG4gICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAqbmdJZj1cInJlZ2lvbnMkIHwgYXN5bmMgYXMgcmVnaW9uc1wiXG4gICAgICAgICAgZm9ybUdyb3VwTmFtZT1cInJlZ2lvblwiXG4gICAgICAgID5cbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwicmVnaW9ucy5sZW5ndGggIT09IDBcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwIGNvbC1tZC02XCI+XG4gICAgICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsLWNvbnRlbnQgcmVxdWlyZWRcIj57e1xuICAgICAgICAgICAgICAgICAgJ2FkZHJlc3NGb3JtLnN0YXRlJyB8IGN4VHJhbnNsYXRlXG4gICAgICAgICAgICAgICAgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPG5nLXNlbGVjdFxuICAgICAgICAgICAgICAgICAgYXJpYS1yZXF1aXJlZD1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJyZWdpb24tc2VsZWN0XCJcbiAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImlzb2NvZGVcIlxuICAgICAgICAgICAgICAgICAgW3NlYXJjaGFibGVdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICBbY2xlYXJhYmxlXT1cImZhbHNlXCJcbiAgICAgICAgICAgICAgICAgIFtpdGVtc109XCJyZWdpb25zXCJcbiAgICAgICAgICAgICAgICAgIGJpbmRMYWJlbD1cInt7IHJlZ2lvbnNbMF0ubmFtZSA/ICduYW1lJyA6ICdpc29jb2RlJyB9fVwiXG4gICAgICAgICAgICAgICAgICBiaW5kVmFsdWU9XCJ7eyByZWdpb25zWzBdLm5hbWUgPyAnaXNvY29kZScgOiAncmVnaW9uJyB9fVwiXG4gICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7ICdhZGRyZXNzRm9ybS5zZWxlY3RPb