From 71cf41362ff83348d0334b646bff50bdd6fd0da9 Mon Sep 17 00:00:00 2001 From: Miguel Medeiros Date: Sat, 10 Jul 2021 10:04:15 -0300 Subject: [PATCH] UI/UX - Add skeleton for blocks preload. (#615) * Add skeleton for blocks preload. * Add e2e testing for skeleton blocks preloader. * Fix reduce mempool blocks to fit the screen. * Fix variable naming. --- .../integration/mainnet/mainnet.spec.ts | 11 +++++++ .../blockchain-blocks.component.html | 11 ++++++- .../blockchain-blocks.component.scss | 12 +++++++ .../blockchain-blocks.component.ts | 32 ++++++++++++++++--- .../blockchain/blockchain.component.html | 12 ++----- .../mempool-blocks.component.html | 10 +++++- .../mempool-blocks.component.ts | 29 +++++++++++++++-- 7 files changed, 99 insertions(+), 18 deletions(-) diff --git a/frontend/cypress/integration/mainnet/mainnet.spec.ts b/frontend/cypress/integration/mainnet/mainnet.spec.ts index 060a3f293..55b73b8dc 100644 --- a/frontend/cypress/integration/mainnet/mainnet.spec.ts +++ b/frontend/cypress/integration/mainnet/mainnet.spec.ts @@ -16,6 +16,17 @@ describe('Mainnet', () => { cy.wait(1000); }); + it('loads the dashboard with the skeleton blocks', () => { + cy.visit('/'); + cy.get('#mempool-block-0').should('be.visible'); + cy.get('#mempool-block-1').should('be.visible'); + cy.get('#mempool-block-2').should('be.visible'); + cy.get(':nth-child(1) > #bitcoin-block-0').should('be.visible'); + cy.get(':nth-child(2) > #bitcoin-block-0').should('be.visible'); + cy.get(':nth-child(3) > #bitcoin-block-0').should('be.visible'); + cy.wait(1000); + }); + it('loads the blocks screen', () => { cy.visit('/'); cy.get('li:nth-of-type(2) > a').click().then(() => { diff --git a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html index 4584974e2..abe055968 100644 --- a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html +++ b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html @@ -1,4 +1,4 @@ -
+
  @@ -24,3 +24,12 @@
+ +
+
+
+
+
+
+
+ diff --git a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss index b456c3cd1..4f9657ad4 100644 --- a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss +++ b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss @@ -108,3 +108,15 @@ border-right: 35px solid transparent; border-bottom: 35px solid #FFF; } + +.flashing { + animation: opacityPulse 2s ease-out; + animation-iteration-count: infinite; + opacity: 1; +} + +@keyframes opacityPulse { + 0% {opacity: 0.7;} + 50% {opacity: 1.0;} + 100% {opacity: 0.7;} +} \ No newline at end of file diff --git a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts index 77434fec8..af6ac35c7 100644 --- a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts +++ b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, Input } from '@angular/core'; +import { Subscription, Observable } from 'rxjs'; import { Block } from 'src/app/interfaces/electrs.interface'; import { StateService } from 'src/app/services/state.service'; import { Router } from '@angular/router'; @@ -11,8 +11,10 @@ import { Router } from '@angular/router'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class BlockchainBlocksComponent implements OnInit, OnDestroy { + @Input() isLoading$: Observable; + network = ''; - blocks: Block[] = []; + blocks: Block[] = this.mountEmptyBlocks(); markHeight: number; blocksSubscription: Subscription; networkSubscriotion: Subscription; @@ -42,6 +44,7 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy { ) { } ngOnInit() { + this.blocks.forEach((b) => this.blockStyles.push(this.getStyleForBlock(b))); this.networkSubscriotion = this.stateService.networkChanged$.subscribe((network) => this.network = network); this.tabHiddenSubscription = this.stateService.isTabHidden$.subscribe((tabHidden) => this.tabHidden = tabHidden); @@ -178,5 +181,26 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy { )`, }; } - + mountEmptyBlocks() { + const emptyBlocks = []; + for (let i = 0; i < 9; i++) { + emptyBlocks.push({ + id: '', + height: 0, + version: 0, + timestamp: 0, + bits: 0, + nonce: 0, + difficulty: 0, + merkle_root: '', + tx_count: 0, + size: 0, + weight: 0, + previousblockhash: '', + matchRate: 0, + stage: 0, + }); + } + return emptyBlocks; + } } diff --git a/frontend/src/app/components/blockchain/blockchain.component.html b/frontend/src/app/components/blockchain/blockchain.component.html index db0b44e6f..21e1a7111 100644 --- a/frontend/src/app/components/blockchain/blockchain.component.html +++ b/frontend/src/app/components/blockchain/blockchain.component.html @@ -1,15 +1,9 @@
-
+
- - + +
-
-
-

Waiting for blocks...

-
-
-
diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html index 6c6246103..ff18f198e 100644 --- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html +++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html @@ -1,4 +1,4 @@ -
+
@@ -41,3 +41,11 @@ In ~{{ i }} minutes In ~{{ i }} minute + +
+
+ +
+
+
+
diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts index 4e327eced..51033ac6f 100644 --- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts +++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, Input } from '@angular/core'; import { Subscription, Observable, fromEvent, merge, of } from 'rxjs'; import { MempoolBlock } from 'src/app/interfaces/websocket.interface'; import { StateService } from 'src/app/services/state.service'; @@ -13,10 +13,12 @@ import { feeLevels, mempoolFeeColors } from 'src/app/app.constants'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class MempoolBlocksComponent implements OnInit, OnDestroy { - mempoolBlocks: MempoolBlock[]; + @Input() isLoading$: Observable; + + mempoolBlocks: MempoolBlock[] = this.mountEmptyBlocks(); mempoolBlocks$: Observable; - mempoolBlocksFull: MempoolBlock[]; + mempoolBlocksFull: MempoolBlock[] = this.mountEmptyBlocks(); mempoolBlockStyles = []; markBlocksSubscription: Subscription; blockSubscription: Subscription; @@ -45,6 +47,11 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy { ) { } ngOnInit() { + this.mempoolBlocks.map(() => { + this.updateMempoolBlockStyles(); + this.calculateTransactionPosition(); + }); + this.reduceMempoolBlocksToFitScreen(this.mempoolBlocks); this.stateService.isTabHidden$.subscribe((tabHidden) => this.tabHidden = tabHidden); this.mempoolBlocks$ = merge( @@ -235,4 +242,20 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy { } } + mountEmptyBlocks() { + const emptyBlocks = []; + const numberOfBlocks = 8; + for (let i = 0; i <= numberOfBlocks; i++) { + emptyBlocks.push({ + blockSize: 0, + blockVSize: 0, + feeRange: [], + index: 0, + medianFee: 0, + nTx: 0, + totalFees: 0 + }); + } + return emptyBlocks; + } }