Merge branch 'Release-0.15.7' into update-dependencies-ng-20

This commit is contained in:
ShahanaFarooqui 2026-01-20 15:58:39 -08:00 committed by GitHub
commit 7c58b29bf4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 365 additions and 293 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
(()=>{"use strict";var e,v={},h={};function r(e){var f=h[e];if(void 0!==f)return f.exports;var t=h[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(f,t,i,o)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,o]=e[n],s=!0,l=0;l<t.length;l++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[l]))?t.splice(l--,1):(s=!1,o<a&&(a=o));if(s){e.splice(n--,1);var d=i();void 0!==d&&(f=d)}}return f}o=o||0;for(var n=e.length;n>0&&e[n-1][2]>o;n--)e[n]=e[n-1];e[n]=[t,i,o]},r.d=(e,f)=>{for(var t in f)r.o(f,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:f[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((f,t)=>(r.f[t](e,f),f),[])),r.u=e=>e+"."+{17:"4868b6e9f86af798",190:"be59cf44a64b6608",193:"02829b19c0b4f117",853:"cb0323674657e3d0"}[e]+".js",r.miniCssF=e=>{},r.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),(()=>{var e={},f="RTLApp:";r.l=(t,i,o,n)=>{if(e[t])e[t].push(i);else{var a,s;if(void 0!==o)for(var l=document.getElementsByTagName("script"),d=0;d<l.length;d++){var u=l[d];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==f+o){a=u;break}}a||(s=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",f+o),a.src=r.tu(t)),e[t]=[i];var c=(m,b)=>{a.onerror=a.onload=null,clearTimeout(p);var g=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),g&&g.forEach(_=>_(b)),m)return m(b)},p=setTimeout(c.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=c.bind(null,a.onerror),a.onload=c.bind(null,a.onload),s&&document.head.appendChild(a)}}})(),r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:f=>f},typeof trustedTypes<"u"&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={121:0};r.f.j=(i,o)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)o.push(n[2]);else if(121!=i){var a=new Promise((u,c)=>n=e[i]=[u,c]);o.push(n[2]=a);var s=r.p+r.u(i),l=new Error;r.l(s,u=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var c=u&&("load"===u.type?"missing":u.type),p=u&&u.target&&u.target.src;l.message="Loading chunk "+i+" failed.\n("+c+": "+p+")",l.name="ChunkLoadError",l.type=c,l.request=p,n[1](l)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var f=(i,o)=>{var l,d,[n,a,s]=o,u=0;if(n.some(p=>0!==e[p])){for(l in a)r.o(a,l)&&(r.m[l]=a[l]);if(s)var c=s(r)}for(i&&i(o);u<n.length;u++)r.o(e,d=n[u])&&e[d]&&e[d][0](),e[d]=0;return r.O(c)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(f.bind(null,0)),t.push=f.bind(null,t.push.bind(t))})()})();

View file

@ -1 +0,0 @@
(()=>{"use strict";var e,b={},h={};function r(e){var f=h[e];if(void 0!==f)return f.exports;var t=h[e]={id:e,loaded:!1,exports:{}};return b[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=b,e=[],r.O=(f,t,i,d)=>{if(!t){var a=1/0;for(n=0;n<e.length;n++){for(var[t,i,d]=e[n],s=!0,o=0;o<t.length;o++)(!1&d||a>=d)&&Object.keys(r.O).every(v=>r.O[v](t[o]))?t.splice(o--,1):(s=!1,d<a&&(a=d));if(s){e.splice(n--,1);var u=i();void 0!==u&&(f=u)}}return f}d=d||0;for(var n=e.length;n>0&&e[n-1][2]>d;n--)e[n]=e[n-1];e[n]=[t,i,d]},r.d=(e,f)=>{for(var t in f)r.o(f,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:f[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((f,t)=>(r.f[t](e,f),f),[])),r.u=e=>e+"."+{17:"cf363ae902a2592a",190:"2688f6008e3db861",193:"02829b19c0b4f117",853:"a31a2eedddece6bd"}[e]+".js",r.miniCssF=e=>{},r.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),(()=>{var e={},f="RTLApp:";r.l=(t,i,d,n)=>{if(e[t])e[t].push(i);else{var a,s;if(void 0!==d)for(var o=document.getElementsByTagName("script"),u=0;u<o.length;u++){var l=o[u];if(l.getAttribute("src")==t||l.getAttribute("data-webpack")==f+d){a=l;break}}a||(s=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",f+d),a.src=r.tu(t)),e[t]=[i];var c=(m,v)=>{a.onerror=a.onload=null,clearTimeout(p);var g=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),g&&g.forEach(_=>_(v)),m)return m(v)},p=setTimeout(c.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=c.bind(null,a.onerror),a.onload=c.bind(null,a.onload),s&&document.head.appendChild(a)}}})(),r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:f=>f},typeof trustedTypes<"u"&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={121:0};r.f.j=(i,d)=>{var n=r.o(e,i)?e[i]:void 0;if(0!==n)if(n)d.push(n[2]);else if(121!=i){var a=new Promise((l,c)=>n=e[i]=[l,c]);d.push(n[2]=a);var s=r.p+r.u(i),o=new Error;r.l(s,l=>{if(r.o(e,i)&&(0!==(n=e[i])&&(e[i]=void 0),n)){var c=l&&("load"===l.type?"missing":l.type),p=l&&l.target&&l.target.src;o.message="Loading chunk "+i+" failed.\n("+c+": "+p+")",o.name="ChunkLoadError",o.type=c,o.request=p,n[1](o)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var f=(i,d)=>{var o,u,[n,a,s]=d,l=0;if(n.some(p=>0!==e[p])){for(o in a)r.o(a,o)&&(r.m[o]=a[o]);if(s)var c=s(r)}for(i&&i(d);l<n.length;l++)r.o(e,u=n[l])&&e[u]&&e[u][0](),e[u]=0;return r.O(c)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(f.bind(null,0)),t.push=f.bind(null,t.push.bind(t))})()})();

View file

@ -1,4 +1,4 @@
import { Component, OnInit, AfterViewInit, OnDestroy, ViewChild, Renderer2 } from '@angular/core';
import { Component, OnInit, AfterViewInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout';
import { Subject } from 'rxjs';
@ -45,8 +45,15 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(
private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private actions: Actions,
private userIdle: UserIdleService, private router: Router, private sessionService: SessionService, private breakpointObserver: BreakpointObserver, private renderer: Renderer2
private logger: LoggerService,
private commonService: CommonService,
private store: Store<RTLState>,
private actions: Actions,
private userIdle: UserIdleService,
private router: Router,
private sessionService: SessionService,
private breakpointObserver: BreakpointObserver,
private cdr: ChangeDetectorRef
) { }
ngOnInit() {
@ -87,12 +94,17 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
this.userIdle.startWatching();
}
this.selNode = selNode;
this.cdr.detectChanges();
});
this.store.select(rootAppConfig).pipe(takeUntil(this.unSubs[2])).subscribe((appConfig) => {
this.appConfig = appConfig;
this.cdr.detectChanges();
});
this.store.select(rootAppConfig).pipe(takeUntil(this.unSubs[2])).subscribe((appConfig) => { this.appConfig = appConfig; });
this.store.select(rootNodeData).pipe(takeUntil(this.unSubs[3])).subscribe((nodeData) => {
this.information = nodeData;
this.flgLoading[0] = !(this.information.identity_pubkey);
this.logger.info(this.information);
this.cdr.detectChanges();
});
if (this.sessionService.getItem('defaultPassword') === 'true') {
this.flgSideNavOpened = false;
@ -118,6 +130,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
this.flgLoggedIn = true;
this.userIdle.startWatching();
this.userIdle.resetTimer();
this.cdr.detectChanges();
setTimeout(() => {
this.commonService.setContainerSize(this.sideNavContent.elementRef.nativeElement.clientWidth, this.sideNavContent.elementRef.nativeElement.clientHeight);
}, 1000);
@ -126,6 +139,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
this.flgLoggedIn = false;
this.userIdle.stopWatching();
this.userIdle.stopTimer();
this.cdr.detectChanges();
}
});
this.userIdle.onTimerStart().pipe(takeUntil(this.unSubs[5])).subscribe((count) => {

View file

@ -1,7 +1,7 @@
<div *ngIf="selNode?.settings.userPersona === userPersonaEnum.OPERATOR; else merchantDashboard"fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start start" class="page-title-container mb-2">
<fa-icon class="page-title-img mr-1" [icon]="apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR ? faFrown : faSmile" />
<span class="page-title">{{apiCallStatusNodeInfo.status === apiCallStatusEnum.COMPLETED ? 'Welcome ' + information.alias + '! Your node is up and running.' : apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED ? 'Wait! Getting your node information...' : 'Error! Please check the server connection.'}}</span>
<fa-icon class="page-title-img mr-1" [icon]="(apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR ? faFrown : faSmile" />
<span class="page-title">{{(apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.COMPLETED ? 'Welcome ' + information.alias + '! Your node is up and running.' : (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED ? 'Wait! Getting your node information...' : 'Error! Please check the server connection.'}}</span>
</div>
<mat-grid-list cols="10" gutterSize="20px" [rowHeight]="operatorCardHeight">
<mat-grid-tile *ngFor="let card of operatorCards" fxFlex="100" fxLayout="column" fxLayoutAlign="start stretch" [colspan]="card.cols" [rowspan]="card.rows">
@ -25,16 +25,16 @@
</mat-card-header>
<mat-card-content fxFlex="{{card.id === 'capacity' ? 90 : 70}}" fxLayout="column"
[ngClass]="{'dashboard-card-content': true,
'error-border': (card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && apiCallStatusBalances.status === apiCallStatusEnum.ERROR) ||
(card.id === 'capacity' && (apiCallStatusChannels.status === apiCallStatusEnum.ERROR || apiCallStatusBalances.status === apiCallStatusEnum.ERROR)) ||
(card.id === 'fee' && (apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR || apiCallStatusChannels.status === apiCallStatusEnum.ERROR || apiCallStatusFHistory.status === apiCallStatusEnum.ERROR)) ||
(card.id === 'status' && (apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR || apiCallStatusChannels.status === apiCallStatusEnum.ERROR || apiCallStatusBalances.status === apiCallStatusEnum.ERROR))}">
<mat-progress-bar *ngIf="(card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && apiCallStatusBalances.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'capacity' && (apiCallStatusChannels.status === apiCallStatusEnum.INITIATED || apiCallStatusBalances.status === apiCallStatusEnum.INITIATED)) ||
(card.id === 'fee' && (apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED || apiCallStatusChannels.status === apiCallStatusEnum.INITIATED || apiCallStatusFHistory.status === apiCallStatusEnum.INITIATED)) ||
(card.id === 'status' && (apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED || apiCallStatusChannels.status === apiCallStatusEnum.INITIATED || apiCallStatusBalances.status === apiCallStatusEnum.INITIATED))"
'error-border': (card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && (apiCallStatusBalances$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'capacity' && ((apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusBalances$ | async)?.status === apiCallStatusEnum.ERROR)) ||
(card.id === 'fee' && ((apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusFHistory$ | async)?.status === apiCallStatusEnum.ERROR)) ||
(card.id === 'status' && ((apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusBalances$ | async)?.status === apiCallStatusEnum.ERROR))}">
<mat-progress-bar *ngIf="(card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && (apiCallStatusBalances$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'capacity' && ((apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusBalances$ | async)?.status === apiCallStatusEnum.INITIATED)) ||
(card.id === 'fee' && ((apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusFHistory$ | async)?.status === apiCallStatusEnum.INITIATED)) ||
(card.id === 'status' && ((apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusBalances$ | async)?.status === apiCallStatusEnum.INITIATED))"
mode="indeterminate"
/>
<div fxLayout="column" fxFlex="100" [ngSwitch]="card.id">
@ -76,12 +76,12 @@
</mat-card-header>
<mat-card-content fxFlex="{{card.id === 'transactions' ? 100 : card.id === 'balance' ? 70: 90}}" fxLayout="column" fxLayoutAlign="start stretch"
[ngClass]="{'dashboard-card-content': true,
'error-border': (card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && apiCallStatusBalances.status === apiCallStatusEnum.ERROR) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && apiCallStatusChannels.status === apiCallStatusEnum.ERROR)}">
<mat-progress-bar *ngIf="(card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && apiCallStatusBalances.status === apiCallStatusEnum.INITIATED) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && apiCallStatusChannels.status === apiCallStatusEnum.INITIATED)"
'error-border': (card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && (apiCallStatusBalances$ | async)?.status === apiCallStatusEnum.ERROR) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.ERROR)}">
<mat-progress-bar *ngIf="(card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && (apiCallStatusBalances$ | async)?.status === apiCallStatusEnum.INITIATED) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.INITIATED)"
mode="indeterminate"
/>
<div fxLayout="column" fxFlex="100" [ngSwitch]="card.id">
@ -109,4 +109,4 @@
</mat-card>
</mat-grid-tile>
</mat-grid-list>
</ng-template>
</ng-template>

View file

@ -1,7 +1,7 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, withLatestFrom } from 'rxjs/operators';
import { Subject, Observable } from 'rxjs';
import { takeUntil, withLatestFrom, map, shareReplay } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { faSmile, faFrown } from '@fortawesome/free-regular-svg-icons';
import { faAngleDoubleDown, faAngleDoubleUp, faChartPie, faBolt, faServer, faNetworkWired } from '@fortawesome/free-solid-svg-icons';
@ -64,10 +64,10 @@ export class CLNHomeComponent implements OnInit, OnDestroy {
public merchantCardHeight = '62px';
public sortField = 'Balance Score';
public errorMessages = ['', '', '', ''];
public apiCallStatusNodeInfo: ApiCallStatusPayload | null = null;
public apiCallStatusBalances: ApiCallStatusPayload | null = null;
public apiCallStatusChannels: ApiCallStatusPayload | null = null;
public apiCallStatusFHistory: ApiCallStatusPayload | null = null;
public apiCallStatusNodeInfo$: Observable<ApiCallStatusPayload>;
public apiCallStatusBalances$: Observable<ApiCallStatusPayload>;
public apiCallStatusChannels$: Observable<ApiCallStatusPayload>;
public apiCallStatusFHistory$: Observable<ApiCallStatusPayload>;
public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
@ -119,67 +119,86 @@ export class CLNHomeComponent implements OnInit, OnDestroy {
}
ngOnInit() {
this.store.select(nodeInfoAndAPIsStatus).pipe(takeUntil(this.unSubs[0]),
withLatestFrom(this.store.select(rootSelectedNode))).
subscribe(([infoFeeStatusSelector, nodeSettings]: [{ information: GetInfo, fees: Fees, apisCallStatus: ApiCallStatusPayload[] }, Node | null]) => {
this.errorMessages[0] = '';
this.errorMessages[3] = '';
this.apiCallStatusNodeInfo = infoFeeStatusSelector.apisCallStatus[0];
this.apiCallStatusFHistory = infoFeeStatusSelector.apisCallStatus[1];
if (this.apiCallStatusNodeInfo.status === APICallStatusEnum.ERROR) {
this.errorMessages[0] = !this.apiCallStatusNodeInfo.message ? '' : (typeof (this.apiCallStatusNodeInfo.message) === 'object') ? JSON.stringify(this.apiCallStatusNodeInfo.message) : this.apiCallStatusNodeInfo.message;
}
if (this.apiCallStatusFHistory.status === APICallStatusEnum.ERROR) {
this.errorMessages[3] = !this.apiCallStatusFHistory.message ? '' : (typeof (this.apiCallStatusFHistory.message) === 'object') ? JSON.stringify(this.apiCallStatusFHistory.message) : this.apiCallStatusFHistory.message;
}
this.selNode = nodeSettings;
this.information = infoFeeStatusSelector.information;
this.fees = infoFeeStatusSelector.fees;
});
this.store.select(channels).pipe(takeUntil(this.unSubs[2])).
subscribe((channelsSeletor: { activeChannels: Channel[], pendingChannels: Channel[], inactiveChannels: Channel[], apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[2] = '';
this.apiCallStatusChannels = channelsSeletor.apiCallStatus;
if (this.apiCallStatusChannels.status === APICallStatusEnum.ERROR) {
this.errorMessages[2] = !this.apiCallStatusChannels.message ? '' : (typeof (this.apiCallStatusChannels.message) === 'object') ? JSON.stringify(this.apiCallStatusChannels.message) : this.apiCallStatusChannels.message;
}
this.totalInboundLiquidity = 0;
this.totalOutboundLiquidity = 0;
this.activeChannels = channelsSeletor.activeChannels;
this.activeChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels, 'balancedness'))) || [];
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels?.filter((channel) => (channel.to_them_msat ? channel.to_them_msat > 0 : false)), 'to_them_msat'))) || [];
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels?.filter((channel) => (channel.to_us_msat ? channel.to_us_msat > 0 : false)), 'to_us_msat'))) || [];
this.activeChannels.forEach((channel) => {
this.totalInboundLiquidity = this.totalInboundLiquidity + Math.ceil((channel.to_them_msat || 0) / 1000);
this.totalOutboundLiquidity = this.totalOutboundLiquidity + Math.floor((channel.to_us_msat || 0) / 1000);
});
this.channelsStatus.active.channels = channelsSeletor.activeChannels.length || 0;
this.channelsStatus.pending.channels = channelsSeletor.pendingChannels.length || 0;
this.channelsStatus.inactive.channels = channelsSeletor.inactiveChannels.length || 0;
this.logger.info(channelsSeletor);
});
this.store.select(utxoBalances).pipe(takeUntil(this.unSubs[3])).
subscribe((utxoBalancesSeletor: { utxos: UTXO[], balance: Balance, localRemoteBalance: LocalRemoteBalance, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[1] = '';
this.apiCallStatusBalances = utxoBalancesSeletor.apiCallStatus;
if (this.apiCallStatusBalances.status === APICallStatusEnum.ERROR) {
this.errorMessages[1] = !this.apiCallStatusBalances.message ? '' : (typeof (this.apiCallStatusBalances.message) === 'object') ? JSON.stringify(this.apiCallStatusBalances.message) : this.apiCallStatusBalances.message;
}
this.totalBalance = utxoBalancesSeletor.balance;
this.balances.onchain = utxoBalancesSeletor.balance.totalBalance || 0;
this.balances.lightning = utxoBalancesSeletor.localRemoteBalance.localBalance;
this.balances.total = this.balances.lightning + this.balances.onchain;
this.balances = Object.assign({}, this.balances);
const nodeInfoSelector$ = this.store.select(nodeInfoAndAPIsStatus).pipe(
takeUntil(this.unSubs[0]),
withLatestFrom(this.store.select(rootSelectedNode)),
shareReplay(1)
);
const local = (utxoBalancesSeletor.localRemoteBalance.localBalance) ? +utxoBalancesSeletor.localRemoteBalance.localBalance : 0;
const remote = (utxoBalancesSeletor.localRemoteBalance.remoteBalance) ? +utxoBalancesSeletor.localRemoteBalance.remoteBalance : 0;
const total = local + remote;
this.channelBalances = { localBalance: local, remoteBalance: remote, balancedness: +(1 - Math.abs((local - remote) / total)).toFixed(3) };
this.channelsStatus.active.capacity = utxoBalancesSeletor.localRemoteBalance.localBalance || 0;
this.channelsStatus.pending.capacity = utxoBalancesSeletor.localRemoteBalance.pendingBalance || 0;
this.channelsStatus.inactive.capacity = utxoBalancesSeletor.localRemoteBalance.inactiveBalance || 0;
this.logger.info(utxoBalancesSeletor);
nodeInfoSelector$.subscribe(([infoFeeStatusSelector, nodeSettings]: [{ information: GetInfo, fees: Fees, apisCallStatus: ApiCallStatusPayload[] }, Node | null]) => {
this.errorMessages[0] = '';
this.errorMessages[3] = '';
if (infoFeeStatusSelector.apisCallStatus[0].status === APICallStatusEnum.ERROR) {
this.errorMessages[0] = !infoFeeStatusSelector.apisCallStatus[0].message ? '' : (typeof (infoFeeStatusSelector.apisCallStatus[0].message) === 'object') ? JSON.stringify(infoFeeStatusSelector.apisCallStatus[0].message) : infoFeeStatusSelector.apisCallStatus[0].message;
}
if (infoFeeStatusSelector.apisCallStatus[1].status === APICallStatusEnum.ERROR) {
this.errorMessages[3] = !infoFeeStatusSelector.apisCallStatus[1].message ? '' : (typeof (infoFeeStatusSelector.apisCallStatus[1].message) === 'object') ? JSON.stringify(infoFeeStatusSelector.apisCallStatus[1].message) : infoFeeStatusSelector.apisCallStatus[1].message;
}
this.selNode = nodeSettings;
this.information = infoFeeStatusSelector.information;
this.fees = infoFeeStatusSelector.fees;
});
this.apiCallStatusNodeInfo$ = nodeInfoSelector$.pipe(
map(([infoFeeStatusSelector]) => infoFeeStatusSelector.apisCallStatus[0])
);
this.apiCallStatusFHistory$ = nodeInfoSelector$.pipe(
map(([infoFeeStatusSelector]) => infoFeeStatusSelector.apisCallStatus[1])
);
const channelsSelector$ = this.store.select(channels).pipe(
takeUntil(this.unSubs[2]),
shareReplay(1)
);
channelsSelector$.subscribe((channelsSeletor: { activeChannels: Channel[], pendingChannels: Channel[], inactiveChannels: Channel[], apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[2] = '';
if (channelsSeletor.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[2] = !channelsSeletor.apiCallStatus.message ? '' : (typeof (channelsSeletor.apiCallStatus.message) === 'object') ? JSON.stringify(channelsSeletor.apiCallStatus.message) : channelsSeletor.apiCallStatus.message;
}
this.totalInboundLiquidity = 0;
this.totalOutboundLiquidity = 0;
this.activeChannels = channelsSeletor.activeChannels;
this.activeChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels, 'balancedness'))) || [];
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels?.filter((channel) => (channel.to_them_msat ? channel.to_them_msat > 0 : false)), 'to_them_msat'))) || [];
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.activeChannels?.filter((channel) => (channel.to_us_msat ? channel.to_us_msat > 0 : false)), 'to_us_msat'))) || [];
this.activeChannels.forEach((channel) => {
this.totalInboundLiquidity = this.totalInboundLiquidity + Math.ceil((channel.to_them_msat || 0) / 1000);
this.totalOutboundLiquidity = this.totalOutboundLiquidity + Math.floor((channel.to_us_msat || 0) / 1000);
});
this.channelsStatus.active.channels = channelsSeletor.activeChannels.length || 0;
this.channelsStatus.pending.channels = channelsSeletor.pendingChannels.length || 0;
this.channelsStatus.inactive.channels = channelsSeletor.inactiveChannels.length || 0;
this.logger.info(channelsSeletor);
});
this.apiCallStatusChannels$ = channelsSelector$.pipe(map((cs) => cs.apiCallStatus));
const utxoBalancesSelector$ = this.store.select(utxoBalances).pipe(takeUntil(this.unSubs[3]), shareReplay(1));
utxoBalancesSelector$.subscribe((utxoBalancesSeletor: { utxos: UTXO[], balance: Balance, localRemoteBalance: LocalRemoteBalance, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[1] = '';
if (utxoBalancesSeletor.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[1] = !utxoBalancesSeletor.apiCallStatus.message ? '' : (typeof (utxoBalancesSeletor.apiCallStatus.message) === 'object') ? JSON.stringify(utxoBalancesSeletor.apiCallStatus.message) : utxoBalancesSeletor.apiCallStatus.message;
}
this.totalBalance = utxoBalancesSeletor.balance;
this.balances.onchain = utxoBalancesSeletor.balance.totalBalance || 0;
this.balances.lightning = utxoBalancesSeletor.localRemoteBalance.localBalance;
this.balances.total = this.balances.lightning + this.balances.onchain;
this.balances = Object.assign({}, this.balances);
const local = (utxoBalancesSeletor.localRemoteBalance.localBalance) ? +utxoBalancesSeletor.localRemoteBalance.localBalance : 0;
const remote = (utxoBalancesSeletor.localRemoteBalance.remoteBalance) ? +utxoBalancesSeletor.localRemoteBalance.remoteBalance : 0;
const total = local + remote;
this.channelBalances = { localBalance: local, remoteBalance: remote, balancedness: +(1 - Math.abs((local - remote) / total)).toFixed(3) };
this.channelsStatus.active.capacity = utxoBalancesSeletor.localRemoteBalance.localBalance || 0;
this.channelsStatus.pending.capacity = utxoBalancesSeletor.localRemoteBalance.pendingBalance || 0;
this.channelsStatus.inactive.capacity = utxoBalancesSeletor.localRemoteBalance.inactiveBalance || 0;
this.logger.info(utxoBalancesSeletor);
});
this.apiCallStatusBalances$ = utxoBalancesSelector$.pipe(map((ubs) => ubs.apiCallStatus));
}
onNavigateTo(link: string) {

View file

@ -1,7 +1,7 @@
<div *ngIf="selNode?.settings.userPersona === userPersonaEnum.OPERATOR; else merchantDashboard"fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start start" class="page-title-container mb-2">
<fa-icon class="page-title-img mr-1" [icon]="apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR ? faFrown : faSmile" />
<span class="page-title">{{apiCallStatusNodeInfo.status === apiCallStatusEnum.COMPLETED ? 'Welcome ' + information.alias + '! Your node is up and running.' : apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED ? 'Wait! Getting your node information...' : 'Error! Please check the server connection.'}}</span>
<fa-icon class="page-title-img mr-1" [icon]="(apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR ? faFrown : faSmile" />
<span class="page-title">{{(apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.COMPLETED ? 'Welcome ' + information.alias + '! Your node is up and running.' : (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED ? 'Wait! Getting your node information...' : 'Error! Please check the server connection.'}}</span>
</div>
<mat-grid-list cols="10" gutterSize="20px" [rowHeight]="operatorCardHeight">
<mat-grid-tile *ngFor="let card of operatorCards" fxFlex="100" fxLayout="column" fxLayoutAlign="start stretch" [colspan]="card.cols" [rowspan]="card.rows">
@ -27,14 +27,14 @@
</mat-card-header>
<mat-card-content fxFlex="{{card.id === 'capacity' ? 90 : 70}}" fxLayout="column"
[ngClass]="{'dashboard-card-content': true,
'error-border': (card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && (apiCallStatusAllChannels.status === apiCallStatusEnum.ERROR || apiCallStatusOCBal.status === apiCallStatusEnum.ERROR)) ||
((card.id === 'capacity' || card.id === 'status') && apiCallStatusAllChannels.status === apiCallStatusEnum.ERROR) ||
(card.id === 'fee' && apiCallStatusFees.status === apiCallStatusEnum.ERROR)}">
<mat-progress-bar *ngIf="(card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && (apiCallStatusAllChannels.status === apiCallStatusEnum.INITIATED || apiCallStatusOCBal.status === apiCallStatusEnum.INITIATED)) ||
((card.id === 'capacity' || card.id === 'status') && apiCallStatusAllChannels.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'fee' && apiCallStatusFees.status === apiCallStatusEnum.INITIATED)"
'error-border': (card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && ((apiCallStatusAllChannels$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusOCBal$ | async)?.status === apiCallStatusEnum.ERROR)) ||
((card.id === 'capacity' || card.id === 'status') && (apiCallStatusAllChannels$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'fee' && (apiCallStatusFees$ | async)?.status === apiCallStatusEnum.ERROR)}">
<mat-progress-bar *ngIf="(card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && ((apiCallStatusAllChannels$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusOCBal$ | async)?.status === apiCallStatusEnum.INITIATED)) ||
((card.id === 'capacity' || card.id === 'status') && (apiCallStatusAllChannels$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'fee' && (apiCallStatusFees$ | async)?.status === apiCallStatusEnum.INITIATED)"
mode="indeterminate"
/>
<div fxLayout="column" fxFlex="100" [ngSwitch]="card.id">
@ -77,12 +77,12 @@
</mat-card-header>
<mat-card-content fxFlex="{{card.id === 'transactions' ? 100 : card.id === 'balance' ? 70: 90}}" fxLayout="column" fxLayoutAlign="start stretch"
[ngClass]="{'dashboard-card-content': true,
'error-border': (card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && (apiCallStatusAllChannels.status === apiCallStatusEnum.ERROR || apiCallStatusOCBal.status === apiCallStatusEnum.ERROR)) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && apiCallStatusAllChannels.status === apiCallStatusEnum.ERROR)}">
<mat-progress-bar *ngIf="(card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && (apiCallStatusAllChannels.status === apiCallStatusEnum.INITIATED || apiCallStatusOCBal.status === apiCallStatusEnum.INITIATED)) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && apiCallStatusAllChannels.status === apiCallStatusEnum.INITIATED)"
'error-border': (card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && ((apiCallStatusAllChannels$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusOCBal$ | async)?.status === apiCallStatusEnum.ERROR)) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && (apiCallStatusAllChannels$ | async)?.status === apiCallStatusEnum.ERROR)}">
<mat-progress-bar *ngIf="(card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && ((apiCallStatusAllChannels$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusOCBal$ | async)?.status === apiCallStatusEnum.INITIATED)) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && (apiCallStatusAllChannels$ | async)?.status === apiCallStatusEnum.INITIATED)"
mode="indeterminate"
/>
<div fxLayout="column" fxFlex="100" [ngSwitch]="card.id">

View file

@ -1,7 +1,7 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, withLatestFrom } from 'rxjs/operators';
import { Subject, Observable } from 'rxjs';
import { takeUntil, withLatestFrom, map, shareReplay } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { faSmile, faFrown } from '@fortawesome/free-regular-svg-icons';
import { faAngleDoubleDown, faAngleDoubleUp, faChartPie, faBolt, faServer, faNetworkWired } from '@fortawesome/free-solid-svg-icons';
@ -64,10 +64,10 @@ export class ECLHomeComponent implements OnInit, OnDestroy {
public merchantCardHeight = '62px';
public sortField = 'Balance Score';
public errorMessages = ['', '', '', ''];
public apiCallStatusNodeInfo: ApiCallStatusPayload = { status: APICallStatusEnum.COMPLETED };
public apiCallStatusFees: ApiCallStatusPayload = { status: APICallStatusEnum.COMPLETED };
public apiCallStatusOCBal: ApiCallStatusPayload = { status: APICallStatusEnum.COMPLETED };
public apiCallStatusAllChannels: ApiCallStatusPayload = { status: APICallStatusEnum.COMPLETED };
public apiCallStatusNodeInfo$: Observable<ApiCallStatusPayload>;
public apiCallStatusFees$: Observable<ApiCallStatusPayload>;
public apiCallStatusOCBal$: Observable<ApiCallStatusPayload>;
public apiCallStatusAllChannels$: Observable<ApiCallStatusPayload>;
public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
@ -123,61 +123,83 @@ export class ECLHomeComponent implements OnInit, OnDestroy {
subscribe((nodeSettings) => {
this.selNode = nodeSettings;
});
this.store.select(nodeInfoStatus).pipe(takeUntil(this.unSubs[1])).
subscribe((selNodeInfoStatusSelector: { information: GetInfo, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[0] = '';
this.apiCallStatusNodeInfo = selNodeInfoStatusSelector.apiCallStatus;
if (this.apiCallStatusNodeInfo.status === APICallStatusEnum.ERROR) {
this.errorMessages[0] = (typeof (this.apiCallStatusNodeInfo.message) === 'object') ? JSON.stringify(this.apiCallStatusNodeInfo.message) : this.apiCallStatusNodeInfo.message ? this.apiCallStatusNodeInfo.message : '';
}
this.information = selNodeInfoStatusSelector.information;
});
this.store.select(fees).pipe(takeUntil(this.unSubs[2])).
subscribe((feesSelector: { fees: Fees, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[1] = '';
this.apiCallStatusFees = feesSelector.apiCallStatus;
if (this.apiCallStatusFees.status === APICallStatusEnum.ERROR) {
this.errorMessages[1] = (typeof (this.apiCallStatusFees.message) === 'object') ? JSON.stringify(this.apiCallStatusFees.message) : this.apiCallStatusFees.message ? this.apiCallStatusFees.message : '';
}
this.fees = feesSelector.fees;
});
this.store.select(allChannelsInfo).pipe(takeUntil(this.unSubs[3]),
withLatestFrom(this.store.select(onchainBalance))).
subscribe(([allChannelsSelector, oCBalanceSelector]: [({ activeChannels: Channel[], pendingChannels: Channel[], inactiveChannels: Channel[], lightningBalance: LightningBalance, channelsStatus: ChannelsStatus, apiCallStatus: ApiCallStatusPayload }),
const nodeInfoSelector$ = this.store.select(nodeInfoStatus).pipe(
takeUntil(this.unSubs[1]),
shareReplay(1)
);
nodeInfoSelector$.subscribe((selNodeInfoStatusSelector: { information: GetInfo, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[0] = '';
if (selNodeInfoStatusSelector.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[0] = (typeof (selNodeInfoStatusSelector.apiCallStatus.message) === 'object') ? JSON.stringify(selNodeInfoStatusSelector.apiCallStatus.message) : selNodeInfoStatusSelector.apiCallStatus.message ? selNodeInfoStatusSelector.apiCallStatus.message : '';
}
this.information = selNodeInfoStatusSelector.information;
});
this.apiCallStatusNodeInfo$ = nodeInfoSelector$.pipe(map((s) => s.apiCallStatus));
const feesSelector$ = this.store.select(fees).pipe(
takeUntil(this.unSubs[2]),
shareReplay(1)
);
feesSelector$.subscribe((feesSelector: { fees: Fees, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[1] = '';
if (feesSelector.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[1] = (typeof (feesSelector.apiCallStatus.message) === 'object') ? JSON.stringify(feesSelector.apiCallStatus.message) : feesSelector.apiCallStatus.message ? feesSelector.apiCallStatus.message : '';
}
this.fees = feesSelector.fees;
});
this.apiCallStatusFees$ = feesSelector$.pipe(map((fs) => fs.apiCallStatus));
const allChannelsSelector$ = this.store.select(allChannelsInfo).pipe(
takeUntil(this.unSubs[3]),
withLatestFrom(this.store.select(onchainBalance)),
shareReplay(1)
);
allChannelsSelector$.subscribe(([allChannelsSelector, oCBalanceSelector]: [({ activeChannels: Channel[], pendingChannels: Channel[], inactiveChannels: Channel[], lightningBalance: LightningBalance, channelsStatus: ChannelsStatus, apiCallStatus: ApiCallStatusPayload }),
({ onchainBalance: OnChainBalance, apiCallStatus: ApiCallStatusPayload })]) => {
this.errorMessages[2] = '';
this.errorMessages[3] = '';
this.apiCallStatusAllChannels = allChannelsSelector.apiCallStatus;
this.apiCallStatusOCBal = oCBalanceSelector.apiCallStatus;
if (this.apiCallStatusAllChannels.status === APICallStatusEnum.ERROR) {
this.errorMessages[2] = (typeof (this.apiCallStatusAllChannels.message) === 'object') ? JSON.stringify(this.apiCallStatusAllChannels.message) : this.apiCallStatusAllChannels.message ? this.apiCallStatusAllChannels.message : '';
}
if (this.apiCallStatusOCBal.status === APICallStatusEnum.ERROR) {
this.errorMessages[3] = (typeof (this.apiCallStatusOCBal.message) === 'object') ? JSON.stringify(this.apiCallStatusOCBal.message) : this.apiCallStatusOCBal.message ? this.apiCallStatusOCBal.message : '';
}
this.channels = allChannelsSelector.activeChannels;
this.onchainBalance = oCBalanceSelector.onchainBalance;
this.balances.onchain = this.onchainBalance.total || 0;
this.balances.lightning = allChannelsSelector.lightningBalance.localBalance;
this.balances.total = this.balances.lightning + this.balances.onchain;
this.balances = Object.assign({}, this.balances);
const local = (allChannelsSelector.lightningBalance.localBalance) ? +allChannelsSelector.lightningBalance.localBalance : 0;
const remote = (allChannelsSelector.lightningBalance.remoteBalance) ? +allChannelsSelector.lightningBalance.remoteBalance : 0;
const total = local + remote;
this.channelBalances = { localBalance: local, remoteBalance: remote, balancedness: +(1 - Math.abs((local - remote) / total)).toFixed(3) };
this.channelsStatus = allChannelsSelector.channelsStatus;
this.totalInboundLiquidity = 0;
this.totalOutboundLiquidity = 0;
this.allChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels, 'balancedness')));
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels?.filter((channel: Channel) => (channel.toRemote || 0) > 0), 'toRemote')));
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels?.filter((channel: Channel) => (channel.toLocal || 0) > 0), 'toLocal')));
this.channels.forEach((channel: Channel) => {
this.totalInboundLiquidity = this.totalInboundLiquidity + Math.ceil(channel.toRemote || 0);
this.totalOutboundLiquidity = this.totalOutboundLiquidity + Math.floor(channel.toLocal || 0);
});
this.logger.info(allChannelsSelector);
this.errorMessages[2] = '';
this.errorMessages[3] = '';
if (allChannelsSelector.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[2] = (typeof (allChannelsSelector.apiCallStatus.message) === 'object') ? JSON.stringify(allChannelsSelector.apiCallStatus.message) : allChannelsSelector.apiCallStatus.message ? allChannelsSelector.apiCallStatus.message : '';
}
if (oCBalanceSelector.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[3] = (typeof (oCBalanceSelector.apiCallStatus.message) === 'object') ? JSON.stringify(oCBalanceSelector.apiCallStatus.message) : oCBalanceSelector.apiCallStatus.message ? oCBalanceSelector.apiCallStatus.message : '';
}
this.channels = allChannelsSelector.activeChannels;
this.onchainBalance = oCBalanceSelector.onchainBalance;
this.balances.onchain = this.onchainBalance.total || 0;
this.balances.lightning = allChannelsSelector.lightningBalance.localBalance;
this.balances.total = this.balances.lightning + this.balances.onchain;
this.balances = Object.assign({}, this.balances);
const local = (allChannelsSelector.lightningBalance.localBalance) ? +allChannelsSelector.lightningBalance.localBalance : 0;
const remote = (allChannelsSelector.lightningBalance.remoteBalance) ? +allChannelsSelector.lightningBalance.remoteBalance : 0;
const total = local + remote;
this.channelBalances = { localBalance: local, remoteBalance: remote, balancedness: +(1 - Math.abs((local - remote) / total)).toFixed(3) };
this.channelsStatus = allChannelsSelector.channelsStatus;
this.totalInboundLiquidity = 0;
this.totalOutboundLiquidity = 0;
this.allChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels, 'balancedness')));
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels?.filter((channel: Channel) => (channel.toRemote || 0) > 0), 'toRemote')));
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.channels?.filter((channel: Channel) => (channel.toLocal || 0) > 0), 'toLocal')));
this.channels.forEach((channel: Channel) => {
this.totalInboundLiquidity = this.totalInboundLiquidity + Math.ceil(channel.toRemote || 0);
this.totalOutboundLiquidity = this.totalOutboundLiquidity + Math.floor(channel.toLocal || 0);
});
this.logger.info(allChannelsSelector);
});
this.apiCallStatusAllChannels$ = allChannelsSelector$.pipe(
map(([acs]) => acs.apiCallStatus)
);
this.apiCallStatusOCBal$ = allChannelsSelector$.pipe(
map(([, ocbs]) => ocbs.apiCallStatus)
);
}
onNavigateTo(link: string) {

View file

@ -1,7 +1,7 @@
<div *ngIf="selNode?.settings.userPersona === userPersonaEnum.OPERATOR; else merchantDashboard"fxLayout="column">
<div *ngIf="selNode?.settings.userPersona === userPersonaEnum.OPERATOR; else merchantDashboard" fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start start" class="page-title-container mb-2">
<fa-icon class="page-title-img mr-1" [icon]="apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR ? faFrown : faSmile" />
<span class="page-title">{{apiCallStatusNodeInfo.status === apiCallStatusEnum.COMPLETED ? 'Welcome ' + information.alias + '! Your node is up and running.' : apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED ? 'Wait! Getting your node information...' : 'Error! Please check the server connection.'}}</span>
<fa-icon class="page-title-img mr-1" [icon]="(apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR ? faFrown : faSmile" />
<span class="page-title">{{(apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.COMPLETED ? 'Welcome ' + information.alias + '! Your node is up and running.' : (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED ? 'Wait! Getting your node information...' : 'Error! Please check the server connection.'}}</span>
</div>
<mat-grid-list cols="10" gutterSize="20px" [rowHeight]="operatorCardHeight">
<mat-grid-tile *ngFor="let card of operatorCards" fxFlex="100" fxLayout="column" fxLayoutAlign="start stretch" [colspan]="card.cols" [rowspan]="card.rows">
@ -25,16 +25,16 @@
</mat-card-header>
<mat-card-content fxFlex="{{card.id === 'node' || card.id === 'balance' ? 70 : card.id === 'fee' || card.id === 'status' ? 78 : 90}}" fxLayout="column"
[ngClass]="{'dashboard-card-content': true,
'error-border': (card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && (apiCallStatusChannels.status === apiCallStatusEnum.ERROR || apiCallStatusBlockchainBalance.status === apiCallStatusEnum.ERROR)) ||
(card.id === 'capacity' && apiCallStatusChannels.status === apiCallStatusEnum.ERROR) ||
(card.id === 'fee' && apiCallStatusFees.status === apiCallStatusEnum.ERROR) ||
(card.id === 'status' && (apiCallStatusChannels.status === apiCallStatusEnum.ERROR || apiCallStatusPendingChannels.status === apiCallStatusEnum.ERROR))}">
<mat-progress-bar *ngIf="(card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && (apiCallStatusChannels.status === apiCallStatusEnum.INITIATED || apiCallStatusBlockchainBalance.status === apiCallStatusEnum.INITIATED)) ||
(card.id === 'capacity' && apiCallStatusChannels.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'fee' && apiCallStatusFees.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'status' && (apiCallStatusChannels.status === apiCallStatusEnum.INITIATED || apiCallStatusPendingChannels.status === apiCallStatusEnum.INITIATED))"
'error-border': (card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && ((apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusBlockchainBalance$ | async)?.status === apiCallStatusEnum.ERROR)) ||
(card.id === 'capacity' && (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'fee' && (apiCallStatusFees$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'status' && ((apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusPendingChannels$ | async)?.status === apiCallStatusEnum.ERROR))}">
<mat-progress-bar *ngIf="(card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && ((apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusBlockchainBalance$ | async)?.status === apiCallStatusEnum.INITIATED)) ||
(card.id === 'capacity' && (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'fee' && (apiCallStatusFees$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'status' && ((apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusPendingChannels$ | async)?.status === apiCallStatusEnum.INITIATED))"
mode="indeterminate"
/>
<div fxLayout="column" fxFlex="100" [ngSwitch]="card.id">
@ -76,12 +76,12 @@
</mat-card-header>
<mat-card-content fxFlex="{{card.id === 'transactions' ? 100 : card.id === 'balance' ? 70: 90}}" fxLayout="column" fxLayoutAlign="start stretch"
[ngClass]="{'dashboard-card-content': true,
'error-border': (card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && (apiCallStatusChannels.status === apiCallStatusEnum.ERROR || apiCallStatusBlockchainBalance.status === apiCallStatusEnum.ERROR)) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && apiCallStatusChannels.status === apiCallStatusEnum.ERROR)}">
<mat-progress-bar *ngIf="(card.id === 'node' && apiCallStatusNodeInfo.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && (apiCallStatusChannels.status === apiCallStatusEnum.INITIATED || apiCallStatusBlockchainBalance.status === apiCallStatusEnum.INITIATED)) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && apiCallStatusChannels.status === apiCallStatusEnum.INITIATED)"
'error-border': (card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.ERROR) ||
(card.id === 'balance' && ((apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.ERROR || (apiCallStatusBlockchainBalance$ | async)?.status === apiCallStatusEnum.ERROR)) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.ERROR)}">
<mat-progress-bar *ngIf="(card.id === 'node' && (apiCallStatusNodeInfo$ | async)?.status === apiCallStatusEnum.INITIATED) ||
(card.id === 'balance' && ((apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.INITIATED || (apiCallStatusBlockchainBalance$ | async)?.status === apiCallStatusEnum.INITIATED)) ||
((card.id === 'inboundLiq' || card.id === 'outboundLiq') && (apiCallStatusChannels$ | async)?.status === apiCallStatusEnum.INITIATED)"
mode="indeterminate"
/>
<div fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch" [ngSwitch]="card.id">
@ -109,4 +109,4 @@
</mat-card>
</mat-grid-tile>
</mat-grid-list>
</ng-template>
</ng-template>

View file

@ -1,7 +1,7 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, filter, withLatestFrom } from 'rxjs/operators';
import { Subject, Observable } from 'rxjs';
import { takeUntil, withLatestFrom, map, shareReplay } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { faSmile, faFrown } from '@fortawesome/free-regular-svg-icons';
@ -9,7 +9,7 @@ import { faAngleDoubleDown, faAngleDoubleUp, faChartPie, faBolt, faServer, faNet
import { LoggerService } from '../../shared/services/logger.service';
import { CommonService } from '../../shared/services/common.service';
import { UserPersonaEnum, ScreenSizeEnum, APICallStatusEnum, LNDActions } from '../../shared/services/consts-enums-functions';
import { UserPersonaEnum, ScreenSizeEnum, APICallStatusEnum } from '../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../shared/models/apiCallsPayload';
import { ChannelsStatus, GetInfo, Fees, Channel, BlockchainBalance, PendingChannels, PendingChannelsSummary, ChannelsSummary, LightningBalance } from '../../shared/models/lndModels';
import { Node } from '../../shared/models/RTLconfig';
@ -44,7 +44,6 @@ export class HomeComponent implements OnInit, OnDestroy {
public faBolt = faBolt;
public faServer = faServer;
public faNetworkWired = faNetworkWired;
public flgChildInfoUpdated = false;
public userPersonaEnum = UserPersonaEnum;
public activeChannels = 0;
public inactiveChannels = 0;
@ -68,11 +67,11 @@ export class HomeComponent implements OnInit, OnDestroy {
public sortField = 'Balance Score';
public screenSizeEnum = ScreenSizeEnum;
public errorMessages = ['', '', '', '', ''];
public apiCallStatusNodeInfo: ApiCallStatusPayload | null = null;
public apiCallStatusFees: ApiCallStatusPayload | null = null;
public apiCallStatusBlockchainBalance: ApiCallStatusPayload | null = null;
public apiCallStatusChannels: ApiCallStatusPayload | null = null;
public apiCallStatusPendingChannels: ApiCallStatusPayload | null = null;
public apiCallStatusNodeInfo$: Observable<ApiCallStatusPayload>;
public apiCallStatusFees$: Observable<ApiCallStatusPayload>;
public apiCallStatusBlockchainBalance$: Observable<ApiCallStatusPayload>;
public apiCallStatusChannels$: Observable<ApiCallStatusPayload>;
public apiCallStatusPendingChannels$: Observable<ApiCallStatusPayload>;
public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
@ -146,96 +145,102 @@ export class HomeComponent implements OnInit, OnDestroy {
}
ngOnInit() {
this.store.select(nodeInfoAndAPIStatus).pipe(takeUntil(this.unSubs[0]),
withLatestFrom(this.store.select(rootSelectedNode))).
subscribe(([infoStatusSelector, nodeSettings]: [{ information: GetInfo | null, apiCallStatus: ApiCallStatusPayload }, nodeSettings: Node]) => {
this.errorMessages[0] = '';
this.apiCallStatusNodeInfo = infoStatusSelector.apiCallStatus;
if (this.apiCallStatusNodeInfo.status === APICallStatusEnum.ERROR) {
this.errorMessages[0] = (typeof (this.apiCallStatusNodeInfo.message) === 'object') ? JSON.stringify(this.apiCallStatusNodeInfo.message) : this.apiCallStatusNodeInfo.message ? this.apiCallStatusNodeInfo.message : '';
}
this.selNode = nodeSettings;
this.information = infoStatusSelector.information;
});
this.store.select(fees).pipe(takeUntil(this.unSubs[1])).
subscribe((feesSelector: { fees: Fees, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[1] = '';
this.apiCallStatusFees = feesSelector.apiCallStatus;
if (this.apiCallStatusFees.status === APICallStatusEnum.ERROR) {
this.errorMessages[1] = (typeof (this.apiCallStatusFees.message) === 'object') ? JSON.stringify(this.apiCallStatusFees.message) : this.apiCallStatusFees.message ? this.apiCallStatusFees.message : '';
}
this.fees = feesSelector.fees;
});
this.store.select(blockchainBalance).pipe(takeUntil(this.unSubs[2])).
subscribe((bcBalanceSelector: { blockchainBalance: BlockchainBalance, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[2] = '';
this.apiCallStatusBlockchainBalance = bcBalanceSelector.apiCallStatus;
if (this.apiCallStatusBlockchainBalance.status === APICallStatusEnum.ERROR) {
this.errorMessages[2] = (typeof (this.apiCallStatusBlockchainBalance.message) === 'object') ? JSON.stringify(this.apiCallStatusBlockchainBalance.message) : this.apiCallStatusBlockchainBalance.message ? this.apiCallStatusBlockchainBalance.message : '';
}
this.balances.onchain = (bcBalanceSelector.blockchainBalance.total_balance && +bcBalanceSelector.blockchainBalance.total_balance >= 0) ? +bcBalanceSelector.blockchainBalance.total_balance : 0;
this.balances.total = this.balances.lightning + this.balances.onchain;
this.balances = Object.assign({}, this.balances);
});
this.store.select(pendingChannels).pipe(takeUntil(this.unSubs[3])).
subscribe((pendingChannelsSelector: { pendingChannels: PendingChannels, pendingChannelsSummary: PendingChannelsSummary, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[4] = '';
this.apiCallStatusPendingChannels = pendingChannelsSelector.apiCallStatus;
if (this.apiCallStatusPendingChannels.status === APICallStatusEnum.ERROR) {
this.errorMessages[4] = (typeof (this.apiCallStatusPendingChannels.message) === 'object') ? JSON.stringify(this.apiCallStatusPendingChannels.message) : this.apiCallStatusPendingChannels.message ? this.apiCallStatusPendingChannels.message : '';
}
this.channelsStatus.pending = { num_channels: pendingChannelsSelector.pendingChannelsSummary.open?.num_channels, capacity: pendingChannelsSelector.pendingChannelsSummary.open?.limbo_balance };
this.channelsStatus.closing = {
num_channels: (pendingChannelsSelector.pendingChannelsSummary.closing?.num_channels || 0) + (pendingChannelsSelector.pendingChannelsSummary.force_closing?.num_channels || 0) + (pendingChannelsSelector.pendingChannelsSummary.waiting_close?.num_channels || 0),
capacity: pendingChannelsSelector.pendingChannelsSummary.total_limbo_balance
};
});
this.store.select(channels).pipe(takeUntil(this.unSubs[4])).
subscribe((channelsSelector: { channels: Channel[], channelsSummary: ChannelsSummary, lightningBalance: LightningBalance, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[3] = '';
this.apiCallStatusChannels = channelsSelector.apiCallStatus;
if (this.apiCallStatusChannels.status === APICallStatusEnum.ERROR) {
this.errorMessages[3] = (typeof (this.apiCallStatusChannels.message) === 'object') ? JSON.stringify(this.apiCallStatusChannels.message) : this.apiCallStatusChannels.message ? this.apiCallStatusChannels.message : '';
}
const local = (channelsSelector.lightningBalance && channelsSelector.lightningBalance.local) ? +channelsSelector.lightningBalance.local : 0;
const remote = (channelsSelector.lightningBalance && channelsSelector.lightningBalance.remote) ? +channelsSelector.lightningBalance.remote : 0;
const total = local + remote;
this.channelBalances = { localBalance: local, remoteBalance: remote, balancedness: +(1 - Math.abs((local - remote) / total)).toFixed(3) };
this.balances.lightning = channelsSelector.lightningBalance.local || 0;
this.balances.total = this.balances.lightning + this.balances.onchain;
this.balances = Object.assign({}, this.balances);
this.activeChannels = channelsSelector.channelsSummary.active?.num_channels || 0;
this.inactiveChannels = channelsSelector.channelsSummary.inactive?.num_channels || 0;
this.channelsStatus.active = channelsSelector.channelsSummary.active;
this.channelsStatus.inactive = channelsSelector.channelsSummary.inactive;
this.totalInboundLiquidity = 0;
this.totalOutboundLiquidity = 0;
this.allChannels = channelsSelector.channels?.filter((channel) => channel.active === true);
this.allChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels, 'balancedness')));
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels?.filter((channel) => channel.remote_balance && channel.remote_balance > 0), 'remote_balance')));
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels?.filter((channel) => channel.local_balance && channel.local_balance > 0), 'local_balance')));
this.allChannels.forEach((channel) => {
this.totalInboundLiquidity = this.totalInboundLiquidity + +(channel.remote_balance || 0);
this.totalOutboundLiquidity = this.totalOutboundLiquidity + +(channel.local_balance || 0);
});
if (this.balances.lightning >= 0 && this.balances.onchain >= 0 && this.fees.month_fee_sum && this.fees.month_fee_sum >= 0) {
this.flgChildInfoUpdated = true;
} else {
this.flgChildInfoUpdated = false;
}
this.logger.info(channelsSelector);
});
this.actions.pipe(
takeUntil(this.unSubs[5]),
filter((action) => action.type === LNDActions.FETCH_FEES_LND || action.type === LNDActions.SET_FEES_LND)).
subscribe((action) => {
if (action.type === LNDActions.FETCH_FEES_LND) {
this.flgChildInfoUpdated = false;
}
if (action.type === LNDActions.SET_FEES_LND) {
this.flgChildInfoUpdated = true;
}
const nodeInfoSelector$ = this.store.select(nodeInfoAndAPIStatus).pipe(
takeUntil(this.unSubs[0]),
withLatestFrom(this.store.select(rootSelectedNode)),
shareReplay(1)
);
nodeInfoSelector$.subscribe(([infoStatusSelector, nodeSettings]: [{ information: GetInfo | null, apiCallStatus: ApiCallStatusPayload }, nodeSettings: Node]) => {
this.errorMessages[0] = '';
if (infoStatusSelector.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[0] = (typeof (infoStatusSelector.apiCallStatus.message) === 'object') ? JSON.stringify(infoStatusSelector.apiCallStatus.message) : infoStatusSelector.apiCallStatus.message ? infoStatusSelector.apiCallStatus.message : '';
}
this.selNode = nodeSettings;
this.information = infoStatusSelector.information;
});
this.apiCallStatusNodeInfo$ = nodeInfoSelector$.pipe(
map(([infoStatusSelector]) => infoStatusSelector.apiCallStatus)
);
const feesSelector$ = this.store.select(fees).pipe(
takeUntil(this.unSubs[1]),
shareReplay(1)
);
feesSelector$.subscribe((feesSelector: { fees: Fees; apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[1] = '';
if (feesSelector.apiCallStatus?.status === APICallStatusEnum.ERROR) {
this.errorMessages[1] = typeof feesSelector.apiCallStatus.message === 'object' ? JSON.stringify(feesSelector.apiCallStatus.message) : feesSelector.apiCallStatus.message || '';
}
this.fees = feesSelector.fees;
});
this.apiCallStatusFees$ = feesSelector$.pipe(map((fs) => fs.apiCallStatus));
const bcBalanceSelector$ = this.store.select(blockchainBalance).pipe(takeUntil(this.unSubs[2]), shareReplay(1));
bcBalanceSelector$.subscribe((bcBalanceSelector: { blockchainBalance: BlockchainBalance, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[2] = '';
if (bcBalanceSelector.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[2] = (typeof (bcBalanceSelector.apiCallStatus.message) === 'object') ? JSON.stringify(bcBalanceSelector.apiCallStatus.message) : bcBalanceSelector.apiCallStatus.message ? bcBalanceSelector.apiCallStatus.message : '';
}
this.balances.onchain = (bcBalanceSelector.blockchainBalance.total_balance && +bcBalanceSelector.blockchainBalance.total_balance >= 0) ? +bcBalanceSelector.blockchainBalance.total_balance : 0;
this.balances.total = this.balances.lightning + this.balances.onchain;
this.balances = Object.assign({}, this.balances);
});
this.apiCallStatusBlockchainBalance$ = bcBalanceSelector$.pipe(map((bcs) => bcs.apiCallStatus));
const pendingChannelsSelector$ = this.store.select(pendingChannels).pipe(takeUntil(this.unSubs[3]), shareReplay(1));
pendingChannelsSelector$.subscribe((pendingChannelsSelector: { pendingChannels: PendingChannels, pendingChannelsSummary: PendingChannelsSummary, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[4] = '';
if (pendingChannelsSelector.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[4] = (typeof (pendingChannelsSelector.apiCallStatus.message) === 'object') ? JSON.stringify(pendingChannelsSelector.apiCallStatus.message) : pendingChannelsSelector.apiCallStatus.message ? pendingChannelsSelector.apiCallStatus.message : '';
}
this.channelsStatus.pending = { num_channels: pendingChannelsSelector.pendingChannelsSummary.open?.num_channels, capacity: pendingChannelsSelector.pendingChannelsSummary.open?.limbo_balance };
this.channelsStatus.closing = {
num_channels: (pendingChannelsSelector.pendingChannelsSummary.closing?.num_channels || 0) + (pendingChannelsSelector.pendingChannelsSummary.force_closing?.num_channels || 0) + (pendingChannelsSelector.pendingChannelsSummary.waiting_close?.num_channels || 0),
capacity: pendingChannelsSelector.pendingChannelsSummary.total_limbo_balance
};
});
this.apiCallStatusPendingChannels$ = pendingChannelsSelector$.pipe(map((pcs) => pcs.apiCallStatus));
const channelsSelector$ = this.store.select(channels).pipe(takeUntil(this.unSubs[4]), shareReplay(1));
channelsSelector$.subscribe((channelsSelector: { channels: Channel[], channelsSummary: ChannelsSummary, lightningBalance: LightningBalance, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessages[3] = '';
if (channelsSelector.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessages[3] = (typeof (channelsSelector.apiCallStatus.message) === 'object') ? JSON.stringify(channelsSelector.apiCallStatus.message) : channelsSelector.apiCallStatus.message ? channelsSelector.apiCallStatus.message : '';
}
const local = (channelsSelector.lightningBalance && channelsSelector.lightningBalance.local) ? +channelsSelector.lightningBalance.local : 0;
const remote = (channelsSelector.lightningBalance && channelsSelector.lightningBalance.remote) ? +channelsSelector.lightningBalance.remote : 0;
const total = local + remote;
this.channelBalances = { localBalance: local, remoteBalance: remote, balancedness: +(1 - Math.abs((local - remote) / total)).toFixed(3) };
this.balances.lightning = channelsSelector.lightningBalance.local || 0;
this.balances.total = this.balances.lightning + this.balances.onchain;
this.balances = Object.assign({}, this.balances);
this.activeChannels = channelsSelector.channelsSummary.active?.num_channels || 0;
this.inactiveChannels = channelsSelector.channelsSummary.inactive?.num_channels || 0;
this.channelsStatus.active = channelsSelector.channelsSummary.active;
this.channelsStatus.inactive = channelsSelector.channelsSummary.inactive;
this.totalInboundLiquidity = 0;
this.totalOutboundLiquidity = 0;
this.allChannels = channelsSelector.channels?.filter((channel) => channel.active === true);
this.allChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels, 'balancedness')));
this.allInboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels?.filter((channel) => channel.remote_balance && channel.remote_balance > 0), 'remote_balance')));
this.allOutboundChannels = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels?.filter((channel) => channel.local_balance && channel.local_balance > 0), 'local_balance')));
this.allChannels.forEach((channel) => {
this.totalInboundLiquidity = this.totalInboundLiquidity + +(channel.remote_balance || 0);
this.totalOutboundLiquidity = this.totalOutboundLiquidity + +(channel.local_balance || 0);
});
this.logger.info(channelsSelector);
});
this.apiCallStatusChannels$ = channelsSelector$.pipe(map((cs) => cs.apiCallStatus));
}
onNavigateTo(link: string) {

View file

@ -1,6 +1,6 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="space-between start" [perfectScrollbar]>
<div fxLayout="column" fxFlex="90" fxLayoutAlign="start stretch" class="w-100">
<mat-select *ngIf="appConfig.nodes.length > 1" class="m-2 multi-node-select" [value]="selConfigNodeIndex" (selectionChange)="onNodeSelectionChange($event.value)">
<mat-select *ngIf="appConfig?.nodes?.length > 1" class="m-2 multi-node-select" [value]="selConfigNodeIndex" (selectionChange)="onNodeSelectionChange($event.value)">
<perfect-scrollbar>
<mat-option *ngFor="let node of appConfig.nodes" tabindex="1" [value]="node.index">
{{node.lnNode}} ({{node.lnImplementation}})
@ -66,4 +66,4 @@
</g>
</g>
</svg>
</ng-template>
</ng-template>

View file

@ -1,4 +1,4 @@
import { Component, OnInit, OnDestroy, Output, EventEmitter, ViewChild } from '@angular/core';
import { Component, OnInit, OnDestroy, Output, EventEmitter, ViewChild, ChangeDetectorRef } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -17,7 +17,6 @@ import { MenuChildNode, MENU_DATA } from '../../../models/navMenu';
import { RTLEffects } from '../../../../store/rtl.effects';
import { RTLState } from '../../../../store/rtl.state';
import { VERSION, AlertTypeEnum, RTLActions, UI_MESSAGES, UserPersonaEnum } from '../../../services/consts-enums-functions';
import { CommonService } from '../../../services/common.service';
import { logout, openConfirmation, setSelectedNode, showPubkey } from '../../../../store/rtl.actions';
import { rootAppConfig, rootSelNodeAndNodeData } from '../../../../store/rtl.selector';
@ -35,7 +34,7 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
faEye = faEye;
public appConfig: RTLConfiguration;
public selConfigNodeIndex: Number;
public selNode: Node | any;
public selNode: Node | any = null;
public version = '';
public information: GetInfoRoot = {};
public informationChain: GetInfoChain = {};
@ -55,7 +54,14 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
navMenusLogout = new MatTreeNestedDataSource<MenuChildNode>();
navMenusShowData = new MatTreeNestedDataSource<MenuChildNode>();
constructor(private logger: LoggerService, private commonService: CommonService, private sessionService: SessionService, private store: Store<RTLState>, private actions: Actions, private rtlEffects: RTLEffects) {
constructor(
private logger: LoggerService,
private sessionService: SessionService,
private store: Store<RTLState>,
private actions: Actions,
private rtlEffects: RTLEffects,
private cdr: ChangeDetectorRef
) {
this.version = VERSION;
if (MENU_DATA.LNDChildren && MENU_DATA.LNDChildren[MENU_DATA.LNDChildren.length - 1].id === 200) {
MENU_DATA.LNDChildren.pop();
@ -71,6 +77,7 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
this.flgLoading = !!token;
this.store.select(rootAppConfig).pipe(takeUntil(this.unSubs[0])).subscribe((appConfig) => {
this.appConfig = appConfig;
this.cdr.detectChanges();
});
this.store.select(rootSelNodeAndNodeData).pipe(takeUntil(this.unSubs[1])).
subscribe((rootData: { nodeDate: GetInfoRoot, selNode: Node | null }) => {
@ -98,18 +105,21 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
this.filterSideMenuNodes();
}
this.logger.info(rootData);
this.cdr.detectChanges();
});
this.sessionService.watchSession().
pipe(takeUntil(this.unSubs[2])).
subscribe((session) => {
this.showLogout = !!session.token;
this.flgLoading = !!session.token;
this.cdr.detectChanges();
});
this.actions.pipe(
takeUntil(this.unSubs[3]),
filter((action) => action.type === RTLActions.LOGOUT)).
subscribe((action: any) => {
this.showLogout = false;
this.cdr.detectChanges();
});
}
@ -160,9 +170,11 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
const clonedMenu = JSON.parse(JSON.stringify(MENU_DATA.LNDChildren));
this.navMenus.data = clonedMenu?.filter((navMenuData: any) => {
if (navMenuData.children && navMenuData.children.length) {
navMenuData.children = navMenuData.children?.filter((navMenuChild) => ((navMenuChild.userPersona === UserPersonaEnum.ALL || navMenuChild.userPersona === this.selNode.settings.userPersona) && navMenuChild.link !== '/services/loop' && navMenuChild.link !== '/services/boltz') ||
navMenuData.children = navMenuData.children?.filter((navMenuChild) => ((navMenuChild.userPersona === UserPersonaEnum.ALL || navMenuChild.userPersona === this.selNode.settings.userPersona)) &&
(!navMenuChild.link.includes('/services') ||
(navMenuChild.link === '/services/loop' && this.selNode.settings.swapServerUrl && this.selNode.settings.swapServerUrl.trim() !== '') ||
(navMenuChild.link === '/services/boltz' && this.selNode.settings.boltzServerUrl && this.selNode.settings.boltzServerUrl.trim() !== ''));
(navMenuChild.link === '/services/boltz' && this.selNode.settings.boltzServerUrl && this.selNode.settings.boltzServerUrl.trim() !== '')
));
return navMenuData.children.length > 0;
}
return navMenuData.userPersona === UserPersonaEnum.ALL || navMenuData.userPersona === this.selNode.settings.userPersona;