diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts
index 18949876e..e123a1525 100644
--- a/frontend/src/app/app-routing.module.ts
+++ b/frontend/src/app/app-routing.module.ts
@@ -6,7 +6,6 @@ import { EightBlocksComponent } from './components/eight-blocks/eight-blocks.com
import { MempoolBlockViewComponent } from './components/mempool-block-view/mempool-block-view.component';
import { ClockComponent } from './components/clock/clock.component';
import { StatusViewComponent } from './components/status-view/status-view.component';
-import { ServerHealthComponent } from './components/server-health/server-health.component';
const browserWindow = window || {};
// @ts-ignore
@@ -32,11 +31,6 @@ let routes: Routes = [
data: { networks: ['bitcoin', 'liquid'] },
component: StatusViewComponent
},
- {
- path: 'nodes',
- data: { networks: ['bitcoin', 'liquid'] },
- component: ServerHealthComponent
- },
{
path: '',
loadChildren: () => import('./bitcoin-graphs.module').then(m => m.BitcoinGraphsModule),
@@ -72,11 +66,6 @@ let routes: Routes = [
data: { networks: ['bitcoin', 'liquid'] },
component: StatusViewComponent
},
- {
- path: 'nodes',
- data: { networks: ['bitcoin', 'liquid'] },
- component: ServerHealthComponent
- },
{
path: '',
loadChildren: () => import('./bitcoin-graphs.module').then(m => m.BitcoinGraphsModule),
@@ -145,11 +134,6 @@ let routes: Routes = [
data: { networks: ['bitcoin', 'liquid'] },
component: StatusViewComponent
},
- {
- path: 'nodes',
- data: { networks: ['bitcoin', 'liquid'] },
- component: ServerHealthComponent
- },
{
path: '',
loadChildren: () => import('./bitcoin-graphs.module').then(m => m.BitcoinGraphsModule),
@@ -189,11 +173,6 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
data: { networks: ['bitcoin', 'liquid'] },
component: StatusViewComponent
},
- {
- path: 'nodes',
- data: { networks: ['bitcoin', 'liquid'] },
- component: ServerHealthComponent
- },
{
path: '',
loadChildren: () => import('./liquid/liquid-graphs.module').then(m => m.LiquidGraphsModule),
@@ -234,11 +213,6 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
data: { networks: ['bitcoin', 'liquid']},
component: StatusViewComponent
},
- {
- path: 'nodes',
- data: { networks: ['bitcoin', 'liquid'] },
- component: ServerHealthComponent
- },
{
path: '',
loadChildren: () => import('./liquid/liquid-graphs.module').then(m => m.LiquidGraphsModule),
diff --git a/frontend/src/app/components/server-health/server-health.component.html b/frontend/src/app/components/server-health/server-health.component.html
index dd8d61444..f376b4314 100644
--- a/frontend/src/app/components/server-health/server-health.component.html
+++ b/frontend/src/app/components/server-health/server-health.component.html
@@ -1,4 +1,10 @@
-
+
+
+
Node Status
+
@@ -9,7 +15,7 @@
RTT |
Height |
-
+
⭐️ |
{{ host.host }} |
{{ host.rtt | number : '1.0-0' }} {{ host.rtt == null ? '' : 'ms'}} {{ !host.checked ? '⏳' : (host.unreachable ? '🔥' : '✅') }} |
@@ -19,11 +25,4 @@
-
-
-
-
-
diff --git a/frontend/src/app/components/server-health/server-health.component.scss b/frontend/src/app/components/server-health/server-health.component.scss
index e403e5824..ebc6a883c 100644
--- a/frontend/src/app/components/server-health/server-health.component.scss
+++ b/frontend/src/app/components/server-health/server-health.component.scss
@@ -1,4 +1,18 @@
.tomahawk {
+ .links {
+ float: right;
+ text-align: right;
+ margin-top: 1em;
+
+ a, span {
+ margin-left: 1em;
+ }
+ }
+
+ .dashboard-title {
+ text-align: left;
+ }
+
.status-panel {
max-width: 720px;
margin: auto;
@@ -16,20 +30,5 @@
text-align: right;
}
}
-
- td {
- cursor: pointer;
- }
- }
-
- .mempoolStatus {
- width: 100%;
- height: 270px;
- }
-
- .hostLink {
- text-align: center;
- margin: auto;
- margin-top: 1em;
}
}
\ No newline at end of file
diff --git a/frontend/src/app/components/server-health/server-health.component.ts b/frontend/src/app/components/server-health/server-health.component.ts
index bd7cc57e8..b1008a4a5 100644
--- a/frontend/src/app/components/server-health/server-health.component.ts
+++ b/frontend/src/app/components/server-health/server-health.component.ts
@@ -1,6 +1,6 @@
-import { Component, OnInit, ChangeDetectionStrategy, SecurityContext, OnDestroy } from '@angular/core';
+import { Component, OnInit, ChangeDetectionStrategy, SecurityContext } from '@angular/core';
import { WebsocketService } from '../../services/websocket.service';
-import { Observable, Subject, map, tap } from 'rxjs';
+import { Observable, Subject, map } from 'rxjs';
import { StateService } from '../../services/state.service';
import { HealthCheckHost } from '../../interfaces/websocket.interface';
import { DomSanitizer } from '@angular/platform-browser';
@@ -11,10 +11,9 @@ import { DomSanitizer } from '@angular/platform-browser';
styleUrls: ['./server-health.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class ServerHealthComponent implements OnInit, OnDestroy {
+export class ServerHealthComponent implements OnInit {
hosts$: Observable
;
tip$: Subject;
- hosts: HealthCheckHost[] = [];
constructor(
private websocketService: WebsocketService,
@@ -33,36 +32,17 @@ export class ServerHealthComponent implements OnInit, OnDestroy {
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;
+ const hostUrl = new URL(host.host);
+ statusUrl = 'https://' + hostUrl.hostname + subpath + '/status';
+ linkHost = hostUrl.hostname + 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 = [];
- }
}
diff --git a/frontend/src/app/components/server-health/server-status.component.html b/frontend/src/app/components/server-health/server-status.component.html
new file mode 100644
index 000000000..484d774a0
--- /dev/null
+++ b/frontend/src/app/components/server-health/server-status.component.html
@@ -0,0 +1,14 @@
+
+
+
Live Network
+
+
+
+
+
+
diff --git a/frontend/src/app/components/server-health/server-status.component.scss b/frontend/src/app/components/server-health/server-status.component.scss
new file mode 100644
index 000000000..09bebe040
--- /dev/null
+++ b/frontend/src/app/components/server-health/server-status.component.scss
@@ -0,0 +1,26 @@
+.tomahawk {
+ .links {
+ float: right;
+ text-align: right;
+ margin-top: 1em;
+
+ a, span {
+ margin-left: 1em;
+ }
+ }
+
+ .dashboard-title {
+ text-align: left;
+ }
+
+ .mempoolStatus {
+ width: 100%;
+ height: 270px;
+ }
+
+ .hostLink {
+ text-align: center;
+ margin: auto;
+ margin-top: 1em;
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/app/components/server-health/server-status.component.ts b/frontend/src/app/components/server-health/server-status.component.ts
new file mode 100644
index 000000000..8c893988d
--- /dev/null
+++ b/frontend/src/app/components/server-health/server-status.component.ts
@@ -0,0 +1,80 @@
+import { Component, OnInit, ChangeDetectionStrategy, SecurityContext, OnDestroy, ChangeDetectorRef } from '@angular/core';
+import { WebsocketService } from '../../services/websocket.service';
+import { Observable, Subject, Subscription, 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-status',
+ templateUrl: './server-status.component.html',
+ styleUrls: ['./server-status.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class ServerStatusComponent implements OnInit, OnDestroy {
+ tip$: Subject;
+ hosts: HealthCheckHost[] = [];
+ hostSubscription: Subscription;
+
+ constructor(
+ private websocketService: WebsocketService,
+ private stateService: StateService,
+ private cd: ChangeDetectorRef,
+ public sanitizer: DomSanitizer,
+ ) {}
+
+ ngOnInit(): void {
+ this.hostSubscription = this.stateService.serverHealth$.pipe(
+ map((hosts) => {
+ const subpath = window.location.pathname.slice(0, -8);
+ for (const host of hosts) {
+ let statusUrl = '';
+ let linkHost = '';
+ if (host.socket) {
+ statusUrl = window.location.host + subpath + '/status';
+ linkHost = window.location.host + subpath;
+ } else {
+ const hostUrl = new URL(host.host);
+ statusUrl = 'https://' + hostUrl.hostname + subpath + '/status';
+ linkHost = hostUrl.hostname + 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.sort((a,b) => {
+ const aParts = (a.host?.split('.') || []).reverse();
+ const bParts = (b.host?.split('.') || []).reverse();
+ let i = 0;
+ while (i < Math.max(aParts.length, bParts.length)) {
+ if (aParts[i] && !bParts[i]) {
+ return 1;
+ } else if (bParts[i] && !aParts[i]) {
+ return -1;
+ } else if (aParts[i] !== bParts[i]) {
+ return aParts[i].localeCompare(bParts[i]);
+ }
+ i++;
+ }
+ return 0;
+ });
+ }
+ this.cd.markForCheck();
+ })
+ ).subscribe();
+ this.tip$ = this.stateService.chainTip$;
+ this.websocketService.want(['blocks', 'tomahawk']);
+ }
+
+ trackByFn(index: number, host: HealthCheckHost): string {
+ return host.host;
+ }
+
+ ngOnDestroy(): void {
+ this.hosts = [];
+ this.hostSubscription.unsubscribe();
+ }
+}
diff --git a/frontend/src/app/liquid/liquid-master-page.module.ts b/frontend/src/app/liquid/liquid-master-page.module.ts
index 8988cb05c..4b8364ad5 100644
--- a/frontend/src/app/liquid/liquid-master-page.module.ts
+++ b/frontend/src/app/liquid/liquid-master-page.module.ts
@@ -19,6 +19,8 @@ import { RecentPegsListComponent } from '../components/liquid-reserves-audit/rec
import { FederationWalletComponent } from '../components/liquid-reserves-audit/federation-wallet/federation-wallet.component';
import { FederationUtxosListComponent } from '../components/liquid-reserves-audit/federation-utxos-list/federation-utxos-list.component';
import { FederationAddressesListComponent } from '../components/liquid-reserves-audit/federation-addresses-list/federation-addresses-list.component';
+import { ServerHealthComponent } from '../components/server-health/server-health.component';
+import { ServerStatusComponent } from '../components/server-health/server-status.component';
const routes: Routes = [
{
@@ -140,6 +142,19 @@ const routes: Routes = [
},
];
+if (window['__env']?.OFFICIAL_MEMPOOL_SPACE) {
+ routes[0].children.push({
+ path: 'nodes',
+ data: { networks: ['bitcoin', 'liquid'] },
+ component: ServerHealthComponent
+ });
+ routes[0].children.push({
+ path: 'network',
+ data: { networks: ['bitcoin', 'liquid'] },
+ component: ServerStatusComponent
+ });
+}
+
@NgModule({
imports: [
RouterModule.forChild(routes)
diff --git a/frontend/src/app/master-page.module.ts b/frontend/src/app/master-page.module.ts
index d7ec87030..ec3e08674 100644
--- a/frontend/src/app/master-page.module.ts
+++ b/frontend/src/app/master-page.module.ts
@@ -10,6 +10,8 @@ import { PushTransactionComponent } from './components/push-transaction/push-tra
import { CalculatorComponent } from './components/calculator/calculator.component';
import { BlocksList } from './components/blocks-list/blocks-list.component';
import { RbfList } from './components/rbf-list/rbf-list.component';
+import { ServerHealthComponent } from './components/server-health/server-health.component';
+import { ServerStatusComponent } from './components/server-health/server-status.component';
const browserWindow = window || {};
// @ts-ignore
@@ -96,6 +98,19 @@ const routes: Routes = [
}
];
+if (window['__env']?.OFFICIAL_MEMPOOL_SPACE) {
+ routes[0].children.push({
+ path: 'nodes',
+ data: { networks: ['bitcoin', 'liquid'] },
+ component: ServerHealthComponent
+ });
+ routes[0].children.push({
+ path: 'network',
+ data: { networks: ['bitcoin', 'liquid'] },
+ component: ServerStatusComponent
+ });
+}
+
@NgModule({
imports: [
RouterModule.forChild(routes)
diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts
index 6c43a019f..2f6496559 100644
--- a/frontend/src/app/shared/shared.module.ts
+++ b/frontend/src/app/shared/shared.module.ts
@@ -54,6 +54,7 @@ import { AssetsComponent } from '../components/assets/assets.component';
import { AssetsNavComponent } from '../components/assets/assets-nav/assets-nav.component';
import { StatusViewComponent } from '../components/status-view/status-view.component';
import { ServerHealthComponent } from '../components/server-health/server-health.component';
+import { ServerStatusComponent } from '../components/server-health/server-status.component';
import { FeesBoxComponent } from '../components/fees-box/fees-box.component';
import { DifficultyComponent } from '../components/difficulty/difficulty.component';
import { DifficultyTooltipComponent } from '../components/difficulty/difficulty-tooltip.component';
@@ -153,6 +154,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
AssetsComponent,
StatusViewComponent,
ServerHealthComponent,
+ ServerStatusComponent,
FeesBoxComponent,
DifficultyComponent,
DifficultyMiningComponent,
@@ -280,6 +282,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
AssetsComponent,
StatusViewComponent,
ServerHealthComponent,
+ ServerStatusComponent,
FeesBoxComponent,
DifficultyComponent,
DifficultyMiningComponent,