Add download button on pool ranking and mempool graphs
This commit is contained in:
parent
e8bb18fbc3
commit
7a487046b9
@ -1,7 +1,7 @@
|
|||||||
<div class="full-container">
|
<div class="full-container">
|
||||||
<div class="card-header mb-0 mb-md-4">
|
<div class="card-header mb-0 mb-md-4">
|
||||||
<span i18n="mining.block-fee-rates">Block fee rates</span>
|
<span i18n="mining.block-fee-rates">Block fee rates</span>
|
||||||
<button #saveChart class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
<button class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
||||||
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div class="full-container">
|
<div class="full-container">
|
||||||
<div class="card-header mb-0 mb-md-4">
|
<div class="card-header mb-0 mb-md-4">
|
||||||
<span i18n="mining.block-fees">Block fees</span>
|
<span i18n="mining.block-fees">Block fees</span>
|
||||||
<button #saveChart class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
<button class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
||||||
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div class="card-header mb-0 mb-md-4">
|
<div class="card-header mb-0 mb-md-4">
|
||||||
<span i18n="mining.block-rewards">Block rewards</span>
|
<span i18n="mining.block-rewards">Block rewards</span>
|
||||||
<button #saveChart class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
<button class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
||||||
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
<div class="card-header mb-0 mb-md-4" [style]="widget ? 'display:none' : ''">
|
<div class="card-header mb-0 mb-md-4" [style]="widget ? 'display:none' : ''">
|
||||||
<span i18n="mining.hashrate-difficulty">Hashrate & Difficulty</span>
|
<span i18n="mining.hashrate-difficulty">Hashrate & Difficulty</span>
|
||||||
<button #saveChart class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
<button class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
||||||
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div class="card-header mb-0 mb-md-4">
|
<div class="card-header mb-0 mb-md-4">
|
||||||
<span i18n="mining.pools-dominance">Mining pools dominance</span>
|
<span i18n="mining.pools-dominance">Mining pools dominance</span>
|
||||||
<button #saveChart class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
<button class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
||||||
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
<div class="echarts" echarts [initOpts]="mempoolStatsChartInitOption" [options]="mempoolStatsChartOption" (chartRendered)="rendered()"></div>
|
<div class="echarts" echarts [initOpts]="mempoolStatsChartInitOption" [options]="mempoolStatsChartOption" (chartRendered)="rendered()"
|
||||||
|
(chartInit)="onChartInit($event)">
|
||||||
|
</div>
|
||||||
<div class="text-center loadingGraphs" *ngIf="isLoading">
|
<div class="text-center loadingGraphs" *ngIf="isLoading">
|
||||||
<div class="spinner-border text-light"></div>
|
<div class="spinner-border text-light"></div>
|
||||||
</div>
|
</div>
|
@ -2,7 +2,7 @@ import { Component, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnInit }
|
|||||||
import { EChartsOption } from 'echarts';
|
import { EChartsOption } from 'echarts';
|
||||||
import { OnChanges } from '@angular/core';
|
import { OnChanges } from '@angular/core';
|
||||||
import { StorageService } from 'src/app/services/storage.service';
|
import { StorageService } from 'src/app/services/storage.service';
|
||||||
import { formatterXAxis, formatterXAxisLabel } from 'src/app/shared/graphs.utils';
|
import { download, formatterXAxis, formatterXAxisLabel } from 'src/app/shared/graphs.utils';
|
||||||
import { formatNumber } from '@angular/common';
|
import { formatNumber } from '@angular/common';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -34,6 +34,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
|
|||||||
renderer: 'svg'
|
renderer: 'svg'
|
||||||
};
|
};
|
||||||
windowPreference: string;
|
windowPreference: string;
|
||||||
|
chartInstance: any = undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(LOCALE_ID) private locale: string,
|
@Inject(LOCALE_ID) private locale: string,
|
||||||
@ -61,6 +62,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
mountChart(): void {
|
mountChart(): void {
|
||||||
this.mempoolStatsChartOption = {
|
this.mempoolStatsChartOption = {
|
||||||
|
backgroundColor: '#11131f',
|
||||||
grid: {
|
grid: {
|
||||||
height: this.height,
|
height: this.height,
|
||||||
right: this.right,
|
right: this.right,
|
||||||
@ -224,7 +226,27 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChartInit(ec) {
|
||||||
|
this.chartInstance = ec;
|
||||||
|
}
|
||||||
|
|
||||||
isMobile() {
|
isMobile() {
|
||||||
return window.innerWidth <= 767.98;
|
return window.innerWidth <= 767.98;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSaveChart(timespan) {
|
||||||
|
// @ts-ignore
|
||||||
|
const prevHeight = this.mempoolStatsChartOption.grid.height;
|
||||||
|
const now = new Date();
|
||||||
|
// @ts-ignore
|
||||||
|
this.mempoolStatsChartOption.grid.height = prevHeight + 20;
|
||||||
|
this.chartInstance.setOption(this.mempoolStatsChartOption);
|
||||||
|
download(this.chartInstance.getDataURL({
|
||||||
|
pixelRatio: 2,
|
||||||
|
excludeComponents: ['dataZoom'],
|
||||||
|
}), `incoming-vbytes-${timespan}-${now.getTime() / 1000}`);
|
||||||
|
// @ts-ignore
|
||||||
|
this.mempoolStatsChartOption.grid.height = prevHeight;
|
||||||
|
this.chartInstance.setOption(this.mempoolStatsChartOption);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { Component, OnInit, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnChanges } from '@angular/core';
|
import { Component, OnInit, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnChanges } from '@angular/core';
|
||||||
import { VbytesPipe } from 'src/app/shared/pipes/bytes-pipe/vbytes.pipe';
|
import { VbytesPipe } from 'src/app/shared/pipes/bytes-pipe/vbytes.pipe';
|
||||||
import { formatNumber } from "@angular/common";
|
import { formatNumber } from '@angular/common';
|
||||||
import { OptimizedMempoolStats } from 'src/app/interfaces/node-api.interface';
|
import { OptimizedMempoolStats } from 'src/app/interfaces/node-api.interface';
|
||||||
import { StateService } from 'src/app/services/state.service';
|
import { StateService } from 'src/app/services/state.service';
|
||||||
import { StorageService } from 'src/app/services/storage.service';
|
import { StorageService } from 'src/app/services/storage.service';
|
||||||
import { EChartsOption } from 'echarts';
|
import { EChartsOption } from 'echarts';
|
||||||
import { feeLevels, chartColors } from 'src/app/app.constants';
|
import { feeLevels, chartColors } from 'src/app/app.constants';
|
||||||
import { formatterXAxis, formatterXAxisLabel } from 'src/app/shared/graphs.utils';
|
import { download, formatterXAxis, formatterXAxisLabel } from 'src/app/shared/graphs.utils';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-mempool-graph',
|
selector: 'app-mempool-graph',
|
||||||
@ -45,6 +45,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
|||||||
feeLevelsOrdered = [];
|
feeLevelsOrdered = [];
|
||||||
chartColorsOrdered = chartColors;
|
chartColorsOrdered = chartColors;
|
||||||
inverted: boolean;
|
inverted: boolean;
|
||||||
|
chartInstance: any = undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private vbytesPipe: VbytesPipe,
|
private vbytesPipe: VbytesPipe,
|
||||||
@ -83,6 +84,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
|||||||
this.hoverIndexSerie = e.target.parent.parent.__ecComponentInfo.index;
|
this.hoverIndexSerie = e.target.parent.parent.__ecComponentInfo.index;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.chartInstance = myChart;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNewMempoolData(mempoolStats: OptimizedMempoolStats[]) {
|
handleNewMempoolData(mempoolStats: OptimizedMempoolStats[]) {
|
||||||
@ -99,7 +101,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
|||||||
generateArray(mempoolStats: OptimizedMempoolStats[]) {
|
generateArray(mempoolStats: OptimizedMempoolStats[]) {
|
||||||
const finalArray: number[][][] = [];
|
const finalArray: number[][][] = [];
|
||||||
let feesArray: number[][] = [];
|
let feesArray: number[][] = [];
|
||||||
let limitFeesTemplate = this.template === 'advanced' ? 26 : 20;
|
const limitFeesTemplate = this.template === 'advanced' ? 26 : 20;
|
||||||
for (let index = limitFeesTemplate; index > -1; index--) {
|
for (let index = limitFeesTemplate; index > -1; index--) {
|
||||||
feesArray = [];
|
feesArray = [];
|
||||||
mempoolStats.forEach((stats) => {
|
mempoolStats.forEach((stats) => {
|
||||||
@ -167,6 +169,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.mempoolVsizeFeesOptions = {
|
this.mempoolVsizeFeesOptions = {
|
||||||
|
backgroundColor: '#11131f',
|
||||||
series: this.inverted ? [...seriesGraph].reverse() : seriesGraph,
|
series: this.inverted ? [...seriesGraph].reverse() : seriesGraph,
|
||||||
hover: true,
|
hover: true,
|
||||||
color: this.inverted ? [...newColors].reverse() : newColors,
|
color: this.inverted ? [...newColors].reverse() : newColors,
|
||||||
@ -387,5 +390,21 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
|||||||
isMobile() {
|
isMobile() {
|
||||||
return window.innerWidth <= 767.98;
|
return window.innerWidth <= 767.98;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSaveChart(timespan) {
|
||||||
|
// @ts-ignore
|
||||||
|
const prevHeight = this.mempoolVsizeFeesOptions.grid.height;
|
||||||
|
const now = new Date();
|
||||||
|
// @ts-ignore
|
||||||
|
this.mempoolVsizeFeesOptions.grid.height = prevHeight + 20;
|
||||||
|
this.chartInstance.setOption(this.mempoolVsizeFeesOptions);
|
||||||
|
download(this.chartInstance.getDataURL({
|
||||||
|
pixelRatio: 2,
|
||||||
|
excludeComponents: ['dataZoom'],
|
||||||
|
}), `mempool-graph-${timespan}-${now.getTime() / 1000}`);
|
||||||
|
// @ts-ignore
|
||||||
|
this.mempoolVsizeFeesOptions.grid.height = prevHeight;
|
||||||
|
this.chartInstance.setOption(this.mempoolVsizeFeesOptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
<div class="card-header" *ngIf="!widget">
|
<div class="card-header" *ngIf="!widget">
|
||||||
<span i18n="mining.mining-pool-share">Mining pools share</span>
|
<span i18n="mining.mining-pool-share">Mining pools share</span>
|
||||||
<button #saveChart class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
<button class="btn" style="position: absolute; right: 30px" (click)="onSaveChart()">
|
||||||
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<i class="fa fa-area-chart"></i> <span i18n="statistics.memory-by-vBytes">Mempool by vBytes (sat/vByte)</span>
|
<i class="fa fa-area-chart"></i> <span i18n="statistics.memory-by-vBytes">Mempool by vBytes (sat/vByte)</span>
|
||||||
|
<button class="btn" style="position: absolute; right: 30px" (click)="onSaveChart('mempool')">
|
||||||
|
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
<form [formGroup]="radioGroupForm" class="formRadioGroup" [class]="stateService.env.MINING_DASHBOARD ? 'mining' : ''" (click)="saveGraphPreference()">
|
<form [formGroup]="radioGroupForm" class="formRadioGroup" [class]="stateService.env.MINING_DASHBOARD ? 'mining' : ''" (click)="saveGraphPreference()">
|
||||||
<div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
|
<div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
|
||||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||||
@ -60,7 +64,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="incoming-transactions-graph">
|
<div class="incoming-transactions-graph">
|
||||||
<app-mempool-graph
|
<app-mempool-graph #mempoolgraph
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
[template]="'advanced'"
|
[template]="'advanced'"
|
||||||
[limitFee]="500"
|
[limitFee]="500"
|
||||||
@ -80,9 +84,13 @@
|
|||||||
<div class="card-header">
|
<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>
|
<i class="fa fa-area-chart"></i> <span i18n="statistics.transaction-vbytes-per-second">Transaction vBytes per second (vB/s)</span>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn" style="position: absolute; right: 30px" (click)="onSaveChart('incoming')">
|
||||||
|
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="incoming-transactions-graph">
|
<div class="incoming-transactions-graph">
|
||||||
<app-incoming-transactions-graph
|
<app-incoming-transactions-graph #incominggraph
|
||||||
[height]="500"
|
[height]="500"
|
||||||
[left]="65"
|
[left]="65"
|
||||||
[template]="'advanced'"
|
[template]="'advanced'"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit, LOCALE_ID, Inject } from '@angular/core';
|
import { Component, OnInit, LOCALE_ID, Inject, ViewChild, ElementRef } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { FormGroup, FormBuilder } from '@angular/forms';
|
import { FormGroup, FormBuilder } from '@angular/forms';
|
||||||
import { of, merge} from 'rxjs';
|
import { of, merge} from 'rxjs';
|
||||||
@ -12,6 +12,8 @@ import { StateService } from 'src/app/services/state.service';
|
|||||||
import { SeoService } from 'src/app/services/seo.service';
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
import { StorageService } from 'src/app/services/storage.service';
|
import { StorageService } from 'src/app/services/storage.service';
|
||||||
import { feeLevels, chartColors } from 'src/app/app.constants';
|
import { feeLevels, chartColors } from 'src/app/app.constants';
|
||||||
|
import { MempoolGraphComponent } from '../mempool-graph/mempool-graph.component';
|
||||||
|
import { IncomingTransactionsGraphComponent } from '../incoming-transactions-graph/incoming-transactions-graph.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-statistics',
|
selector: 'app-statistics',
|
||||||
@ -19,6 +21,9 @@ import { feeLevels, chartColors } from 'src/app/app.constants';
|
|||||||
styleUrls: ['./statistics.component.scss']
|
styleUrls: ['./statistics.component.scss']
|
||||||
})
|
})
|
||||||
export class StatisticsComponent implements OnInit {
|
export class StatisticsComponent implements OnInit {
|
||||||
|
@ViewChild('mempoolgraph') mempoolGraph: MempoolGraphComponent;
|
||||||
|
@ViewChild('incominggraph') incomingGraph: IncomingTransactionsGraphComponent;
|
||||||
|
|
||||||
network = '';
|
network = '';
|
||||||
|
|
||||||
loading = true;
|
loading = true;
|
||||||
@ -38,6 +43,7 @@ export class StatisticsComponent implements OnInit {
|
|||||||
graphWindowPreference: string;
|
graphWindowPreference: string;
|
||||||
inverted: boolean;
|
inverted: boolean;
|
||||||
feeLevelDropdownData = [];
|
feeLevelDropdownData = [];
|
||||||
|
timespan = '';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(LOCALE_ID) private locale: string,
|
@Inject(LOCALE_ID) private locale: string,
|
||||||
@ -75,6 +81,7 @@ export class StatisticsComponent implements OnInit {
|
|||||||
)
|
)
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(() => {
|
switchMap(() => {
|
||||||
|
this.timespan = this.radioGroupForm.controls.dateSpan.value;
|
||||||
this.spinnerLoading = true;
|
this.spinnerLoading = true;
|
||||||
if (this.radioGroupForm.controls.dateSpan.value === '2h') {
|
if (this.radioGroupForm.controls.dateSpan.value === '2h') {
|
||||||
this.websocketService.want(['blocks', 'live-2h-chart']);
|
this.websocketService.want(['blocks', 'live-2h-chart']);
|
||||||
@ -195,4 +202,12 @@ export class StatisticsComponent implements OnInit {
|
|||||||
stat.vbytes_per_second = Math.min(median * capRatio, stat.vbytes_per_second);
|
stat.vbytes_per_second = Math.min(median * capRatio, stat.vbytes_per_second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSaveChart(name) {
|
||||||
|
if (name === 'mempool') {
|
||||||
|
this.mempoolGraph.onSaveChart(this.timespan);
|
||||||
|
} else if (name === 'incoming') {
|
||||||
|
this.incomingGraph.onSaveChart(this.timespan);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user