Electrs server status page
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<div class="tomahawk">
|
||||
<ng-container *ngIf="(hosts$ | async) as hosts">
|
||||
<div class="status-panel">
|
||||
<table class="status-table table table-borderless table-striped" *ngIf="(tip$ | async) as tip">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="active"></th>
|
||||
<th class="host">Host</th>
|
||||
<th class="rtt">RTT</th>
|
||||
<th class="height">Height</th>
|
||||
</tr>
|
||||
<tr *ngFor="let host of hosts;" (click)="scrollTo(host)">
|
||||
<td class="active"><span *ngIf="host.active">⭐️</span></td>
|
||||
<td class="host">{{ host.host }}</td>
|
||||
<td class="rtt">{{ host.rtt | number : '1.0-0' }} {{ host.rtt == null ? '' : 'ms'}} {{ !host.checked ? '⏳' : (host.unreachable ? '🔥' : '✅') }}</td>
|
||||
<td class="height">{{ host.latestHeight }} {{ !host.checked ? '⏳' : (host.outOfSync ? '🚫' : (host.latestHeight && host.latestHeight < tip ? '🟧' : '✅')) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngFor="let host of hosts; trackBy: trackByFn">
|
||||
<h5 [id]="host.host" class="hostLink">
|
||||
<a [href]="host.link">{{ host.link }}</a>
|
||||
</h5>
|
||||
<iframe class="mempoolStatus" [src]="host.statusPage"></iframe>
|
||||
</ng-container>
|
||||
</div>
|
||||
@@ -0,0 +1,35 @@
|
||||
.tomahawk {
|
||||
.status-panel {
|
||||
max-width: 720px;
|
||||
margin: auto;
|
||||
margin-top: 2em;
|
||||
padding: 1em;
|
||||
background: #24273e;
|
||||
}
|
||||
|
||||
.status-table {
|
||||
width: 100%;
|
||||
|
||||
td, th {
|
||||
padding: 0.25em;
|
||||
&.rtt, &.height {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.mempoolStatus {
|
||||
width: 100%;
|
||||
height: 270px;
|
||||
}
|
||||
|
||||
.hostLink {
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Component, OnInit, ChangeDetectionStrategy, SecurityContext, OnDestroy } from '@angular/core';
|
||||
import { WebsocketService } from '../../services/websocket.service';
|
||||
import { Observable, Subject, map, tap } from 'rxjs';
|
||||
import { StateService } from '../../services/state.service';
|
||||
import { HealthCheckHost } from '../../interfaces/websocket.interface';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'app-server-health',
|
||||
templateUrl: './server-health.component.html',
|
||||
styleUrls: ['./server-health.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ServerHealthComponent implements OnInit, OnDestroy {
|
||||
hosts$: Observable<HealthCheckHost[]>;
|
||||
tip$: Subject<number>;
|
||||
hosts: HealthCheckHost[] = [];
|
||||
|
||||
constructor(
|
||||
private websocketService: WebsocketService,
|
||||
private stateService: StateService,
|
||||
public sanitizer: DomSanitizer,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.hosts$ = this.stateService.serverHealth$.pipe(
|
||||
map((hosts) => {
|
||||
const subpath = window.location.pathname.slice(0, -6);
|
||||
for (const host of hosts) {
|
||||
let statusUrl = '';
|
||||
let linkHost = '';
|
||||
if (host.socket) {
|
||||
statusUrl = window.location.host + subpath + '/status';
|
||||
linkHost = window.location.host + subpath;
|
||||
} else {
|
||||
statusUrl = host.host.slice(0, -4) + subpath + '/status';
|
||||
linkHost = host.host.slice(0, -4) + subpath;
|
||||
}
|
||||
host.statusPage = this.sanitizer.bypassSecurityTrustResourceUrl(this.sanitizer.sanitize(SecurityContext.URL, statusUrl));
|
||||
host.link = linkHost;
|
||||
}
|
||||
return hosts;
|
||||
}),
|
||||
tap((hosts) => {
|
||||
if (this.hosts.length !== hosts.length) {
|
||||
this.hosts = hosts;
|
||||
}
|
||||
})
|
||||
);
|
||||
this.tip$ = this.stateService.chainTip$;
|
||||
this.websocketService.want(['blocks', 'tomahawk']);
|
||||
}
|
||||
|
||||
scrollTo(host: HealthCheckHost): void {
|
||||
const el = document.getElementById(host.host);
|
||||
if (el) {
|
||||
el.scrollIntoView();
|
||||
}
|
||||
}
|
||||
|
||||
trackByFn(index: number, host: HealthCheckHost): string {
|
||||
return host.host;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.hosts = [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user