Show error message when the node public key does not exist

This commit is contained in:
nymkappa 2022-07-24 12:34:50 +02:00
parent 886e7e6638
commit d9e85fdcb6
No known key found for this signature in database
GPG Key ID: E155910B16E8BD04
2 changed files with 136 additions and 108 deletions

View File

@ -1,128 +1,146 @@
<div class="container-xl" *ngIf="(node$ | async) as node">
<div class="title-container mb-2">
<div class="title-container mb-2" *ngIf="!error">
<h1 class="mb-0">{{ node.alias }}</h1>
<span class="tx-link">
<a [routerLink]="['/lightning/node' | relativeUrl, node.public_key]">{{ node.public_key | shortenString : 12 }}</a>
<a [routerLink]="['/lightning/node' | relativeUrl, node.public_key]">{{ node.public_key | shortenString : 12
}}</a>
<app-clipboard [text]="node.public_key"></app-clipboard>
</span>
</div>
<div class="clearfix"></div>
<div class="box">
<div *ngIf="error" class="d-flex flex-column justify-content-around align-items-center mt-5 w-100" style="min-height: 100px">
<span i18n="lightning.node-not-found">No node found for public key "{{ node.public_key | shortenString : 12}}"</span>
<a [routerLink]="['/lightning' | relativeUrl]" i18n="lightning.back-to-lightning-dashboard">Back to the lightning dashboard</a>
</div>
<div class="row">
<div class="col-md">
<table class="table table-borderless table-striped">
<tbody>
<tr>
<td i18n="address.total-received">Total capacity</td>
<td>
<app-sats [satoshis]="node.capacity"></app-sats><app-fiat [value]="node.capacity" digitsInfo="1.0-0"></app-fiat>
</td>
</tr>
<tr>
<td i18n="address.total-sent">Total channels</td>
<td>
{{ node.channel_active_count }}
</td>
</tr>
<tr>
<td i18n="address.total-received">Average channel size</td>
<td>
<app-sats [satoshis]="node.channels_capacity_avg"></app-sats><app-fiat [value]="node.channels_capacity_avg" digitsInfo="1.0-0"></app-fiat>
</td>
</tr>
<tr *ngIf="node.country && node.city && node.subdivision">
<td i18n="location">Location</td>
<td>{{ node.city.en }}, {{ node.subdivision.en }}<br>{{ node.country.en }}</td>
</tr>
<tr *ngIf="node.country && !node.city">
<td i18n="location">Location</td>
<td>{{ node.country.en }}</td>
</tr>
</tbody>
</table>
</div>
<div class="w-100 d-block d-md-none"></div>
<div class="col-md">
<table class="table table-borderless table-striped">
<tbody>
<tr>
<td i18n="address.total-received">First seen</td>
<td>
<app-timestamp [dateString]="node.first_seen"></app-timestamp>
</td>
</tr>
<tr>
<td i18n="address.total-sent">Last update</td>
<td>
<app-timestamp [dateString]="node.updated_at"></app-timestamp>
</td>
</tr>
<tr>
<td i18n="address.balance">Color</td>
<td><div [ngStyle]="{'color': node.color}">{{ node.color }}</div></td>
</tr>
<tr *ngIf="node.country">
<td i18n="isp">ISP</td>
<td>
{{ node.as_organization }} [ASN {{node.as_number}}]
</td>
</tr>
</tbody>
</table>
</div>
<div class="box" *ngIf="!error">
<div class="row">
<div class="col-md">
<table class="table table-borderless table-striped">
<tbody>
<tr>
<td i18n="address.total-received">Total capacity</td>
<td>
<app-sats [satoshis]="node.capacity"></app-sats>
<app-fiat [value]="node.capacity" digitsInfo="1.0-0"></app-fiat>
</td>
</tr>
<tr>
<td i18n="address.total-sent">Total channels</td>
<td>
{{ node.channel_active_count }}
</td>
</tr>
<tr>
<td i18n="address.total-received">Average channel size</td>
<td>
<app-sats [satoshis]="node.channels_capacity_avg"></app-sats>
<app-fiat [value]="node.channels_capacity_avg" digitsInfo="1.0-0"></app-fiat>
</td>
</tr>
<tr *ngIf="node.country && node.city && node.subdivision">
<td i18n="location">Location</td>
<td>{{ node.city.en }}, {{ node.subdivision.en }}<br>{{ node.country.en }}</td>
</tr>
<tr *ngIf="node.country && !node.city">
<td i18n="location">Location</td>
<td>{{ node.country.en }}</td>
</tr>
</tbody>
</table>
</div>
<div class="w-100 d-block d-md-none"></div>
<div class="col-md">
<table class="table table-borderless table-striped">
<tbody>
<tr>
<td i18n="address.total-received">First seen</td>
<td>
<app-timestamp [dateString]="node.first_seen"></app-timestamp>
</td>
</tr>
<tr>
<td i18n="address.total-sent">Last update</td>
<td>
<app-timestamp [dateString]="node.updated_at"></app-timestamp>
</td>
</tr>
<tr>
<td i18n="address.balance">Color</td>
<td>
<div [ngStyle]="{'color': node.color}">{{ node.color }}</div>
</td>
</tr>
<tr *ngIf="node.country">
<td i18n="isp">ISP</td>
<td>
{{ node.as_organization }} [ASN {{node.as_number}}]
</td>
</tr>
</tbody>
</table>
</div>
</div>
<br>
</div>
<div class="input-group mb-3" *ngIf="node.socketsObject.length">
<div class="d-inline-block" ngbDropdown #myDrop="ngbDropdown" *ngIf="node.socketsObject.length > 1; else noDropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" aria-expanded="false" ngbDropdownAnchor (focus)="myDrop.open()"><div class="dropdownLabel">{{ node.socketsObject[selectedSocketIndex].label }}</div></button>
<div ngbDropdownMenu aria-labelledby="dropdownManual">
<button *ngFor="let socket of node.socketsObject; let i = index;" ngbDropdownItem (click)="changeSocket(i)">{{ socket.label }}</button>
</div>
<br>
<div class="input-group mb-3" *ngIf="!error && node.socketsObject.length">
<div class="d-inline-block" ngbDropdown #myDrop="ngbDropdown"
*ngIf="node.socketsObject.length > 1; else noDropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" aria-expanded="false" ngbDropdownAnchor
(focus)="myDrop.open()">
<div class="dropdownLabel">{{ node.socketsObject[selectedSocketIndex].label }}</div>
</button>
<div ngbDropdownMenu aria-labelledby="dropdownManual">
<button *ngFor="let socket of node.socketsObject; let i = index;" ngbDropdownItem (click)="changeSocket(i)">{{
socket.label }}</button>
</div>
<ng-template #noDropdown>
<span class="input-group-text" id="basic-addon3">{{ node.socketsObject[selectedSocketIndex].label }}</span>
</ng-template>
<input type="text" class="form-control" aria-label="Text input with dropdown button" [value]="node.socketsObject[selectedSocketIndex].socket">
<button class="btn btn-secondary ml-1" type="button" id="inputGroupFileAddon04" (mouseover)="qrCodeVisible = true" (mouseout)="qrCodeVisible = false">
<fa-icon [icon]="['fas', 'qrcode']" [fixedWidth]="true"></fa-icon>
<div class="qr-wrapper" [hidden]="!qrCodeVisible">
<app-qrcode [size]="200" [data]="node.socketsObject[selectedSocketIndex].socket"></app-qrcode>
</div>
</button>
<button class="btn btn-secondary ml-1" type="button" id="inputGroupFileAddon04">
<app-clipboard [text]="node.socketsObject[selectedSocketIndex].socket"></app-clipboard>
</button>
</div>
<ng-template #noDropdown>
<span class="input-group-text" id="basic-addon3">{{ node.socketsObject[selectedSocketIndex].label }}</span>
</ng-template>
<input type="text" class="form-control" aria-label="Text input with dropdown button"
[value]="node.socketsObject[selectedSocketIndex].socket">
<button class="btn btn-secondary ml-1" type="button" id="inputGroupFileAddon04" (mouseover)="qrCodeVisible = true"
(mouseout)="qrCodeVisible = false">
<fa-icon [icon]="['fas', 'qrcode']" [fixedWidth]="true"></fa-icon>
<div class="qr-wrapper" [hidden]="!qrCodeVisible">
<app-qrcode [size]="200" [data]="node.socketsObject[selectedSocketIndex].socket"></app-qrcode>
</div>
</button>
<button class="btn btn-secondary ml-1" type="button" id="inputGroupFileAddon04">
<app-clipboard [text]="node.socketsObject[selectedSocketIndex].socket"></app-clipboard>
</button>
</div>
<br>
<br>
<app-node-statistics-chart [publicKey]="node.public_key"></app-node-statistics-chart>
<app-node-statistics-chart [publicKey]="node.public_key" *ngIf="!error"></app-node-statistics-chart>
<br>
<div class="d-flex justify-content-between" *ngIf="!error">
<h2>Channels ({{ channelsListStatus === 'open' ? node.channel_active_count : node.channel_closed_count }})</h2>
<div class="d-flex align-items-center justify-content-end">
<span style="margin-bottom: 0.5rem">List</span>&nbsp;
<label class="switch">
<input type="checkbox" (change)="channelsListModeChange($event)">
<span class="slider round"></span>
</label>
&nbsp;<span style="margin-bottom: 0.5rem">Map</span>
</div>
</div>
<app-nodes-channels-map *ngIf="channelsListMode === 'map' && !error" [style]="'nodepage'" [publicKey]="node.public_key">
</app-nodes-channels-map>
<app-channels-list *ngIf="channelsListMode === 'list' && !error" [publicKey]="node.public_key"
(channelsStatusChangedEvent)="onChannelsListStatusChanged($event)"></app-channels-list>
<br>
<div class="d-flex justify-content-between">
<h2>Channels ({{ channelsListStatus === 'open' ? node.channel_active_count : node.channel_closed_count }})</h2>
<div class="d-flex align-items-center justify-content-end">
<span style="margin-bottom: 0.5rem">List</span>&nbsp;
<label class="switch">
<input type="checkbox" (change)="channelsListModeChange($event)">
<span class="slider round"></span>
</label>
&nbsp;<span style="margin-bottom: 0.5rem">Map</span>
</div>
</div>
<app-nodes-channels-map *ngIf="channelsListMode === 'map'" [style]="'nodepage'" [publicKey]="node.public_key"></app-nodes-channels-map>
<app-channels-list *ngIf="channelsListMode === 'list'" [publicKey]="node.public_key"
(channelsStatusChangedEvent)="onChannelsListStatusChanged($event)"></app-channels-list>
</div>
<br>
<br>

View File

@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { catchError, map, switchMap } from 'rxjs/operators';
import { SeoService } from 'src/app/services/seo.service';
import { LightningApiService } from '../lightning-api.service';
@ -19,6 +19,8 @@ export class NodeComponent implements OnInit {
qrCodeVisible = false;
channelsListMode = 'list';
channelsListStatus: string;
error: Error;
publicKey: string;
constructor(
private lightningApiService: LightningApiService,
@ -30,6 +32,7 @@ export class NodeComponent implements OnInit {
this.node$ = this.activatedRoute.paramMap
.pipe(
switchMap((params: ParamMap) => {
this.publicKey = params.get('public_key');
return this.lightningApiService.getNode$(params.get('public_key'));
}),
map((node) => {
@ -56,6 +59,13 @@ export class NodeComponent implements OnInit {
node.socketsObject = socketsObject;
return node;
}),
catchError(err => {
this.error = err;
return [{
alias: this.publicKey,
public_key: this.publicKey,
}];
})
);
}