diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index dfb64c4bd..0dfc853cc 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -75,6 +75,7 @@ import { HashrateChartPoolsComponent } from './components/hashrates-chart-pools/ import { MiningStartComponent } from './components/mining-start/mining-start.component'; import { AmountShortenerPipe } from './shared/pipes/amount-shortener.pipe'; import { ShortenStringPipe } from './shared/pipes/shorten-string-pipe/shorten-string.pipe'; +import { DifficultyAdjustmentsTable } from './components/difficulty-adjustments-table/difficulty-adjustments-table.components'; @NgModule({ declarations: [ @@ -131,6 +132,7 @@ import { ShortenStringPipe } from './shared/pipes/shorten-string-pipe/shorten-st HashrateChartPoolsComponent, MiningStartComponent, AmountShortenerPipe, + DifficultyAdjustmentsTable, ], imports: [ BrowserModule.withServerTransition({ appId: 'serverApp' }), diff --git a/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.html b/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.html new file mode 100644 index 000000000..a04c60f6a --- /dev/null +++ b/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.html @@ -0,0 +1,33 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
HeightAdjustedDifficultyChange
{{ diffChange.height + }} + + {{ diffChange.difficultyShorten }} + {{ diffChange.change >= 0 ? '+' : '' }}{{ formatNumber(diffChange.change, locale, '1.2-2') }}% +
+
\ No newline at end of file diff --git a/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.scss b/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.scss new file mode 100644 index 000000000..c4a81f804 --- /dev/null +++ b/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.scss @@ -0,0 +1,40 @@ +.latest-transactions { + width: 100%; + text-align: left; + table-layout:fixed; + tr, td, th { + border: 0px; + } + td { + width: 25%; + } + .table-cell-satoshis { + display: none; + text-align: right; + @media (min-width: 576px) { + display: table-cell; + } + @media (min-width: 768px) { + display: none; + } + @media (min-width: 1100px) { + display: table-cell; + } + } + .table-cell-fiat { + display: none; + text-align: right; + @media (min-width: 485px) { + display: table-cell; + } + @media (min-width: 768px) { + display: none; + } + @media (min-width: 992px) { + display: table-cell; + } + } + .table-cell-fees { + text-align: right; + } +} diff --git a/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.components.ts b/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.components.ts new file mode 100644 index 000000000..24c44fe05 --- /dev/null +++ b/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.components.ts @@ -0,0 +1,65 @@ +import { Component, Inject, LOCALE_ID, OnInit } from '@angular/core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { ApiService } from 'src/app/services/api.service'; +import { formatNumber } from '@angular/common'; +import { selectPowerOfTen } from 'src/app/bitcoin.utils'; + +@Component({ + selector: 'app-difficulty-adjustments-table', + templateUrl: './difficulty-adjustments-table.component.html', + styleUrls: ['./difficulty-adjustments-table.component.scss'], + styles: [` + .loadingGraphs { + position: absolute; + top: 50%; + left: calc(50% - 15px); + z-index: 100; + } + `], +}) +export class DifficultyAdjustmentsTable implements OnInit { + hashrateObservable$: Observable; + isLoading = true; + formatNumber = formatNumber; + + constructor( + @Inject(LOCALE_ID) public locale: string, + private apiService: ApiService, + ) { + } + + ngOnInit(): void { + this.hashrateObservable$ = this.apiService.getHistoricalHashrate$('1y') + .pipe( + map((data: any) => { + const availableTimespanDay = ( + (new Date().getTime() / 1000) - (data.oldestIndexedBlockTimestamp) + ) / 3600 / 24; + + const tableData = []; + for (let i = data.difficulty.length - 1; i > 0; --i) { + const selectedPowerOfTen: any = selectPowerOfTen(data.difficulty[i].difficulty); + const change = (data.difficulty[i].difficulty / data.difficulty[i - 1].difficulty - 1) * 100; + + tableData.push(Object.assign(data.difficulty[i], { + change: change, + difficultyShorten: formatNumber( + data.difficulty[i].difficulty / selectedPowerOfTen.divider, + this.locale, '1.2-2') + selectedPowerOfTen.unit + })); + } + this.isLoading = false; + + return { + availableTimespanDay: availableTimespanDay, + difficulty: tableData.slice(0, 5), + }; + }), + ); + } + + isMobile() { + return (window.innerWidth <= 767.98); + } +} diff --git a/frontend/src/app/components/hashrate-chart/hashrate-chart.component.html b/frontend/src/app/components/hashrate-chart/hashrate-chart.component.html index b208d9c41..2ca0e8376 100644 --- a/frontend/src/app/components/hashrate-chart/hashrate-chart.component.html +++ b/frontend/src/app/components/hashrate-chart/hashrate-chart.component.html @@ -1,6 +1,6 @@
-
+
-
-
+
- - - - - - - - - - - - - - - - - - - - - - - - - -
HeightAdjustedDifficultyChange
{{ diffChange.height }}{{ diffChange.difficultyShorten }} - {{ diffChange.change >= 0 ? '+' : '' }}{{ formatNumber(diffChange.change, locale, '1.2-2') }}% -
-
diff --git a/frontend/src/app/components/hashrate-chart/hashrate-chart.component.scss b/frontend/src/app/components/hashrate-chart/hashrate-chart.component.scss index c68e2f406..0254d3175 100644 --- a/frontend/src/app/components/hashrate-chart/hashrate-chart.component.scss +++ b/frontend/src/app/components/hashrate-chart/hashrate-chart.component.scss @@ -48,44 +48,3 @@ } } } - -.latest-transactions { - width: 100%; - text-align: left; - table-layout:fixed; - tr, td, th { - border: 0px; - } - td { - width: 25%; - } - .table-cell-satoshis { - display: none; - text-align: right; - @media (min-width: 576px) { - display: table-cell; - } - @media (min-width: 768px) { - display: none; - } - @media (min-width: 1100px) { - display: table-cell; - } - } - .table-cell-fiat { - display: none; - text-align: right; - @media (min-width: 485px) { - display: table-cell; - } - @media (min-width: 768px) { - display: none; - } - @media (min-width: 992px) { - display: table-cell; - } - } - .table-cell-fees { - text-align: right; - } -} diff --git a/frontend/src/app/components/hashrate-chart/hashrate-chart.component.ts b/frontend/src/app/components/hashrate-chart/hashrate-chart.component.ts index 67b4fd233..382071e37 100644 --- a/frontend/src/app/components/hashrate-chart/hashrate-chart.component.ts +++ b/frontend/src/app/components/hashrate-chart/hashrate-chart.component.ts @@ -1,7 +1,7 @@ -import { Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { EChartsOption, graphic } from 'echarts'; import { Observable } from 'rxjs'; -import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; +import { delay, map, retryWhen, share, startWith, switchMap, tap } from 'rxjs/operators'; import { ApiService } from 'src/app/services/api.service'; import { SeoService } from 'src/app/services/seo.service'; import { formatNumber } from '@angular/common'; @@ -20,6 +20,7 @@ import { selectPowerOfTen } from 'src/app/bitcoin.utils'; z-index: 100; } `], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class HashrateChartComponent implements OnInit { @Input() tableOnly = false; @@ -45,6 +46,7 @@ export class HashrateChartComponent implements OnInit { private seoService: SeoService, private apiService: ApiService, private formBuilder: FormBuilder, + private cd: ChangeDetectorRef, ) { this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' }); this.radioGroupForm.controls.dateSpan.setValue('1y'); @@ -92,9 +94,15 @@ export class HashrateChartComponent implements OnInit { this.prepareChartOptions({ hashrates: data.hashrates.map(val => [val.timestamp * 1000, val.avgHashrate]), - difficulty: diffFixed.map(val => [val.timestamp * 1000, val.difficulty]) + difficulty: diffFixed.map(val => [val.timestamp * 1000, val.difficulty]), + timestamp: data.oldestIndexedBlockTimestamp, }); this.isLoading = false; + + if (data.hashrates.length === 0) { + this.cd.markForCheck(); + throw new Error(); + } }), map((data: any) => { const availableTimespanDay = ( @@ -115,9 +123,12 @@ export class HashrateChartComponent implements OnInit { } return { availableTimespanDay: availableTimespanDay, - difficulty: this.tableOnly ? tableData.slice(0, 5) : tableData + difficulty: this.tableOnly ? tableData.slice(0, 5) : tableData, }; }), + retryWhen((errors) => errors.pipe( + delay(60000) + )) ); }), share() @@ -125,16 +136,20 @@ export class HashrateChartComponent implements OnInit { } prepareChartOptions(data) { - let title = undefined; + let title: object; if (data.hashrates.length === 0) { + const lastBlock = new Date(data.timestamp * 1000); + const dd = String(lastBlock.getDate()).padStart(2, '0'); + const mm = String(lastBlock.getMonth() + 1).padStart(2, '0'); // January is 0! + const yyyy = lastBlock.getFullYear(); title = { textStyle: { - color: "grey", + color: 'grey', fontSize: 15 }, - text: "Indexing in progress...", - left: "center", - top: "center" + text: `Indexing in progess - ${yyyy}-${mm}-${dd}`, + left: 'center', + top: 'center' }; } @@ -190,11 +205,11 @@ export class HashrateChartComponent implements OnInit { `; }.bind(this) }, - xAxis: { + xAxis: data.hashrates.length === 0 ? undefined : { type: 'time', splitNumber: (this.isMobile() || this.widget) ? 5 : 10, }, - legend: { + legend: data.hashrates.length === 0 ? undefined : { data: [ { name: 'Hashrate', @@ -220,7 +235,7 @@ export class HashrateChartComponent implements OnInit { }, ], }, - yAxis: [ + yAxis: data.hashrates.length === 0 ? undefined : [ { min: function (value) { return value.min * 0.9; @@ -259,7 +274,7 @@ export class HashrateChartComponent implements OnInit { } } ], - series: [ + series: data.hashrates.length === 0 ? [] : [ { name: 'Hashrate', showSymbol: false, diff --git a/frontend/src/app/components/hashrates-chart-pools/hashrate-chart-pools.component.ts b/frontend/src/app/components/hashrates-chart-pools/hashrate-chart-pools.component.ts index 0e79a21dd..3257465a1 100644 --- a/frontend/src/app/components/hashrates-chart-pools/hashrate-chart-pools.component.ts +++ b/frontend/src/app/components/hashrates-chart-pools/hashrate-chart-pools.component.ts @@ -1,7 +1,7 @@ -import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { EChartsOption } from 'echarts'; import { Observable } from 'rxjs'; -import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; +import { delay, map, retryWhen, share, startWith, switchMap, tap } from 'rxjs/operators'; import { ApiService } from 'src/app/services/api.service'; import { SeoService } from 'src/app/services/seo.service'; import { FormBuilder, FormGroup } from '@angular/forms'; @@ -22,7 +22,7 @@ import { poolsColor } from 'src/app/app.constants'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class HashrateChartPoolsComponent implements OnInit { - @Input() widget: boolean = false; + @Input() widget = false; @Input() right: number | string = 40; @Input() left: number | string = 25; @@ -43,6 +43,7 @@ export class HashrateChartPoolsComponent implements OnInit { private seoService: SeoService, private apiService: ApiService, private formBuilder: FormBuilder, + private cd: ChangeDetectorRef, ) { this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' }); this.radioGroupForm.controls.dateSpan.setValue('1y'); @@ -105,9 +106,15 @@ export class HashrateChartPoolsComponent implements OnInit { this.prepareChartOptions({ legends: legends, - series: series + series: series, + timestamp: data.oldestIndexedBlockTimestamp, }); this.isLoading = false; + + if (series.length === 0) { + this.cd.markForCheck(); + throw new Error(); + } }), map((data: any) => { const availableTimespanDay = ( @@ -117,6 +124,9 @@ export class HashrateChartPoolsComponent implements OnInit { availableTimespanDay: availableTimespanDay, }; }), + retryWhen((errors) => errors.pipe( + delay(60000) + )) ); }), share() @@ -124,16 +134,20 @@ export class HashrateChartPoolsComponent implements OnInit { } prepareChartOptions(data) { - let title = undefined; + let title: object; if (data.series.length === 0) { + const lastBlock = new Date(data.timestamp * 1000); + const dd = String(lastBlock.getDate()).padStart(2, '0'); + const mm = String(lastBlock.getMonth() + 1).padStart(2, '0'); // January is 0! + const yyyy = lastBlock.getFullYear(); title = { textStyle: { - color: "grey", - fontSize: 15 + color: 'grey', + fontSize: 15 }, - text: "Indexing in progress...", - left: "center", - top: this.widget ? 115 : this.isMobile() ? 'center' : 225, + text: `Indexing in progess - ${yyyy}-${mm}-${dd}`, + left: 'center', + top: 'center', }; } @@ -171,14 +185,14 @@ export class HashrateChartPoolsComponent implements OnInit { return tooltip; }.bind(this) }, - xAxis: { + xAxis: data.series.length === 0 ? undefined : { type: 'time', splitNumber: (this.isMobile() || this.widget) ? 5 : 10, }, - legend: (this.isMobile() || this.widget) ? undefined : { + legend: (this.isMobile() || this.widget || data.series.length === 0) ? undefined : { data: data.legends }, - yAxis: { + yAxis: data.series.length === 0 ? undefined : { position: 'right', axisLabel: { color: 'rgb(110, 112, 121)', diff --git a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html index dff5436f0..68209fed0 100644 --- a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html +++ b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html @@ -114,7 +114,7 @@
Adjustments
- +