From 935999cabf5ef1e444df8783c789f3e8d0f9a15e Mon Sep 17 00:00:00 2001
From: Spencer Ofwiti <maxspencer56@gmail.com>
Date: Fri, 13 Aug 2021 13:24:54 +0300
Subject: [PATCH] Update account details component on meta update.

---
 src/app/_services/user.service.ts             | 111 ++++++++++++------
 src/app/_workers/fetch-accounts.worker.ts     |   5 +-
 .../account-details.component.ts              |  45 ++++---
 3 files changed, 101 insertions(+), 60 deletions(-)

diff --git a/src/app/_services/user.service.ts b/src/app/_services/user.service.ts
index cf6a044..7d63be6 100644
--- a/src/app/_services/user.service.ts
+++ b/src/app/_services/user.service.ts
@@ -82,7 +82,7 @@ export class UserService {
     location: string,
     locationType: string,
     oldPhoneNumber: string
-  ): Promise<any> {
+  ): Promise<boolean> {
     const accountInfo = await this.loadChangesToAccountStructure(
       name,
       phoneNumber,
@@ -96,53 +96,64 @@ export class UserService {
       locationType
     );
     const accountKey: string = await User.toKey(address);
-    this.getAccountDetailsFromMeta(accountKey)
-      .pipe(first())
-      .subscribe(
-        async (res) => {
-          const syncableAccount: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
-          const update: Array<ArgPair> = [];
-          for (const prop of Object.keys(accountInfo)) {
-            update.push(new ArgPair(prop, accountInfo[prop]));
+    return new Promise((resolve) => {
+      let status: boolean = false;
+      this.getAccountDetailsFromMeta(accountKey)
+        .pipe(first())
+        .subscribe(
+          async (res) => {
+            const syncableAccount: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
+            const update: Array<ArgPair> = [];
+            for (const prop of Object.keys(accountInfo)) {
+              update.push(new ArgPair(prop, accountInfo[prop]));
+            }
+            updateSyncable(update, 'client-branch', syncableAccount);
+            await personValidation(syncableAccount.m.data);
+            status = await this.updateMeta(syncableAccount, accountKey, this.headers);
+            if (status && phoneNumber !== oldPhoneNumber) {
+              await this.updatePhonePointers(address, oldPhoneNumber, phoneNumber);
+            }
+            resolve(status);
+          },
+          async (error) => {
+            this.loggingService.sendErrorLevelMessage(
+              'Cannot find account info in meta service',
+              this,
+              { error }
+            );
+            const syncableAccount: Syncable = new Syncable(accountKey, accountInfo);
+            status = await this.updateMeta(syncableAccount, accountKey, this.headers);
+            if (status && phoneNumber !== oldPhoneNumber) {
+              await this.updatePhonePointers(address, oldPhoneNumber, phoneNumber);
+            }
+            resolve(status);
           }
-          updateSyncable(update, 'client-branch', syncableAccount);
-          await personValidation(syncableAccount.m.data);
-          await this.updateMeta(syncableAccount, accountKey, this.headers);
-        },
-        async (error) => {
-          this.loggingService.sendErrorLevelMessage(
-            'Cannot find account info in meta service',
-            this,
-            { error }
-          );
-          const syncableAccount: Syncable = new Syncable(accountKey, accountInfo);
-          await this.updateMeta(syncableAccount, accountKey, this.headers);
-        }
-      );
-    if (phoneNumber !== oldPhoneNumber) {
-      const oldPhoneKey: string = await Phone.toKey(oldPhoneNumber);
-      const newPhoneKey: string = await Phone.toKey(phoneNumber);
-      const newPhoneData: Syncable = new Syncable(newPhoneKey, strip0x(address));
-      await this.updateMeta(newPhoneData, newPhoneKey, this.headers);
-      const oldPhoneData: Syncable = new Syncable(oldPhoneKey, '');
-      await this.updateMeta(oldPhoneData, oldPhoneKey, this.headers);
-    }
-    return accountKey;
+        );
+    });
   }
 
   async updateMeta(
     syncableAccount: Syncable,
     accountKey: string,
     headers: HttpHeaders
-  ): Promise<any> {
+  ): Promise<boolean> {
     const envelope: Envelope = await this.wrap(syncableAccount, this.signer);
     const reqBody: string = envelope.toJSON();
-    this.httpClient
-      .put(`${environment.cicMetaUrl}/${accountKey}`, reqBody, { headers })
-      .pipe(first())
-      .subscribe((res) => {
-        this.loggingService.sendInfoLevelMessage(`Response: ${res}`);
-      });
+    return new Promise((resolve) => {
+      this.httpClient
+        .put(`${environment.cicMetaUrl}/${accountKey}`, reqBody, { headers })
+        .pipe(first())
+        .subscribe(
+          (res) => {
+            this.loggingService.sendInfoLevelMessage(`Response: ${res}`);
+            resolve(true);
+          },
+          (error) => {
+            this.loggingService.sendErrorLevelMessage('Metadata update failed!', this, { error });
+            resolve(false);
+          }
+        );
+    });
   }
 
   getActions(): void {
@@ -384,4 +395,26 @@ export class UserService {
     accountInfo.vcard = btoa(vCard.generate(accountInfo.vcard));
     return accountInfo;
   }
+
+  async updatePhonePointers(
+    address: string,
+    oldPhoneNumber: string,
+    newPhoneNumber: string
+  ): Promise<void> {
+    const oldPhoneKey: string = await Phone.toKey(oldPhoneNumber);
+    const newPhoneKey: string = await Phone.toKey(newPhoneNumber);
+    const newPhoneData: Syncable = new Syncable(newPhoneKey, strip0x(address));
+    const newPhoneSetStatus = await this.updateMeta(newPhoneData, newPhoneKey, this.headers);
+    if (!newPhoneSetStatus) {
+      const error = `Failed to update new phone number pointer: ${newPhoneNumber}`;
+      this.loggingService.sendErrorLevelMessage(error, this, { error });
+    } else {
+      const oldPhoneData: Syncable = new Syncable(oldPhoneKey, '');
+      const oldPhoneSetStatus = await this.updateMeta(oldPhoneData, oldPhoneKey, this.headers);
+      if (!oldPhoneSetStatus) {
+        const error = `Failed to update old phone number pointer: ${oldPhoneNumber}`;
+        this.loggingService.sendErrorLevelMessage(error, this, { error });
+      }
+    }
+  }
 }
diff --git a/src/app/_workers/fetch-accounts.worker.ts b/src/app/_workers/fetch-accounts.worker.ts
index ed11dec..8f28221 100644
--- a/src/app/_workers/fetch-accounts.worker.ts
+++ b/src/app/_workers/fetch-accounts.worker.ts
@@ -32,8 +32,9 @@ async function getAccountByAddress(
   token: string
 ): Promise<any> {
   const userKey = await User.toKey(add0x(accountAddress));
-
-  headers['Authorization'] = 'Bearer ' + token;
+  if (token) {
+    headers['Authorization'] = 'Bearer ' + token;
+  }
   const response = await fetch(`${metaUrl}/${userKey}`, options)
     .then((res) => {
       if (res.ok) {
diff --git a/src/app/pages/accounts/account-details/account-details.component.ts b/src/app/pages/accounts/account-details/account-details.component.ts
index 85e44e7..dde50bf 100644
--- a/src/app/pages/accounts/account-details/account-details.component.ts
+++ b/src/app/pages/accounts/account-details/account-details.component.ts
@@ -56,8 +56,8 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
     'dependencies',
     'timestamp',
   ];
-  historyDefaultPageSize: number = 10;
-  historyPageSizeOptions: Array<number> = [10, 20, 50, 100];
+  historyDefaultPageSize: number = 5;
+  historyPageSizeOptions: Array<number> = [5, 10, 20, 50, 100];
   @ViewChild('HistoryTablePaginator', { static: true }) historyTablePaginator: MatPaginator;
   @ViewChild('HistoryTableSort', { static: true }) historyTableSort: MatSort;
 
@@ -114,22 +114,7 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
     this.transactionService.resetTransactionsList();
     await this.blockSyncService.blockSync(this.accountAddress);
     this.userService.resetAccountsList();
-    (await this.userService.getAccountByAddress(this.accountAddress, 100, true)).subscribe(
-      async (res) => {
-        if (res !== undefined) {
-          this.account = res;
-          this.cdr.detectChanges();
-          this.queryLocationAndCategory(this.account);
-          this.populateAccountsInfoForm(this.account);
-          this.userService
-            .getAccountStatus(this.account.vcard?.tel[0].value)
-            .pipe(first())
-            .subscribe((response) => (this.accountStatus = response.status));
-        } else {
-          alert('Account not found!');
-        }
-      }
-    );
+    await this.loadAccount();
     this.populateDataTables();
     this.loadSearchData();
     this.tokenService.load.subscribe(async (status: boolean) => {
@@ -185,7 +170,7 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
     if (this.accountInfoForm.invalid || !confirm(`Change user's profile information?`)) {
       return;
     }
-    const accountKey = await this.userService.changeAccountInfo(
+    const status = await this.userService.changeAccountInfo(
       this.accountAddress,
       this.accountInfoFormStub.firstName.value + ', ' + this.accountInfoFormStub.lastName.value,
       this.accountInfoFormStub.phoneNumber.value,
@@ -199,6 +184,9 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
       this.accountInfoFormStub.locationType.value,
       this.account.vcard?.tel[0].value
     );
+    if (status) {
+      await this.loadAccount();
+    }
     this.submitted = false;
   }
 
@@ -374,4 +362,23 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
       .pipe(first())
       .subscribe((res) => (this.genders = res));
   }
+
+  async loadAccount(): Promise<void> {
+    (await this.userService.getAccountByAddress(this.accountAddress, 100, true)).subscribe(
+      async (res) => {
+        if (res !== undefined) {
+          this.account = res;
+          this.cdr.detectChanges();
+          this.queryLocationAndCategory(this.account);
+          this.populateAccountsInfoForm(this.account);
+          this.userService
+            .getAccountStatus(this.account.vcard?.tel[0].value)
+            .pipe(first())
+            .subscribe((response) => (this.accountStatus = response.status));
+        } else {
+          alert('Account not found!');
+        }
+      }
+    );
+  }
 }