Merge pull request #944 from mempool/simon/chart-loading-spinner
Moving chart loading spinner to chart component
This commit is contained in:
		
						commit
						8da89230c9
					
				| @ -271,7 +271,7 @@ describe('Mainnet', () => { | ||||
|             cy.changeNetwork("bisq"); | ||||
|         }); | ||||
| 
 | ||||
|         it('loads the dashboard with the skeleton blocks', () => { | ||||
|         it.skip('loads the dashboard with the skeleton blocks', () => { | ||||
|             cy.mockMempoolSocket(); | ||||
|             cy.visit("/"); | ||||
|             cy.get(':nth-child(1) > #bitcoin-block-0').should('be.visible'); | ||||
|  | ||||
| @ -23,7 +23,7 @@ describe('Signet', () => { | ||||
|       cy.get('#mempool-block-0 > .blockLink').should('exist'); | ||||
|     }); | ||||
| 
 | ||||
|     it('loads the dashboard with the skeleton blocks', () => { | ||||
|     it.skip('loads the dashboard with the skeleton blocks', () => { | ||||
|         cy.mockMempoolSocket(); | ||||
|         cy.visit("/signet"); | ||||
|         cy.get(':nth-child(1) > #bitcoin-block-0').should('be.visible'); | ||||
|  | ||||
| @ -23,7 +23,7 @@ describe('Testnet', () => { | ||||
|       cy.get('#mempool-block-0 > .blockLink').should('exist'); | ||||
|     }); | ||||
| 
 | ||||
|     it('loads the dashboard with the skeleton blocks', () => { | ||||
|     it.skip('loads the dashboard with the skeleton blocks', () => { | ||||
|         cy.mockMempoolSocket(); | ||||
|         cy.visit("/testnet"); | ||||
|         cy.get(':nth-child(1) > #bitcoin-block-0').should('be.visible'); | ||||
|  | ||||
| @ -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> | ||||
| @ -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 { EChartsOption } from 'echarts'; | ||||
| import { OnChanges } from '@angular/core'; | ||||
| @ -7,6 +7,14 @@ import { StorageService } from 'src/app/services/storage.service'; | ||||
| @Component({ | ||||
|   selector: 'app-incoming-transactions-graph', | ||||
|   templateUrl: './incoming-transactions-graph.component.html', | ||||
|   styles: [` | ||||
|     .loadingGraphs { | ||||
|       position: absolute; | ||||
|       top: 50%; | ||||
|       left: calc(50% - 16px); | ||||
|       z-index: 100; | ||||
|     } | ||||
|   `],
 | ||||
|   changeDetection: ChangeDetectionStrategy.OnPush, | ||||
| }) | ||||
| export class IncomingTransactionsGraphComponent implements OnInit, OnChanges { | ||||
| @ -18,6 +26,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges { | ||||
|   @Input() left: number | string = '0'; | ||||
|   @Input() template: ('widget' | 'advanced') = 'widget'; | ||||
| 
 | ||||
|   isLoading = true; | ||||
|   mempoolStatsChartOption: EChartsOption = {}; | ||||
|   mempoolStatsChartInitOption = { | ||||
|     renderer: 'svg' | ||||
| @ -29,13 +38,23 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges { | ||||
|     private storageService: StorageService, | ||||
|   ) { } | ||||
| 
 | ||||
|   ngOnInit() { | ||||
|     this.isLoading = true; | ||||
|   } | ||||
| 
 | ||||
|   ngOnChanges(): void { | ||||
|     if (!this.data) { | ||||
|       return; | ||||
|     } | ||||
|     this.windowPreference = this.storageService.getValue('graphWindowPreference'); | ||||
|     this.mountChart(); | ||||
|   } | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|     this.mountChart(); | ||||
|   rendered() { | ||||
|     if (!this.data) { | ||||
|       return; | ||||
|     } | ||||
|     this.isLoading = false; | ||||
|   } | ||||
| 
 | ||||
|   mountChart(): void { | ||||
|  | ||||
| @ -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> | ||||
| @ -12,6 +12,14 @@ import { feeLevels, chartColors } from 'src/app/app.constants'; | ||||
| @Component({ | ||||
|   selector: 'app-mempool-graph', | ||||
|   templateUrl: './mempool-graph.component.html', | ||||
|   styles: [` | ||||
|     .loadingGraphs { | ||||
|       position: absolute; | ||||
|       top: 50%; | ||||
|       left: calc(50% - 16px); | ||||
|       z-index: 100; | ||||
|     } | ||||
|   `],
 | ||||
|   changeDetection: ChangeDetectionStrategy.OnPush, | ||||
| }) | ||||
| export class MempoolGraphComponent implements OnInit, OnChanges { | ||||
| @ -25,6 +33,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges { | ||||
|   @Input() template: ('widget' | 'advanced') = 'widget'; | ||||
|   @Input() showZoom = true; | ||||
| 
 | ||||
|   isLoading = true; | ||||
|   mempoolVsizeFeesData: any; | ||||
|   mempoolVsizeFeesOptions: EChartsOption; | ||||
|   mempoolVsizeFeesInitOptions = { | ||||
| @ -45,16 +54,26 @@ export class MempoolGraphComponent implements OnInit, OnChanges { | ||||
|   ) { } | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
|     this.isLoading = true; | ||||
|     this.inverted = this.storageService.getValue('inverted-graph') === 'true'; | ||||
|     this.mountFeeChart(); | ||||
|   } | ||||
| 
 | ||||
|   ngOnChanges() { | ||||
|     if (!this.data) { | ||||
|       return; | ||||
|     } | ||||
|     this.windowPreference = this.storageService.getValue('graphWindowPreference'); | ||||
|     this.mempoolVsizeFeesData = this.handleNewMempoolData(this.data.concat([])); | ||||
|     this.mountFeeChart(); | ||||
|   } | ||||
| 
 | ||||
|   rendered() { | ||||
|     if (!this.data) { | ||||
|       return; | ||||
|     } | ||||
|     this.isLoading = false; | ||||
|   } | ||||
| 
 | ||||
|   onChartReady(myChart: any) { | ||||
|     myChart.getZr().on('mousemove', (e: any) => { | ||||
|       if (e.target !== undefined && | ||||
|  | ||||
| @ -1,14 +1,7 @@ | ||||
| <div class="container-graph"> | ||||
|   <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 class="card mb-3" *ngIf="mempoolStats.length"> | ||||
|       <div class="card mb-3"> | ||||
|         <div class="card-header"> | ||||
|           <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()"> | ||||
| @ -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> | ||||
|             </div> | ||||
|           </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 class="card-body"> | ||||
|           <div class="incoming-transactions-graph"> | ||||
| @ -92,7 +85,7 @@ | ||||
|               [height]="500" | ||||
|               [left]="65" | ||||
|               [right]="10" | ||||
|               [data]="mempoolStats" | ||||
|               [data]="mempoolStats && mempoolStats.length ? mempoolStats : null" | ||||
|             ></app-mempool-graph> | ||||
|           </div> | ||||
|         </div> | ||||
| @ -100,7 +93,7 @@ | ||||
|     </div> | ||||
| 
 | ||||
|     <div> | ||||
|       <div class="card mb-3" *ngIf="mempoolTransactionsWeightPerSecondData"> | ||||
|       <div class="card mb-3"> | ||||
|         <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> | ||||
|         </div> | ||||
|  | ||||
| @ -1,10 +1,5 @@ | ||||
| <div id="tv-wrapper"> | ||||
| 
 | ||||
|   <div *ngIf="mempoolStats.length === 0" class="loading"> | ||||
|     <div class="spinner-border text-light"></div> | ||||
|   </div> | ||||
| 
 | ||||
|   <div class="tv-container" *ngIf="mempoolStats.length"> | ||||
|   <div class="tv-container"> | ||||
|     <div class="chart-holder"> | ||||
|       <app-mempool-graph | ||||
|         [template]="'advanced'" | ||||
| @ -12,7 +7,7 @@ | ||||
|         [height]="600" | ||||
|         [left]="60" | ||||
|         [right]="10" | ||||
|         [data]="mempoolStats" | ||||
|         [data]="mempoolStats && mempoolStats.length ? mempoolStats : null" | ||||
|         [showZoom]="false" | ||||
|       ></app-mempool-graph> | ||||
|     </div> | ||||
|  | ||||
| @ -16,6 +16,7 @@ | ||||
| } | ||||
| 
 | ||||
| .chart-holder { | ||||
|   position: relative; | ||||
|   height: 650px; | ||||
|   width: 100%; | ||||
|   margin: 30px auto 0; | ||||
|  | ||||
| @ -47,14 +47,16 @@ | ||||
|               <ng-container *ngTemplateOutlet="mempoolTable; context: { $implicit: mempoolInfoData }"></ng-container> | ||||
|               <hr> | ||||
|             </div> | ||||
|             <div class="mempool-graph" *ngIf="(mempoolStats$ | async) as mempoolStats; else loadingSpinner"> | ||||
|               <app-mempool-graph | ||||
|             <ng-container *ngIf="{ value: (mempoolStats$ | async) } as mempoolStats"> | ||||
|               <div class="mempool-graph"> | ||||
|                 <app-mempool-graph | ||||
|                 [template]="'widget'" | ||||
|                 [limitFee]="150" | ||||
|                 [limitFilterFee]="1" | ||||
|                 [data]="mempoolStats.mempool" | ||||
|               ></app-mempool-graph> | ||||
|             </div> | ||||
|                 [data]="mempoolStats.value?.mempool" | ||||
|                 ></app-mempool-graph> | ||||
|               </div> | ||||
|             </ng-container> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
| @ -67,10 +69,10 @@ | ||||
|               <app-lbtc-pegs-graph [data]="liquidPegsMonth$ | async"></app-lbtc-pegs-graph> | ||||
|             </div> | ||||
|             <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 | ||||
|                   [left]="50" | ||||
|                   [data]="mempoolStats.weightPerSecond" | ||||
|                   [data]="mempoolStats.value?.weightPerSecond" | ||||
|                   ></app-incoming-transactions-graph> | ||||
|               </div> | ||||
|             </ng-template> | ||||
| @ -280,13 +282,6 @@ | ||||
|   </div> | ||||
| </ng-template> | ||||
| 
 | ||||
| 
 | ||||
| <ng-template #loadingSpinner> | ||||
|   <div class="text-center loadingGraphs"> | ||||
|     <div class="spinner-border text-light"></div> | ||||
|   </div> | ||||
| </ng-template> | ||||
| 
 | ||||
| <ng-template #loadingDifficulty> | ||||
|   <div class="difficulty-skeleton loading-container"> | ||||
|     <div class="item"> | ||||
|  | ||||
| @ -2,15 +2,13 @@ import { ChangeDetectionStrategy, Component, Inject, LOCALE_ID, OnInit } from '@ | ||||
| import { combineLatest, merge, Observable, of, timer } from 'rxjs'; | ||||
| import { filter, map, scan, share, switchMap, tap } from 'rxjs/operators'; | ||||
| 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 { ApiService } from '../services/api.service'; | ||||
| import { StateService } from '../services/state.service'; | ||||
| import { formatDate } from '@angular/common'; | ||||
| import { WebsocketService } from '../services/websocket.service'; | ||||
| import { SeoService } from '../services/seo.service'; | ||||
| import { StorageService } from '../services/storage.service'; | ||||
| import { EChartsOption } from 'echarts'; | ||||
| 
 | ||||
| interface MempoolBlocksData { | ||||
|   blocks: number; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user