@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
75 lines • 17.5 kB
JavaScript
import { ChangeDetectorRef, Component, EventEmitter, Output, ViewChild } from '@angular/core';
import { ControlContainer, NgForm, NgModel } from '@angular/forms';
import { LoginService } from '../login/login.service';
import * as i0 from "@angular/core";
import * as i1 from "../login/login.service";
import * as i2 from "../forms/default-validation.directive";
import * as i3 from "@angular/forms";
import * as i4 from "../forms/form-group.component";
import * as i5 from "../i18n/c8y-translate.directive";
import * as i6 from "@angular/common";
import * as i7 from "./password-confirm.directive";
import * as i8 from "./password-check-list.component";
import * as i9 from "./password-input.component";
import * as i10 from "../i18n/c8y-translate.pipe";
export class NewPasswordComponent {
set _newPasswordModel(ngModel) {
if (ngModel) {
this.newPasswordModel = ngModel;
ngModel.control.addValidators(this.passwordChecklistValidator);
}
}
constructor(loginService, cdRef) {
this.loginService = loginService;
this.cdRef = cdRef;
this.password = new EventEmitter();
this.model = {};
this.changePassword = false;
this.passwordEnforced = false;
this.passwordChecklistValidator = () => this.requirementsFulfilled ? null : { passwordStrengthChecklist: true };
}
ngOnInit() {
this.loadPasswordStrengthSettings();
this.loginService.getGreenMinLength().then(value => {
this.minlength = value;
});
}
newPasswordChanged() {
this.password.emit({
password: this.model.newPassword,
passwordStrength: this.model.strength
});
}
updateValidity(requirementsFulfilled) {
this.requirementsFulfilled = requirementsFulfilled;
this.cdRef.detectChanges();
this.newPasswordModel.control.updateValueAndValidity();
// There are two validators checking password validity, but we only want to show one of these errors at a time,
// where checklist validator takes priority.
if (!this.requirementsFulfilled) {
delete this.newPasswordModel.control.errors['password'];
}
}
async loadPasswordStrengthSettings() {
this.passwordEnforced = await this.loginService.getPasswordStrengthEnforced({ refresh: true });
}
toggleChangePassword() {
this.changePassword = !this.changePassword;
if (!this.changePassword) {
this.password.emit({});
this.model = {};
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NewPasswordComponent, deps: [{ token: i1.LoginService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NewPasswordComponent, selector: "c8y-new-password", outputs: { password: "password" }, viewQueries: [{ propertyName: "_newPasswordModel", first: true, predicate: ["newPassword"], descendants: true }], ngImport: i0, template: "<div class=\"form-group\">\n <button\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"toggleChangePassword()\"\n >\n <ng-container *ngIf=\"!changePassword\">\n {{ 'Change password' | translate }}\n </ng-container>\n <ng-container *ngIf=\"changePassword\">\n {{ 'Cancel password change' | translate }}\n </ng-container>\n </button>\n</div>\n\n<div\n class=\"row content-flex-50\"\n *ngIf=\"changePassword\"\n>\n <div class=\"col-6\">\n <c8y-form-group>\n <label\n for=\"newPassword\"\n translate\n >\n Password\n </label>\n <c8y-password-input\n name=\"newPassword\"\n required\n [id]=\"'newPassword'\"\n #newPassword=\"ngModel\"\n [(ngModel)]=\"model.newPassword\"\n (change)=\"newPasswordChanged()\"\n (input)=\"newPasswordConfirm.control.updateValueAndValidity()\"\n c8yDefaultValidation=\"password\"\n [autocomplete]=\"'new-password'\"\n ></c8y-password-input>\n </c8y-form-group>\n\n <c8y-form-group>\n <label\n for=\"newConfirmPassword\"\n translate\n >\n Confirm password\n </label>\n <c8y-password-input\n name=\"newPasswordConfirm\"\n required\n [id]=\"'newConfirmPassword'\"\n #newPasswordConfirm=\"ngModel\"\n [(ngModel)]=\"model.newPasswordConfirm\"\n passwordConfirm=\"newPassword\"\n [autocomplete]=\"'new-password'\"\n ></c8y-password-input>\n </c8y-form-group>\n </div>\n <div class=\"col-6\">\n <c8y-password-check-list\n [password]=\"model.newPassword\"\n [strengthEnforced]=\"passwordEnforced\"\n (onRequirementsFulfilled)=\"updateValidity($event)\"\n ></c8y-password-check-list>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.DefaultValidationDirective, selector: "[c8yDefaultValidation]", inputs: ["c8yDefaultValidation"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i5.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.PasswordConfirm, selector: "[passwordConfirm]" }, { kind: "component", type: i8.PasswordCheckListComponent, selector: "c8y-password-check-list", inputs: ["strengthEnforced", "password"], outputs: ["onRequirementsFulfilled"] }, { kind: "component", type: i9.PasswordInputComponent, selector: "c8y-password-input", inputs: ["id", "autocomplete"] }, { kind: "pipe", type: i10.C8yTranslatePipe, name: "translate" }], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NewPasswordComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-new-password', viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], template: "<div class=\"form-group\">\n <button\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"toggleChangePassword()\"\n >\n <ng-container *ngIf=\"!changePassword\">\n {{ 'Change password' | translate }}\n </ng-container>\n <ng-container *ngIf=\"changePassword\">\n {{ 'Cancel password change' | translate }}\n </ng-container>\n </button>\n</div>\n\n<div\n class=\"row content-flex-50\"\n *ngIf=\"changePassword\"\n>\n <div class=\"col-6\">\n <c8y-form-group>\n <label\n for=\"newPassword\"\n translate\n >\n Password\n </label>\n <c8y-password-input\n name=\"newPassword\"\n required\n [id]=\"'newPassword'\"\n #newPassword=\"ngModel\"\n [(ngModel)]=\"model.newPassword\"\n (change)=\"newPasswordChanged()\"\n (input)=\"newPasswordConfirm.control.updateValueAndValidity()\"\n c8yDefaultValidation=\"password\"\n [autocomplete]=\"'new-password'\"\n ></c8y-password-input>\n </c8y-form-group>\n\n <c8y-form-group>\n <label\n for=\"newConfirmPassword\"\n translate\n >\n Confirm password\n </label>\n <c8y-password-input\n name=\"newPasswordConfirm\"\n required\n [id]=\"'newConfirmPassword'\"\n #newPasswordConfirm=\"ngModel\"\n [(ngModel)]=\"model.newPasswordConfirm\"\n passwordConfirm=\"newPassword\"\n [autocomplete]=\"'new-password'\"\n ></c8y-password-input>\n </c8y-form-group>\n </div>\n <div class=\"col-6\">\n <c8y-password-check-list\n [password]=\"model.newPassword\"\n [strengthEnforced]=\"passwordEnforced\"\n (onRequirementsFulfilled)=\"updateValidity($event)\"\n ></c8y-password-check-list>\n </div>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.LoginService }, { type: i0.ChangeDetectorRef }], propDecorators: { password: [{
type: Output
}], _newPasswordModel: [{
type: ViewChild,
args: ['newPassword']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV3LXBhc3N3b3JkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2NvcmUvYXV0aGVudGljYXRpb24vbmV3LXBhc3N3b3JkLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL2NvcmUvYXV0aGVudGljYXRpb24vbmV3LXBhc3N3b3JkLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFlBQVksRUFFWixNQUFNLEVBQ04sU0FBUyxFQUNWLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFlLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHdCQUF3QixDQUFDOzs7Ozs7Ozs7Ozs7QUFPdEQsTUFBTSxPQUFPLG9CQUFvQjtJQVMvQixJQUNJLGlCQUFpQixDQUFDLE9BQWdCO1FBQ3BDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsT0FBTyxDQUFDO1lBQ2hDLE9BQU8sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7SUFDSCxDQUFDO0lBRUQsWUFDVSxZQUEwQixFQUMxQixLQUF3QjtRQUR4QixpQkFBWSxHQUFaLFlBQVksQ0FBYztRQUMxQixVQUFLLEdBQUwsS0FBSyxDQUFtQjtRQWxCeEIsYUFBUSxHQUFHLElBQUksWUFBWSxFQUF3QixDQUFDO1FBQzlELFVBQUssR0FBUSxFQUFFLENBQUM7UUFDaEIsbUJBQWMsR0FBRyxLQUFLLENBQUM7UUFDdkIscUJBQWdCLEdBQUcsS0FBSyxDQUFDO1FBa0J6QiwrQkFBMEIsR0FBZ0IsR0FBRyxFQUFFLENBQzdDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLHlCQUF5QixFQUFFLElBQUksRUFBRSxDQUFDO0lBSHZFLENBQUM7SUFLSixRQUFRO1FBQ04sSUFBSSxDQUFDLDRCQUE0QixFQUFFLENBQUM7UUFDcEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUNqRCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN6QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxrQkFBa0I7UUFDaEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7WUFDakIsUUFBUSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVztZQUNoQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVE7U0FDdEMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGNBQWMsQ0FBQyxxQkFBOEI7UUFDM0MsSUFBSSxDQUFDLHFCQUFxQixHQUFHLHFCQUFxQixDQUFDO1FBQ25ELElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQ3ZELCtHQUErRztRQUMvRyw0Q0FBNEM7UUFDNUMsSUFBSSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQ2hDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDMUQsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsNEJBQTRCO1FBQ2hDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsMkJBQTJCLENBQUMsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNqRyxDQUFDO0lBRUQsb0JBQW9CO1FBQ2xCLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQzNDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdkIsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDbEIsQ0FBQztJQUNILENBQUM7K0dBNURVLG9CQUFvQjttR0FBcEIsb0JBQW9CLDZNQ2pCakMsNHdEQWtFQSwwOUNEbkRpQixDQUFDLEVBQUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsQ0FBQzs7NEZBRXhELG9CQUFvQjtrQkFMaEMsU0FBUzsrQkFDRSxrQkFBa0IsaUJBRWIsQ0FBQyxFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLENBQUM7aUhBR3pELFFBQVE7c0JBQWpCLE1BQU07Z0JBU0gsaUJBQWlCO3NCQURwQixTQUFTO3VCQUFDLGFBQWEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOZXdQYXNzd29yZCB9IGZyb20gJy4vcGFzc3dvcmQubW9kZWwnO1xuaW1wb3J0IHsgQ29udHJvbENvbnRhaW5lciwgTmdGb3JtLCBOZ01vZGVsLCBWYWxpZGF0b3JGbiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IExvZ2luU2VydmljZSB9IGZyb20gJy4uL2xvZ2luL2xvZ2luLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktbmV3LXBhc3N3b3JkJyxcbiAgdGVtcGxhdGVVcmw6ICcuL25ldy1wYXNzd29yZC5jb21wb25lbnQuaHRtbCcsXG4gIHZpZXdQcm92aWRlcnM6IFt7IHByb3ZpZGU6IENvbnRyb2xDb250YWluZXIsIHVzZUV4aXN0aW5nOiBOZ0Zvcm0gfV1cbn0pXG5leHBvcnQgY2xhc3MgTmV3UGFzc3dvcmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBAT3V0cHV0KCkgcGFzc3dvcmQgPSBuZXcgRXZlbnRFbWl0dGVyPE5ld1Bhc3N3b3JkIHwgb2JqZWN0PigpO1xuICBtb2RlbDogYW55ID0ge307XG4gIGNoYW5nZVBhc3N3b3JkID0gZmFsc2U7XG4gIHBhc3N3b3JkRW5mb3JjZWQgPSBmYWxzZTtcbiAgbWlubGVuZ3RoOiBudW1iZXI7XG4gIHJlcXVpcmVtZW50c0Z1bGZpbGxlZDogYm9vbGVhbjtcbiAgbmV3UGFzc3dvcmRNb2RlbDogTmdNb2RlbDtcblxuICBAVmlld0NoaWxkKCduZXdQYXNzd29yZCcpXG4gIHNldCBfbmV3UGFzc3dvcmRNb2RlbChuZ01vZGVsOiBOZ01vZGVsKSB7XG4gICAgaWYgKG5nTW9kZWwpIHtcbiAgICAgIHRoaXMubmV3UGFzc3dvcmRNb2RlbCA9IG5nTW9kZWw7XG4gICAgICBuZ01vZGVsLmNvbnRyb2wuYWRkVmFsaWRhdG9ycyh0aGlzLnBhc3N3b3JkQ2hlY2tsaXN0VmFsaWRhdG9yKTtcbiAgICB9XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGxvZ2luU2VydmljZTogTG9naW5TZXJ2aWNlLFxuICAgIHByaXZhdGUgY2RSZWY6IENoYW5nZURldGVjdG9yUmVmXG4gICkge31cblxuICBwYXNzd29yZENoZWNrbGlzdFZhbGlkYXRvcjogVmFsaWRhdG9yRm4gPSAoKSA9PlxuICAgIHRoaXMucmVxdWlyZW1lbnRzRnVsZmlsbGVkID8gbnVsbCA6IHsgcGFzc3dvcmRTdHJlbmd0aENoZWNrbGlzdDogdHJ1ZSB9O1xuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMubG9hZFBhc3N3b3JkU3RyZW5ndGhTZXR0aW5ncygpO1xuICAgIHRoaXMubG9naW5TZXJ2aWNlLmdldEdyZWVuTWluTGVuZ3RoKCkudGhlbih2YWx1ZSA9PiB7XG4gICAgICB0aGlzLm1pbmxlbmd0aCA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG5cbiAgbmV3UGFzc3dvcmRDaGFuZ2VkKCkge1xuICAgIHRoaXMucGFzc3dvcmQuZW1pdCh7XG4gICAgICBwYXNzd29yZDogdGhpcy5tb2RlbC5uZXdQYXNzd29yZCxcbiAgICAgIHBhc3N3b3JkU3RyZW5ndGg6IHRoaXMubW9kZWwuc3RyZW5ndGhcbiAgICB9KTtcbiAgfVxuXG4gIHVwZGF0ZVZhbGlkaXR5KHJlcXVpcmVtZW50c0Z1bGZpbGxlZDogYm9vbGVhbikge1xuICAgIHRoaXMucmVxdWlyZW1lbnRzRnVsZmlsbGVkID0gcmVxdWlyZW1lbnRzRnVsZmlsbGVkO1xuICAgIHRoaXMuY2RSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIHRoaXMubmV3UGFzc3dvcmRNb2RlbC5jb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcbiAgICAvLyBUaGVyZSBhcmUgdHdvIHZhbGlkYXRvcnMgY2hlY2tpbmcgcGFzc3dvcmQgdmFsaWRpdHksIGJ1dCB3ZSBvbmx5IHdhbnQgdG8gc2hvdyBvbmUgb2YgdGhlc2UgZXJyb3JzIGF0IGEgdGltZSxcbiAgICAvLyB3aGVyZSBjaGVja2xpc3QgdmFsaWRhdG9yIHRha2VzIHByaW9yaXR5LlxuICAgIGlmICghdGhpcy5yZXF1aXJlbWVudHNGdWxmaWxsZWQpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLm5ld1Bhc3N3b3JkTW9kZWwuY29udHJvbC5lcnJvcnNbJ3Bhc3N3b3JkJ107XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgbG9hZFBhc3N3b3JkU3RyZW5ndGhTZXR0aW5ncygpIHtcbiAgICB0aGlzLnBhc3N3b3JkRW5mb3JjZWQgPSBhd2FpdCB0aGlzLmxvZ2luU2VydmljZS5nZXRQYXNzd29yZFN0cmVuZ3RoRW5mb3JjZWQoeyByZWZyZXNoOiB0cnVlIH0pO1xuICB9XG5cbiAgdG9nZ2xlQ2hhbmdlUGFzc3dvcmQoKSB7XG4gICAgdGhpcy5jaGFuZ2VQYXNzd29yZCA9ICF0aGlzLmNoYW5nZVBhc3N3b3JkO1xuICAgIGlmICghdGhpcy5jaGFuZ2VQYXNzd29yZCkge1xuICAgICAgdGhpcy5wYXNzd29yZC5lbWl0KHt9KTtcbiAgICAgIHRoaXMubW9kZWwgPSB7fTtcbiAgICB9XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gIDxidXR0b25cbiAgICBjbGFzcz1cImJ0biBidG4tZGVmYXVsdFwiXG4gICAgdHlwZT1cImJ1dHRvblwiXG4gICAgKGNsaWNrKT1cInRvZ2dsZUNoYW5nZVBhc3N3b3JkKClcIlxuICA+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFjaGFuZ2VQYXNzd29yZFwiPlxuICAgICAge3sgJ0NoYW5nZSBwYXNzd29yZCcgfCB0cmFuc2xhdGUgfX1cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiY2hhbmdlUGFzc3dvcmRcIj5cbiAgICAgIHt7ICdDYW5jZWwgcGFzc3dvcmQgY2hhbmdlJyB8IHRyYW5zbGF0ZSB9fVxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L2J1dHRvbj5cbjwvZGl2PlxuXG48ZGl2XG4gIGNsYXNzPVwicm93IGNvbnRlbnQtZmxleC01MFwiXG4gICpuZ0lmPVwiY2hhbmdlUGFzc3dvcmRcIlxuPlxuICA8ZGl2IGNsYXNzPVwiY29sLTZcIj5cbiAgICA8Yzh5LWZvcm0tZ3JvdXA+XG4gICAgICA8bGFiZWxcbiAgICAgICAgZm9yPVwibmV3UGFzc3dvcmRcIlxuICAgICAgICB0cmFuc2xhdGVcbiAgICAgID5cbiAgICAgICAgUGFzc3dvcmRcbiAgICAgIDwvbGFiZWw+XG4gICAgICA8Yzh5LXBhc3N3b3JkLWlucHV0XG4gICAgICAgIG5hbWU9XCJuZXdQYXNzd29yZFwiXG4gICAgICAgIHJlcXVpcmVkXG4gICAgICAgIFtpZF09XCInbmV3UGFzc3dvcmQnXCJcbiAgICAgICAgI25ld1Bhc3N3b3JkPVwibmdNb2RlbFwiXG4gICAgICAgIFsobmdNb2RlbCldPVwibW9kZWwubmV3UGFzc3dvcmRcIlxuICAgICAgICAoY2hhbmdlKT1cIm5ld1Bhc3N3b3JkQ2hhbmdlZCgpXCJcbiAgICAgICAgKGlucHV0KT1cIm5ld1Bhc3N3b3JkQ29uZmlybS5jb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKVwiXG4gICAgICAgIGM4eURlZmF1bHRWYWxpZGF0aW9uPVwicGFzc3dvcmRcIlxuICAgICAgICBbYXV0b2NvbXBsZXRlXT1cIiduZXctcGFzc3dvcmQnXCJcbiAgICAgID48L2M4eS1wYXNzd29yZC1pbnB1dD5cbiAgICA8L2M4eS1mb3JtLWdyb3VwPlxuXG4gICAgPGM4eS1mb3JtLWdyb3VwPlxuICAgICAgPGxhYmVsXG4gICAgICAgIGZvcj1cIm5ld0NvbmZpcm1QYXNzd29yZFwiXG4gICAgICAgIHRyYW5zbGF0ZVxuICAgICAgPlxuICAgICAgICBDb25maXJtIHBhc3N3b3JkXG4gICAgICA8L2xhYmVsPlxuICAgICAgPGM4eS1wYXNzd29yZC1pbnB1dFxuICAgICAgICBuYW1lPVwibmV3UGFzc3dvcmRDb25maXJtXCJcbiAgICAgICAgcmVxdWlyZWRcbiAgICAgICAgW2lkXT1cIiduZXdDb25maXJtUGFzc3dvcmQnXCJcbiAgICAgICAgI25ld1Bhc3N3b3JkQ29uZmlybT1cIm5nTW9kZWxcIlxuICAgICAgICBbKG5nTW9kZWwpXT1cIm1vZGVsLm5ld1Bhc3N3b3JkQ29uZmlybVwiXG4gICAgICAgIHBhc3N3b3JkQ29uZmlybT1cIm5ld1Bhc3N3b3JkXCJcbiAgICAgICAgW2F1dG9jb21wbGV0ZV09XCInbmV3LXBhc3N3b3JkJ1wiXG4gICAgICA+PC9jOHktcGFzc3dvcmQtaW5wdXQ+XG4gICAgPC9jOHktZm9ybS1ncm91cD5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJjb2wtNlwiPlxuICAgIDxjOHktcGFzc3dvcmQtY2hlY2stbGlzdFxuICAgICAgW3Bhc3N3b3JkXT1cIm1vZGVsLm5ld1Bhc3N3b3JkXCJcbiAgICAgIFtzdHJlbmd0aEVuZm9yY2VkXT1cInBhc3N3b3JkRW5mb3JjZWRcIlxuICAgICAgKG9uUmVxdWlyZW1lbnRzRnVsZmlsbGVkKT1cInVwZGF0ZVZhbGlkaXR5KCRldmVudClcIlxuICAgID48L2M4eS1wYXNzd29yZC1jaGVjay1saXN0PlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19