Feature: Add a collapse/show advanced view feature on the Dashboard

fixes #134
This commit is contained in:
softsimon 2020-10-27 02:58:29 +07:00
parent 645772c01a
commit edf2d4205d
No known key found for this signature in database
GPG Key ID: 488D7DCFB5A430D7
4 changed files with 180 additions and 105 deletions

View File

@ -46,6 +46,7 @@ import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontaweso
import { faBolt, faChartArea, faCogs, faCubes, faDatabase, faInfoCircle, faLink, faList, faSearch, faTachometerAlt, faThList, faTv } from '@fortawesome/free-solid-svg-icons';
import { ApiDocsComponent } from './components/api-docs/api-docs.component';
import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component';
import { StorageService } from './services/storage.service';
@NgModule({
declarations: [
@ -97,6 +98,7 @@ import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-
WebsocketService,
AudioService,
SeoService,
StorageService,
],
bootstrap: [AppComponent]
})

View File

@ -2,6 +2,33 @@
<div class="container-xl mt-2">
<div class="row row-cols-1 row-cols-md-2" *ngIf="{ value: (mempoolInfoData$ | async) } as mempoolInfoData">
<ng-template [ngIf]="collapsed" [ngIfElse]="expanded">
<div class="col mb-4">
<div class="card text-center">
<div class="card-body">
<app-fees-box class="d-block"></app-fees-box>
</div>
</div>
</div>
<div class="col mb-4">
<div class="card text-center">
<div class="card-body">
<ng-container *ngTemplateOutlet="mempoolTable; context: { $implicit: mempoolInfoData }"></ng-container>
</div>
</div>
</div>
<div class="col mb-4">
<div class="card text-center">
<div class="card-body">
<ng-container *ngTemplateOutlet="txPerSecond; context: { $implicit: mempoolInfoData }"></ng-container>
</div>
</div>
</div>
<div class="col mb-4" *ngIf="(network$ | async) !== 'liquid'; else emptyBlock">
<ng-container *ngTemplateOutlet="difficultyEpoch"></ng-container>
</div>
</ng-template>
<ng-template #expanded>
<div class="col mb-4">
<div class="card text-center">
<div class="card-body">
@ -10,37 +37,13 @@
</div>
</div>
<div class="col mb-4" *ngIf="(network$ | async) !== 'liquid'; else emptyBlock">
<div class="card text-center">
<div class="card-body more-padding">
<h5 class="card-title">Difficulty adjustment</h5>
<div class="progress" *ngIf="(difficultyEpoch$ | async) as epochData; else loading">
<div class="progress-bar" role="progressbar" style="width: 15%; background-color: #105fb0" [ngStyle]="{'width': epochData.base}"><ng-template [ngIf]="epochData.change > 0">+</ng-template>{{ epochData.change | number: '1.0-2' }}%</div>
<div class="progress-bar bg-success" role="progressbar" style="width: 0%" [ngStyle]="{'width': epochData.green}"></div>
<div class="progress-bar bg-danger" role="progressbar" style="width: 1%; background-color: #f14d80;" [ngStyle]="{'width': epochData.red}"></div>
</div>
</div>
</div>
<ng-container *ngTemplateOutlet="difficultyEpoch"></ng-container>
</div>
<div class="col mb-4">
<div class="card text-center graph-card">
<div class="card-body pl-0">
<div style="padding-left: 1.25rem;">
<table style="width: 100%;">
<tr>
<td>
<h5 class="card-title">Mempool size</h5>
<p class="card-text" *ngIf="(mempoolBlocksData$ | async) as mempoolBlocksData; else loading">
{{ mempoolBlocksData.size | bytes }} ({{ mempoolBlocksData.blocks }} block<span [hidden]="mempoolBlocksData.blocks <= 1">s</span>)
</p>
</td>
<td>
<h5 class="card-title">Unconfirmed</h5>
<p class="card-text" *ngIf="mempoolInfoData.value; else loading">
{{ mempoolInfoData.value.memPoolInfo.size | number }} TXs
</p>
</td>
</tr>
</table>
<ng-container *ngTemplateOutlet="mempoolTable; context: { $implicit: mempoolInfoData }"></ng-container>
<hr>
</div>
<div style="height: 250px;" *ngIf="(mempoolStats$ | async) as mempoolStats">
@ -51,18 +54,8 @@
</div>
<div class="col mb-4">
<div class="card text-center graph-card">
<div class="card-body ">
<h5 class="card-title">Tx vBytes per second</h5>
<ng-template [ngIf]="mempoolInfoData.value" [ngIfElse]="loading">
<span *ngIf="mempoolInfoData.value.vBytesPerSecond === 0; else inSync">
&nbsp;<span class="badge badge-pill badge-warning">Backend is synchronizing</span>
</span>
<ng-template #inSync>
<div class="progress sub-text" style="max-width: 250px;">
<div class="progress-bar {{ mempoolInfoData.value.progressClass }}" style="padding: 4px;" role="progressbar" [ngStyle]="{'width': mempoolInfoData.value.progressWidth}">{{ mempoolInfoData.value.vBytesPerSecond | ceil | number }} vB/s</div>
</div>
</ng-template>
</ng-template>
<div class="card-body">
<ng-container *ngTemplateOutlet="txPerSecond; context: { $implicit: mempoolInfoData }"></ng-container>
<br>
<hr>
<div style="height: 250px;" *ngIf="(mempoolStats$ | async) as mempoolStats">
@ -128,8 +121,11 @@
</div>
</div>
</div>
</ng-template>
</div>
<button type="button" class="btn btn-secondary btn-sm d-block mx-auto" (click)="toggleCollapsed()">{{ collapsed ? 'Expand' : 'Collapse' }}</button>
<br>
<div class="text-small text-center">
@ -147,3 +143,49 @@
</div>
</ng-template>
<ng-template #mempoolTable let-mempoolInfoData>
<table style="width: 100%;">
<tr>
<td>
<h5 class="card-title">Mempool size</h5>
<p class="card-text" *ngIf="(mempoolBlocksData$ | async) as mempoolBlocksData; else loading">
{{ mempoolBlocksData.size | bytes }} ({{ mempoolBlocksData.blocks }} block<span [hidden]="mempoolBlocksData.blocks <= 1">s</span>)
</p>
</td>
<td>
<h5 class="card-title">Unconfirmed</h5>
<p class="card-text" *ngIf="mempoolInfoData.value; else loading">
{{ mempoolInfoData.value.memPoolInfo.size | number }} TXs
</p>
</td>
</tr>
</table>
</ng-template>
<ng-template #txPerSecond let-mempoolInfoData>
<h5 class="card-title">Tx vBytes per second</h5>
<ng-template [ngIf]="mempoolInfoData.value" [ngIfElse]="loading">
<span *ngIf="mempoolInfoData.value.vBytesPerSecond === 0; else inSync">
&nbsp;<span class="badge badge-pill badge-warning">Backend is synchronizing</span>
</span>
<ng-template #inSync>
<div class="progress sub-text" style="max-width: 250px;">
<div class="progress-bar {{ mempoolInfoData.value.progressClass }}" style="padding: 4px;" role="progressbar" [ngStyle]="{'width': mempoolInfoData.value.progressWidth}">{{ mempoolInfoData.value.vBytesPerSecond | ceil | number }} vB/s</div>
</div>
</ng-template>
</ng-template>
</ng-template>
<ng-template #difficultyEpoch>
<div class="card text-center">
<div class="card-body more-padding">
<h5 class="card-title">Difficulty adjustment</h5>
<div class="progress" *ngIf="(difficultyEpoch$ | async) as epochData; else loading">
<div class="progress-bar" role="progressbar" style="width: 15%; background-color: #105fb0" [ngStyle]="{'width': epochData.base}"><ng-template [ngIf]="epochData.change > 0">+</ng-template>{{ epochData.change | number: '1.0-2' }}%</div>
<div class="progress-bar bg-success" role="progressbar" style="width: 0%" [ngStyle]="{'width': epochData.green}"></div>
<div class="progress-bar bg-danger" role="progressbar" style="width: 1%; background-color: #f14d80;" [ngStyle]="{'width': epochData.red}"></div>
</div>
</div>
</div>
</ng-template>

View File

@ -10,6 +10,7 @@ import * as Chartist from 'chartist';
import { formatDate } from '@angular/common';
import { WebsocketService } from '../services/websocket.service';
import { SeoService } from '../services/seo.service';
import { StorageService } from '../services/storage.service';
interface MempoolBlocksData {
blocks: number;
@ -42,6 +43,7 @@ interface MempoolStatsData {
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DashboardComponent implements OnInit {
collapsed = true;
network$: Observable<string>;
mempoolBlocksData$: Observable<MempoolBlocksData>;
mempoolInfoData$: Observable<MempoolInfoData>;
@ -60,12 +62,14 @@ export class DashboardComponent implements OnInit {
private apiService: ApiService,
private websocketService: WebsocketService,
private seoService: SeoService,
private storageService: StorageService,
) { }
ngOnInit(): void {
this.seoService.resetTitle();
this.websocketService.want(['blocks', 'stats', 'mempool-blocks', 'live-2h-chart']);
this.network$ = merge(of(''), this.stateService.networkChanged$);
this.collapsed = this.storageService.getValue('dashboard-collapsed') === 'true' || false;
this.mempoolInfoData$ = combineLatest([
this.stateService.mempoolInfo$,
@ -217,4 +221,9 @@ export class DashboardComponent implements OnInit {
trackByBlock(index: number, block: Block) {
return block.height;
}
toggleCollapsed() {
this.collapsed = !this.collapsed;
this.storageService.setValue('dashboard-collapsed', this.collapsed);
}
}

View File

@ -0,0 +1,22 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class StorageService {
getValue(key: string): string {
try {
return localStorage.getItem(key);
} catch (e) {
console.log(e);
}
}
setValue(key: string, value: any): void {
try {
localStorage.setItem(key, value);
} catch (e) {
console.log(e);
}
}
}