SSR: Fix initial state of lightning pages & graphs
This commit is contained in:
		
							parent
							
								
									99730d02ab
								
							
						
					
					
						commit
						b167848b9b
					
				| @ -8,6 +8,7 @@ import { IChannel, INodesRanking, IOldestNodes, ITopNodesPerCapacity, ITopNodesP | ||||
|   providedIn: 'root' | ||||
| }) | ||||
| export class LightningApiService { | ||||
|   private apiBaseUrl: string; // base URL is protocol, hostname, and port
 | ||||
|   private apiBasePath = ''; // network path is /testnet, etc. or '' for mainnet
 | ||||
|    | ||||
|   private requestCache = new Map<string, { subject: BehaviorSubject<any>, expiry: number }>; | ||||
| @ -16,6 +17,10 @@ export class LightningApiService { | ||||
|     private httpClient: HttpClient, | ||||
|     private stateService: StateService, | ||||
|   ) { | ||||
|     this.apiBaseUrl = ''; // use relative URL by default
 | ||||
|     if (!stateService.isBrowser) { // except when inside AU SSR process
 | ||||
|       this.apiBaseUrl = this.stateService.env.NGINX_PROTOCOL + '://' + this.stateService.env.NGINX_HOSTNAME + ':' + this.stateService.env.NGINX_PORT; | ||||
|     } | ||||
|     this.apiBasePath = ''; // assume mainnet by default
 | ||||
|     this.stateService.networkChanged$.subscribe((network) => { | ||||
|       if (network === 'bisq' && !this.stateService.env.BISQ_SEPARATE_BACKEND) { | ||||
| @ -66,15 +71,15 @@ export class LightningApiService { | ||||
|   } | ||||
| 
 | ||||
|   getNode$(publicKey: string): Observable<any> { | ||||
|     return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/nodes/' + publicKey); | ||||
|     return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/nodes/' + publicKey); | ||||
|   } | ||||
| 
 | ||||
|   getNodeGroup$(name: string): Observable<any[]> { | ||||
|     return this.httpClient.get<any[]>(this.apiBasePath + '/api/v1/lightning/nodes/group/' + name); | ||||
|     return this.httpClient.get<any[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/nodes/group/' + name); | ||||
|   } | ||||
| 
 | ||||
|   getChannel$(shortId: string): Observable<any> { | ||||
|     return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/channels/' + shortId); | ||||
|     return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/channels/' + shortId); | ||||
|   } | ||||
| 
 | ||||
|   getChannelsByNodeId$(publicKey: string, index: number = 0, status = 'open'): Observable<any> { | ||||
| @ -84,57 +89,57 @@ export class LightningApiService { | ||||
|       .set('status', status) | ||||
|     ; | ||||
| 
 | ||||
|     return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/channels', { params, observe: 'response' }); | ||||
|     return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/channels', { params, observe: 'response' }); | ||||
|   } | ||||
| 
 | ||||
|   getLatestStatistics$(): Observable<any> { | ||||
|     return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/statistics/latest'); | ||||
|     return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/statistics/latest'); | ||||
|   } | ||||
| 
 | ||||
|   listNodeStats$(publicKey: string): Observable<any> { | ||||
|     return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/nodes/' + publicKey + '/statistics'); | ||||
|     return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/nodes/' + publicKey + '/statistics'); | ||||
|   } | ||||
| 
 | ||||
|   getNodeFeeHistogram$(publicKey: string): Observable<any> { | ||||
|     return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/nodes/' + publicKey + '/fees/histogram'); | ||||
|     return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/nodes/' + publicKey + '/fees/histogram'); | ||||
|   } | ||||
| 
 | ||||
|   getNodesRanking$(): Observable<INodesRanking> { | ||||
|     return this.httpClient.get<INodesRanking>(this.apiBasePath + '/api/v1/lightning/nodes/rankings'); | ||||
|     return this.httpClient.get<INodesRanking>(this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/nodes/rankings'); | ||||
|   } | ||||
| 
 | ||||
|   listChannelStats$(publicKey: string): Observable<any> { | ||||
|     return this.httpClient.get<any>(this.apiBasePath + '/channels/' + publicKey + '/statistics'); | ||||
|     return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/channels/' + publicKey + '/statistics'); | ||||
|   } | ||||
| 
 | ||||
|   listStatistics$(interval: string | undefined): Observable<any> { | ||||
|     return this.httpClient.get<any>( | ||||
|       this.apiBasePath + '/api/v1/lightning/statistics' + | ||||
|       this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/statistics' + | ||||
|       (interval !== undefined ? `/${interval}` : ''), { observe: 'response' } | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   getTopNodesByCapacity$(): Observable<ITopNodesPerCapacity[]> { | ||||
|     return this.httpClient.get<ITopNodesPerCapacity[]>( | ||||
|       this.apiBasePath + '/api/v1/lightning/nodes/rankings/liquidity' | ||||
|       this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/nodes/rankings/liquidity' | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   getTopNodesByChannels$(): Observable<ITopNodesPerChannels[]> { | ||||
|     return this.httpClient.get<ITopNodesPerChannels[]>( | ||||
|       this.apiBasePath + '/api/v1/lightning/nodes/rankings/connectivity' | ||||
|       this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/nodes/rankings/connectivity' | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   getPenaltyClosedChannels$(): Observable<IChannel[]> { | ||||
|     return this.httpClient.get<IChannel[]>( | ||||
|       this.apiBasePath + '/api/v1/lightning/penalties' | ||||
|       this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/penalties' | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   getOldestNodes$(): Observable<IOldestNodes[]> { | ||||
|     return this.httpClient.get<IOldestNodes[]>( | ||||
|       this.apiBasePath + '/api/v1/lightning/nodes/rankings/age' | ||||
|       this.apiBaseUrl + this.apiBasePath + '/api/v1/lightning/nodes/rankings/age' | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, OnInit } from '@angular/core'; | ||||
| import { Observable } from 'rxjs'; | ||||
| import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, OnInit } from '@angular/core'; | ||||
| import { Observable, merge } from 'rxjs'; | ||||
| import { share } from 'rxjs/operators'; | ||||
| import { INodesRanking, INodesStatistics } from '../../interfaces/node-api.interface'; | ||||
| import { SeoService } from '../../services/seo.service'; | ||||
| @ -24,6 +24,7 @@ export class LightningDashboardComponent implements OnInit, AfterViewInit { | ||||
|     private seoService: SeoService, | ||||
|     private ogService: OpenGraphService, | ||||
|     private stateService: StateService, | ||||
|     private cd: ChangeDetectorRef, | ||||
|   ) { } | ||||
| 
 | ||||
|   ngOnInit(): void { | ||||
| @ -35,6 +36,12 @@ export class LightningDashboardComponent implements OnInit, AfterViewInit { | ||||
| 
 | ||||
|     this.nodesRanking$ = this.lightningApiService.getNodesRanking$().pipe(share()); | ||||
|     this.statistics$ = this.lightningApiService.getLatestStatistics$().pipe(share()); | ||||
| 
 | ||||
|     if (!this.stateService.isBrowser) { | ||||
|       merge(this.nodesRanking$, this.statistics$).subscribe(() => { | ||||
|         this.cd.markForCheck(); | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ngAfterViewInit(): void { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <div class="full-container"> | ||||
|   <h2 i18n="lightning.node-fee-distribution">Fee distribution</h2> | ||||
|   <div class="chart" *browserOnly echarts [initOpts]="chartInitOptions" [options]="chartOptions" (chartInit)="onChartInit($event)"></div> | ||||
|   <div class="text-center loadingGraphs" *ngIf="isLoading"> | ||||
|   <div class="text-center loadingGraphs" *ngIf="!stateService.isBrowser || isLoading"> | ||||
|     <div class="spinner-border text-light"></div> | ||||
|   </div> | ||||
| </div> | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| .full-container { | ||||
|   position: relative; | ||||
|   margin-top: 25px; | ||||
|   margin-bottom: 25px; | ||||
|   min-height: 100%; | ||||
| } | ||||
|   min-height: 450px; | ||||
| } | ||||
| @ -5,6 +5,7 @@ import { download } from '../../shared/graphs.utils'; | ||||
| import { LightningApiService } from '../lightning-api.service'; | ||||
| import { ActivatedRoute, ParamMap } from '@angular/router'; | ||||
| import { AmountShortenerPipe } from '../../shared/pipes/amount-shortener.pipe'; | ||||
| import { StateService } from '../../services/state.service'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-node-fee-chart', | ||||
| @ -33,6 +34,7 @@ export class NodeFeeChartComponent implements OnInit { | ||||
|   constructor( | ||||
|     @Inject(LOCALE_ID) public locale: string, | ||||
|     private lightningApiService: LightningApiService, | ||||
|     public stateService: StateService, | ||||
|     private activatedRoute: ActivatedRoute, | ||||
|     private amountShortenerPipe: AmountShortenerPipe, | ||||
|   ) { | ||||
|  | ||||
| @ -33,7 +33,6 @@ | ||||
|   min-height: 400px; | ||||
|   margin-top: 25px; | ||||
|   margin-bottom: 25px; | ||||
|   min-height: 100%; | ||||
| } | ||||
| .full-container.widget { | ||||
|   height: 250px; | ||||
|  | ||||
| @ -1,9 +1,11 @@ | ||||
| <div *ngIf="channelsObservable$ | async" style="min-height: 455px"> | ||||
|   <h2 i18n="lightning.active-channels-map">Active channels map</h2> | ||||
|   <div *browserOnly echarts [initOpts]="chartInitOptions" [options]="chartOptions" (chartInit)="onChartInit($event)"> | ||||
| <div class="node-channels-container"> | ||||
|   <div *ngIf="channelsObservable$ | async" style="min-height: 455px"> | ||||
|     <h2 i18n="lightning.active-channels-map">Active channels map</h2> | ||||
|     <div *browserOnly echarts [initOpts]="chartInitOptions" [options]="chartOptions" (chartInit)="onChartInit($event)"> | ||||
|     </div> | ||||
|   </div> | ||||
| 
 | ||||
|   <div *ngIf="!stateService.isBrowser || isLoading" class="text-center loading-spinner"> | ||||
|     <div class="spinner-border text-light"></div> | ||||
|   </div> | ||||
| </div> | ||||
| 
 | ||||
| <div *ngIf="isLoading" class="text-center loading-spinner"> | ||||
|   <div class="spinner-border text-light"></div> | ||||
| </div> | ||||
|  | ||||
| @ -1,5 +1,13 @@ | ||||
| .node-channels-container { | ||||
|   position: relative; | ||||
| } | ||||
| 
 | ||||
| .loading-spinner { | ||||
|   min-height: 455px; | ||||
|   position: absolute; | ||||
|   top: 0; | ||||
|   left: 0; | ||||
|   right: 0; | ||||
|   width: 100%; | ||||
|   z-index: 100; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -33,7 +33,7 @@ export class NodeChannels implements OnChanges { | ||||
|     private amountShortenerPipe: AmountShortenerPipe, | ||||
|     private zone: NgZone, | ||||
|     private router: Router, | ||||
|     private stateService: StateService, | ||||
|     public stateService: StateService, | ||||
|   ) {} | ||||
| 
 | ||||
|   ngOnChanges(): void { | ||||
|  | ||||
| @ -43,10 +43,6 @@ | ||||
|       (chartInit)="onChartInit($event)"> | ||||
|     </div> | ||||
| 
 | ||||
|     <div class="text-center loadingGraphs" *ngIf="isLoading"> | ||||
|       <div class="spinner-border text-light"></div> | ||||
|     </div> | ||||
| 
 | ||||
|     <div class="d-flex justify-content-md-end toggle" *ngIf="!widget"> | ||||
|       <app-toggle [textLeft]="'Sort by nodes'" [textRight]="'capacity'" [checked]="true" (toggleStatusChanged)="onGroupToggleStatusChanged($event)"></app-toggle> | ||||
|     </div> | ||||
| @ -74,6 +70,9 @@ | ||||
|       </tbody> | ||||
|     </table> | ||||
|   </div> | ||||
|   <div class="text-center loadingGraphs" *ngIf="!stateService.isBrowser || isLoading"> | ||||
|     <div class="spinner-border text-light"></div> | ||||
|   </div> | ||||
| </div> | ||||
| 
 | ||||
| <ng-template #loadingReward> | ||||
|  | ||||
| @ -44,7 +44,7 @@ export class NodesPerISPChartComponent implements OnInit { | ||||
|     private amountShortenerPipe: AmountShortenerPipe, | ||||
|     private router: Router, | ||||
|     private zone: NgZone, | ||||
|     private stateService: StateService, | ||||
|     public stateService: StateService, | ||||
|   ) { | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -44,7 +44,7 @@ | ||||
| 
 | ||||
|   <div [class]="!widget ? 'chart' : 'chart-widget'" *browserOnly [style]="{ height: widget ? (height + 'px') : null}" echarts [initOpts]="chartInitOptions" [options]="chartOptions" | ||||
|     (chartInit)="onChartInit($event)"></div> | ||||
|   <div class="text-center loadingGraphs" *ngIf="isLoading"> | ||||
|   <div class="text-center loadingGraphs" *ngIf="!stateService.isBrowser || isLoading"> | ||||
|     <div class="spinner-border text-light"></div> | ||||
|   </div> | ||||
| 
 | ||||
|  | ||||
| @ -11,6 +11,7 @@ import { download } from '../../shared/graphs.utils'; | ||||
| import { LightningApiService } from '../lightning-api.service'; | ||||
| import { AmountShortenerPipe } from '../../shared/pipes/amount-shortener.pipe'; | ||||
| import { isMobile } from '../../shared/common.utils'; | ||||
| import { StateService } from '../../services/state.service'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-lightning-statistics-chart', | ||||
| @ -55,6 +56,7 @@ export class LightningStatisticsChartComponent implements OnInit, OnChanges { | ||||
|     private formBuilder: UntypedFormBuilder, | ||||
|     private storageService: StorageService, | ||||
|     private miningService: MiningService, | ||||
|     public stateService: StateService, | ||||
|     private amountShortenerPipe: AmountShortenerPipe, | ||||
|   ) { | ||||
|   } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user