Add sankey diagram to main tx page
This commit is contained in:
parent
5e1ca44a7f
commit
1e5cef4a62
@ -190,6 +190,24 @@
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<div class="title">
|
||||||
|
<h2 i18n="transaction.diagram|Transaction diagram">Diagram</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<div class="graph-container" #graphContainer>
|
||||||
|
<tx-bowtie-graph [tx]="tx" [width]="graphWidth" [height]="graphExpanded ? (maxInOut * 15) : 360" [maxStrands]="graphExpanded ? maxInOut : 24" [network]="network"></tx-bowtie-graph>
|
||||||
|
</div>
|
||||||
|
<div class="toggle-wrapper" *ngIf="maxInOut > 24">
|
||||||
|
<button class="btn btn-sm btn-primary graph-toggle" (click)="expandGraph();" *ngIf="!graphExpanded; else collapseBtn"><span i18n="show-more">Show more</span></button>
|
||||||
|
<ng-template #collapseBtn>
|
||||||
|
<button class="btn btn-sm btn-primary graph-toggle" (click)="collapseGraph();"><span i18n="show-less">Show less</span></button>
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
<div class="title float-left">
|
<div class="title float-left">
|
||||||
<h2 i18n="transaction.inputs-and-outputs|Transaction inputs and outputs">Inputs & Outputs</h2>
|
<h2 i18n="transaction.inputs-and-outputs|Transaction inputs and outputs">Inputs & Outputs</h2>
|
||||||
</div>
|
</div>
|
||||||
@ -283,6 +301,36 @@
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<div class="title">
|
||||||
|
<h2 i18n="transaction.diagram|Transaction diagram">Diagram</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<div class="graph-container" #graphContainer style="visibility: hidden;"></div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm">
|
||||||
|
<table class="table table-borderless table-striped">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><span class="skeleton-loader"></span></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<table class="table table-borderless table-striped">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><span class="skeleton-loader"></span></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<h2 i18n="transaction.inputs-and-outputs|Transaction inputs and outputs">Inputs & Outputs</h2>
|
<h2 i18n="transaction.inputs-and-outputs|Transaction inputs and outputs">Inputs & Outputs</h2>
|
||||||
</div>
|
</div>
|
||||||
|
@ -73,6 +73,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.graph-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
background: #181b2d;
|
||||||
|
padding: 10px;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
margin: 1.25em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graph-toggle {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 767.98px) {
|
@media (max-width: 767.98px) {
|
||||||
.mobile-bottomcol {
|
.mobile-bottomcol {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
import { Component, OnInit, AfterViewInit, OnDestroy, HostListener, ViewChild, ElementRef } from '@angular/core';
|
||||||
import { ElectrsApiService } from '../../services/electrs-api.service';
|
import { ElectrsApiService } from '../../services/electrs-api.service';
|
||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
import {
|
import {
|
||||||
@ -24,7 +24,7 @@ import { LiquidUnblinding } from './liquid-ublinding';
|
|||||||
templateUrl: './transaction.component.html',
|
templateUrl: './transaction.component.html',
|
||||||
styleUrls: ['./transaction.component.scss'],
|
styleUrls: ['./transaction.component.scss'],
|
||||||
})
|
})
|
||||||
export class TransactionComponent implements OnInit, OnDestroy {
|
export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
network = '';
|
network = '';
|
||||||
tx: Transaction;
|
tx: Transaction;
|
||||||
txId: string;
|
txId: string;
|
||||||
@ -47,6 +47,12 @@ export class TransactionComponent implements OnInit, OnDestroy {
|
|||||||
timeAvg$: Observable<number>;
|
timeAvg$: Observable<number>;
|
||||||
liquidUnblinding = new LiquidUnblinding();
|
liquidUnblinding = new LiquidUnblinding();
|
||||||
outputIndex: number;
|
outputIndex: number;
|
||||||
|
graphExpanded: boolean = false;
|
||||||
|
graphWidth: number = 1000;
|
||||||
|
maxInOut: number = 0;
|
||||||
|
|
||||||
|
@ViewChild('graphContainer')
|
||||||
|
graphContainer: ElementRef;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
@ -167,6 +173,7 @@ export class TransactionComponent implements OnInit, OnDestroy {
|
|||||||
this.waitingForTransaction = false;
|
this.waitingForTransaction = false;
|
||||||
this.setMempoolBlocksSubscription();
|
this.setMempoolBlocksSubscription();
|
||||||
this.websocketService.startTrackTransaction(tx.txid);
|
this.websocketService.startTrackTransaction(tx.txid);
|
||||||
|
this.setupGraph();
|
||||||
|
|
||||||
if (!tx.status.confirmed && tx.firstSeen) {
|
if (!tx.status.confirmed && tx.firstSeen) {
|
||||||
this.transactionTime = tx.firstSeen;
|
this.transactionTime = tx.firstSeen;
|
||||||
@ -222,6 +229,10 @@ export class TransactionComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
this.setGraphSize();
|
||||||
|
}
|
||||||
|
|
||||||
handleLoadElectrsTransactionError(error: any): Observable<any> {
|
handleLoadElectrsTransactionError(error: any): Observable<any> {
|
||||||
if (error.status === 404 && /^[a-fA-F0-9]{64}$/.test(this.txId)) {
|
if (error.status === 404 && /^[a-fA-F0-9]{64}$/.test(this.txId)) {
|
||||||
this.websocketService.startMultiTrackTransaction(this.txId);
|
this.websocketService.startMultiTrackTransaction(this.txId);
|
||||||
@ -284,6 +295,26 @@ export class TransactionComponent implements OnInit, OnDestroy {
|
|||||||
return +(cpfpTx.fee / (cpfpTx.weight / 4)).toFixed(1);
|
return +(cpfpTx.fee / (cpfpTx.weight / 4)).toFixed(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupGraph() {
|
||||||
|
this.maxInOut = Math.min(250, Math.max(this.tx?.vin?.length || 1, this.tx?.vout?.length || 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
expandGraph() {
|
||||||
|
this.graphExpanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
collapseGraph() {
|
||||||
|
this.graphExpanded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('window:resize', ['$event'])
|
||||||
|
setGraphSize(): void {
|
||||||
|
console.log('resize', this.graphContainer);
|
||||||
|
if (this.graphContainer) {
|
||||||
|
this.graphWidth = this.graphContainer.nativeElement.clientWidth - 24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.subscription.unsubscribe();
|
this.subscription.unsubscribe();
|
||||||
this.fetchCpfpSubscription.unsubscribe();
|
this.fetchCpfpSubscription.unsubscribe();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user