Dashboard with Pie Chart

Dashboard with Pie Chart
pull/260/head
Shahana Farooqui 5 years ago
parent 92b01b1761
commit 9f676f7468

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

@ -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.f3946135b912b44b7ab0.css"></head>
<link rel="stylesheet" href="styles.2854cf815b8f6666c61c.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.bd1f2742607d74fabe48.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.c3537a1c742904e625c2.js"></script></body>
<script src="runtime.32f66eb87b7f21a182be.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.ec8cc621bd3cf505ae93.js"></script></body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
!function(e){function r(r){for(var n,a,i=r[0],f=r[1],c=r[2],p=0,s=[];p<i.length;p++)o[a=i[p]]&&s.push(o[a][0]),o[a]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,c||[]),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:"a7c32a5ae5fa426d06f7",6:"a76fcdaa2f54dbf5d786",7:"642e87ab150b17f6b8d0"}[e]+".js"}(e);var f=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(c);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;f.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",f.name="ChunkLoadError",f.type=n,f.request=u,t[1](f)}o[e]=void 0}};var c=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||[],f=i.push.bind(i);i.push=r,i=i.slice();for(var c=0;c<i.length;c++)r(i[c]);var l=f;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:"e98fe0b31473cd63eb21",7:"bb13bd7e7c6fc23f4ea7"}[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

@ -3,72 +3,98 @@ var common = require('../../common');
var logger = require('../logger');
var options = {};
getAliasForChannel = (channel, channelType) => {
getAliasForChannel = (channel) => {
return new Promise(function(resolve, reject) {
if (undefined === channelType || channelType === 'all') {
options.url = common.getSelLNServerUrl() + '/graph/node/' + channel.remote_pubkey;
} else {
options.url = common.getSelLNServerUrl() + '/graph/node/' + channel.channel.remote_node_pub;
}
options.url = common.getSelLNServerUrl() + '/graph/node/' + channel.remote_pubkey;
request(options).then(function(aliasBody) {
logger.info({fileName: 'Channels', msg: 'Alias: ' + JSON.stringify(aliasBody.node.alias)});
if (undefined === channelType || channelType === 'all') {
channel.remote_alias = aliasBody.node.alias;
resolve(aliasBody.node.alias);
} else {
channel.channel.remote_alias = aliasBody.node.alias;
resolve(aliasBody.node.alias);
}
channel.remote_alias = aliasBody.node.alias;
resolve(aliasBody.node.alias);
})
.catch(err => resolve(''));
});
}
exports.getChannels = (req, res, next) => {
exports.getAllChannels = (req, res, next) => {
options = common.getOptions();
if (undefined === req.params.channelType || req.params.channelType === 'all') {
options.url = common.getSelLNServerUrl() + '/channels';
} else {
options.url = common.getSelLNServerUrl() + '/channels/' + req.params.channelType; // active_only, inactive_only, public_only, private_only, Not Implemented in Frontend yet
}
options.url = common.getSelLNServerUrl() + '/channels';
options.qs = req.query;
request(options).then(function (body) {
let channels = [];
if (undefined === req.params.channelType || req.params.channelType === 'all') {
channels = (undefined === body.channels) ? [] : body.channels;
if(body.channels) {
let channels = body.channels;
Promise.all(
channels.map(channel => {
return getAliasForChannel(channel, req.params.channelType);
return getAliasForChannel(channel);
})
)
.then(function(values) {
logger.info({fileName: 'Channels', msg: 'Channels with Alias: ' + JSON.stringify(body)});
logger.info({fileName: 'Channels', msg: 'All Channels with Alias: ' + JSON.stringify(body)});
body.channels = common.sortAscByKey(body.channels, 'capacity');
res.status(200).json(body);
}).catch(err => {
console.error(err.error);
logger.error({fileName: 'Channels', lineNum: 49, msg: 'Get All Channel Alias: ' + JSON.stringify(err)});
res.status(500).json({
message: 'Fetching Channels Alias Failed!',
error: err.error
});
});
} else {
if (undefined === body.total_limbo_balance) {
body.total_limbo_balance = 0;
body.btc_total_limbo_balance = 0;
} else {
body.btc_total_limbo_balance = common.convertToBTC(body.total_limbo_balance);
}
if (req.params.channelType === 'closed' && body.channels && body.channels.length > 0) {
body.channels.forEach(channel => {
channel.close_type = (undefined === channel.close_type) ? 'COOPERATIVE_CLOSE' : channel.close_type;
});
body.channels = common.sortDescByKey(body.channels, 'close_type');
}
logger.info({fileName: 'Channels', msg: 'Pending/Closed Channels: ' + JSON.stringify(body)});
body.channels = [];
res.status(200).json(body);
}
})
.catch(function (err) {
logger.error({fileName: 'Channels', lineNum: 68, msg: 'Get Channel: ' + JSON.stringify(err)});
logger.error({fileName: 'Channels', lineNum: 68, msg: 'Get All Channel: ' + JSON.stringify(err)});
return res.status(500).json({
message: 'Fetching All Channels Failed!',
error: err.error
});
});
};
exports.getPendingChannels = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/channels/pending';
options.qs = req.query;
request(options).then(function (body) {
let channels = [];
if (undefined === body.total_limbo_balance) {
body.total_limbo_balance = 0;
body.btc_total_limbo_balance = 0;
} else {
body.btc_total_limbo_balance = common.convertToBTC(body.total_limbo_balance);
}
logger.info({fileName: 'Channels', msg: 'Pending Channels: ' + JSON.stringify(body)});
res.status(200).json(body);
})
.catch(function (err) {
logger.error({fileName: 'Channels', lineNum: 68, msg: 'Get Pending Channel: ' + JSON.stringify(err)});
return res.status(500).json({
message: 'Fetching Pending Channels Failed!',
error: err.error
});
});
};
exports.getClosedChannels = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/channels/closed';
options.qs = req.query;
request(options).then(function (body) {
let channels = [];
if (body.channels && body.channels.length > 0) {
body.channels.forEach(channel => {
channel.close_type = (undefined === channel.close_type) ? 'COOPERATIVE_CLOSE' : channel.close_type;
});
body.channels = common.sortDescByKey(body.channels, 'close_type');
}
logger.info({fileName: 'Channels', msg: 'Closed Channels: ' + JSON.stringify(body)});
res.status(200).json(body);
})
.catch(function (err) {
logger.error({fileName: 'Channels', lineNum: 68, msg: 'Get Closed Channel: ' + JSON.stringify(err)});
return res.status(500).json({
message: 'Fetching Channels Failed!',
message: 'Fetching Closed Channels Failed!',
error: err.error
});
});

@ -3,9 +3,10 @@ const express = require("express");
const router = express.Router();
const authCheck = require("../authCheck");
router.get("/", authCheck, ChannelsController.getChannels);
router.get("/", authCheck, ChannelsController.getAllChannels);
router.get("/pending", authCheck, ChannelsController.getPendingChannels);
router.get("/closed", authCheck, ChannelsController.getClosedChannels);
router.post("/", authCheck, ChannelsController.postChannel);
router.get("/:channelType", authCheck, ChannelsController.getChannels);
router.post("/transactions", authCheck, ChannelsController.postTransactions);
router.delete("/:channelPoint", authCheck, ChannelsController.closeChannel);
router.post("/chanPolicy", authCheck, ChannelsController.postChanPolicy);

@ -1,4 +1,4 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="start start">
<!-- <div fxLayout="column" fxFlex="100" fxLayoutAlign="start start">
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-500">Lightning</h4>
<div class="foreground-secondary-text">{{balances.lightning | number}} (Sats)</div>
@ -7,11 +7,55 @@
<h4 fxLayoutAlign="start" class="font-bold-500">On-chain</h4>
<div class="foreground-secondary-text">{{balances.onchain | number}} (Sats)</div>
</div>
<div fxFlex="43" fxLayoutAlign="start start" style="margin-left: -2rem;">
<div fxFlex="43" fxLayoutAlign="start start" style="margin-left: -1.4rem;">
<div *ngIf="flgBalanceUpdated">
<ngx-charts-bar-horizontal
[view]="[360, 80]"
[scheme]="colorScheme"
[results]="totalBalances">
[yAxis]="true"
[showDataLabel]="true"
[tooltipDisabled]="true"
[view]="[360, 80]"
[results]="totalBalances">
</ngx-charts-bar-horizontal>
</div>
</div>
</div> -->
<!-- <div fxLayout="column" fxFlex="40" fxLayoutAlign="start start">
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-500">Lightning</h4>
<div class="foreground-secondary-text">{{balances.lightning | number}} (Sats)</div>
</div>
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-500">On-chain</h4>
<div class="foreground-secondary-text">{{balances.onchain | number}} (Sats)</div>
</div>
<div fxFlex="34" fxLayoutAlign="start start"></div>
</div>
<div fxLayout="column" fxFlex="60" fxLayoutAlign="start start">
<div *ngIf="flgBalanceUpdated">
<ngx-charts-bar-vertical
[xAxis]="true"
[showDataLabel]="true"
[tooltipDisabled]="true"
[view]="[190, 240]"
[results]="totalBalances">
</ngx-charts-bar-vertical>
</div>
</div> -->
<div fxLayout="column" fxFlex="40" fxLayoutAlign="start start">
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-500">Lightning</h4>
<div class="foreground-secondary-text">{{balances.lightning | number}} (Sats)</div>
</div>
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-500">On-chain</h4>
<div class="foreground-secondary-text">{{balances.onchain | number}} (Sats)</div>
</div>
<div fxFlex="34" fxLayoutAlign="start start"></div>
</div>
<div fxLayout="column" fxFlex="60" fxLayoutAlign="start start" *ngIf="flgInfoUpdate">
<ngx-charts-pie-chart class="balances-info-pie-chart" style="margin-top: -2.5rem;"
[explodeSlices]="true"
[view]="[190, 190]"
[results]="totalBalances">
</ngx-charts-pie-chart>
</div>

@ -7,20 +7,18 @@ import { Component, OnChanges, Input } from '@angular/core';
})
export class BalancesInfoComponent implements OnChanges {
@Input() balances = { onchain: 0, lightning: 0 };
@Input() flgInfoUpdate = false;
flgBalanceUpdated = false;
totalBalances = [{'name': 'Lightning ', 'value': 45850609}, {'name': 'On-chain', 'value': 44755091}];
maxBalanceValue = 150;
totalBalances = [{'name': 'Lightning ', 'value': 0}, {'name': 'On-chain', 'value': 0}];
maxBalanceValue = 0;
xAxisLabel = 'Balance';
colorScheme = {domain: ['#FFFFFF']};
constructor() {}
ngOnChanges() {
// this.totalBalances = [{'name': 'Lightning ', 'value': this.balances.lightning}, {'name': 'On-chain', 'value': this.balances.onchain}];
// this.maxBalanceValue = (this.balances.lightning > this.balances.onchain) ? this.balances.lightning : this.balances.onchain;
// Object.assign(this, this.totalBalances);
this.flgBalanceUpdated = true;
console.warn(this.totalBalances);
this.totalBalances = [{'name': 'Lightning ', 'value': this.balances.lightning}, {'name': 'On-chain', 'value': this.balances.onchain}];
this.maxBalanceValue = (this.balances.lightning > this.balances.onchain) ? this.balances.lightning : this.balances.onchain;
Object.assign(this, this.totalBalances);
}
}

@ -8,13 +8,18 @@
<mat-divider class="w-100 dashboard-divider"></mat-divider>
</div>
<div fxLayout="column" fxFlex="92" fxFlex.lt-md="85" fxLayoutAlign="start start" class="channels-capacity-scroll" perfectScrollbar>
<div fxLayout="column" fxFlex="100" class="w-100 mt-2" *ngFor="let channel of allChannels">
<h4>{{(channel.remote_alias || channel.remote_pubkey) | slice:0:24}}{{(channel.remote_alias || channel.remote_pubkey).length > 25 ? '...' : ''}}</h4>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
<mat-hint fxFlex="50" fxLayoutAlign="start center" class="font-size-80"><strong class="font-weight-900">Local:</strong>{{channel.local_balance || 0 | number}} Sats</mat-hint>
<mat-hint fxFlex="50" fxLayoutAlign="end center" class="font-size-80"><strong class="font-weight-900">Remote:</strong>{{channel.remote_balance || 0 | number}} Sats</mat-hint>
<div fxLayout="column" fxFlex="100" class="w-100" *ngIf="allChannels && allChannels.length > 0; else noChannelBlock">
<div *ngFor="let channel of allChannels" class="mt-2">
<h4>{{(channel.remote_alias || channel.remote_pubkey) | slice:0:24}}{{(channel.remote_alias || channel.remote_pubkey).length > 25 ? '...' : ''}}</h4>
<div fxLayout="row" fxLayoutAlign="space-between start" class="w-100">
<mat-hint fxFlex="50" fxLayoutAlign="start center" class="font-size-80"><strong class="font-weight-900">Local:</strong>{{channel.local_balance || 0 | number}} Sats</mat-hint>
<mat-hint fxFlex="50" fxLayoutAlign="end center" class="font-size-80"><strong class="font-weight-900">Remote:</strong>{{channel.remote_balance || 0 | number}} Sats</mat-hint>
</div>
<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>
<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>
<ng-template #noChannelBlock>
<div fxLayout="column" fxFlex="100" class="w-100 mt-2">No channels available.</div>
</ng-template>

@ -1,4 +1,4 @@
<div fxLayout="column" fxFlex="50" fxLayoutAlign="center start">
<div fxLayout="column" fxFlex="60" fxLayoutAlign="center start">
<div fxFlex="33">
<h4 fxLayoutAlign="start" class="font-bold-500">Daily</h4>
<div class="foreground-secondary-text">{{fees?.day_fee_sum | number}} (Sats)</div>
@ -12,4 +12,11 @@
<div class="foreground-secondary-text">{{fees?.month_fee_sum | number}} (Sats)</div>
</div>
</div>
<div fxLayout="column" fxFlex="50" fxLayoutAlign="center center" style="background-color:#afa7d2;height:67%;border-radius: 500px;">Pie Chart</div>
<div fxLayout="column" fxFlex="60" fxLayoutAlign="start start" *ngIf="flgInfoUpdate">
<ngx-charts-gauge class="fee-info-gauge-chart" style="margin-top: -2.5rem;margin-left: -8rem;"
[showText]="false"
[max]="maxFeeValue"
[view]="[300, 300]"
[results]="totalFees">
</ngx-charts-gauge>
</div>

@ -8,9 +8,24 @@ import { Fees } from '../../../shared/models/lndModels';
})
export class FeeInfoComponent implements OnChanges {
@Input() fees: Fees;
@Input() flgInfoUpdate = false;
totalFees = [{'name': 'Monthly', 'value': 0}, {'name': 'Weekly', 'value': 0}, {'name': 'Daily', 'value': 0}];
maxFeeValue = 100;
constructor() {}
ngOnChanges() {}
ngOnChanges() {
if(this.fees.month_fee_sum) {
this.totalFees = [{'name': 'Monthly', 'value': this.fees.month_fee_sum}, {'name': 'Weekly', 'value': this.fees.week_fee_sum}, {'name': 'Daily ', 'value': this.fees.day_fee_sum}];
let e = Math.ceil(Math.log(this.fees.month_fee_sum + 1) / Math.LN10);
let m = Math.pow(10, e - 1);
this.maxFeeValue = Math.ceil(this.fees.month_fee_sum / m) * m || 100;
Object.assign(this, this.totalFees);
} else {
this.totalFees = [{'name': 'Monthly', 'value': 0}, {'name': 'Weekly', 'value': 0}, {'name': 'Daily', 'value': 0}];
this.maxFeeValue = 100;
Object.assign(this, this.totalFees);
}
}
}

@ -20,11 +20,11 @@
</mat-card-header>
<mat-card-content class="dashboard-card-content w-100" fxFlex="95">
<div [ngSwitch]="card.id" fxLayout="column" fxFlex="100">
<rtl-node-info fxFlex="100" *ngSwitchCase="'node'" [information]="information"></rtl-node-info>
<rtl-balances-info fxFlex="100" *ngSwitchCase="'balance'" [balances]="balances"></rtl-balances-info>
<rtl-channel-capacity-info fxFlex="100" *ngSwitchCase="'capacity'" [channelBalances]="channelBalances" [allChannels]="allChannels"></rtl-channel-capacity-info>
<rtl-fee-info fxFlex="100" *ngSwitchCase="'fee'" [fees]="fees"></rtl-fee-info>
<rtl-channel-status-info fxFlex="100" *ngSwitchCase="'status'" [channelsStatus]="channelsStatus"></rtl-channel-status-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'" [flgInfoUpdate]="flgChildInfoUpdated" [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]="allChannels" [ngClass]="{'error-border': flgLoading[5]==='error'}"></rtl-channel-capacity-info>
<rtl-fee-info fxFlex="100" *ngSwitchCase="'fee'" [flgInfoUpdate]="flgChildInfoUpdated" [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>
<h3 *ngSwitchDefault>Error! Unable to find information!</h3>
</div>
</mat-card-content>

@ -2,14 +2,16 @@ import { Component, OnInit, OnDestroy } from '@angular/core';
import { map } from 'rxjs/operators';
import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
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 { LoggerService } from '../../shared/services/logger.service';
import { ChannelsStatus, GetInfo, Fees, Peer } from '../../shared/models/lndModels';
import { SelNodeChild } from '../../shared/models/RTLconfig';
import * as fromRTLReducer from '../../store/rtl.reducers';
import * as RTLActions from '../../store/rtl.actions';
@Component({
selector: 'rtl-home',
@ -18,14 +20,15 @@ import * as fromRTLReducer from '../../store/rtl.reducers';
})
export class HomeComponent implements OnInit, OnDestroy {
public faSmile = faSmile;
public flgChildInfoUpdated = false;
public activeChannels = 0;
public inactiveChannels = 0;
public pendingChannels = 0;
public channelBalances = {localBalance: -1, remoteBalance: -1};
public channelBalances = {localBalance: 0, remoteBalance: 0};
public selNode: SelNodeChild = {};
public fees: Fees;
public information: GetInfo = {};
public balances = { onchain: -1, lightning: -1 };
public balances = { onchain: 0, lightning: 0 };
public allChannels = [];
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()];
@ -53,8 +56,7 @@ export class HomeComponent implements OnInit, OnDestroy {
})
);
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private breakpointObserver: BreakpointObserver) {}
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions, private breakpointObserver: BreakpointObserver) {}
ngOnInit() {
this.store.select('lnd')
@ -75,6 +77,8 @@ export class HomeComponent implements OnInit, OnDestroy {
}
if (effectsErr.action === 'FetchChannels/all') {
this.flgLoading[5] = 'error';
}
if (effectsErr.action === 'FetchChannels/pending') {
this.flgLoading[6] = 'error';
}
});
@ -88,18 +92,18 @@ export class HomeComponent implements OnInit, OnDestroy {
if (this.flgLoading[1] !== 'error') {
this.flgLoading[1] = (undefined !== this.fees.day_fee_sum) ? false : true;
}
this.balances.onchain = rtlStore.blockchainBalance.total_balance;
this.balances.onchain = (+rtlStore.blockchainBalance.total_balance >= 0) ? +rtlStore.blockchainBalance.total_balance : 0;
if (this.flgLoading[2] !== 'error') {
this.flgLoading[2] = (this.balances.onchain >= 0) ? false : true;
this.flgLoading[2] = false;
}
if (rtlStore.totalLocalBalance >= 0 && rtlStore.totalRemoteBalance >= 0) {
this.channelBalances = { localBalance: rtlStore.totalLocalBalance, remoteBalance: rtlStore.totalRemoteBalance };
this.balances.lightning = rtlStore.totalLocalBalance;
if (this.flgLoading[5] !== 'error') {
this.flgLoading[5] = false;
}
this.channelBalances = { localBalance: rtlStore.totalLocalBalance, remoteBalance: rtlStore.totalRemoteBalance };
this.balances.lightning = rtlStore.totalLocalBalance;
if (this.flgLoading[5] !== 'error') {
this.flgLoading[5] = false;
}
this.balances = Object.assign({}, this.balances);
this.activeChannels = rtlStore.numberOfActiveChannels;
this.inactiveChannels = rtlStore.numberOfInactiveChannels;
this.pendingChannels = (undefined !== rtlStore.pendingChannels.pending_open_channels) ? rtlStore.pendingChannels.pending_open_channels.length : 0;
@ -112,12 +116,22 @@ export class HomeComponent implements OnInit, OnDestroy {
pending: { channels: this.pendingChannels, capacity: rtlStore.pendingChannels.total_limbo_balance },
closed: { channels: (rtlStore.closedChannels && rtlStore.closedChannels.length) ? rtlStore.closedChannels.length : 0, capacity: 0 }
};
if (rtlStore.totalLocalBalance >= 0 && rtlStore.totalRemoteBalance >= 0 && this.flgLoading[6] !== 'error') {
this.flgLoading[6] = false;
if (rtlStore.totalLocalBalance >= 0 && rtlStore.totalRemoteBalance >= 0 && this.flgLoading[5] !== 'error') {
this.flgLoading[5] = false;
}
this.allChannels = rtlStore.allChannels.filter(channel => channel.active === true);
this.logger.info(rtlStore);
});
this.actions$.pipe(takeUntil(this.unSubs[2]),
filter((action) => action.type === RTLActions.FETCH_FEES || action.type === RTLActions.SET_FEES))
.subscribe(action => {
if(action.type === RTLActions.FETCH_FEES) {
this.flgChildInfoUpdated = false;
}
if(action.type === RTLActions.SET_FEES) {
this.flgChildInfoUpdated = true;
}
});
}
ngOnDestroy() {

@ -14,7 +14,6 @@ export class NodeInfoComponent implements OnChanges {
constructor(private commonService: CommonService) { }
ngOnChanges() {
console.warn(this.information);
if(this.information && this.information.chains && this.information.chains.length > 0) {
this.chains = [''];
this.information.chains.forEach(chain => {

@ -71,8 +71,8 @@ export class ChannelBackupTableComponent implements OnInit, OnDestroy {
this.actions$
.pipe(
takeUntil(this.unSubs[1]),
filter((action) => action.type === RTLActions.SET_CHANNELS)
).subscribe((setchannels: RTLActions.SetChannels) => {
filter((action) => action.type === RTLActions.SET_ALL_CHANNELS)
).subscribe((setchannels: RTLActions.SetAllChannels) => {
this.selChannel = undefined;
});
}

@ -59,7 +59,7 @@ export class ChannelClosedTableComponent implements OnInit, OnDestroy {
ngOnInit() {
this.actions$.pipe(takeUntil(this.unsub[2]), filter((action) => action.type === RTLActions.RESET_LND_STORE)).subscribe((resetLndStore: RTLActions.ResetLNDStore) => {
this.store.dispatch(new RTLActions.FetchChannels({routeParam: 'closed'}));
this.store.dispatch(new RTLActions.FetchClosedChannels());
});
this.store.select('lnd')
.pipe(takeUntil(this.unsub[0]))

@ -231,11 +231,10 @@ export class LNDEffects implements OnDestroy {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.FetchBalance('blockchain'));
this.store.dispatch(new RTLActions.FetchChannels({ routeParam: 'all' }));
this.store.dispatch(new RTLActions.FetchAllChannels());
this.store.dispatch(new RTLActions.BackupChannels({ channelPoint: 'ALL', showMessage: 'Channel Added Successfully!' }));
return {
type: RTLActions.FETCH_CHANNELS,
payload: { routeParam: 'pending', channelStatus: '' }
type: RTLActions.FETCH_PENDING_CHANNELS
};
}),
catchError((err: any) => {
@ -258,8 +257,7 @@ export class LNDEffects implements OnDestroy {
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Channel Updated', titleMessage: 'Channel Updated Successfully!' }}));
return {
type: RTLActions.FETCH_CHANNELS,
payload: { routeParam: 'all', channelStatus: '' }
type: RTLActions.FETCH_ALL_CHANNELS
};
}),
catchError((err: any) => {
@ -281,11 +279,11 @@ export class LNDEffects implements OnDestroy {
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.FetchBalance('channels'));
this.store.dispatch(new RTLActions.FetchBalance('blockchain'));
this.store.dispatch(new RTLActions.FetchChannels({ routeParam: 'all' }));
this.store.dispatch(new RTLActions.FetchAllChannels());
if (action.payload.forcibly) {
this.store.dispatch(new RTLActions.FetchChannels({ routeParam: 'pending' }));
this.store.dispatch(new RTLActions.FetchPendingChannels());
} else {
this.store.dispatch(new RTLActions.FetchChannels({ routeParam: 'closed' }));
this.store.dispatch(new RTLActions.FetchClosedChannels());
}
this.store.dispatch(new RTLActions.BackupChannels({ channelPoint: 'ALL', showMessage: 'Channel Closed Successfully!' }));
return {
@ -444,50 +442,82 @@ export class LNDEffects implements OnDestroy {
));
@Effect()
channelsFetch = this.actions$.pipe(
ofType(RTLActions.FETCH_CHANNELS),
mergeMap((action: RTLActions.FetchChannels) => {
this.store.dispatch(new RTLActions.ClearEffectErrorLnd('FetchChannels/' + action.payload.routeParam));
return this.httpClient.get(this.CHILD_API_URL + environment.CHANNELS_API + '/' + action.payload.routeParam)
channelsAllFetch = this.actions$.pipe(
ofType(RTLActions.FETCH_ALL_CHANNELS),
mergeMap((action: RTLActions.FetchAllChannels) => {
this.store.dispatch(new RTLActions.ClearEffectErrorLnd('FetchChannels/all'));
return this.httpClient.get(this.CHILD_API_URL + environment.CHANNELS_API)
.pipe(
map((channels: any) => {
this.logger.info(channels);
if (action.payload.routeParam === 'pending') {
let pendingChannels = -1;
if (channels) {
pendingChannels = 0;
if (channels.pending_closing_channels) {
pendingChannels = pendingChannels + channels.pending_closing_channels.length;
}
if (channels.pending_force_closing_channels) {
pendingChannels = pendingChannels + channels.pending_force_closing_channels.length;
}
if (channels.pending_open_channels) {
pendingChannels = pendingChannels + channels.pending_open_channels.length;
}
if (channels.waiting_close_channels) {
pendingChannels = pendingChannels + channels.waiting_close_channels.length;
}
return {
type: RTLActions.SET_ALL_CHANNELS,
payload: (channels && channels.channels && channels.channels.length > 0) ? channels.channels : []
};
},
catchError((err: any) => {
this.handleErrorWithoutAlert('FetchChannels/all', err);
return of({type: RTLActions.VOID});
})
));
}
));
@Effect()
channelsPendingFetch = this.actions$.pipe(
ofType(RTLActions.FETCH_PENDING_CHANNELS),
mergeMap((action: RTLActions.FetchPendingChannels) => {
this.store.dispatch(new RTLActions.ClearEffectErrorLnd('FetchChannels/pending'));
return this.httpClient.get(this.CHILD_API_URL + environment.CHANNELS_API + '/pending')
.pipe(
map((channels: any) => {
this.logger.info(channels);
let pendingChannels = -1;
if (channels) {
pendingChannels = 0;
if (channels.pending_closing_channels) {
pendingChannels = pendingChannels + channels.pending_closing_channels.length;
}
if (channels.pending_force_closing_channels) {
pendingChannels = pendingChannels + channels.pending_force_closing_channels.length;
}
if (channels.pending_open_channels) {
pendingChannels = pendingChannels + channels.pending_open_channels.length;
}
if (channels.waiting_close_channels) {
pendingChannels = pendingChannels + channels.waiting_close_channels.length;
}
this.store.dispatch(new RTLActions.SetNodePendingChannelsData(pendingChannels));
return {
type: RTLActions.SET_PENDING_CHANNELS,
payload: channels ? { channels: channels, pendingChannels: pendingChannels } : {channels: {}, pendingChannels: pendingChannels}
};
} else if (action.payload.routeParam === 'closed') {
return {
type: RTLActions.SET_CLOSED_CHANNELS,
payload: (channels && channels.channels && channels.channels.length > 0) ? channels.channels : []
};
} else if (action.payload.routeParam === 'all') {
return {
type: RTLActions.SET_CHANNELS,
payload: (channels && channels.channels && channels.channels.length > 0) ? channels.channels : []
};
}
this.store.dispatch(new RTLActions.SetNodePendingChannelsData(pendingChannels));
return {
type: RTLActions.SET_PENDING_CHANNELS,
payload: channels ? { channels: channels, pendingChannels: pendingChannels } : {channels: {}, pendingChannels: pendingChannels}
};
},
catchError((err: any) => {
this.handleErrorWithoutAlert('FetchChannels/pending', err);
return of({type: RTLActions.VOID});
})
));
}
));
@Effect()
channelsClosedFetch = this.actions$.pipe(
ofType(RTLActions.FETCH_CLOSED_CHANNELS),
mergeMap((action: RTLActions.FetchClosedChannels) => {
this.store.dispatch(new RTLActions.ClearEffectErrorLnd('FetchChannels/closed'));
return this.httpClient.get(this.CHILD_API_URL + environment.CHANNELS_API + '/closed')
.pipe(
map((channels: any) => {
this.logger.info(channels);
return {
type: RTLActions.SET_CLOSED_CHANNELS,
payload: (channels && channels.channels && channels.channels.length > 0) ? channels.channels : []
};
},
catchError((err: any) => {
this.handleErrorWithoutAlert('FetchChannels/' + action.payload.routeParam, err);
this.handleErrorWithoutAlert('FetchChannels/closed', err);
return of({type: RTLActions.VOID});
})
));
@ -626,7 +656,7 @@ export class LNDEffects implements OnDestroy {
titleMessage: 'Payment Sent Successfully!',
message: msg
}}));
this.store.dispatch(new RTLActions.FetchChannels({ routeParam: 'all' }));
this.store.dispatch(new RTLActions.FetchAllChannels());
this.store.dispatch(new RTLActions.FetchBalance('channels'));
this.store.dispatch(new RTLActions.FetchPayments());
return {
@ -1047,9 +1077,9 @@ export class LNDEffects implements OnDestroy {
this.store.dispatch(new RTLActions.FetchPeers());
this.store.dispatch(new RTLActions.FetchBalance('channels'));
this.store.dispatch(new RTLActions.FetchNetwork());
this.store.dispatch(new RTLActions.FetchChannels({routeParam: 'all'}));
this.store.dispatch(new RTLActions.FetchChannels({routeParam: 'pending'}));
this.store.dispatch(new RTLActions.FetchChannels({routeParam: 'closed'}));
this.store.dispatch(new RTLActions.FetchAllChannels());
this.store.dispatch(new RTLActions.FetchPendingChannels());
this.store.dispatch(new RTLActions.FetchClosedChannels());
this.store.dispatch(new RTLActions.FetchInvoices({num_max_invoices: 10, reversed: true}));
this.store.dispatch(new RTLActions.FetchPayments());
let newRoute = this.location.path();

@ -46,10 +46,10 @@ export const initLNDState: LNDState = {
numberOfActiveChannels: 0,
numberOfInactiveChannels: 0,
numberOfPendingChannels: -1,
totalCapacityActive: -1,
totalCapacityInactive: -1,
totalLocalBalance: -1,
totalRemoteBalance: -1,
totalCapacityActive: 0,
totalCapacityInactive: 0,
totalLocalBalance: 0,
totalRemoteBalance: 0,
totalInvoices: -1,
transactions: [],
payments: [],
@ -136,7 +136,7 @@ export function LNDReducer(state = initLNDState, action: RTLActions.RTLActions)
pendingChannels: action.payload.channels,
numberOfPendingChannels: action.payload.pendingChannels,
};
case RTLActions.SET_CHANNELS:
case RTLActions.SET_ALL_CHANNELS:
let localBal = 0, remoteBal = 0, activeChannels = 0, inactiveChannels = 0, totalCapacityActive = 0, totalCapacityInactive = 0;
if (action.payload) {
action.payload.filter(channel => {

@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, Output, EventEmitter } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -14,7 +13,6 @@ import { RTLConfiguration, LightningNode, Settings, GetInfoRoot } from '../../..
import { LoggerService } from '../../../services/logger.service';
import { SessionService } from '../../../services/session.service';
import { GetInfoChain } from '../../../models/lndModels';
import { ShowPubkeyComponent } from '../../../components/data-modal/show-pubkey/show-pubkey.component';
import { MenuChildNode, MENU_DATA } from '../../../models/navMenu';
import { RTLEffects } from '../../../../store/rtl.effects';
@ -52,7 +50,7 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
navMenusLogout = new MatTreeNestedDataSource<MenuChildNode>();
navMenusShowData = new MatTreeNestedDataSource<MenuChildNode>();
constructor(private logger: LoggerService, private sessionService: SessionService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions, private rtlEffects: RTLEffects, private router: Router, private activatedRoute: ActivatedRoute) {
constructor(private logger: LoggerService, private sessionService: SessionService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions, private rtlEffects: RTLEffects) {
this.version = environment.VERSION;
if (MENU_DATA.LNDChildren[MENU_DATA.LNDChildren.length - 1].id === 200) {
MENU_DATA.LNDChildren.pop();

@ -341,4 +341,59 @@
.mat-drawer-inner-container {
overflow: hidden;
}
.balances-info-pie-chart .ngx-charts .ng-star-inserted:nth-child(1) {
& .arc {
fill: mat-color($primary, 400);
}
& .arc.active, .arc:hover {
fill: mat-color($primary, 300);
}
}
.balances-info-pie-chart .ngx-charts .ng-star-inserted:nth-child(2) {
& .arc {
fill: mat-color($primary, 600);
}
& .arc.active, .arc:hover {
fill: mat-color($primary, 700);
}
}
.ngx-charts .arc.active, .ngx-charts .arc:hover {
opacity: 1;
transform: scale(1.03);
-webkit-transition: transform 200ms linear;
transition: transform 200ms linear;
}
.fee-info-gauge-chart .ngx-charts .gauge .ng-star-inserted:nth-child(1) g g:nth-child(2) {
& .arc {
fill: mat-color($primary, 700);
}
& .arc.active, .arc:hover {
fill: mat-color($primary, 900);
}
}
.fee-info-gauge-chart .ngx-charts .gauge .ng-star-inserted:nth-child(2) g g:nth-child(2) {
& .arc {
fill: mat-color($primary, 500);
}
& .arc.active, .arc:hover {
fill: mat-color($primary, 900);
}
}
.fee-info-gauge-chart .ngx-charts .gauge .ng-star-inserted:nth-child(3) g g:nth-child(2) {
& .arc {
fill: mat-color($primary, 300);
}
& .arc.active, .arc:hover {
fill: mat-color($primary, 900);
}
}
}

@ -50,11 +50,13 @@ export const FETCH_BALANCE = 'FETCH_BALANCE';
export const SET_BALANCE = 'SET_BALANCE';
export const FETCH_NETWORK = 'FETCH_NETWORK';
export const SET_NETWORK = 'SET_NETWORK';
export const FETCH_CHANNELS = 'FETCH_CHANNELS';
export const SET_CHANNELS = 'SET_CHANNELS';
export const UPDATE_CHANNELS = 'UPDATE_CHANNELS';
export const FETCH_ALL_CHANNELS = 'FETCH_ALL_CHANNELS';
export const FETCH_PENDING_CHANNELS = 'FETCH_PENDING_CHANNELS';
export const FETCH_CLOSED_CHANNELS = 'FETCH_CLOSED_CHANNELS';
export const SET_ALL_CHANNELS = 'SET_ALL_CHANNELS';
export const SET_PENDING_CHANNELS = 'SET_PENDING_CHANNELS';
export const SET_CLOSED_CHANNELS = 'SET_CLOSED_CHANNELS';
export const UPDATE_CHANNELS = 'UPDATE_CHANNELS';
export const SAVE_NEW_CHANNEL = 'SAVE_NEW_CHANNEL';
export const CLOSE_CHANNEL = 'CLOSE_CHANNEL';
export const REMOVE_CHANNEL = 'REMOVE_CHANNEL';
@ -347,19 +349,17 @@ export class SetNetwork implements Action {
constructor(public payload: NetworkInfo) {}
}
export class FetchChannels implements Action {
readonly type = FETCH_CHANNELS;
constructor(public payload: {routeParam: string}) {}
export class FetchAllChannels implements Action {
readonly type = FETCH_ALL_CHANNELS;
}
export class SetChannels implements Action {
readonly type = SET_CHANNELS;
export class SetAllChannels implements Action {
readonly type = SET_ALL_CHANNELS;
constructor(public payload: Channel[]) {}
}
export class UpdateChannels implements Action {
readonly type = UPDATE_CHANNELS;
constructor(public payload: any) {}
export class FetchPendingChannels implements Action {
readonly type = FETCH_PENDING_CHANNELS;
}
export class SetPendingChannels implements Action {
@ -367,11 +367,20 @@ export class SetPendingChannels implements Action {
constructor(public payload: {channels: PendingChannels, pendingChannels: number}) {}
}
export class FetchClosedChannels implements Action {
readonly type = FETCH_CLOSED_CHANNELS;
}
export class SetClosedChannels implements Action {
readonly type = SET_CLOSED_CHANNELS;
constructor(public payload: ClosedChannel[]) {}
}
export class UpdateChannels implements Action {
readonly type = UPDATE_CHANNELS;
constructor(public payload: any) {}
}
export class SaveNewChannel implements Action {
readonly type = SAVE_NEW_CHANNEL;
constructor(public payload: {selectedPeerPubkey: string, fundingAmount: number, private: boolean, transType: string, transTypeValue: string, spendUnconfirmed: boolean}) {}
@ -824,7 +833,7 @@ export type RTLActions =
FetchFees | SetFees |
FetchBalance | SetBalance |
FetchNetwork | SetNetwork |
FetchChannels | SetChannels | SetPendingChannels | SetClosedChannels | UpdateChannels |
FetchAllChannels | SetAllChannels | FetchPendingChannels | SetPendingChannels | FetchClosedChannels | SetClosedChannels | UpdateChannels |
SaveNewChannel | CloseChannel | RemoveChannel |
BackupChannels | VerifyChannels | BackupChannelsRes | VerifyChannelsRes |
RestoreChannels | RestoreChannelsRes | RestoreChannelsList | SetRestoreChannelsList |

Loading…
Cancel
Save