From c9ad316ed569779ab9e3967360d38951885fa158 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Wed, 2 Feb 2022 17:49:38 +0900 Subject: [PATCH 1/4] Allow /tv view timespan to be changed through url fragment --- .../television/television.component.ts | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/television/television.component.ts b/frontend/src/app/components/television/television.component.ts index ae5d9abfd..a2f1dcdd8 100644 --- a/frontend/src/app/components/television/television.component.ts +++ b/frontend/src/app/components/television/television.component.ts @@ -4,7 +4,8 @@ import { OptimizedMempoolStats } from '../../interfaces/node-api.interface'; import { StateService } from 'src/app/services/state.service'; import { ApiService } from 'src/app/services/api.service'; import { SeoService } from 'src/app/services/seo.service'; -import { Observable } from 'rxjs'; +import { ActivatedRoute } from '@angular/router'; +import { switchMap } from 'rxjs/operators'; @Component({ selector: 'app-television', @@ -21,13 +22,30 @@ export class TelevisionComponent implements OnInit { private apiService: ApiService, private stateService: StateService, private seoService: SeoService, + private route: ActivatedRoute ) { } ngOnInit() { this.seoService.setTitle($localize`:@@46ce8155c9ab953edeec97e8950b5a21e67d7c4e:TV view`); this.websocketService.want(['blocks', 'live-2h-chart', 'mempool-blocks']); - this.apiService.list2HStatistics$() + this.route.fragment + .pipe( + switchMap(() => { + switch (this.route.snapshot.fragment) { + case '2h': return this.apiService.list2HStatistics$(); + case '24h': return this.apiService.list24HStatistics$(); + case '1w': return this.apiService.list1WStatistics$(); + case '1m': return this.apiService.list1MStatistics$(); + case '3m': return this.apiService.list3MStatistics$(); + case '6m': return this.apiService.list6MStatistics$(); + case '1y': return this.apiService.list1YStatistics$(); + case '2y': return this.apiService.list2YStatistics$(); + case '3y': return this.apiService.list3YStatistics$(); + default: return this.apiService.list2HStatistics$(); + } + }) + ) .subscribe((mempoolStats) => { this.mempoolStats = mempoolStats; }); From aa77faf3140b964f4e27e8c2996fe4bd688221a5 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Sat, 5 Feb 2022 19:06:27 +0900 Subject: [PATCH 2/4] Use switchMap param instead of re-reading this.route.snapshot.fragment --- .../src/app/components/television/television.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/television/television.component.ts b/frontend/src/app/components/television/television.component.ts index a2f1dcdd8..e219a0b51 100644 --- a/frontend/src/app/components/television/television.component.ts +++ b/frontend/src/app/components/television/television.component.ts @@ -31,8 +31,8 @@ export class TelevisionComponent implements OnInit { this.route.fragment .pipe( - switchMap(() => { - switch (this.route.snapshot.fragment) { + switchMap((fragment) => { + switch (fragment) { case '2h': return this.apiService.list2HStatistics$(); case '24h': return this.apiService.list24HStatistics$(); case '1w': return this.apiService.list1WStatistics$(); From cd9eaf816bc8d3f96b9113db3de58ba4b38809a3 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Wed, 9 Feb 2022 10:18:51 +0900 Subject: [PATCH 3/4] Refactor TV component subscription --- .../television/television.component.html | 2 +- .../television/television.component.ts | 71 +++++++++++-------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/frontend/src/app/components/television/television.component.html b/frontend/src/app/components/television/television.component.html index c9caa54ef..7da6e2d38 100644 --- a/frontend/src/app/components/television/television.component.html +++ b/frontend/src/app/components/television/television.component.html @@ -7,7 +7,7 @@ [height]="600" [left]="60" [right]="10" - [data]="mempoolStats && mempoolStats.length ? mempoolStats : null" + [data]="statsSubscription$ | async" [showZoom]="false" > diff --git a/frontend/src/app/components/television/television.component.ts b/frontend/src/app/components/television/television.component.ts index e219a0b51..f7cdcf074 100644 --- a/frontend/src/app/components/television/television.component.ts +++ b/frontend/src/app/components/television/television.component.ts @@ -5,7 +5,9 @@ import { StateService } from 'src/app/services/state.service'; import { ApiService } from 'src/app/services/api.service'; import { SeoService } from 'src/app/services/seo.service'; import { ActivatedRoute } from '@angular/router'; -import { switchMap } from 'rxjs/operators'; +import { map, startWith, switchMap, tap } from 'rxjs/operators'; +import { interval, merge, Observable } from 'rxjs'; +import { isArray } from 'src/app/shared/pipes/bytes-pipe/utils'; @Component({ selector: 'app-television', @@ -15,7 +17,8 @@ import { switchMap } from 'rxjs/operators'; export class TelevisionComponent implements OnInit { mempoolStats: OptimizedMempoolStats[] = []; - mempoolVsizeFeesData: any; + statsSubscription$: Observable; + fragment: string; constructor( private websocketService: WebsocketService, @@ -25,36 +28,46 @@ export class TelevisionComponent implements OnInit { private route: ActivatedRoute ) { } + refreshStats(time: number, fn: Observable) { + return interval(time).pipe(startWith(0), switchMap(() => fn)); + } + ngOnInit() { this.seoService.setTitle($localize`:@@46ce8155c9ab953edeec97e8950b5a21e67d7c4e:TV view`); this.websocketService.want(['blocks', 'live-2h-chart', 'mempool-blocks']); - this.route.fragment - .pipe( - switchMap((fragment) => { - switch (fragment) { - case '2h': return this.apiService.list2HStatistics$(); - case '24h': return this.apiService.list24HStatistics$(); - case '1w': return this.apiService.list1WStatistics$(); - case '1m': return this.apiService.list1MStatistics$(); - case '3m': return this.apiService.list3MStatistics$(); - case '6m': return this.apiService.list6MStatistics$(); - case '1y': return this.apiService.list1YStatistics$(); - case '2y': return this.apiService.list2YStatistics$(); - case '3y': return this.apiService.list3YStatistics$(); - default: return this.apiService.list2HStatistics$(); - } - }) - ) - .subscribe((mempoolStats) => { - this.mempoolStats = mempoolStats; - }); - - this.stateService.live2Chart$ - .subscribe((mempoolStats) => { - this.mempoolStats.unshift(mempoolStats); - this.mempoolStats = this.mempoolStats.slice(0, this.mempoolStats.length - 1); - }); + this.statsSubscription$ = merge( + this.stateService.live2Chart$, + this.route.fragment + .pipe( + tap(fragment => { this.fragment = fragment; }), + switchMap((fragment) => { + const minute = 60000; const hour = 3600000; + switch (fragment) { + case '2h': return this.apiService.list2HStatistics$(); + case '24h': return this.apiService.list24HStatistics$(); + case '1w': return this.refreshStats(5 * minute, this.apiService.list1WStatistics$()); + case '1m': return this.refreshStats(30 * minute, this.apiService.list1MStatistics$()); + case '3m': return this.refreshStats(2 * hour, this.apiService.list3MStatistics$()); + case '6m': return this.refreshStats(3 * hour, this.apiService.list6MStatistics$()); + case '1y': return this.refreshStats(8 * hour, this.apiService.list1YStatistics$()); + case '2y': return this.refreshStats(8 * hour, this.apiService.list2YStatistics$()); + case '3y': return this.refreshStats(12 * hour, this.apiService.list3YStatistics$()); + default: return this.apiService.list2HStatistics$(); + } + }) + ) + ) + .pipe( + map(stats => { + if (isArray(stats)) { + this.mempoolStats = stats as OptimizedMempoolStats[]; + } else if (['2h', '24h'].includes(this.fragment)) { + this.mempoolStats.unshift(stats as OptimizedMempoolStats); + this.mempoolStats = this.mempoolStats.slice(0, this.mempoolStats.length - 1); + } + return this.mempoolStats; + }) + ); } - } From 055c587351f81ee9211b0a2cb0e5586b048c59bf Mon Sep 17 00:00:00 2001 From: nymkappa Date: Thu, 10 Feb 2022 00:04:14 +0900 Subject: [PATCH 4/4] Fix bug when loading `/tv` and cleanup Observable flow --- .../television/television.component.ts | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/components/television/television.component.ts b/frontend/src/app/components/television/television.component.ts index f7cdcf074..3c0c88ec8 100644 --- a/frontend/src/app/components/television/television.component.ts +++ b/frontend/src/app/components/television/television.component.ts @@ -5,19 +5,20 @@ import { StateService } from 'src/app/services/state.service'; import { ApiService } from 'src/app/services/api.service'; import { SeoService } from 'src/app/services/seo.service'; import { ActivatedRoute } from '@angular/router'; -import { map, startWith, switchMap, tap } from 'rxjs/operators'; +import { map, scan, startWith, switchMap, tap } from 'rxjs/operators'; import { interval, merge, Observable } from 'rxjs'; -import { isArray } from 'src/app/shared/pipes/bytes-pipe/utils'; +import { ChangeDetectionStrategy } from '@angular/core'; @Component({ selector: 'app-television', templateUrl: './television.component.html', - styleUrls: ['./television.component.scss'] + styleUrls: ['./television.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class TelevisionComponent implements OnInit { mempoolStats: OptimizedMempoolStats[] = []; - statsSubscription$: Observable; + statsSubscription$: Observable; fragment: string; constructor( @@ -37,14 +38,13 @@ export class TelevisionComponent implements OnInit { this.websocketService.want(['blocks', 'live-2h-chart', 'mempool-blocks']); this.statsSubscription$ = merge( - this.stateService.live2Chart$, + this.stateService.live2Chart$.pipe(map(stats => [stats])), this.route.fragment .pipe( - tap(fragment => { this.fragment = fragment; }), + tap(fragment => { this.fragment = fragment ?? '2h'; }), switchMap((fragment) => { const minute = 60000; const hour = 3600000; switch (fragment) { - case '2h': return this.apiService.list2HStatistics$(); case '24h': return this.apiService.list24HStatistics$(); case '1w': return this.refreshStats(5 * minute, this.apiService.list1WStatistics$()); case '1m': return this.refreshStats(30 * minute, this.apiService.list1MStatistics$()); @@ -53,20 +53,20 @@ export class TelevisionComponent implements OnInit { case '1y': return this.refreshStats(8 * hour, this.apiService.list1YStatistics$()); case '2y': return this.refreshStats(8 * hour, this.apiService.list2YStatistics$()); case '3y': return this.refreshStats(12 * hour, this.apiService.list3YStatistics$()); - default: return this.apiService.list2HStatistics$(); + default /* 2h */: return this.apiService.list2HStatistics$(); } }) ) ) .pipe( - map(stats => { - if (isArray(stats)) { - this.mempoolStats = stats as OptimizedMempoolStats[]; + scan((mempoolStats, newStats) => { + if (newStats.length > 1) { + mempoolStats = newStats; } else if (['2h', '24h'].includes(this.fragment)) { - this.mempoolStats.unshift(stats as OptimizedMempoolStats); - this.mempoolStats = this.mempoolStats.slice(0, this.mempoolStats.length - 1); + mempoolStats.unshift(newStats[0]); + mempoolStats = mempoolStats.slice(0, mempoolStats.length - 1); } - return this.mempoolStats; + return mempoolStats; }) ); }