Network Information

Network Information
This commit is contained in:
Shahana Farooqui 2019-12-11 19:58:20 -05:00
parent 79d04a5d7a
commit 98f874cd07
26 changed files with 203 additions and 38 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -9,8 +9,8 @@
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicon/favicon-16x16.png">
<link rel="manifest" href="assets/images/favicon/site.webmanifest">
<link rel="stylesheet" href="styles.3b647f02f87dbde63ee9.css"></head>
<link rel="stylesheet" href="styles.8a1ddaedb5da1018195e.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.af78130362f8d52a18b0.js"></script><script src="polyfills-es5.2e75d230d7f9c760eb2f.js" nomodule></script><script src="polyfills.1ebb102854b0ec478c1b.js"></script><script src="main.1a920fe27b5e532dac46.js"></script></body>
<script src="runtime.8de0300ea7cbcf176757.js"></script><script src="polyfills-es5.2e75d230d7f9c760eb2f.js" nomodule></script><script src="polyfills.1ebb102854b0ec478c1b.js"></script><script src="main.54108a6aab5d60775c5e.js"></script></body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
!function(e){function r(r){for(var n,a,i=r[0],c=r[1],f=r[2],p=0,s=[];p<i.length;p++)o[a=i[p]]&&s.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"9e71a210a8bdc5ba9df9",6:"af311c76cbdf1165a591",7:"f304a8c9801c62bf8967"}[e]+".js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var l=c;t()}([]);
!function(e){function r(r){for(var n,a,i=r[0],c=r[1],f=r[2],p=0,s=[];p<i.length;p++)o[a=i[p]]&&s.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"9e71a210a8bdc5ba9df9",6:"9f448ec4afdcbbc42cf2",7:"f304a8c9801c62bf8967"}[e]+".js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var l=c;t()}([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -26,6 +26,9 @@ common.getOptions = () => {
};
common.updateSelectedNodeOptions = () => {
if (!common.selectedNode) {
common.selectedNode = {};
}
common.selectedNode.options = {
url: '',
rejectUnauthorized: false,

View file

@ -6,7 +6,7 @@ var common = require('../common');
exports.updateSelectedNode = (req, res, next) => {
const selNodeIndex = req.body.selNodeIndex;
common.selectedNode = common.findNode(selNodeIndex);
const responseVal = common.selectedNode.ln_node ? common.selectedNode.ln_node : common.selectedNode.ln_server_url;
const responseVal = !common.selectedNode ? '' : (common.selectedNode.ln_node ? common.selectedNode.ln_node : common.selectedNode.ln_server_url);
logger.info({fileName: 'RTLConf', msg: 'Selected Node Updated To: ' + JSON.stringify(responseVal)});
res.status(200).json({status: 'Selected Node Updated To: ' + JSON.stringify(responseVal) + '!'});
};

View file

@ -6,7 +6,7 @@ exports.info = (msgJSON, selNode = common.selectedNode) => {
if (msgJSON.fileName !== 'Config Setup Variable') {
console.log('Console: ' + msgStr);
}
if(selNode.enable_logging) {
if(selNode && selNode.enable_logging) {
fs.appendFile(selNode.log_file, msgStr, function(err) {
if (err) {
return ({ error: 'Updating Log Failed!' });
@ -20,7 +20,7 @@ exports.info = (msgJSON, selNode = common.selectedNode) => {
exports.error = (msgJSON, selNode = common.selectedNode) => {
const msgStr = '\r\nERROR: ' + msgJSON.fileName + '(' + msgJSON.lineNum + ') => ' + msgJSON.msg;
console.error('Console: ' + msgStr);
if(selNode.enable_logging) {
if(selNode && selNode.enable_logging) {
fs.appendFile(selNode.log_file, msgStr, function(err) {
if (err) {
return ({ error: 'Updating Log Failed!' });

View file

@ -1,5 +1,6 @@
.mat-progress-bar.dashboard-progress-bar {
height: 6px;
min-height: 6px;
}
.dashboard-divider {

View file

@ -1,5 +1,5 @@
<div fxLayout="column" fxLayoutAlign="space-between start" fxFlex="100">
<div fxLayout="column" fxFlex="8" fxLayoutAlign="end start" class="w-100">
<div fxLayout="column" fxFlex="9" fxLayoutAlign="end start" class="w-100">
<h2>{{totalLiquidity | number}} Sats</h2>
<h4>Max Transaction Amount: {{(maxAmount <= 4200000 ? maxAmount : 4200000) | number}} Sats</h4>
<mat-divider class="w-100 dashboard-divider mt-2"></mat-divider>

View file

@ -1,7 +1,7 @@
<div fxLayout="column" *ngIf="selNode.userPersona === userPersonaEnum.OPERATOR; else merchantDashboard">
<div fxLayout="row" fxLayoutAlign="start end" class="padding-gap-x page-title-container mb-0">
<fa-icon [icon]="faSmile" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Welcome! Your node is up and running.</span>
<fa-icon [icon]="!flgLoading[0] ? faSmile : faFrown" class="page-title-img mr-1"></fa-icon>
<span class="page-title">{{!flgLoading[0] ? 'Welcome! Your node is up and running.' : 'Error! Please check the server connection.'}}</span>
</div>
<mat-grid-list cols="10" rowHeight="330px">
<mat-grid-tile *ngFor="let card of operatorCards | async" [colspan]="card.cols" [rowspan]="card.rows">
@ -30,12 +30,13 @@
<fa-icon [icon]="faSmile" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Welcome! Your node is up and running.</span>
</div>
<mat-grid-list cols="3" rowHeight="220px">
<mat-grid-list cols="3" rowHeight="66px">
<mat-grid-tile *ngFor="let card of merchantCards | async" [colspan]="card.cols" [rowspan]="card.rows">
<mat-card fxLayout="column" fxLayoutAlign="start start" class="dashboard-card" [ngClass]="{'p-16': card.id !== 'transactions'}">
<mat-card-header *ngIf="card.id !== 'transactions'"><mat-card-title>{{card.title}}</mat-card-title></mat-card-header>
<mat-card-content class="dashboard-card-content w-100" fxFlex="{{card.id !== 'transactions' ? 95 : 100}}">
<div [ngSwitch]="card.id" fxLayout="column" fxFlex="100">
<rtl-node-info fxFlex="100" *ngSwitchCase="'node'" [information]="information" [ngClass]="{'error-border': flgLoading[0]==='error'}"></rtl-node-info>
<rtl-balances-info fxFlex="100" *ngSwitchCase="'balance'" [flgInfoUpdate]="flgChildInfoUpdated" [balances]="balances" [ngClass]="{'error-border': flgLoading[2]==='error' || flgLoading[5]==='error'}"></rtl-balances-info>
<rtl-channel-liquidity-info fxFlex="100" *ngSwitchCase="'inboundLiq'" [direction]="'In'" [totalLiquidity]="totalInboundLiquidity" [allChannels]="allInboundChannels" [ngClass]="{'error-border': flgLoading[5]==='error'}"></rtl-channel-liquidity-info>
<rtl-channel-liquidity-info fxFlex="100" *ngSwitchCase="'outboundLiq'" [direction]="'Out'" [totalLiquidity]="totalOutboundLiquidity" [allChannels]="allOutboundChannels" [ngClass]="{'error-border': flgLoading[5]==='error'}"></rtl-channel-liquidity-info>

View file

@ -5,7 +5,7 @@ import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { faSmile } from '@fortawesome/free-regular-svg-icons';
import { faSmile, faFrown } from '@fortawesome/free-regular-svg-icons';
import { LoggerService } from '../../shared/services/logger.service';
import { CommonService } from '../../shared/services/common.service';
@ -22,6 +22,7 @@ import * as RTLActions from '../../store/rtl.actions';
})
export class HomeComponent implements OnInit, OnDestroy {
public faSmile = faSmile;
public faFrown = faFrown;
public flgChildInfoUpdated = false;
public userPersonaEnum = UserPersonaEnum;
public activeChannels = 0;
@ -67,18 +68,20 @@ export class HomeComponent implements OnInit, OnDestroy {
map(({ matches }) => {
if (matches) {
return [
{ id: 'balance', title: 'Balances', cols: 3, rows: 1 },
{ id: 'transactions', title: 'Transactions', cols: 3, rows: 1 },
{ id: 'inboundLiq', title: 'In-Bound Liquidity', cols: 3, rows: 1 },
{ id: 'outboundLiq', title: 'Out-Bound Liquidity', cols: 3, rows: 1 }
{ id: 'node', title: 'Node Details', cols: 3, rows: 3 },
{ id: 'balance', title: 'Balances', cols: 3, rows: 3 },
{ id: 'transactions', title: 'Transactions', cols: 3, rows: 4 },
{ id: 'inboundLiq', title: 'In-Bound Liquidity', cols: 3, rows: 8 },
{ id: 'outboundLiq', title: 'Out-Bound Liquidity', cols: 3, rows: 8 }
];
}
return [
{ id: 'balance', title: 'Balances', cols: 1, rows: 1 },
{ id: 'inboundLiq', title: 'In-Bound Liquidity', cols: 1, rows: 3 },
{ id: 'outboundLiq', title: 'Out-Bound Liquidity', cols: 1, rows: 3 },
{ id: 'transactions', title: 'Transactions', cols: 1, rows: 2 }
{ id: 'node', title: 'Node Details', cols: 1, rows: 3 },
{ id: 'inboundLiq', title: 'In-Bound Liquidity', cols: 1, rows: 10 },
{ id: 'outboundLiq', title: 'Out-Bound Liquidity', cols: 1, rows: 10 },
{ id: 'balance', title: 'Balances', cols: 1, rows: 3 },
{ id: 'transactions', title: 'Transactions', cols: 1, rows: 4 }
];
})
);

View file

@ -8,7 +8,7 @@
</div>
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-500">Implementation</h4>
<div class="foreground-secondary-text">{{information.lnImplementation + ' v' + information.version}}</div>
<div class="foreground-secondary-text">{{(information.lnImplementation || information.version) ? information.lnImplementation + ' v' + information.version : ''}}</div>
</div>
<div fxFlex="34">
<h4 fxLayoutAlign="start" class="font-bold-500">Chain</h4>

View file

@ -48,6 +48,7 @@ import { MatButtonModule } from '@angular/material/button';
import { LayoutModule } from '@angular/cdk/layout';
import { ChannelLiquidityInfoComponent } from './home/channel-liquidity-info/channel-liquidity-info.component';
import { LoopComponent } from './loop/loop.component';
import { NetworkInfoComponent } from './network-info/network-info.component';
@NgModule({
imports: [
@ -96,7 +97,8 @@ import { LoopComponent } from './loop/loop.component';
ChannelStatusInfoComponent,
ChannelCapacityInfoComponent,
LoopComponent,
ChannelLiquidityInfoComponent
ChannelLiquidityInfoComponent,
NetworkInfoComponent
],
providers: [
{ provide: LoggerService, useClass: ConsoleLoggerService },

View file

@ -9,6 +9,7 @@ import { TransactionsComponent } from './transactions/transactions.component';
import { LookupsComponent } from './lookups/lookups.component';
import { RoutingComponent } from './routing/routing.component';
import { OnChainComponent } from './on-chain/on-chain.component';
import { NetworkInfoComponent } from './network-info/network-info.component';
import { LoopComponent } from './loop/loop.component';
import { AuthGuard, LNDUnlockedGuard } from '../shared/services/auth.guard';
@ -24,6 +25,7 @@ export const LndRoutes: Routes = [
{ path: 'onchain', component: OnChainComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'routing', component: RoutingComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'lookups', component: LookupsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'network', component: NetworkInfoComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'loop', component: LoopComponent, canActivate: [LNDUnlockedGuard] },
{ path: '**', component: NotFoundComponent }
]}

View file

@ -0,0 +1,54 @@
<div fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faNetworkWired" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Network Information</span>
</div>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="start start" class="padding-gap-x">
<mat-card fxLayout="row" fxFlex="100" fxLayoutAlign="start start">
<mat-progress-bar *ngIf="flgLoading[1]===true" mode="indeterminate"></mat-progress-bar>
<mat-card-content fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch" class="card-content-gap">
<div fxLayout="row" fxLayoutAlign="start start" fxFlex="100" class="my-2">
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-330">Network Capacity</h4>
<span class="foreground-secondary-text">{{networkInfo.total_network_capacity | number}} Sats</span>
</div>
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-330">Number of Nodes</h4>
<span class="foreground-secondary-text">{{networkInfo.num_nodes | number}}</span>
</div>
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-330">Number of Channels</h4>
<span class="foreground-secondary-text">{{networkInfo.num_channels | number}}</span>
</div>
<mat-divider fxFlex="100" class="w-100 mt-6"></mat-divider>
</div>
<div fxLayout="row" fxLayoutAlign="start start" fxFlex="100" class="my-2">
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-330">Max Channel Size</h4>
<span class="foreground-secondary-text">{{networkInfo.max_channel_size | number}}</span>
</div>
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-330">Avg Channel Size</h4>
<span class="foreground-secondary-text">{{networkInfo.avg_channel_size | number}}</span>
</div>
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-330">Min Channel Size</h4>
<span class="foreground-secondary-text">{{networkInfo.min_channel_size | number}}</span>
</div>
<mat-divider fxFlex="100" class="w-100 mt-6"></mat-divider>
</div>
<div fxLayout="row" fxLayoutAlign="start start" fxFlex="100" class="my-2">
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-330">Max Out Degree</h4>
<span class="foreground-secondary-text">{{networkInfo.max_out_degree | number}}</span>
</div>
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-330">Avg Out Degree</h4>
<span class="foreground-secondary-text">{{networkInfo.avg_out_degree | number:'1.0-2'}}</span>
</div>
<mat-divider fxFlex="100" class="w-100 mt-6"></mat-divider>
</div>
</mat-card-content>
</mat-card>
</div>
</div>

View file

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NetworkInfoComponent } from './network-info.component';
describe('NetworkInfoComponent', () => {
let component: NetworkInfoComponent;
let fixture: ComponentFixture<NetworkInfoComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ NetworkInfoComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NetworkInfoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,61 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { faNetworkWired } from '@fortawesome/free-solid-svg-icons';
import { LoggerService } from '../../shared/services/logger.service';
import { GetInfo, NetworkInfo } from '../../shared/models/lndModels';
import { SelNodeChild } from '../../shared/models/RTLconfig';
import * as fromRTLReducer from '../../store/rtl.reducers';
@Component({
selector: 'rtl-network-info',
templateUrl: './network-info.component.html',
styleUrls: ['./network-info.component.scss']
})
export class NetworkInfoComponent implements OnInit, OnDestroy {
public faNetworkWired = faNetworkWired;
public selNode: SelNodeChild = {};
public information: GetInfo = {};
public networkInfo: NetworkInfo = {};
public flgLoading: Array<Boolean | 'error'> = [true, true];
private unSubs: Array<Subject<void>> = [new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>) {}
ngOnInit() {
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsLnd.forEach(effectsErr => {
if (effectsErr.action === 'FetchInfo') {
this.flgLoading[0] = 'error';
}
if (effectsErr.action === 'FetchNetwork') {
this.flgLoading[1] = 'error';
}
});
this.selNode = rtlStore.nodeSettings;
this.information = rtlStore.information;
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== this.information.identity_pubkey) ? false : true;
}
this.networkInfo = rtlStore.networkInfo;
if (this.flgLoading[1] !== 'error') {
this.flgLoading[1] = (undefined !== this.networkInfo.num_nodes) ? false : true;
}
this.logger.info(rtlStore);
});
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

View file

@ -3,22 +3,22 @@
<mat-form-field fxFlex="100" fxLayoutAlign="start end">
<input matInput [(ngModel)]="memo" placeholder="Memo" tabindex="1" name="memo">
</mat-form-field>
<div fxLayout="column" [fxLayout.gt-sm]="showDetails ? 'row wrap' : 'column'" [fxFlex]="showDetails ? 70 : 100" [fxLayoutAlign.gt-sm]="showDetails ? 'space-between center' : 'start stretch'" fxLayoutAlign="space-between center">
<div fxLayout="column" [fxLayout.gt-sm]="showDetails ? 'row wrap' : 'column'" [fxFlex]="showDetails ? 70 : 100" [fxLayoutAlign.gt-sm]="showDetails ? 'space-between center' : 'start stretch'" fxLayoutAlign="start stretch">
<mat-form-field fxFlex="40" fxLayoutAlign="start end">
<input matInput [(ngModel)]="invoiceValue" (keyup)="onInvoiceValueChange()" placeholder="Amount" type="number" step="100" min="1" tabindex="2" name="invoiceValue">
<span matSuffix> {{information?.smaller_currency_unit}} </span>
<mat-hint>{{invoiceValueHint}}</mat-hint>
</mat-form-field>
<mat-form-field fxFlex="15" fxLayoutAlign="start end">
<mat-form-field fxFlex="15" fxLayoutAlign="start end" *ngIf="showDetails">
<input matInput [(ngModel)]="expiry" placeholder="Expiry" type="number" step="{{selTimeUnit === timeUnitEnum.SECS ? 300 : selTimeUnit === timeUnitEnum.MINS ? 10 : selTimeUnit === timeUnitEnum.HOURS ? 2 : 1}}" min="1" tabindex="3" name="expiry">
<span matSuffix> {{selTimeUnit | titlecase}} </span>
</mat-form-field>
<mat-form-field fxFlex="15" fxLayoutAlign="start end">
<mat-form-field fxFlex="15" fxLayoutAlign="start end" *ngIf="showDetails">
<mat-select [value]="selTimeUnit" tabindex="4" required name="timeUnit" (selectionChange)="onTimeUnitChange($event)">
<mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">{{timeUnit | titlecase}}</mat-option>
</mat-select>
</mat-form-field>
<div fxFlex="25" tabindex="4" fxLayoutAlign="start center">
<div fxFlex="25" tabindex="4" fxLayoutAlign="start center" *ngIf="showDetails">
<mat-slide-toggle color="primary" [(ngModel)]="private" matTooltip="Include routing hints for private channels" [matTooltipPosition]="'above'" name="private">Private Routing Hints</mat-slide-toggle>
</div>
</div>

View file

@ -1,4 +1,4 @@
import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faProjectDiagram, faCog, faQuestion, faSearch, faTools } from '@fortawesome/free-solid-svg-icons';
import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faProjectDiagram, faNetworkWired, faCog, faQuestion, faSearch, faTools } from '@fortawesome/free-solid-svg-icons';
export const MENU_DATA: MenuRootNode = {
LNDChildren: [
@ -8,7 +8,8 @@ export const MENU_DATA: MenuRootNode = {
{id: 31, parentId: 3, name: 'Peers/Channels', iconType: 'FA', icon: faUsers, link: '/lnd/peerschannels'},
{id: 32, parentId: 3, name: 'Transactions', iconType: 'FA', icon: faExchangeAlt, link: '/lnd/transactions'},
{id: 33, parentId: 3, name: 'Lookup', iconType: 'FA', icon: faSearch, link: '/lnd/lookups'},
{id: 34, parentId: 3, name: 'Routing', iconType: 'FA', icon: faProjectDiagram, link: '/lnd/routing'}
{id: 34, parentId: 3, name: 'Routing', iconType: 'FA', icon: faProjectDiagram, link: '/lnd/routing'},
{id: 35, parentId: 3, name: 'Network', iconType: 'FA', icon: faNetworkWired, link: '/lnd/network'}
]},
{id: 4, parentId: 0, name: 'Advanced', iconType: 'FA', icon: faCog, link: '/advanced'},
{id: 5, parentId: 0, name: 'Settings', iconType: 'FA', icon: faTools, link: '/settings'},

View file

@ -326,6 +326,10 @@ body {
margin-top: 4rem !important;
}
.mt-6 {
margin-top: 6rem !important;
}
.mt-minus-1 {
margin-top: -1rem !important;
}

View file

@ -121,12 +121,18 @@ export class RTLEffects implements OnDestroy {
map((rtlConfig: RTLConfiguration) => {
this.logger.info(rtlConfig);
let searchNode = rtlConfig.nodes.find(node => +node.index === rtlConfig.selectedNodeIndex);
searchNode.settings.currencyUnits = [...CURRENCY_UNITS, searchNode.settings.currencyUnit];
this.store.dispatch(new RTLActions.SetSelelectedNode({lnNode: searchNode, isInitialSetup: true}))
return {
type: RTLActions.SET_RTL_CONFIG,
payload: rtlConfig
};
if(searchNode) {
searchNode.settings.currencyUnits = [...CURRENCY_UNITS, searchNode.settings.currencyUnit];
this.store.dispatch(new RTLActions.SetSelelectedNode({lnNode: searchNode, isInitialSetup: true}))
return {
type: RTLActions.SET_RTL_CONFIG,
payload: rtlConfig
};
} else {
return {
type: RTLActions.VOID
}
}
},
catchError((err) => {
this.handleErrorWithoutAlert('FetchRTLConfig', err);
@ -242,6 +248,8 @@ export class RTLEffects implements OnDestroy {
ofType(RTLActions.SIGNIN),
withLatestFrom(this.store.select('root')),
mergeMap(([action, rootStore]: [RTLActions.Signin, fromRTLReducer.RootState]) => {
this.store.dispatch(new RTLActions.ClearEffectErrorLnd('FetchInfo'));
this.store.dispatch(new RTLActions.ClearEffectErrorCl('FetchInfoCL'));
this.store.dispatch(new RTLActions.ClearEffectErrorRoot('Signin'));
return this.httpClient.post(environment.AUTHENTICATE_API, {
authenticateWith: (undefined === action.payload || action.payload == null || action.payload === '') ? AuthenticateWith.TOKEN : AuthenticateWith.PASSWORD,
@ -357,7 +365,7 @@ export class RTLEffects implements OnDestroy {
width: '55%', data: {
type: alertType,
alertTitle: alertTitle,
message: { code: err.status, message: err.error.error, URL: errURL },
message: { code: err.status ? err.status : 'Unknown Error', message: (err.error && err.error.error) ? err.error.error : (err.error) ? err.error : 'Unknown Error', URL: errURL },
component: ErrorMessageComponent
}
}));

View file

@ -13,7 +13,7 @@ export interface RootState {
nodeData: GetInfoRoot;
}
const initNodeSettings = { userPersona: 'Operator', flgSidenavOpened: true, flgSidenavPinned: true, menu: 'vertical', menuType: 'regular', fontSize: 'regular-font', themeMode: 'night', themeColor: 'blue', satsToBTC: false, channelBackupPath: '', selCurrencyUnit: 'USD', currencyUnits: ['Sats', 'BTC', 'USD'] };
const initNodeSettings = { userPersona: 'Operator', flgSidenavOpened: true, flgSidenavPinned: true, menu: 'vertical', menuType: 'regular', fontSize: 'regular-font', themeMode: 'day', themeColor: 'purple', satsToBTC: false, channelBackupPath: '', selCurrencyUnit: 'USD', currencyUnits: ['Sats', 'BTC', 'USD'] };
const initNodeAuthentication = { nodeAuthType: 'CUSTOM', configPath: '', bitcoindConfigPath: '' };
const initRootState: RootState = {