Dashboard and settings tweeks

Dashboard and settings tweeks
pull/260/head
Shahana Farooqui 5 years ago
parent 01748ace27
commit 71442c2573

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

@ -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="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="icon" type="image/png" sizes="16x16" href="assets/images/favicon/favicon-16x16.png">
<link rel="manifest" href="assets/images/favicon/site.webmanifest"> <link rel="manifest" href="assets/images/favicon/site.webmanifest">
<link rel="stylesheet" href="styles.7342c1312d7434d854df.css"></head> <link rel="stylesheet" href="styles.77aafb08c5a2ab8c8821.css"></head>
<body> <body>
<rtl-app></rtl-app> <rtl-app></rtl-app>
<script src="runtime.3200a96426bdc2028426.js" defer></script><script src="polyfills-es5.b8e32dec482ae69710a2.js" nomodule defer></script><script src="polyfills.ebf9033c33aa4a5af12a.js" defer></script><script src="main.8060670d53993730b06c.js" defer></script></body> <script src="runtime.f8483477e70a87426a22.js" defer></script><script src="polyfills-es5.b8e32dec482ae69710a2.js" nomodule defer></script><script src="polyfills.ebf9033c33aa4a5af12a.js" defer></script><script src="main.e93f84cc3826441e698b.js" defer></script></body>
</html> </html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

@ -0,0 +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++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&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:"df8a42ae5fabe34ad893",6:"9052d99b0c58d3773f50",7:"6fbd1a1cd900b63944af"}[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

@ -33,6 +33,14 @@ exports.getRTLConfig = (req, res, next) => {
bitcoindConfigPath: common.nodes[0].bitcoind_config_path bitcoindConfigPath: common.nodes[0].bitcoind_config_path
}; };
jsonConfig.Settings.channelBackupPath = (undefined !== jsonConfig.Settings.channelBackupPath) ? jsonConfig.Settings.channelBackupPath : common.nodes[0].channel_backup_path; jsonConfig.Settings.channelBackupPath = (undefined !== jsonConfig.Settings.channelBackupPath) ? jsonConfig.Settings.channelBackupPath : common.nodes[0].channel_backup_path;
jsonConfig.Settings.flgSidenavOpened = (undefined !== jsonConfig.Settings.flgSidenavOpened) ? jsonConfig.Settings.flgSidenavOpened : true;
jsonConfig.Settings.flgSidenavPinned = (undefined !== jsonConfig.Settings.flgSidenavPinned) ? jsonConfig.Settings.flgSidenavPinned : true;
jsonConfig.Settings.menu = (undefined !== jsonConfig.Settings.menu) ? jsonConfig.Settings.menu : 'vertical';
jsonConfig.Settings.menuType = (undefined !== jsonConfig.Settings.menuType) ? jsonConfig.Settings.menuType : 'regular';
jsonConfig.Settings.fontSize = (undefined !== jsonConfig.Settings.fontSize) ? jsonConfig.Settings.fontSize : 'regular-font';
jsonConfig.Settings.themeMode = (undefined !== jsonConfig.Settings.themeMode) ? jsonConfig.Settings.themeMode : 'day';
jsonConfig.Settings.themeColor = (undefined !== jsonConfig.Settings.themeColor) ? jsonConfig.Settings.themeColor : 'purple';
jsonConfig.Settings.satsToBTC = (undefined !== jsonConfig.Settings.satsToBTC) ? jsonConfig.Settings.satsToBTC : false;
res.status(200).json({ defaultNodeIndex: 0, selectedNodeIndex: common.selectedNode.index, sso: sso, nodes: [{ res.status(200).json({ defaultNodeIndex: 0, selectedNodeIndex: common.selectedNode.index, sso: sso, nodes: [{
index: common.nodes[0].index, index: common.nodes[0].index,
lnNode: 'SingleNode', lnNode: 'SingleNode',
@ -71,11 +79,18 @@ exports.getRTLConfig = (req, res, next) => {
} else { } else {
authentication.configPath = ''; authentication.configPath = '';
} }
if(node.Settings.bitcoindConfigPath) {
if(node.Settings.bitcoindConfigPath) {
authentication.bitcoindConfigPath = node.Settings.bitcoindConfigPath; authentication.bitcoindConfigPath = node.Settings.bitcoindConfigPath;
} }
node.Settings.channelBackupPath = (undefined !== node.Settings.channelBackupPath) ? node.Settings.channelBackupPath : common.nodes[i].channel_backup_path; node.Settings.channelBackupPath = (undefined !== node.Settings.channelBackupPath) ? node.Settings.channelBackupPath : common.nodes[i].channel_backup_path;
node.Settings.flgSidenavOpened = (undefined !== node.Settings.flgSidenavOpened) ? node.Settings.flgSidenavOpened : true;
node.Settings.flgSidenavPinned = (undefined !== node.Settings.flgSidenavPinned) ? node.Settings.flgSidenavPinned : true;
node.Settings.menu = (undefined !== node.Settings.menu) ? node.Settings.menu : 'vertical';
node.Settings.menuType = (undefined !== node.Settings.menuType) ? node.Settings.menuType : 'regular';
node.Settings.fontSize = (undefined !== node.Settings.fontSize) ? node.Settings.fontSize : 'regular-font';
node.Settings.themeMode = (undefined !== node.Settings.themeMode) ? node.Settings.themeMode : 'day';
node.Settings.themeColor = (undefined !== node.Settings.themeColor) ? node.Settings.themeColor : 'purple';
node.Settings.satsToBTC = (undefined !== node.Settings.satsToBTC) ? node.Settings.satsToBTC : false;
nodesArr.push({ nodesArr.push({
index: node.index, index: node.index,
lnNode: node.lnNode, lnNode: node.lnNode,
@ -224,7 +239,6 @@ exports.getConfig = (req, res, next) => {
exports.getCurrencyRates = (req, res, next) => { exports.getCurrencyRates = (req, res, next) => {
options.url = 'https://blockchain.info/ticker'; options.url = 'https://blockchain.info/ticker';
console.log(options);
request(options).then((body) => { request(options).then((body) => {
if(undefined === body || body.error) { if(undefined === body || body.error) {
res.status(500).json({ res.status(500).json({
@ -234,7 +248,6 @@ exports.getCurrencyRates = (req, res, next) => {
} else { } else {
res.status(200).json(body); res.status(200).json(body);
body = JSON.parse(body); body = JSON.parse(body);
logger.info({fileName: 'RTLConf', msg: 'Rates Received: ' + JSON.stringify(body)});
} }
}) })
.catch(function (err) { .catch(function (err) {

@ -19,19 +19,17 @@ exports.getAllChannels = (req, res, next) => {
options = common.getOptions(); options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/channels'; options.url = common.getSelLNServerUrl() + '/channels';
options.qs = req.query; options.qs = req.query;
let local = 0;
let remote = 0;
let total = 0;
request(options).then(function (body) { request(options).then(function (body) {
if(body.channels) { if(body.channels) {
Promise.all( Promise.all(
body.channels.map(channel => { body.channels.map(channel => {
if (!channel.local_balance && !channel.remote_balance) { local = (channel.local_balance) ? +channel.local_balance : 0;
channel.balancedness = 50; remote = (channel.remote_balance) ? +channel.remote_balance : 0;
} else if((channel.local_balance || channel.local_balance < 1) && !channel.remote_balance) { total = local + remote;
channel.balancedness = 100; channel.balancedness = ((1 - Math.abs((local-remote)/total)) * 100).toFixed(2);
} else if(!channel.local_balance && (channel.remote_balance || channel.remote_balance < 1)) {
channel.balancedness = 0;
} else {
channel.balancedness = (+channel.local_balance/(+channel.remote_balance + +channel.local_balance)) * 100;
}
return getAliasForChannel(channel); return getAliasForChannel(channel);
}) })
) )

@ -38,7 +38,7 @@
<div [ngClass]="{'mt-minus-1': smallScreen, 'inner-sidenav-content': true}"> <div [ngClass]="{'mt-minus-1': smallScreen, 'inner-sidenav-content': true}">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div> </div>
</mat-sidenav-content> </mat-sidenav-content>>
</mat-sidenav-container> </mat-sidenav-container>
<div class="rtl-spinner" *ngIf="undefined === settings.themeColor"> <div class="rtl-spinner" *ngIf="undefined === settings.themeColor">
<mat-spinner color="accent"></mat-spinner> <mat-spinner color="accent"></mat-spinner>

@ -1,5 +1,5 @@
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container"> <div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faArchive" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faDownload" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Channels Backup</span> <span class="page-title">Channels Backup</span>
</div> </div>
<div fxLayout="column" class="padding-gap-x"> <div fxLayout="column" class="padding-gap-x">

@ -1,5 +1,5 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { faArchive } from '@fortawesome/free-solid-svg-icons'; import { faDownload } from '@fortawesome/free-solid-svg-icons';
@Component({ @Component({
selector: 'rtl-backup', selector: 'rtl-backup',
@ -7,7 +7,7 @@ import { faArchive } from '@fortawesome/free-solid-svg-icons';
styleUrls: ['./backup.component.scss'] styleUrls: ['./backup.component.scss']
}) })
export class BackupComponent { export class BackupComponent {
public faArchive = faArchive; public faDownload = faDownload;
constructor() {} constructor() {}

@ -1,22 +1,28 @@
<div fxLayout="column" fxLayoutAlign="space-between stretch" fxFlex="100"> <div fxLayout="column" fxLayoutAlign="space-between stretch" fxFlex="100">
<div fxLayout="column" fxFlex="10" fxLayoutAlign="end start"> <div fxLayout="column" fxFlex="9" fxLayoutAlign="end start">
<span class="dashboard-capacity-header this-channel-capacity">Total Capacity</span> <span class="dashboard-capacity-header this-channel-capacity">Total Capacity</span>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100"> <div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
<mat-hint fxFlex="50" fxLayoutAlign="start center" class="font-size-90"><strong class="font-weight-900 mr-5px">Local:</strong>{{channelBalances.localBalance || 0 | number}} Sats</mat-hint> <mat-hint fxFlex="50" fxLayoutAlign="start center" class="font-size-90"><strong class="font-weight-900 mr-5px">Local:</strong>{{channelBalances.localBalance || 0 | number}} Sats</mat-hint>
<mat-hint fxFlex="50" fxLayoutAlign="end center" class="font-size-90"><strong class="font-weight-900 mr-5px">Remote:</strong>{{channelBalances.remoteBalance || 0 | number}} Sats</mat-hint> <mat-hint fxFlex="50" fxLayoutAlign="end center" class="font-size-90"><strong class="font-weight-900 mr-5px">Remote:</strong>{{channelBalances.remoteBalance || 0 | number}} Sats</mat-hint>
</div> </div>
<mat-progress-bar class="dashboard-progress-bar this-channel-bar" mode="determinate" color="accent" value="{{channelBalances.localBalance && channelBalances.localBalance > 0 ? ((+channelBalances.localBalance/((+channelBalances.localBalance)+(+channelBalances.remoteBalance)))*100) : 0}}"></mat-progress-bar> <mat-progress-bar class="dashboard-progress-bar this-channel-bar" mode="determinate" color="accent" value="{{channelBalances.localBalance && channelBalances.localBalance > 0 ? ((+channelBalances.localBalance/((+channelBalances.localBalance)+(+channelBalances.remoteBalance)))*100) : 0}}"></mat-progress-bar>
<mat-divider class="w-100 dashboard-divider"></mat-divider>
</div> </div>
<div fxLayout="column" fxFlex="89" fxFlex.lt-md="85" fxLayoutAlign="start start" class="channels-capacity-scroll" perfectScrollbar> <div fxLayout="column" fxFlex="3" fxLayoutAlign="end stretch"><mat-divider class="dashboard-divider"></mat-divider></div>
<div fxLayout="column" fxFlex.gt-sm="88" fxFlex="84" fxLayoutAlign="start start" class="channels-capacity-scroll" perfectScrollbar>
<div fxLayout="column" fxFlex="100" class="w-100" *ngIf="allChannels && allChannels.length > 0; else noChannelBlock"> <div fxLayout="column" fxFlex="100" class="w-100" *ngIf="allChannels && allChannels.length > 0; else noChannelBlock">
<div *ngFor="let channel of allChannels" class="mt-2"> <div *ngFor="let channel of allChannels" class="mt-2">
<span class="dashboard-capacity-header">{{(channel.remote_alias || channel.remote_pubkey) | slice:0:24}}{{(channel.remote_alias || channel.remote_pubkey).length > 25 ? '...' : ''}}</span> <span class="dashboard-capacity-header" matTooltip="{{channel.remote_alias || channel.remote_pubkey}}" matTooltipDisabled="{{(channel.remote_alias || channel.remote_pubkey).length < 26}}">{{(channel.remote_alias || channel.remote_pubkey) | slice:0:24}}{{(channel.remote_alias || channel.remote_pubkey).length > 25 ? '...' : ''}}</span>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100"> <div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
<mat-hint fxFlex="50" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Local:</strong>{{channel.local_balance || 0 | number}} Sats</mat-hint> <mat-hint fxFlex="40" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Local:</strong>{{channel.local_balance || 0 | number}} Sats</mat-hint>
<mat-hint fxFlex="50" fxLayoutAlign="end center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Remote:</strong>{{channel.remote_balance || 0 | number}} Sats</mat-hint> <mat-hint fxFlex="20" fxLayoutAlign="center center" class="font-size-90 color-primary">
<fa-icon [icon]="faBalanceScale" class="color-primary mr-3px" matTooltip="Balance Score"></fa-icon>
({{channel.balancedness || 0 | number}})
<!-- <fa-icon [icon]="sortBy === 'Channel Balance' ? faBalanceScale : faDumbbell" class="color-primary mr-3px" matTooltip="Balance Score"></fa-icon>
({{((sortBy === 'Channel Balance' ? channel.balancedness : channel.capacity) || 0) | number}}{{sortBy === 'Channel Balance' ? '' : ' Sats'}}) -->
</mat-hint>
<mat-hint fxFlex="40" fxLayoutAlign="end center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Remote:</strong>{{channel.remote_balance || 0 | number}} Sats</mat-hint>
</div> </div>
<mat-progress-bar class="dashboard-progress-bar" mode="determinate" value="{{channel.balancedness}}"></mat-progress-bar> <mat-progress-bar class="dashboard-progress-bar" mode="determinate" value="{{channel.local_balance && channel.local_balance > 0 ? ((+channel.local_balance/((+channel.local_balance)+(+channel.remote_balance)))*100) : 0}}"></mat-progress-bar>
</div> </div>
</div> </div>
</div> </div>

@ -1,4 +1,6 @@
import { Component, OnChanges, Input } from '@angular/core'; import { Component, OnChanges, Input } from '@angular/core';
import { faBalanceScale, faDumbbell } from '@fortawesome/free-solid-svg-icons';
import { Channel } from '../../../shared/models/lndModels'; import { Channel } from '../../../shared/models/lndModels';
@Component({ @Component({
@ -7,8 +9,11 @@ import { Channel } from '../../../shared/models/lndModels';
styleUrls: ['./channel-capacity-info.component.scss'] styleUrls: ['./channel-capacity-info.component.scss']
}) })
export class ChannelCapacityInfoComponent implements OnChanges { export class ChannelCapacityInfoComponent implements OnChanges {
public faBalanceScale = faBalanceScale;
public faDumbbell = faDumbbell;
@Input() channelBalances: {localBalance: number, remoteBalance: number}; @Input() channelBalances: {localBalance: number, remoteBalance: number};
@Input() allChannels: Channel[]; @Input() allChannels: Channel[];
@Input() sortBy: string = 'Channel Balance';
constructor() {} constructor() {}

@ -1,20 +1,14 @@
<div fxLayout="column" fxLayoutAlign="space-between stretch" fxFlex="100"> <div fxLayout="column" fxLayoutAlign="space-between stretch" fxFlex="100">
<div fxLayout="column" fxFlex="10" fxLayoutAlign="end stretch"> <div fxLayout="column" fxFlex="9" fxLayoutAlign="end start">
<div fxLayout="row" fxLayoutAlign="space-between start"> <span class="dashboard-capacity-header this-channel-capacity">Total Capacity</span>
<span class="dashboard-capacity-header this-channel-capacity">Max Transaction</span> <mat-hint class="font-size-90">{{totalLiquidity | number}} Sats</mat-hint>
<span class="dashboard-capacity-header this-channel-capacity">Total Capacity</span> <mat-progress-bar class="dashboard-progress-bar this-channel-bar" mode="determinate" color="accent" value="100"></mat-progress-bar>
</div>
<div fxLayout="row" fxLayoutAlign="space-between stretch">
<mat-hint class="font-size-90">{{maxAmount | number}} Sats</mat-hint>
<mat-hint class="font-size-90">{{totalLiquidity | number}} Sats</mat-hint>
</div>
<mat-progress-bar class="dashboard-progress-bar this-channel-bar" mode="determinate" color="accent" value="{{maxAmount/totalLiquidity*100 ? maxAmount/totalLiquidity*100 : 0}}"></mat-progress-bar>
<mat-divider class="w-100 dashboard-divider mt-2"></mat-divider>
</div> </div>
<div fxLayout="column" fxFlex="89" fxFlex.lt-md="85" fxLayoutAlign="start start" class="channels-capacity-scroll w-100 mt-2" perfectScrollbar> <div fxLayout="column" fxFlex="3" fxLayoutAlign="end stretch"><mat-divider class="dashboard-divider"></mat-divider></div>
<div fxLayout="column" fxFlex.gt-sm="88" fxFlex="84" fxLayoutAlign="start start" class="channels-capacity-scroll" perfectScrollbar>
<div fxLayout="column" fxFlex="100" class="w-100" *ngIf="allChannels && allChannels.length > 0; else noChannelBlock"> <div fxLayout="column" fxFlex="100" class="w-100" *ngIf="allChannels && allChannels.length > 0; else noChannelBlock">
<div *ngFor="let channel of allChannels" class="mt-2"> <div *ngFor="let channel of allChannels" class="mt-2">
<span class="dashboard-capacity-header">{{(channel.remote_alias || channel.remote_pubkey) | slice:0:24}}{{(channel.remote_alias || channel.remote_pubkey).length > 25 ? '...' : ''}}</span> <span class="dashboard-capacity-header" matTooltip="{{channel.remote_alias || channel.remote_pubkey}}" matTooltipDisabled="{{(channel.remote_alias || channel.remote_pubkey).length < 26}}">{{(channel.remote_alias || channel.remote_pubkey) | slice:0:24}}{{(channel.remote_alias || channel.remote_pubkey).length > 25 ? '...' : ''}}</span>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100"> <div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
<mat-hint *ngIf="direction === 'In'" fxFlex="100" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Capacity: </strong>{{channel.remote_balance || 0 | number}} Sats</mat-hint> <mat-hint *ngIf="direction === 'In'" fxFlex="100" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Capacity: </strong>{{channel.remote_balance || 0 | number}} Sats</mat-hint>
<mat-hint *ngIf="direction === 'Out'" fxFlex="100" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Capacity: </strong>{{channel.local_balance || 0 | number}} Sats</mat-hint> <mat-hint *ngIf="direction === 'Out'" fxFlex="100" fxLayoutAlign="start center" class="font-size-90 color-primary"><strong class="font-weight-900 mr-5px">Capacity: </strong>{{channel.local_balance || 0 | number}} Sats</mat-hint>

@ -10,13 +10,20 @@
<mat-card-title> <mat-card-title>
<fa-icon [icon]="card.icon" class="mr-1"></fa-icon> <fa-icon [icon]="card.icon" class="mr-1"></fa-icon>
<span>{{card.title}}</span> <span>{{card.title}}</span>
<button *ngIf="card.link" mat-icon-button class="more-button mt-1" [matMenuTriggerFor]="menuOperator" aria-label="Toggle menu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menuOperator="matMenu" class="dashboard-vert-menu" xPosition="before">
<button mat-menu-item (click)="onNavigateTo(card.link)">Go To {{card.goTo}}</button>
<button *ngIf="card.id === 'capacity'" (click)="onsortChannelsBy()" mat-menu-item>Sort By {{sortField === 'Channel Balance' ? 'Capacity' : 'Channel Balance'}}</button>
</mat-menu>
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<mat-card-content class="dashboard-card-content w-100" fxFlex="95"> <mat-card-content class="dashboard-card-content w-100" fxFlex="95">
<div [ngSwitch]="card.id" fxLayout="column" fxFlex="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-node-info fxFlex="100" *ngSwitchCase="'node'" [information]="information" [ngClass]="{'error-border': flgLoading[0]==='error'}"></rtl-node-info>
<rtl-balances-info fxFlex="100" *ngSwitchCase="'balance'" [balances]="balances" [ngClass]="{'error-border': flgLoading[2]==='error' || flgLoading[5]==='error'}"></rtl-balances-info> <rtl-balances-info fxFlex="100" *ngSwitchCase="'balance'" [balances]="balances" [ngClass]="{'error-border': flgLoading[2]==='error' || flgLoading[5]==='error'}"></rtl-balances-info>
<rtl-channel-capacity-info fxFlex="100" *ngSwitchCase="'capacity'" [channelBalances]="channelBalances" [allChannels]="allChannelsCapacity" [ngClass]="{'error-border': flgLoading[5]==='error'}"></rtl-channel-capacity-info> <rtl-channel-capacity-info fxFlex="100" *ngSwitchCase="'capacity'" [sortBy]="sortField" [channelBalances]="channelBalances" [allChannels]="allChannelsCapacity" [ngClass]="{'error-border': flgLoading[5]==='error'}"></rtl-channel-capacity-info>
<rtl-fee-info fxFlex="100" *ngSwitchCase="'fee'" [fees]="fees" [ngClass]="{'error-border': flgLoading[1]==='error'}"></rtl-fee-info> <rtl-fee-info fxFlex="100" *ngSwitchCase="'fee'" [fees]="fees" [ngClass]="{'error-border': flgLoading[1]==='error'}"></rtl-fee-info>
<rtl-channel-status-info fxFlex="100" *ngSwitchCase="'status'" [channelsStatus]="channelsStatus" [ngClass]="{'error-border': flgLoading[5]==='error' || flgLoading[6]==='error'}"></rtl-channel-status-info> <rtl-channel-status-info fxFlex="100" *ngSwitchCase="'status'" [channelsStatus]="channelsStatus" [ngClass]="{'error-border': flgLoading[5]==='error' || flgLoading[6]==='error'}"></rtl-channel-status-info>
<h3 *ngSwitchDefault>Error! Unable to find information!</h3> <h3 *ngSwitchDefault>Error! Unable to find information!</h3>
@ -38,6 +45,12 @@
<mat-card-title> <mat-card-title>
<fa-icon [icon]="card.icon" class="mr-1"></fa-icon> <fa-icon [icon]="card.icon" class="mr-1"></fa-icon>
<span>{{card.title}}</span> <span>{{card.title}}</span>
<button *ngIf="card.link" mat-icon-button class="more-button mt-1" [matMenuTriggerFor]="menuMerchant" aria-label="Toggle menu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menuMerchant="matMenu" class="dashboard-vert-menu" xPosition="before">
<button mat-menu-item (click)="onNavigateTo(card.link)">Go To {{card.goTo}}</button>
</mat-menu>
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<mat-card-content class="dashboard-card-content w-100" fxFlex="{{card.id !== 'transactions' ? 95 : 100}}"> <mat-card-content class="dashboard-card-content w-100" fxFlex="{{card.id !== 'transactions' ? 95 : 100}}">
@ -46,10 +59,20 @@
<rtl-balances-info fxFlex="100" *ngSwitchCase="'balance'" [balances]="balances" [ngClass]="{'error-border': flgLoading[2]==='error' || flgLoading[5]==='error'}"></rtl-balances-info> <rtl-balances-info fxFlex="100" *ngSwitchCase="'balance'" [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="'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> <rtl-channel-liquidity-info fxFlex="100" *ngSwitchCase="'outboundLiq'" [direction]="'Out'" [totalLiquidity]="totalOutboundLiquidity" [allChannels]="allOutboundChannels" [ngClass]="{'error-border': flgLoading[5]==='error'}"></rtl-channel-liquidity-info>
<span fxLayout="column" fxFlex="100" *ngSwitchCase="'transactions'"> <span fxLayout="column" fxFlex="100" fxLayoutAlign="space-between start" *ngSwitchCase="'transactions'">
<mat-tab-group fxLayout="column" fxFlex="100"> <mat-tab-group fxLayout="column" class="w-100 dashboard-tabs-group">
<mat-tab label="Receive"><rtl-lightning-invoices class="h-100" [showDetails]="false"></rtl-lightning-invoices></mat-tab> <mat-tab label="Receive"><rtl-lightning-invoices class="h-100" [showDetails]="false"></rtl-lightning-invoices></mat-tab>
<mat-tab label="Pay"><rtl-lightning-payments [showDetails]="false"></rtl-lightning-payments></mat-tab> <mat-tab label="Pay"><rtl-lightning-payments [showDetails]="false"></rtl-lightning-payments></mat-tab>
<mat-tab [disabled]="true">
<ng-template mat-tab-label>
<button mat-icon-button class="more-button" [matMenuTriggerFor]="menuTransactions" aria-label="Toggle menu" style="max-width: 20px;">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menuTransactions="matMenu" class="dashboard-vert-menu" xPosition="before">
<button mat-menu-item (click)="onNavigateTo(card.link)">Go To {{card.goTo}}</button>
</mat-menu>
</ng-template>
</mat-tab>
</mat-tab-group> </mat-tab-group>
</span> </span>
<h3 *ngSwitchDefault>Error! Unable to find information!</h3> <h3 *ngSwitchDefault>Error! Unable to find information!</h3>

@ -1,10 +1,11 @@
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators'; import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects'; import { Actions } from '@ngrx/effects';
import { faSmile, faFrown } from '@fortawesome/free-regular-svg-icons'; import { faSmile, faFrown } from '@fortawesome/free-regular-svg-icons';
import { faFileDownload, faFileUpload, faChartPie, faBolt, faInfoCircle, faNetworkWired } from '@fortawesome/free-solid-svg-icons'; import { faAngleDoubleDown, faAngleDoubleUp, faChartPie, faBolt, faInfoCircle, faNetworkWired } from '@fortawesome/free-solid-svg-icons';
import { LoggerService } from '../../shared/services/logger.service'; import { LoggerService } from '../../shared/services/logger.service';
import { CommonService } from '../../shared/services/common.service'; import { CommonService } from '../../shared/services/common.service';
@ -22,8 +23,8 @@ import * as RTLActions from '../../store/rtl.actions';
export class HomeComponent implements OnInit, OnDestroy { export class HomeComponent implements OnInit, OnDestroy {
public faSmile = faSmile; public faSmile = faSmile;
public faFrown = faFrown; public faFrown = faFrown;
public faFileDownload = faFileDownload; public faAngleDoubleDown = faAngleDoubleDown;
public faFileUpload = faFileUpload; public faAngleDoubleUp = faAngleDoubleUp;
public faChartPie = faChartPie; public faChartPie = faChartPie;
public faBolt = faBolt; public faBolt = faBolt;
public faInfoCircle = faInfoCircle; public faInfoCircle = faInfoCircle;
@ -49,54 +50,55 @@ export class HomeComponent implements OnInit, OnDestroy {
public screenSize = ''; public screenSize = '';
public operatorCardHeight = '330px'; public operatorCardHeight = '330px';
public merchantCardHeight = '65px'; public merchantCardHeight = '65px';
public sortField = 'Channel Balance';
public flgLoading: Array<Boolean | 'error'> = [true, true, true, true, true, true, true, true]; // 0: Info, 1: Fee, 2: Wallet, 3: Channel, 4: Network public flgLoading: Array<Boolean | 'error'> = [true, true, true, true, true, true, true, true]; // 0: Info, 1: Fee, 2: Wallet, 3: Channel, 4: Network
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions, private commonService: CommonService) { constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions, private commonService: CommonService, private router: Router) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
if(this.screenSize === ScreenSizeEnum.XS) { if(this.screenSize === ScreenSizeEnum.XS) {
this.operatorCards = [ this.operatorCards = [
{ id: 'node', icon: this.faInfoCircle, title: 'Node Information', cols: 10, rows: 1 }, { id: 'node', icon: this.faInfoCircle, title: 'Node Information', cols: 10, rows: 1 },
{ id: 'balance', icon: this.faChartPie, title: 'Balances', cols: 10, rows: 1 }, { id: 'balance', goTo: 'On-Chain', link: '/lnd/onchain', icon: this.faChartPie, title: 'Balances', cols: 10, rows: 1 },
{ id: 'fee', icon: this.faBolt, title: 'Routing Fee Report', cols: 10, rows: 1 }, { id: 'fee', goTo: 'Routing', link: '/lnd/routing', icon: this.faBolt, title: 'Routing Fee Report', cols: 10, rows: 1 },
{ id: 'status', icon: this.faNetworkWired, title: 'Channels', cols: 10, rows: 1 }, { id: 'status', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faNetworkWired, title: 'Channels', cols: 10, rows: 1 },
{ id: 'capacity', icon: this.faNetworkWired, title: 'Channels Capacity', cols: 10, rows: 2 } { id: 'capacity', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faNetworkWired, title: 'Channels Capacity', cols: 10, rows: 2 }
]; ];
this.merchantCards = [ this.merchantCards = [
{ id: 'balance', icon: this.faChartPie, title: 'Balances', cols: 6, rows: 4 }, { id: 'balance', goTo: 'On-Chain', link: '/lnd/onchain', icon: this.faChartPie, title: 'Balances', cols: 6, rows: 4 },
{ id: 'transactions', title: 'Transactions', cols: 6, rows: 4 }, { id: 'transactions', goTo: 'Transactions', link: '/lnd/transactions', title: '', cols: 6, rows: 4 },
{ id: 'inboundLiq', icon: this.faFileDownload, title: 'In-Bound Liquidity', cols: 6, rows: 8 }, { id: 'inboundLiq', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faAngleDoubleDown, title: 'In-Bound Liquidity', cols: 6, rows: 8 },
{ id: 'outboundLiq', icon: this.faFileUpload, title: 'Out-Bound Liquidity', cols: 6, rows: 8 } { id: 'outboundLiq', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faAngleDoubleUp, title: 'Out-Bound Liquidity', cols: 6, rows: 8 }
]; ];
} else if(this.screenSize === ScreenSizeEnum.SM || this.screenSize === ScreenSizeEnum.MD) { } else if(this.screenSize === ScreenSizeEnum.SM || this.screenSize === ScreenSizeEnum.MD) {
this.operatorCards = [ this.operatorCards = [
{ id: 'node', icon: this.faInfoCircle, title: 'Node Information', cols: 5, rows: 1 }, { id: 'node', icon: this.faInfoCircle, title: 'Node Information', cols: 5, rows: 1 },
{ id: 'balance', icon: this.faChartPie, title: 'Balances', cols: 5, rows: 1 }, { id: 'balance', goTo: 'On-Chain', link: '/lnd/onchain', icon: this.faChartPie, title: 'Balances', cols: 5, rows: 1 },
{ id: 'fee', icon: this.faBolt, title: 'Routing Fee Report', cols: 5, rows: 1 }, { id: 'fee', goTo: 'Routing', link: '/lnd/routing', icon: this.faBolt, title: 'Routing Fee Report', cols: 5, rows: 1 },
{ id: 'status', icon: this.faNetworkWired, title: 'Channels', cols: 5, rows: 1 }, { id: 'status', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faNetworkWired, title: 'Channels', cols: 5, rows: 1 },
{ id: 'capacity', icon: this.faNetworkWired, title: 'Channels Capacity', cols: 10, rows: 2 } { id: 'capacity', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faNetworkWired, title: 'Channels Capacity', cols: 10, rows: 2 }
]; ];
this.merchantCards = [ this.merchantCards = [
{ id: 'balance', icon: this.faChartPie, title: 'Balances', cols: 3, rows: 4 }, { id: 'balance', goTo: 'On-Chain', link: '/lnd/onchain', icon: this.faChartPie, title: 'Balances', cols: 3, rows: 4 },
{ id: 'transactions', title: 'Transactions', cols: 3, rows: 4 }, { id: 'transactions', goTo: 'Transactions', link: '/lnd/transactions', title: '', cols: 3, rows: 4 },
{ id: 'inboundLiq', icon: this.faFileDownload, title: 'In-Bound Liquidity', cols: 3, rows: 8 }, { id: 'inboundLiq', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faAngleDoubleDown, title: 'In-Bound Liquidity', cols: 3, rows: 8 },
{ id: 'outboundLiq', icon: this.faFileUpload, title: 'Out-Bound Liquidity', cols: 3, rows: 8 } { id: 'outboundLiq', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faAngleDoubleUp, title: 'Out-Bound Liquidity', cols: 3, rows: 8 }
]; ];
} else { } else {
this.operatorCardHeight = ((window.screen.height - 200) / 2) + 'px'; this.operatorCardHeight = ((window.screen.height - 200) / 2) + 'px';
this.merchantCardHeight = ((window.screen.height - 210) / 10) + 'px'; this.merchantCardHeight = ((window.screen.height - 210) / 10) + 'px';
this.operatorCards = [ this.operatorCards = [
{ id: 'node', icon: this.faInfoCircle, title: 'Node Information', cols: 3, rows: 1 }, { id: 'node', icon: this.faInfoCircle, title: 'Node Information', cols: 3, rows: 1 },
{ id: 'balance', icon: this.faChartPie, title: 'Balances', cols: 3, rows: 1 }, { id: 'balance', goTo: 'On-Chain', link: '/lnd/onchain', icon: this.faChartPie, title: 'Balances', cols: 3, rows: 1 },
{ id: 'capacity', icon: this.faNetworkWired, title: 'Channels Capacity', cols: 4, rows: 2 }, { id: 'capacity', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faNetworkWired, title: 'Channels Capacity', cols: 4, rows: 2 },
{ id: 'fee', icon: this.faBolt, title: 'Routing Fee Report', cols: 3, rows: 1 }, { id: 'fee', goTo: 'Routing', link: '/lnd/routing', icon: this.faBolt, title: 'Routing Fee Report', cols: 3, rows: 1 },
{ id: 'status', icon: this.faNetworkWired, title: 'Channels', cols: 3, rows: 1 } { id: 'status', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faNetworkWired, title: 'Channels', cols: 3, rows: 1 }
]; ];
this.merchantCards = [ this.merchantCards = [
{ id: 'balance', icon: this.faChartPie, title: 'Balances', cols: 2, rows: 5 }, { id: 'balance', goTo: 'On-Chain', link: '/lnd/onchain', icon: this.faChartPie, title: 'Balances', cols: 2, rows: 5 },
{ id: 'inboundLiq', icon: this.faFileDownload, title: 'In-Bound Liquidity', cols: 2, rows: 10 }, { id: 'inboundLiq', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faAngleDoubleDown, title: 'In-Bound Liquidity', cols: 2, rows: 10 },
{ id: 'outboundLiq', icon: this.faFileUpload, title: 'Out-Bound Liquidity', cols: 2, rows: 10 }, { id: 'outboundLiq', goTo: 'Channels', link: '/lnd/peerschannels', icon: this.faAngleDoubleUp, title: 'Out-Bound Liquidity', cols: 2, rows: 10 },
{ id: 'transactions', title: 'Transactions', cols: 2, rows: 5 } { id: 'transactions', goTo: 'Transactions', link: '/lnd/transactions', title: '', cols: 2, rows: 5 }
]; ];
} }
} }
@ -157,7 +159,7 @@ export class HomeComponent implements OnInit, OnDestroy {
pending: { channels: rtlStore.numberOfPendingChannels.open.num_channels, capacity: rtlStore.numberOfPendingChannels.open.limbo_balance }, pending: { channels: rtlStore.numberOfPendingChannels.open.num_channels, capacity: rtlStore.numberOfPendingChannels.open.limbo_balance },
closing: { closing: {
channels: rtlStore.numberOfPendingChannels.closing.num_channels + rtlStore.numberOfPendingChannels.force_closing.num_channels + rtlStore.numberOfPendingChannels.waiting_close.num_channels, channels: rtlStore.numberOfPendingChannels.closing.num_channels + rtlStore.numberOfPendingChannels.force_closing.num_channels + rtlStore.numberOfPendingChannels.waiting_close.num_channels,
capacity: rtlStore.numberOfPendingChannels.closing.limbo_balance + rtlStore.numberOfPendingChannels.force_closing.limbo_balance + rtlStore.numberOfPendingChannels.waiting_close.limbo_balance capacity: rtlStore.numberOfPendingChannels.total_limbo_balance
} }
}; };
if (rtlStore.totalLocalBalance >= 0 && rtlStore.totalRemoteBalance >= 0 && this.flgLoading[5] !== 'error') { if (rtlStore.totalLocalBalance >= 0 && rtlStore.totalRemoteBalance >= 0 && this.flgLoading[5] !== 'error') {
@ -192,6 +194,24 @@ export class HomeComponent implements OnInit, OnDestroy {
}); });
} }
onNavigateTo(link: string) {
this.router.navigateByUrl(link);
}
onsortChannelsBy() {
if (this.sortField === 'Channel Balance') {
this.sortField = 'Capacity';
this.allChannelsCapacity = this.allChannels.sort(function (a, b) {
const x = +a.local_balance + +a.remote_balance;
const y = +b.local_balance + +b.remote_balance;
return ((x > y) ? -1 : ((x < y) ? 1 : 0));
});
} else {
this.sortField = 'Channel Balance';
this.allChannelsCapacity = JSON.parse(JSON.stringify(this.commonService.sortDescByKey(this.allChannels, 'balancedness')));
}
}
ngOnDestroy() { ngOnDestroy() {
this.unSubs.forEach(completeSub => { this.unSubs.forEach(completeSub => {
completeSub.next(); completeSub.next();

@ -30,4 +30,4 @@
<rtl-on-chain-transaction-history fxLayout="row" fxFlex="100"></rtl-on-chain-transaction-history> <rtl-on-chain-transaction-history fxLayout="row" fxFlex="100"></rtl-on-chain-transaction-history>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
</div> </div>

@ -1,6 +1,6 @@
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container"> <div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faProjectDiagram" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faMapSigns" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Routing</span> <span class="page-title">Routing</span>
</div> </div>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="start start" class="padding-gap-x"> <div fxLayout="row" fxFlex="100" fxLayoutAlign="start start" class="padding-gap-x">

@ -3,7 +3,7 @@ import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators'; import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects'; import { Actions } from '@ngrx/effects';
import { faProjectDiagram } from '@fortawesome/free-solid-svg-icons'; import { faMapSigns } from '@fortawesome/free-solid-svg-icons';
import { LoggerService } from '../../shared/services/logger.service'; import { LoggerService } from '../../shared/services/logger.service';
@ -17,7 +17,7 @@ import * as fromRTLReducer from '../../store/rtl.reducers';
styleUrls: ['./routing.component.scss'] styleUrls: ['./routing.component.scss']
}) })
export class RoutingComponent implements OnInit, OnDestroy { export class RoutingComponent implements OnInit, OnDestroy {
public faProjectDiagram = faProjectDiagram; public faMapSigns = faMapSigns;
public lastOffsetIndex = 0; public lastOffsetIndex = 0;
public eventsData = []; public eventsData = [];
public today = new Date(Date.now()); public today = new Date(Date.now());

@ -478,6 +478,7 @@ export class LNDEffects implements OnDestroy {
this.logger.info(channels); this.logger.info(channels);
let pendingChannels: PendingChannelsGroup = { open: {num_channels: 0, limbo_balance: 0}, closing: {num_channels: 0, limbo_balance: 0}, force_closing: {num_channels: 0, limbo_balance: 0}, waiting_close: {num_channels: 0, limbo_balance: 0}, total_channels: 0, total_limbo_balance: 0}; let pendingChannels: PendingChannelsGroup = { open: {num_channels: 0, limbo_balance: 0}, closing: {num_channels: 0, limbo_balance: 0}, force_closing: {num_channels: 0, limbo_balance: 0}, waiting_close: {num_channels: 0, limbo_balance: 0}, total_channels: 0, total_limbo_balance: 0};
if (channels) { if (channels) {
pendingChannels.total_limbo_balance = channels.total_limbo_balance;
if (channels.pending_closing_channels) { if (channels.pending_closing_channels) {
pendingChannels.closing.num_channels = channels.pending_closing_channels.length; pendingChannels.closing.num_channels = channels.pending_closing_channels.length;
pendingChannels.total_channels = pendingChannels.total_channels + channels.pending_closing_channels.length; pendingChannels.total_channels = pendingChannels.total_channels + channels.pending_closing_channels.length;

@ -1,13 +1,17 @@
<div fxLayout="column" fxFlex="100" class="overflow-x-hidden"> <div fxLayout="column" fxFlex="100" class="overflow-x-hidden">
<div fxLayout="column" fxLayoutAlign="start stretch" class="settings-container page-sub-title-container mt-1"> <div fxLayout="column" fxLayoutAlign="start stretch" class="settings-container page-sub-title-container mt-1">
<div fxFlex="100" class="mb-2"> <div fxFlex="100" class="mb-1">
<fa-icon [icon]="faWrench" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faWrench" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Node Layout</span> <span class="page-title">Node Layout</span>
</div> </div>
<div fxFlex="100" class="alert alert-info">
<fa-icon [icon]="faInfoCircle" class="mr-1"></fa-icon>
<span>Application layout will be tailored based upon user persona.</span>
</div>
<div fxLayout="column" fxLayout.gt-sm="row" fxFlex="100" fxLayoutAlign="space-between stretch"> <div fxLayout="column" fxLayout.gt-sm="row" fxFlex="100" fxLayoutAlign="space-between stretch">
<mat-form-field fxFlex="32" fxLayoutAlign="start end"> <mat-form-field fxFlex="32" fxLayoutAlign="start end">
<mat-label>User Persona</mat-label> <mat-label>User Persona</mat-label>
<mat-select [(ngModel)]="selNode.settings.userPersona" tabindex="1" required name="userPersona"> <mat-select [(ngModel)]="selNode.settings.userPersona" tabindex="1" name="userPersona">
<mat-option *ngFor="let userPersona of userPersonas" [value]="userPersona"> <mat-option *ngFor="let userPersona of userPersonas" [value]="userPersona">
{{userPersona | titlecase}} {{userPersona | titlecase}}
</mat-option> </mat-option>
@ -15,7 +19,7 @@
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="32" fxLayoutAlign="start end"> <mat-form-field fxFlex="32" fxLayoutAlign="start end">
<mat-label>Currency Unit</mat-label> <mat-label>Currency Unit</mat-label>
<mat-select [(ngModel)]="selNode.settings.currencyUnit" (selectionChange)="onCurrencyChange($event)" tabindex="1" required name="currencyUnit"> <mat-select [(ngModel)]="selNode.settings.currencyUnit" (selectionChange)="onCurrencyChange($event)" tabindex="1" name="currencyUnit">
<mat-option *ngFor="let currencyUnit of currencyUnits" [value]="currencyUnit.id"> <mat-option *ngFor="let currencyUnit of currencyUnits" [value]="currencyUnit.id">
{{currencyUnit.id}} {{currencyUnit.id}}
</mat-option> </mat-option>
@ -23,17 +27,13 @@
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="32" fxLayoutAlign="start end" *ngIf="appConfig.nodes.length && appConfig.nodes.length > 1"> <mat-form-field fxFlex="32" fxLayoutAlign="start end" *ngIf="appConfig.nodes.length && appConfig.nodes.length > 1">
<mat-label>Default Node</mat-label> <mat-label>Default Node</mat-label>
<mat-select [(ngModel)]="appConfig.defaultNodeIndex" tabindex="1" required name="defaultNode"> <mat-select [(ngModel)]="appConfig.defaultNodeIndex" tabindex="1" name="defaultNode">
<mat-option *ngFor="let node of appConfig.nodes" [value]="node.index"> <mat-option *ngFor="let node of appConfig.nodes" [value]="node.index">
{{node.lnNode}} ({{node.lnImplementation}}) {{node.lnNode}} ({{node.lnImplementation}})
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
<div fxFlex="100" class="alert alert-info">
<fa-icon [icon]="faInfoCircle" class="mr-1"></fa-icon>
<span>Application layout will be tailored based upon user persona, this will affect the information displayed.</span>
</div>
<div fxLayout="column" fxLayout.gt-sm="row" fxFlex="100" fxLayoutAlign="start stretch" class="mt-1"> <div fxLayout="column" fxLayout.gt-sm="row" fxFlex="100" fxLayoutAlign="start stretch" class="mt-1">
<mat-divider class="w-100"></mat-divider> <mat-divider class="w-100"></mat-divider>
<div fxLayout="column" fxLayoutAlign="space-between stretch" class="settings-container page-sub-title-container mt-1 w-100"> <div fxLayout="column" fxLayoutAlign="space-between stretch" class="settings-container page-sub-title-container mt-1 w-100">
@ -43,7 +43,7 @@
</div> </div>
<div fxLayout="column" fxLayout.gt-xs="row" fxFlex="100" fxLayoutAlign="space-between stretch" fxLayoutAlign.gt-xs="start stretch"> <div fxLayout="column" fxLayout.gt-xs="row" fxFlex="100" fxLayoutAlign="space-between stretch" fxLayoutAlign.gt-xs="start stretch">
<div fxFlex.gt-xs="20" fxFlex.gt-md="15" fxLayout="column" fxLayoutAlign="space-between stretch"> <div fxFlex.gt-xs="20" fxFlex.gt-md="15" fxLayout="column" fxLayoutAlign="space-between stretch">
<h4>Theme</h4> <h4>Mode</h4>
<mat-radio-group color="primary" [(ngModel)]="selectedThemeMode" (change)="chooseThemeMode()"> <mat-radio-group color="primary" [(ngModel)]="selectedThemeMode" (change)="chooseThemeMode()">
<mat-radio-button *ngFor="let themeMode of themeModes" [value]="themeMode" [ngClass]="{'mr-4': screenSize === screenSizeEnum.XS || screenSize === screenSizeEnum.SM}">{{themeMode.name}} <mat-radio-button *ngFor="let themeMode of themeModes" [value]="themeMode" [ngClass]="{'mr-4': screenSize === screenSizeEnum.XS || screenSize === screenSizeEnum.SM}">{{themeMode.name}}
</mat-radio-button> </mat-radio-button>
@ -51,11 +51,11 @@
</div> </div>
<div fxLayout="column" fxFlex.gt-xs="20" fxFlex.gt-md="15" fxLayoutAlign="space-between stretch"></div> <div fxLayout="column" fxFlex.gt-xs="20" fxFlex.gt-md="15" fxLayoutAlign="space-between stretch"></div>
<div fxLayout="column" fxFlex.gt-xs="50" fxFlex.gt-md="30" fxLayoutAlign="space-between stretch"> <div fxLayout="column" fxFlex.gt-xs="50" fxFlex.gt-md="30" fxLayoutAlign="space-between stretch">
<h4>Colors</h4> <h4>Themes</h4>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start"> <div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start">
<span *ngFor="let themeColor of themeColors" fxLayout="row"> <span *ngFor="let themeColor of themeColors" fxLayout="row">
<div [class]="themeColor" [ngClass]="{'skin': true, 'selected-color': selectedThemeColor === themeColor}" (click)="changeThemeColor(themeColor)"></div> <div [class]="themeColor.id" [ngClass]="{'skin': true, 'selected-color': selectedThemeColor === themeColor.id}" (click)="changeThemeColor(themeColor.id)"></div>
{{themeColor | titlecase}} {{themeColor.name}}
</span> </span>
</div> </div>
</div> </div>

@ -4,7 +4,7 @@ import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { faWrench, faPaintBrush, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; import { faWrench, faPaintBrush, faInfoCircle } from '@fortawesome/free-solid-svg-icons';
import { CURRENCY_UNITS, UserPersonaEnum, ScreenSizeEnum, FIAT_CURRENCY_UNITS } from '../../../services/consts-enums-functions'; import { CURRENCY_UNITS, UserPersonaEnum, ScreenSizeEnum, FIAT_CURRENCY_UNITS, NODE_SETTINGS } from '../../../services/consts-enums-functions';
import { LightningNode, Settings, RTLConfiguration, GetInfoRoot } from '../../../models/RTLconfig'; import { LightningNode, Settings, RTLConfiguration, GetInfoRoot } from '../../../models/RTLconfig';
import { LoggerService } from '../../../services/logger.service'; import { LoggerService } from '../../../services/logger.service';
import { CommonService } from '../../../services/common.service'; import { CommonService } from '../../../services/common.service';
@ -25,16 +25,16 @@ export class AppSettingsComponent implements OnInit, OnDestroy {
public information: GetInfoRoot = {}; public information: GetInfoRoot = {};
public userPersonas = [UserPersonaEnum.OPERATOR, UserPersonaEnum.MERCHANT]; public userPersonas = [UserPersonaEnum.OPERATOR, UserPersonaEnum.MERCHANT];
public currencyUnits = FIAT_CURRENCY_UNITS; public currencyUnits = FIAT_CURRENCY_UNITS;
public menus = [{id: 'vertical', name: 'Vertical'}, {id: 'horizontal', name: 'Horizontal'}]; public menus = NODE_SETTINGS.menus;
public selectedMenu = {id: 'vertical', name: 'Vertical'}; public selectedMenu = NODE_SETTINGS.menus[0];
public menuTypes = [{id: 'regular', name: 'Regular'}, {id: 'compact', name: 'Compact'}, {id: 'mini', name: 'Mini'}]; public menuTypes = NODE_SETTINGS.menuTypes;
public themeModes = [{id: 'day', name: 'Day'}, {id: 'night', name: 'Night'}]; public themeModes = NODE_SETTINGS.modes;
public themeColors = ['purple', 'teal', 'indigo', 'pink']; public themeColors = NODE_SETTINGS.themes;
public fontSizes = [{id: 1, name: 'Small', class: 'small-font'}, {id: 2, name: 'Regular', class: 'regular-font'}, {id: 3, name: 'Large', class: 'large-font'}]; public fontSizes = NODE_SETTINGS.fontSize;
public selectedMenuType = {id: 'regular', name: 'Regular'}; public selectedMenuType = NODE_SETTINGS.menuTypes[0];
public selectedFontSize = {id: 2, name: 'Regular', class: 'regular-font'}; public selectedFontSize = NODE_SETTINGS.fontSize[1];
public selectedThemeMode = {id: 'day', name: 'Day'}; public selectedThemeMode = NODE_SETTINGS.modes[0];
public selectedThemeColor = 'blue'; public selectedThemeColor = NODE_SETTINGS.themes[0].id;
public currencyUnit = 'BTC'; public currencyUnit = 'BTC';
public smallerCurrencyUnit = 'Sats'; public smallerCurrencyUnit = 'Sats';
public showSettingOption = true; public showSettingOption = true;

@ -1,4 +1,4 @@
import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faArchive, faProjectDiagram, faNetworkWired, faCog, faQuestion, faSearch, faTools, faServer } from '@fortawesome/free-solid-svg-icons'; import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faMapSigns, faQuestion, faSearch, faTools, faServer, faDownload } from '@fortawesome/free-solid-svg-icons';
export const MENU_DATA: MenuRootNode = { export const MENU_DATA: MenuRootNode = {
LNDChildren: [ LNDChildren: [
@ -7,8 +7,8 @@ export const MENU_DATA: MenuRootNode = {
{id: 3, parentId: 0, name: 'Lightning', iconType: 'FA', icon: faBolt, link: '/lnd/peerschannels', children: [ {id: 3, parentId: 0, name: 'Lightning', iconType: 'FA', icon: faBolt, link: '/lnd/peerschannels', children: [
{id: 31, parentId: 3, name: 'Peers/Channels', iconType: 'FA', icon: faUsers, link: '/lnd/peerschannels'}, {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: 32, parentId: 3, name: 'Transactions', iconType: 'FA', icon: faExchangeAlt, link: '/lnd/transactions'},
{id: 33, parentId: 3, name: 'Backup', iconType: 'FA', icon: faArchive, link: '/lnd/backup'}, {id: 33, parentId: 3, name: 'Backup', iconType: 'FA', icon: faDownload, link: '/lnd/backup'},
{id: 34, parentId: 3, name: 'Routing', iconType: 'FA', icon: faProjectDiagram, link: '/lnd/routing'}, {id: 34, parentId: 3, name: 'Routing', iconType: 'FA', icon: faMapSigns, link: '/lnd/routing'},
{id: 35, parentId: 3, name: 'Graph Lookup', iconType: 'FA', icon: faSearch, link: '/lnd/lookups'} {id: 35, parentId: 3, name: 'Graph Lookup', iconType: 'FA', icon: faSearch, link: '/lnd/lookups'}
]}, ]},
{id: 5, parentId: 0, name: 'Node/Network', iconType: 'FA', icon: faServer, link: '/lnd/network'}, {id: 5, parentId: 0, name: 'Node/Network', iconType: 'FA', icon: faServer, link: '/lnd/network'},

@ -35,6 +35,19 @@ export const TRANS_TYPES = [
{id: '2', name: 'Fee'} {id: '2', name: 'Fee'}
]; ];
export const NODE_SETTINGS = {
themes: [
{id: 'purple', name: 'Diogo'},
{id: 'teal', name: 'Sauby'},
{id: 'indigo', name: 'RTL'},
{id: 'pink', name: 'BK'}
],
modes: [{id: 'day', name: 'Day'}, {id: 'night', name: 'Night'}],
fontSize: [{id: 1, name: 'Small', class: 'small-font'}, {id: 2, name: 'Regular', class: 'regular-font'}, {id: 3, name: 'Large', class: 'large-font'}],
menuTypes: [{id: 'regular', name: 'Regular'}, {id: 'compact', name: 'Compact'}, {id: 'mini', name: 'Mini'}],
menus: [{id: 'vertical', name: 'Vertical'}, {id: 'horizontal', name: 'Horizontal'}]
};
export enum UserPersonaEnum { export enum UserPersonaEnum {
OPERATOR = 'operator', OPERATOR = 'operator',
MERCHANT = 'merchant' MERCHANT = 'merchant'

@ -6,7 +6,7 @@
@include mat-core(); @include mat-core();
$blue-primary: mat-palette($mat-blue, 700, 200, A200); $blue-primary: mat-palette($mat-blue, 700, 200, A200);
$blue-accent: mat-palette($mat-pink, A200, A100, A400); $blue-accent: mat-palette($mat-gray, 800, 600, 900);
$blue-accent-night: mat-palette($mat-white, 300, 600, 900); $blue-accent-night: mat-palette($mat-white, 300, 600, 900);
$blue-warn: mat-palette($red-warn, 500); $blue-warn: mat-palette($red-warn, 500);

@ -7,7 +7,7 @@
@include mat-core(); @include mat-core();
$green-primary: mat-palette($green-primary, 500, 300, A200); $green-primary: mat-palette($green-primary, 500, 300, A200);
$green-accent: mat-palette($mat-amber, A200, A100, A700); $green-accent: mat-palette($mat-gray, 800, 600, 900);
$green-accent-night: mat-palette($mat-white, 300, 600, 900); $green-accent-night: mat-palette($mat-white, 300, 600, 900);
$green-warn: mat-palette($red-warn, 500); $green-warn: mat-palette($red-warn, 500);

@ -7,7 +7,7 @@
$indigo-primary: mat-palette($mat-indigo, 500, 200, A200); $indigo-primary: mat-palette($mat-indigo, 500, 200, A200);
$indigo-accent: mat-palette($mat-pink, A200, A100, A400); $indigo-accent: mat-palette($mat-gray, 800, 600, 900);
$indigo-accent-night: mat-palette($mat-white, 300, 600, 900); $indigo-accent-night: mat-palette($mat-white, 300, 600, 900);
$indigo-warn: mat-palette($red-warn, 500); $indigo-warn: mat-palette($red-warn, 500);

@ -6,7 +6,7 @@
@include mat-core(); @include mat-core();
$pink-primary: mat-palette($mat-pink, 500, 300, A200); $pink-primary: mat-palette($mat-pink, 500, 300, A200);
$pink-accent: mat-palette($mat-blue-grey, 700, 500, 900); $pink-accent: mat-palette($mat-gray, 800, 600, 900);
$pink-accent-night: mat-palette($mat-white, 300, 600, 900); $pink-accent-night: mat-palette($mat-white, 300, 600, 900);
$pink-warn: mat-palette($red-warn, 500); $pink-warn: mat-palette($red-warn, 500);

@ -6,7 +6,7 @@
@include mat-core(); @include mat-core();
$teal-primary: mat-palette($mat-teal, 800, 300, A200); $teal-primary: mat-palette($mat-teal, 800, 300, A200);
$teal-accent: mat-palette($mat-amber, A200, A100, A700); $teal-accent: mat-palette($mat-gray, 800, 600, 900);
$teal-accent-night: mat-palette($mat-white, 300, 600, 900); $teal-accent-night: mat-palette($mat-white, 300, 600, 900);
$teal-warn: mat-palette($red-warn, 500); $teal-warn: mat-palette($red-warn, 500);

@ -145,9 +145,22 @@
} }
} }
.mat-progress-bar.this-channel-bar .mat-progress-bar-fill::after {
background-color: mat-color($accent, A200);
}
.mat-progress-bar.this-channel-bar .mat-progress-bar-buffer {
background-color: mat-color($accent, 400);
}
} }
&.day { &.day {
.mat-progress-bar.this-channel-bar .mat-progress-bar-fill::after {
background-color: mat-color($accent, 700);
}
.mat-progress-bar.this-channel-bar .mat-progress-bar-buffer {
background-color: mat-color($accent, 200);
}
.rtl-top-toolbar { .rtl-top-toolbar {
border-bottom: 1px solid white; border-bottom: 1px solid white;
} }
@ -239,7 +252,7 @@
} }
.color-primary { .color-primary {
color: $primary-color; color: $primary-color !important;
} }
.mat-progress-bar-buffer { .mat-progress-bar-buffer {
@ -515,7 +528,7 @@
.dashboard-card { .dashboard-card {
& .dashboard-divider { & .dashboard-divider {
margin-top: 2rem; // margin: 1.5rem 0;
border-top-width: 2px; border-top-width: 2px;
} }
@ -537,6 +550,9 @@
font-size: 130%; font-size: 130%;
font-weight: 700; font-weight: 700;
color: $foreground-secondary-text; color: $foreground-secondary-text;
&.this-channel-capacity {
font-size: 120%;
}
} }
} }

@ -302,6 +302,10 @@ body {
margin-right: 0 !important; margin-right: 0 !important;
} }
.mr-3px {
margin-right: 0.3rem !important;
}
.mr-5px { .mr-5px {
margin-right: 0.5rem !important; margin-right: 0.5rem !important;
} }
@ -921,6 +925,18 @@ table {
.alert { .alert {
margin-bottom: 1rem; margin-bottom: 1rem;
padding: 1.2rem 2rem; padding: 0.6rem 1rem;
border-radius: 4px; border-radius: 4px;
} }
.dashboard-vert-menu.mat-menu-panel {
min-height: 4.8rem;
}
.mat-tab-body-content {
overflow: hidden !important;
}
.dashboard-tabs-group .mat-tab-label {
min-width: 32%;
}

@ -330,6 +330,7 @@ export class RTLEffects implements OnDestroy {
map((postRes: any) => { map((postRes: any) => {
this.logger.info(postRes); this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner()); this.store.dispatch(new RTLActions.CloseSpinner());
console.warn(action.payload.lnNode);
this.initializeNode(action.payload.lnNode, action.payload.isInitialSetup); this.initializeNode(action.payload.lnNode, action.payload.isInitialSetup);
return { type: RTLActions.VOID }; return { type: RTLActions.VOID };
}), }),

Loading…
Cancel
Save