Polish clocks, fix urls, make interactive
This commit is contained in:
		
							parent
							
								
									6076eeed46
								
							
						
					
					
						commit
						ec0d5e0c23
					
				@ -4,8 +4,7 @@ import { AppPreloadingStrategy } from './app.preloading-strategy'
 | 
			
		||||
import { StartComponent } from './components/start/start.component';
 | 
			
		||||
import { TransactionComponent } from './components/transaction/transaction.component';
 | 
			
		||||
import { BlockComponent } from './components/block/block.component';
 | 
			
		||||
import { ClockMinedComponent as ClockMinedComponent } from './components/clock/clock-mined.component';
 | 
			
		||||
import { ClockMempoolComponent as ClockMempoolComponent } from './components/clock/clock-mempool.component';
 | 
			
		||||
import { ClockComponent } from './components/clock/clock.component';
 | 
			
		||||
import { AddressComponent } from './components/address/address.component';
 | 
			
		||||
import { MasterPageComponent } from './components/master-page/master-page.component';
 | 
			
		||||
import { AboutComponent } from './components/about/about.component';
 | 
			
		||||
@ -358,12 +357,16 @@ let routes: Routes = [
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'clock-mined',
 | 
			
		||||
    component: ClockMinedComponent,
 | 
			
		||||
    path: 'clock',
 | 
			
		||||
    redirectTo: 'clock/mined/0'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'clock-mempool',
 | 
			
		||||
    component: ClockMempoolComponent,
 | 
			
		||||
    path: 'clock/:mode',
 | 
			
		||||
    redirectTo: 'clock/:mode/0'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'clock/:mode/:index',
 | 
			
		||||
    component: ClockComponent,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'status',
 | 
			
		||||
 | 
			
		||||
@ -13,10 +13,10 @@
 | 
			
		||||
        [class.offscreen]="!static && count && i >= count"
 | 
			
		||||
        id="bitcoin-block-{{ block.height }}" [ngStyle]="blockStyles[i]"
 | 
			
		||||
        [class.blink-bg]="isSpecial(block.height)">
 | 
			
		||||
        <a draggable="false" [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }"
 | 
			
		||||
        <a draggable="false" [routerLink]="[getHref(i, block) | relativeUrl]" [state]="{ data: { block: block } }"
 | 
			
		||||
          class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}"> </a>
 | 
			
		||||
        <div *ngIf="!minimal" [attr.data-cy]="'bitcoin-block-' + i + '-height'" class="block-height">
 | 
			
		||||
          <a [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height
 | 
			
		||||
          <a [routerLink]="[getHref(i, block) | relativeUrl]" [state]="{ data: { block: block } }">{{ block.height
 | 
			
		||||
            }}</a>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="block-body">
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  @Input() minimal: boolean = false;
 | 
			
		||||
  @Input() blockWidth: number = 125;
 | 
			
		||||
  @Input() spotlight: number = 0;
 | 
			
		||||
  @Input() getHref?: (index, block) => string = (index, block) => `/block/${block.id}`;
 | 
			
		||||
  
 | 
			
		||||
  specialBlocks = specialBlocks;
 | 
			
		||||
  network = '';
 | 
			
		||||
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
<app-clock mode="mempool"></app-clock>
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
import { Component } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-clock-mempool',
 | 
			
		||||
  templateUrl: './clock-mempool.component.html',
 | 
			
		||||
})
 | 
			
		||||
export class ClockMempoolComponent {}
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
<app-clock mode="block"></app-clock>
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
import { Component } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-clock-mined',
 | 
			
		||||
  templateUrl: './clock-mined.component.html',
 | 
			
		||||
})
 | 
			
		||||
export class ClockMinedComponent {}
 | 
			
		||||
@ -1,14 +1,19 @@
 | 
			
		||||
<div class="clock-wrapper" [style]="wrapperStyle">
 | 
			
		||||
  <div class="clockchain-bar" [style.height]="chainHeight + 'px'">
 | 
			
		||||
    <div class="clockchain">
 | 
			
		||||
      <app-clockchain [width]="chainWidth" [height]="chainHeight" [mode]="mode"></app-clockchain>
 | 
			
		||||
      <app-clockchain
 | 
			
		||||
        [width]="chainWidth"
 | 
			
		||||
        [height]="chainHeight"
 | 
			
		||||
        [mode]="mode"
 | 
			
		||||
        [index]="blockIndex"
 | 
			
		||||
      ></app-clockchain>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="clock-face">
 | 
			
		||||
    <app-clock-face [size]="clockSize">
 | 
			
		||||
      <div class="block-wrapper">
 | 
			
		||||
        <ng-container *ngIf="block && block.height >= 0">
 | 
			
		||||
          <ng-container *ngIf="mode === 'block'; else mempoolMode;">
 | 
			
		||||
        <ng-container *ngIf="blocks && blocks.length">
 | 
			
		||||
          <ng-container *ngIf="mode === 'mined'; else mempoolMode;">
 | 
			
		||||
            <div class="block-cube">
 | 
			
		||||
              <div class="side top"></div>
 | 
			
		||||
              <div class="side bottom"></div>
 | 
			
		||||
@ -20,12 +25,12 @@
 | 
			
		||||
          </ng-container>
 | 
			
		||||
          <ng-template #mempoolMode>
 | 
			
		||||
            <div class="block-sizer" [style]="blockSizerStyle">
 | 
			
		||||
              <app-mempool-block-overview [index]="0" [pixelAlign]="true"></app-mempool-block-overview>
 | 
			
		||||
              <app-mempool-block-overview [index]="blockIndex" [pixelAlign]="true"></app-mempool-block-overview>
 | 
			
		||||
            </div>
 | 
			
		||||
          </ng-template>
 | 
			
		||||
          <div class="fader"></div>
 | 
			
		||||
          <div class="title-wrapper">
 | 
			
		||||
            <h1 class="block-height">{{ block.height }}</h1>
 | 
			
		||||
            <h1 class="block-height">{{ blocks[mode === 'mempool' ? 0 : blockIndex].height }}</h1>
 | 
			
		||||
          </div>
 | 
			
		||||
        </ng-container>
 | 
			
		||||
      </div>
 | 
			
		||||
@ -42,13 +47,13 @@
 | 
			
		||||
      <p class="label" i18n="clock.priority-rate|priority fee rate">priority rate</p>
 | 
			
		||||
      <p *ngIf="recommendedFees$ | async as recommendedFees;" i18n="shared.sat-vbyte|sat/vB">{{ recommendedFees.fastestFee }} sat/vB</p>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div *ngIf="mode !== 'mempool' && block" class="stats bottom left">
 | 
			
		||||
      <p [innerHTML]="block.size | bytes: 2"></p>
 | 
			
		||||
    <div *ngIf="mode !== 'mempool' && blocks?.length" class="stats bottom left">
 | 
			
		||||
      <p [innerHTML]="blocks[blockIndex].size | bytes: 2"></p>
 | 
			
		||||
      <p class="label" i18n="clock.block-size">block size</p>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div *ngIf="mode !== 'mempool' && block" class="stats bottom right">
 | 
			
		||||
    <div *ngIf="mode !== 'mempool' && blocks?.length" class="stats bottom right">
 | 
			
		||||
      <p class="force-wrap">
 | 
			
		||||
        <ng-container *ngTemplateOutlet="block.tx_count === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: block.tx_count | number}"></ng-container>
 | 
			
		||||
        <ng-container *ngTemplateOutlet="blocks[blockIndex].tx_count === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: blocks[blockIndex].tx_count | number}"></ng-container>
 | 
			
		||||
        <ng-template #transactionsSingular let-i i18n="shared.transaction-count.singular">{{ i }} <span class="label">transaction</span></ng-template>
 | 
			
		||||
        <ng-template #transactionsPlural let-i i18n="shared.transaction-count.plural">{{ i }} <span class="label">transactions</span></ng-template>
 | 
			
		||||
      </p>
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,11 @@
 | 
			
		||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, Input, OnInit } from '@angular/core';
 | 
			
		||||
import { Observable, Subscription } from 'rxjs';
 | 
			
		||||
import { Observable, Subscription, of, switchMap, tap } from 'rxjs';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { BlockExtended } from '../../interfaces/node-api.interface';
 | 
			
		||||
import { WebsocketService } from '../../services/websocket.service';
 | 
			
		||||
import { MempoolInfo, Recommendedfees } from '../../interfaces/websocket.interface';
 | 
			
		||||
import { ActivatedRoute } from '@angular/router';
 | 
			
		||||
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
 | 
			
		||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-clock',
 | 
			
		||||
@ -13,12 +14,14 @@ import { ActivatedRoute } from '@angular/router';
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush,
 | 
			
		||||
})
 | 
			
		||||
export class ClockComponent implements OnInit {
 | 
			
		||||
  @Input() mode: 'block' | 'mempool' = 'block';
 | 
			
		||||
  hideStats: boolean = false;
 | 
			
		||||
  mode: 'mempool' | 'mined' = 'mined';
 | 
			
		||||
  blockIndex: number;
 | 
			
		||||
  pageSubscription: Subscription;
 | 
			
		||||
  blocksSubscription: Subscription;
 | 
			
		||||
  recommendedFees$: Observable<Recommendedfees>;
 | 
			
		||||
  mempoolInfo$: Observable<MempoolInfo>;
 | 
			
		||||
  block: BlockExtended;
 | 
			
		||||
  blocks: BlockExtended[] = [];
 | 
			
		||||
  clockSize: number = 300;
 | 
			
		||||
  chainWidth: number = 384;
 | 
			
		||||
  chainHeight: number = 60;
 | 
			
		||||
@ -41,6 +44,8 @@ export class ClockComponent implements OnInit {
 | 
			
		||||
    public stateService: StateService,
 | 
			
		||||
    private websocketService: WebsocketService,
 | 
			
		||||
    private route: ActivatedRoute,
 | 
			
		||||
    private router: Router,
 | 
			
		||||
    private relativeUrlPipe: RelativeUrlPipe,
 | 
			
		||||
    private cd: ChangeDetectorRef,
 | 
			
		||||
  ) {
 | 
			
		||||
    this.route.queryParams.subscribe((params) => {
 | 
			
		||||
@ -57,14 +62,40 @@ export class ClockComponent implements OnInit {
 | 
			
		||||
    this.blocksSubscription = this.stateService.blocks$
 | 
			
		||||
      .subscribe(([block]) => {
 | 
			
		||||
        if (block) {
 | 
			
		||||
          this.block = block;
 | 
			
		||||
          this.blockStyle = this.getStyleForBlock(this.block);
 | 
			
		||||
          this.cd.markForCheck();
 | 
			
		||||
          this.blocks.unshift(block);
 | 
			
		||||
          this.blocks = this.blocks.slice(0, 16);
 | 
			
		||||
          if (this.blocks[this.blockIndex]) {
 | 
			
		||||
            this.blockStyle = this.getStyleForBlock(this.blocks[this.blockIndex]);
 | 
			
		||||
            this.cd.markForCheck();
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    this.recommendedFees$ = this.stateService.recommendedFees$;
 | 
			
		||||
    this.mempoolInfo$ = this.stateService.mempoolInfo$;
 | 
			
		||||
 | 
			
		||||
    this.pageSubscription = this.route.paramMap.pipe(
 | 
			
		||||
      switchMap((params: ParamMap) => {
 | 
			
		||||
        const rawMode: string = params.get('mode');
 | 
			
		||||
        const mode = rawMode === 'mempool' ? 'mempool' : 'mined';
 | 
			
		||||
        const index: number = Number.parseInt(params.get('index'));
 | 
			
		||||
        if (mode !== rawMode || index < 0 || isNaN(index)) {
 | 
			
		||||
          this.router.navigate([this.relativeUrlPipe.transform('/clock'), mode, index || 0]);
 | 
			
		||||
        }
 | 
			
		||||
        return of({
 | 
			
		||||
          mode,
 | 
			
		||||
          index,
 | 
			
		||||
        });
 | 
			
		||||
      }),
 | 
			
		||||
      tap((page: { mode: 'mempool' | 'mined', index: number }) => {
 | 
			
		||||
        this.mode = page.mode;
 | 
			
		||||
        this.blockIndex = page.index || 0;
 | 
			
		||||
        if (this.blocks[this.blockIndex]) {
 | 
			
		||||
          this.blockStyle = this.getStyleForBlock(this.blocks[this.blockIndex]);
 | 
			
		||||
          this.cd.markForCheck();
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    ).subscribe();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getStyleForBlock(block: BlockExtended) {
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,20 @@
 | 
			
		||||
  <div class="position-container" [ngClass]="network ? network : ''" [style.top]="(height / 3) + 'px'">
 | 
			
		||||
    <span>
 | 
			
		||||
      <div class="blocks-wrapper">
 | 
			
		||||
        <app-mempool-blocks [minimal]="true" [count]="mempoolBlocks" [blockWidth]="blockWidth" [spotlight]="mode === 'mempool' ? 1 : 0"></app-mempool-blocks>
 | 
			
		||||
        <app-blockchain-blocks [minimal]="true" [count]="blockchainBlocks" [blockWidth]="blockWidth" [spotlight]="mode === 'block' ? -1 : 0"></app-blockchain-blocks>
 | 
			
		||||
        <app-mempool-blocks
 | 
			
		||||
          [minimal]="true"
 | 
			
		||||
          [count]="mempoolBlocks"
 | 
			
		||||
          [blockWidth]="blockWidth"
 | 
			
		||||
          [spotlight]="mode === 'mempool' ? index + 1 : 0"
 | 
			
		||||
          [getHref]="getMempoolUrl"
 | 
			
		||||
        ></app-mempool-blocks>
 | 
			
		||||
        <app-blockchain-blocks
 | 
			
		||||
          [minimal]="true"
 | 
			
		||||
          [count]="blockchainBlocks"
 | 
			
		||||
          [blockWidth]="blockWidth"
 | 
			
		||||
          [spotlight]="mode === 'mined' ? -index - 1 : 0"
 | 
			
		||||
          [getHref]="getMinedUrl"
 | 
			
		||||
        ></app-blockchain-blocks>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="divider" [style.top]="-(height / 6) + 'px'">
 | 
			
		||||
        <svg
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,8 @@ import { StateService } from '../../services/state.service';
 | 
			
		||||
export class ClockchainComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  @Input() width: number = 300;
 | 
			
		||||
  @Input() height: number = 60;
 | 
			
		||||
  @Input() mode: 'mempool' | 'block';
 | 
			
		||||
  @Input() mode: 'mempool' | 'mined';
 | 
			
		||||
  @Input() index: number = 0;
 | 
			
		||||
 | 
			
		||||
  mempoolBlocks: number = 3;
 | 
			
		||||
  blockchainBlocks: number = 6;
 | 
			
		||||
@ -70,4 +71,12 @@ export class ClockchainComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
    this.ltrTransitionEnabled = true;
 | 
			
		||||
    this.stateService.timeLtr.next(!this.timeLtr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getMempoolUrl(index): string {
 | 
			
		||||
    return `/clock/mempool/${index}`;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getMinedUrl(index): string {
 | 
			
		||||
    return `/clock/block/${index}`;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@
 | 
			
		||||
          [style.right]="mempoolBlockStyles[i].right"
 | 
			
		||||
        ></div>
 | 
			
		||||
        <div @blockEntryTrigger [@.disabled]="i > 0 || !animateEntry" [attr.data-cy]="'mempool-block-' + i" class="bitcoin-block text-center mempool-block" [class.hide-block]="count && i >= count" id="mempool-block-{{ i }}" [ngStyle]="mempoolBlockStyles[i]" [class.blink-bg]="projectedBlock.blink">
 | 
			
		||||
          <a draggable="false" [routerLink]="['/mempool-block/' | relativeUrl, i]"
 | 
			
		||||
          <a draggable="false" [routerLink]="[getHref(i) | relativeUrl]"
 | 
			
		||||
            class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}"> </a>
 | 
			
		||||
          <div class="block-body">
 | 
			
		||||
            <ng-container *ngIf="!minimal">
 | 
			
		||||
 | 
			
		||||
@ -28,6 +28,7 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  @Input() blockWidth: number = 125;
 | 
			
		||||
  @Input() count: number = null;
 | 
			
		||||
  @Input() spotlight: number = 0;
 | 
			
		||||
  @Input() getHref?: (index) => string = (index) => `/mempool-block/${index}`;
 | 
			
		||||
 | 
			
		||||
  specialBlocks = specialBlocks;
 | 
			
		||||
  mempoolBlocks: MempoolBlock[] = [];
 | 
			
		||||
 | 
			
		||||
@ -95,8 +95,6 @@ import { MempoolBlockOverviewComponent } from '../components/mempool-block-overv
 | 
			
		||||
import { ClockchainComponent } from '../components/clockchain/clockchain.component';
 | 
			
		||||
import { ClockFaceComponent } from '../components/clock-face/clock-face.component';
 | 
			
		||||
import { ClockComponent } from '../components/clock/clock.component';
 | 
			
		||||
import { ClockMinedComponent } from '../components/clock/clock-mined.component';
 | 
			
		||||
import { ClockMempoolComponent } from '../components/clock/clock-mempool.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
@ -185,8 +183,6 @@ import { ClockMempoolComponent } from '../components/clock/clock-mempool.compone
 | 
			
		||||
    MempoolBlockOverviewComponent,
 | 
			
		||||
    ClockchainComponent,
 | 
			
		||||
    ClockComponent,
 | 
			
		||||
    ClockMinedComponent,
 | 
			
		||||
    ClockMempoolComponent,
 | 
			
		||||
    ClockFaceComponent,
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
@ -300,8 +296,6 @@ import { ClockMempoolComponent } from '../components/clock/clock-mempool.compone
 | 
			
		||||
    MempoolBlockOverviewComponent,
 | 
			
		||||
    ClockchainComponent,
 | 
			
		||||
    ClockComponent,
 | 
			
		||||
    ClockMinedComponent,
 | 
			
		||||
    ClockMempoolComponent,
 | 
			
		||||
    ClockFaceComponent,
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user