ngx-auth-firebaseui-updated
Version:
From ngx-auth-firbaseui but updated to fix dependency issues with Angular 16. Open Source Library for Angular Web Apps to integrate a material user interface for firebase authentication
218 lines (217 loc) • 53.2 kB
JavaScript
import { Component, EventEmitter, forwardRef, Inject, Input, Output, } from "@angular/core";
import { UntypedFormControl, UntypedFormGroup, Validators } from "@angular/forms";
import { NgxAuthFirebaseUIConfigToken } from "../../tokens";
import { EMAIL_REGEX, PHONE_NUMBER_REGEX } from '../../interfaces';
import { map, take } from "rxjs/operators";
import * as i0 from "@angular/core";
import * as i1 from "@angular/fire/compat/auth";
import * as i2 from "../../services/auth-process.service";
import * as i3 from "../../services/firestore-sync.service";
import * as i4 from "@angular/common";
import * as i5 from "@angular/forms";
import * as i6 from "@angular/material/card";
import * as i7 from "@angular/material/input";
import * as i8 from "@angular/material/form-field";
import * as i9 from "@angular/material/button";
import * as i10 from "@angular/material/icon";
import * as i11 from "@angular/material/tooltip";
export class UserComponent {
constructor(auth, authProcess, fireStoreService, config) {
this.auth = auth;
this.authProcess = authProcess;
this.fireStoreService = fireStoreService;
this.config = config;
this.canLogout = true;
this.canEditAccount = true;
this.canDeleteAccount = true;
// i18n commons
this.notLoggedInText = "You are not logged in!";
this.emailVerifiedText = "email is verified";
this.emailNotVerifiedText = "email is not verified";
this.cancelButtonText = "cancel";
this.saveChangesButtonText = "Save changes";
this.editButtonText = "edit";
this.signoutButtonText = "Sign out";
this.deleteAccountButtonText = "Delete account";
//i18n name
this.nameText = "Name";
this.nameErrorRequiredText = "Name is required";
// i18n email
this.emailText = "Email";
this.emailErrorRequiredText = "Email is required";
this.emailErrorPatternText = "Please enter a valid email address";
// i18n phone
this.phoneText = "Phone number";
this.phoneHintText = `
The phone number is international. Therefore, it should start with a + sign or 00,
followed by the country code, - and national number e.g: +49-12345678 or 0041-1234567890
NOTE : the phone number must be a valid phone credential !!`;
this.phoneErrorPatternText = "Please enter a valid phone number";
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
this.onSignOut = new EventEmitter();
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
this.onAccountEdited = new EventEmitter();
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
this.onAccountDeleted = new EventEmitter();
}
changeEditMode() {
if (this.editMode) {
this.reset();
this.editMode = false;
}
else {
this.initUpdateFormGroup().subscribe((updateFormGroup) => {
this.updateFormGroup = updateFormGroup;
this.editMode = true;
});
}
}
reset() {
this.updateFormGroup.reset();
this.updateFormGroup.disable();
this.updateFormGroup = null;
}
async save() {
if (this.updateFormGroup.dirty) {
this.editMode = false;
const user = this.authProcess.user;
// ngx-auth-firebaseui-user.updateProfile()
// ngx-auth-firebaseui-user.updateEmail()
// console.log('form = ', this.updateFormGroup);
const snackBarMsg = [];
try {
if (this.updateNameFormControl.dirty) {
await user.updateProfile({
displayName: this.updateNameFormControl.value,
});
snackBarMsg.push(`your name has been updated to ${user.displayName}`);
}
if (this.updateEmailFormControl.dirty) {
await user.updateEmail(this.updateEmailFormControl.value);
snackBarMsg.push(`your email has been updated to ${user.email}`);
}
if (this.updatePhoneNumberFormControl.dirty) {
await user.updatePhoneNumber(this.updatePhoneNumberFormControl.value);
console.log("phone number = ", this.updatePhoneNumberFormControl.value);
snackBarMsg.push(`your phone number has been updated to ${user.phoneNumber}`);
}
if (this.config.enableFirestoreSync) {
await this.fireStoreService.updateUserData(this.authProcess.parseUserInfo(user));
}
}
catch (error) {
this.authProcess.showToast(error && error.message ? error.message : error);
console.error(error);
}
if (snackBarMsg.length > 0) {
this.authProcess.showToast(snackBarMsg.join("\\n"));
}
this.onAccountEdited.emit(); // emit event if the form was dirty
this.updateFormGroup.reset();
}
}
signOut() {
this.auth
.signOut()
.then(() => this.onSignOut.emit())
.catch((e) => console.error("An error happened while signing out!", e));
}
/**
* Delete the account of the current firebase ngx-auth-firebaseui-user
*
* On Success, emit the <onAccountDeleted> event and toast a msg!#
* Otherwise, log the and toast and error msg!
*
*/
async deleteAccount() {
try {
const user = this.authProcess.user;
// await this.authProcess.deleteAccount();
await this.authProcess.user.delete();
// if (this.config.enableFirestoreSync) {
await this.fireStoreService.deleteUserData(user.uid);
// }
this.onAccountDeleted.emit();
this.editMode = false;
console.log("Your account has been successfully deleted!");
this.authProcess.showToast("Your account has been successfully deleted!");
}
catch (error) {
console.log("Error while delete user account", error);
this.authProcess.showToast(`Error occurred while deleting your account: ${error.message}`);
}
}
initUpdateFormGroup() {
return this.authProcess.user$.pipe(take(1), map((currentUser) => {
const updateFormGroup = new UntypedFormGroup({
name: this.updateNameFormControl = new UntypedFormControl({ value: currentUser.displayName, disabled: this.editMode }, [
Validators.required,
Validators.minLength(this.config.nameMinLength),
Validators.maxLength(this.config.nameMaxLength),
]),
email: this.updateEmailFormControl = new UntypedFormControl({ value: currentUser.email, disabled: this.editMode }, [Validators.required, Validators.pattern(EMAIL_REGEX)]),
phoneNumber: this.updatePhoneNumberFormControl = new UntypedFormControl({ value: currentUser.phoneNumber, disabled: this.editMode }, [Validators.pattern(PHONE_NUMBER_REGEX)]),
});
updateFormGroup.enable();
return updateFormGroup;
}));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UserComponent, deps: [{ token: i1.AngularFireAuth }, { token: i2.AuthProcessService }, { token: i3.FirestoreSyncService }, { token: forwardRef(() => NgxAuthFirebaseUIConfigToken) }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: UserComponent, selector: "ngx-auth-firebaseui-user", inputs: { editMode: "editMode", canLogout: "canLogout", canEditAccount: "canEditAccount", canDeleteAccount: "canDeleteAccount", appearance: "appearance", notLoggedInText: "notLoggedInText", emailVerifiedText: "emailVerifiedText", emailNotVerifiedText: "emailNotVerifiedText", cancelButtonText: "cancelButtonText", saveChangesButtonText: "saveChangesButtonText", editButtonText: "editButtonText", signoutButtonText: "signoutButtonText", deleteAccountButtonText: "deleteAccountButtonText", nameText: "nameText", nameErrorRequiredText: "nameErrorRequiredText", emailText: "emailText", emailErrorRequiredText: "emailErrorRequiredText", emailErrorPatternText: "emailErrorPatternText", phoneText: "phoneText", phoneHintText: "phoneHintText", phoneErrorPatternText: "phoneErrorPatternText" }, outputs: { onSignOut: "onSignOut", onAccountEdited: "onAccountEdited", onAccountDeleted: "onAccountDeleted" }, ngImport: i0, template: "<div *ngIf=\"auth.authState| async; then authenticated else none\">\n\n</div>\n\n<ng-template #authenticated>\n <mat-card *ngIf=\"auth.user | async as user\">\n <!--<form [formGroup]=\"updateFormGroup\" >-->\n <!--card header-->\n <mat-card-header style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n\n <img *ngIf=\"authProcess?.getUserPhotoUrl() | async as photoUrl\" [src]=\"photoUrl\" mat-card-avatar>\n\n <div *ngIf=\"user.emailVerified; then emailVerified else emailNotVerified\"></div>\n <ng-template #emailVerified>\n <mat-icon color=\"primary\"\n [matTooltip]=\"emailVerifiedText\"\n matTooltipPosition=\"after\">\n verified_user\n </mat-icon>\n </ng-template>\n <ng-template #emailNotVerified>\n <mat-icon color=\"warn\"\n [matTooltip]=\"emailNotVerifiedText\"\n matTooltipPosition=\"after\">\n warning\n </mat-icon>\n </ng-template>\n\n </mat-card-header>\n\n <!--card content-->\n <mat-card-content *ngIf=\"editMode; then edit else readonly\">\n </mat-card-content>\n\n <ng-template #edit>\n <form (submit)=\"save()\" [formGroup]=\"updateFormGroup\">\n\n <mat-card-content style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n <div fxLayoutAlign=\"center\">\n <button (click)=\"changeEditMode()\" class=\"edit-button\" color=\"warn\"\n mat-raised-button>\n {{cancelButtonText}}\n </button>\n </div>\n\n <!--name-->\n <mat-form-field [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{nameText}}</mat-label>\n <input [formControl]=\"updateNameFormControl\"\n matInput\n [placeholder]=\"nameText\">\n <mat-icon matSuffix>person</mat-icon>\n <mat-hint align=\"end\" aria-live=\"polite\"> {{ updateNameFormControl.value?.length }}\n / {{ config.nameMaxLength }} </mat-hint>\n <mat-error *ngIf=\"updateNameFormControl.hasError('required')\">\n {{nameErrorRequiredText}}\n </mat-error>\n </mat-form-field>\n\n <!--email-->\n <mat-form-field [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{emailText}}</mat-label>\n <input [formControl]=\"updateEmailFormControl\"\n matInput\n [placeholder]=\"emailText\">\n <mat-icon matSuffix>email</mat-icon>\n <mat-error *ngIf=\"updateEmailFormControl.hasError('required')\">\n {{emailErrorRequiredText}} {{updateEmailFormControl.value}}\n </mat-error>\n <mat-error *ngIf=\"updateEmailFormControl.hasError('pattern')\">\n {{emailErrorPatternText}} {{updateEmailFormControl.value}}\n </mat-error>\n </mat-form-field>\n\n <!--phone number-->\n <mat-form-field *ngIf=\"false\" [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{phoneText}}</mat-label>\n <input [formControl]=\"updatePhoneNumberFormControl\"\n matInput\n [placeholder]=\"phoneText\"\n type=\"tel\">\n <mat-icon matSuffix>phone</mat-icon>\n <mat-hint align=\"end\" aria-live=\"polite\">\n {{phoneHintText}}\n </mat-hint>\n <mat-error *ngIf=\"updatePhoneNumberFormControl.hasError('pattern')\">\n {{phoneErrorPatternText}}\n </mat-error>\n </mat-form-field>\n\n </mat-card-content>\n\n <mat-card-actions style=\"flex-direction: column\">\n <button color=\"primary\"\n mat-button\n type=\"submit\">\n {{saveChangesButtonText}}\n </button>\n </mat-card-actions>\n </form>\n </ng-template>\n\n <ng-template #readonly>\n <div fxLayoutAlign=\"center\">\n <button *ngIf=\"canEditAccount\" (click)=\"changeEditMode()\" class=\"edit-button\" color=\"primary\"\n mat-raised-button>\n {{editButtonText}}\n </button>\n </div>\n\n <!--name-->\n <mat-form-field [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{nameText}}</mat-label>\n <input [disabled]=\"!editMode\"\n [value]=\"user.displayName\"\n matInput\n [placeholder]=\"nameText\">\n <mat-icon color=\"primary\" matSuffix>person</mat-icon>\n </mat-form-field>\n\n <!--email-->\n <mat-form-field [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{emailText}}</mat-label>\n <input [disabled]=\"!editMode\"\n [value]=\"user.email\" matInput\n [placeholder]=\"emailText\">\n <mat-icon color=\"primary\" matSuffix>email</mat-icon>\n </mat-form-field>\n\n <!--phone number-->\n <mat-form-field *ngIf=\"false\" [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{phoneText}}</mat-label>\n <input [disabled]=\"!editMode\"\n [value]=\"user.phoneNumber\"\n matInput\n [placeholder]=\"phoneText\">\n <mat-icon color=\"primary\" matSuffix>phone</mat-icon>\n </mat-form-field>\n\n <mat-card-actions style=\"flex-direction: column\">\n <button (click)=\"signOut()\" *ngIf=\"canLogout\" color=\"primary\" mat-button>{{signoutButtonText}}</button>\n <button (click)=\"deleteAccount()\" *ngIf=\"canDeleteAccount\" color=\"warn\" mat-button>{{deleteAccountButtonText}}</button>\n </mat-card-actions>\n\n </ng-template>\n\n </mat-card>\n\n</ng-template>\n\n\n<ng-template #none>\n <mat-card class=\"none-card\" style=\"flex-direction: row\" fxLayoutAlign=\"center center\">\n <mat-card-content style=\"flex-direction: row\" fxLayoutAlign=\"center center\">\n <mat-icon color=\"accent\">warning</mat-icon>\n <span>{{notLoggedInText}}</span>\n </mat-card-content>\n </mat-card>\n</ng-template>\n", styles: [".edit-button{margin:1rem}.full-width{width:100%}.cut-text{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.none-card{min-height:430px}.none-card span{font-size:24px;text-align:center;color:#0000008a}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i6.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i6.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i6.MatCardAvatar, selector: "[mat-card-avatar], [matCardAvatar]" }, { kind: "directive", type: i6.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i6.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i7.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: 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.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i8.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i8.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i9.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i10.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UserComponent, decorators: [{
type: Component,
args: [{ selector: "ngx-auth-firebaseui-user", template: "<div *ngIf=\"auth.authState| async; then authenticated else none\">\n\n</div>\n\n<ng-template #authenticated>\n <mat-card *ngIf=\"auth.user | async as user\">\n <!--<form [formGroup]=\"updateFormGroup\" >-->\n <!--card header-->\n <mat-card-header style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n\n <img *ngIf=\"authProcess?.getUserPhotoUrl() | async as photoUrl\" [src]=\"photoUrl\" mat-card-avatar>\n\n <div *ngIf=\"user.emailVerified; then emailVerified else emailNotVerified\"></div>\n <ng-template #emailVerified>\n <mat-icon color=\"primary\"\n [matTooltip]=\"emailVerifiedText\"\n matTooltipPosition=\"after\">\n verified_user\n </mat-icon>\n </ng-template>\n <ng-template #emailNotVerified>\n <mat-icon color=\"warn\"\n [matTooltip]=\"emailNotVerifiedText\"\n matTooltipPosition=\"after\">\n warning\n </mat-icon>\n </ng-template>\n\n </mat-card-header>\n\n <!--card content-->\n <mat-card-content *ngIf=\"editMode; then edit else readonly\">\n </mat-card-content>\n\n <ng-template #edit>\n <form (submit)=\"save()\" [formGroup]=\"updateFormGroup\">\n\n <mat-card-content style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n <div fxLayoutAlign=\"center\">\n <button (click)=\"changeEditMode()\" class=\"edit-button\" color=\"warn\"\n mat-raised-button>\n {{cancelButtonText}}\n </button>\n </div>\n\n <!--name-->\n <mat-form-field [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{nameText}}</mat-label>\n <input [formControl]=\"updateNameFormControl\"\n matInput\n [placeholder]=\"nameText\">\n <mat-icon matSuffix>person</mat-icon>\n <mat-hint align=\"end\" aria-live=\"polite\"> {{ updateNameFormControl.value?.length }}\n / {{ config.nameMaxLength }} </mat-hint>\n <mat-error *ngIf=\"updateNameFormControl.hasError('required')\">\n {{nameErrorRequiredText}}\n </mat-error>\n </mat-form-field>\n\n <!--email-->\n <mat-form-field [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{emailText}}</mat-label>\n <input [formControl]=\"updateEmailFormControl\"\n matInput\n [placeholder]=\"emailText\">\n <mat-icon matSuffix>email</mat-icon>\n <mat-error *ngIf=\"updateEmailFormControl.hasError('required')\">\n {{emailErrorRequiredText}} {{updateEmailFormControl.value}}\n </mat-error>\n <mat-error *ngIf=\"updateEmailFormControl.hasError('pattern')\">\n {{emailErrorPatternText}} {{updateEmailFormControl.value}}\n </mat-error>\n </mat-form-field>\n\n <!--phone number-->\n <mat-form-field *ngIf=\"false\" [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{phoneText}}</mat-label>\n <input [formControl]=\"updatePhoneNumberFormControl\"\n matInput\n [placeholder]=\"phoneText\"\n type=\"tel\">\n <mat-icon matSuffix>phone</mat-icon>\n <mat-hint align=\"end\" aria-live=\"polite\">\n {{phoneHintText}}\n </mat-hint>\n <mat-error *ngIf=\"updatePhoneNumberFormControl.hasError('pattern')\">\n {{phoneErrorPatternText}}\n </mat-error>\n </mat-form-field>\n\n </mat-card-content>\n\n <mat-card-actions style=\"flex-direction: column\">\n <button color=\"primary\"\n mat-button\n type=\"submit\">\n {{saveChangesButtonText}}\n </button>\n </mat-card-actions>\n </form>\n </ng-template>\n\n <ng-template #readonly>\n <div fxLayoutAlign=\"center\">\n <button *ngIf=\"canEditAccount\" (click)=\"changeEditMode()\" class=\"edit-button\" color=\"primary\"\n mat-raised-button>\n {{editButtonText}}\n </button>\n </div>\n\n <!--name-->\n <mat-form-field [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{nameText}}</mat-label>\n <input [disabled]=\"!editMode\"\n [value]=\"user.displayName\"\n matInput\n [placeholder]=\"nameText\">\n <mat-icon color=\"primary\" matSuffix>person</mat-icon>\n </mat-form-field>\n\n <!--email-->\n <mat-form-field [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{emailText}}</mat-label>\n <input [disabled]=\"!editMode\"\n [value]=\"user.email\" matInput\n [placeholder]=\"emailText\">\n <mat-icon color=\"primary\" matSuffix>email</mat-icon>\n </mat-form-field>\n\n <!--phone number-->\n <mat-form-field *ngIf=\"false\" [appearance]=\"appearance\" class=\"full-width\">\n <mat-label>{{phoneText}}</mat-label>\n <input [disabled]=\"!editMode\"\n [value]=\"user.phoneNumber\"\n matInput\n [placeholder]=\"phoneText\">\n <mat-icon color=\"primary\" matSuffix>phone</mat-icon>\n </mat-form-field>\n\n <mat-card-actions style=\"flex-direction: column\">\n <button (click)=\"signOut()\" *ngIf=\"canLogout\" color=\"primary\" mat-button>{{signoutButtonText}}</button>\n <button (click)=\"deleteAccount()\" *ngIf=\"canDeleteAccount\" color=\"warn\" mat-button>{{deleteAccountButtonText}}</button>\n </mat-card-actions>\n\n </ng-template>\n\n </mat-card>\n\n</ng-template>\n\n\n<ng-template #none>\n <mat-card class=\"none-card\" style=\"flex-direction: row\" fxLayoutAlign=\"center center\">\n <mat-card-content style=\"flex-direction: row\" fxLayoutAlign=\"center center\">\n <mat-icon color=\"accent\">warning</mat-icon>\n <span>{{notLoggedInText}}</span>\n </mat-card-content>\n </mat-card>\n</ng-template>\n", styles: [".edit-button{margin:1rem}.full-width{width:100%}.cut-text{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.none-card{min-height:430px}.none-card span{font-size:24px;text-align:center;color:#0000008a}\n"] }]
}], ctorParameters: function () { return [{ type: i1.AngularFireAuth }, { type: i2.AuthProcessService }, { type: i3.FirestoreSyncService }, { type: undefined, decorators: [{
type: Inject,
args: [forwardRef(() => NgxAuthFirebaseUIConfigToken)]
}] }]; }, propDecorators: { editMode: [{
type: Input
}], canLogout: [{
type: Input
}], canEditAccount: [{
type: Input
}], canDeleteAccount: [{
type: Input
}], appearance: [{
type: Input
}], notLoggedInText: [{
type: Input
}], emailVerifiedText: [{
type: Input
}], emailNotVerifiedText: [{
type: Input
}], cancelButtonText: [{
type: Input
}], saveChangesButtonText: [{
type: Input
}], editButtonText: [{
type: Input
}], signoutButtonText: [{
type: Input
}], deleteAccountButtonText: [{
type: Input
}], nameText: [{
type: Input
}], nameErrorRequiredText: [{
type: Input
}], emailText: [{
type: Input
}], emailErrorRequiredText: [{
type: Input
}], emailErrorPatternText: [{
type: Input
}], phoneText: [{
type: Input
}], phoneHintText: [{
type: Input
}], phoneErrorPatternText: [{
type: Input
}], onSignOut: [{
type: Output
}], onAccountEdited: [{
type: Output
}], onAccountDeleted: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtYXV0aC1maXJlYmFzZXVpL3NyYy9saWIvY29tcG9uZW50cy9uZ3gtYXV0aC1maXJlYmFzZXVpLXVzZXIvdXNlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtYXV0aC1maXJlYmFzZXVpL3NyYy9saWIvY29tcG9uZW50cy9uZ3gtYXV0aC1maXJlYmFzZXVpLXVzZXIvdXNlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFlBQVksRUFDWixVQUFVLEVBQ1YsTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBR2xGLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUM1RCxPQUFPLEVBQUMsV0FBVyxFQUEyQixrQkFBa0IsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBRzFGLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7Ozs7Ozs7QUFRM0MsTUFBTSxPQUFPLGFBQWE7SUFpRHhCLFlBQ1MsSUFBcUIsRUFDckIsV0FBK0IsRUFDOUIsZ0JBQXNDLEVBRXZDLE1BQStCO1FBSi9CLFNBQUksR0FBSixJQUFJLENBQWlCO1FBQ3JCLGdCQUFXLEdBQVgsV0FBVyxDQUFvQjtRQUM5QixxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQXNCO1FBRXZDLFdBQU0sR0FBTixNQUFNLENBQXlCO1FBcEQvQixjQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLG1CQUFjLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLHFCQUFnQixHQUFHLElB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RyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUdHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUNHLG9CQUFvQjtzQkFBNUIsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBQ0cscUJBQXFCO3NCQUE3QixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUNHLHVCQUF1QjtzQkFBL0IsS0FBSztnQkFHRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFHRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLHNCQUFzQjtzQkFBOUIsS0FBSztnQkFDRyxxQkFBcUI7c0JBQTdCLEtBQUs7Z0JBR0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUtHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFHSSxTQUFTO3NCQUFsQixNQUFNO2dCQUdHLGVBQWU7c0JBQXhCLE1BQU07Z0JBR0csZ0JBQWdCO3NCQUF6QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIGZvcndhcmRSZWYsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gXCJAYW5ndWxhci9maXJlL2NvbXBhdC9hdXRoXCI7XG5pbXBvcnQgeyBVbnR5cGVkRm9ybUNvbnRyb2wsIFVudHlwZWRGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCBmaXJlYmFzZSBmcm9tIFwiZmlyZWJhc2UvY29tcGF0L2FwcFwiO1xuaW1wb3J0IHsgIE1hdEZvcm1GaWVsZEFwcGVhcmFuY2UgfSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZFwiO1xuaW1wb3J0IHsgTmd4QXV0aEZpcmViYXNlVUlDb25maWdUb2tlbiB9IGZyb20gXCIuLi8uLi90b2tlbnNcIjtcbmltcG9ydCB7RU1BSUxfUkVHRVgsIE5neEF1dGhGaXJlYmFzZVVJQ29uZmlnLCBQSE9ORV9OVU1CRVJfUkVHRVh9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgQXV0aFByb2Nlc3NTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uL3NlcnZpY2VzL2F1dGgtcHJvY2Vzcy5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBGaXJlc3RvcmVTeW5jU2VydmljZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9maXJlc3RvcmUtc3luYy5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBtYXAsIHRha2UgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tIFwicnhqc1wiO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwibmd4LWF1dGgtZmlyZWJhc2V1aS11c2VyXCIsXG4gIHRlbXBsYXRlVXJsOiBcIi4vdXNlci5jb21wb25lbnQuaHRtbFwiLFxuICBzdHlsZVVybHM6IFtcIi4vdXNlci5jb21wb25lbnQuc2Nzc1wiXSxcbn0pXG5leHBvcnQgY2xhc3MgVXNlckNvbXBvbmVudCB7XG4gIEBJbnB1dCgpIGVkaXRNb2RlOiBib29sZWFuO1xuICBASW5wdXQoKSBjYW5Mb2dvdXQgPSB0cnVlO1xuICBASW5wdXQoKSBjYW5FZGl0QWNjb3VudCA9IHRydWU7XG4gIEBJbnB1dCgpIGNhbkRlbGV0ZUFjY291bnQgPSB0cnVlO1xuICBASW5wdXQoKSBhcHBlYXJhbmNlOiBNYXRGb3JtRmllbGRBcHBlYXJhbmNlO1xuXG4gIC8vIGkxOG4gY29tbW9uc1xuICBASW5wdXQoKSBub3RMb2dnZWRJblRleHQgPSBcIllvdSBhcmUgbm90IGxvZ2dlZCBpbiFcIjtcbiAgQElucHV0KCkgZW1haWxWZXJpZmllZFRleHQgPSBcImVtYWlsIGlzIHZlcmlmaWVkXCI7XG4gIEBJbnB1dCgpIGVtYWlsTm90VmVyaWZpZWRUZXh0ID0gXCJlbWFpbCBpcyBub3QgdmVyaWZpZWRcIjtcbiAgQElucHV0KCkgY2FuY2VsQnV0dG9uVGV4dCA9IFwiY2FuY2VsXCI7XG4gIEBJbnB1dCgpIHNhdmVDaGFuZ2VzQnV0dG9uVGV4dCA9IFwiU2F2ZSBjaGFuZ2VzXCI7XG4gIEBJbnB1dCgpIGVkaXRCdXR0b25UZXh0ID0gXCJlZGl0XCI7XG4gIEBJbnB1dCgpIHNpZ25vdXRCdXR0b25UZXh0ID0gXCJTaWduIG91dFwiO1xuICBASW5wdXQoKSBkZWxldGVBY2NvdW50QnV0dG9uVGV4dCA9IFwiRGVsZXRlIGFjY291bnRcIjtcblxuICAvL2kxOG4gbmFtZVxuICBASW5wdXQoKSBuYW1lVGV4dCA9IFwiTmFtZVwiO1xuICBASW5wdXQoKSBuYW1lRXJyb3JSZXF1aXJlZFRleHQgPSBcIk5hbWUgaXMgcmVxdWlyZWRcIjtcblxuICAvLyBpMThuIGVtYWlsXG4gIEBJbnB1dCgpIGVtYWlsVGV4dCA9IFwiRW1haWxcIjtcbiAgQElucHV0KCkgZW1haWxFcnJvclJlcXVpcmVkVGV4dCA9IFwiRW1haWwgaXMgcmVxdWlyZWRcIjtcbiAgQElucHV0KCkgZW1haWxFcnJvclBhdHRlcm5UZXh0ID0gXCJQbGVhc2UgZW50ZXIgYSB2YWxpZCBlbWFpbCBhZGRyZXNzXCI7XG5cbiAgLy8gaTE4biBwaG9uZVxuICBASW5wdXQoKSBwaG9uZVRleHQgPSBcIlBob25lIG51bWJlclwiO1xuICBASW5wdXQoKSBwaG9uZUhpbnRUZXh0ID0gYFxuICAgIFRoZSBwaG9uZSBudW1iZXIgaXMgaW50ZXJuYXRpb25hbC4gVGhlcmVmb3JlLCBpdCBzaG91bGQgc3RhcnQgd2l0aCBhICsgc2lnbiBvciAwMCxcbiAgICBmb2xsb3dlZCBieSB0aGUgY291bnRyeSBjb2RlLCAtIGFuZCBuYXRpb25hbCBudW1iZXIgZS5nOiArNDktMTIzNDU2Nzggb3IgMDA0MS0xMjM0NTY3ODkwXG5cbiAgICAgIE5PVEUgOiB0aGUgcGhvbmUgbnVtYmVyIG11c3QgYmUgYSB2YWxpZCBwaG9uZSBjcmVkZW50aWFsICEhYDtcbiAgQElucHV0KCkgcGhvbmVFcnJvclBhdHRlcm5UZXh0ID0gXCJQbGVhc2UgZW50ZXIgYSB2YWxpZCBwaG9uZSBudW1iZXJcIjtcblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGFuZ3VsYXItZXNsaW50L25vLW91dHB1dC1vbi1wcmVmaXhcbiAgQE91dHB1dCgpIG9uU2lnbk91dDogRXZlbnRFbWl0dGVyPHZvaWQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvbm8tb3V0cHV0LW9uLXByZWZpeFxuICBAT3V0cHV0KCkgb25BY2NvdW50RWRpdGVkOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9uby1vdXRwdXQtb24tcHJlZml4XG4gIEBPdXRwdXQoKSBvbkFjY291bnREZWxldGVkOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgdXBkYXRlRm9ybUdyb3VwOiBVbnR5cGVkRm9ybUdyb3VwO1xuICB1cGRhdGVOYW1lRm9ybUNvbnRyb2w6IFVudHlwZWRGb3JtQ29udHJvbDtcbiAgdXBkYXRlRW1haWxGb3JtQ29udHJvbDogVW50eXBlZEZvcm1Db250cm9sO1xuICB1cGRhdGVQaG9uZU51bWJlckZvcm1Db250cm9sOiBVbnR5cGVkRm9ybUNvbnRyb2w7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIGF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBwdWJsaWMgYXV0aFByb2Nlc3M6IEF1dGhQcm9jZXNzU2VydmljZSxcbiAgICBwcml2YXRlIGZpcmVTdG9yZVNlcnZpY2U6IEZpcmVzdG9yZVN5bmNTZXJ2aWNlLFxuICAgIEBJbmplY3QoZm9yd2FyZFJlZigoKSA9PiBOZ3hBdXRoRmlyZWJhc2VVSUNvbmZpZ1Rva2VuKSlcbiAgICBwdWJsaWMgY29uZmlnOiBOZ3hBdXRoRmlyZWJhc2VVSUNvbmZpZ1xuICApIHt9XG5cbiAgY2hhbmdlRWRpdE1vZGUoKSB7XG4gICAgaWYgKHRoaXMuZWRpdE1vZGUpIHtcbiAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgIHRoaXMuZWRpdE1vZGUgPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5pbml0VXBkYXRlRm9ybUdyb3VwKCkuc3Vic2NyaWJlKCh1cGRhdGVGb3JtR3JvdXA6IFVudHlwZWRGb3JtR3JvdXApID0+IHtcbiAgICAgICAgdGhpcy51cGRhdGVGb3JtR3JvdXAgPSB1cGRhdGVGb3JtR3JvdXA7XG4gICAgICAgIHRoaXMuZWRpdE1vZGUgPSB0cnVlO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmVzZXQoKSB7XG4gICAgdGhpcy51cGRhdGVGb3JtR3JvdXAucmVzZXQoKTtcbiAgICB0aGlzLnVwZGF0ZUZvcm1Hcm91cC5kaXNhYmxlKCk7XG4gICAgdGhpcy51cGRhdGVGb3JtR3JvdXAgPSBudWxsO1xuICB9XG5cbiAgYXN5bmMgc2F2ZSgpIHtcbiAgICBpZiAodGhpcy51cGRhdGVGb3JtR3JvdXAuZGlydHkpIHtcbiAgICAgIHRoaXMuZWRpdE1vZGUgPSBmYWxzZTtcbiAgICAgIGNvbnN0IHVzZXIgPSB0aGlzLmF1dGhQcm9jZXNzLnVzZXI7XG4gICAgICAvLyBuZ3gtYXV0aC1maXJlYmFzZXVpLXVzZXIudXBkYXRlUHJvZmlsZSgpXG4gICAgICAvLyBuZ3gtYXV0aC1maXJlYmFzZXVpLXVzZXIudXBkYXRlRW1haWwoKVxuICAgICAgLy8gY29uc29sZS5sb2coJ2Zvcm0gPSAnLCB0aGlzLnVwZGF0ZUZvcm1Hcm91cCk7XG5cbiAgICAgIGNvbnN0IHNuYWNrQmFyTXNnOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICB0cnkge1xuICAgICAgICBpZiAodGhpcy51cGRhdGVOYW1lRm9ybUNvbnRyb2wuZGlydHkpIHtcbiAgICAgICAgICBhd2FpdCB1c2VyLnVwZGF0ZVByb2ZpbGUoe1xuICAgICAgICAgICAgZGlzcGxheU5hbWU6IHRoaXMudXBkYXRlTmFtZUZvcm1Db250cm9sLnZhbHVlLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHNuYWNrQmFyTXNnLnB1c2goYHlvdXIgbmFtZSBoYXMgYmVlbiB1cGRhdGVkIHRvICR7dXNlci5kaXNwbGF5TmFtZX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnVwZGF0ZUVtYWlsRm9ybUNvbnRyb2wuZGlydHkpIHtcbiAgICAgICAgICBhd2FpdCB1c2VyLnVwZGF0ZUVtYWlsKHRoaXMudXBkYXRlRW1haWxGb3JtQ29udHJvbC52YWx1ZSk7XG4gICAgICAgICAgc25hY2tCYXJNc2cucHVzaChgeW91ciBlbWFpbCBoYXMgYmVlbiB1cGRhdGVkIHRvICR7dXNlci5lbWFpbH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnVwZGF0ZVBob25lTnVtYmVyRm9ybUNvbnRyb2wuZGlydHkpIHtcbiAgICAgICAgICBhd2FpdCB1c2VyLnVwZGF0ZVBob25lTnVtYmVyKHRoaXMudXBkYXRlUGhvbmVOdW1iZXJGb3JtQ29udHJvbC52YWx1ZSk7XG4gICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICBcInBob25lIG51bWJlciA9IFwiLFxuICAgICAgICAgICAgdGhpcy51cGRhdGVQaG9uZU51bWJlckZvcm1Db250cm9sLnZhbHVlXG4gICAgICAgICAgKTtcbiAgICAgICAgICBzbmFja0Jhck1zZy5wdXNoKFxuICAgICAgICAgICAgYHlvdXIgcGhvbmUgbnVtYmVyIGhhcyBiZWVuIHVwZGF0ZWQgdG8gJHt1c2VyLnBob25lTnVtYmVyfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmVuYWJsZUZpcmVzdG9yZVN5bmMpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmZpcmVTdG9yZVNlcnZpY2UudXBkYXRlVXNlckRhdGEoXG4gICAgICAgICAgICB0aGlzLmF1dGhQcm9jZXNzLnBhcnNlVXNlckluZm8odXNlcilcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICB0aGlzLmF1dGhQcm9jZXNzLnNob3dUb2FzdChcbiAgICAgICAgICBlcnJvciAmJiBlcnJvci5tZXNzYWdlID8gZXJyb3IubWVzc2FnZSA6IGVycm9yXG4gICAgICAgICk7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc25hY2tCYXJNc2cubGVuZ3RoID4gMCkge1xuICAgICAgICB0aGlzLmF1dGhQcm9jZXNzLnNob3dUb2FzdChzbmFja0Jhck1zZy5qb2luKFwiXFxcXG5cIikpO1xuICAgICAgfVxuICAgICAgdGhpcy5vbkFjY291bnRFZGl0ZWQuZW1pdCgpOyAvLyBlbWl0IGV2ZW50IGlmIHRoZSBmb3JtIHdhcyBkaXJ0eVxuICAgICAgdGhpcy51cGRhdGVGb3JtR3JvdXAucmVzZXQoKTtcbiAgICB9XG4gIH1cblxuICBzaWduT3V0KCkge1xuICAgIHRoaXMuYXV0aFxuICAgICAgLnNpZ25PdXQoKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5vblNpZ25PdXQuZW1pdCgpKVxuICAgICAgLmNhdGNoKChlKSA9PiBjb25zb2xlLmVycm9yKFwiQW4gZXJyb3IgaGFwcGVuZWQgd2hpbGUgc2lnbmluZyBvdXQhXCIsIGUpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgdGhlIGFjY291bnQgb2YgdGhlIGN1cnJlbnQgZmlyZWJhc2Ugbmd4LWF1dGgtZmlyZWJhc2V1aS11c2VyXG4gICAqXG4gICAqIE9uIFN1Y2Nlc3MsIGVtaXQgdGhlIDxvbkFjY291bnREZWxldGVkPiBldmVudCBhbmQgdG9hc3QgYSBtc2chI1xuICAgKiBPdGhlcndpc2UsIGxvZyB0aGUgYW5kIHRvYXN0IGFuZCBlcnJvciBtc2chXG4gICAqXG4gICAqL1xuICBhc3luYyBkZWxldGVBY2NvdW50KCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1c2VyID0gdGhpcy5hdXRoUHJvY2Vzcy51c2VyO1xuXG4gICAgICAvLyBhd2FpdCB0aGlzLmF1dGhQcm9jZXNzLmRlbGV0ZUFjY291bnQoKTtcbiAgICAgIGF3YWl0IHRoaXMuYXV0aFByb2Nlc3MudXNlci5kZWxldGUoKTtcbiAgICAgIC8vIGlmICh0aGlzLmNvbmZpZy5lbmFibGVGaXJlc3RvcmVTeW5jKSB7XG4gICAgICBhd2FpdCB0aGlzLmZpcmVTdG9yZVNlcnZpY2UuZGVsZXRlVXNlckRhdGEodXNlci51aWQpO1xuICAgICAgLy8gfVxuICAgICAgdGhpcy5vbkFjY291bnREZWxldGVkLmVtaXQoKTtcbiAgICAgIHRoaXMuZWRpdE1vZGUgPSBmYWxzZTtcbiAgICAgIGNvbnNvbGUubG9nKFwiWW91ciBhY2NvdW50IGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBkZWxldGVkIVwiKTtcbiAgICAgIHRoaXMuYXV0aFByb2Nlc3Muc2hvd1RvYXN0KFwiWW91ciBhY2NvdW50IGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBkZWxldGVkIVwiKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5sb2coXCJFcnJvciB3aGlsZSBkZWxldGUgdXNlciBhY2NvdW50XCIsIGVycm9yKTtcbiAgICAgIHRoaXMuYXV0aFByb2Nlc3Muc2hvd1RvYXN0KFxuICAgICAgICBgRXJyb3Igb2NjdXJyZWQgd2hpbGUgZGVsZXRpbmcgeW91ciBhY2NvdW50OiAke2Vycm9yLm1lc3NhZ2V9YFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgaW5pdFVwZGF0ZUZvcm1Hcm91cCgpOiBPYnNlcnZhYmxlPFVudHlwZWRGb3JtR3JvdXA+IHtcbiAgICByZXR1cm4gdGhpcy5hdXRoUHJvY2Vzcy51c2VyJC5waXBlKFxuICAgICAgdGFrZSgxKSxcbiAgICAgIG1hcCgoY3VycmVudFVzZXI6IGZpcmViYXNlLlVzZXIpID0+IHtcbiAgICAgICAgY29uc3QgdXBkYXRlRm9ybUdyb3VwID0gbmV3IFVudHlwZWRGb3JtR3JvdXAoe1xuICAgICAgICAgIG5hbWU6IHRoaXMudXBkYXRlTmFtZUZvcm1Db250cm9sID0gbmV3IFVudHlwZWRGb3JtQ29udHJvbChcbiAgICAgICAgICAgIHsgdmFsdWU6IGN1cnJlbnRVc2VyLmRpc3BsYXlOYW1lLCBkaXNhYmxlZDogdGhpcy5lZGl0TW9kZSB9LFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICBWYWxpZGF0b3JzLnJlcXVpcmVkLFxuICAgICAgICAgICAgICBWYWxpZGF0b3JzLm1pbkxlbmd0aCh0aGlzLmNvbmZpZy5uYW1lTWluTGVuZ3RoKSxcbiAgICAgICAgICAgICAgVmFsaWRhdG9ycy5tYXhMZW5ndGgodGhpcy5jb25maWcubmFtZU1heExlbmd0aCksXG4gICAgICAgICAgICBdXG4gICAgICAgICAgKSxcblxuICAgICAgICAgIGVtYWlsOiB0aGlzLnVwZGF0ZUVtYWlsRm9ybUNvbnRyb2wgPSBuZXcgVW50eXBlZEZvcm1Db250cm9sKFxuICAgICAgICAgICAgeyB2YWx1ZTogY3VycmVudFVzZXIuZW1haWwsIGRpc2FibGVkOiB0aGlzLmVkaXRNb2RlIH0sXG4gICAgICAgICAgICBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5wYXR0ZXJuKEVNQUlMX1JFR0VYKV1cbiAgICAgICAgICApLFxuXG4gICAgICAgICAgcGhvbmVOdW1iZXI6IHRoaXMudXBkYXRlUGhvbmVOdW1iZXJGb3JtQ29udHJvbCA9IG5ldyBVbnR5cGVkRm9ybUNvbnRyb2woXG4gICAgICAgICAgICB7IHZhbHVlOiBjdXJyZW50VXNlci5waG9uZU51bWJlciwgZGlzYWJsZWQ6IHRoaXMuZWRpdE1vZGUgfSxcbiAgICAgICAgICAgIFtWYWxpZGF0b3JzLnBhdHRlcm4oUEhPTkVfTlVNQkVSX1JFR0VYKV1cbiAgICAgICAgICApLFxuICAgICAgICB9KTtcblxuICAgICAgICB1cGRhdGVGb3JtR3JvdXAuZW5hYmxlKCk7XG4gICAgICAgIHJldHVybiB1cGRhdGVGb3JtR3JvdXA7XG4gICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIjxkaXYgKm5nSWY9XCJhdXRoLmF1dGhTdGF0ZXwgYXN5bmM7IHRoZW4gYXV0aGVudGljYXRlZCBlbHNlIG5vbmVcIj5cblxuPC9kaXY+XG5cbjxuZy10ZW1wbGF0ZSAjYXV0aGVudGljYXRlZD5cbiAgPG1hdC1jYXJkICpuZ0lmPVwiYXV0aC51c2VyIHwgYXN5bmMgYXMgdXNlclwiPlxuICAgIDwhLS08Zm9ybSBbZm9ybUdyb3VwXT1cInVwZGF0ZUZvcm1Hcm91cFwiID4tLT5cbiAgICA8IS0tY2FyZCBoZWFkZXItLT5cbiAgICA8bWF0LWNhcmQtaGVhZGVyIHN0eWxlPVwiZmxleC1kaXJlY3Rpb246IGNvbHVtblwiIGZ4TGF5b3V0QWxpZ249XCJjZW50ZXIgY2VudGVyXCI+XG5cbiAgICAgIDxpbWcgKm5nSWY9XCJhdXRoUHJvY2Vzcz8uZ2V0VXNlclBob3RvVXJsKCkgfCBhc3luYyBhcyBwaG90b1VybFwiIFtzcmNdPVwicGhvdG9VcmxcIiBtYXQtY2FyZC1hdmF0YXI+XG5cbiAgICAgIDxkaXYgKm5nSWY9XCJ1c2VyLmVtYWlsVmVyaWZpZWQ7IHRoZW4gZW1haWxWZXJpZmllZCBlbHNlIGVtYWlsTm90VmVyaWZpZWRcIj48L2Rpdj5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjZW1haWxWZXJpZmllZD5cbiAgICAgICAgPG1hdC1pY29uIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJlbWFpbFZlcmlmaWVkVGV4dFwiXG4gICAgICAgICAgICAgICAgICBtYXRUb29sdGlwUG9zaXRpb249XCJhZnRlclwiPlxuICAgICAgICAgIHZlcmlmaWVkX3VzZXJcbiAgICAgICAgPC9tYXQtaWNvbj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8bmctdGVtcGxhdGUgI2VtYWlsTm90VmVyaWZpZWQ+XG4gICAgICAgIDxtYXQtaWNvbiBjb2xvcj1cIndhcm5cIlxuICAgICAgICAgICAgICAgICAgW21hdFRvb2x0aXBdPVwiZW1haWxOb3RWZXJpZmllZFRleHRcIlxuICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcFBvc2l0aW9uPVwiYWZ0ZXJcIj5cbiAgICAgICAgICB3YXJuaW5nXG4gICAgICAgIDwvbWF0LWljb24+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgPC9tYXQtY2FyZC1oZWFkZXI+XG5cbiAgICA8IS0tY2FyZCBjb250ZW50LS0+XG4gICAgPG1hdC1jYXJkLWNvbnRlbnQgKm5nSWY9XCJlZGl0TW9kZTsgdGhlbiBlZGl0IGVsc2UgcmVhZG9ubHlcIj5cbiAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XG5cbiAgICA8bmctdGVtcGxhdGUgI2VkaXQ+XG4gICAgICA8Zm9ybSAoc3VibWl0KT1cInNhdmUoKVwiIFtmb3JtR3JvdXBdPVwidXBkYXRlRm9ybUdyb3VwXCI+XG5cbiAgICAgICAgPG1hdC1jYXJkLWNvbnRlbnQgc3R5bGU9XCJmbGV4LWRpcmVjdGlvbjogY29sdW1uXCIgZnhMYXlvdXRBbGlnbj1cImNlbnRlciBjZW50ZXJcIj5cbiAgICAgICAgICA8ZGl2IGZ4TGF5b3V0QWxpZ249XCJjZW50ZXJcIj5cbiAgICAgICAgICAgIDxidXR0b24gKGNsaWNrKT1cImNoYW5nZUVkaXRNb2RlKClcIiBjbGFzcz1cImVkaXQtYnV0dG9uXCIgY29sb3I9XCJ3YXJuXCJcbiAgICAgICAgICAgICAgICAgICAgbWF0LXJhaXNlZC1idXR0b24+XG4gICAgICAgICAgICAgIHt7Y2FuY2VsQnV0dG9uVGV4dH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDwhLS1uYW1lLS0+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIFthcHBlYXJhbmNlXT1cImFwcGVhcmFuY2VcIiBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+e3tuYW1lVGV4dH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXQgW2Zvcm1Db250cm9sXT1cInVwZGF0ZU5hbWVGb3JtQ29udHJvbFwiXG4gICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwibmFtZVRleHRcIj5cbiAgICAgICAgICAgIDxtYXQtaWNvbiBtYXRTdWZmaXg+cGVyc29uPC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDxtYXQtaGludCBhbGlnbj1cImVuZFwiIGFyaWEtbGl2ZT1cInBvbGl0ZVwiPiB7eyB1cGRhdGVOYW1lRm9ybUNvbnRyb2wudmFsdWU/Lmxlbmd0aCB9fVxuICAgICAgICAgICAgICAvIHt7IGNvbmZpZy5uYW1lTWF4TGVuZ3RoIH19IDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwidXBkYXRlTmFtZUZvcm1Db250cm9sLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICAgICAgICAgIHt7bmFtZUVycm9yUmVxdWlyZWRUZXh0fX1cbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG5cbiAgICAgICAgICA8IS0tZW1haWwtLT5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgW2FwcGVhcmFuY2VdPVwiYXBwZWFyYW5jZVwiIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57e2VtYWlsVGV4dH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXQgW2Zvcm1Db250cm9sXT1cInVwZGF0ZUVtYWlsRm9ybUNvbnRyb2xcIlxuICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cImVtYWlsVGV4dFwiPlxuICAgICAgICAgICAgPG1hdC1pY29uIG1hdFN1ZmZpeD5lbWFpbDwvbWF0LWljb24+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwidXBkYXRlRW1haWxGb3JtQ29udHJvbC5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgICAgICAgICB7e2VtYWlsRXJyb3JSZXF1aXJlZFRleHR9fSB7e3VwZGF0ZUVtYWlsRm9ybUNvbnRyb2wudmFsdWV9fVxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwidXBkYXRlRW1haWxGb3JtQ29udHJvbC5oYXNFcnJvcigncGF0dGVybicpXCI+XG4gICAgICAgICAgICAgIHt7ZW1haWxFcnJvclBhdHRlcm5UZXh0fX0ge3t1cGRhdGVFbWFpbEZvcm1Db250cm9sLnZhbHVlfX1cbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG5cbiAgICAgICAgICA8IS0tcGhvbmUgbnVtYmVyLS0+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiZmFsc2VcIiBbYXBwZWFyYW5jZV09XCJhcHBlYXJhbmNlXCIgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPnt7cGhvbmVUZXh0fX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dCBbZm9ybUNvbnRyb2xdPVwidXBkYXRlUGhvbmVOdW1iZXJGb3JtQ29udHJvbFwiXG4gICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwicGhvbmVUZXh0XCJcbiAgICAgICAgICAgICAgICAgICB0eXBlPVwidGVsXCI+XG4gICAgICAgICAgICA8bWF0LWljb24gbWF0U3VmZml4PnBob25lPC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDxtYXQtaGludCBhbGlnbj1cImVuZFwiIGFyaWEtbGl2ZT1cInBvbGl0ZVwiPlxuICAgICAgICAgICAgICB7e3Bob25lSGludFRleHR9fVxuICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJ1cGRhdGVQaG9uZU51bWJlckZvcm1Db250cm9sLmhhc0Vycm9yKCdwYXR0ZXJuJylcIj5cbiAgICAgICAgICAgICAge3twaG9uZUVycm9yUGF0dGVyblRleHR9fVxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XG5cbiAgICAgICAgPG1hdC1jYXJkLWFjdGlvbnMgc3R5bGU9XCJmbGV4LWRpcmVjdGlvbjogY29sdW1uXCI+XG4gIC