Improve mining graphs timespan selection UX
This commit is contained in:
parent
848e02eca0
commit
7dd0173e84
@ -27,6 +27,7 @@ class Mining {
|
||||
case '3m': timeRange = 7200; break; // 2h
|
||||
case '1m': timeRange = 1800; break; // 30min
|
||||
case '1w': timeRange = 300; break; // 5min
|
||||
case '3d': timeRange = 1; break;
|
||||
case '24h': timeRange = 1; break;
|
||||
default: timeRange = 86400; break; // 24h
|
||||
}
|
||||
|
@ -1,41 +1,43 @@
|
||||
<div [class]="widget === false ? 'full-container' : ''">
|
||||
|
||||
<div class="card-header mb-0 mb-md-4" [style]="widget ? 'display:none' : ''">
|
||||
<div class="full-container">
|
||||
<div class="card-header mb-0 mb-md-4">
|
||||
<span i18n="mining.block-fees">Block fees</span>
|
||||
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as hashrates">
|
||||
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as stats">
|
||||
<div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 1">
|
||||
<input ngbButton type="radio" [value]="'24h'"> 24h
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 1">
|
||||
<input ngbButton type="radio" [value]="'24h'" fragment="24h"> 24h
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 7">
|
||||
<input ngbButton type="radio" [value]="'1w'"> 1W
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 3">
|
||||
<input ngbButton type="radio" [value]="'3d'" fragment="3d"> 3D
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 30">
|
||||
<input ngbButton type="radio" [value]="'1m'"> 1M
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 7">
|
||||
<input ngbButton type="radio" [value]="'1w'" fragment="1w"> 1W
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 90">
|
||||
<input ngbButton type="radio" [value]="'3m'"> 3M
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 30">
|
||||
<input ngbButton type="radio" [value]="'1m'" fragment="1m"> 1M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 180">
|
||||
<input ngbButton type="radio" [value]="'6m'"> 6M
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 90">
|
||||
<input ngbButton type="radio" [value]="'3m'" fragment="3m"> 3M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 365">
|
||||
<input ngbButton type="radio" [value]="'1y'"> 1Y
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 180">
|
||||
<input ngbButton type="radio" [value]="'6m'" fragment="6m"> 6M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 730">
|
||||
<input ngbButton type="radio" [value]="'2y'"> 2Y
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 365">
|
||||
<input ngbButton type="radio" [value]="'1y'" fragment="1y"> 1Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 1095">
|
||||
<input ngbButton type="radio" [value]="'3y'"> 3Y
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 730">
|
||||
<input ngbButton type="radio" [value]="'2y'" fragment="2y"> 2Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'"> ALL
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 1095">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay > 1095">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all"> ALL
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div [class]="!widget ? 'chart' : 'chart-widget'" echarts [initOpts]="chartInitOptions" [options]="chartOptions">
|
||||
<div class="chart" echarts [initOpts]="chartInitOptions" [options]="chartOptions">
|
||||
</div>
|
||||
<div class="text-center loadingGraphs" *ngIf="isLoading">
|
||||
<div class="spinner-border text-light"></div>
|
||||
|
@ -7,6 +7,8 @@ import { SeoService } from 'src/app/services/seo.service';
|
||||
import { formatNumber } from '@angular/common';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { formatterXAxisLabel } from 'src/app/shared/graphs.utils';
|
||||
import { StorageService } from 'src/app/services/storage.service';
|
||||
import { MiningService } from 'src/app/services/mining.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-block-fees-graph',
|
||||
@ -24,10 +26,10 @@ import { formatterXAxisLabel } from 'src/app/shared/graphs.utils';
|
||||
})
|
||||
export class BlockFeesGraphComponent implements OnInit {
|
||||
@Input() tableOnly = false;
|
||||
@Input() widget = false;
|
||||
@Input() right: number | string = 45;
|
||||
@Input() left: number | string = 75;
|
||||
|
||||
miningWindowPreference: string;
|
||||
radioGroupForm: FormGroup;
|
||||
|
||||
chartOptions: EChartsOption = {};
|
||||
@ -44,21 +46,25 @@ export class BlockFeesGraphComponent implements OnInit {
|
||||
@Inject(LOCALE_ID) public locale: string,
|
||||
private seoService: SeoService,
|
||||
private apiService: ApiService,
|
||||
private formBuilder: FormBuilder
|
||||
private formBuilder: FormBuilder,
|
||||
private storageService: StorageService,
|
||||
private miningService: MiningService
|
||||
) {
|
||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' });
|
||||
this.radioGroupForm.controls.dateSpan.setValue('1y');
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (!this.widget) {
|
||||
this.seoService.setTitle($localize`:@@mining.block-fees:Block Fees`);
|
||||
}
|
||||
this.seoService.setTitle($localize`:@@mining.block-fees:Block Fees`);
|
||||
this.miningWindowPreference = this.miningService.getDefaultTimespan('24h');
|
||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.miningWindowPreference });
|
||||
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
|
||||
|
||||
this.statsObservable$ = this.radioGroupForm.get('dateSpan').valueChanges
|
||||
.pipe(
|
||||
startWith('1y'),
|
||||
startWith(this.miningWindowPreference),
|
||||
switchMap((timespan) => {
|
||||
this.storageService.setValue('miningWindowPreference', timespan);
|
||||
this.timespan = timespan;
|
||||
this.isLoading = true;
|
||||
return this.apiService.getHistoricalBlockFees$(timespan)
|
||||
@ -103,7 +109,7 @@ export class BlockFeesGraphComponent implements OnInit {
|
||||
left: this.left,
|
||||
},
|
||||
tooltip: {
|
||||
show: !this.isMobile() || !this.widget,
|
||||
show: !this.isMobile(),
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'line'
|
||||
@ -161,7 +167,7 @@ export class BlockFeesGraphComponent implements OnInit {
|
||||
},
|
||||
},
|
||||
],
|
||||
dataZoom: this.widget ? null : [{
|
||||
dataZoom: [{
|
||||
type: 'inside',
|
||||
realtime: true,
|
||||
zoomLock: true,
|
||||
|
@ -20,25 +20,28 @@
|
||||
|
||||
<div class="card-header mb-0 mb-md-4" [style]="widget ? 'display:none' : ''">
|
||||
<span i18n="mining.hashrate-difficulty">Hashrate & Difficulty</span>
|
||||
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(hashrateObservable$ | async) as hashrates">
|
||||
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(hashrateObservable$ | async) as stats">
|
||||
<div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 90">
|
||||
<input ngbButton type="radio" [value]="'3m'"> 3M
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 30">
|
||||
<input ngbButton type="radio" [value]="'1m'" fragment="1m"> 1M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 180">
|
||||
<input ngbButton type="radio" [value]="'6m'"> 6M
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 90">
|
||||
<input ngbButton type="radio" [value]="'3m'" fragment="3m"> 3M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 365">
|
||||
<input ngbButton type="radio" [value]="'1y'"> 1Y
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 180">
|
||||
<input ngbButton type="radio" [value]="'6m'" fragment="6m"> 6M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 730">
|
||||
<input ngbButton type="radio" [value]="'2y'"> 2Y
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 365">
|
||||
<input ngbButton type="radio" [value]="'1y'" fragment="1y"> 1Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 1095">
|
||||
<input ngbButton type="radio" [value]="'3y'"> 3Y
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 730">
|
||||
<input ngbButton type="radio" [value]="'2y'" fragment="2y"> 2Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'"> ALL
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 1095">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay > 1095">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all"> ALL
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -132,4 +132,4 @@
|
||||
display: block;
|
||||
max-width: 80px;
|
||||
margin: 15px auto 3px;
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ import { SeoService } from 'src/app/services/seo.service';
|
||||
import { formatNumber } from '@angular/common';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { selectPowerOfTen } from 'src/app/bitcoin.utils';
|
||||
import { StorageService } from 'src/app/services/storage.service';
|
||||
import { MiningService } from 'src/app/services/mining.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hashrate-chart',
|
||||
@ -28,6 +30,7 @@ export class HashrateChartComponent implements OnInit {
|
||||
@Input() right: number | string = 45;
|
||||
@Input() left: number | string = 75;
|
||||
|
||||
miningWindowPreference: string;
|
||||
radioGroupForm: FormGroup;
|
||||
|
||||
chartOptions: EChartsOption = {};
|
||||
@ -47,20 +50,32 @@ export class HashrateChartComponent implements OnInit {
|
||||
private apiService: ApiService,
|
||||
private formBuilder: FormBuilder,
|
||||
private cd: ChangeDetectorRef,
|
||||
private storageService: StorageService,
|
||||
private miningService: MiningService
|
||||
) {
|
||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' });
|
||||
this.radioGroupForm.controls.dateSpan.setValue('1y');
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (!this.widget) {
|
||||
let firstRun = true;
|
||||
|
||||
if (this.widget) {
|
||||
this.miningWindowPreference = '1y';
|
||||
} else {
|
||||
this.seoService.setTitle($localize`:@@mining.hashrate-difficulty:Hashrate and Difficulty`);
|
||||
this.miningWindowPreference = this.miningService.getDefaultTimespan('1m');
|
||||
}
|
||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.miningWindowPreference });
|
||||
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
|
||||
|
||||
this.hashrateObservable$ = this.radioGroupForm.get('dateSpan').valueChanges
|
||||
.pipe(
|
||||
startWith('1y'),
|
||||
startWith(this.miningWindowPreference),
|
||||
switchMap((timespan) => {
|
||||
if (!this.widget && !firstRun) {
|
||||
this.storageService.setValue('miningWindowPreference', timespan);
|
||||
}
|
||||
firstRun = false;
|
||||
this.miningWindowPreference = timespan;
|
||||
this.isLoading = true;
|
||||
return this.apiService.getHistoricalHashrate$(timespan)
|
||||
.pipe(
|
||||
|
@ -1,32 +1,35 @@
|
||||
<div [class]="widget === false ? 'full-container' : ''">
|
||||
<div class="full-container">
|
||||
|
||||
<div class="card-header mb-0 mb-md-4" [style]="widget ? 'display:none' : ''">
|
||||
<span *ngIf="!widget" i18n="mining.pools-dominance">Mining pools dominance</span>
|
||||
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(hashrateObservable$ | async) as hashrates">
|
||||
<div class="card-header mb-0 mb-md-4">
|
||||
<span i18n="mining.pools-dominance">Mining pools dominance</span>
|
||||
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(hashrateObservable$ | async) as stats">
|
||||
<div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 90">
|
||||
<input ngbButton type="radio" [value]="'3m'"> 3M
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 30">
|
||||
<input ngbButton type="radio" [value]="'1m'" fragment="1m"> 1M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 180">
|
||||
<input ngbButton type="radio" [value]="'6m'"> 6M
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 90">
|
||||
<input ngbButton type="radio" [value]="'3m'" fragment="3m"> 3M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 365">
|
||||
<input ngbButton type="radio" [value]="'1y'"> 1Y
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 180">
|
||||
<input ngbButton type="radio" [value]="'6m'" fragment="6m"> 6M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 730">
|
||||
<input ngbButton type="radio" [value]="'2y'"> 2Y
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 365">
|
||||
<input ngbButton type="radio" [value]="'1y'" fragment="1y"> 1Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="hashrates.availableTimespanDay >= 1095">
|
||||
<input ngbButton type="radio" [value]="'3y'"> 3Y
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 730">
|
||||
<input ngbButton type="radio" [value]="'2y'" fragment="2y"> 2Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'"> ALL
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 1095">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay > 1095">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all"> ALL
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div [class]="!widget ? 'chart' : 'chart-widget'"
|
||||
<div class="chart"
|
||||
echarts [initOpts]="chartInitOptions" [options]="chartOptions"></div>
|
||||
<div class="text-center loadingGraphs" *ngIf="isLoading">
|
||||
<div class="spinner-border text-light"></div>
|
||||
|
@ -6,6 +6,8 @@ import { ApiService } from 'src/app/services/api.service';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { poolsColor } from 'src/app/app.constants';
|
||||
import { StorageService } from 'src/app/services/storage.service';
|
||||
import { MiningService } from 'src/app/services/mining.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hashrate-chart-pools',
|
||||
@ -22,10 +24,10 @@ import { poolsColor } from 'src/app/app.constants';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class HashrateChartPoolsComponent implements OnInit {
|
||||
@Input() widget = false;
|
||||
@Input() right: number | string = 45;
|
||||
@Input() left: number | string = 25;
|
||||
|
||||
miningWindowPreference: string;
|
||||
radioGroupForm: FormGroup;
|
||||
|
||||
chartOptions: EChartsOption = {};
|
||||
@ -44,20 +46,29 @@ export class HashrateChartPoolsComponent implements OnInit {
|
||||
private apiService: ApiService,
|
||||
private formBuilder: FormBuilder,
|
||||
private cd: ChangeDetectorRef,
|
||||
private storageService: StorageService,
|
||||
private miningService: MiningService
|
||||
) {
|
||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' });
|
||||
this.radioGroupForm.controls.dateSpan.setValue('1y');
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (!this.widget) {
|
||||
this.seoService.setTitle($localize`:@@mining.pools-historical-dominance:Pools Historical Dominance`);
|
||||
}
|
||||
let firstRun = true;
|
||||
|
||||
this.seoService.setTitle($localize`:@@mining.pools-historical-dominance:Pools Historical Dominance`);
|
||||
this.miningWindowPreference = this.miningService.getDefaultTimespan('1m');
|
||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.miningWindowPreference });
|
||||
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
|
||||
|
||||
this.hashrateObservable$ = this.radioGroupForm.get('dateSpan').valueChanges
|
||||
.pipe(
|
||||
startWith('1y'),
|
||||
startWith(this.miningWindowPreference),
|
||||
switchMap((timespan) => {
|
||||
if (!firstRun) {
|
||||
this.storageService.setValue('miningWindowPreference', timespan);
|
||||
}
|
||||
firstRun = false;
|
||||
this.isLoading = true;
|
||||
return this.apiService.getHistoricalPoolsHashrate$(timespan)
|
||||
.pipe(
|
||||
@ -157,11 +168,11 @@ export class HashrateChartPoolsComponent implements OnInit {
|
||||
grid: {
|
||||
right: this.right,
|
||||
left: this.left,
|
||||
bottom: this.widget ? 30 : 70,
|
||||
top: this.widget || this.isMobile() ? 10 : 50,
|
||||
bottom: 70,
|
||||
top: this.isMobile() ? 10 : 50,
|
||||
},
|
||||
tooltip: {
|
||||
show: !this.isMobile() || !this.widget,
|
||||
show: !this.isMobile(),
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'line'
|
||||
@ -188,9 +199,9 @@ export class HashrateChartPoolsComponent implements OnInit {
|
||||
},
|
||||
xAxis: data.series.length === 0 ? undefined : {
|
||||
type: 'time',
|
||||
splitNumber: (this.isMobile() || this.widget) ? 5 : 10,
|
||||
splitNumber: (this.isMobile()) ? 5 : 10,
|
||||
},
|
||||
legend: (this.isMobile() || this.widget || data.series.length === 0) ? undefined : {
|
||||
legend: (this.isMobile() || data.series.length === 0) ? undefined : {
|
||||
data: data.legends
|
||||
},
|
||||
yAxis: data.series.length === 0 ? undefined : {
|
||||
@ -207,7 +218,7 @@ export class HashrateChartPoolsComponent implements OnInit {
|
||||
min: 0,
|
||||
},
|
||||
series: data.series,
|
||||
dataZoom: this.widget ? null : [{
|
||||
dataZoom: [{
|
||||
type: 'inside',
|
||||
realtime: true,
|
||||
zoomLock: true,
|
||||
|
@ -55,7 +55,7 @@
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="miningStats.availableTimespanDay >= 1095">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="miningStats.availableTimespanDay > 1095">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all"> ALL
|
||||
</label>
|
||||
</div>
|
||||
@ -79,7 +79,7 @@
|
||||
<th class="d-none d-md-block" i18n="mining.rank">Rank</th>
|
||||
<th class=""></th>
|
||||
<th class="" i18n="mining.pool-name">Pool</th>
|
||||
<th class="" *ngIf="this.poolsWindowPreference === '24h'" i18n="mining.hashrate">Hashrate</th>
|
||||
<th class="" *ngIf="this.miningWindowPreference === '24h'" i18n="mining.hashrate">Hashrate</th>
|
||||
<th class="" i18n="master-page.blocks">Blocks</th>
|
||||
<th class="d-none d-md-block" i18n="mining.empty-blocks">Empty Blocks</th>
|
||||
</tr>
|
||||
@ -90,7 +90,7 @@
|
||||
<td class="text-right"><img width="25" height="25" src="{{ pool.logo }}"
|
||||
onError="this.src = './resources/mining-pools/default.svg'"></td>
|
||||
<td class=""><a [routerLink]="[('/mining/pool/' + pool.slug) | relativeUrl]">{{ pool.name }}</a></td>
|
||||
<td class="" *ngIf="this.poolsWindowPreference === '24h' && !isLoading">{{ pool.lastEstimatedHashrate }} {{
|
||||
<td class="" *ngIf="this.miningWindowPreference === '24h' && !isLoading">{{ pool.lastEstimatedHashrate }} {{
|
||||
miningStats.miningUnits.hashrateUnit }}</td>
|
||||
<td class="">{{ pool['blockText'] }}</td>
|
||||
<td class="d-none d-md-block">{{ pool.emptyBlocks }} ({{ pool.emptyBlockRatio }}%)</td>
|
||||
@ -99,7 +99,7 @@
|
||||
<td class="d-none d-md-block"></td>
|
||||
<td class="text-right"></td>
|
||||
<td class="" i18n="mining.all-miners"><b>All miners</b></td>
|
||||
<td class="" *ngIf="this.poolsWindowPreference === '24h'"><b>{{ miningStats.lastEstimatedHashrate}} {{
|
||||
<td class="" *ngIf="this.miningWindowPreference === '24h'"><b>{{ miningStats.lastEstimatedHashrate}} {{
|
||||
miningStats.miningUnits.hashrateUnit }}</b></td>
|
||||
<td class=""><b>{{ miningStats.blockCount }}</b></td>
|
||||
<td class="d-none d-md-block"><b>{{ miningStats.totalEmptyBlock }} ({{ miningStats.totalEmptyBlockRatio
|
||||
|
@ -19,9 +19,9 @@ import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class PoolRankingComponent implements OnInit {
|
||||
@Input() widget: boolean = false;
|
||||
@Input() widget = false;
|
||||
|
||||
poolsWindowPreference: string;
|
||||
miningWindowPreference: string;
|
||||
radioGroupForm: FormGroup;
|
||||
|
||||
isLoading = true;
|
||||
@ -48,13 +48,13 @@ export class PoolRankingComponent implements OnInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.widget) {
|
||||
this.poolsWindowPreference = '1w';
|
||||
this.miningWindowPreference = '1w';
|
||||
} else {
|
||||
this.seoService.setTitle($localize`:@@mining.mining-pools:Mining Pools`);
|
||||
this.poolsWindowPreference = this.storageService.getValue('poolsWindowPreference') ? this.storageService.getValue('poolsWindowPreference') : '1w';
|
||||
this.miningWindowPreference = this.miningService.getDefaultTimespan('24h');
|
||||
}
|
||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.poolsWindowPreference });
|
||||
this.radioGroupForm.controls.dateSpan.setValue(this.poolsWindowPreference);
|
||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.miningWindowPreference });
|
||||
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
|
||||
|
||||
// When...
|
||||
this.miningStatsObservable$ = combineLatest([
|
||||
@ -67,12 +67,12 @@ export class PoolRankingComponent implements OnInit {
|
||||
// ...or we change the timespan
|
||||
this.radioGroupForm.get('dateSpan').valueChanges
|
||||
.pipe(
|
||||
startWith(this.poolsWindowPreference), // (trigger when the page loads)
|
||||
startWith(this.miningWindowPreference), // (trigger when the page loads)
|
||||
tap((value) => {
|
||||
if (!this.widget) {
|
||||
this.storageService.setValue('poolsWindowPreference', value);
|
||||
this.storageService.setValue('miningWindowPreference', value);
|
||||
}
|
||||
this.poolsWindowPreference = value;
|
||||
this.miningWindowPreference = value;
|
||||
})
|
||||
)
|
||||
])
|
||||
@ -80,7 +80,7 @@ export class PoolRankingComponent implements OnInit {
|
||||
.pipe(
|
||||
switchMap(() => {
|
||||
this.isLoading = true;
|
||||
return this.miningService.getMiningStats(this.poolsWindowPreference)
|
||||
return this.miningService.getMiningStats(this.miningWindowPreference)
|
||||
.pipe(
|
||||
catchError((e) => of(this.getEmptyMiningStat()))
|
||||
);
|
||||
@ -150,7 +150,7 @@ export class PoolRankingComponent implements OnInit {
|
||||
},
|
||||
borderColor: '#000',
|
||||
formatter: () => {
|
||||
if (this.poolsWindowPreference === '24h') {
|
||||
if (this.miningWindowPreference === '24h') {
|
||||
return `<b style="color: white">${pool.name} (${pool.share}%)</b><br>` +
|
||||
pool.lastEstimatedHashrate.toString() + ' PH/s' +
|
||||
`<br>` + pool.blockCount.toString() + ` blocks`;
|
||||
@ -186,7 +186,7 @@ export class PoolRankingComponent implements OnInit {
|
||||
},
|
||||
borderColor: '#000',
|
||||
formatter: () => {
|
||||
if (this.poolsWindowPreference === '24h') {
|
||||
if (this.miningWindowPreference === '24h') {
|
||||
return `<b style="color: white">${'Other'} (${totalShareOther.toFixed(2)}%)</b><br>` +
|
||||
totalEstimatedHashrateOther.toString() + ' PH/s' +
|
||||
`<br>` + totalBlockOther.toString() + ` blocks`;
|
||||
|
@ -4,6 +4,7 @@ import { map } from 'rxjs/operators';
|
||||
import { PoolsStats, SinglePoolStats } from '../interfaces/node-api.interface';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import { StateService } from './state.service';
|
||||
import { StorageService } from './storage.service';
|
||||
|
||||
export interface MiningUnits {
|
||||
hashrateDivider: number;
|
||||
@ -28,8 +29,12 @@ export class MiningService {
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
private apiService: ApiService,
|
||||
private storageService: StorageService,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Generate pool ranking stats
|
||||
*/
|
||||
public getMiningStats(interval: string): Observable<MiningStats> {
|
||||
return this.apiService.listPools$(interval).pipe(
|
||||
map(pools => this.generateMiningStats(pools))
|
||||
@ -63,6 +68,20 @@ export class MiningService {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default selection timespan, cap with `min`
|
||||
*/
|
||||
public getDefaultTimespan(min: string): string {
|
||||
const timespans = [
|
||||
'24h', '3d', '1w', '1m', '3m', '6m', '1y', '2y', '3y', 'all'
|
||||
];
|
||||
const preference = this.storageService.getValue('miningWindowPreference') ?? '1w';
|
||||
if (timespans.indexOf(preference) < timespans.indexOf(min)) {
|
||||
return min;
|
||||
}
|
||||
return preference;
|
||||
}
|
||||
|
||||
private generateMiningStats(stats: PoolsStats): MiningStats {
|
||||
const miningUnits = this.getMiningUnits();
|
||||
const hashrateDivider = miningUnits.hashrateDivider;
|
||||
|
@ -7,21 +7,21 @@ import { Router, ActivatedRoute } from '@angular/router';
|
||||
export class StorageService {
|
||||
constructor(private router: Router, private route: ActivatedRoute) {
|
||||
this.setDefaultValueIfNeeded('graphWindowPreference', '2h');
|
||||
this.setDefaultValueIfNeeded('poolsWindowPreference', '1w');
|
||||
this.setDefaultValueIfNeeded('miningWindowPreference', '1w');
|
||||
}
|
||||
|
||||
setDefaultValueIfNeeded(key: string, defaultValue: string) {
|
||||
let graphWindowPreference: string = this.getValue(key);
|
||||
const graphWindowPreference: string = this.getValue(key);
|
||||
if (graphWindowPreference === null) { // First visit to mempool.space
|
||||
if (this.router.url.includes('graphs') && key === 'graphWindowPreference' ||
|
||||
this.router.url.includes('pools') && key === 'poolsWindowPreference'
|
||||
this.router.url.includes('pools') && key === 'miningWindowPreference'
|
||||
) {
|
||||
this.setValue(key, this.route.snapshot.fragment ? this.route.snapshot.fragment : defaultValue);
|
||||
} else {
|
||||
this.setValue(key, defaultValue);
|
||||
}
|
||||
} else if (this.router.url.includes('graphs') && key === 'graphWindowPreference' ||
|
||||
this.router.url.includes('pools') && key === 'poolsWindowPreference'
|
||||
this.router.url.includes('pools') && key === 'miningWindowPreference'
|
||||
) {
|
||||
// Visit a different graphs#fragment from last visit
|
||||
if (this.route.snapshot.fragment !== null && graphWindowPreference !== this.route.snapshot.fragment) {
|
||||
|
@ -38,6 +38,7 @@ do for url in / \
|
||||
'/api/v1/mining/reward-stats/144' \
|
||||
'/api/v1/mining/blocks-extras' \
|
||||
'/api/v1/mining/blocks/fees/24h' \
|
||||
'/api/v1/mining/blocks/fees/3d' \
|
||||
'/api/v1/mining/blocks/fees/1w' \
|
||||
'/api/v1/mining/blocks/fees/1m' \
|
||||
'/api/v1/mining/blocks/fees/3m' \
|
||||
|
Loading…
x
Reference in New Issue
Block a user