Fetch data from cic meta and patch to user details.

This commit is contained in:
Spencer Ofwiti 2021-02-23 15:32:02 +03:00
parent 3286c1df82
commit ef1999dc0d
9 changed files with 120 additions and 110 deletions

View File

@ -113,8 +113,7 @@
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json",
"tsconfig.worker.json"
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"

View File

@ -4,11 +4,11 @@ import {Observable, of, throwError} from 'rxjs';
import {delay, dematerialize, materialize, mergeMap} from 'rxjs/operators';
const accounts = [
{id: 1, name: 'John Doe', phone: '+25412345678', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'user', created: '08/16/2020', balance: '12987', failedPinAttempts: 1, status: 'approved', bio: 'Bodaboda', category: 'transport', gender: 'male', location: 'Bofu', token: 'RSV', referrer: 'Jane Buck'},
{id: 2, name: 'Jane Buck', phone: '+25412341234', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'vendor', created: '04/02/2020', balance: '56281', failedPinAttempts: 0, status: 'approved', bio: 'Groceries', category: 'food/water', gender: 'female', location: 'Lindi', token: 'ERN', referrer: ''},
{id: 3, name: 'Mc Donald', phone: '+25498765432', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'group', created: '11/16/2020', balance: '450', failedPinAttempts: 2, status: 'unapproved', bio: 'Food', category: 'food/water', gender: 'male', location: 'Miyani', token: 'RSV', referrer: 'Hera Cles'},
{id: 4, name: 'Hera Cles', phone: '+25498769876', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'user', created: '05/28/2020', balance: '5621', failedPinAttempts: 3, status: 'approved', bio: 'Shop', category: 'shop', gender: 'female', location: 'Kayaba', token: 'BRT', referrer: 'Jane Buck'},
{id: 5, name: 'Silver Fia', phone: '+25462518374', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'tokenAgent', created: '10/10/2020', balance: '817', failedPinAttempts: 0, status: 'unapproved', bio: 'Electronics', category: 'shop', gender: 'male', location: 'Mkanyeni', token: 'RSV', referrer: 'John Doe'},
{id: 1, name: 'John Doe', phone: '+25412345678', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'user', age: 43, created: '08/16/2020', balance: '12987', failedPinAttempts: 1, status: 'active', bio: 'Bodaboda', category: 'transport', gender: 'male', location: 'Bofu', locationType: 'Rural', token: 'RSV', referrer: 'Jane Buck'},
{id: 2, name: 'Jane Buck', phone: '+25412341234', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'vendor', age: 25, created: '04/02/2020', balance: '56281', failedPinAttempts: 0, status: 'active', bio: 'Groceries', category: 'food/water', gender: 'female', location: 'Lindi', locationType: 'Urban', token: 'ERN', referrer: ''},
{id: 3, name: 'Mc Donald', phone: '+25498765432', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'group', age: 31, created: '11/16/2020', balance: '450', failedPinAttempts: 2, status: 'blocked', bio: 'Food', category: 'food/water', gender: 'male', location: 'Miyani', locationType: 'Rural', token: 'RSV', referrer: 'Hera Cles'},
{id: 4, name: 'Hera Cles', phone: '+25498769876', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'user', age: 38, created: '05/28/2020', balance: '5621', failedPinAttempts: 3, status: 'active', bio: 'Shop', category: 'shop', gender: 'female', location: 'Kayaba', locationType: 'Urban', token: 'BRT', referrer: 'Jane Buck'},
{id: 5, name: 'Silver Fia', phone: '+25462518374', address: '0xc86ff893ac40d3950b4d5f94a9b837258b0a9865', type: 'tokenAgent', age: 19, created: '10/10/2020', balance: '817', failedPinAttempts: 0, status: 'blocked', bio: 'Electronics', category: 'shop', gender: 'male', location: 'Mkanyeni', locationType: 'Rural', token: 'RSV', referrer: 'John Doe'},
];
const actions = [

View File

@ -1,9 +1,9 @@
import { Injectable } from '@angular/core';
import {Injectable} from '@angular/core';
import {BehaviorSubject, Observable} from 'rxjs';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {environment} from '@src/environments/environment';
import {first} from 'rxjs/operators';
import { ArgPair, Envelope, Syncable } from '@src/assets/js/cic-meta/sync.js';
import {ArgPair, Envelope, Syncable} from '@src/assets/js/cic-meta/sync.js';
import {MutableKeyStore, MutablePgpKeyStore, PGPSigner, Signer} from '@app/_helpers';
import {User} from 'cic-client-meta';
@ -11,8 +11,8 @@ import {User} from 'cic-client-meta';
providedIn: 'root'
})
export class UserService {
headers: HttpHeaders = new HttpHeaders({'x-cic-automerge': 'client'});
keystore: MutableKeyStore = new MutablePgpKeyStore();
syncableAccount: Syncable;
signer: Signer = new PGPSigner(this.keystore);
accounts: any = '';
@ -34,33 +34,14 @@ export class UserService {
return this.http.get(`${environment.cicUssdUrl}/pin`, { params });
}
createAccount(accountType: string, idNumber: string, phoneNumber: string, givenName: string, surname: string, directoryEntry: string,
location: string, gender: string, referrer: string, businessCategory: string): Observable<any> {
console.log(accountType);
return this.http.post(
`${environment.cicUssdUrl}/user`,
{
accountType: accountType,
idNumber: idNumber,
phone: phoneNumber,
givenName: givenName,
surname: surname,
directoryEntry: directoryEntry,
location: location,
gender: gender,
referrer: referrer,
businessCategory: businessCategory
}
);
}
async changeAccountInfo(address: string, status: string, name: string, phoneNumber: string, type: string, token: string,
async changeAccountInfo(address: string, status: string, name: string, phoneNumber: string, age: string, type: string, token: string,
failedPinAttempts: string, bio: string, gender: string, businessCategory: string, userLocation: string,
location: string, referrer: string): Promise<any> {
location: string, locationType: string, referrer: string): Promise<any> {
const accountDetails = {
status,
name,
phoneNumber,
age,
type,
token,
failedPinAttempts,
@ -69,31 +50,31 @@ export class UserService {
businessCategory,
userLocation,
location,
locationType,
referrer
};
const accountKey = await User.toKey(address);
const headers = new HttpHeaders({'x-cic-automerge': 'client'});
this.http.get(`${environment.cicMetaUrl}/${accountKey}`, { headers }).pipe(first()).subscribe(async res => {
this.syncableAccount = Envelope.fromJSON(res).unwrap();
this.http.get<JSON>(`${environment.cicMetaUrl}/${accountKey}`, { headers: this.headers }).pipe(first()).subscribe(async res => {
const syncableAccount: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
let update = [];
for (const prop in accountDetails) {
update.push(new ArgPair(prop, accountDetails[prop]));
}
this.syncableAccount.update(update, 'client-branch');
await this.updateMeta(accountKey, headers);
syncableAccount.update(update, 'client-branch');
await this.updateMeta(syncableAccount, accountKey, this.headers);
}, async error => {
console.error('There is an error!', error);
const refName = accountKey + ':cic.person';
this.syncableAccount = new Syncable(refName, accountDetails);
await this.updateMeta(accountKey, headers);
const syncableAccount: Syncable = new Syncable(refName, accountDetails);
await this.updateMeta(syncableAccount, accountKey, this.headers);
});
return accountKey;
}
async updateMeta(accountKey: string, headers: HttpHeaders): Promise<any> {
const envelope = await this.wrap(this.syncableAccount , this.signer);
async updateMeta(syncableAccount: Syncable, accountKey: string, headers: HttpHeaders): Promise<any> {
const envelope = await this.wrap(syncableAccount , this.signer);
const reqBody = envelope.toJSON();
this.http.put(`${environment.cicMetaUrl}/${accountKey}`, { data: reqBody }, { headers }).pipe(first()).subscribe(res => {
this.http.put(`${environment.cicMetaUrl}/${accountKey}`, reqBody , { headers }).pipe(first()).subscribe(res => {
console.log(res);
});
}
@ -146,11 +127,13 @@ export class UserService {
return this.http.post(`${environment.cicCacheUrl}/staff/${id}`, {accountType: type});
}
getAccountDetailsFromMeta(userKey: string): Observable<any> {
return this.http.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers });
}
getUser(userKey: string): any {
const headers = new HttpHeaders({'x-cic-automerge': 'client'});
this.http.get(`${environment.cicMetaUrl}/${userKey}`, { headers }).pipe(first()).subscribe(async res => {
const fetchedAccount = Envelope.fromJSON(res).unwrap();
return fetchedAccount.m.data;
this.http.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers }).pipe(first()).subscribe(async res => {
return Envelope.fromJSON(JSON.stringify(res)).unwrap();
});
}

View File

@ -24,7 +24,7 @@
</h3>
<span class="ml-auto"><strong>Balance:</strong> {{account?.balance}} RCU</span>
<span class="ml-2"><strong>Created:</strong> {{account?.created}}</span>
<span class="ml-2"><strong>Address:</strong> {{account?.address}}</span>
<span class="ml-2"><strong>Address:</strong><a href="{{bloxbergLink}}" target="_blank"> {{account?.address}} </a></span>
</div>
</div>
<app-disbursement *ngIf="isDisbursing" (cancelDisbursmentEvent)="addTransfer()" [account]="account">
@ -56,8 +56,8 @@
<mat-label> STATUS </mat-label>
<mat-select id="status" [(value)]="account.status" formControlName="status"
[errorStateMatcher]="matcher">
<mat-option value="unapproved">Unapproved</mat-option>
<mat-option value="approved">Approved</mat-option>
<mat-option value="blocked">Blocked</mat-option>
<mat-option value="active">Active</mat-option>
</mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.status.errors">Status is required.</mat-error>
</mat-form-field>
@ -81,6 +81,15 @@
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Age: </mat-label>
<input matInput type="text" id="age" placeholder="{{account?.age}}"
value="{{account?.age}}" formControlName="age" [errorStateMatcher]="matcher">
<mat-error *ngIf="submitted && accountInfoFormStub.age.errors">Age is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label> ACCOUNT TYPE: </mat-label>
@ -196,6 +205,20 @@
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label> LOCATION TYPE: </mat-label>
<mat-select id="locationType" [(value)]="account.locationType" formControlName="locationType"
[errorStateMatcher]="matcher">
<mat-option value="Urban"> URBAN </mat-option>
<mat-option value="Periurban"> PERIURBAN </mat-option>
<mat-option value="Rural"> RURAL </mat-option>
<mat-option value="Other"> OTHER </mat-option>
</mat-select>
<mat-error *ngIf="submitted && accountInfoFormStub.locationType.errors">Location Type is required.</mat-error>
</mat-form-field>
</div>
<div class="col-md-6 col-lg-4">
<mat-form-field appearance="outline">
<mat-label>Referred By: </mat-label>
@ -256,10 +279,10 @@
<td>{{account?.type}}</td>
<td>{{account?.created}}</td>
<td>
<span *ngIf="account?.status === 'approved'" class="badge badge-success badge-pill">
<span *ngIf="account?.status === 'active'" class="badge badge-success badge-pill">
{{account?.status}}
</span>
<span *ngIf="account?.status === 'unapproved'" class="badge badge-danger badge-pill">
<span *ngIf="account?.status === 'blocked'" class="badge badge-danger badge-pill">
{{account?.status}}
</span>
</td>

View File

@ -8,6 +8,8 @@ import {ActivatedRoute, Params, Router} from '@angular/router';
import {first} from 'rxjs/operators';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {CustomErrorStateMatcher} from '@app/_helpers';
import {User} from 'cic-client-meta';
import {Envelope} from '@src/assets/js/cic-meta/sync';
@Component({
selector: 'app-account-details',
@ -32,6 +34,7 @@ export class AccountDetailsComponent implements OnInit {
accountInfoForm: FormGroup;
account: any;
metaAccount: any;
accounts: any[] = [];
accountsType = 'all';
initialSelection = [];
@ -46,6 +49,7 @@ export class AccountDetailsComponent implements OnInit {
transactionsType = 'all';
matcher = new CustomErrorStateMatcher();
submitted: boolean = false;
bloxbergLink: string;
constructor(
private formBuilder: FormBuilder,
@ -59,6 +63,7 @@ export class AccountDetailsComponent implements OnInit {
status: ['', Validators.required],
name: ['', Validators.required],
phoneNumber: ['', Validators.required],
age: ['', Validators.required],
type: ['', Validators.required],
token: ['', Validators.required],
failedPinAttempts: ['', Validators.required],
@ -67,30 +72,56 @@ export class AccountDetailsComponent implements OnInit {
businessCategory: ['', Validators.required],
userLocation: ['', Validators.required],
location: ['', Validators.required],
locationType: ['', Validators.required],
referrer: ['', Validators.required]
});
this.route.paramMap.subscribe((params: Params) => {
this.userService.getAccountById(params.get('id')).pipe(first()).subscribe(account => {
this.userService.getAccountById(params.get('id')).pipe(first()).subscribe(async account => {
this.account = account;
this.userService.getAccountDetailsFromMeta(await User.toKey(account.address)).pipe(first()).subscribe(res => {
this.metaAccount = Envelope.fromJSON(JSON.stringify(res)).unwrap();
const accountInfo = this.metaAccount.m.data;
console.log(accountInfo);
this.accountInfoForm.patchValue({
status: accountInfo.status,
name: accountInfo.name,
phoneNumber: accountInfo.phoneNumber,
age: accountInfo.age,
type: accountInfo.type,
token: accountInfo.token,
failedPinAttempts: accountInfo.failedPinAttempts,
bio: accountInfo.bio,
gender: accountInfo.gender,
businessCategory: accountInfo.businessCategory,
userLocation: accountInfo.userLocation,
location: accountInfo.location,
locationType: accountInfo.locationType,
referrer: accountInfo.referrer
});
}, error => {
this.accountInfoForm.patchValue({
status: account.status,
name: account.name,
phoneNumber: account.phone,
age: account.age,
type: account.type,
token: account.token,
failedPinAttempts: account.failedPinAttempts,
bio: account.bio,
gender: account.gender,
businessCategory: account.category,
// userLocation: account.userLocation,
location: account.location,
locationType: account.locationType,
referrer: account.referrer
});
});
this.bloxbergLink = 'https://blockexplorer.bloxberg.org/address/' + this.account.address + '/transactions';
this.userService.getHistoryByUser(this.account?.id).pipe(first()).subscribe(history => {
this.historyDataSource = new MatTableDataSource<any>(history);
this.historyDataSource.paginator = this.historyTablePaginator;
this.historyDataSource.sort = this.historyTableSort;
});
this.accountInfoForm.patchValue({
status: account.status,
name: account.name,
phoneNumber: account.phone,
type: account.type,
token: account.token,
failedPinAttempts: account.failedPinAttempts,
bio: account.bio,
gender: account.gender,
businessCategory: account.category,
// userLocation: account.userLocation,
location: account.location,
referrer: account.referrer
});
});
});
this.userService.getAccounts();
@ -141,15 +172,6 @@ export class AccountDetailsComponent implements OnInit {
}
viewAccount(account): void {
(function smoothscroll(): void {
const currentScroll = document.documentElement.scrollTop || document.body.scrollTop;
if (currentScroll > 0) {
window.requestAnimationFrame(smoothscroll);
window.scrollTo(0, currentScroll - (currentScroll / 8));
}
})();
window.scrollTo(0, 0);
document.body.scrollTop = document.documentElement.scrollTop = 0;
this.router.navigateByUrl(`/accounts/${account.id}`);
}
@ -163,6 +185,7 @@ export class AccountDetailsComponent implements OnInit {
this.accountInfoFormStub.status.value,
this.accountInfoFormStub.name.value,
this.accountInfoFormStub.phoneNumber.value,
this.accountInfoFormStub.age.value,
this.accountInfoFormStub.type.value,
this.accountInfoFormStub.token.value,
this.accountInfoFormStub.failedPinAttempts.value,
@ -171,6 +194,7 @@ export class AccountDetailsComponent implements OnInit {
this.accountInfoFormStub.businessCategory.value,
this.accountInfoFormStub.userLocation.value,
this.accountInfoFormStub.location.value,
this.accountInfoFormStub.locationType.value,
this.accountInfoFormStub.referrer.value,
).then(res => console.log(res));
this.submitted = false;
@ -203,8 +227,4 @@ export class AccountDetailsComponent implements OnInit {
console.log(res);
});
}
setDefault(formStub: any, name: string, value: string): void {
formStub[name].value = value;
}
}

View File

@ -47,20 +47,20 @@ export class CreateAccountComponent implements OnInit {
onSubmit(): void {
this.submitted = true;
if (this.createForm.invalid) { return; }
this.userService.createAccount(
this.createFormStub.accountType.value,
this.createFormStub.idNumber.value,
this.createFormStub.phoneNumber.value,
this.createFormStub.givenName.value,
this.createFormStub.surname.value,
this.createFormStub.directoryEntry.value,
this.createFormStub.location.value,
this.createFormStub.gender.value,
this.createFormStub.referrer.value,
this.createFormStub.businessCategory.value,
).pipe(first()).subscribe(res => {
console.log(res);
});
// this.userService.createAccount(
// this.createFormStub.accountType.value,
// this.createFormStub.idNumber.value,
// this.createFormStub.phoneNumber.value,
// this.createFormStub.givenName.value,
// this.createFormStub.surname.value,
// this.createFormStub.directoryEntry.value,
// this.createFormStub.location.value,
// this.createFormStub.gender.value,
// this.createFormStub.referrer.value,
// this.createFormStub.businessCategory.value,
// ).pipe(first()).subscribe(res => {
// console.log(res);
// });
// this.router.navigateByUrl(`/accounts`);
this.submitted = false;
}

View File

@ -5,7 +5,7 @@ export const environment = {
publicKeysUrl: 'http://localhost:8000',
cicCacheUrl: 'http://localhost:63313',
cicScriptsUrl: 'http://localhost:9999',
web3Provider: 'ws://localhost:8546',
web3Provider: 'ws://localhost:63546',
cicUssdUrl: 'http://localhost:63315',
cicEthUrl: 'http://localhost:63314',
contractAddress: '0x35Ef60C4624Eaf6AeEBeBec9Ddd3CBA6b24C4b17',

View File

@ -9,7 +9,7 @@ export const environment = {
publicKeysUrl: 'http://localhost:8000',
cicCacheUrl: 'http://localhost:63313',
cicScriptsUrl: 'http://localhost:9999',
web3Provider: 'ws://localhost:8546',
web3Provider: 'ws://localhost:63546',
cicUssdUrl: 'http://localhost:63315',
cicEthUrl: 'http://localhost:63314',
contractAddress: '0x35Ef60C4624Eaf6AeEBeBec9Ddd3CBA6b24C4b17',

View File

@ -1,15 +0,0 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/worker",
"lib": [
"es2018",
"webworker"
],
"types": []
},
"include": [
"src/**/*.worker.ts"
]
}