Merge branch 'master' into block-preview-title-layout
This commit is contained in:
commit
deae7b28e6
@ -3,14 +3,10 @@ import { Routes, RouterModule } from '@angular/router';
|
|||||||
import { AppPreloadingStrategy } from './app.preloading-strategy'
|
import { AppPreloadingStrategy } from './app.preloading-strategy'
|
||||||
import { StartComponent } from './components/start/start.component';
|
import { StartComponent } from './components/start/start.component';
|
||||||
import { TransactionComponent } from './components/transaction/transaction.component';
|
import { TransactionComponent } from './components/transaction/transaction.component';
|
||||||
import { TransactionPreviewComponent } from './components/transaction/transaction-preview.component';
|
|
||||||
import { BlockComponent } from './components/block/block.component';
|
import { BlockComponent } from './components/block/block.component';
|
||||||
import { BlockAuditComponent } from './components/block-audit/block-audit.component';
|
import { BlockAuditComponent } from './components/block-audit/block-audit.component';
|
||||||
import { BlockPreviewComponent } from './components/block/block-preview.component';
|
|
||||||
import { AddressComponent } from './components/address/address.component';
|
import { AddressComponent } from './components/address/address.component';
|
||||||
import { AddressPreviewComponent } from './components/address/address-preview.component';
|
|
||||||
import { MasterPageComponent } from './components/master-page/master-page.component';
|
import { MasterPageComponent } from './components/master-page/master-page.component';
|
||||||
import { MasterPagePreviewComponent } from './components/master-page-preview/master-page-preview.component';
|
|
||||||
import { AboutComponent } from './components/about/about.component';
|
import { AboutComponent } from './components/about/about.component';
|
||||||
import { StatusViewComponent } from './components/status-view/status-view.component';
|
import { StatusViewComponent } from './components/status-view/status-view.component';
|
||||||
import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component';
|
import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component';
|
||||||
@ -346,61 +342,18 @@ let routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'preview',
|
path: 'preview',
|
||||||
component: MasterPagePreviewComponent,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'block/:id',
|
path: '',
|
||||||
component: BlockPreviewComponent
|
loadChildren: () => import('./previews.module').then(m => m.PreviewsModule)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'testnet/block/:id',
|
path: 'testnet',
|
||||||
component: BlockPreviewComponent
|
loadChildren: () => import('./previews.module').then(m => m.PreviewsModule)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'signet/block/:id',
|
path: 'signet',
|
||||||
component: BlockPreviewComponent
|
loadChildren: () => import('./previews.module').then(m => m.PreviewsModule)
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressPreviewComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'testnet/address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressPreviewComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'signet/address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressPreviewComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tx/:id',
|
|
||||||
children: [],
|
|
||||||
component: TransactionPreviewComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'testnet/tx/:id',
|
|
||||||
children: [],
|
|
||||||
component: TransactionPreviewComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'signet/tx/:id',
|
|
||||||
children: [],
|
|
||||||
component: TransactionPreviewComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lightning',
|
|
||||||
loadChildren: () => import('./lightning/lightning-previews.module').then(m => m.LightningPreviewsModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'testnet/lightning',
|
|
||||||
loadChildren: () => import('./lightning/lightning-previews.module').then(m => m.LightningPreviewsModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'signet/lightning',
|
|
||||||
loadChildren: () => import('./lightning/lightning-previews.module').then(m => m.LightningPreviewsModule)
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -643,35 +596,14 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'preview',
|
path: 'preview',
|
||||||
component: MasterPagePreviewComponent,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'block/:id',
|
path: '',
|
||||||
component: BlockPreviewComponent
|
loadChildren: () => import('./previews.module').then(m => m.PreviewsModule)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'testnet/block/:id',
|
path: 'testnet',
|
||||||
component: BlockPreviewComponent
|
loadChildren: () => import('./previews.module').then(m => m.PreviewsModule)
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressPreviewComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'testnet/address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressPreviewComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tx/:id',
|
|
||||||
children: [],
|
|
||||||
component: TransactionPreviewComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'testnet/tx/:id',
|
|
||||||
children: [],
|
|
||||||
component: TransactionPreviewComponent
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -8,10 +8,12 @@ import { LightningApiService } from './lightning-api.service';
|
|||||||
import { NodePreviewComponent } from './node/node-preview.component';
|
import { NodePreviewComponent } from './node/node-preview.component';
|
||||||
import { LightningPreviewsRoutingModule } from './lightning-previews.routing.module';
|
import { LightningPreviewsRoutingModule } from './lightning-previews.routing.module';
|
||||||
import { ChannelPreviewComponent } from './channel/channel-preview.component';
|
import { ChannelPreviewComponent } from './channel/channel-preview.component';
|
||||||
|
import { NodesPerISPPreview } from './nodes-per-isp/nodes-per-isp-preview.component';
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
NodePreviewComponent,
|
NodePreviewComponent,
|
||||||
ChannelPreviewComponent,
|
ChannelPreviewComponent,
|
||||||
|
NodesPerISPPreview,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
|
|||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { NodePreviewComponent } from './node/node-preview.component';
|
import { NodePreviewComponent } from './node/node-preview.component';
|
||||||
import { ChannelPreviewComponent } from './channel/channel-preview.component';
|
import { ChannelPreviewComponent } from './channel/channel-preview.component';
|
||||||
|
import { NodesPerISPPreview } from './nodes-per-isp/nodes-per-isp-preview.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -12,6 +13,10 @@ const routes: Routes = [
|
|||||||
path: 'channel/:short_id',
|
path: 'channel/:short_id',
|
||||||
component: ChannelPreviewComponent,
|
component: ChannelPreviewComponent,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'nodes/isp/:isp',
|
||||||
|
component: NodesPerISPPreview,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
redirectTo: ''
|
redirectTo: ''
|
||||||
|
@ -43,6 +43,13 @@
|
|||||||
|
|
||||||
<ng-template #loadingReward>
|
<ng-template #loadingReward>
|
||||||
<div class="fee-estimation-container loading-container">
|
<div class="fee-estimation-container loading-container">
|
||||||
|
<div class="item">
|
||||||
|
<h5 class="card-title" i18n="lightning.capacity">Capacity</h5>
|
||||||
|
<div class="card-text">
|
||||||
|
<div class="skeleton-loader"></div>
|
||||||
|
<div class="skeleton-loader"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<h5 class="card-title" i18n="lightning.nodes">Nodes</h5>
|
<h5 class="card-title" i18n="lightning.nodes">Nodes</h5>
|
||||||
<div class="card-text">
|
<div class="card-text">
|
||||||
@ -57,12 +64,5 @@
|
|||||||
<div class="skeleton-loader"></div>
|
<div class="skeleton-loader"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
|
||||||
<h5 class="card-title" i18n="lightning.average-channels">Average Channel</h5>
|
|
||||||
<div class="card-text">
|
|
||||||
<div class="skeleton-loader"></div>
|
|
||||||
<div class="skeleton-loader"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
@ -42,7 +42,7 @@ export class NodePreviewComponent implements OnInit {
|
|||||||
this.node$ = this.activatedRoute.paramMap
|
this.node$ = this.activatedRoute.paramMap
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap((params: ParamMap) => {
|
switchMap((params: ParamMap) => {
|
||||||
this.publicKey = params.get('public_key');
|
this.publicKey = params.get('public_key');
|
||||||
this.openGraphService.waitFor('node-map-' + this.publicKey);
|
this.openGraphService.waitFor('node-map-' + this.publicKey);
|
||||||
this.openGraphService.waitFor('node-data-' + this.publicKey);
|
this.openGraphService.waitFor('node-data-' + this.publicKey);
|
||||||
return this.lightningApiService.getNode$(params.get('public_key'));
|
return this.lightningApiService.getNode$(params.get('public_key'));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="full-container" [class]="widget ? 'widget' : ''">
|
<div class="full-container" [class]="widget ? 'widget' : ''" [class.fit-container]="fitContainer">
|
||||||
|
|
||||||
<div *ngIf="!widget" class="card-header">
|
<div *ngIf="!widget" class="card-header">
|
||||||
<div class="d-flex d-md-block align-items-baseline" style="margin-bottom: -5px">
|
<div class="d-flex d-md-block align-items-baseline" style="margin-bottom: -5px">
|
||||||
@ -8,7 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="observable$ | async" class="chart" [class]="widget ? 'widget' : ''" echarts [initOpts]="chartInitOptions" [options]="chartOptions"
|
<div *ngIf="observable$ | async" class="chart" [class]="widget ? 'widget' : ''" echarts [initOpts]="chartInitOptions" [options]="chartOptions"
|
||||||
(chartInit)="onChartInit($event)">
|
(chartInit)="onChartInit($event)" (chartFinished)="onChartFinished($event)">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,6 +21,17 @@
|
|||||||
height: 240px;
|
height: 240px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
.full-container.fit-container {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 100px;
|
||||||
|
|
||||||
|
.chart {
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.chart {
|
.chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, NgZone, OnDestroy, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Inject, Input, Output, EventEmitter, LOCALE_ID, NgZone, OnDestroy, OnInit, OnChanges } from '@angular/core';
|
||||||
import { SeoService } from 'src/app/services/seo.service';
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
import { ApiService } from 'src/app/services/api.service';
|
import { ApiService } from 'src/app/services/api.service';
|
||||||
import { Observable, tap, zip } from 'rxjs';
|
import { Observable, BehaviorSubject, switchMap, tap, combineLatest } from 'rxjs';
|
||||||
import { AssetsService } from 'src/app/services/assets.service';
|
import { AssetsService } from 'src/app/services/assets.service';
|
||||||
import { EChartsOption, registerMap } from 'echarts';
|
import { EChartsOption, registerMap } from 'echarts';
|
||||||
import { lerpColor } from 'src/app/shared/graphs.utils';
|
import { lerpColor } from 'src/app/shared/graphs.utils';
|
||||||
@ -17,11 +17,14 @@ import { getFlagEmoji } from 'src/app/shared/common.utils';
|
|||||||
styleUrls: ['./nodes-map.component.scss'],
|
styleUrls: ['./nodes-map.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class NodesMap implements OnInit {
|
export class NodesMap implements OnInit, OnChanges {
|
||||||
@Input() widget: boolean = false;
|
@Input() widget: boolean = false;
|
||||||
@Input() nodes: any[] | undefined = undefined;
|
@Input() nodes: any[] | undefined = undefined;
|
||||||
@Input() type: 'none' | 'isp' | 'country' = 'none';
|
@Input() type: 'none' | 'isp' | 'country' = 'none';
|
||||||
|
@Input() fitContainer = false;
|
||||||
|
@Output() readyEvent = new EventEmitter();
|
||||||
|
inputNodes$: BehaviorSubject<any>;
|
||||||
|
nodes$: Observable<any>;
|
||||||
observable$: Observable<any>;
|
observable$: Observable<any>;
|
||||||
|
|
||||||
chartInstance = undefined;
|
chartInstance = undefined;
|
||||||
@ -45,9 +48,17 @@ export class NodesMap implements OnInit {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.seoService.setTitle($localize`Lightning nodes world map`);
|
this.seoService.setTitle($localize`Lightning nodes world map`);
|
||||||
|
|
||||||
this.observable$ = zip(
|
if (!this.inputNodes$) {
|
||||||
|
this.inputNodes$ = new BehaviorSubject(this.nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.nodes$ = this.inputNodes$.pipe(
|
||||||
|
switchMap((nodes) => nodes ? [nodes] : this.apiService.getWorldNodes$())
|
||||||
|
);
|
||||||
|
|
||||||
|
this.observable$ = combineLatest(
|
||||||
this.assetsService.getWorldMapJson$,
|
this.assetsService.getWorldMapJson$,
|
||||||
this.nodes ? [this.nodes] : this.apiService.getWorldNodes$()
|
this.nodes$
|
||||||
).pipe(tap((data) => {
|
).pipe(tap((data) => {
|
||||||
registerMap('world', data[0]);
|
registerMap('world', data[0]);
|
||||||
|
|
||||||
@ -110,6 +121,16 @@ export class NodesMap implements OnInit {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes): void {
|
||||||
|
if (changes.nodes) {
|
||||||
|
if (!this.inputNodes$) {
|
||||||
|
this.inputNodes$ = new BehaviorSubject(changes.nodes.currentValue);
|
||||||
|
} else {
|
||||||
|
this.inputNodes$.next(changes.nodes.currentValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
prepareChartOptions(nodes, maxLiquidity, mapCenter, mapZoom) {
|
prepareChartOptions(nodes, maxLiquidity, mapCenter, mapZoom) {
|
||||||
let title: object;
|
let title: object;
|
||||||
if (nodes.length === 0) {
|
if (nodes.length === 0) {
|
||||||
@ -224,4 +245,8 @@ export class NodesMap implements OnInit {
|
|||||||
this.chartInstance.resize();
|
this.chartInstance.resize();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChartFinished(e) {
|
||||||
|
this.readyEvent.emit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
<div class="box preview-box" *ngIf="(nodes$ | async) as ispNodes">
|
||||||
|
<app-preview-title>
|
||||||
|
<span i18n="lightning.node">lightning ISP</span>
|
||||||
|
</app-preview-title>
|
||||||
|
<div class="row d-flex justify-content-between full-width-row">
|
||||||
|
<div class="title-wrapper">
|
||||||
|
<h1 class="title">{{ isp?.name }}</h1>
|
||||||
|
<a class="subtitle" [routerLink]="['/lightning/nodes/isp/' | relativeUrl, isp?.id]">
|
||||||
|
ASN {{ isp?.id }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="logo-wrapper">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md">
|
||||||
|
<table class="table table-borderless table-striped table-fixed">
|
||||||
|
<col span="1" width="250px">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td i18n="lightning.node-count">Nodes</td>
|
||||||
|
<td>{{ ispNodes.nodes.length }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td i18n="lightning.liquidity">Liquidity</td>
|
||||||
|
<td>
|
||||||
|
<app-amount *ngIf="ispNodes.sumLiquidity > 100000000; else smallnode" [satoshis]="ispNodes.sumLiquidity" [digitsInfo]="'1.2-2'" [noFiat]="false"></app-amount>
|
||||||
|
<ng-template #smallnode>
|
||||||
|
<app-sats [satoshis]="ispNodes.sumLiquidity" digitsInfo="1.0-2"></app-sats>
|
||||||
|
</ng-template>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td i18n="lightning.channels">Channels</td>
|
||||||
|
<td>{{ ispNodes.sumChannels }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td i18n="lightning.top-country">Top country</td>
|
||||||
|
<td class="text-truncate">
|
||||||
|
<span class="">{{ ispNodes.topCountry.country }} {{ ispNodes.topCountry.flag }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td i18n="lightning.top-node">Top node</td>
|
||||||
|
<td class="text-truncate">
|
||||||
|
{{ ispNodes.nodes[0].alias }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-md map-col">
|
||||||
|
<app-nodes-map [widget]="true" [nodes]="ispNodes.nodes" type="isp" [fitContainer]="true" (readyEvent)="onMapReady()"></app-nodes-map>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-template [ngIf]="error">
|
||||||
|
<div class="text-center">
|
||||||
|
<span i18n="error.general-loading-data">Error loading data.</span>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
@ -0,0 +1,31 @@
|
|||||||
|
.table {
|
||||||
|
font-size: 32px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-col {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 470px;
|
||||||
|
height: 360px;
|
||||||
|
min-width: 470px;
|
||||||
|
min-height: 360px;
|
||||||
|
max-height: 360px;
|
||||||
|
padding: 0;
|
||||||
|
background: #181b2d;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-width-row {
|
||||||
|
padding-left: 15px;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .symbol {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
|
import { catchError, map, switchMap, Observable, share, of } from 'rxjs';
|
||||||
|
import { ApiService } from 'src/app/services/api.service';
|
||||||
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
|
import { OpenGraphService } from 'src/app/services/opengraph.service';
|
||||||
|
import { getFlagEmoji } from 'src/app/shared/common.utils';
|
||||||
|
import { GeolocationData } from 'src/app/shared/components/geolocation/geolocation.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-nodes-per-isp-preview',
|
||||||
|
templateUrl: './nodes-per-isp-preview.component.html',
|
||||||
|
styleUrls: ['./nodes-per-isp-preview.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NodesPerISPPreview implements OnInit {
|
||||||
|
nodes$: Observable<any>;
|
||||||
|
isp: {name: string, id: number};
|
||||||
|
id: string;
|
||||||
|
error: Error;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private apiService: ApiService,
|
||||||
|
private seoService: SeoService,
|
||||||
|
private openGraphService: OpenGraphService,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.nodes$ = this.route.paramMap
|
||||||
|
.pipe(
|
||||||
|
switchMap((params: ParamMap) => {
|
||||||
|
this.id = params.get('isp');
|
||||||
|
this.isp = null;
|
||||||
|
this.openGraphService.waitFor('isp-map-' + this.id);
|
||||||
|
this.openGraphService.waitFor('isp-data-' + this.id);
|
||||||
|
return this.apiService.getNodeForISP$(params.get('isp'));
|
||||||
|
}),
|
||||||
|
map(response => {
|
||||||
|
this.isp = {
|
||||||
|
name: response.isp,
|
||||||
|
id: this.route.snapshot.params.isp.split(',').join(', ')
|
||||||
|
};
|
||||||
|
this.seoService.setTitle($localize`Lightning nodes on ISP: ${response.isp} [AS${this.route.snapshot.params.isp}]`);
|
||||||
|
|
||||||
|
for (const i in response.nodes) {
|
||||||
|
response.nodes[i].geolocation = <GeolocationData>{
|
||||||
|
country: response.nodes[i].country?.en,
|
||||||
|
city: response.nodes[i].city?.en,
|
||||||
|
subdivision: response.nodes[i].subdivision?.en,
|
||||||
|
iso: response.nodes[i].iso_code,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const sumLiquidity = response.nodes.reduce((partialSum, a) => partialSum + a.capacity, 0);
|
||||||
|
const sumChannels = response.nodes.reduce((partialSum, a) => partialSum + a.channels, 0);
|
||||||
|
const countries = {};
|
||||||
|
const topCountry = {
|
||||||
|
count: 0,
|
||||||
|
country: '',
|
||||||
|
iso: '',
|
||||||
|
flag: '',
|
||||||
|
};
|
||||||
|
for (const node of response.nodes) {
|
||||||
|
if (!node.geolocation.iso) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
countries[node.geolocation.iso] = countries[node.geolocation.iso] ?? 0 + 1;
|
||||||
|
if (countries[node.geolocation.iso] > topCountry.count) {
|
||||||
|
topCountry.count = countries[node.geolocation.iso];
|
||||||
|
topCountry.country = node.geolocation.country;
|
||||||
|
topCountry.iso = node.geolocation.iso;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
topCountry.flag = getFlagEmoji(topCountry.iso);
|
||||||
|
|
||||||
|
this.openGraphService.waitOver('isp-data-' + this.id);
|
||||||
|
|
||||||
|
return {
|
||||||
|
nodes: response.nodes,
|
||||||
|
sumLiquidity: sumLiquidity,
|
||||||
|
sumChannels: sumChannels,
|
||||||
|
topCountry: topCountry,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
catchError(err => {
|
||||||
|
this.error = err;
|
||||||
|
this.openGraphService.fail('isp-map-' + this.id);
|
||||||
|
this.openGraphService.fail('isp-data-' + this.id);
|
||||||
|
return of({
|
||||||
|
nodes: [],
|
||||||
|
sumLiquidity: 0,
|
||||||
|
sumChannels: 0,
|
||||||
|
topCountry: {},
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMapReady() {
|
||||||
|
this.openGraphService.waitOver('isp-map-' + this.id);
|
||||||
|
}
|
||||||
|
}
|
26
frontend/src/app/previews.module.ts
Normal file
26
frontend/src/app/previews.module.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { SharedModule } from './shared/shared.module';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { GraphsModule } from './graphs/graphs.module';
|
||||||
|
import { PreviewsRoutingModule } from './previews.routing.module';
|
||||||
|
import { TransactionPreviewComponent } from './components/transaction/transaction-preview.component';
|
||||||
|
import { BlockPreviewComponent } from './components/block/block-preview.component';
|
||||||
|
import { AddressPreviewComponent } from './components/address/address-preview.component';
|
||||||
|
import { MasterPagePreviewComponent } from './components/master-page-preview/master-page-preview.component';
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
TransactionPreviewComponent,
|
||||||
|
BlockPreviewComponent,
|
||||||
|
AddressPreviewComponent,
|
||||||
|
MasterPagePreviewComponent,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
SharedModule,
|
||||||
|
RouterModule,
|
||||||
|
GraphsModule,
|
||||||
|
PreviewsRoutingModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class PreviewsModule { }
|
39
frontend/src/app/previews.routing.module.ts
Normal file
39
frontend/src/app/previews.routing.module.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { TransactionPreviewComponent } from './components/transaction/transaction-preview.component';
|
||||||
|
import { BlockPreviewComponent } from './components/block/block-preview.component';
|
||||||
|
import { AddressPreviewComponent } from './components/address/address-preview.component';
|
||||||
|
import { MasterPagePreviewComponent } from './components/master-page-preview/master-page-preview.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: MasterPagePreviewComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'block/:id',
|
||||||
|
component: BlockPreviewComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'address/:id',
|
||||||
|
children: [],
|
||||||
|
component: AddressPreviewComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tx/:id',
|
||||||
|
children: [],
|
||||||
|
component: TransactionPreviewComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'lightning',
|
||||||
|
loadChildren: () => import('./lightning/lightning-previews.module').then(m => m.LightningPreviewsModule)
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class PreviewsRoutingModule { }
|
@ -7,7 +7,6 @@ import { faFilter, faAngleDown, faAngleUp, faAngleRight, faAngleLeft, faBolt, fa
|
|||||||
faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft } from '@fortawesome/free-solid-svg-icons';
|
faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
||||||
import { MasterPageComponent } from '../components/master-page/master-page.component';
|
import { MasterPageComponent } from '../components/master-page/master-page.component';
|
||||||
import { MasterPagePreviewComponent } from '../components/master-page-preview/master-page-preview.component';
|
|
||||||
import { PreviewTitleComponent } from '../components/master-page-preview/preview-title.component';
|
import { PreviewTitleComponent } from '../components/master-page-preview/preview-title.component';
|
||||||
import { BisqMasterPageComponent } from '../components/bisq-master-page/bisq-master-page.component';
|
import { BisqMasterPageComponent } from '../components/bisq-master-page/bisq-master-page.component';
|
||||||
import { LiquidMasterPageComponent } from '../components/liquid-master-page/liquid-master-page.component';
|
import { LiquidMasterPageComponent } from '../components/liquid-master-page/liquid-master-page.component';
|
||||||
@ -44,15 +43,12 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { CapAddressPipe } from './pipes/cap-address-pipe/cap-address-pipe';
|
import { CapAddressPipe } from './pipes/cap-address-pipe/cap-address-pipe';
|
||||||
import { StartComponent } from '../components/start/start.component';
|
import { StartComponent } from '../components/start/start.component';
|
||||||
import { TransactionComponent } from '../components/transaction/transaction.component';
|
import { TransactionComponent } from '../components/transaction/transaction.component';
|
||||||
import { TransactionPreviewComponent } from '../components/transaction/transaction-preview.component';
|
|
||||||
import { TransactionsListComponent } from '../components/transactions-list/transactions-list.component';
|
import { TransactionsListComponent } from '../components/transactions-list/transactions-list.component';
|
||||||
import { BlockComponent } from '../components/block/block.component';
|
import { BlockComponent } from '../components/block/block.component';
|
||||||
import { BlockPreviewComponent } from '../components/block/block-preview.component';
|
|
||||||
import { BlockAuditComponent } from '../components/block-audit/block-audit.component';
|
import { BlockAuditComponent } from '../components/block-audit/block-audit.component';
|
||||||
import { BlockOverviewGraphComponent } from '../components/block-overview-graph/block-overview-graph.component';
|
import { BlockOverviewGraphComponent } from '../components/block-overview-graph/block-overview-graph.component';
|
||||||
import { BlockOverviewTooltipComponent } from '../components/block-overview-tooltip/block-overview-tooltip.component';
|
import { BlockOverviewTooltipComponent } from '../components/block-overview-tooltip/block-overview-tooltip.component';
|
||||||
import { AddressComponent } from '../components/address/address.component';
|
import { AddressComponent } from '../components/address/address.component';
|
||||||
import { AddressPreviewComponent } from '../components/address/address-preview.component';
|
|
||||||
import { SearchFormComponent } from '../components/search-form/search-form.component';
|
import { SearchFormComponent } from '../components/search-form/search-form.component';
|
||||||
import { AddressLabelsComponent } from '../components/address-labels/address-labels.component';
|
import { AddressLabelsComponent } from '../components/address-labels/address-labels.component';
|
||||||
import { FooterComponent } from '../components/footer/footer.component';
|
import { FooterComponent } from '../components/footer/footer.component';
|
||||||
@ -117,21 +113,17 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati
|
|||||||
AmountComponent,
|
AmountComponent,
|
||||||
AboutComponent,
|
AboutComponent,
|
||||||
MasterPageComponent,
|
MasterPageComponent,
|
||||||
MasterPagePreviewComponent,
|
|
||||||
PreviewTitleComponent,
|
PreviewTitleComponent,
|
||||||
BisqMasterPageComponent,
|
BisqMasterPageComponent,
|
||||||
LiquidMasterPageComponent,
|
LiquidMasterPageComponent,
|
||||||
StartComponent,
|
StartComponent,
|
||||||
TransactionComponent,
|
TransactionComponent,
|
||||||
TransactionPreviewComponent,
|
|
||||||
BlockComponent,
|
BlockComponent,
|
||||||
BlockPreviewComponent,
|
|
||||||
BlockAuditComponent,
|
BlockAuditComponent,
|
||||||
BlockOverviewGraphComponent,
|
BlockOverviewGraphComponent,
|
||||||
BlockOverviewTooltipComponent,
|
BlockOverviewTooltipComponent,
|
||||||
TransactionsListComponent,
|
TransactionsListComponent,
|
||||||
AddressComponent,
|
AddressComponent,
|
||||||
AddressPreviewComponent,
|
|
||||||
SearchFormComponent,
|
SearchFormComponent,
|
||||||
TimeSpanComponent,
|
TimeSpanComponent,
|
||||||
AddressLabelsComponent,
|
AddressLabelsComponent,
|
||||||
@ -228,15 +220,12 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati
|
|||||||
AmountComponent,
|
AmountComponent,
|
||||||
StartComponent,
|
StartComponent,
|
||||||
TransactionComponent,
|
TransactionComponent,
|
||||||
TransactionPreviewComponent,
|
|
||||||
BlockComponent,
|
BlockComponent,
|
||||||
BlockPreviewComponent,
|
|
||||||
BlockAuditComponent,
|
BlockAuditComponent,
|
||||||
BlockOverviewGraphComponent,
|
BlockOverviewGraphComponent,
|
||||||
BlockOverviewTooltipComponent,
|
BlockOverviewTooltipComponent,
|
||||||
TransactionsListComponent,
|
TransactionsListComponent,
|
||||||
AddressComponent,
|
AddressComponent,
|
||||||
AddressPreviewComponent,
|
|
||||||
SearchFormComponent,
|
SearchFormComponent,
|
||||||
TimeSpanComponent,
|
TimeSpanComponent,
|
||||||
AddressLabelsComponent,
|
AddressLabelsComponent,
|
||||||
|
@ -46,6 +46,17 @@ const routes = {
|
|||||||
return `Lightning Channel: ${path[0]}`;
|
return `Lightning Channel: ${path[0]}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
nodes: {
|
||||||
|
routes: {
|
||||||
|
isp: {
|
||||||
|
render: true,
|
||||||
|
params: 1,
|
||||||
|
getTitle(path) {
|
||||||
|
return `Lightning ISP: ${path[0]}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mining: {
|
mining: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user