Moving chart loading spinner to chart component

fixes #885
This commit is contained in:
softsimon 2021-11-19 00:10:12 +04:00
parent 9bef7da210
commit 8569523b89
No known key found for this signature in database
GPG key ID: 488D7DCFB5A430D7
9 changed files with 67 additions and 41 deletions

View file

@ -1 +1,4 @@
<div class="echarts" echarts [initOpts]="mempoolStatsChartInitOption" [options]="mempoolStatsChartOption"></div> <div class="echarts" echarts [initOpts]="mempoolStatsChartInitOption" [options]="mempoolStatsChartOption" (chartRendered)="rendered()"></div>
<div class="text-center loadingGraphs" *ngIf="isLoading">
<div class="spinner-border text-light"></div>
</div>

View file

@ -1,4 +1,4 @@
import { Component, OnInit, Input, Inject, LOCALE_ID, ChangeDetectionStrategy } from '@angular/core'; import { Component, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnInit } from '@angular/core';
import { formatDate } from '@angular/common'; import { formatDate } from '@angular/common';
import { EChartsOption } from 'echarts'; import { EChartsOption } from 'echarts';
import { OnChanges } from '@angular/core'; import { OnChanges } from '@angular/core';
@ -7,6 +7,14 @@ import { StorageService } from 'src/app/services/storage.service';
@Component({ @Component({
selector: 'app-incoming-transactions-graph', selector: 'app-incoming-transactions-graph',
templateUrl: './incoming-transactions-graph.component.html', templateUrl: './incoming-transactions-graph.component.html',
styles: [`
.loadingGraphs {
position: absolute;
top: 50%;
left: calc(50% - 16px);
z-index: 100;
}
`],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class IncomingTransactionsGraphComponent implements OnInit, OnChanges { export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
@ -18,6 +26,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
@Input() left: number | string = '0'; @Input() left: number | string = '0';
@Input() template: ('widget' | 'advanced') = 'widget'; @Input() template: ('widget' | 'advanced') = 'widget';
isLoading = true;
mempoolStatsChartOption: EChartsOption = {}; mempoolStatsChartOption: EChartsOption = {};
mempoolStatsChartInitOption = { mempoolStatsChartInitOption = {
renderer: 'svg' renderer: 'svg'
@ -29,13 +38,23 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
private storageService: StorageService, private storageService: StorageService,
) { } ) { }
ngOnInit() {
this.isLoading = true;
}
ngOnChanges(): void { ngOnChanges(): void {
if (!this.data) {
return;
}
this.windowPreference = this.storageService.getValue('graphWindowPreference'); this.windowPreference = this.storageService.getValue('graphWindowPreference');
this.mountChart(); this.mountChart();
} }
ngOnInit(): void { rendered() {
this.mountChart(); if (!this.data) {
return;
}
this.isLoading = false;
} }
mountChart(): void { mountChart(): void {

View file

@ -1 +1,4 @@
<div echarts class="echarts" (chartInit)="onChartReady($event)" [initOpts]="mempoolVsizeFeesInitOptions" [options]="mempoolVsizeFeesOptions"></div> <div echarts class="echarts" (chartInit)="onChartReady($event)" (chartRendered)="rendered()" [initOpts]="mempoolVsizeFeesInitOptions" [options]="mempoolVsizeFeesOptions"></div>
<div class="text-center loadingGraphs" *ngIf="isLoading">
<div class="spinner-border text-light"></div>
</div>

View file

@ -12,6 +12,14 @@ import { feeLevels, chartColors } from 'src/app/app.constants';
@Component({ @Component({
selector: 'app-mempool-graph', selector: 'app-mempool-graph',
templateUrl: './mempool-graph.component.html', templateUrl: './mempool-graph.component.html',
styles: [`
.loadingGraphs {
position: absolute;
top: 50%;
left: calc(50% - 16px);
z-index: 100;
}
`],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class MempoolGraphComponent implements OnInit, OnChanges { export class MempoolGraphComponent implements OnInit, OnChanges {
@ -25,6 +33,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
@Input() template: ('widget' | 'advanced') = 'widget'; @Input() template: ('widget' | 'advanced') = 'widget';
@Input() showZoom = true; @Input() showZoom = true;
isLoading = true;
mempoolVsizeFeesData: any; mempoolVsizeFeesData: any;
mempoolVsizeFeesOptions: EChartsOption; mempoolVsizeFeesOptions: EChartsOption;
mempoolVsizeFeesInitOptions = { mempoolVsizeFeesInitOptions = {
@ -45,16 +54,26 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.isLoading = true;
this.inverted = this.storageService.getValue('inverted-graph') === 'true'; this.inverted = this.storageService.getValue('inverted-graph') === 'true';
this.mountFeeChart();
} }
ngOnChanges() { ngOnChanges() {
if (!this.data) {
return;
}
this.windowPreference = this.storageService.getValue('graphWindowPreference'); this.windowPreference = this.storageService.getValue('graphWindowPreference');
this.mempoolVsizeFeesData = this.handleNewMempoolData(this.data.concat([])); this.mempoolVsizeFeesData = this.handleNewMempoolData(this.data.concat([]));
this.mountFeeChart(); this.mountFeeChart();
} }
rendered() {
if (!this.data) {
return;
}
this.isLoading = false;
}
onChartReady(myChart: any) { onChartReady(myChart: any) {
myChart.getZr().on('mousemove', (e: any) => { myChart.getZr().on('mousemove', (e: any) => {
if (e.target !== undefined && if (e.target !== undefined &&

View file

@ -1,14 +1,7 @@
<div class="container-graph"> <div class="container-graph">
<div> <div>
<div *ngIf="loading" class="loading">
<div class="text-center">
<h3 i18n="statistics.loading-graphs">Loading graphs...</h3>
<br>
<div class="spinner-border text-light"></div>
</div>
</div>
<div> <div>
<div class="card mb-3" *ngIf="mempoolStats.length"> <div class="card mb-3">
<div class="card-header"> <div class="card-header">
<i class="fa fa-area-chart"></i> <span i18n="statistics.memory-by-vBytes">Mempool by vBytes (sat/vByte)</span> <i class="fa fa-area-chart"></i> <span i18n="statistics.memory-by-vBytes">Mempool by vBytes (sat/vByte)</span>
<form [formGroup]="radioGroupForm" class="formRadioGroup" (click)="saveGraphPreference()"> <form [formGroup]="radioGroupForm" class="formRadioGroup" (click)="saveGraphPreference()">
@ -80,7 +73,7 @@
<button (click)="invertGraph()" class="btn btn-primary btn-sm"><fa-icon [icon]="['fas', 'exchange-alt']" [rotate]="90" [fixedWidth]="true" i18n-title="statistics.component-invert.title" title="Invert"></fa-icon></button> <button (click)="invertGraph()" class="btn btn-primary btn-sm"><fa-icon [icon]="['fas', 'exchange-alt']" [rotate]="90" [fixedWidth]="true" i18n-title="statistics.component-invert.title" title="Invert"></fa-icon></button>
</div> </div>
</form> </form>
<div class="spinner-border text-light bootstrap-spinner" *ngIf="spinnerLoading"></div> <div class="spinner-border text-light bootstrap-spinner" *ngIf="spinnerLoading && mempoolStats.length"></div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="incoming-transactions-graph"> <div class="incoming-transactions-graph">
@ -92,7 +85,7 @@
[height]="500" [height]="500"
[left]="65" [left]="65"
[right]="10" [right]="10"
[data]="mempoolStats" [data]="mempoolStats && mempoolStats.length ? mempoolStats : null"
></app-mempool-graph> ></app-mempool-graph>
</div> </div>
</div> </div>
@ -100,7 +93,7 @@
</div> </div>
<div> <div>
<div class="card mb-3" *ngIf="mempoolTransactionsWeightPerSecondData"> <div class="card mb-3">
<div class="card-header"> <div class="card-header">
<i class="fa fa-area-chart"></i> <span i18n="statistics.transaction-vbytes-per-second">Transaction vBytes per second (vB/s)</span> <i class="fa fa-area-chart"></i> <span i18n="statistics.transaction-vbytes-per-second">Transaction vBytes per second (vB/s)</span>
</div> </div>

View file

@ -1,10 +1,5 @@
<div id="tv-wrapper"> <div id="tv-wrapper">
<div class="tv-container">
<div *ngIf="mempoolStats.length === 0" class="loading">
<div class="spinner-border text-light"></div>
</div>
<div class="tv-container" *ngIf="mempoolStats.length">
<div class="chart-holder"> <div class="chart-holder">
<app-mempool-graph <app-mempool-graph
[template]="'advanced'" [template]="'advanced'"
@ -12,7 +7,7 @@
[height]="600" [height]="600"
[left]="60" [left]="60"
[right]="10" [right]="10"
[data]="mempoolStats" [data]="mempoolStats && mempoolStats.length ? mempoolStats : null"
[showZoom]="false" [showZoom]="false"
></app-mempool-graph> ></app-mempool-graph>
</div> </div>

View file

@ -16,6 +16,7 @@
} }
.chart-holder { .chart-holder {
position: relative;
height: 650px; height: 650px;
width: 100%; width: 100%;
margin: 30px auto 0; margin: 30px auto 0;

View file

@ -47,14 +47,16 @@
<ng-container *ngTemplateOutlet="mempoolTable; context: { $implicit: mempoolInfoData }"></ng-container> <ng-container *ngTemplateOutlet="mempoolTable; context: { $implicit: mempoolInfoData }"></ng-container>
<hr> <hr>
</div> </div>
<div class="mempool-graph" *ngIf="(mempoolStats$ | async) as mempoolStats; else loadingSpinner"> <ng-container *ngIf="{ value: (mempoolStats$ | async) } as mempoolStats">
<app-mempool-graph <div class="mempool-graph">
<app-mempool-graph
[template]="'widget'" [template]="'widget'"
[limitFee]="150" [limitFee]="150"
[limitFilterFee]="1" [limitFilterFee]="1"
[data]="mempoolStats.mempool" [data]="mempoolStats.value?.mempool"
></app-mempool-graph> ></app-mempool-graph>
</div> </div>
</ng-container>
</div> </div>
</div> </div>
</div> </div>
@ -67,10 +69,10 @@
<app-lbtc-pegs-graph [data]="liquidPegsMonth$ | async"></app-lbtc-pegs-graph> <app-lbtc-pegs-graph [data]="liquidPegsMonth$ | async"></app-lbtc-pegs-graph>
</div> </div>
<ng-template #mempoolGraph> <ng-template #mempoolGraph>
<div class="mempool-graph" *ngIf="(mempoolStats$ | async) as mempoolStats; else loadingSpinner"> <div class="mempool-graph" *ngIf="{ value: (mempoolStats$ | async) } as mempoolStats">
<app-incoming-transactions-graph <app-incoming-transactions-graph
[left]="50" [left]="50"
[data]="mempoolStats.weightPerSecond" [data]="mempoolStats.value?.weightPerSecond"
></app-incoming-transactions-graph> ></app-incoming-transactions-graph>
</div> </div>
</ng-template> </ng-template>
@ -280,13 +282,6 @@
</div> </div>
</ng-template> </ng-template>
<ng-template #loadingSpinner>
<div class="text-center loadingGraphs">
<div class="spinner-border text-light"></div>
</div>
</ng-template>
<ng-template #loadingDifficulty> <ng-template #loadingDifficulty>
<div class="difficulty-skeleton loading-container"> <div class="difficulty-skeleton loading-container">
<div class="item"> <div class="item">

View file

@ -2,15 +2,13 @@ import { ChangeDetectionStrategy, Component, Inject, LOCALE_ID, OnInit } from '@
import { combineLatest, merge, Observable, of, timer } from 'rxjs'; import { combineLatest, merge, Observable, of, timer } from 'rxjs';
import { filter, map, scan, share, switchMap, tap } from 'rxjs/operators'; import { filter, map, scan, share, switchMap, tap } from 'rxjs/operators';
import { Block } from '../interfaces/electrs.interface'; import { Block } from '../interfaces/electrs.interface';
import { LiquidPegs, OptimizedMempoolStats } from '../interfaces/node-api.interface'; import { OptimizedMempoolStats } from '../interfaces/node-api.interface';
import { MempoolInfo, TransactionStripped } from '../interfaces/websocket.interface'; import { MempoolInfo, TransactionStripped } from '../interfaces/websocket.interface';
import { ApiService } from '../services/api.service'; import { ApiService } from '../services/api.service';
import { StateService } from '../services/state.service'; import { StateService } from '../services/state.service';
import { formatDate } from '@angular/common';
import { WebsocketService } from '../services/websocket.service'; import { WebsocketService } from '../services/websocket.service';
import { SeoService } from '../services/seo.service'; import { SeoService } from '../services/seo.service';
import { StorageService } from '../services/storage.service'; import { StorageService } from '../services/storage.service';
import { EChartsOption } from 'echarts';
interface MempoolBlocksData { interface MempoolBlocksData {
blocks: number; blocks: number;