@sumaris-net/ngx-components 18.23.10 → 18.23.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/doc/changelog.md +4 -1
  2. package/esm2022/src/app/admin/users/person.filter.mjs +4 -4
  3. package/esm2022/src/app/admin/users/person.service.mjs +34 -158
  4. package/esm2022/src/app/admin/users/testing/person.testing.sevice.mjs +128 -0
  5. package/esm2022/src/app/admin/users/users.mjs +54 -49
  6. package/esm2022/src/app/core/account/account.page.mjs +76 -31
  7. package/esm2022/src/app/core/menu/menu.component.mjs +16 -5
  8. package/esm2022/src/app/core/register/register.form.mjs +3 -3
  9. package/esm2022/src/app/core/services/account.service.mjs +18 -12
  10. package/esm2022/src/app/core/services/config/core.config.mjs +7 -1
  11. package/esm2022/src/app/core/services/model/account.model.mjs +15 -1
  12. package/esm2022/src/app/core/services/model/entity.model.mjs +8 -1
  13. package/esm2022/src/app/core/services/model/person.model.mjs +4 -1
  14. package/esm2022/src/app/shared/form/field.component.mjs +2 -1
  15. package/esm2022/src/app/shared/form/field.model.mjs +18 -1
  16. package/esm2022/src/app/shared/image/image.service.mjs +5 -3
  17. package/esm2022/src/app/social/feed/feed.service.mjs +3 -3
  18. package/esm2022/src/app/social/message/message.service.mjs +2 -2
  19. package/esm2022/src/environments/environment.class.mjs +1 -1
  20. package/esm2022/src/environments/environment.mjs +2 -1
  21. package/fesm2022/sumaris-net.ngx-components.mjs +358 -248
  22. package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
  23. package/package.json +1 -1
  24. package/src/app/admin/users/person.filter.d.ts +3 -3
  25. package/src/app/admin/users/person.service.d.ts +32 -28
  26. package/src/app/admin/users/testing/person.testing.sevice.d.ts +17 -0
  27. package/src/app/admin/users/users.d.ts +4 -4
  28. package/src/app/core/account/account.page.d.ts +9 -2
  29. package/src/app/core/menu/menu.component.d.ts +4 -2
  30. package/src/app/core/services/account.service.d.ts +5 -2
  31. package/src/app/core/services/config/core.config.d.ts +45 -44
  32. package/src/app/core/services/model/account.model.d.ts +10 -0
  33. package/src/app/core/services/model/entity.model.d.ts +1 -1
  34. package/src/app/core/services/model/person.model.d.ts +2 -0
  35. package/src/app/shared/form/field.component.d.ts +2 -4
  36. package/src/app/shared/form/field.model.d.ts +15 -4
  37. package/src/app/shared/image/image.service.d.ts +1 -0
  38. package/src/app/social/config/social.config.d.ts +1 -1
  39. package/src/app/social/feed/feed.service.d.ts +1 -2
  40. package/src/assets/i18n/en-US.json +10 -2
  41. package/src/assets/i18n/en.json +10 -2
  42. package/src/assets/i18n/fr.json +9 -5
  43. package/src/assets/manifest.json +1 -1
  44. package/src/environments/environment.class.d.ts +1 -0
@@ -178,11 +178,11 @@ export class RegisterForm {
178
178
  this.form.enable();
179
179
  }
180
180
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RegisterForm, deps: [{ token: i1.AccountService }, { token: i2.AccountValidatorService }, { token: i3.UntypedFormBuilder }, { token: ENVIRONMENT }, { token: i4.LocalSettingsService }], target: i0.ɵɵFactoryTarget.Component });
181
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: RegisterForm, selector: "app-register-form", outputs: { onCancel: "onCancel", onSubmit: "onSubmit" }, viewQueries: [{ propertyName: "stepper", first: true, predicate: ["stepper"], descendants: true, static: true }], ngImport: i0, template: "<mat-horizontal-stepper linear #stepper=\"matHorizontalStepper\">\n <!-- Step 1: Username -->\n <mat-step [stepControl]=\"forms[0]\" *ngIf=\"forms[0].controls; let controls\">\n <form [formGroup]=\"forms[0]\" class=\"form-container ion-padding\" (keyup.enter)=\"slideNext($event)\">\n <ng-template matStepLabel>{{ 'REGISTER.STEP_EMAIL' | translate }}</ng-template>\n\n <!-- Email -->\n <mat-form-field>\n <mat-label>{{ 'USER.EMAIL' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"email\"\n autocomplete=\"off\"\n required\n />\n <mat-error *ngIf=\"controls.email.hasError('required') && controls.email.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error\n *ngIf=\"controls.email.hasError('email') && !controls.email.hasError('required') && controls.email.touched\"\n >\n <span>{{ 'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n <mat-error *ngIf=\"controls.email.hasError('availability') && controls.email.touched\" translate>\n REGISTER.ERROR.EMAIL_ALREADY_REGISTERED\n </mat-error>\n </mat-form-field>\n\n <!-- Confirm Email -->\n <mat-form-field>\n <mat-label>{{ 'REGISTER.CONFIRM_EMAIL' | translate }}</mat-label>\n <input matInput autocomplete=\"off\" matFormFieldControl formControlName=\"confirmEmail\" />\n <mat-error *ngIf=\"controls.confirmEmail.hasError('required') && controls.confirmEmail.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.confirmEmail.hasError('equals') && controls.confirmEmail.touched\">\n <span>{{ 'REGISTER.ERROR.NOT_SAME_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </form>\n </mat-step>\n\n <!-- Step 2: Password -->\n <mat-step [stepControl]=\"forms[1]\" *ngIf=\"forms[1].controls; let controls\">\n <form [formGroup]=\"forms[1]\" class=\"form-container ion-padding\" (keyup.enter)=\"slideNext($event)\">\n <ng-template matStepLabel>{{ 'REGISTER.STEP_PASSWORD' | translate }}</ng-template>\n\n <!-- Password -->\n <mat-form-field>\n <mat-label>{{ 'USER.PASSWORD' | translate }}</mat-label>\n <input\n matInput\n formControlName=\"password\"\n autocomplete=\"section-red new-password\"\n [type]=\"showPwd ? 'text' : 'password'\"\n required\n />\n <button matSuffix mat-icon-button type=\"button\" (click)=\"showPwd = !showPwd\" tabindex=\"-1\">\n <mat-icon>{{ showPwd ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n <mat-error *ngIf=\"controls.password.hasError('required') && controls.password.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.password.hasError('minlength') && controls.password.touched\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 8 } }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- Confirm password -->\n <mat-form-field>\n <mat-label>{{ 'REGISTER.CONFIRM_PASSWORD' | translate }}</mat-label>\n <input\n matInput\n formControlName=\"confirmPassword\"\n autocomplete=\"section-red new-password\"\n [type]=\"showConfirmPwd ? 'text' : 'password'\"\n required\n />\n <button mat-icon-button matSuffix (click)=\"showConfirmPwd = !showConfirmPwd\" tabindex=\"-1\">\n <mat-icon>{{ showConfirmPwd ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n <mat-error *ngIf=\"controls.confirmPassword.hasError('required') && controls.confirmPassword.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.confirmPassword.hasError('equals') && controls.confirmPassword.touched\">\n <span>{{ 'REGISTER.ERROR.NOT_SAME_PASSWORD' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </form>\n </mat-step>\n\n <!-- Step 3: user details -->\n <mat-step [stepControl]=\"forms[2]\" *ngIf=\"forms[2].controls; let controls\">\n <form\n [formGroup]=\"forms[2]\"\n (ngSubmit)=\"doSubmit($event)\"\n class=\"form-container ion-padding\"\n (keyup.enter)=\"doSubmit()\"\n >\n <ng-template matStepLabel>{{ 'REGISTER.STEP_USER_DETAILS' | translate }}</ng-template>\n\n <!-- error -->\n <ion-item *ngIf=\"error && !sending\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- Last name -->\n <mat-form-field>\n <mat-label>{{ 'USER.LAST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"lastName\" autocomplete=\"section-blue family-name\" required />\n <mat-error *ngIf=\"controls.lastName.hasError('required') && controls.lastName.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.lastName.hasError('minlength') && controls.lastName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <mat-label>{{ 'USER.FIRST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"firstName\" autocomplete=\"section-blue given-name\" required />\n <mat-error *ngIf=\"controls.firstName.hasError('required') && controls.firstName.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.firstName.hasError('minlength') && controls.firstName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- Additional fields -->\n <app-form-field\n *ngFor=\"let field of additionalFields\"\n [definition]=\"field\"\n [formControlName]=\"field.key\"\n [required]=\"field.extra?.registration.required ?? field.extra?.account.required ?? false\"\n ></app-form-field>\n </form>\n </mat-step>\n</mat-horizontal-stepper>\n", styles: ["form ion-toolbar.toolbar-buttons .toolbar-content{text-align:right}form ion-toolbar.toolbar-buttons .toolbar-background{border:0;background:inherit!important}\n"], dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i6.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i6.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "directive", type: i7.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { 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.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatLabel, selector: "mat-label" }, { kind: "directive", type: i8.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i8.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i10.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i11.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i12.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i12.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i12.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "directive", type: i13.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "component", type: i14.AppFormField, selector: "app-form-field", inputs: ["definition", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "required", "hideRequiredMarker", "floatLabel", "label", "appearance", "subscriptSizing", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug", "panelClass", "panelWidth"], outputs: ["keyup.enter"] }, { kind: "pipe", type: i7.TranslatePipe, name: "translate" }] });
181
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: RegisterForm, selector: "app-register-form", outputs: { onCancel: "onCancel", onSubmit: "onSubmit" }, viewQueries: [{ propertyName: "stepper", first: true, predicate: ["stepper"], descendants: true, static: true }], ngImport: i0, template: "<mat-horizontal-stepper linear #stepper=\"matHorizontalStepper\">\n <!-- Step 1: Username -->\n <mat-step [stepControl]=\"forms[0]\" *ngIf=\"forms[0].controls; let controls\">\n <form [formGroup]=\"forms[0]\" class=\"form-container ion-padding\" (keyup.enter)=\"slideNext($event)\">\n <ng-template matStepLabel>{{ 'REGISTER.STEP_EMAIL' | translate }}</ng-template>\n\n <!-- Email -->\n <mat-form-field>\n <mat-label>{{ 'USER.EMAIL' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"email\"\n autocomplete=\"off\"\n required\n />\n <mat-error *ngIf=\"controls.email.hasError('required') && controls.email.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error\n *ngIf=\"controls.email.hasError('email') && !controls.email.hasError('required') && controls.email.touched\"\n >\n <span>{{ 'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n <mat-error *ngIf=\"controls.email.hasError('availability') && controls.email.touched\" translate>\n REGISTER.ERROR.EMAIL_ALREADY_REGISTERED\n </mat-error>\n </mat-form-field>\n\n <!-- Confirm Email -->\n <mat-form-field>\n <mat-label>{{ 'REGISTER.CONFIRM_EMAIL' | translate }}</mat-label>\n <input matInput autocomplete=\"off\" matFormFieldControl formControlName=\"confirmEmail\"/>\n <mat-error *ngIf=\"controls.confirmEmail.hasError('required') && controls.confirmEmail.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.confirmEmail.hasError('equals') && controls.confirmEmail.touched\">\n <span>{{ 'REGISTER.ERROR.NOT_SAME_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </form>\n </mat-step>\n\n <!-- Step 2: Password -->\n <mat-step [stepControl]=\"forms[1]\" *ngIf=\"forms[1].controls; let controls\">\n <form [formGroup]=\"forms[1]\" class=\"form-container ion-padding\" (keyup.enter)=\"slideNext($event)\">\n <ng-template matStepLabel>{{ 'REGISTER.STEP_PASSWORD' | translate }}</ng-template>\n\n <!-- Password -->\n <mat-form-field>\n <mat-label>{{ 'USER.PASSWORD' | translate }}</mat-label>\n <input\n matInput\n formControlName=\"password\"\n autocomplete=\"section-red new-password\"\n [type]=\"showPwd ? 'text' : 'password'\"\n required\n />\n <button matSuffix mat-icon-button type=\"button\" (click)=\"showPwd = !showPwd\" tabindex=\"-1\">\n <mat-icon>{{ showPwd ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n <mat-error *ngIf=\"controls.password.hasError('required') && controls.password.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.password.hasError('minlength') && controls.password.touched\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: {requiredLength: 8} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- Confirm password -->\n <mat-form-field>\n <mat-label>{{ 'REGISTER.CONFIRM_PASSWORD' | translate }}</mat-label>\n <input\n matInput\n formControlName=\"confirmPassword\"\n autocomplete=\"section-red new-password\"\n [type]=\"showConfirmPwd ? 'text' : 'password'\"\n required\n />\n <button mat-icon-button matSuffix (click)=\"showConfirmPwd = !showConfirmPwd\" tabindex=\"-1\">\n <mat-icon>{{ showConfirmPwd ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n <mat-error *ngIf=\"controls.confirmPassword.hasError('required') && controls.confirmPassword.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.confirmPassword.hasError('equals') && controls.confirmPassword.touched\">\n <span>{{ 'REGISTER.ERROR.NOT_SAME_PASSWORD' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </form>\n </mat-step>\n\n <!-- Step 3: user details -->\n <mat-step [stepControl]=\"forms[2]\" *ngIf=\"forms[2].controls; let controls\">\n <form\n [formGroup]=\"forms[2]\"\n (ngSubmit)=\"doSubmit($event)\"\n class=\"form-container ion-padding\"\n (keyup.enter)=\"doSubmit()\"\n >\n <ng-template matStepLabel>{{ 'REGISTER.STEP_USER_DETAILS' | translate }}</ng-template>\n\n <!-- error -->\n <ion-item *ngIf=\"error && !sending\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- Last name -->\n <mat-form-field>\n <mat-label>{{ 'USER.LAST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"lastName\" autocomplete=\"section-blue family-name\" required/>\n <mat-error *ngIf=\"controls.lastName.hasError('required') && controls.lastName.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.lastName.hasError('minlength') && controls.lastName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: {requiredLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <mat-label>{{ 'USER.FIRST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"firstName\" autocomplete=\"section-blue given-name\" required/>\n <mat-error *ngIf=\"controls.firstName.hasError('required') && controls.firstName.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.firstName.hasError('minlength') && controls.firstName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: {requiredLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- Additional fields -->\n @for (field of additionalFields; track field.key) {\n @if (field.extra.registration?.description; as description) {\n <ion-text>\n <p [innerHTML]=\"description | translate\"></p>\n </ion-text>\n }\n <app-form-field\n [definition]=\"field\"\n [formControlName]=\"field.key\"\n [required]=\"field.extra?.registration.required ?? field.extra?.account.required ?? false\"\n ></app-form-field>\n }\n </form>\n </mat-step>\n</mat-horizontal-stepper>\n", styles: ["form ion-toolbar.toolbar-buttons .toolbar-content{text-align:right}form ion-toolbar.toolbar-buttons .toolbar-background{border:0;background:inherit!important}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i6.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i6.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i6.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i7.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { 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.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatLabel, selector: "mat-label" }, { kind: "directive", type: i8.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i8.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i10.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i11.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i12.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i12.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i12.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "directive", type: i13.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "component", type: i14.AppFormField, selector: "app-form-field", inputs: ["definition", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "required", "hideRequiredMarker", "floatLabel", "label", "appearance", "subscriptSizing", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug", "panelClass", "panelWidth"], outputs: ["keyup.enter"] }, { kind: "pipe", type: i7.TranslatePipe, name: "translate" }] });
182
182
  }
183
183
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RegisterForm, decorators: [{
184
184
  type: Component,
185
- args: [{ selector: 'app-register-form', template: "<mat-horizontal-stepper linear #stepper=\"matHorizontalStepper\">\n <!-- Step 1: Username -->\n <mat-step [stepControl]=\"forms[0]\" *ngIf=\"forms[0].controls; let controls\">\n <form [formGroup]=\"forms[0]\" class=\"form-container ion-padding\" (keyup.enter)=\"slideNext($event)\">\n <ng-template matStepLabel>{{ 'REGISTER.STEP_EMAIL' | translate }}</ng-template>\n\n <!-- Email -->\n <mat-form-field>\n <mat-label>{{ 'USER.EMAIL' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"email\"\n autocomplete=\"off\"\n required\n />\n <mat-error *ngIf=\"controls.email.hasError('required') && controls.email.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error\n *ngIf=\"controls.email.hasError('email') && !controls.email.hasError('required') && controls.email.touched\"\n >\n <span>{{ 'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n <mat-error *ngIf=\"controls.email.hasError('availability') && controls.email.touched\" translate>\n REGISTER.ERROR.EMAIL_ALREADY_REGISTERED\n </mat-error>\n </mat-form-field>\n\n <!-- Confirm Email -->\n <mat-form-field>\n <mat-label>{{ 'REGISTER.CONFIRM_EMAIL' | translate }}</mat-label>\n <input matInput autocomplete=\"off\" matFormFieldControl formControlName=\"confirmEmail\" />\n <mat-error *ngIf=\"controls.confirmEmail.hasError('required') && controls.confirmEmail.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.confirmEmail.hasError('equals') && controls.confirmEmail.touched\">\n <span>{{ 'REGISTER.ERROR.NOT_SAME_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </form>\n </mat-step>\n\n <!-- Step 2: Password -->\n <mat-step [stepControl]=\"forms[1]\" *ngIf=\"forms[1].controls; let controls\">\n <form [formGroup]=\"forms[1]\" class=\"form-container ion-padding\" (keyup.enter)=\"slideNext($event)\">\n <ng-template matStepLabel>{{ 'REGISTER.STEP_PASSWORD' | translate }}</ng-template>\n\n <!-- Password -->\n <mat-form-field>\n <mat-label>{{ 'USER.PASSWORD' | translate }}</mat-label>\n <input\n matInput\n formControlName=\"password\"\n autocomplete=\"section-red new-password\"\n [type]=\"showPwd ? 'text' : 'password'\"\n required\n />\n <button matSuffix mat-icon-button type=\"button\" (click)=\"showPwd = !showPwd\" tabindex=\"-1\">\n <mat-icon>{{ showPwd ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n <mat-error *ngIf=\"controls.password.hasError('required') && controls.password.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.password.hasError('minlength') && controls.password.touched\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 8 } }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- Confirm password -->\n <mat-form-field>\n <mat-label>{{ 'REGISTER.CONFIRM_PASSWORD' | translate }}</mat-label>\n <input\n matInput\n formControlName=\"confirmPassword\"\n autocomplete=\"section-red new-password\"\n [type]=\"showConfirmPwd ? 'text' : 'password'\"\n required\n />\n <button mat-icon-button matSuffix (click)=\"showConfirmPwd = !showConfirmPwd\" tabindex=\"-1\">\n <mat-icon>{{ showConfirmPwd ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n <mat-error *ngIf=\"controls.confirmPassword.hasError('required') && controls.confirmPassword.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.confirmPassword.hasError('equals') && controls.confirmPassword.touched\">\n <span>{{ 'REGISTER.ERROR.NOT_SAME_PASSWORD' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </form>\n </mat-step>\n\n <!-- Step 3: user details -->\n <mat-step [stepControl]=\"forms[2]\" *ngIf=\"forms[2].controls; let controls\">\n <form\n [formGroup]=\"forms[2]\"\n (ngSubmit)=\"doSubmit($event)\"\n class=\"form-container ion-padding\"\n (keyup.enter)=\"doSubmit()\"\n >\n <ng-template matStepLabel>{{ 'REGISTER.STEP_USER_DETAILS' | translate }}</ng-template>\n\n <!-- error -->\n <ion-item *ngIf=\"error && !sending\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- Last name -->\n <mat-form-field>\n <mat-label>{{ 'USER.LAST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"lastName\" autocomplete=\"section-blue family-name\" required />\n <mat-error *ngIf=\"controls.lastName.hasError('required') && controls.lastName.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.lastName.hasError('minlength') && controls.lastName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <mat-label>{{ 'USER.FIRST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"firstName\" autocomplete=\"section-blue given-name\" required />\n <mat-error *ngIf=\"controls.firstName.hasError('required') && controls.firstName.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.firstName.hasError('minlength') && controls.firstName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- Additional fields -->\n <app-form-field\n *ngFor=\"let field of additionalFields\"\n [definition]=\"field\"\n [formControlName]=\"field.key\"\n [required]=\"field.extra?.registration.required ?? field.extra?.account.required ?? false\"\n ></app-form-field>\n </form>\n </mat-step>\n</mat-horizontal-stepper>\n", styles: ["form ion-toolbar.toolbar-buttons .toolbar-content{text-align:right}form ion-toolbar.toolbar-buttons .toolbar-background{border:0;background:inherit!important}\n"] }]
185
+ args: [{ selector: 'app-register-form', template: "<mat-horizontal-stepper linear #stepper=\"matHorizontalStepper\">\n <!-- Step 1: Username -->\n <mat-step [stepControl]=\"forms[0]\" *ngIf=\"forms[0].controls; let controls\">\n <form [formGroup]=\"forms[0]\" class=\"form-container ion-padding\" (keyup.enter)=\"slideNext($event)\">\n <ng-template matStepLabel>{{ 'REGISTER.STEP_EMAIL' | translate }}</ng-template>\n\n <!-- Email -->\n <mat-form-field>\n <mat-label>{{ 'USER.EMAIL' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"email\"\n autocomplete=\"off\"\n required\n />\n <mat-error *ngIf=\"controls.email.hasError('required') && controls.email.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error\n *ngIf=\"controls.email.hasError('email') && !controls.email.hasError('required') && controls.email.touched\"\n >\n <span>{{ 'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n <mat-error *ngIf=\"controls.email.hasError('availability') && controls.email.touched\" translate>\n REGISTER.ERROR.EMAIL_ALREADY_REGISTERED\n </mat-error>\n </mat-form-field>\n\n <!-- Confirm Email -->\n <mat-form-field>\n <mat-label>{{ 'REGISTER.CONFIRM_EMAIL' | translate }}</mat-label>\n <input matInput autocomplete=\"off\" matFormFieldControl formControlName=\"confirmEmail\"/>\n <mat-error *ngIf=\"controls.confirmEmail.hasError('required') && controls.confirmEmail.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.confirmEmail.hasError('equals') && controls.confirmEmail.touched\">\n <span>{{ 'REGISTER.ERROR.NOT_SAME_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </form>\n </mat-step>\n\n <!-- Step 2: Password -->\n <mat-step [stepControl]=\"forms[1]\" *ngIf=\"forms[1].controls; let controls\">\n <form [formGroup]=\"forms[1]\" class=\"form-container ion-padding\" (keyup.enter)=\"slideNext($event)\">\n <ng-template matStepLabel>{{ 'REGISTER.STEP_PASSWORD' | translate }}</ng-template>\n\n <!-- Password -->\n <mat-form-field>\n <mat-label>{{ 'USER.PASSWORD' | translate }}</mat-label>\n <input\n matInput\n formControlName=\"password\"\n autocomplete=\"section-red new-password\"\n [type]=\"showPwd ? 'text' : 'password'\"\n required\n />\n <button matSuffix mat-icon-button type=\"button\" (click)=\"showPwd = !showPwd\" tabindex=\"-1\">\n <mat-icon>{{ showPwd ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n <mat-error *ngIf=\"controls.password.hasError('required') && controls.password.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.password.hasError('minlength') && controls.password.touched\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: {requiredLength: 8} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- Confirm password -->\n <mat-form-field>\n <mat-label>{{ 'REGISTER.CONFIRM_PASSWORD' | translate }}</mat-label>\n <input\n matInput\n formControlName=\"confirmPassword\"\n autocomplete=\"section-red new-password\"\n [type]=\"showConfirmPwd ? 'text' : 'password'\"\n required\n />\n <button mat-icon-button matSuffix (click)=\"showConfirmPwd = !showConfirmPwd\" tabindex=\"-1\">\n <mat-icon>{{ showConfirmPwd ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n <mat-error *ngIf=\"controls.confirmPassword.hasError('required') && controls.confirmPassword.touched\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.confirmPassword.hasError('equals') && controls.confirmPassword.touched\">\n <span>{{ 'REGISTER.ERROR.NOT_SAME_PASSWORD' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </form>\n </mat-step>\n\n <!-- Step 3: user details -->\n <mat-step [stepControl]=\"forms[2]\" *ngIf=\"forms[2].controls; let controls\">\n <form\n [formGroup]=\"forms[2]\"\n (ngSubmit)=\"doSubmit($event)\"\n class=\"form-container ion-padding\"\n (keyup.enter)=\"doSubmit()\"\n >\n <ng-template matStepLabel>{{ 'REGISTER.STEP_USER_DETAILS' | translate }}</ng-template>\n\n <!-- error -->\n <ion-item *ngIf=\"error && !sending\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- Last name -->\n <mat-form-field>\n <mat-label>{{ 'USER.LAST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"lastName\" autocomplete=\"section-blue family-name\" required/>\n <mat-error *ngIf=\"controls.lastName.hasError('required') && controls.lastName.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.lastName.hasError('minlength') && controls.lastName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: {requiredLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <mat-label>{{ 'USER.FIRST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"firstName\" autocomplete=\"section-blue given-name\" required/>\n <mat-error *ngIf=\"controls.firstName.hasError('required') && controls.firstName.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"controls.firstName.hasError('minlength') && controls.firstName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: {requiredLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- Additional fields -->\n @for (field of additionalFields; track field.key) {\n @if (field.extra.registration?.description; as description) {\n <ion-text>\n <p [innerHTML]=\"description | translate\"></p>\n </ion-text>\n }\n <app-form-field\n [definition]=\"field\"\n [formControlName]=\"field.key\"\n [required]=\"field.extra?.registration.required ?? field.extra?.account.required ?? false\"\n ></app-form-field>\n }\n </form>\n </mat-step>\n</mat-horizontal-stepper>\n", styles: ["form ion-toolbar.toolbar-buttons .toolbar-content{text-align:right}form ion-toolbar.toolbar-buttons .toolbar-background{border:0;background:inherit!important}\n"] }]
186
186
  }], ctorParameters: () => [{ type: i1.AccountService }, { type: i2.AccountValidatorService }, { type: i3.UntypedFormBuilder }, { type: i15.Environment, decorators: [{
187
187
  type: Inject,
188
188
  args: [ENVIRONMENT]
@@ -194,4 +194,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
194
194
  }], onSubmit: [{
195
195
  type: Output
196
196
  }] } });
197
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0ZXIuZm9ybS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29yZS9yZWdpc3Rlci9yZWdpc3Rlci5mb3JtLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb3JlL3JlZ2lzdGVyL3JlZ2lzdGVyLmZvcm0uaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQVUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRixPQUFPLEVBSUwsa0JBQWtCLEVBSWxCLFVBQVUsR0FDWCxNQUFNLGdCQUFnQixDQUFDO0FBRXhCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMxRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUUxRSxPQUFPLEVBQUUsS0FBSyxFQUFjLEVBQUUsRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFHM0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTFDLE9BQU8sRUFBZSxXQUFXLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUNuRixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxpRUFBaUUsQ0FBQztBQUM5RyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBT2xELE1BQU0sT0FBTyxZQUFZO0lBdUJiO0lBQ0E7SUFDRDtJQUN3QjtJQUNyQjtJQTFCRixLQUFLLEdBQUcsS0FBSyxDQUFDO0lBRXhCLGtCQUFrQixDQUE4QjtJQUNoRCxnQkFBZ0IsQ0FBd0I7SUFDeEMsSUFBSSxDQUFtQjtJQUN2QixLQUFLLENBQXFCO0lBQzFCLGFBQWEsR0FBbUIsRUFBRSxDQUFDO0lBQ25DLEtBQUssQ0FBUztJQUNkLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFFaEIsT0FB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SSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDcEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRCxtQkFBbUIsR0FBRyxtQkFBbUIsQ0FBQztJQUUxQyxhQUFhO1FBQ1gsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRUQsT0FBTztRQUNMLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVELE1BQU07UUFDSixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ3JCLENBQUM7d0dBOUxVLFlBQVkseUhBMEJiLFdBQVc7NEZBMUJWLFlBQVksb09DN0J6QixpM01BK0lBOzs0RkRsSGEsWUFBWTtrQkFMeEIsU0FBUzsrQkFDRSxtQkFBbUI7OzBCQThCMUIsTUFBTTsyQkFBQyxXQUFXOzRFQVoyQixPQUFPO3NCQUF0RCxTQUFTO3VCQUFDLFNBQVMsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBR3RDLFFBQVE7c0JBRFAsTUFBTTtnQkFJUCxRQUFRO3NCQURQLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5qZWN0LCBPbkluaXQsIE91dHB1dCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBBYnN0cmFjdENvbnRyb2wsXG4gIEFzeW5jVmFsaWRhdG9yRm4sXG4gIFVudHlwZWRGb3JtQnVpbGRlcixcbiAgVW50eXBlZEZvcm1Db250cm9sLFxuICBVbnR5cGVkRm9ybUdyb3VwLFxuICBWYWxpZGF0aW9uRXJyb3JzLFxuICBWYWxpZGF0b3JGbixcbiAgVmFsaWRhdG9ycyxcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQWNjb3VudFNlcnZpY2UsIFJlZ2lzdGVyRGF0YSB9IGZyb20gJy4uL3NlcnZpY2VzL2FjY291bnQuc2VydmljZSc7XG5pbXBvcnQgeyBBY2NvdW50IH0gZnJvbSAnLi4vc2VydmljZXMvbW9kZWwvYWNjb3VudC5tb2RlbCc7XG5pbXBvcnQgeyByZWZlcmVudGlhbFRvU3RyaW5nIH0gZnJvbSAnLi4vc2VydmljZXMvbW9kZWwvcmVmZXJlbnRpYWwubW9kZWwnO1xuaW1wb3J0IHsgTWF0U3RlcHBlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3N0ZXBwZXInO1xuaW1wb3J0IHsgZGVsYXksIE9ic2VydmFibGUsIG9mLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEFjY291bnRWYWxpZGF0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvdmFsaWRhdG9yL2FjY291bnQudmFsaWRhdG9yJztcbmltcG9ydCB7IEZvcm1GaWVsZERlZmluaXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQvZm9ybS9maWVsZC5tb2RlbCc7XG5pbXBvcnQgeyBtZXJnZU1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IExvY2FsU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvbG9jYWwtc2V0dGluZ3Muc2VydmljZSc7XG5pbXBvcnQgeyBFbnZpcm9ubWVudCwgRU5WSVJPTk1FTlQgfSBmcm9tICcuLi8uLi8uLi9lbnZpcm9ubWVudHMvZW52aXJvbm1lbnQuY2xhc3MnO1xuaW1wb3J0IHsgTWF0QXV0b2NvbXBsZXRlQ29uZmlnSG9sZGVyIH0gZnJvbSAnLi4vLi4vc2hhcmVkL21hdGVyaWFsL2F1dG9jb21wbGV0ZS9tYXRlcmlhbC5hdXRvY29tcGxldGUuY29uZmlnJztcbmltcG9ydCB7IGlzTm90TmlsIH0gZnJvbSAnLi4vLi4vc2hhcmVkL2Z1bmN0aW9ucyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1yZWdpc3Rlci1mb3JtJyxcbiAgdGVtcGxhdGVVcmw6ICdyZWdpc3Rlci5mb3JtLmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9yZWdpc3Rlci5mb3JtLnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgUmVnaXN0ZXJGb3JtIGltcGxlbWVudHMgT25Jbml0IHtcbiAgcHJvdGVjdGVkIGRlYnVnID0gZmFsc2U7XG5cbiAgYXV0b2NvbXBsZXRlSGVscGVyOiBNYXRBdXRvY29tcGxldGVDb25maWdIb2xkZXI7XG4gIGFkZGl0aW9uYWxGaWVsZHM6IEZvcm1GaWVsZERlZmluaXRpb25bXTtcbiAgZm9ybTogVW50eXBlZEZvcm1Hcm91cDtcbiAgZm9ybXM6IFVudHlwZWRGb3JtR3JvdXBbXTtcbiAgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcbiAgZXJyb3I6IHN0cmluZztcbiAgc2VuZGluZyA9IGZhbHNlO1xuXG4gIHNob3dQd2QgPSBmYWxzZTtcbiAgc2hvd0NvbmZpcm1Qd2QgPSBmYWxzZTtcblxuICBAVmlld0NoaWxkKCdzdGVwcGVyJywgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSBzdGVwcGVyOiBNYXRTdGVwcGVyO1xuXG4gIEBPdXRwdXQoKVxuICBvbkNhbmNlbCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIEBPdXRwdXQoKVxuICBvblN1Ym1pdCA9IG5ldyBFdmVudEVtaXR0ZXI8UmVnaXN0ZXJEYXRhPigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYWNjb3VudFNlcnZpY2U6IEFjY291bnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgYWNjb3VudFZhbGlkYXRvclNlcnZpY2U6IEFjY291bnRWYWxpZGF0b3JTZXJ2aWNlLFxuICAgIHB1YmxpYyBmb3JtQnVpbGRlcjogVW50eXBlZEZvcm1CdWlsZGVyLFxuICAgIEBJbmplY3QoRU5WSVJPTk1FTlQpIHByb3RlY3RlZCBlbnZpcm9ubWVudDogRW52aXJvbm1lbnQsXG4gICAgcHJvdGVjdGVkIHNldHRpbmdzPzogTG9jYWxTZXR0aW5nc1NlcnZpY2VcbiAgKSB7XG4gICAgdGhpcy5mb3JtcyA9IFtdO1xuICAgIC8vIEVtYWlsIGZvcm1cbiAgICB0aGlzLmZvcm1zLnB1c2goXG4gICAgICBmb3JtQnVpbGRlci5ncm91cCh7XG4gICAgICAgIGVtYWlsOiBuZXcgVW50eXBlZEZvcm1Db250cm9sKG51bGwsIFZhbGlkYXRvcnMuY29tcG9zZShbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5lbWFpbF0pLCB0aGlzLmVtYWlsQXZhaWxhYmlsaXR5KHRoaXMuYWNjb3VudFNlcnZpY2UpKSxcbiAgICAgICAgY29uZmlybUVtYWlsOiBuZXcgVW50eXBlZEZvcm1Db250cm9sKG51bGwsIFZhbGlkYXRvcnMuY29tcG9zZShbVmFsaWRhdG9ycy5yZXF1aXJlZCwgdGhpcy5lcXVhbHNWYWxpZGF0b3IoJ2VtYWlsJyldKSksXG4gICAgICB9KVxuICAgICk7XG5cbiAgICAvLyBQYXNzd29yZCBmb3JtXG4gICAgdGhpcy5mb3Jtcy5wdXNoKFxuICAgICAgZm9ybUJ1aWxkZXIuZ3JvdXAoe1xuICAgICAgICBwYXNzd29yZDogbmV3IFVudHlwZWRGb3JtQ29udHJvbChudWxsLCBWYWxpZGF0b3JzLmNvbXBvc2UoW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMubWluTGVuZ3RoKDgpXSkpLFxuICAgICAgICBjb25maXJtUGFzc3dvcmQ6IG5ldyBVbnR5cGVkRm9ybUNvbnRyb2wobnVsbCwgVmFsaWRhdG9ycy5jb21wb3NlKFtWYWxpZGF0b3JzLnJlcXVpcmVkLCB0aGlzLmVxdWFsc1ZhbGlkYXRvcigncGFzc3dvcmQnKV0pKSxcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIC8vIERldGFpbCBmb3JtXG4gICAgY29uc3QgZm9ybURldGFpbERlZiA9IHtcbiAgICAgIGxhc3ROYW1lOiBuZXcgVW50eXBlZEZvcm1Db250cm9sKG51bGwsIFZhbGlkYXRvcnMuY29tcG9zZShbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5taW5MZW5ndGgoMildKSksXG4gICAgICBmaXJzdE5hbWU6IG5ldyBVbnR5cGVkRm9ybUNvbnRyb2wobnVsbCwgVmFsaWRhdG9ycy5jb21wb3NlKFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLm1pbkxlbmd0aCgyKV0pKSxcbiAgICB9O1xuXG4gICAgLy8gUHJlcGFyZSBhdXRvY29tcGxldGUgc2V0dGluZ3NcbiAgICB0aGlzLmF1dG9jb21wbGV0ZUhlbHBlciA9IG5ldyBNYXRBdXRvY29tcGxldGVDb25maWdIb2xkZXIoXG4gICAgICBzZXR0aW5ncyAmJiB7XG4gICAgICAgIGdldFVzZXJBdHRyaWJ1dGVzOiAoYSwgYikgPT4gc2V0dGluZ3MuZ2V0RmllbGREaXNwbGF5QXR0cmlidXRlcyhhLCBiKSxcbiAgICAgIH1cbiAgICApO1xuXG4gICAgLy8gQWRkIGFkZGl0aW9uYWwgZmllbGRzIHRvIGRldGFpbHMgZm9ybVxuICAgIHRoaXMuYWRkaXRpb25hbEZpZWxkcyA9IHRoaXMuYWNjb3VudFNlcnZpY2UuYWRkaXRpb25hbEZpZWxkc1xuICAgICAgLy8gS2VlcCBvbmx5IHJlcXVpcmVkIGZpZWxkc1xuICAgICAgLmZpbHRlcigoZmllbGQpID0+IGZpZWxkLmV4dHJhPy5yZWdpc3RyYXRpb24gJiYgZmllbGQuZXh0cmEucmVnaXN0cmF0aW9uLmRpc2FibGVkICE9PSBmYWxzZSlcbiAgICAgIC5tYXAoKGZpZWxkKSA9PiB7XG4gICAgICAgIC8vaWYgKHRoaXMuZGVidWcpIGNvbnNvbGUuZGVidWcoXCJbcmVnaXN0ZXItZm9ybV0gQWRkIGFkZGl0aW9uYWwgZmllbGQge1wiICsgZmllbGQubmFtZSArIFwifSB0byBmb3JtXCIsIGZpZWxkKTtcbiAgICAgICAgZm9ybURldGFpbERlZltmaWVsZC5rZXldID0gbmV3IFVudHlwZWRGb3JtQ29udHJvbChudWxsLCB0aGlzLmFjY291bnRWYWxpZGF0b3JTZXJ2aWNlLmdldFZhbGlkYXRvcnMoZmllbGQsIGZpZWxkLmV4dHJhLnJlZ2lzdHJhdGlvbi5yZXF1aXJlZCkpO1xuXG4gICAgICAgIGlmIChpc05vdE5pbChmaWVsZC5hdXRvY29tcGxldGUpKSB7XG4gICAgICAgICAgZmllbGQuYXV0b2NvbXBsZXRlID0gdGhpcy5hdXRvY29tcGxldGVIZWxwZXIuYWRkKGZpZWxkLmtleSwgZmllbGQuYXV0b2NvbXBsZXRlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmllbGQ7XG4gICAgICB9KTtcblxuICAgIHRoaXMuZm9ybXMucHVzaChmb3JtQnVpbGRlci5ncm91cChmb3JtRGV0YWlsRGVmKSk7XG5cbiAgICB0aGlzLmZvcm0gPSBmb3JtQnVpbGRlci5ncm91cCh7XG4gICAgICBlbWFpbFN0ZXA6IHRoaXMuZm9ybXNbMF0sXG4gICAgICBwYXNzd29yZFN0ZXA6IHRoaXMuZm9ybXNbMV0sXG4gICAgICBkZXRhaWxzU3RlcDogdGhpcy5mb3Jtc1syXSxcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIC8vIEZvciBERVYgb25seSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBpZiAoIXRoaXMuZW52aXJvbm1lbnQucHJvZHVjdGlvbikge1xuICAgICAgdGhpcy5mb3JtLnNldFZhbHVlKHtcbiAgICAgICAgZW1haWxTdGVwOiB7XG4gICAgICAgICAgZW1haWw6ICdjb250YWN0QGUtaXMucHJvJyxcbiAgICAgICAgICBjb25maXJtRW1haWw6ICdjb250YWN0QGUtaXMucHJvJyxcbiAgICAgICAgfSxcbiAgICAgICAgcGFzc3dvcmRTdGVwOiB7XG4gICAgICAgICAgcGFzc3dvcmQ6ICdjb250YWN0ZXJhJyxcbiAgICAgICAgICBjb25maXJtUGFzc3dvcmQ6ICdjb250YWN0ZXJhJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGV0YWlsc1N0ZXA6IHtcbiAgICAgICAgICBsYXN0TmFtZTogJ0xhdmVuaWVyIDInLFxuICAgICAgICAgIGZpcnN0TmFtZTogJ0Jlbm9pdCcsXG4gICAgICAgICAgZGVwYXJ0bWVudDogbnVsbCxcbiAgICAgICAgICBwcm9ncmFtczogbnVsbFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IHZhbHVlKCk6IFJlZ2lzdGVyRGF0YSB7XG4gICAgY29uc3QgcmVzdWx0OiBSZWdpc3RlckRhdGEgPSB7XG4gICAgICB1c2VybmFtZTogdGhpcy5mb3JtLnZhbHVlLmVtYWlsU3RlcC5lbWFpbCxcbiAgICAgIHBhc3N3b3JkOiB0aGlzLmZvcm0udmFsdWUucGFzc3dvcmRTdGVwLnBhc3N3b3JkLFxuICAgICAgYWNjb3VudDogbmV3IEFjY291bnQoKSxcbiAgICB9O1xuICAgIHJlc3VsdC5hY2NvdW50LmZyb21PYmplY3QodGhpcy5mb3JtLnZhbHVlLmRldGFpbHNTdGVwKTtcbiAgICByZXN1bHQuYWNjb3VudC5lbWFpbCA9IHJlc3VsdC51c2VybmFtZTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBnZXQgdmFsaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybS52YWxpZDtcbiAgfVxuXG4gIGlzRW5kKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN0ZXBwZXIuc2VsZWN0ZWRJbmRleCA9PT0gMjtcbiAgfVxuXG4gIGlzQmVnaW5uaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN0ZXBwZXIuc2VsZWN0ZWRJbmRleCA9PT0gMDtcbiAgfVxuXG4gIHNsaWRlUHJldigpIHtcbiAgICByZXR1cm4gdGhpcy5zdGVwcGVyLnByZXZpb3VzKCk7XG4gIH1cblxuICBzbGlkZU5leHQoZXZlbnQ/OiBFdmVudCkge1xuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zdGVwcGVyLm5leHQoKTtcbiAgfVxuXG4gIGVxdWFsc1ZhbGlkYXRvcihvdGhlckNvbnRyb2xOYW1lOiBzdHJpbmcpOiBWYWxpZGF0b3JGbiB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChjOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XG4gICAgICBpZiAoYy5wYXJlbnQgJiYgYy52YWx1ZSAhPT0gYy5wYXJlbnQudmFsdWVbb3RoZXJDb250cm9sTmFtZV0pIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBlcXVhbHM6IHRydWUsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICB9XG5cbiAgZW1haWxBdmFpbGFiaWxpdHkoYWNjb3VudFNlcnZpY2U6IEFjY291bnRTZXJ2aWNlKTogQXN5bmNWYWxpZGF0b3JGbiB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBPYnNlcnZhYmxlPFZhbGlkYXRpb25FcnJvcnMgfCBudWxsPiB7XG4gICAgICByZXR1cm4gb2YobnVsbCkucGlwZShcbiAgICAgICAgZGVsYXkoNTAwKSxcbiAgICAgICAgbWVyZ2VNYXAoKCkgPT5cbiAgICAgICAgICBhY2NvdW50U2VydmljZVxuICAgICAgICAgICAgLmNoZWNrRW1haWxBdmFpbGFibGUoY29udHJvbC52YWx1ZSlcbiAgICAgICAgICAgIC50aGVuKChyZXMpID0+IG51bGwpXG4gICAgICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICAgICAgICAgIHJldHVybiB7IGF2YWlsYWJpbGl0eTogdHJ1ZSB9O1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9O1xuICB9XG5cbiAgY2FuY2VsKCkge1xuICAgIHRoaXMub25DYW5jZWwuZW1pdCgpO1xuICB9XG5cbiAgZG9TdWJtaXQoZXZlbnQ/OiBhbnkpIHtcbiAgICBpZiAodGhpcy5mb3JtLmludmFsaWQpIHJldHVybjtcbiAgICB0aGlzLnNlbmRpbmcgPSB0cnVlO1xuICAgIHRoaXMub25TdWJtaXQuZW1pdCh0aGlzLnZhbHVlKTtcbiAgfVxuXG4gIHJlZmVyZW50aWFsVG9TdHJpbmcgPSByZWZlcmVudGlhbFRvU3RyaW5nO1xuXG4gIG1hcmtBc1RvdWNoZWQoKSB7XG4gICAgdGhpcy5mb3JtLm1hcmtBc1RvdWNoZWQoKTtcbiAgfVxuXG4gIGRpc2FibGUoKSB7XG4gICAgdGhpcy5mb3JtLmRpc2FibGUoKTtcbiAgfVxuXG4gIGVuYWJsZSgpIHtcbiAgICB0aGlzLmZvcm0uZW5hYmxlKCk7XG4gIH1cbn1cbiIsIjxtYXQtaG9yaXpvbnRhbC1zdGVwcGVyIGxpbmVhciAjc3RlcHBlcj1cIm1hdEhvcml6b250YWxTdGVwcGVyXCI+XG4gIDwhLS0gU3RlcCAxOiBVc2VybmFtZSAtLT5cbiAgPG1hdC1zdGVwIFtzdGVwQ29udHJvbF09XCJmb3Jtc1swXVwiICpuZ0lmPVwiZm9ybXNbMF0uY29udHJvbHM7IGxldCBjb250cm9sc1wiPlxuICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiZm9ybXNbMF1cIiBjbGFzcz1cImZvcm0tY29udGFpbmVyIGlvbi1wYWRkaW5nXCIgKGtleXVwLmVudGVyKT1cInNsaWRlTmV4dCgkZXZlbnQpXCI+XG4gICAgICA8bmctdGVtcGxhdGUgbWF0U3RlcExhYmVsPnt7ICdSRUdJU1RFUi5TVEVQX0VNQUlMJyB8IHRyYW5zbGF0ZSB9fTwvbmctdGVtcGxhdGU+XG5cbiAgICAgIDwhLS0gRW1haWwgLS0+XG4gICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgIDxtYXQtbGFiZWw+e3sgJ1VTRVIuRU1BSUwnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgW2FwcEF1dG9mb2N1c109XCJ0cnVlXCJcbiAgICAgICAgICBbYXV0b2ZvY3VzRGVsYXldPVwiNTAwXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICAgICAgYXV0b2NvbXBsZXRlPVwib2ZmXCJcbiAgICAgICAgICByZXF1aXJlZFxuICAgICAgICAvPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuZW1haWwuaGFzRXJyb3IoJ3JlcXVpcmVkJykgJiYgY29udHJvbHMuZW1haWwudG91Y2hlZFwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgPG1hdC1lcnJvclxuICAgICAgICAgICpuZ0lmPVwiY29udHJvbHMuZW1haWwuaGFzRXJyb3IoJ2VtYWlsJykgJiYgIWNvbnRyb2xzLmVtYWlsLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIGNvbnRyb2xzLmVtYWlsLnRvdWNoZWRcIlxuICAgICAgICA+XG4gICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX05PVF9WQUxJRF9FTUFJTCcgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuZW1haWwuaGFzRXJyb3IoJ2F2YWlsYWJpbGl0eScpICYmIGNvbnRyb2xzLmVtYWlsLnRvdWNoZWRcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgUkVHSVNURVIuRVJST1IuRU1BSUxfQUxSRUFEWV9SRUdJU1RFUkVEXG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgPCEtLSBDb25maXJtIEVtYWlsIC0tPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdSRUdJU1RFUi5DT05GSVJNX0VNQUlMJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXQgbWF0SW5wdXQgYXV0b2NvbXBsZXRlPVwib2ZmXCIgbWF0Rm9ybUZpZWxkQ29udHJvbCBmb3JtQ29udHJvbE5hbWU9XCJjb25maXJtRW1haWxcIiAvPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuY29uZmlybUVtYWlsLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIGNvbnRyb2xzLmNvbmZpcm1FbWFpbC50b3VjaGVkXCIgdHJhbnNsYXRlPlxuICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuY29uZmlybUVtYWlsLmhhc0Vycm9yKCdlcXVhbHMnKSAmJiBjb250cm9scy5jb25maXJtRW1haWwudG91Y2hlZFwiPlxuICAgICAgICAgIDxzcGFuPnt7ICdSRUdJU1RFUi5FUlJPUi5OT1RfU0FNRV9FTUFJTCcgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Zvcm0+XG4gIDwvbWF0LXN0ZXA+XG5cbiAgPCEtLSBTdGVwIDI6IFBhc3N3b3JkIC0tPlxuICA8bWF0LXN0ZXAgW3N0ZXBDb250cm9sXT1cImZvcm1zWzFdXCIgKm5nSWY9XCJmb3Jtc1sxXS5jb250cm9sczsgbGV0IGNvbnRyb2xzXCI+XG4gICAgPGZvcm0gW2Zvcm1Hcm91cF09XCJmb3Jtc1sxXVwiIGNsYXNzPVwiZm9ybS1jb250YWluZXIgaW9uLXBhZGRpbmdcIiAoa2V5dXAuZW50ZXIpPVwic2xpZGVOZXh0KCRldmVudClcIj5cbiAgICAgIDxuZy10ZW1wbGF0ZSBtYXRTdGVwTGFiZWw+e3sgJ1JFR0lTVEVSLlNURVBfUEFTU1dPUkQnIHwgdHJhbnNsYXRlIH19PC9uZy10ZW1wbGF0ZT5cblxuICAgICAgPCEtLSBQYXNzd29yZCAtLT5cbiAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnVVNFUi5QQVNTV09SRCcgfCB0cmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJwYXNzd29yZFwiXG4gICAgICAgICAgYXV0b2NvbXBsZXRlPVwic2VjdGlvbi1yZWQgbmV3LXBhc3N3b3JkXCJcbiAgICAgICAgICBbdHlwZV09XCJzaG93UHdkID8gJ3RleHQnIDogJ3Bhc3N3b3JkJ1wiXG4gICAgICAgICAgcmVxdWlyZWRcbiAgICAgICAgLz5cbiAgICAgICAgPGJ1dHRvbiBtYXRTdWZmaXggbWF0LWljb24tYnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwic2hvd1B3ZCA9ICFzaG93UHdkXCIgdGFiaW5kZXg9XCItMVwiPlxuICAgICAgICAgIDxtYXQtaWNvbj57eyBzaG93UHdkID8gJ3Zpc2liaWxpdHlfb2ZmJyA6ICd2aXNpYmlsaXR5JyB9fTwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMucGFzc3dvcmQuaGFzRXJyb3IoJ3JlcXVpcmVkJykgJiYgY29udHJvbHMucGFzc3dvcmQudG91Y2hlZFwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cImNvbnRyb2xzLnBhc3N3b3JkLmhhc0Vycm9yKCdtaW5sZW5ndGgnKSAmJiBjb250cm9scy5wYXNzd29yZC50b3VjaGVkXCI+XG4gICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX01JTl9MRU5HVEgnIHwgdHJhbnNsYXRlOiB7IHJlcXVpcmVkTGVuZ3RoOiA4IH0gfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgPCEtLSBDb25maXJtIHBhc3N3b3JkIC0tPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdSRUdJU1RFUi5DT05GSVJNX1BBU1NXT1JEJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImNvbmZpcm1QYXNzd29yZFwiXG4gICAgICAgICAgYXV0b2NvbXBsZXRlPVwic2VjdGlvbi1yZWQgbmV3LXBhc3N3b3JkXCJcbiAgICAgICAgICBbdHlwZV09XCJzaG93Q29uZmlybVB3ZCA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgIHJlcXVpcmVkXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIG1hdFN1ZmZpeCAoY2xpY2spPVwic2hvd0NvbmZpcm1Qd2QgPSAhc2hvd0NvbmZpcm1Qd2RcIiB0YWJpbmRleD1cIi0xXCI+XG4gICAgICAgICAgPG1hdC1pY29uPnt7IHNob3dDb25maXJtUHdkID8gJ3Zpc2liaWxpdHlfb2ZmJyA6ICd2aXNpYmlsaXR5JyB9fTwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuY29uZmlybVBhc3N3b3JkLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIGNvbnRyb2xzLmNvbmZpcm1QYXNzd29yZC50b3VjaGVkXCIgdHJhbnNsYXRlPlxuICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuY29uZmlybVBhc3N3b3JkLmhhc0Vycm9yKCdlcXVhbHMnKSAmJiBjb250cm9scy5jb25maXJtUGFzc3dvcmQudG91Y2hlZFwiPlxuICAgICAgICAgIDxzcGFuPnt7ICdSRUdJU1RFUi5FUlJPUi5OT1RfU0FNRV9QQVNTV09SRCcgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Zvcm0+XG4gIDwvbWF0LXN0ZXA+XG5cbiAgPCEtLSBTdGVwIDM6IHVzZXIgZGV0YWlscyAtLT5cbiAgPG1hdC1zdGVwIFtzdGVwQ29udHJvbF09XCJmb3Jtc1syXVwiICpuZ0lmPVwiZm9ybXNbMl0uY29udHJvbHM7IGxldCBjb250cm9sc1wiPlxuICAgIDxmb3JtXG4gICAgICBbZm9ybUdyb3VwXT1cImZvcm1zWzJdXCJcbiAgICAgIChuZ1N1Ym1pdCk9XCJkb1N1Ym1pdCgkZXZlbnQpXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250YWluZXIgaW9uLXBhZGRpbmdcIlxuICAgICAgKGtleXVwLmVudGVyKT1cImRvU3VibWl0KClcIlxuICAgID5cbiAgICAgIDxuZy10ZW1wbGF0ZSBtYXRTdGVwTGFiZWw+e3sgJ1JFR0lTVEVSLlNURVBfVVNFUl9ERVRBSUxTJyB8IHRyYW5zbGF0ZSB9fTwvbmctdGVtcGxhdGU+XG5cbiAgICAgIDwhLS0gZXJyb3IgLS0+XG4gICAgICA8aW9uLWl0ZW0gKm5nSWY9XCJlcnJvciAmJiAhc2VuZGluZ1wiIGxpbmVzPVwibm9uZVwiPlxuICAgICAgICA8aW9uLWljb24gY29sb3I9XCJkYW5nZXJcIiBzbG90PVwic3RhcnRcIiBuYW1lPVwiYWxlcnQtY2lyY2xlXCI+PC9pb24taWNvbj5cbiAgICAgICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIGNsYXNzPVwiZXJyb3JcIiBbaW5uZXJIVE1MXT1cImVycm9yIHwgdHJhbnNsYXRlXCI+PC9pb24tbGFiZWw+XG4gICAgICA8L2lvbi1pdGVtPlxuXG4gICAgICA8IS0tIExhc3QgbmFtZSAtLT5cbiAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnVVNFUi5MQVNUX05BTUUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dCBtYXRJbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJsYXN0TmFtZVwiIGF1dG9jb21wbGV0ZT1cInNlY3Rpb24tYmx1ZSBmYW1pbHktbmFtZVwiIHJlcXVpcmVkIC8+XG4gICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJjb250cm9scy5sYXN0TmFtZS5oYXNFcnJvcigncmVxdWlyZWQnKSAmJiBjb250cm9scy5sYXN0TmFtZS5kaXJ0eVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cImNvbnRyb2xzLmxhc3ROYW1lLmhhc0Vycm9yKCdtaW5sZW5ndGgnKSAmJiBjb250cm9scy5sYXN0TmFtZS5kaXJ0eVwiPlxuICAgICAgICAgIDxzcGFuPnt7ICdFUlJPUi5GSUVMRF9NSU5fTEVOR1RIJyB8IHRyYW5zbGF0ZTogeyByZXF1aXJlZExlbmd0aDogMiB9IH19PC9zcGFuPlxuICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG5cbiAgICAgIDwhLS0gRmlyc3QgbmFtZSAtLT5cbiAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnVVNFUi5GSVJTVF9OQU1FJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXQgbWF0SW5wdXQgZm9ybUNvbnRyb2xOYW1lPVwiZmlyc3ROYW1lXCIgYXV0b2NvbXBsZXRlPVwic2VjdGlvbi1ibHVlIGdpdmVuLW5hbWVcIiByZXF1aXJlZCAvPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuZmlyc3ROYW1lLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIGNvbnRyb2xzLmZpcnN0TmFtZS5kaXJ0eVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cImNvbnRyb2xzLmZpcnN0TmFtZS5oYXNFcnJvcignbWlubGVuZ3RoJykgJiYgY29udHJvbHMuZmlyc3ROYW1lLmRpcnR5XCI+XG4gICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX01JTl9MRU5HVEgnIHwgdHJhbnNsYXRlOiB7IHJlcXVpcmVkTGVuZ3RoOiAyIH0gfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgPCEtLSBBZGRpdGlvbmFsIGZpZWxkcyAtLT5cbiAgICAgIDxhcHAtZm9ybS1maWVsZFxuICAgICAgICAqbmdGb3I9XCJsZXQgZmllbGQgb2YgYWRkaXRpb25hbEZpZWxkc1wiXG4gICAgICAgIFtkZWZpbml0aW9uXT1cImZpZWxkXCJcbiAgICAgICAgW2Zvcm1Db250cm9sTmFtZV09XCJmaWVsZC5rZXlcIlxuICAgICAgICBbcmVxdWlyZWRdPVwiZmllbGQuZXh0cmE/LnJlZ2lzdHJhdGlvbi5yZXF1aXJlZCA/PyBmaWVsZC5leHRyYT8uYWNjb3VudC5yZXF1aXJlZCA/PyBmYWxzZVwiXG4gICAgICA+PC9hcHAtZm9ybS1maWVsZD5cbiAgICA8L2Zvcm0+XG4gIDwvbWF0LXN0ZXA+XG48L21hdC1ob3Jpem9udGFsLXN0ZXBwZXI+XG4iXX0=
197
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0ZXIuZm9ybS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29yZS9yZWdpc3Rlci9yZWdpc3Rlci5mb3JtLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb3JlL3JlZ2lzdGVyL3JlZ2lzdGVyLmZvcm0uaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQVUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRixPQUFPLEVBSUwsa0JBQWtCLEVBSWxCLFVBQVUsR0FDWCxNQUFNLGdCQUFnQixDQUFDO0FBRXhCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMxRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUUxRSxPQUFPLEVBQUUsS0FBSyxFQUFjLEVBQUUsRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFHM0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTFDLE9BQU8sRUFBZSxXQUFXLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUNuRixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxpRUFBaUUsQ0FBQztBQUM5RyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBT2xELE1BQU0sT0FBTyxZQUFZO0lBdUJiO0lBQ0E7SUFDRDtJQUN3QjtJQUNyQjtJQTFCRixLQUFLLEdBQUcsS0FBSyxDQUFDO0lBRXhCLGtCQUFrQixDQUE4QjtJQUNoRCxnQkFBZ0IsQ0FBd0I7SUFDeEMsSUFBSSxDQUFtQjtJQUN2QixLQUFLLENBQXFCO0lBQzFCLGFBQWEsR0FBbUIsRUFBRSxDQUFDO0lBQ25DLEtBQUssQ0FBUztJQUNkLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFFaEIsT0FB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SSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDcEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRCxtQkFBbUIsR0FBRyxtQkFBbUIsQ0FBQztJQUUxQyxhQUFhO1FBQ1gsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRUQsT0FBTztRQUNMLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVELE1BQU07UUFDSixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ3JCLENBQUM7d0dBOUxVLFlBQVkseUhBMEJiLFdBQVc7NEZBMUJWLFlBQVksb09DN0J6Qixna05BcUpBOzs0RkR4SGEsWUFBWTtrQkFMeEIsU0FBUzsrQkFDRSxtQkFBbUI7OzBCQThCMUIsTUFBTTsyQkFBQyxXQUFXOzRFQVoyQixPQUFPO3NCQUF0RCxTQUFTO3VCQUFDLFNBQVMsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBR3RDLFFBQVE7c0JBRFAsTUFBTTtnQkFJUCxRQUFRO3NCQURQLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5qZWN0LCBPbkluaXQsIE91dHB1dCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBBYnN0cmFjdENvbnRyb2wsXG4gIEFzeW5jVmFsaWRhdG9yRm4sXG4gIFVudHlwZWRGb3JtQnVpbGRlcixcbiAgVW50eXBlZEZvcm1Db250cm9sLFxuICBVbnR5cGVkRm9ybUdyb3VwLFxuICBWYWxpZGF0aW9uRXJyb3JzLFxuICBWYWxpZGF0b3JGbixcbiAgVmFsaWRhdG9ycyxcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQWNjb3VudFNlcnZpY2UsIFJlZ2lzdGVyRGF0YSB9IGZyb20gJy4uL3NlcnZpY2VzL2FjY291bnQuc2VydmljZSc7XG5pbXBvcnQgeyBBY2NvdW50IH0gZnJvbSAnLi4vc2VydmljZXMvbW9kZWwvYWNjb3VudC5tb2RlbCc7XG5pbXBvcnQgeyByZWZlcmVudGlhbFRvU3RyaW5nIH0gZnJvbSAnLi4vc2VydmljZXMvbW9kZWwvcmVmZXJlbnRpYWwubW9kZWwnO1xuaW1wb3J0IHsgTWF0U3RlcHBlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3N0ZXBwZXInO1xuaW1wb3J0IHsgZGVsYXksIE9ic2VydmFibGUsIG9mLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEFjY291bnRWYWxpZGF0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvdmFsaWRhdG9yL2FjY291bnQudmFsaWRhdG9yJztcbmltcG9ydCB7IEZvcm1GaWVsZERlZmluaXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQvZm9ybS9maWVsZC5tb2RlbCc7XG5pbXBvcnQgeyBtZXJnZU1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IExvY2FsU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvbG9jYWwtc2V0dGluZ3Muc2VydmljZSc7XG5pbXBvcnQgeyBFbnZpcm9ubWVudCwgRU5WSVJPTk1FTlQgfSBmcm9tICcuLi8uLi8uLi9lbnZpcm9ubWVudHMvZW52aXJvbm1lbnQuY2xhc3MnO1xuaW1wb3J0IHsgTWF0QXV0b2NvbXBsZXRlQ29uZmlnSG9sZGVyIH0gZnJvbSAnLi4vLi4vc2hhcmVkL21hdGVyaWFsL2F1dG9jb21wbGV0ZS9tYXRlcmlhbC5hdXRvY29tcGxldGUuY29uZmlnJztcbmltcG9ydCB7IGlzTm90TmlsIH0gZnJvbSAnLi4vLi4vc2hhcmVkL2Z1bmN0aW9ucyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1yZWdpc3Rlci1mb3JtJyxcbiAgdGVtcGxhdGVVcmw6ICdyZWdpc3Rlci5mb3JtLmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9yZWdpc3Rlci5mb3JtLnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgUmVnaXN0ZXJGb3JtIGltcGxlbWVudHMgT25Jbml0IHtcbiAgcHJvdGVjdGVkIGRlYnVnID0gZmFsc2U7XG5cbiAgYXV0b2NvbXBsZXRlSGVscGVyOiBNYXRBdXRvY29tcGxldGVDb25maWdIb2xkZXI7XG4gIGFkZGl0aW9uYWxGaWVsZHM6IEZvcm1GaWVsZERlZmluaXRpb25bXTtcbiAgZm9ybTogVW50eXBlZEZvcm1Hcm91cDtcbiAgZm9ybXM6IFVudHlwZWRGb3JtR3JvdXBbXTtcbiAgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcbiAgZXJyb3I6IHN0cmluZztcbiAgc2VuZGluZyA9IGZhbHNlO1xuXG4gIHNob3dQd2QgPSBmYWxzZTtcbiAgc2hvd0NvbmZpcm1Qd2QgPSBmYWxzZTtcblxuICBAVmlld0NoaWxkKCdzdGVwcGVyJywgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSBzdGVwcGVyOiBNYXRTdGVwcGVyO1xuXG4gIEBPdXRwdXQoKVxuICBvbkNhbmNlbCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIEBPdXRwdXQoKVxuICBvblN1Ym1pdCA9IG5ldyBFdmVudEVtaXR0ZXI8UmVnaXN0ZXJEYXRhPigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYWNjb3VudFNlcnZpY2U6IEFjY291bnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgYWNjb3VudFZhbGlkYXRvclNlcnZpY2U6IEFjY291bnRWYWxpZGF0b3JTZXJ2aWNlLFxuICAgIHB1YmxpYyBmb3JtQnVpbGRlcjogVW50eXBlZEZvcm1CdWlsZGVyLFxuICAgIEBJbmplY3QoRU5WSVJPTk1FTlQpIHByb3RlY3RlZCBlbnZpcm9ubWVudDogRW52aXJvbm1lbnQsXG4gICAgcHJvdGVjdGVkIHNldHRpbmdzPzogTG9jYWxTZXR0aW5nc1NlcnZpY2VcbiAgKSB7XG4gICAgdGhpcy5mb3JtcyA9IFtdO1xuICAgIC8vIEVtYWlsIGZvcm1cbiAgICB0aGlzLmZvcm1zLnB1c2goXG4gICAgICBmb3JtQnVpbGRlci5ncm91cCh7XG4gICAgICAgIGVtYWlsOiBuZXcgVW50eXBlZEZvcm1Db250cm9sKG51bGwsIFZhbGlkYXRvcnMuY29tcG9zZShbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5lbWFpbF0pLCB0aGlzLmVtYWlsQXZhaWxhYmlsaXR5KHRoaXMuYWNjb3VudFNlcnZpY2UpKSxcbiAgICAgICAgY29uZmlybUVtYWlsOiBuZXcgVW50eXBlZEZvcm1Db250cm9sKG51bGwsIFZhbGlkYXRvcnMuY29tcG9zZShbVmFsaWRhdG9ycy5yZXF1aXJlZCwgdGhpcy5lcXVhbHNWYWxpZGF0b3IoJ2VtYWlsJyldKSksXG4gICAgICB9KVxuICAgICk7XG5cbiAgICAvLyBQYXNzd29yZCBmb3JtXG4gICAgdGhpcy5mb3Jtcy5wdXNoKFxuICAgICAgZm9ybUJ1aWxkZXIuZ3JvdXAoe1xuICAgICAgICBwYXNzd29yZDogbmV3IFVudHlwZWRGb3JtQ29udHJvbChudWxsLCBWYWxpZGF0b3JzLmNvbXBvc2UoW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMubWluTGVuZ3RoKDgpXSkpLFxuICAgICAgICBjb25maXJtUGFzc3dvcmQ6IG5ldyBVbnR5cGVkRm9ybUNvbnRyb2wobnVsbCwgVmFsaWRhdG9ycy5jb21wb3NlKFtWYWxpZGF0b3JzLnJlcXVpcmVkLCB0aGlzLmVxdWFsc1ZhbGlkYXRvcigncGFzc3dvcmQnKV0pKSxcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIC8vIERldGFpbCBmb3JtXG4gICAgY29uc3QgZm9ybURldGFpbERlZiA9IHtcbiAgICAgIGxhc3ROYW1lOiBuZXcgVW50eXBlZEZvcm1Db250cm9sKG51bGwsIFZhbGlkYXRvcnMuY29tcG9zZShbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5taW5MZW5ndGgoMildKSksXG4gICAgICBmaXJzdE5hbWU6IG5ldyBVbnR5cGVkRm9ybUNvbnRyb2wobnVsbCwgVmFsaWRhdG9ycy5jb21wb3NlKFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLm1pbkxlbmd0aCgyKV0pKSxcbiAgICB9O1xuXG4gICAgLy8gUHJlcGFyZSBhdXRvY29tcGxldGUgc2V0dGluZ3NcbiAgICB0aGlzLmF1dG9jb21wbGV0ZUhlbHBlciA9IG5ldyBNYXRBdXRvY29tcGxldGVDb25maWdIb2xkZXIoXG4gICAgICBzZXR0aW5ncyAmJiB7XG4gICAgICAgIGdldFVzZXJBdHRyaWJ1dGVzOiAoYSwgYikgPT4gc2V0dGluZ3MuZ2V0RmllbGREaXNwbGF5QXR0cmlidXRlcyhhLCBiKSxcbiAgICAgIH1cbiAgICApO1xuXG4gICAgLy8gQWRkIGFkZGl0aW9uYWwgZmllbGRzIHRvIGRldGFpbHMgZm9ybVxuICAgIHRoaXMuYWRkaXRpb25hbEZpZWxkcyA9IHRoaXMuYWNjb3VudFNlcnZpY2UuYWRkaXRpb25hbEZpZWxkc1xuICAgICAgLy8gS2VlcCBvbmx5IHJlcXVpcmVkIGZpZWxkc1xuICAgICAgLmZpbHRlcigoZmllbGQpID0+IGZpZWxkLmV4dHJhPy5yZWdpc3RyYXRpb24gJiYgZmllbGQuZXh0cmEucmVnaXN0cmF0aW9uLmRpc2FibGVkICE9PSBmYWxzZSlcbiAgICAgIC5tYXAoKGZpZWxkKSA9PiB7XG4gICAgICAgIC8vaWYgKHRoaXMuZGVidWcpIGNvbnNvbGUuZGVidWcoXCJbcmVnaXN0ZXItZm9ybV0gQWRkIGFkZGl0aW9uYWwgZmllbGQge1wiICsgZmllbGQubmFtZSArIFwifSB0byBmb3JtXCIsIGZpZWxkKTtcbiAgICAgICAgZm9ybURldGFpbERlZltmaWVsZC5rZXldID0gbmV3IFVudHlwZWRGb3JtQ29udHJvbChudWxsLCB0aGlzLmFjY291bnRWYWxpZGF0b3JTZXJ2aWNlLmdldFZhbGlkYXRvcnMoZmllbGQsIGZpZWxkLmV4dHJhLnJlZ2lzdHJhdGlvbi5yZXF1aXJlZCkpO1xuXG4gICAgICAgIGlmIChpc05vdE5pbChmaWVsZC5hdXRvY29tcGxldGUpKSB7XG4gICAgICAgICAgZmllbGQuYXV0b2NvbXBsZXRlID0gdGhpcy5hdXRvY29tcGxldGVIZWxwZXIuYWRkKGZpZWxkLmtleSwgZmllbGQuYXV0b2NvbXBsZXRlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmllbGQ7XG4gICAgICB9KTtcblxuICAgIHRoaXMuZm9ybXMucHVzaChmb3JtQnVpbGRlci5ncm91cChmb3JtRGV0YWlsRGVmKSk7XG5cbiAgICB0aGlzLmZvcm0gPSBmb3JtQnVpbGRlci5ncm91cCh7XG4gICAgICBlbWFpbFN0ZXA6IHRoaXMuZm9ybXNbMF0sXG4gICAgICBwYXNzd29yZFN0ZXA6IHRoaXMuZm9ybXNbMV0sXG4gICAgICBkZXRhaWxzU3RlcDogdGhpcy5mb3Jtc1syXSxcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIC8vIEZvciBERVYgb25seSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBpZiAoIXRoaXMuZW52aXJvbm1lbnQucHJvZHVjdGlvbikge1xuICAgICAgdGhpcy5mb3JtLnNldFZhbHVlKHtcbiAgICAgICAgZW1haWxTdGVwOiB7XG4gICAgICAgICAgZW1haWw6ICdjb250YWN0QGUtaXMucHJvJyxcbiAgICAgICAgICBjb25maXJtRW1haWw6ICdjb250YWN0QGUtaXMucHJvJyxcbiAgICAgICAgfSxcbiAgICAgICAgcGFzc3dvcmRTdGVwOiB7XG4gICAgICAgICAgcGFzc3dvcmQ6ICdjb250YWN0ZXJhJyxcbiAgICAgICAgICBjb25maXJtUGFzc3dvcmQ6ICdjb250YWN0ZXJhJyxcbiAgICAgICAgfSxcbiAgICAgICAgZGV0YWlsc1N0ZXA6IHtcbiAgICAgICAgICBsYXN0TmFtZTogJ0xhdmVuaWVyIDInLFxuICAgICAgICAgIGZpcnN0TmFtZTogJ0Jlbm9pdCcsXG4gICAgICAgICAgZGVwYXJ0bWVudDogbnVsbCxcbiAgICAgICAgICBwcm9ncmFtczogbnVsbFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IHZhbHVlKCk6IFJlZ2lzdGVyRGF0YSB7XG4gICAgY29uc3QgcmVzdWx0OiBSZWdpc3RlckRhdGEgPSB7XG4gICAgICB1c2VybmFtZTogdGhpcy5mb3JtLnZhbHVlLmVtYWlsU3RlcC5lbWFpbCxcbiAgICAgIHBhc3N3b3JkOiB0aGlzLmZvcm0udmFsdWUucGFzc3dvcmRTdGVwLnBhc3N3b3JkLFxuICAgICAgYWNjb3VudDogbmV3IEFjY291bnQoKSxcbiAgICB9O1xuICAgIHJlc3VsdC5hY2NvdW50LmZyb21PYmplY3QodGhpcy5mb3JtLnZhbHVlLmRldGFpbHNTdGVwKTtcbiAgICByZXN1bHQuYWNjb3VudC5lbWFpbCA9IHJlc3VsdC51c2VybmFtZTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBnZXQgdmFsaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybS52YWxpZDtcbiAgfVxuXG4gIGlzRW5kKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN0ZXBwZXIuc2VsZWN0ZWRJbmRleCA9PT0gMjtcbiAgfVxuXG4gIGlzQmVnaW5uaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN0ZXBwZXIuc2VsZWN0ZWRJbmRleCA9PT0gMDtcbiAgfVxuXG4gIHNsaWRlUHJldigpIHtcbiAgICByZXR1cm4gdGhpcy5zdGVwcGVyLnByZXZpb3VzKCk7XG4gIH1cblxuICBzbGlkZU5leHQoZXZlbnQ/OiBFdmVudCkge1xuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zdGVwcGVyLm5leHQoKTtcbiAgfVxuXG4gIGVxdWFsc1ZhbGlkYXRvcihvdGhlckNvbnRyb2xOYW1lOiBzdHJpbmcpOiBWYWxpZGF0b3JGbiB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChjOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XG4gICAgICBpZiAoYy5wYXJlbnQgJiYgYy52YWx1ZSAhPT0gYy5wYXJlbnQudmFsdWVbb3RoZXJDb250cm9sTmFtZV0pIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBlcXVhbHM6IHRydWUsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICB9XG5cbiAgZW1haWxBdmFpbGFiaWxpdHkoYWNjb3VudFNlcnZpY2U6IEFjY291bnRTZXJ2aWNlKTogQXN5bmNWYWxpZGF0b3JGbiB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBPYnNlcnZhYmxlPFZhbGlkYXRpb25FcnJvcnMgfCBudWxsPiB7XG4gICAgICByZXR1cm4gb2YobnVsbCkucGlwZShcbiAgICAgICAgZGVsYXkoNTAwKSxcbiAgICAgICAgbWVyZ2VNYXAoKCkgPT5cbiAgICAgICAgICBhY2NvdW50U2VydmljZVxuICAgICAgICAgICAgLmNoZWNrRW1haWxBdmFpbGFibGUoY29udHJvbC52YWx1ZSlcbiAgICAgICAgICAgIC50aGVuKChyZXMpID0+IG51bGwpXG4gICAgICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICAgICAgICAgIHJldHVybiB7IGF2YWlsYWJpbGl0eTogdHJ1ZSB9O1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9O1xuICB9XG5cbiAgY2FuY2VsKCkge1xuICAgIHRoaXMub25DYW5jZWwuZW1pdCgpO1xuICB9XG5cbiAgZG9TdWJtaXQoZXZlbnQ/OiBhbnkpIHtcbiAgICBpZiAodGhpcy5mb3JtLmludmFsaWQpIHJldHVybjtcbiAgICB0aGlzLnNlbmRpbmcgPSB0cnVlO1xuICAgIHRoaXMub25TdWJtaXQuZW1pdCh0aGlzLnZhbHVlKTtcbiAgfVxuXG4gIHJlZmVyZW50aWFsVG9TdHJpbmcgPSByZWZlcmVudGlhbFRvU3RyaW5nO1xuXG4gIG1hcmtBc1RvdWNoZWQoKSB7XG4gICAgdGhpcy5mb3JtLm1hcmtBc1RvdWNoZWQoKTtcbiAgfVxuXG4gIGRpc2FibGUoKSB7XG4gICAgdGhpcy5mb3JtLmRpc2FibGUoKTtcbiAgfVxuXG4gIGVuYWJsZSgpIHtcbiAgICB0aGlzLmZvcm0uZW5hYmxlKCk7XG4gIH1cbn1cbiIsIjxtYXQtaG9yaXpvbnRhbC1zdGVwcGVyIGxpbmVhciAjc3RlcHBlcj1cIm1hdEhvcml6b250YWxTdGVwcGVyXCI+XG4gIDwhLS0gU3RlcCAxOiBVc2VybmFtZSAtLT5cbiAgPG1hdC1zdGVwIFtzdGVwQ29udHJvbF09XCJmb3Jtc1swXVwiICpuZ0lmPVwiZm9ybXNbMF0uY29udHJvbHM7IGxldCBjb250cm9sc1wiPlxuICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiZm9ybXNbMF1cIiBjbGFzcz1cImZvcm0tY29udGFpbmVyIGlvbi1wYWRkaW5nXCIgKGtleXVwLmVudGVyKT1cInNsaWRlTmV4dCgkZXZlbnQpXCI+XG4gICAgICA8bmctdGVtcGxhdGUgbWF0U3RlcExhYmVsPnt7ICdSRUdJU1RFUi5TVEVQX0VNQUlMJyB8IHRyYW5zbGF0ZSB9fTwvbmctdGVtcGxhdGU+XG5cbiAgICAgIDwhLS0gRW1haWwgLS0+XG4gICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgIDxtYXQtbGFiZWw+e3sgJ1VTRVIuRU1BSUwnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgW2FwcEF1dG9mb2N1c109XCJ0cnVlXCJcbiAgICAgICAgICBbYXV0b2ZvY3VzRGVsYXldPVwiNTAwXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICAgICAgYXV0b2NvbXBsZXRlPVwib2ZmXCJcbiAgICAgICAgICByZXF1aXJlZFxuICAgICAgICAvPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuZW1haWwuaGFzRXJyb3IoJ3JlcXVpcmVkJykgJiYgY29udHJvbHMuZW1haWwudG91Y2hlZFwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgPG1hdC1lcnJvclxuICAgICAgICAgICpuZ0lmPVwiY29udHJvbHMuZW1haWwuaGFzRXJyb3IoJ2VtYWlsJykgJiYgIWNvbnRyb2xzLmVtYWlsLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIGNvbnRyb2xzLmVtYWlsLnRvdWNoZWRcIlxuICAgICAgICA+XG4gICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX05PVF9WQUxJRF9FTUFJTCcgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuZW1haWwuaGFzRXJyb3IoJ2F2YWlsYWJpbGl0eScpICYmIGNvbnRyb2xzLmVtYWlsLnRvdWNoZWRcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgUkVHSVNURVIuRVJST1IuRU1BSUxfQUxSRUFEWV9SRUdJU1RFUkVEXG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgPCEtLSBDb25maXJtIEVtYWlsIC0tPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdSRUdJU1RFUi5DT05GSVJNX0VNQUlMJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXQgbWF0SW5wdXQgYXV0b2NvbXBsZXRlPVwib2ZmXCIgbWF0Rm9ybUZpZWxkQ29udHJvbCBmb3JtQ29udHJvbE5hbWU9XCJjb25maXJtRW1haWxcIi8+XG4gICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJjb250cm9scy5jb25maXJtRW1haWwuaGFzRXJyb3IoJ3JlcXVpcmVkJykgJiYgY29udHJvbHMuY29uZmlybUVtYWlsLnRvdWNoZWRcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJjb250cm9scy5jb25maXJtRW1haWwuaGFzRXJyb3IoJ2VxdWFscycpICYmIGNvbnRyb2xzLmNvbmZpcm1FbWFpbC50b3VjaGVkXCI+XG4gICAgICAgICAgPHNwYW4+e3sgJ1JFR0lTVEVSLkVSUk9SLk5PVF9TQU1FX0VNQUlMJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZm9ybT5cbiAgPC9tYXQtc3RlcD5cblxuICA8IS0tIFN0ZXAgMjogUGFzc3dvcmQgLS0+XG4gIDxtYXQtc3RlcCBbc3RlcENvbnRyb2xdPVwiZm9ybXNbMV1cIiAqbmdJZj1cImZvcm1zWzFdLmNvbnRyb2xzOyBsZXQgY29udHJvbHNcIj5cbiAgICA8Zm9ybSBbZm9ybUdyb3VwXT1cImZvcm1zWzFdXCIgY2xhc3M9XCJmb3JtLWNvbnRhaW5lciBpb24tcGFkZGluZ1wiIChrZXl1cC5lbnRlcik9XCJzbGlkZU5leHQoJGV2ZW50KVwiPlxuICAgICAgPG5nLXRlbXBsYXRlIG1hdFN0ZXBMYWJlbD57eyAnUkVHSVNURVIuU1RFUF9QQVNTV09SRCcgfCB0cmFuc2xhdGUgfX08L25nLXRlbXBsYXRlPlxuXG4gICAgICA8IS0tIFBhc3N3b3JkIC0tPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdVU0VSLlBBU1NXT1JEJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICBhdXRvY29tcGxldGU9XCJzZWN0aW9uLXJlZCBuZXctcGFzc3dvcmRcIlxuICAgICAgICAgIFt0eXBlXT1cInNob3dQd2QgPyAndGV4dCcgOiAncGFzc3dvcmQnXCJcbiAgICAgICAgICByZXF1aXJlZFxuICAgICAgICAvPlxuICAgICAgICA8YnV0dG9uIG1hdFN1ZmZpeCBtYXQtaWNvbi1idXR0b24gdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJzaG93UHdkID0gIXNob3dQd2RcIiB0YWJpbmRleD1cIi0xXCI+XG4gICAgICAgICAgPG1hdC1pY29uPnt7IHNob3dQd2QgPyAndmlzaWJpbGl0eV9vZmYnIDogJ3Zpc2liaWxpdHknIH19PC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJjb250cm9scy5wYXNzd29yZC5oYXNFcnJvcigncmVxdWlyZWQnKSAmJiBjb250cm9scy5wYXNzd29yZC50b3VjaGVkXCIgdHJhbnNsYXRlPlxuICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMucGFzc3dvcmQuaGFzRXJyb3IoJ21pbmxlbmd0aCcpICYmIGNvbnRyb2xzLnBhc3N3b3JkLnRvdWNoZWRcIj5cbiAgICAgICAgICA8c3Bhbj57eyAnRVJST1IuRklFTERfTUlOX0xFTkdUSCcgfCB0cmFuc2xhdGU6IHtyZXF1aXJlZExlbmd0aDogOH0gfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgPCEtLSBDb25maXJtIHBhc3N3b3JkIC0tPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdSRUdJU1RFUi5DT05GSVJNX1BBU1NXT1JEJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImNvbmZpcm1QYXNzd29yZFwiXG4gICAgICAgICAgYXV0b2NvbXBsZXRlPVwic2VjdGlvbi1yZWQgbmV3LXBhc3N3b3JkXCJcbiAgICAgICAgICBbdHlwZV09XCJzaG93Q29uZmlybVB3ZCA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgIHJlcXVpcmVkXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIG1hdFN1ZmZpeCAoY2xpY2spPVwic2hvd0NvbmZpcm1Qd2QgPSAhc2hvd0NvbmZpcm1Qd2RcIiB0YWJpbmRleD1cIi0xXCI+XG4gICAgICAgICAgPG1hdC1pY29uPnt7IHNob3dDb25maXJtUHdkID8gJ3Zpc2liaWxpdHlfb2ZmJyA6ICd2aXNpYmlsaXR5JyB9fTwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuY29uZmlybVBhc3N3b3JkLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIGNvbnRyb2xzLmNvbmZpcm1QYXNzd29yZC50b3VjaGVkXCIgdHJhbnNsYXRlPlxuICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuY29uZmlybVBhc3N3b3JkLmhhc0Vycm9yKCdlcXVhbHMnKSAmJiBjb250cm9scy5jb25maXJtUGFzc3dvcmQudG91Y2hlZFwiPlxuICAgICAgICAgIDxzcGFuPnt7ICdSRUdJU1RFUi5FUlJPUi5OT1RfU0FNRV9QQVNTV09SRCcgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Zvcm0+XG4gIDwvbWF0LXN0ZXA+XG5cbiAgPCEtLSBTdGVwIDM6IHVzZXIgZGV0YWlscyAtLT5cbiAgPG1hdC1zdGVwIFtzdGVwQ29udHJvbF09XCJmb3Jtc1syXVwiICpuZ0lmPVwiZm9ybXNbMl0uY29udHJvbHM7IGxldCBjb250cm9sc1wiPlxuICAgIDxmb3JtXG4gICAgICBbZm9ybUdyb3VwXT1cImZvcm1zWzJdXCJcbiAgICAgIChuZ1N1Ym1pdCk9XCJkb1N1Ym1pdCgkZXZlbnQpXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250YWluZXIgaW9uLXBhZGRpbmdcIlxuICAgICAgKGtleXVwLmVudGVyKT1cImRvU3VibWl0KClcIlxuICAgID5cbiAgICAgIDxuZy10ZW1wbGF0ZSBtYXRTdGVwTGFiZWw+e3sgJ1JFR0lTVEVSLlNURVBfVVNFUl9ERVRBSUxTJyB8IHRyYW5zbGF0ZSB9fTwvbmctdGVtcGxhdGU+XG5cbiAgICAgIDwhLS0gZXJyb3IgLS0+XG4gICAgICA8aW9uLWl0ZW0gKm5nSWY9XCJlcnJvciAmJiAhc2VuZGluZ1wiIGxpbmVzPVwibm9uZVwiPlxuICAgICAgICA8aW9uLWljb24gY29sb3I9XCJkYW5nZXJcIiBzbG90PVwic3RhcnRcIiBuYW1lPVwiYWxlcnQtY2lyY2xlXCI+PC9pb24taWNvbj5cbiAgICAgICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIGNsYXNzPVwiZXJyb3JcIiBbaW5uZXJIVE1MXT1cImVycm9yIHwgdHJhbnNsYXRlXCI+PC9pb24tbGFiZWw+XG4gICAgICA8L2lvbi1pdGVtPlxuXG4gICAgICA8IS0tIExhc3QgbmFtZSAtLT5cbiAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnVVNFUi5MQVNUX05BTUUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dCBtYXRJbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJsYXN0TmFtZVwiIGF1dG9jb21wbGV0ZT1cInNlY3Rpb24tYmx1ZSBmYW1pbHktbmFtZVwiIHJlcXVpcmVkLz5cbiAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cImNvbnRyb2xzLmxhc3ROYW1lLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIGNvbnRyb2xzLmxhc3ROYW1lLmRpcnR5XCIgdHJhbnNsYXRlPlxuICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMubGFzdE5hbWUuaGFzRXJyb3IoJ21pbmxlbmd0aCcpICYmIGNvbnRyb2xzLmxhc3ROYW1lLmRpcnR5XCI+XG4gICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX01JTl9MRU5HVEgnIHwgdHJhbnNsYXRlOiB7cmVxdWlyZWRMZW5ndGg6IDJ9IH19PC9zcGFuPlxuICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG5cbiAgICAgIDwhLS0gRmlyc3QgbmFtZSAtLT5cbiAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnVVNFUi5GSVJTVF9OQU1FJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXQgbWF0SW5wdXQgZm9ybUNvbnRyb2xOYW1lPVwiZmlyc3ROYW1lXCIgYXV0b2NvbXBsZXRlPVwic2VjdGlvbi1ibHVlIGdpdmVuLW5hbWVcIiByZXF1aXJlZC8+XG4gICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJjb250cm9scy5maXJzdE5hbWUuaGFzRXJyb3IoJ3JlcXVpcmVkJykgJiYgY29udHJvbHMuZmlyc3ROYW1lLmRpcnR5XCIgdHJhbnNsYXRlPlxuICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiY29udHJvbHMuZmlyc3ROYW1lLmhhc0Vycm9yKCdtaW5sZW5ndGgnKSAmJiBjb250cm9scy5maXJzdE5hbWUuZGlydHlcIj5cbiAgICAgICAgICA8c3Bhbj57eyAnRVJST1IuRklFTERfTUlOX0xFTkdUSCcgfCB0cmFuc2xhdGU6IHtyZXF1aXJlZExlbmd0aDogMn0gfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgPCEtLSBBZGRpdGlvbmFsIGZpZWxkcyAtLT5cbiAgICAgIEBmb3IgKGZpZWxkIG9mIGFkZGl0aW9uYWxGaWVsZHM7IHRyYWNrIGZpZWxkLmtleSkge1xuICAgICAgICBAaWYgKGZpZWxkLmV4dHJhLnJlZ2lzdHJhdGlvbj8uZGVzY3JpcHRpb247IGFzIGRlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgPGlvbi10ZXh0PlxuICAgICAgICAgICAgPHAgW2lubmVySFRNTF09XCJkZXNjcmlwdGlvbiB8IHRyYW5zbGF0ZVwiPjwvcD5cbiAgICAgICAgICA8L2lvbi10ZXh0PlxuICAgICAgICB9XG4gICAgICAgIDxhcHAtZm9ybS1maWVsZFxuICAgICAgICAgIFtkZWZpbml0aW9uXT1cImZpZWxkXCJcbiAgICAgICAgICBbZm9ybUNvbnRyb2xOYW1lXT1cImZpZWxkLmtleVwiXG4gICAgICAgICAgW3JlcXVpcmVkXT1cImZpZWxkLmV4dHJhPy5yZWdpc3RyYXRpb24ucmVxdWlyZWQgPz8gZmllbGQuZXh0cmE/LmFjY291bnQucmVxdWlyZWQgPz8gZmFsc2VcIlxuICAgICAgICA+PC9hcHAtZm9ybS1maWVsZD5cbiAgICAgIH1cbiAgICA8L2Zvcm0+XG4gIDwvbWF0LXN0ZXA+XG48L21hdC1ob3Jpem9udGFsLXN0ZXBwZXI+XG4iXX0=