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