Add metadata history datatable.
This commit is contained in:
		
							parent
							
								
									858e1e65bd
								
							
						
					
					
						commit
						0acb94ce98
					
				
							
								
								
									
										29002
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										29002
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -74,6 +74,7 @@
 | 
			
		||||
    "karma-jasmine-html-reporter": "^1.5.0",
 | 
			
		||||
    "karma-junit-reporter": "^2.0.1",
 | 
			
		||||
    "lint-staged": "^11.0.0",
 | 
			
		||||
    "openpgp": "^4.10.10",
 | 
			
		||||
    "prettier": "^2.3.1",
 | 
			
		||||
    "pretty-quick": "^3.1.0",
 | 
			
		||||
    "protractor": "~7.0.0",
 | 
			
		||||
 | 
			
		||||
@ -10,3 +10,4 @@ export * from '@app/_helpers/read-csv';
 | 
			
		||||
export * from '@app/_helpers/schema-validation';
 | 
			
		||||
export * from '@app/_helpers/sync';
 | 
			
		||||
export * from '@app/_helpers/online-status';
 | 
			
		||||
export * from './to-hex';
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/app/_helpers/to-hex.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/app/_helpers/to-hex.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
function asciiToHex(str: string): string {
 | 
			
		||||
  const arr = [];
 | 
			
		||||
  for (let n = 0, l = str.length; n < l; n++) {
 | 
			
		||||
    arr.push(Number(str.charCodeAt(n)).toString(16));
 | 
			
		||||
  }
 | 
			
		||||
  return arr.join('');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export { asciiToHex };
 | 
			
		||||
@ -13,6 +13,7 @@ import { CICRegistry } from '@cicnet/cic-client';
 | 
			
		||||
import { personValidation, updateSyncable, vcardValidation } from '@app/_helpers';
 | 
			
		||||
import { add0x, strip0x } from '@src/assets/js/ethtx/dist/hex';
 | 
			
		||||
import { KeystoreService } from '@app/_services/keystore.service';
 | 
			
		||||
import * as Automerge from 'automerge';
 | 
			
		||||
const vCard = require('vcard-parser');
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
@ -38,6 +39,10 @@ export class UserService {
 | 
			
		||||
  private categoriesList: BehaviorSubject<object> = new BehaviorSubject<object>(this.categories);
 | 
			
		||||
  categoriesSubject: Observable<object> = this.categoriesList.asObservable();
 | 
			
		||||
 | 
			
		||||
  history: Array<any> = [];
 | 
			
		||||
  private historyList: BehaviorSubject<any> = new BehaviorSubject<any>(this.history);
 | 
			
		||||
  historySubject: Observable<Array<any>> = this.historyList.asObservable();
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private httpClient: HttpClient,
 | 
			
		||||
    private loggingService: LoggingService,
 | 
			
		||||
@ -243,13 +248,22 @@ export class UserService {
 | 
			
		||||
 | 
			
		||||
  async getAccountByAddress(
 | 
			
		||||
    accountAddress: string,
 | 
			
		||||
    limit: number = 100
 | 
			
		||||
    limit: number = 100,
 | 
			
		||||
    history: boolean = false
 | 
			
		||||
  ): Promise<Observable<AccountDetails>> {
 | 
			
		||||
    const accountSubject: Subject<any> = new Subject<any>();
 | 
			
		||||
    this.getAccountDetailsFromMeta(await User.toKey(add0x(accountAddress)))
 | 
			
		||||
      .pipe(first())
 | 
			
		||||
      .subscribe(async (res) => {
 | 
			
		||||
        const account: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
 | 
			
		||||
        if (history) {
 | 
			
		||||
          try {
 | 
			
		||||
            // @ts-ignore
 | 
			
		||||
            this.historyList.next(Automerge.getHistory(account.m).reverse());
 | 
			
		||||
          } catch (error) {
 | 
			
		||||
            this.loggingService.sendErrorLevelMessage('No history found', this, { error });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        const accountInfo = account.m.data;
 | 
			
		||||
        await personValidation(accountInfo);
 | 
			
		||||
        this.tokenService.load.subscribe(async (status: boolean) => {
 | 
			
		||||
 | 
			
		||||
@ -44,6 +44,23 @@ export class AppComponent implements OnInit {
 | 
			
		||||
    await this.tokenService.init();
 | 
			
		||||
    await this.userService.init();
 | 
			
		||||
    await this.transactionService.init();
 | 
			
		||||
    try {
 | 
			
		||||
      const publicKeys = await this.authService.getPublicKeys();
 | 
			
		||||
      await this.authService.mutableKeyStore.importPublicKey(publicKeys);
 | 
			
		||||
      this.authService.getTrustedUsers();
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      this.errorDialogService.openDialog({
 | 
			
		||||
        message: 'Trusted keys endpoint cannot be reached. Please try again later.',
 | 
			
		||||
      });
 | 
			
		||||
      // TODO do something to halt user progress...show a sad cicada page 🦗?
 | 
			
		||||
    }
 | 
			
		||||
    if (!this.swUpdate.isEnabled) {
 | 
			
		||||
      this.swUpdate.available.subscribe(() => {
 | 
			
		||||
        if (confirm('New Version available. Load New Version?')) {
 | 
			
		||||
          window.location.reload();
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    await this.router.events
 | 
			
		||||
      .pipe(filter((e) => e instanceof NavigationEnd))
 | 
			
		||||
      .forEach(async (routeInfo) => {
 | 
			
		||||
@ -69,23 +86,6 @@ export class AppComponent implements OnInit {
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    try {
 | 
			
		||||
      const publicKeys = await this.authService.getPublicKeys();
 | 
			
		||||
      await this.authService.mutableKeyStore.importPublicKey(publicKeys);
 | 
			
		||||
      this.authService.getTrustedUsers();
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      this.errorDialogService.openDialog({
 | 
			
		||||
        message: 'Trusted keys endpoint cannot be reached. Please try again later.',
 | 
			
		||||
      });
 | 
			
		||||
      // TODO do something to halt user progress...show a sad cicada page 🦗?
 | 
			
		||||
    }
 | 
			
		||||
    if (!this.swUpdate.isEnabled) {
 | 
			
		||||
      this.swUpdate.available.subscribe(() => {
 | 
			
		||||
        if (confirm('New Version available. Load New Version?')) {
 | 
			
		||||
          window.location.reload();
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Load resize
 | 
			
		||||
 | 
			
		||||
@ -333,7 +333,88 @@
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <mat-tab-group *ngIf="account" dynamicHeight mat-align-tabs="start">
 | 
			
		||||
      <div class="card mt-1">
 | 
			
		||||
        <app-account-history
 | 
			
		||||
          *ngIf="history"
 | 
			
		||||
          [account]="history?.snapshot.data"
 | 
			
		||||
          (closeWindow)="history = $event"
 | 
			
		||||
        ></app-account-history>
 | 
			
		||||
        <mat-card-title class="card-header"> HISTORY </mat-card-title>
 | 
			
		||||
        <div class="card-body">
 | 
			
		||||
          <div *ngIf="historyLoading">
 | 
			
		||||
            <h2 class="text-center"><strong>Loading History!</strong></h2>
 | 
			
		||||
            <mat-progress-bar [mode]="'query'"></mat-progress-bar>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <mat-table
 | 
			
		||||
            class="mat-elevation-z10"
 | 
			
		||||
            [dataSource]="historyDataSource"
 | 
			
		||||
            matSort
 | 
			
		||||
            matSortActive="timestamp"
 | 
			
		||||
            #HistoryTableSort="matSort"
 | 
			
		||||
            matSortDirection="asc"
 | 
			
		||||
            matSortDisableClear
 | 
			
		||||
          >
 | 
			
		||||
            <ng-container matColumnDef="actor">
 | 
			
		||||
              <mat-header-cell *matHeaderCellDef mat-sort-header>Actor</mat-header-cell>
 | 
			
		||||
              <mat-cell *matCellDef="let history">
 | 
			
		||||
                {{ history?.change.actor }}
 | 
			
		||||
              </mat-cell>
 | 
			
		||||
            </ng-container>
 | 
			
		||||
 | 
			
		||||
            <ng-container matColumnDef="signer">
 | 
			
		||||
              <mat-header-cell *matHeaderCellDef mat-sort-header>Signer</mat-header-cell>
 | 
			
		||||
              <mat-cell *matCellDef="let history">
 | 
			
		||||
                {{ history?.snapshot.signature?.data | signatureUser | async }}
 | 
			
		||||
              </mat-cell>
 | 
			
		||||
            </ng-container>
 | 
			
		||||
 | 
			
		||||
            <ng-container matColumnDef="message">
 | 
			
		||||
              <mat-header-cell *matHeaderCellDef mat-sort-header>Message</mat-header-cell>
 | 
			
		||||
              <mat-cell *matCellDef="let history">
 | 
			
		||||
                {{ history?.change.message }}
 | 
			
		||||
              </mat-cell>
 | 
			
		||||
            </ng-container>
 | 
			
		||||
 | 
			
		||||
            <ng-container matColumnDef="sequence">
 | 
			
		||||
              <mat-header-cell *matHeaderCellDef mat-sort-header>Sequence</mat-header-cell>
 | 
			
		||||
              <mat-cell *matCellDef="let history">
 | 
			
		||||
                {{ history?.change.seq }}
 | 
			
		||||
              </mat-cell>
 | 
			
		||||
            </ng-container>
 | 
			
		||||
 | 
			
		||||
            <ng-container matColumnDef="dependencies">
 | 
			
		||||
              <mat-header-cell *matHeaderCellDef mat-sort-header>Dependencies</mat-header-cell>
 | 
			
		||||
              <mat-cell *matCellDef="let history">
 | 
			
		||||
                {{ getKeyValue(history?.change.deps) }}
 | 
			
		||||
              </mat-cell>
 | 
			
		||||
            </ng-container>
 | 
			
		||||
 | 
			
		||||
            <ng-container matColumnDef="timestamp">
 | 
			
		||||
              <mat-header-cell *matHeaderCellDef mat-sort-header>ChangedAt</mat-header-cell>
 | 
			
		||||
              <mat-cell *matCellDef="let history">
 | 
			
		||||
                {{ history?.snapshot.timestamp | unixDate }}
 | 
			
		||||
              </mat-cell>
 | 
			
		||||
            </ng-container>
 | 
			
		||||
 | 
			
		||||
            <mat-header-row *matHeaderRowDef="historyDisplayedColumns"></mat-header-row>
 | 
			
		||||
            <mat-row
 | 
			
		||||
              *matRowDef="let history; columns: historyDisplayedColumns"
 | 
			
		||||
              (click)="viewHistory(history)"
 | 
			
		||||
              matRipple
 | 
			
		||||
            ></mat-row>
 | 
			
		||||
          </mat-table>
 | 
			
		||||
 | 
			
		||||
          <mat-paginator
 | 
			
		||||
            #HistoryTablePaginator="matPaginator"
 | 
			
		||||
            [pageSize]="historyDefaultPageSize"
 | 
			
		||||
            [pageSizeOptions]="historyPageSizeOptions"
 | 
			
		||||
            showFirstLastButtons
 | 
			
		||||
          ></mat-paginator>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <mat-tab-group dynamicHeight mat-align-tabs="start">
 | 
			
		||||
        <mat-tab label="Transactions">
 | 
			
		||||
          <app-transaction-details
 | 
			
		||||
            [transaction]="transaction"
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,20 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
 | 
			
		||||
  @ViewChild('UserTablePaginator', { static: true }) userTablePaginator: MatPaginator;
 | 
			
		||||
  @ViewChild('UserTableSort', { static: true }) userTableSort: MatSort;
 | 
			
		||||
 | 
			
		||||
  historyDataSource: MatTableDataSource<any>;
 | 
			
		||||
  historyDisplayedColumns: Array<string> = [
 | 
			
		||||
    'actor',
 | 
			
		||||
    'signer',
 | 
			
		||||
    'message',
 | 
			
		||||
    'sequence',
 | 
			
		||||
    'dependencies',
 | 
			
		||||
    'timestamp',
 | 
			
		||||
  ];
 | 
			
		||||
  historyDefaultPageSize: number = 10;
 | 
			
		||||
  historyPageSizeOptions: Array<number> = [10, 20, 50, 100];
 | 
			
		||||
  @ViewChild('HistoryTablePaginator', { static: true }) historyTablePaginator: MatPaginator;
 | 
			
		||||
  @ViewChild('HistoryTableSort', { static: true }) historyTableSort: MatSort;
 | 
			
		||||
 | 
			
		||||
  accountInfoForm: FormGroup;
 | 
			
		||||
  account: AccountDetails;
 | 
			
		||||
  accountAddress: string;
 | 
			
		||||
@ -71,6 +85,9 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
 | 
			
		||||
  areaType: string;
 | 
			
		||||
  accountsLoading: boolean = true;
 | 
			
		||||
  transactionsLoading: boolean = true;
 | 
			
		||||
  histories: Array<any> = [];
 | 
			
		||||
  history: any;
 | 
			
		||||
  historyLoading: boolean = true;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private formBuilder: FormBuilder,
 | 
			
		||||
@ -109,7 +126,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)).subscribe(
 | 
			
		||||
    (await this.userService.getAccountByAddress(this.accountAddress, 100, true)).subscribe(
 | 
			
		||||
      async (res) => {
 | 
			
		||||
        if (res !== undefined) {
 | 
			
		||||
          this.account = res;
 | 
			
		||||
@ -173,6 +190,18 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
 | 
			
		||||
      }
 | 
			
		||||
      this.cdr.detectChanges();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.userService.historySubject.subscribe(async (histories) => {
 | 
			
		||||
      this.historyDataSource = new MatTableDataSource<any>(histories);
 | 
			
		||||
      this.historyDataSource.paginator = this.historyTablePaginator;
 | 
			
		||||
      this.historyDataSource.sort = this.historyTableSort;
 | 
			
		||||
      this.histories = histories;
 | 
			
		||||
      if (histories.length > 0) {
 | 
			
		||||
        this.historyLoading = false;
 | 
			
		||||
      }
 | 
			
		||||
      this.cdr.detectChanges();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.userService.getCategories();
 | 
			
		||||
    this.userService.categoriesSubject.subscribe((res) => {
 | 
			
		||||
      this.categories = Object.keys(res);
 | 
			
		||||
@ -213,6 +242,10 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
 | 
			
		||||
      this.transactionsDataSource.paginator = this.transactionTablePaginator;
 | 
			
		||||
      this.transactionsDataSource.sort = this.transactionTableSort;
 | 
			
		||||
    }
 | 
			
		||||
    if (this.historyDataSource) {
 | 
			
		||||
      this.historyDataSource.paginator = this.historyTablePaginator;
 | 
			
		||||
      this.historyDataSource.sort = this.historyTableSort;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  doTransactionFilter(value: string): void {
 | 
			
		||||
@ -227,6 +260,10 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
 | 
			
		||||
    this.transaction = transaction;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  viewHistory(history): void {
 | 
			
		||||
    this.history = history;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  viewAccount(account): void {
 | 
			
		||||
    this.router.navigateByUrl(
 | 
			
		||||
      `/accounts/${strip0x(account.identities.evm[`bloxberg:${environment.bloxbergChainId}`][0])}`
 | 
			
		||||
@ -308,4 +345,14 @@ export class AccountDetailsComponent implements OnInit, AfterViewInit {
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getKeyValue(obj: any): string {
 | 
			
		||||
    let str = '';
 | 
			
		||||
    if (obj instanceof Object) {
 | 
			
		||||
      for (const [key, value] of Object.entries(obj)) {
 | 
			
		||||
        str += `${key}: ${value} `;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return str;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,59 @@
 | 
			
		||||
<div *ngIf="account" class="mb-3 mt-1">
 | 
			
		||||
  <div class="card text-center">
 | 
			
		||||
    <mat-card-title class="card-header">
 | 
			
		||||
      <div class="row">
 | 
			
		||||
        ACCOUNT DETAILS
 | 
			
		||||
        <button
 | 
			
		||||
          mat-raised-button
 | 
			
		||||
          type="button"
 | 
			
		||||
          class="btn btn-outline-secondary ml-auto mr-2"
 | 
			
		||||
          (click)="close()"
 | 
			
		||||
        >
 | 
			
		||||
          CLOSE
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </mat-card-title>
 | 
			
		||||
    <div class="card-body">
 | 
			
		||||
      <div class="row">
 | 
			
		||||
        <div class="col-md-6">
 | 
			
		||||
          <ul class="list-group list-group-flush">
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>Name: {{ account?.vcard?.fn[0].value }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>Phone Number: {{ account?.vcard?.tel[0].value }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>Account Type: {{ account?.type }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>Gender: {{ account?.gender }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>Age: {{ account?.age }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
          </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-md-6">
 | 
			
		||||
          <ul class="list-group list-group-flush">
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>Bio: {{ account?.products }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>Business Category: {{ account?.category }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>User Location: {{ account?.location?.area_name }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>Location: {{ account?.location?.area }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li class="list-group-item">
 | 
			
		||||
              <span>Location Type: {{ account?.location?.area_type }}</span>
 | 
			
		||||
            </li>
 | 
			
		||||
          </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
@ -0,0 +1,24 @@
 | 
			
		||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { AccountHistoryComponent } from './account-history.component';
 | 
			
		||||
 | 
			
		||||
describe('AccountHistoryComponent', () => {
 | 
			
		||||
  let component: AccountHistoryComponent;
 | 
			
		||||
  let fixture: ComponentFixture<AccountHistoryComponent>;
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    await TestBed.configureTestingModule({
 | 
			
		||||
      declarations: [AccountHistoryComponent],
 | 
			
		||||
    }).compileComponents();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    fixture = TestBed.createComponent(AccountHistoryComponent);
 | 
			
		||||
    component = fixture.componentInstance;
 | 
			
		||||
    fixture.detectChanges();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should create', () => {
 | 
			
		||||
    expect(component).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -0,0 +1,38 @@
 | 
			
		||||
import {
 | 
			
		||||
  Component,
 | 
			
		||||
  OnInit,
 | 
			
		||||
  ChangeDetectionStrategy,
 | 
			
		||||
  Input,
 | 
			
		||||
  Output,
 | 
			
		||||
  EventEmitter,
 | 
			
		||||
  SimpleChanges,
 | 
			
		||||
  OnChanges,
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
const vCard = require('vcard-parser');
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-account-history',
 | 
			
		||||
  templateUrl: './account-history.component.html',
 | 
			
		||||
  styleUrls: ['./account-history.component.scss'],
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush,
 | 
			
		||||
})
 | 
			
		||||
export class AccountHistoryComponent implements OnInit, OnChanges {
 | 
			
		||||
  @Input() account;
 | 
			
		||||
 | 
			
		||||
  @Output() closeWindow: EventEmitter<any> = new EventEmitter<any>();
 | 
			
		||||
 | 
			
		||||
  constructor() {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {}
 | 
			
		||||
 | 
			
		||||
  ngOnChanges(changes: SimpleChanges): void {
 | 
			
		||||
    if (this.account) {
 | 
			
		||||
      this.account.vcard = vCard.parse(atob(this.account.vcard));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  close(): void {
 | 
			
		||||
    this.account = null;
 | 
			
		||||
    this.closeWindow.emit(this.account);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -24,6 +24,7 @@ import { ReactiveFormsModule } from '@angular/forms';
 | 
			
		||||
import { AccountSearchComponent } from './account-search/account-search.component';
 | 
			
		||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
 | 
			
		||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
 | 
			
		||||
import { AccountHistoryComponent } from './account-history/account-history.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
@ -31,7 +32,9 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
 | 
			
		||||
    AccountDetailsComponent,
 | 
			
		||||
    CreateAccountComponent,
 | 
			
		||||
    AccountSearchComponent,
 | 
			
		||||
    AccountHistoryComponent,
 | 
			
		||||
  ],
 | 
			
		||||
  exports: [AccountHistoryComponent],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
    AccountsRoutingModule,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								src/app/shared/_pipes/signature-user.pipe.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/app/shared/_pipes/signature-user.pipe.spec.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
import { SignatureUserPipe } from './signature-user.pipe';
 | 
			
		||||
 | 
			
		||||
describe('SignatureUserPipe', () => {
 | 
			
		||||
  it('create an instance', () => {
 | 
			
		||||
    const pipe = new SignatureUserPipe();
 | 
			
		||||
    expect(pipe).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										20
									
								
								src/app/shared/_pipes/signature-user.pipe.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/app/shared/_pipes/signature-user.pipe.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
import { Pipe, PipeTransform } from '@angular/core';
 | 
			
		||||
import * as openpgp from 'openpgp';
 | 
			
		||||
import { asciiToHex } from '@app/_helpers';
 | 
			
		||||
import { KeystoreService } from '@app/_services';
 | 
			
		||||
 | 
			
		||||
@Pipe({
 | 
			
		||||
  name: 'signatureUser',
 | 
			
		||||
})
 | 
			
		||||
export class SignatureUserPipe implements PipeTransform {
 | 
			
		||||
  async transform(armoredSignature: string, ...args: unknown[]): Promise<string> {
 | 
			
		||||
    const keystore = await KeystoreService.getKeystore();
 | 
			
		||||
    const signature = await openpgp.signature.readArmored(armoredSignature);
 | 
			
		||||
    const keyId = asciiToHex(signature.packets[0].issuerKeyId.bytes);
 | 
			
		||||
    const pubKey = keystore.getPublicKeyForId(keyId);
 | 
			
		||||
    if (pubKey) {
 | 
			
		||||
      return pubKey.users[0].userId.userid;
 | 
			
		||||
    }
 | 
			
		||||
    return '';
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -13,6 +13,7 @@ import { MatDialogModule } from '@angular/material/dialog';
 | 
			
		||||
import { SafePipe } from '@app/shared/_pipes/safe.pipe';
 | 
			
		||||
import { NetworkStatusComponent } from './network-status/network-status.component';
 | 
			
		||||
import { UnixDatePipe } from './_pipes/unix-date.pipe';
 | 
			
		||||
import { SignatureUserPipe } from './_pipes/signature-user.pipe';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
@ -26,6 +27,7 @@ import { UnixDatePipe } from './_pipes/unix-date.pipe';
 | 
			
		||||
    SafePipe,
 | 
			
		||||
    NetworkStatusComponent,
 | 
			
		||||
    UnixDatePipe,
 | 
			
		||||
    SignatureUserPipe,
 | 
			
		||||
  ],
 | 
			
		||||
  exports: [
 | 
			
		||||
    TopbarComponent,
 | 
			
		||||
@ -36,6 +38,7 @@ import { UnixDatePipe } from './_pipes/unix-date.pipe';
 | 
			
		||||
    SafePipe,
 | 
			
		||||
    NetworkStatusComponent,
 | 
			
		||||
    UnixDatePipe,
 | 
			
		||||
    SignatureUserPipe,
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [CommonModule, RouterModule, MatIconModule, MatDialogModule],
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user