Adding mini-graphs on dashboard.
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
<div class="col mb-4">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<div class="card-body more-padding">
|
||||
<h5 class="card-title">Tx weight per second</h5>
|
||||
<ng-template [ngIf]="mempoolInfoData.value" [ngIfElse]="loading">
|
||||
<span *ngIf="mempoolInfoData.value.vBytesPerSecond === 0; else inSync">
|
||||
@@ -38,7 +38,7 @@
|
||||
</div>
|
||||
<div class="col mb-4" *ngIf="(network$ | async) !== 'liquid'; else emptyBlock">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<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>
|
||||
@@ -48,6 +48,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col mb-4">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<div style="height: 250px;" *ngIf="(mempoolStats$ | async) as mempoolStats">
|
||||
<app-mempool-graph [data]="mempoolStats.mempool" [showLegend]="false" [offsetX]="10"></app-mempool-graph>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col mb-4">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<div style="height: 250px;" *ngIf="(mempoolStats$ | async) as mempoolStats">
|
||||
<app-chartist
|
||||
[data]="mempoolStats.weightPerSecond"
|
||||
[type]="'Line'"
|
||||
[options]="transactionsWeightPerSecondOptions">
|
||||
</app-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col mb-4">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
@@ -56,14 +81,14 @@
|
||||
<thead>
|
||||
<th style="width: 15%;">Height</th>
|
||||
<th style="width: 35%;">Mined</th>
|
||||
<th style="width: 20%;" class="d-none d-lg-block">Txs</th>
|
||||
<th style="width: 20%;" class="d-none d-lg-table-cell">Txs</th>
|
||||
<th style="width: 30%;">Filled</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let block of blocks$ | async; let i = index; trackBy: trackByBlock">
|
||||
<td><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
|
||||
<td><app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since> ago</td>
|
||||
<td class="d-none d-lg-block">{{ block.tx_count | number }}</td>
|
||||
<td class="d-none d-lg-table-cell">{{ block.tx_count | number }}</td>
|
||||
<td>
|
||||
<div class="progress position-relative">
|
||||
<div class="progress-bar progress-mempool {{ network$ | async }}" role="progressbar" [ngStyle]="{'width': (block.weight / 4000000)*100 + '%' }"></div>
|
||||
@@ -84,13 +109,13 @@
|
||||
<table class="table table-borderless text-left">
|
||||
<thead>
|
||||
<th style="width: 25%;">TXID</th>
|
||||
<th style="width: 50%;" class="text-right d-none d-lg-block">Amount (BTC)</th>
|
||||
<th style="width: 50%;" class="text-right d-none d-lg-table-cell">Amount (BTC)</th>
|
||||
<th style="width: 25%;" class="text-right">Fee</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let transaction of transactions$ | async; let i = index;">
|
||||
<td><a [routerLink]="['/tx' | relativeUrl, transaction.txid]">{{ transaction.txid | shortenString : 12 }}</a></td>
|
||||
<td class="text-right d-none d-lg-block"><app-amount [satoshis]="transaction.value" digitsInfo="1.2-2" [noFiat]="true"></app-amount> (<app-fiat [value]="transaction.value" digitsInfo="1.0-0"></app-fiat>)</td>
|
||||
<td class="text-right d-none d-lg-table-cell"><app-amount [satoshis]="transaction.value" digitsInfo="1.2-2" [noFiat]="true"></app-amount> (<app-fiat [value]="transaction.value" digitsInfo="1.0-0"></app-fiat>)</td>
|
||||
<td class="text-right">{{ transaction.fee / (transaction.weight / 4) | number : '1.1-1' }} sat/vB</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -27,6 +27,6 @@
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
.more-padding {
|
||||
padding: 1.25rem 2rem 1.25rem 2rem;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Inject, LOCALE_ID, OnInit } from '@angular/core';
|
||||
import { combineLatest, merge, Observable, of } from 'rxjs';
|
||||
import { map, reduce, scan, tap } from 'rxjs/operators';
|
||||
import { map, scan, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { Block } from '../interfaces/electrs.interface';
|
||||
import { OptimizedMempoolStats } from '../interfaces/node-api.interface';
|
||||
import { MempoolInfo, TransactionStripped } from '../interfaces/websocket.interface';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import { StateService } from '../services/state.service';
|
||||
import * as Chartist from 'chartist';
|
||||
import { formatDate } from '@angular/common';
|
||||
import { WebsocketService } from '../services/websocket.service';
|
||||
|
||||
interface MempoolBlocksData {
|
||||
blocks: number;
|
||||
@@ -24,6 +29,11 @@ interface MempoolInfoData {
|
||||
progressClass: string;
|
||||
}
|
||||
|
||||
interface MempoolStatsData {
|
||||
mempool: OptimizedMempoolStats[];
|
||||
weightPerSecond: any;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
templateUrl: './dashboard.component.html',
|
||||
@@ -39,12 +49,19 @@ export class DashboardComponent implements OnInit {
|
||||
blocks$: Observable<Block[]>;
|
||||
transactions$: Observable<TransactionStripped[]>;
|
||||
latestBlockHeight: number;
|
||||
mempoolTransactionsWeightPerSecondData: any;
|
||||
mempoolStats$: Observable<MempoolStatsData>;
|
||||
transactionsWeightPerSecondOptions: any;
|
||||
|
||||
constructor(
|
||||
@Inject(LOCALE_ID) private locale: string,
|
||||
private stateService: StateService,
|
||||
private apiService: ApiService,
|
||||
private websocketService: WebsocketService,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.websocketService.want(['blocks', 'stats', 'mempool-blocks', 'live-2h-chart']);
|
||||
this.network$ = merge(of(''), this.stateService.networkChanged$);
|
||||
|
||||
this.mempoolInfoData$ = combineLatest([
|
||||
@@ -137,6 +154,59 @@ export class DashboardComponent implements OnInit {
|
||||
}, []),
|
||||
map((txs) => txs.slice(0, 6)),
|
||||
);
|
||||
|
||||
this.mempoolStats$ = this.apiService.list2HStatistics$()
|
||||
.pipe(
|
||||
switchMap((mempoolStats) => {
|
||||
return merge(
|
||||
this.stateService.live2Chart$
|
||||
.pipe(
|
||||
scan((acc, stats) => {
|
||||
acc.unshift(stats);
|
||||
acc = acc.slice(0, acc.length - 1);
|
||||
return acc;
|
||||
}, mempoolStats)
|
||||
),
|
||||
of(mempoolStats)
|
||||
);
|
||||
}),
|
||||
map((mempoolStats) => {
|
||||
return {
|
||||
mempool: mempoolStats,
|
||||
weightPerSecond: this.handleNewMempoolData(mempoolStats.concat([])),
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
this.transactionsWeightPerSecondOptions = {
|
||||
showArea: false,
|
||||
showLine: true,
|
||||
fullWidth: true,
|
||||
showPoint: false,
|
||||
low: 0,
|
||||
axisY: {
|
||||
offset: 40
|
||||
},
|
||||
axisX: {
|
||||
labelInterpolationFnc: (value: any, index: any) => index % 12 === 0 ? formatDate(value, 'HH:mm', this.locale) : null,
|
||||
offset: 10
|
||||
},
|
||||
plugins: [
|
||||
Chartist.plugins.ctTargetLine({
|
||||
value: 1667
|
||||
}),
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
handleNewMempoolData(mempoolStats: OptimizedMempoolStats[]) {
|
||||
mempoolStats.reverse();
|
||||
const labels = mempoolStats.map(stats => stats.added);
|
||||
|
||||
return {
|
||||
labels: labels,
|
||||
series: [mempoolStats.map((stats) => stats.vbytes_per_second)],
|
||||
};
|
||||
}
|
||||
|
||||
trackByBlock(index: number, block: Block) {
|
||||
|
||||
Reference in New Issue
Block a user