Improve data load process to occur on app load.
This commit is contained in:
@@ -9,3 +9,4 @@ export * from '@app/_helpers/mock-backend';
|
||||
export * from '@app/_helpers/read-csv';
|
||||
export * from '@app/_helpers/schema-validation';
|
||||
export * from '@app/_helpers/sync';
|
||||
export * from '@app/_helpers/online-status';
|
||||
|
||||
15
src/app/_helpers/online-status.ts
Normal file
15
src/app/_helpers/online-status.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
const apiUrls = [
|
||||
'https://api.coindesk.com/v1/bpi/currentprice.json',
|
||||
'https://dog.ceo/api/breeds/image/random',
|
||||
];
|
||||
|
||||
async function checkOnlineStatus(): Promise<boolean> {
|
||||
try {
|
||||
const online = await fetch(apiUrls[Math.floor(Math.random() * apiUrls.length)]);
|
||||
return online.status >= 200 && online.status < 300;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export { checkOnlineStatus };
|
||||
16
src/app/_interceptors/connection.interceptor.spec.ts
Normal file
16
src/app/_interceptors/connection.interceptor.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ConnectionInterceptor } from './connection.interceptor';
|
||||
|
||||
describe('ConnectionInterceptor', () => {
|
||||
beforeEach(() =>
|
||||
TestBed.configureTestingModule({
|
||||
providers: [ConnectionInterceptor],
|
||||
})
|
||||
);
|
||||
|
||||
it('should be created', () => {
|
||||
const interceptor: ConnectionInterceptor = TestBed.inject(ConnectionInterceptor);
|
||||
expect(interceptor).toBeTruthy();
|
||||
});
|
||||
});
|
||||
42
src/app/_interceptors/connection.interceptor.ts
Normal file
42
src/app/_interceptors/connection.interceptor.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
// Core imports
|
||||
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
// Third party imports
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
// Application imports
|
||||
import { LoggingService } from '@app/_services/logging.service';
|
||||
import { checkOnlineStatus } from '@app/_helpers';
|
||||
|
||||
/** Intercepts and handles of events from outgoing HTTP request. */
|
||||
@Injectable()
|
||||
export class ConnectionInterceptor implements HttpInterceptor {
|
||||
/**
|
||||
* Initialization of the connection interceptor.
|
||||
*
|
||||
* @param loggingService - A service that provides logging capabilities.
|
||||
*/
|
||||
constructor(private loggingService: LoggingService) {}
|
||||
|
||||
/**
|
||||
* Intercepts HTTP requests.
|
||||
*
|
||||
* @param request - An outgoing HTTP request with an optional typed body.
|
||||
* @param next - The next HTTP handler or the outgoing request dispatcher.
|
||||
* @returns The forwarded request.
|
||||
*/
|
||||
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
||||
checkOnlineStatus().then((online) => {
|
||||
if (!online) {
|
||||
this.loggingService.sendErrorLevelMessage('No internet connection on device!', this, {
|
||||
error: `NetworkError when attempting to fetch resource ${request.url}.`,
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
return next.handle(request);
|
||||
}
|
||||
});
|
||||
return next.handle(request);
|
||||
}
|
||||
}
|
||||
@@ -59,9 +59,10 @@ export class ErrorInterceptor implements HttpInterceptor {
|
||||
this.router.navigateByUrl('/auth').then();
|
||||
break;
|
||||
case 403: // forbidden
|
||||
this.errorDialogService.openDialog(
|
||||
{ message: 'Access to resource is not allowed (Error 403)'})
|
||||
//alert('Access to resource is not allowed!');
|
||||
this.errorDialogService.openDialog({
|
||||
message: 'Access to resource is not allowed (Error 403)',
|
||||
});
|
||||
// alert('Access to resource is not allowed!');
|
||||
break;
|
||||
}
|
||||
// Return an observable with a user-facing error message.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from '@app/_interceptors/connection.interceptor';
|
||||
export * from '@app/_interceptors/error.interceptor';
|
||||
export * from '@app/_interceptors/http-config.interceptor';
|
||||
export * from '@app/_interceptors/logging.interceptor';
|
||||
|
||||
@@ -5,7 +5,6 @@ import { environment } from '@src/environments/environment';
|
||||
import { LoggingService } from '@app/_services/logging.service';
|
||||
import { MutableKeyStore } from '@app/_pgp';
|
||||
import { ErrorDialogService } from '@app/_services/error-dialog.service';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { HttpError, rejectBody } from '@app/_helpers/global-error-handler';
|
||||
import { Staff } from '@app/_models';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
@@ -23,7 +22,6 @@ export class AuthService {
|
||||
trustedUsersSubject: Observable<Array<Staff>> = this.trustedUsersList.asObservable();
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
private loggingService: LoggingService,
|
||||
private errorDialogService: ErrorDialogService
|
||||
) {}
|
||||
@@ -48,7 +46,7 @@ export class AuthService {
|
||||
}
|
||||
|
||||
getWithToken(): Promise<boolean> {
|
||||
const sessionToken = this.getSessionToken()
|
||||
const sessionToken = this.getSessionToken();
|
||||
const headers = {
|
||||
Authorization: 'Bearer ' + sessionToken,
|
||||
'Content-Type': 'application/json;charset=utf-8',
|
||||
@@ -94,33 +92,32 @@ export class AuthService {
|
||||
async login(): Promise<boolean> {
|
||||
if (this.getSessionToken()) {
|
||||
sessionStorage.removeItem(btoa('CICADA_SESSION_TOKEN'));
|
||||
}
|
||||
}
|
||||
const o = await this.getChallenge();
|
||||
|
||||
const r = await signChallenge(
|
||||
o.challenge,
|
||||
o.realm,
|
||||
environment.cicMetaUrl,
|
||||
this.mutableKeyStore
|
||||
o.challenge,
|
||||
o.realm,
|
||||
environment.cicMetaUrl,
|
||||
this.mutableKeyStore
|
||||
);
|
||||
|
||||
const tokenResponse = await this.sendSignedChallenge(r)
|
||||
.then((response) => {
|
||||
const token = response.headers.get('Token');
|
||||
if (token) {
|
||||
return token;
|
||||
}
|
||||
if (response.status === 401) {
|
||||
throw new HttpError('You are not authorized to use this system', response.status);
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new HttpError('Unknown error from authentication server', response.status);
|
||||
}
|
||||
const tokenResponse = await this.sendSignedChallenge(r).then((response) => {
|
||||
const token = response.headers.get('Token');
|
||||
if (token) {
|
||||
return token;
|
||||
}
|
||||
if (response.status === 401) {
|
||||
throw new HttpError('You are not authorized to use this system', response.status);
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new HttpError('Unknown error from authentication server', response.status);
|
||||
}
|
||||
});
|
||||
|
||||
if (tokenResponse) {
|
||||
this.setSessionToken(tokenResponse);
|
||||
//this.setState('Click button to log in');
|
||||
// this.setState('Click button to log in');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -4,7 +4,6 @@ import { TransactionHelper } from '@cicnet/cic-client';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { TransactionService } from '@app/_services/transaction.service';
|
||||
import { environment } from '@src/environments/environment';
|
||||
import { LoggingService } from '@app/_services/logging.service';
|
||||
import { RegistryService } from '@app/_services/registry.service';
|
||||
import { Web3Service } from '@app/_services/web3.service';
|
||||
|
||||
@@ -15,17 +14,9 @@ export class BlockSyncService {
|
||||
readyStateTarget: number = 2;
|
||||
readyState: number = 0;
|
||||
|
||||
constructor(
|
||||
private transactionService: TransactionService,
|
||||
private loggingService: LoggingService
|
||||
) {}
|
||||
|
||||
async init(): Promise<void> {
|
||||
await this.transactionService.init();
|
||||
}
|
||||
constructor(private transactionService: TransactionService) {}
|
||||
|
||||
async blockSync(address: string = null, offset: number = 0, limit: number = 100): Promise<void> {
|
||||
this.transactionService.resetTransactionsList();
|
||||
const settings: Settings = new Settings(this.scan);
|
||||
const readyStateElements: { network: number } = { network: 2 };
|
||||
settings.w3.provider = environment.web3Provider;
|
||||
|
||||
@@ -35,6 +35,7 @@ export class LocationService {
|
||||
return queriedAreaName;
|
||||
}
|
||||
}
|
||||
return 'other';
|
||||
}
|
||||
|
||||
getAreaTypes(): void {
|
||||
@@ -54,5 +55,6 @@ export class LocationService {
|
||||
return queriedAreaType;
|
||||
}
|
||||
}
|
||||
return 'other';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,6 @@ import { NGXLogger } from 'ngx-logger';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class LoggingService {
|
||||
env: string;
|
||||
canDebug: boolean;
|
||||
|
||||
constructor(private logger: NGXLogger) {
|
||||
// TRACE|DEBUG|INFO|LOG|WARN|ERROR|FATAL|OFF
|
||||
if (isDevMode()) {
|
||||
|
||||
@@ -22,9 +22,7 @@ export class TokenService {
|
||||
|
||||
async init(): Promise<void> {
|
||||
this.registry = await RegistryService.getRegistry();
|
||||
this.tokenRegistry = new TokenRegistry(
|
||||
await this.registry.getContractAddressByName('TokenRegistry')
|
||||
);
|
||||
this.tokenRegistry = await RegistryService.getTokenRegistry();
|
||||
this.load.next(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import { add0x, fromHex, strip0x, toHex } from '@src/assets/js/ethtx/dist/hex';
|
||||
import { Tx } from '@src/assets/js/ethtx/dist';
|
||||
import { toValue } from '@src/assets/js/ethtx/dist/tx';
|
||||
import * as secp256k1 from 'secp256k1';
|
||||
import { AuthService } from '@app/_services/auth.service';
|
||||
import { defaultAccount } from '@app/_models';
|
||||
import { LoggingService } from '@app/_services/logging.service';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
@@ -28,13 +27,11 @@ export class TransactionService {
|
||||
transactions: any[] = [];
|
||||
private transactionList = new BehaviorSubject<any[]>(this.transactions);
|
||||
transactionsSubject = this.transactionList.asObservable();
|
||||
userInfo: any;
|
||||
web3: Web3;
|
||||
registry: CICRegistry;
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
private authService: AuthService,
|
||||
private userService: UserService,
|
||||
private loggingService: LoggingService
|
||||
) {
|
||||
@@ -42,8 +39,6 @@ export class TransactionService {
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
await this.authService.init();
|
||||
await this.userService.init();
|
||||
this.registry = await RegistryService.getRegistry();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,9 @@ import { ArgPair, Envelope, Phone, Syncable, User } from 'cic-client-meta';
|
||||
import { AccountDetails } from '@app/_models';
|
||||
import { LoggingService } from '@app/_services/logging.service';
|
||||
import { TokenService } from '@app/_services/token.service';
|
||||
import { AccountIndex } from '@app/_eth';
|
||||
import { MutableKeyStore, PGPSigner, Signer } from '@app/_pgp';
|
||||
import { RegistryService } from '@app/_services/registry.service';
|
||||
import { CICRegistry } from '@cicnet/cic-client';
|
||||
import { AuthService } from '@app/_services/auth.service';
|
||||
import { personValidation, updateSyncable, vcardValidation } from '@app/_helpers';
|
||||
import { add0x } from '@src/assets/js/ethtx/dist/hex';
|
||||
import { KeystoreService } from '@app/_services/keystore.service';
|
||||
@@ -43,13 +41,10 @@ export class UserService {
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
private loggingService: LoggingService,
|
||||
private tokenService: TokenService,
|
||||
private authService: AuthService
|
||||
private tokenService: TokenService
|
||||
) {}
|
||||
|
||||
async init(): Promise<void> {
|
||||
await this.authService.init();
|
||||
await this.tokenService.init();
|
||||
this.keystore = await KeystoreService.getKeystore();
|
||||
this.signer = new PGPSigner(this.keystore);
|
||||
this.registry = await RegistryService.getRegistry();
|
||||
@@ -203,12 +198,6 @@ export class UserService {
|
||||
}
|
||||
|
||||
async loadAccounts(limit: number = 100, offset: number = 0): Promise<void> {
|
||||
this.resetAccountsList();
|
||||
// const accountIndexAddress: string = await this.registry.getContractAddressByName(
|
||||
// 'AccountRegistry'
|
||||
// );
|
||||
// const accountIndexQuery = new AccountIndex(accountIndexAddress);
|
||||
// const accountAddresses: Array<string> = await accountIndexQuery.last(limit);
|
||||
try {
|
||||
const accountRegistry = await RegistryService.getAccountRegistry();
|
||||
const accountAddresses: Array<string> = await accountRegistry.last(limit);
|
||||
@@ -271,10 +260,6 @@ export class UserService {
|
||||
this.accountsList.next(this.accounts);
|
||||
}
|
||||
|
||||
searchAccountByName(name: string): any {
|
||||
return;
|
||||
}
|
||||
|
||||
getCategories(): void {
|
||||
this.httpClient
|
||||
.get(`${environment.cicMetaUrl}/categories`)
|
||||
@@ -292,6 +277,7 @@ export class UserService {
|
||||
return queriedCategory;
|
||||
}
|
||||
}
|
||||
return 'other';
|
||||
}
|
||||
|
||||
getAccountTypes(): Observable<any> {
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { ChangeDetectionStrategy, Component, HostListener, OnInit } from '@angular/core';
|
||||
import {
|
||||
AuthService,
|
||||
BlockSyncService,
|
||||
ErrorDialogService,
|
||||
LoggingService,
|
||||
TokenService,
|
||||
TransactionService,
|
||||
UserService,
|
||||
} from '@app/_services';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { filter } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -16,16 +20,20 @@ import { SwUpdate } from '@angular/service-worker';
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
title = 'CICADA';
|
||||
readyStateTarget: number = 3;
|
||||
readyState: number = 0;
|
||||
mediaQuery: MediaQueryList = window.matchMedia('(max-width: 768px)');
|
||||
url: string;
|
||||
accountDetailsRegex = '/accounts/[a-z,A-Z,0-9]{40}';
|
||||
|
||||
constructor(
|
||||
private authService: AuthService,
|
||||
private transactionService: TransactionService,
|
||||
private loggingService: LoggingService,
|
||||
private blockSyncService: BlockSyncService,
|
||||
private errorDialogService: ErrorDialogService,
|
||||
private swUpdate: SwUpdate
|
||||
private loggingService: LoggingService,
|
||||
private tokenService: TokenService,
|
||||
private transactionService: TransactionService,
|
||||
private userService: UserService,
|
||||
private swUpdate: SwUpdate,
|
||||
private router: Router
|
||||
) {
|
||||
this.mediaQuery.addEventListener('change', this.onResize);
|
||||
this.onResize(this.mediaQuery);
|
||||
@@ -33,7 +41,34 @@ export class AppComponent implements OnInit {
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.authService.init();
|
||||
await this.tokenService.init();
|
||||
await this.userService.init();
|
||||
await this.transactionService.init();
|
||||
await this.router.events
|
||||
.pipe(filter((e) => e instanceof NavigationEnd))
|
||||
.forEach(async (routeInfo) => {
|
||||
if (routeInfo instanceof NavigationEnd) {
|
||||
this.url = routeInfo.url;
|
||||
if (!this.url.match(this.accountDetailsRegex) || !this.url.includes('tx')) {
|
||||
await this.blockSyncService.blockSync();
|
||||
}
|
||||
if (!this.url.includes('accounts')) {
|
||||
try {
|
||||
// TODO it feels like this should be in the onInit handler
|
||||
await this.userService.loadAccounts(100);
|
||||
} catch (error) {
|
||||
this.loggingService.sendErrorLevelMessage('Failed to load accounts', this, { error });
|
||||
}
|
||||
}
|
||||
if (!this.url.includes('tokens')) {
|
||||
this.tokenService.load.subscribe(async (status: boolean) => {
|
||||
if (status) {
|
||||
await this.tokenService.getTokens();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
const publicKeys = await this.authService.getPublicKeys();
|
||||
await this.authService.mutableKeyStore.importPublicKey(publicKeys);
|
||||
|
||||
@@ -11,7 +11,12 @@ import { MatTableModule } from '@angular/material/table';
|
||||
import { AuthGuard } from '@app/_guards';
|
||||
import { LoggerModule } from 'ngx-logger';
|
||||
import { environment } from '@src/environments/environment';
|
||||
import { ErrorInterceptor, HttpConfigInterceptor, LoggingInterceptor } from '@app/_interceptors';
|
||||
import {
|
||||
ConnectionInterceptor,
|
||||
ErrorInterceptor,
|
||||
HttpConfigInterceptor,
|
||||
LoggingInterceptor,
|
||||
} from '@app/_interceptors';
|
||||
import { MutablePgpKeyStore } from '@app/_pgp';
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
|
||||
@@ -38,6 +43,7 @@ import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
MockBackendProvider,
|
||||
GlobalErrorHandler,
|
||||
{ provide: ErrorHandler, useClass: GlobalErrorHandler },
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: ConnectionInterceptor, multi: true },
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: HttpConfigInterceptor, multi: true },
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true },
|
||||
|
||||
@@ -3,7 +3,6 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { CustomErrorStateMatcher } from '@app/_helpers';
|
||||
import { AuthService } from '@app/_services';
|
||||
import { ErrorDialogService } from '@app/_services/error-dialog.service';
|
||||
import { LoggingService } from '@app/_services/logging.service';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
@@ -25,7 +24,7 @@ export class AuthComponent implements OnInit {
|
||||
private errorDialogService: ErrorDialogService
|
||||
) {}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
ngOnInit(): void {
|
||||
this.keyForm = this.formBuilder.group({
|
||||
key: ['', Validators.required],
|
||||
});
|
||||
@@ -58,7 +57,7 @@ export class AuthComponent implements OnInit {
|
||||
}
|
||||
} catch (HttpError) {
|
||||
this.errorDialogService.openDialog({
|
||||
message: "Failed to login please try again.",
|
||||
message: 'Failed to login please try again.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +382,11 @@
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="transactionsLoading">
|
||||
<h2 class="text-center"><strong>Loading Transactions!</strong></h2>
|
||||
<mat-progress-bar [mode]="'query'"></mat-progress-bar>
|
||||
</div>
|
||||
|
||||
<table
|
||||
mat-table
|
||||
class="mat-elevation-z10"
|
||||
@@ -491,6 +496,11 @@
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="accountsLoading">
|
||||
<h2 class="text-center"><strong>Loading Accounts!</strong></h2>
|
||||
<mat-progress-bar [mode]="'query'"></mat-progress-bar>
|
||||
</div>
|
||||
|
||||
<mat-table
|
||||
class="mat-elevation-z10"
|
||||
[dataSource]="userDataSource"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
@@ -31,7 +32,7 @@ import { AccountDetails, Transaction } from '@app/_models';
|
||||
styleUrls: ['./account-details.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AccountDetailsComponent implements OnInit {
|
||||
export class AccountDetailsComponent implements OnInit, AfterViewInit {
|
||||
transactionsDataSource: MatTableDataSource<any>;
|
||||
transactionsDisplayedColumns: Array<string> = ['sender', 'recipient', 'value', 'created', 'type'];
|
||||
transactionsDefaultPageSize: number = 10;
|
||||
@@ -68,6 +69,8 @@ export class AccountDetailsComponent implements OnInit {
|
||||
category: string;
|
||||
area: string;
|
||||
areaType: string;
|
||||
accountsLoading: boolean = true;
|
||||
transactionsLoading: boolean = true;
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
@@ -103,10 +106,7 @@ export class AccountDetailsComponent implements OnInit {
|
||||
location: ['', Validators.required],
|
||||
locationType: ['', Validators.required],
|
||||
});
|
||||
await this.blockSyncService.init();
|
||||
await this.tokenService.init();
|
||||
await this.transactionService.init();
|
||||
await this.userService.init();
|
||||
this.transactionService.resetTransactionsList();
|
||||
await this.blockSyncService.blockSync(this.accountAddress);
|
||||
this.userService.resetAccountsList();
|
||||
(await this.userService.getAccountByAddress(this.accountAddress, 100)).subscribe(
|
||||
@@ -114,7 +114,6 @@ export class AccountDetailsComponent implements OnInit {
|
||||
if (res !== undefined) {
|
||||
this.account = res;
|
||||
this.cdr.detectChanges();
|
||||
this.loggingService.sendInfoLevelMessage(this.account);
|
||||
this.locationService.areaNamesSubject.subscribe((response) => {
|
||||
this.area = this.locationService.getAreaNameByLocation(
|
||||
this.account.location.area_name,
|
||||
@@ -158,6 +157,9 @@ export class AccountDetailsComponent implements OnInit {
|
||||
this.userDataSource.paginator = this.userTablePaginator;
|
||||
this.userDataSource.sort = this.userTableSort;
|
||||
this.accounts = accounts;
|
||||
if (accounts.length > 0) {
|
||||
this.accountsLoading = false;
|
||||
}
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
|
||||
@@ -166,6 +168,9 @@ export class AccountDetailsComponent implements OnInit {
|
||||
this.transactionsDataSource.paginator = this.transactionTablePaginator;
|
||||
this.transactionsDataSource.sort = this.transactionTableSort;
|
||||
this.transactions = transactions;
|
||||
if (transactions.length > 0) {
|
||||
this.transactionsLoading = false;
|
||||
}
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
this.userService.getCategories();
|
||||
@@ -199,6 +204,17 @@ export class AccountDetailsComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
if (this.userDataSource) {
|
||||
this.userDataSource.paginator = this.userTablePaginator;
|
||||
this.userDataSource.sort = this.userTableSort;
|
||||
}
|
||||
if (this.transactionsDataSource) {
|
||||
this.transactionsDataSource.paginator = this.transactionTablePaginator;
|
||||
this.transactionsDataSource.sort = this.transactionTableSort;
|
||||
}
|
||||
}
|
||||
|
||||
doTransactionFilter(value: string): void {
|
||||
this.transactionsDataSource.filter = value.trim().toLocaleLowerCase();
|
||||
}
|
||||
|
||||
@@ -13,9 +13,6 @@ import { environment } from '@src/environments/environment';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AccountSearchComponent implements OnInit {
|
||||
nameSearchForm: FormGroup;
|
||||
nameSearchSubmitted: boolean = false;
|
||||
nameSearchLoading: boolean = false;
|
||||
phoneSearchForm: FormGroup;
|
||||
phoneSearchSubmitted: boolean = false;
|
||||
phoneSearchLoading: boolean = false;
|
||||
@@ -29,9 +26,6 @@ export class AccountSearchComponent implements OnInit {
|
||||
private userService: UserService,
|
||||
private router: Router
|
||||
) {
|
||||
this.nameSearchForm = this.formBuilder.group({
|
||||
name: ['', Validators.required],
|
||||
});
|
||||
this.phoneSearchForm = this.formBuilder.group({
|
||||
phoneNumber: ['', Validators.required],
|
||||
});
|
||||
@@ -40,13 +34,8 @@ export class AccountSearchComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.userService.init();
|
||||
}
|
||||
ngOnInit(): void {}
|
||||
|
||||
get nameSearchFormStub(): any {
|
||||
return this.nameSearchForm.controls;
|
||||
}
|
||||
get phoneSearchFormStub(): any {
|
||||
return this.phoneSearchForm.controls;
|
||||
}
|
||||
@@ -54,16 +43,6 @@ export class AccountSearchComponent implements OnInit {
|
||||
return this.addressSearchForm.controls;
|
||||
}
|
||||
|
||||
onNameSearch(): void {
|
||||
this.nameSearchSubmitted = true;
|
||||
if (this.nameSearchForm.invalid) {
|
||||
return;
|
||||
}
|
||||
this.nameSearchLoading = true;
|
||||
this.userService.searchAccountByName(this.nameSearchFormStub.name.value);
|
||||
this.nameSearchLoading = false;
|
||||
}
|
||||
|
||||
async onPhoneSearch(): Promise<void> {
|
||||
this.phoneSearchSubmitted = true;
|
||||
if (this.phoneSearchForm.invalid) {
|
||||
|
||||
@@ -64,6 +64,11 @@
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="loading">
|
||||
<h2 class="text-center"><strong>Loading Accounts!</strong></h2>
|
||||
<mat-progress-bar [mode]="'query'"></mat-progress-bar>
|
||||
</div>
|
||||
|
||||
<mat-table
|
||||
class="mat-elevation-z10"
|
||||
[dataSource]="dataSource"
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { ChangeDetectionStrategy, Component, OnInit, ViewChild } from '@angular/core';
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
@@ -16,7 +22,7 @@ import { AccountDetails } from '@app/_models';
|
||||
styleUrls: ['./accounts.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AccountsComponent implements OnInit {
|
||||
export class AccountsComponent implements OnInit, AfterViewInit {
|
||||
dataSource: MatTableDataSource<any>;
|
||||
accounts: Array<AccountDetails> = [];
|
||||
displayedColumns: Array<string> = ['name', 'phone', 'created', 'balance', 'location'];
|
||||
@@ -25,32 +31,34 @@ export class AccountsComponent implements OnInit {
|
||||
accountsType: string = 'all';
|
||||
accountTypes: Array<string>;
|
||||
tokenSymbol: string;
|
||||
loading: boolean = true;
|
||||
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
|
||||
constructor(
|
||||
private userService: UserService,
|
||||
private loggingService: LoggingService,
|
||||
private userService: UserService,
|
||||
private router: Router,
|
||||
private tokenService: TokenService
|
||||
) {}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.userService.init();
|
||||
await this.tokenService.init();
|
||||
this.userService.accountsSubject.subscribe((accounts) => {
|
||||
this.dataSource = new MatTableDataSource<any>(accounts);
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
this.accounts = accounts;
|
||||
if (accounts.length > 0) {
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
try {
|
||||
// TODO it feels like this should be in the onInit handler
|
||||
await this.userService.loadAccounts(100);
|
||||
} catch (error) {
|
||||
this.loggingService.sendErrorLevelMessage('Failed to load accounts', this, { error });
|
||||
}
|
||||
this.userService.accountsSubject.subscribe((accounts) => {
|
||||
this.dataSource = new MatTableDataSource<any>(accounts);
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
this.accounts = accounts;
|
||||
});
|
||||
this.userService
|
||||
.getAccountTypes()
|
||||
.pipe(first())
|
||||
@@ -62,6 +70,13 @@ export class AccountsComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
if (this.dataSource) {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
}
|
||||
}
|
||||
|
||||
doFilter(value: string): void {
|
||||
this.dataSource.filter = value.trim().toLocaleLowerCase();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
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';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -51,6 +52,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
MatProgressSpinnerModule,
|
||||
ReactiveFormsModule,
|
||||
MatSnackBarModule,
|
||||
MatProgressBarModule,
|
||||
],
|
||||
})
|
||||
export class AccountsModule {}
|
||||
|
||||
@@ -25,8 +25,7 @@ export class CreateAccountComponent implements OnInit {
|
||||
private userService: UserService
|
||||
) {}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.userService.init();
|
||||
ngOnInit(): void {
|
||||
this.createForm = this.formBuilder.group({
|
||||
accountType: ['', Validators.required],
|
||||
idNumber: ['', Validators.required],
|
||||
|
||||
@@ -43,6 +43,11 @@
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="loading">
|
||||
<h2 class="text-center"><strong>Loading Actions!</strong></h2>
|
||||
<mat-progress-bar [mode]="'query'"></mat-progress-bar>
|
||||
</div>
|
||||
|
||||
<mat-table class="mat-elevation-z10" [dataSource]="dataSource" multiTemplateDataRows>
|
||||
<!-- Expand Column -->
|
||||
<ng-container matColumnDef="expand">
|
||||
|
||||
@@ -6,7 +6,7 @@ import { LoggingService, UserService } from '@app/_services';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { exportCsv } from '@app/_helpers';
|
||||
import { Action } from '../../_models';
|
||||
import { Action } from '@app/_models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-admin',
|
||||
@@ -26,20 +26,23 @@ export class AdminComponent implements OnInit {
|
||||
displayedColumns: Array<string> = ['expand', 'user', 'role', 'action', 'status', 'approve'];
|
||||
action: Action;
|
||||
actions: Array<Action>;
|
||||
loading: boolean = true;
|
||||
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
|
||||
constructor(private userService: UserService, private loggingService: LoggingService) {}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.userService.init();
|
||||
ngOnInit(): void {
|
||||
this.userService.getActions();
|
||||
this.userService.actionsSubject.subscribe((actions) => {
|
||||
this.dataSource = new MatTableDataSource<any>(actions);
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
this.actions = actions;
|
||||
if (actions.length > 0) {
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import { MatSortModule } from '@angular/material/sort';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatRippleModule } from '@angular/material/core';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AdminComponent],
|
||||
@@ -29,6 +30,7 @@ import { MatRippleModule } from '@angular/material/core';
|
||||
MatPaginatorModule,
|
||||
MatButtonModule,
|
||||
MatRippleModule,
|
||||
MatProgressBarModule,
|
||||
],
|
||||
})
|
||||
export class AdminModule {}
|
||||
|
||||
@@ -22,10 +22,10 @@ const routes: Routes = [
|
||||
path: 'tokens',
|
||||
loadChildren: () => import('@pages/tokens/tokens.module').then((m) => m.TokensModule),
|
||||
},
|
||||
{
|
||||
path: 'admin',
|
||||
loadChildren: () => import('@pages/admin/admin.module').then((m) => m.AdminModule),
|
||||
},
|
||||
// {
|
||||
// path: 'admin',
|
||||
// loadChildren: () => import('@pages/admin/admin.module').then((m) => m.AdminModule),
|
||||
// },
|
||||
{ path: '**', redirectTo: 'home', pathMatch: 'full' },
|
||||
];
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 mb-2">
|
||||
<div class="card">
|
||||
<mat-card-title class="card-header">
|
||||
@@ -67,6 +68,12 @@
|
||||
/>
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="loading">
|
||||
<h2 class="text-center"><strong>Loading Trusted Users!</strong></h2>
|
||||
<mat-progress-bar [mode]="'query'"></mat-progress-bar>
|
||||
</div>
|
||||
|
||||
<mat-table
|
||||
class="mat-elevation-z10"
|
||||
[dataSource]="dataSource"
|
||||
|
||||
@@ -13,24 +13,26 @@ import { exportCsv } from '@app/_helpers';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class SettingsComponent implements OnInit {
|
||||
date: string;
|
||||
dataSource: MatTableDataSource<any>;
|
||||
displayedColumns: Array<string> = ['name', 'email', 'userId'];
|
||||
trustedUsers: Array<Staff>;
|
||||
userInfo: Staff;
|
||||
loading: boolean = true;
|
||||
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
|
||||
constructor(private authService: AuthService) {}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.authService.init();
|
||||
ngOnInit(): void {
|
||||
this.authService.trustedUsersSubject.subscribe((users) => {
|
||||
this.dataSource = new MatTableDataSource<any>(users);
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
this.trustedUsers = users;
|
||||
if (users.length > 0) {
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
this.userInfo = this.authService.getPrivateKeyInfo();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SettingsComponent, OrganizationComponent],
|
||||
@@ -38,6 +39,7 @@ import { ReactiveFormsModule } from '@angular/forms';
|
||||
MatSelectModule,
|
||||
MatMenuModule,
|
||||
ReactiveFormsModule,
|
||||
MatProgressBarModule,
|
||||
],
|
||||
})
|
||||
export class SettingsModule {}
|
||||
|
||||
@@ -45,6 +45,11 @@
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="loading">
|
||||
<h2 class="text-center"><strong>Loading Tokens!</strong></h2>
|
||||
<mat-progress-bar [mode]="'query'"></mat-progress-bar>
|
||||
</div>
|
||||
|
||||
<mat-table
|
||||
class="mat-elevation-z10 table-responsive"
|
||||
[dataSource]="dataSource"
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { ChangeDetectionStrategy, Component, OnInit, ViewChild } from '@angular/core';
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { LoggingService, TokenService } from '@app/_services';
|
||||
import { TokenService } from '@app/_services';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { Router } from '@angular/router';
|
||||
import { exportCsv } from '@app/_helpers';
|
||||
import { Token } from '@app/_models';
|
||||
|
||||
@@ -13,36 +18,41 @@ import { Token } from '@app/_models';
|
||||
styleUrls: ['./tokens.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class TokensComponent implements OnInit {
|
||||
export class TokensComponent implements OnInit, AfterViewInit {
|
||||
dataSource: MatTableDataSource<any>;
|
||||
columnsToDisplay: Array<string> = ['name', 'symbol', 'address', 'supply'];
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
tokens: Array<Token>;
|
||||
token: Token;
|
||||
loading: boolean = true;
|
||||
|
||||
constructor(
|
||||
private tokenService: TokenService,
|
||||
private loggingService: LoggingService,
|
||||
private router: Router
|
||||
) {}
|
||||
constructor(private tokenService: TokenService) {}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.tokenService.init();
|
||||
ngOnInit(): void {
|
||||
this.tokenService.load.subscribe(async (status: boolean) => {
|
||||
if (status) {
|
||||
await this.tokenService.getTokens();
|
||||
}
|
||||
});
|
||||
this.tokenService.tokensSubject.subscribe((tokens) => {
|
||||
this.loggingService.sendInfoLevelMessage(tokens);
|
||||
this.dataSource = new MatTableDataSource(tokens);
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
this.tokens = tokens;
|
||||
if (tokens.length > 0) {
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
if (this.dataSource) {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
}
|
||||
}
|
||||
|
||||
doFilter(value: string): void {
|
||||
this.dataSource.filter = value.trim().toLocaleLowerCase();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
|
||||
@NgModule({
|
||||
declarations: [TokensComponent, TokenDetailsComponent],
|
||||
@@ -37,6 +38,7 @@ import { MatCardModule } from '@angular/material/card';
|
||||
MatToolbarModule,
|
||||
MatCardModule,
|
||||
MatRippleModule,
|
||||
MatProgressBarModule,
|
||||
],
|
||||
})
|
||||
export class TokensModule {}
|
||||
|
||||
@@ -36,9 +36,7 @@ export class TransactionDetailsComponent implements OnInit {
|
||||
private tokenService: TokenService
|
||||
) {}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.transactionService.init();
|
||||
await this.tokenService.init();
|
||||
ngOnInit(): void {
|
||||
if (this.transaction?.type === 'conversion') {
|
||||
this.traderBloxbergLink =
|
||||
'https://blockexplorer.bloxberg.org/address/' + this.transaction?.trader + '/transactions';
|
||||
|
||||
@@ -63,6 +63,11 @@
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="loading">
|
||||
<h2 class="text-center"><strong>Loading Transactions!</strong></h2>
|
||||
<mat-progress-bar [mode]="'query'"></mat-progress-bar>
|
||||
</div>
|
||||
|
||||
<table
|
||||
mat-table
|
||||
class="mat-elevation-z10"
|
||||
|
||||
@@ -29,6 +29,7 @@ export class TransactionsComponent implements OnInit, AfterViewInit {
|
||||
transactionsType: string = 'all';
|
||||
transactionsTypes: Array<string>;
|
||||
tokenSymbol: string;
|
||||
loading: boolean = true;
|
||||
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
@@ -41,17 +42,16 @@ export class TransactionsComponent implements OnInit, AfterViewInit {
|
||||
) {}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.blockSyncService.blockSync();
|
||||
this.transactionService.transactionsSubject.subscribe((transactions) => {
|
||||
this.transactionDataSource = new MatTableDataSource<any>(transactions);
|
||||
this.transactionDataSource.paginator = this.paginator;
|
||||
this.transactionDataSource.sort = this.sort;
|
||||
this.transactions = transactions;
|
||||
if (transactions.length > 0) {
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
await this.blockSyncService.init();
|
||||
await this.tokenService.init();
|
||||
await this.transactionService.init();
|
||||
await this.userService.init();
|
||||
await this.blockSyncService.blockSync();
|
||||
this.userService
|
||||
.getTransactionTypes()
|
||||
.pipe(first())
|
||||
@@ -85,8 +85,10 @@ export class TransactionsComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.transactionDataSource.paginator = this.paginator;
|
||||
this.transactionDataSource.sort = this.sort;
|
||||
if (this.transactionDataSource) {
|
||||
this.transactionDataSource.paginator = this.paginator;
|
||||
this.transactionDataSource.sort = this.sort;
|
||||
}
|
||||
}
|
||||
|
||||
downloadCsv(): void {
|
||||
|
||||
@@ -17,6 +17,7 @@ import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatRippleModule } from '@angular/material/core';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
|
||||
@NgModule({
|
||||
declarations: [TransactionsComponent, TransactionDetailsComponent],
|
||||
@@ -37,6 +38,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
MatCardModule,
|
||||
MatRippleModule,
|
||||
MatSnackBarModule,
|
||||
MatProgressBarModule,
|
||||
],
|
||||
})
|
||||
export class TransactionsModule {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<nav class="navbar navbar-dark background-dark">
|
||||
<h1 class="navbar-brand">
|
||||
<div *ngIf="noInternetConnection; then offlineBlock; else onlineBlock"></div>
|
||||
<div *ngIf="online; then onlineBlock; else offlineBlock"></div>
|
||||
<ng-template #offlineBlock>
|
||||
<strong style="color: red">OFFLINE </strong>
|
||||
<img width="20rem" src="assets/images/no-wifi.svg" alt="Internet Disconnected" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
|
||||
import { checkOnlineStatus } from '@src/app/_helpers';
|
||||
|
||||
@Component({
|
||||
selector: 'app-network-status',
|
||||
@@ -7,21 +8,30 @@ import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NetworkStatusComponent implements OnInit {
|
||||
noInternetConnection: boolean = !navigator.onLine;
|
||||
online: boolean = navigator.onLine;
|
||||
|
||||
constructor(private cdr: ChangeDetectorRef) {
|
||||
this.handleNetworkChange();
|
||||
}
|
||||
|
||||
ngOnInit(): void {}
|
||||
ngOnInit(): void {
|
||||
window.addEventListener('online', (event: any) => {
|
||||
this.online = true;
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
window.addEventListener('offline', (event: any) => {
|
||||
this.online = false;
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
handleNetworkChange(): void {
|
||||
setTimeout(() => {
|
||||
if (!navigator.onLine !== this.noInternetConnection) {
|
||||
this.noInternetConnection = !navigator.onLine;
|
||||
setTimeout(async () => {
|
||||
if (this.online !== (await checkOnlineStatus())) {
|
||||
this.online = await checkOnlineStatus();
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
this.handleNetworkChange();
|
||||
}, 5000);
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user