alert,confirmation,error and other components

alert,confirmation,error and other components
pull/260/head
Shahana Farooqui 5 years ago
parent 3128cfe2b2
commit 259c5de623

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.a5b94b699c491c77372b.css"></head>
<link rel="stylesheet" href="styles.72af09d2752fe39920ba.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.2468dfb427c0917909a7.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.81428553c1b06d7b04eb.js"></script></body>
<script src="runtime.660e7d8ad0ea662c0efc.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.8a8efbaecb55a11ab3f9.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 +0,0 @@
!function(e){function r(r){for(var n,i,a=r[0],f=r[1],c=r[2],p=0,s=[];p<a.length;p++)o[i=a[p]]&&s.push(o[i][0]),o[i]=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,a=1;a<t.length;a++)0!==o[t[a]]&&(n=!1);n&&(u.splice(r--,1),e=i(i.s=t[0]))}return e}var n={},o={0:0},u=[];function i(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,i),t.l=!0,t.exports}i.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,a=document.createElement("script");a.charset="utf-8",a.timeout=120,i.nc&&a.setAttribute("nonce",i.nc),a.src=function(e){return i.p+""+({}[e]||e)+"."+{1:"50859d501eab13ab41b8",6:"94d16dc6ed641f0bae08",7:"1e934fd67e224f7027ff"}[e]+".js"}(e);var f=new Error;u=function(r){a.onerror=a.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:a})}),12e4);a.onerror=a.onload=u,document.head.appendChild(a)}return Promise.all(r)},i.m=e,i.c=n,i.d=function(e,r,t){i.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,r){if(1&r&&(e=i(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(i.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)i.d(t,n,(function(r){return e[r]}).bind(null,n));return t},i.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(r,"a",r),r},i.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},i.p="",i.oe=function(e){throw console.error(e),e};var a=window.webpackJsonp=window.webpackJsonp||[],f=a.push.bind(a);a.push=r,a=a.slice();for(var c=0;c<a.length;c++)r(a[c]);var l=f;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++)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:"50859d501eab13ab41b8",6:"62086d585c2ead0254d2",7:"fdc70b63fa397b86320a"}[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

@ -83,7 +83,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
this.userIdle.onTimeout().pipe(takeUntil(this.unsubs[3])).subscribe(() => {
if (this.sessionService.getItem('token')) {
this.logger.warn('Time limit exceeded for session inactivity.');
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.WARNING,
alertTitle: 'Logging out',
titleMessage: 'Time limit exceeded for session inactivity.'

@ -13,7 +13,7 @@ import { CLEffects } from '../store/cl.effects';
import { RTLEffects } from '../../store/rtl.effects';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
import { AlertTypeEnum } from '../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../shared/services/consts-enums-functions';
@Component({
selector: 'rtl-cl-channels',
@ -118,9 +118,16 @@ export class CLChannelsComponent implements OnInit, OnDestroy {
}
if (channelToUpdate === 'all') {
const titleMsg = 'Updated Values for ALL Channels';
const confirmationMsg = {};
// const confirmationMsg = {};
const confirmationMsg = [[{key: '', value: '', title: '', width: 0, type: DataTypeEnum.NUMBER}]];
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Channels Update', titleMessage: titleMsg, noBtnText: 'Cancel', yesBtnText: 'Update', message: JSON.stringify(confirmationMsg), flgShowInput: true, getInputs: [
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Confirm Channels Update',
titleMessage: titleMsg,
noBtnText: 'Cancel',
yesBtnText: 'Update',
message: confirmationMsg,
flgShowInput: true, getInputs: [
{placeholder: 'Base Fee msat', inputType: 'number', inputValue: 1000},
{placeholder: 'Fee Rate mili msat', inputType: 'number', inputValue: 1, min: 1}
]
@ -153,9 +160,17 @@ export class CLChannelsComponent implements OnInit, OnDestroy {
this.logger.info(this.myChanPolicy);
this.store.dispatch(new RTLActions.CloseSpinner());
const titleMsg = 'Updated Values for Channel: ' + channelToUpdate.channel_id;
const confirmationMsg = {};
// const confirmationMsg = {};
const confirmationMsg = [[{key: '', value: '', title: '', width: 0, type: DataTypeEnum.NUMBER}]];
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Channel Update', titleMessage: titleMsg, noBtnText: 'Cancel', yesBtnText: 'Update', message: JSON.stringify(confirmationMsg), flgShowInput: true, getInputs: [
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Confirm Channel Update',
titleMessage: titleMsg,
noBtnText: 'Cancel',
yesBtnText: 'Update',
message: confirmationMsg,
flgShowInput: true,
getInputs: [
{placeholder: 'Base Fee msat', inputType: 'number', inputValue: (this.myChanPolicy.fee_base_msat === '') ? 0 : this.myChanPolicy.fee_base_msat},
{placeholder: 'Fee Rate mili msat', inputType: 'number', inputValue: this.myChanPolicy.fee_rate_milli_msat, min: 1}
]
@ -180,7 +195,7 @@ export class CLChannelsComponent implements OnInit, OnDestroy {
return;
}
if (channelToClose.state === 'AWAITING_UNILATERAL') {
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.WARNING,
alertTitle: 'Unable to Close Channel',
titleMessage: 'Channel can not be closed when it is in AWAITING UNILATERAL state.'
@ -216,13 +231,14 @@ export class CLChannelsComponent implements OnInit, OnDestroy {
const selChannel = this.channels.data.filter(channel => {
return channel.channel_id === selRow.channel_id;
})[0];
const reorderedChannel = JSON.parse(JSON.stringify(selChannel, [
'channel_id', 'short_channel_id', 'id', 'alias', 'connected', 'private', 'state', 'funding_txid', 'msatoshi_to_us', 'msatoshi_total', 'their_channel_reserve_satoshis', 'our_channel_reserve_satoshis', 'spendable_msatoshi'
] , 2));
const reorderedChannel = [
[{key: 'status', value: selChannel.status, title: 'Status', width: 100, type: DataTypeEnum.NUMBER}]
// 'channel_id', 'short_channel_id', 'id', 'alias', 'connected', 'private', 'state', 'funding_txid', 'msatoshi_to_us', 'msatoshi_total', 'their_channel_reserve_satoshis', 'our_channel_reserve_satoshis', 'spendable_msatoshi'
];
this.store.dispatch(new RTLActions.OpenAlert({width: '75%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Channel Information',
message: JSON.stringify(reorderedChannel)
message: reorderedChannel
}}));
}

@ -10,7 +10,7 @@ import { LoggerService } from '../../shared/services/logger.service';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
import { AlertTypeEnum } from '../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../shared/services/consts-enums-functions';
@Component({
selector: 'rtl-cl-forwarding-history',
@ -82,10 +82,16 @@ export class CLForwardingHistoryComponent implements OnInit, OnDestroy {
const selFEvent = this.forwardingHistoryEvents.data.filter(fhEvent => {
return (fhEvent.received_time === selRow.received_time && fhEvent.in_channel === selRow.in_channel);
})[0];
const reorderedFHEvent = JSON.parse(JSON.stringify(selFEvent, [
'status', 'received_time_str', 'resolved_time_str', 'in_channel', 'out_channel', 'in_msatoshi', 'in_msat', 'out_msatoshi', 'out_msat', 'fee', 'fee_msat', 'payment_hash'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: { type: AlertTypeEnum.INFORMATION, alertTitle: 'Forwarding History', message: JSON.stringify(reorderedFHEvent)}}));
const reorderedFHEvent = [
[{key: 'status', value: selFEvent.status, title: 'Status', width: 100, type: DataTypeEnum.NUMBER}]
// 'status', 'received_time_str', 'resolved_time_str', 'in_channel', 'out_channel', 'in_msatoshi', 'in_msat', 'out_msatoshi', 'out_msat', 'fee', 'fee_msat', 'payment_hash'
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '40%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Forwarding History',
message: reorderedFHEvent
}}));
}
loadForwardingEventsTable(forwardingEvents: ForwardingEventCL[]) {

@ -6,7 +6,7 @@ import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort } from '@angular/material';
import { SelNodeChild } from '../../shared/models/RTLconfig';
import { GetInfoCL, InvoiceCL } from '../../shared/models/clModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, AlertTypeEnum } from '../../shared/services/consts-enums-functions';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, AlertTypeEnum, DataTypeEnum } from '../../shared/services/consts-enums-functions';
import { LoggerService } from '../../shared/services/logger.service';
import { newlyAddedRowAnimation } from '../../shared/animation/row-animation';
@ -119,13 +119,14 @@ export class CLInvoicesComponent implements OnInit, OnDestroy {
const selInvoice = this.invoices.data.filter(invoice => {
return invoice.bolt11 === selRow.bolt11;
})[0];
const reorderedInvoice = JSON.parse(JSON.stringify(selInvoice, [
'status', 'expires_at_str', 'paid_at_str', 'pay_index', 'label', 'bolt11', 'payment_hash', 'msatoshi', 'msatoshi_received', 'description'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const reorderedInvoice = [
[{key: 'status', value: selInvoice.status, title: 'Status', width: 100, type: DataTypeEnum.NUMBER}]
// 'status', 'expires_at_str', 'paid_at_str', 'pay_index', 'label', 'bolt11', 'payment_hash', 'msatoshi', 'msatoshi_received', 'description'
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Invoice Information',
message: JSON.stringify(reorderedInvoice)
message: reorderedInvoice
}}));
}

@ -13,7 +13,7 @@ import { CLEffects } from '../store/cl.effects';
import { RTLEffects } from '../../store/rtl.effects';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
import { AlertTypeEnum } from '../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../shared/services/consts-enums-functions';
@Component({
selector: 'rtl-cl-on-chain',
@ -87,9 +87,16 @@ export class CLOnChainComponent implements OnInit, OnDestroy {
}
onSendFunds() {
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data:
{type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Send Funds', message: JSON.stringify(this.transaction), noBtnText: 'Cancel', yesBtnText: 'Send'}
}));
const reorderedTransaction = [
[{key: 'address', value: this.transaction.address, title: 'Address', width: 100, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Confirm Send Funds',
message: reorderedTransaction,
noBtnText: 'Cancel',
yesBtnText: 'Send'
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[3]))
.subscribe(confirmRes => {

@ -12,7 +12,7 @@ import { LoggerService } from '../../../shared/services/logger.service';
import { CLEffects } from '../../store/cl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { AlertTypeEnum } from '../../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../../shared/services/consts-enums-functions';
@Component({
selector: 'rtl-cl-query-routes',
@ -83,10 +83,15 @@ export class CLQueryRoutesComponent implements OnInit, OnDestroy {
const selRoute = this.qRoutes.data.filter(route => {
return route.id === route.id;
})[0];
const reorderedRoute = JSON.parse(JSON.stringify(selRoute, [
'id', 'alias', 'channel', 'direction', 'msatoshi', 'amount_msat', 'delay'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: { type: AlertTypeEnum.INFORMATION, alertTitle: 'Route Information', message: JSON.stringify(reorderedRoute)}}));
const reorderedRoute = [
[{key: 'id', value: selRoute.id, title: 'ID', width: 100, type: DataTypeEnum.NUMBER}]
// 'id', 'alias', 'channel', 'direction', 'msatoshi', 'amount_msat', 'delay'
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Route Information',
message: reorderedRoute
}}));
}
ngOnDestroy() {

@ -12,7 +12,7 @@ import { CLEffects } from '../../store/cl.effects';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { AlertTypeEnum } from '../../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../../shared/services/consts-enums-functions';
@Component({
selector: 'rtl-cl-payments',
@ -102,12 +102,19 @@ export class CLPaymentsComponent implements OnInit, OnDestroy {
sendPayment() {
this.flgAnimate = true;
this.newlyAddedPayment = this.paymentDecoded.payment_hash;
const reorderedDecodedPayment = [
[{key: 'amount_msat', value: this.paymentDecoded.amount_msat, title: 'Amount (mSat)', width: 100, type: DataTypeEnum.NUMBER}]
];
if (undefined === this.paymentDecoded.msatoshi || this.paymentDecoded.msatoshi === 0) {
const titleMsg = 'It is an open amount invoice. Enter the amount (Sats) to pay.';
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Enter Amount and Confirm Send Payment', titleMessage: titleMsg, message: JSON.stringify(this.paymentDecoded), noBtnText: 'Cancel', yesBtnText: 'Send', flgShowInput: true, getInputs: [
{placeholder: 'Amount (mSats)', inputType: 'number', inputValue: ''}
]
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Enter Amount and Confirm Send Payment',
titleMessage: titleMsg,
message: reorderedDecodedPayment,
noBtnText: 'Cancel',
yesBtnText: 'Send',
flgShowInput: true, getInputs: [{placeholder: 'Amount (mSats)', inputType: 'number', inputValue: ''}]
}}));
this.rtlEffects.closeConfirm
.pipe(take(1))
@ -120,8 +127,16 @@ export class CLPaymentsComponent implements OnInit, OnDestroy {
}
});
} else {
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Send Payment', titleMessage: 'Send Payment', noBtnText: 'Cancel', yesBtnText: 'Send', message: JSON.stringify(this.paymentDecoded)
const reorderedDecodedPayment = [
[{key: 'amount_msat', value: this.paymentDecoded.amount_msat, title: 'Amount (mSat)', width: 100, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '40%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Confirm Send Payment',
titleMessage: 'Send Payment',
noBtnText: 'Cancel',
yesBtnText: 'Send',
message: reorderedDecodedPayment
}}));
this.rtlEffects.closeConfirm
.pipe(take(1))
@ -158,10 +173,15 @@ export class CLPaymentsComponent implements OnInit, OnDestroy {
const selPayment = this.payments.data.filter(payment => {
return payment.payment_hash === selRow.payment_hash;
})[0];
const reorderedPayment = JSON.parse(JSON.stringify(selPayment, [
'id', 'bolt11', 'created_at_str', 'created_at', 'destination', 'status', 'msatoshi', 'msatoshi_sent', 'payment_hash', 'payment_preimage','amount_msat', 'amount_sent_msat'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: { type: AlertTypeEnum.INFORMATION, alertTitle: 'Payment Information', message: JSON.stringify(reorderedPayment)}}));
const reorderedPayment = [
[{key: 'id', value: selPayment.id, title: 'Status', width: 100, type: DataTypeEnum.NUMBER}]
// 'id', 'bolt11', 'created_at_str', 'created_at', 'destination', 'status', 'msatoshi', 'msatoshi_sent', 'payment_hash', 'payment_preimage','amount_msat', 'amount_sent_msat'
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Payment Information',
message: reorderedPayment
}}));
}
applyFilter(selFilter: string) {

@ -9,7 +9,7 @@ import { MatTableDataSource, MatSort } from '@angular/material';
import { PeerCL, GetInfoCL } from '../../shared/models/clModels';
import { DialogConfig } from '../../shared/models/alertData';
import { AlertTypeEnum } from '../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../shared/services/consts-enums-functions';
import { LoggerService } from '../../shared/services/logger.service';
import { newlyAddedRowAnimation } from '../../shared/animation/row-animation';
@ -105,10 +105,15 @@ export class CLPeersComponent implements OnInit, OnDestroy {
const selPeer = this.peers.data.filter(peer => {
return peer.id === selRow.id;
})[0];
const reorderedPeer = JSON.parse(JSON.stringify(selPeer, [
'id', 'alias', 'connected', 'netaddr', 'globalfeatures', 'localfeatures'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: { type: AlertTypeEnum.INFORMATION, alertTitle: 'Peer Information', message: JSON.stringify(reorderedPeer)}}));
const reorderedPeer = [
[{key: 'status', value: selPeer.status, title: 'Status', width: 100, type: DataTypeEnum.NUMBER}]
// 'id', 'alias', 'connected', 'netaddr', 'globalfeatures', 'localfeatures'
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '40%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Peer Information',
message: reorderedPeer
}}));
}
resetData() {

@ -14,7 +14,8 @@ import { GetInfoCL, FeesCL, BalanceCL, LocalRemoteBalanceCL, PaymentCL, FeeRates
import * as fromRTLReducer from '../../store/rtl.reducers';
import * as RTLActions from '../../store/rtl.actions';
import { AlertTypeEnum } from '../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../shared/services/consts-enums-functions';
import { ErrorMessageComponent } from '../../shared/components/data-modal/error-message/error-message.component';
@Injectable()
export class CLEffects implements OnDestroy {
@ -211,7 +212,7 @@ export class CLEffects implements OnDestroy {
map((postRes: any) => {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({ width: '70%', data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Peer Connected', titleMessage: 'Peer Added Successfully!' }}));
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Peer Connected', titleMessage: 'Peer Added Successfully!' }}));
return {
type: RTLActions.SET_PEERS_CL,
payload: (postRes && postRes.length > 0) ? postRes : []
@ -234,7 +235,7 @@ export class CLEffects implements OnDestroy {
map((postRes: any) => {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({ width: '70%', data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Peer Disconnected', titleMessage: 'Peer Disconnected Successfully!' }}));
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Peer Disconnected', titleMessage: 'Peer Disconnected Successfully!' }}));
return {
type: RTLActions.REMOVE_PEER_CL,
payload: { id: action.payload.id }
@ -303,7 +304,7 @@ export class CLEffects implements OnDestroy {
map((postRes: any) => {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({ width: '70%', data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Channel Updated', titleMessage: 'Channel Updated Successfully!' }}));
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Channel Updated', titleMessage: 'Channel Updated Successfully!' }}));
return {
type: RTLActions.FETCH_CHANNELS_CL
};
@ -404,10 +405,17 @@ export class CLEffects implements OnDestroy {
if (sendRes.error) {
this.handleErrorWithAlert('ERROR', 'Send Payment Failed', this.CHILD_API_URL + environment.PAYMENTS_API, { status: sendRes.status, error: sendRes.error.message });
} else {
const reorderedRes = [
[{key: 'status', value: sendRes.status, title: 'Status', width: 100, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenAlert({
width: '70%',
data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Payment Sent', titleMessage: 'Payment Sent Successfully!', message: JSON.stringify(sendRes) }
}));
data: {
type: AlertTypeEnum.SUCCESS,
alertTitle: 'Payment Sent',
titleMessage: 'Payment Sent Successfully!',
message: reorderedRes
}}));
this.store.dispatch(new RTLActions.FetchChannelsCL());
this.store.dispatch(new RTLActions.FetchBalanceCL());
this.store.dispatch(new RTLActions.FetchPaymentsCL());
@ -606,9 +614,17 @@ export class CLEffects implements OnDestroy {
postRes.expires_at_str = new Date(+postRes.expires_at * 1000).toUTCString();
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
const reorderedRes = [
[{key: 'status', value: postRes.bolt11, title: 'Status', width: 100, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenAlert({
width: '70%',
data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Invoice Created', titleMessage: 'Invoice Added Successfully!', message: JSON.stringify(postRes) }
data: {
type: AlertTypeEnum.SUCCESS,
alertTitle: 'Invoice Created',
titleMessage: 'Invoice Added Successfully!',
message: reorderedRes
}
}));
return {
type: RTLActions.FETCH_INVOICES_CL,
@ -732,11 +748,12 @@ export class CLEffects implements OnDestroy {
} else {
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
width: '70%', data: {
width: '55%',
data: {
type: alerType,
alertTitle: alertTitle,
titleMessage: alertTitle,
message: JSON.stringify({ code: err.status, Message: err.error.error, URL: errURL })
message: { code: err.status, message: err.error.error, URL: errURL },
component: ErrorMessageComponent
}
}));
}

@ -1,109 +1,106 @@
<div fxLayout="column" fxLayout.gt-sm="row wrap">
<mat-card fxFlex="100" fxLayoutAlign="start start">
<mat-card-content fxFlex="100" *ngIf="lookupResult">
<mat-list fxLayoutAlign="space-between start">
<mat-list-item fxFlex="30" fxLayoutAlign="start start">Channel Id</mat-list-item>
<mat-list-item fxFlex="68" fxLayoutAlign="start start">{{lookupResult.channel_id}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="space-between start">
<mat-list-item fxFlex="30" fxLayoutAlign="start start">Channel Point</mat-list-item>
<mat-list-item fxFlex="68" fxLayoutAlign="start start" class="word-break">{{lookupResult.chan_point}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="space-between start">
<mat-list-item fxFlex="30" fxLayoutAlign="start start">Last Update</mat-list-item>
<mat-list-item fxFlex="68" fxLayoutAlign="start start">{{lookupResult.last_update_str}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="space-between start">
<mat-list-item fxFlex="30" fxLayoutAlign="start start">Capacity (Sats)</mat-list-item>
<mat-list-item fxFlex="68" fxLayoutAlign="start start">{{lookupResult.capacity | number}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
</mat-card-content>
</mat-card>
</div>
<div fxLayout="column" fxLayoutAlign="space-between start" fxLayout.gt-sm="row wrap" class="mt-2">
<div fxFlex="48">
<mat-card class="custom-card mat-elevation-z12">
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
<mat-card-title class="m-0 pt-2">
<h5 *ngIf="!node1_match">Node 1</h5>
<h5 *ngIf="node1_match">Node 1 (Your Node)</h5>
</mat-card-title>
</mat-card-header>
<mat-card-content class="px-2">
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="100" fxLayoutAlign="start start" class="word-break">{{lookupResult.node1_pub}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Time Lock Delta</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.time_lock_delta}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Min HTLC</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.min_htlc}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Fee Base Msat</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.fee_base_msat}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Fee Rate Milli Msat</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.fee_rate_milli_msat}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Disabled</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.disabled}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
</mat-card-content>
</mat-card>
<div fxLayout="column" *ngIf="lookupResult">
<mat-list fxLayoutAlign="space-between start">
<mat-list-item fxFlex="30" fxLayoutAlign="start start">Channel Id</mat-list-item>
<mat-list-item fxFlex="68" fxLayoutAlign="start start">{{lookupResult.channel_id}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="space-between start">
<mat-list-item fxFlex="30" fxLayoutAlign="start start">Channel Point</mat-list-item>
<mat-list-item fxFlex="68" fxLayoutAlign="start start" class="word-break">{{lookupResult.chan_point}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="space-between start">
<mat-list-item fxFlex="30" fxLayoutAlign="start start">Last Update</mat-list-item>
<mat-list-item fxFlex="68" fxLayoutAlign="start start">{{lookupResult.last_update_str}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="space-between start">
<mat-list-item fxFlex="30" fxLayoutAlign="start start">Capacity (Sats)</mat-list-item>
<mat-list-item fxFlex="68" fxLayoutAlign="start start">{{lookupResult.capacity | number}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<div fxLayout="column" fxLayoutAlign="space-between start" fxLayout.gt-sm="row wrap" class="mt-1">
<div fxFlex="48">
<mat-card class="custom-card">
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
<mat-card-title class="m-0 pt-2">
<h5 *ngIf="!node1_match">Node 1</h5>
<h5 *ngIf="node1_match">Node 1 (Your Node)</h5>
</mat-card-title>
</mat-card-header>
<mat-card-content class="px-2">
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="100" fxLayoutAlign="start start" class="word-break">{{lookupResult.node1_pub}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Time Lock Delta</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.time_lock_delta}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Min HTLC</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.min_htlc}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Fee Base Msat</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.fee_base_msat}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Fee Rate Milli Msat</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.fee_rate_milli_msat}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Disabled</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node1_policy.disabled}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
</mat-card-content>
</mat-card>
</div>
<div fxFlex="48">
<mat-card class="custom-card">
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
<mat-card-title class="m-0 pt-2">
<h5 *ngIf="!node2_match">Node 2</h5>
<h5 *ngIf="node2_match">Node 2 (Your Node)</h5>
</mat-card-title>
</mat-card-header>
<mat-card-content class="px-2">
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="100" fxLayoutAlign="start start" class="word-break">{{lookupResult.node2_pub}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Time Lock Delta</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.time_lock_delta}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Min HTLC</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.min_htlc}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Fee Base Msat</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.fee_base_msat}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Fee Rate Milli Msat</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.fee_rate_milli_msat}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Disabled</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.disabled}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
</mat-card-content>
</mat-card>
</div>
</div>
<div fxFlex="48">
<mat-card class="custom-card mat-elevation-z12">
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
<mat-card-title class="m-0 pt-2">
<h5 *ngIf="!node2_match">Node 2</h5>
<h5 *ngIf="node2_match">Node 2 (Your Node)</h5>
</mat-card-title>
</mat-card-header>
<mat-card-content class="px-2">
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="100" fxLayoutAlign="start start" class="word-break">{{lookupResult.node2_pub}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Time Lock Delta</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.time_lock_delta}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Min HTLC</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.min_htlc}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Fee Base Msat</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.fee_base_msat}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Fee Rate Milli Msat</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.fee_rate_milli_msat}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Disabled</mat-list-item>
<mat-list-item fxFlex="50" fxLayoutAlign="start start">{{lookupResult.node2_policy.disabled}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
</mat-card-content>
</mat-card>
</div>

@ -1,46 +1,37 @@
<div fxLayout="column">
<div class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Lookups</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<form fxLayout="column" fxLayout.gt-sm="row wrap" #form="ngForm">
<mat-form-field fxFlex="20" fxLayoutAlign="start end">
<mat-select [(ngModel)]="selectedField" placeholder="Lookup Field" (selectionChange)="onSelectChange($event)" tabindex="1" required name="lookupField">
<mat-option *ngFor="let lookupField of lookupFields" [value]="lookupField">
<div fxLayout="row" fxLayoutAlign="start end" class="padding-gap-x page-title-container">
<fa-icon [icon]="faSearch" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Lookups</span>
</div>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="start start" class="padding-gap-x">
<mat-card fxLayout="row" fxFlex="100" fxLayoutAlign="start start">
<mat-card-content fxLayout="column" fxFlex="100" fxLayoutAlign="start start" class="card-content-gap">
<form fxFlex="100" fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="w-100" #form="ngForm">
<mat-form-field fxFlex="22" fxLayoutAlign="start end">
<mat-select [(ngModel)]="selectedFieldId" placeholder="Lookup Field" (selectionChange)="onSelectChange($event)" tabindex="1" required name="lookupField">
<mat-option *ngFor="let lookupField of lookupFields" [value]="lookupField.id">
{{lookupField.name}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="50" fxLayoutAlign="start end">
<input matInput name="lookupKey" [placeholder]="selectedField?.placeholder || 'Lookup Key'" (change)="clearLookupValue()" [(ngModel)]="lookupKey" tabindex="2" required>
<input matInput name="lookupKey" [placeholder]="lookupFields[selectedFieldId]?.placeholder || 'Lookup Key'" (change)="clearLookupValue()" [(ngModel)]="lookupKey" tabindex="2" required>
</mat-form-field>
<div fxFlex="12" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="3" type="submit" (click)="onLookup()" [disabled]="!form.valid">Lookup</button>
<div fxFlex="25" fxLayoutAlign="space-between center">
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="3" type="button" (click)="resetData()">Clear</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="4" type="submit" (click)="onLookup()" [disabled]="!form.valid">Lookup</button>
</div>
<div fxFlex="12" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="4" type="reset" (click)="resetData()">Clear</button>
</form>
<div fxFlex="100" fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" *ngIf="lookupValue && flgSetLookupValue" class="w-100 mt-2">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="start center">
<span class="page-title font-bold-500">{{lookupFields[selectedFieldId].name}} Details</span>
</div>
</form>
</mat-card-content>
</mat-card>
</div>
<div class="padding-gap" *ngIf="lookupValue && flgSetLookupValue">
<mat-card [ngClass]="{'error-border': flgLoading[0]==='error'}">
<mat-card-header>
<mat-card-subtitle>
<h2>{{selectedField.name}} Details</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div [ngSwitch]="selectedField.id">
<span *ngSwitchCase="0"><rtl-node-lookup [lookupResult]="lookupValue"></rtl-node-lookup></span>
<span *ngSwitchCase="1"><rtl-channel-lookup [lookupResult]="lookupValue"></rtl-channel-lookup></span>
<span *ngSwitchDefault><h3>Error! Unable to find details!</h3></span>
</div>
<div [ngSwitch]="selectedFieldId" fxLayout="row" fxFlex="100" fxLayoutAlign="start center">
<span fxFlex="100" *ngSwitchCase="0"><rtl-node-lookup [lookupResult]="lookupValue"></rtl-node-lookup></span>
<span fxFlex="100" *ngSwitchCase="1"><rtl-channel-lookup [lookupResult]="lookupValue"></rtl-channel-lookup></span>
<span fxFlex="100" *ngSwitchDefault><h3>Error! Unable to find details!</h3></span>
</div>
</div>
</mat-card-content>
</mat-card>
</div>

@ -3,6 +3,7 @@ import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { faSearch } from '@fortawesome/free-solid-svg-icons';
import { LoggerService } from '../../shared/services/logger.service';
@ -20,12 +21,13 @@ export class LookupsComponent implements OnInit, OnDestroy {
public flgSetLookupValue = false;
public temp: any;
public messageObj = [];
public selectedField = { id: '0', name: 'Node', placeholder: 'Pubkey'};
public selectedFieldId = 0;
public lookupFields = [
{ id: '0', name: 'Node', placeholder: 'Pubkey'},
{ id: '1', name: 'Channel', placeholder: 'Channel ID'}
{ id: 0, name: 'Node', placeholder: 'Pubkey'},
{ id: 1, name: 'Channel', placeholder: 'Channel ID'}
];
public flgLoading: Array<Boolean | 'error'> = [true];
public faSearch = faSearch;
private unSubs: Array<Subject<void>> = [new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions) {}
@ -35,27 +37,28 @@ export class LookupsComponent implements OnInit, OnDestroy {
.pipe(
takeUntil(this.unSubs[0]),
filter((action) => (action.type === RTLActions.SET_LOOKUP || action.type === RTLActions.EFFECT_ERROR_LND))
).subscribe((resLookup: RTLActions.SetLookup) => {
if (resLookup.payload.action === 'Lookup') {
this.flgLoading[0] = 'error';
} else {
).subscribe((resLookup: RTLActions.SetLookup | RTLActions.EffectErrorLnd) => {
if(resLookup.type === RTLActions.SET_LOOKUP) {
this.flgLoading[0] = true;
this.lookupValue = JSON.parse(JSON.stringify(resLookup.payload));
this.flgSetLookupValue = true;
this.logger.info(this.lookupValue);
}
if (resLookup.type === RTLActions.EFFECT_ERROR_LND && resLookup.payload.action === 'Lookup') {
this.flgLoading[0] = 'error';
}
});
}
onLookup() {
this.flgSetLookupValue = false;
this.lookupValue = {};
this.store.dispatch(new RTLActions.OpenSpinner('Searching ' + this.selectedField.name + '...'));
switch (this.selectedField.id) {
case '0':
this.store.dispatch(new RTLActions.OpenSpinner('Searching ' + this.lookupFields[this.selectedFieldId].name + '...'));
switch (this.selectedFieldId) {
case 0:
this.store.dispatch(new RTLActions.PeerLookup(this.lookupKey.trim()));
break;
case '1':
case 1:
this.store.dispatch(new RTLActions.ChannelLookup(this.lookupKey.trim()));
break;
default:
@ -71,8 +74,8 @@ export class LookupsComponent implements OnInit, OnDestroy {
resetData() {
this.flgSetLookupValue = false;
this.selectedFieldId = 0;
this.lookupKey = '';
this.selectedField = { id: '0', name: 'Node', placeholder: 'Pubkey'};
this.lookupValue = {};
this.flgLoading.forEach((flg, i) => {
this.flgLoading[i] = true;

@ -1,56 +1,52 @@
<div fxLayout="column">
<div class="padding-gap">
<mat-card>
<mat-card-content *ngIf="lookupResult">
<div fxLayout="column">
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Alias</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.node.alias}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Pub Key</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.node.pub_key}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Color</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start"><span [ngStyle]="{'background-color': lookupResult.node?.color}">{{lookupResult.node?.color}}</span></mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Last Update</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.node.last_update_str}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Total Capacity (Sats)</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.total_capacity | number}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Number of Channels</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.num_channels | number}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayout="column" fxLayoutAlign="start start">
<mat-divider></mat-divider>
<mat-list-item fxFlex="100" fxLayoutAlign="start start">Addresses</mat-list-item>
<mat-table [dataSource]="lookupResult.node.addresses" matSort class="mat-elevation-z8 overflow-auto">
<ng-container matColumnDef="network">
<mat-header-cell *matHeaderCellDef mat-sort-header>Network</mat-header-cell>
<mat-cell *matCellDef="let address"><div>{{address?.network}}</div></mat-cell>
</ng-container>
<ng-container matColumnDef="addr">
<mat-header-cell *matHeaderCellDef mat-sort-header>Address</mat-header-cell>
<mat-cell *matCellDef="let address"><div>{{address?.addr}}</div></mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns;"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</mat-list>
</div>
</mat-card-content>
</mat-card>
</div>
</div>
<div fxLayout="column" *ngIf="lookupResult">
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Alias</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.node.alias}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Pub Key</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.node.pub_key}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Color</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start"><span [ngStyle]="{'background-color': lookupResult.node?.color}">{{lookupResult.node?.color}}</span></mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Last Update</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.node.last_update_str}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Total Capacity (Sats)</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.total_capacity | number}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayoutAlign="start start">
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Number of Channels</mat-list-item>
<mat-list-item fxFlex="40" fxLayoutAlign="start start">{{lookupResult.num_channels | number}}</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
<mat-list fxLayout="column" fxLayoutAlign="start start">
<mat-divider></mat-divider>
<mat-list-item fxFlex="100" fxLayoutAlign="start start">Addresses</mat-list-item>
<div fxLayout="row" fxLayoutAlign="start center" class="w-100">
<div perfectScrollbar class="table-container" fxFlex="100">
<table mat-table [dataSource]="lookupResult.node.addresses" matSort class="overflow-auto">
<ng-container matColumnDef="network">
<mat-header-cell *matHeaderCellDef mat-sort-header>Network</mat-header-cell>
<mat-cell *matCellDef="let address"><div>{{address?.network}}</div></mat-cell>
</ng-container>
<ng-container matColumnDef="addr">
<mat-header-cell *matHeaderCellDef mat-sort-header>Address</mat-header-cell>
<mat-cell *matCellDef="let address"><div>{{address?.addr}}</div></mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns;"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedColumns;"></mat-row>
</table>
</div>
</div>
</mat-list>
</div>

@ -36,9 +36,9 @@ export class OnChainReceiveComponent implements OnInit, OnDestroy {
this.store.dispatch(new RTLActions.OpenAlert({
width: '58%',
data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Generated Address',
message: JSON.stringify({address: this.newAddress, addressType: this.selectedAddressType.addressTp}),
address: this.newAddress,
addressType: this.selectedAddressType.addressTp,
component: OnChainGeneratedAddressComponent
}
}));

@ -7,7 +7,7 @@ import { MatSnackBar } from '@angular/material/snack-bar';
import { SelNodeChild, GetInfoRoot } from '../../../shared/models/RTLconfig';
import { GetInfo, Balance, ChannelsTransaction, AddressType } from '../../../shared/models/lndModels';
import { CURRENCY_UNITS, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, AlertTypeEnum } from '../../../shared/services/consts-enums-functions';
import { CURRENCY_UNITS, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, AlertTypeEnum, DataTypeEnum } from '../../../shared/services/consts-enums-functions';
import { RTLConfiguration } from '../../../shared/models/RTLconfig';
import { CommonService } from '../../../shared/services/common.service';
import { LoggerService } from '../../../shared/services/logger.service';
@ -16,6 +16,7 @@ import * as sha256 from 'sha256';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { MessageDataField } from '../../../shared/models/alertData';
@Component({
selector: 'rtl-on-chain-send',
@ -99,34 +100,42 @@ export class OnChainSendComponent implements OnInit, OnDestroy {
}
confirmSend() {
const confirmationMsg = {
'BTC Address': this.transaction.address,
};
const confirmationMsg: Array<Array<MessageDataField>> = [
[{key: 'address', value: this.transaction.address, title: 'BTC Address', width: 100}]
];
if (this.sweepAll) {
confirmationMsg['Sweep All'] = 'True';
confirmationMsg.push([{key: 'sweep_all', value: true, title: 'Sweep All', width: 50, type: DataTypeEnum.BOOLEAN}]);
this.transaction.sendAll = true;
} else {
confirmationMsg['Amount (' + this.nodeData.smaller_currency_unit + ')'] = this.transaction.amount;
confirmationMsg.push([{key: 'amount', value: this.transaction.amount, title: 'Amount (' + this.nodeData.smaller_currency_unit + ')', width: 50, type: DataTypeEnum.NUMBER}]);
this.transaction.sendAll = false;
}
if (this.selTransType === '1') {
delete this.transaction.fees;
confirmationMsg['Target Confirmation Blocks'] = this.transaction.blocks;
confirmationMsg[1].push({key: 'target_conf_blocks', value: this.transaction.blocks, title: 'Target Confirmation Blocks', width: 50, type: DataTypeEnum.NUMBER});
} else {
delete this.transaction.blocks;
confirmationMsg['Fee (' + this.nodeData.smaller_currency_unit + '/Byte)'] = this.transaction.fees;
confirmationMsg[1].push({key: 'fees_per_byte', value: this.transaction.fees, title: 'Fee (' + this.nodeData.smaller_currency_unit + '/Byte)', width: 50, type: DataTypeEnum.NUMBER});
}
if (this.sweepAll && !+this.appConfig.sso.rtlSSO) {
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data:
{type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Payment', titleMessage: 'Please authorize to sweep all funds with login password.',
message: JSON.stringify(confirmationMsg), noBtnText: 'Cancel', yesBtnText: 'Authorize And Sweep All Funds',
flgShowInput: true, getInputs: [{placeholder: 'Enter Login Password', inputType: 'password', inputValue: ''}
]}
}));
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '55%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Confirm Payment',
titleMessage: 'Please authorize to sweep all funds with login password.',
message: confirmationMsg,
noBtnText: 'Cancel',
yesBtnText: 'Authorize And Sweep All',
flgShowInput: true,
getInputs: [{placeholder: 'Enter Login Password', inputType: 'password', inputValue: ''}]
}}));
} else {
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data:
{type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Payment', message: JSON.stringify(confirmationMsg), noBtnText: 'Cancel', yesBtnText: 'Send'}
}));
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '55%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Confirm Payment',
message: confirmationMsg,
noBtnText: 'Cancel',
yesBtnText: 'Send'
}}));
}
}

@ -7,7 +7,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { Transaction } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum } from '../../../shared/services/consts-enums-functions';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service';
import { RTLEffects } from '../../../store/rtl.effects';
@ -93,12 +93,21 @@ export class OnChainTransactionHistoryComponent implements OnInit, OnDestroy {
const selTransaction = this.listTransactions.data.filter(transaction => {
return transaction.tx_hash === selRow.tx_hash;
})[0];
const reorderedTransactions = JSON.parse(JSON.stringify(selTransaction, ['dest_addresses', 'block_hash', 'tx_hash', 'time_stamp_str', 'block_height', 'num_confirmations', 'total_fees', 'amount'], 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '35%', data: {
const reorderedTransactions = [
[{key: 'dest_addresses', value: selTransaction.dest_addresses, title: 'Destination Address', width: 100, type: DataTypeEnum.ARRAY}],
[{key: 'block_hash', value: selTransaction.block_hash, title: 'Block Hash', width: 100}],
[{key: 'tx_hash', value: selTransaction.tx_hash, title: 'Transaction Hash', width: 100}],
[{key: 'time_stamp_str', value: selTransaction.time_stamp_str, title: 'Date/Time', width: 50, type: DataTypeEnum.DATE_TIME},
{key: 'block_height', value: selTransaction.block_height, title: 'Block Height', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'num_confirmations', value: selTransaction.num_confirmations, title: 'Number of Confirmations', width: 50, type: DataTypeEnum.NUMBER},
{key: 'total_fees', value: selTransaction.total_fees, title: 'Total Fees (Sats)', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'amount', value: selTransaction.amount, title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER},
{key: 'active', value: selTransaction.active, title: 'Active', width: 50, type: DataTypeEnum.BOOLEAN}]
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '40%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Transaction Information',
message: JSON.stringify(reorderedTransactions),
messageFieldsBreakdown: [1, 1, 1, 2, 3]
message: reorderedTransactions,
}}));
}

@ -12,7 +12,7 @@ import { LoggerService } from '../../../shared/services/logger.service';
import { LNDEffects } from '../../store/lnd.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { AlertTypeEnum } from '../../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../../shared/services/consts-enums-functions';
@Component({
selector: 'rtl-query-routes',
@ -83,10 +83,16 @@ export class QueryRoutesComponent implements OnInit, OnDestroy {
const selHop = this.qrHops.data.filter(hop => {
return hop.hop_sequence === selRow.hop_sequence;
})[0];
const reorderedHop = JSON.parse(JSON.stringify(selHop, [
'hop_sequence', 'pubkey_alias', 'pub_key', 'chan_id', 'chan_capacity', 'expiry', 'amt_to_forward', 'amt_to_forward_msat', 'fee_msat'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: { type: AlertTypeEnum.INFORMATION, alertTitle: 'Route Information', message: JSON.stringify(reorderedHop)}}));
const reorderedHop = [
[{key: 'active', value: selHop.active, title: 'Active', width: 100, type: DataTypeEnum.NUMBER}]
// 'hop_sequence', 'pubkey_alias', 'pub_key', 'chan_id', 'chan_capacity', 'expiry', 'amt_to_forward', 'amt_to_forward_msat', 'fee_msat'
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Route Information',
message: reorderedHop
}}));
}
ngOnDestroy() {

@ -6,7 +6,7 @@ import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort } from '@angular/material';
import { Channel, Peer, GetInfo } from '../../../../shared/models/lndModels';
import { TRANS_TYPES, AlertTypeEnum } from '../../../../shared/services/consts-enums-functions';
import { TRANS_TYPES, AlertTypeEnum, DataTypeEnum } from '../../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../../shared/services/logger.service';
import { LNDEffects } from '../../../store/lnd.effects';
@ -24,57 +24,23 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
public totalBalance = 0;
public selectedPeer = '';
public fundingAmount: number;
public displayedColumns = [];
public channels: any;
public peers: Peer[] = [];
public information: GetInfo = {};
public flgLoading: Array<Boolean | 'error'> = [true];
public selectedFilter = '';
public myChanPolicy: any = {};
public selFilter = '';
public transTypes = TRANS_TYPES;
public selTransType = '0';
public transTypeValue = {blocks: '', fees: ''};
public spendUnconfirmed = false;
public isPrivate = false;
public showAdvanced = false;
public flgSticky = false;
public redirectedWithPeer = false;
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private lndEffects: LNDEffects, private activatedRoute: ActivatedRoute) {
switch (true) {
case (window.innerWidth <= 415):
this.displayedColumns = ['close', 'update', 'active', 'chan_id', 'remote_alias'];
break;
case (window.innerWidth > 415 && window.innerWidth <= 730):
this.displayedColumns = ['close', 'update', 'active', 'chan_id', 'remote_alias', 'capacity'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['close', 'update', 'active', 'chan_id', 'remote_alias', 'capacity', 'local_balance', 'remote_balance'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['close', 'update', 'active', 'chan_id', 'remote_alias', 'capacity', 'local_balance', 'remote_balance', 'total_satoshis_sent',
'total_satoshis_received', 'commit_fee', 'private'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['close', 'update', 'active', 'chan_id', 'remote_pubkey', 'remote_alias', 'capacity', 'local_balance', 'remote_balance',
'total_satoshis_sent', 'total_satoshis_received', 'commit_fee', 'private'];
break;
}
}
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private activatedRoute: ActivatedRoute) {}
ngOnInit() {
this.store.select('lnd')
.pipe(takeUntil(this.unsub[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsLnd.forEach(effectsErr => {
if (effectsErr.action === 'FetchChannels/all') {
this.flgLoading[0] = 'error';
}
});
this.information = rtlStore.information;
this.peers = rtlStore.peers;
this.peers.forEach(peer => {
@ -82,20 +48,9 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
peer.alias = peer.pub_key.substring(0, 15) + '...';
}
});
this.totalBalance = +rtlStore.blockchainBalance.total_balance;
if (undefined !== rtlStore.allChannels) {
this.loadChannelsTable(rtlStore.allChannels);
}
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== rtlStore.allChannels) ? false : true;
}
this.logger.info(rtlStore);
});
this.activatedRoute.paramMap.subscribe(() => {
this.selectedPeer = window.history.state.peer;
this.redirectedWithPeer = (window.history.state.peer) ? true : false;
});
}
onOpenChannel() {
@ -112,129 +67,6 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
}));
}
onChannelUpdate(channelToUpdate: any) {
if (channelToUpdate === 'all') {
const titleMsg = 'Updated Values for ALL Channels';
const confirmationMsg = {};
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Channels Update', titleMessage: titleMsg, noBtnText: 'Cancel', yesBtnText: 'Update', message: JSON.stringify(confirmationMsg), flgShowInput: true, getInputs: [
{placeholder: 'Base Fee msat', inputType: 'number', inputValue: 1000},
{placeholder: 'Fee Rate mili msat', inputType: 'number', inputValue: 1, min: 1},
{placeholder: 'Time Lock Delta', inputType: 'number', inputValue: 144}
]
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[2]))
.subscribe(confirmRes => {
if (confirmRes) {
const base_fee = confirmRes[0].inputValue;
const fee_rate = confirmRes[1].inputValue;
const time_lock_delta = confirmRes[2].inputValue;
this.store.dispatch(new RTLActions.OpenSpinner('Updating Channel Policy...'));
this.store.dispatch(new RTLActions.UpdateChannels({baseFeeMsat: base_fee, feeRate: fee_rate, timeLockDelta: time_lock_delta, chanPoint: 'all'}));
}
});
} else {
this.myChanPolicy = {fee_base_msat: 0, fee_rate_milli_msat: 0, time_lock_delta: 0};
this.store.dispatch(new RTLActions.OpenSpinner('Fetching Channel Policy...'));
this.store.dispatch(new RTLActions.ChannelLookup(channelToUpdate.chan_id.toString()));
this.lndEffects.setLookup
.pipe(takeUntil(this.unsub[3]))
.subscribe(resLookup => {
this.logger.info(resLookup);
if (resLookup.node1_pub === this.information.identity_pubkey) {
this.myChanPolicy = resLookup.node1_policy;
} else if (resLookup.node2_pub === this.information.identity_pubkey) {
this.myChanPolicy = resLookup.node2_policy;
} else {
this.myChanPolicy = {fee_base_msat: 0, fee_rate_milli_msat: 0, time_lock_delta: 0};
}
this.logger.info(this.myChanPolicy);
this.store.dispatch(new RTLActions.CloseSpinner());
const titleMsg = 'Updated Values for Channel Point: ' + channelToUpdate.channel_point;
const confirmationMsg = {};
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Channel Update', titleMessage: titleMsg, noBtnText: 'Cancel', yesBtnText: 'Update', message: JSON.stringify(confirmationMsg), flgShowInput: true, getInputs: [
{placeholder: 'Base Fee msat', inputType: 'number', inputValue: (this.myChanPolicy.fee_base_msat === '') ? 0 : this.myChanPolicy.fee_base_msat},
{placeholder: 'Fee Rate mili msat', inputType: 'number', inputValue: this.myChanPolicy.fee_rate_milli_msat, min: 1},
{placeholder: 'Time Lock Delta', inputType: 'number', inputValue: this.myChanPolicy.time_lock_delta}
]
}}));
});
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[2]))
.subscribe(confirmRes => {
if (confirmRes) {
const base_fee = confirmRes[0].inputValue;
const fee_rate = confirmRes[1].inputValue;
const time_lock_delta = confirmRes[2].inputValue;
this.store.dispatch(new RTLActions.OpenSpinner('Updating Channel Policy...'));
this.store.dispatch(new RTLActions.UpdateChannels({baseFeeMsat: base_fee, feeRate: fee_rate, timeLockDelta: time_lock_delta, chanPoint: channelToUpdate.channel_point}));
}
});
}
this.applyFilter();
}
onChannelClose(channelToClose: Channel) {
this.store.dispatch(new RTLActions.OpenConfirmation({
width: '70%', data: { type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Channel Closing', titleMessage: 'Closing channel: ' + channelToClose.chan_id, noBtnText: 'Cancel', yesBtnText: 'Close Channel'
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[1]))
.subscribe(confirmRes => {
if (confirmRes) {
this.store.dispatch(new RTLActions.OpenSpinner('Closing Channel...'));
this.store.dispatch(new RTLActions.CloseChannel({channelPoint: channelToClose.channel_point, forcibly: !channelToClose.active}));
}
});
}
applyFilter() {
this.selectedFilter = this.selFilter;
this.channels.filter = this.selFilter;
}
onChannelClick(selRow: Channel, event: any) {
const flgCloseClicked =
event.target.className.includes('mat-column-close')
|| event.target.className.includes('mat-column-update')
|| event.target.className.includes('mat-icon');
if (flgCloseClicked) {
return;
}
const selChannel = this.channels.data.filter(channel => {
return channel.chan_id === selRow.chan_id;
})[0];
const reorderedChannel = JSON.parse(JSON.stringify(selChannel, [
'active', 'remote_pubkey', 'remote_alias', 'channel_point', 'chan_id', 'capacity', 'local_balance', 'remote_balance', 'commit_fee', 'commit_weight',
'fee_per_kw', 'unsettled_balance', 'total_satoshis_sent', 'total_satoshis_received', 'num_updates', 'pending_htlcs', 'csv_delay', 'private'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Channel Information',
message: JSON.stringify(reorderedChannel)
}}));
}
loadChannelsTable(channels) {
channels.sort(function(a, b) {
return (a.active === b.active) ? 0 : ((b.active) ? 1 : -1);
});
this.channels = new MatTableDataSource<Channel>([...channels]);
this.channels.sort = this.sort;
this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = ((channel.active) ? 'active' : 'inactive') + (channel.chan_id ? channel.chan_id : '') +
(channel.remote_pubkey ? channel.remote_pubkey : '') + (channel.remote_alias ? channel.remote_alias : '') +
(channel.capacity ? channel.capacity : '') + (channel.local_balance ? channel.local_balance : '') +
(channel.remote_balance ? channel.remote_balance : '') + (channel.total_satoshis_sent ? channel.total_satoshis_sent : '') +
(channel.total_satoshis_received ? channel.total_satoshis_received : '') + (channel.commit_fee ? channel.commit_fee : '') +
(channel.private ? 'private' : 'public');
return newChannel.includes(fltr);
};
this.logger.info(this.channels);
}
resetData() {
this.selectedPeer = '';
this.fundingAmount = 0;
@ -243,7 +75,6 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
this.isPrivate = false;
this.selTransType = '0';
this.transTypeValue = {blocks: '', fees: ''};
this.redirectedWithPeer = false;
}
onShowAdvanced() {

@ -7,7 +7,7 @@ import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { SelNodeChild } from '../../../../../shared/models/RTLconfig';
import { Channel } from '../../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum } from '../../../../../shared/services/consts-enums-functions';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum } from '../../../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../../../shared/services/logger.service';
import * as RTLActions from '../../../../../store/rtl.actions';
@ -95,14 +95,30 @@ export class ChannelBackupTableComponent implements OnInit, OnDestroy {
const selChannel = this.channels.data.filter(channel => {
return channel.chan_id === selRow.chan_id;
})[0];
const reorderedChannel = JSON.parse(JSON.stringify(selChannel, [
'active', 'remote_pubkey', 'remote_alias', 'channel_point', 'chan_id', 'capacity', 'local_balance', 'remote_balance', 'commit_fee', 'commit_weight',
'fee_per_kw', 'unsettled_balance', 'total_satoshis_sent', 'total_satoshis_received', 'num_updates', 'pending_htlcs', 'csv_delay', 'private'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const reorderedChannel = [
[{key: 'remote_alias', value: selChannel.remote_alias, title: 'Peer Alias', width: 40},
{key: 'active', value: selChannel.active, title: 'Active', width: 30, type: DataTypeEnum.BOOLEAN},
{key: 'private', value: selChannel.private, title: 'Private', width: 30, type: DataTypeEnum.BOOLEAN}],
[{key: 'remote_pubkey', value: selChannel.remote_pubkey, title: 'Peer Public Key', width: 100}],
[{key: 'channel_point', value: selChannel.channel_point, title: 'Channel Point', width: 100}],
[{key: 'chan_id', value: selChannel.chan_id, title: 'Channel ID', width: 50},
{key: 'capacity', value: selChannel.capacity, title: 'Capacity', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'local_balance', value: selChannel.local_balance, title: 'Local Balance', width: 50, type: DataTypeEnum.NUMBER},
{key: 'remote_balance', value: selChannel.remote_balance, title: 'Remote Balance', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'commit_fee', value: selChannel.commit_fee, title: 'Commit Fee', width: 50, type: DataTypeEnum.NUMBER},
{key: 'commit_weight', value: selChannel.commit_weight, title: 'Commit Weight', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'fee_per_kw', value: selChannel.fee_per_kw, title: 'Fee/KW', width: 50, type: DataTypeEnum.NUMBER},
{key: 'unsettled_balance', value: selChannel.unsettled_balance, title: 'Unsettled Balance', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'total_satoshis_sent', value: selChannel.total_satoshis_sent, title: 'Total Satoshis Sent', width: 50, type: DataTypeEnum.NUMBER},
{key: 'total_satoshis_received', value: selChannel.total_satoshis_received, title: 'Total Satoshis Received', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'num_updates', value: selChannel.num_updates, title: 'Number of Updates', width: 40, type: DataTypeEnum.NUMBER},
{key: 'pending_htlcs', value: selChannel.pending_htlcs, title: 'Pending HTLCs', width: 30, type: DataTypeEnum.NUMBER},
{key: 'csv_delay', value: selChannel.csv_delay, title: 'CSV Delay', width: 30, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'channel Information',
message: JSON.stringify(reorderedChannel)
message: reorderedChannel
}}));
}

@ -7,7 +7,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { ClosedChannel } from '../../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum } from '../../../../../shared/services/consts-enums-functions';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum } from '../../../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../../../shared/services/logger.service';
import { RTLEffects } from '../../../../../store/rtl.effects';
@ -90,12 +90,21 @@ export class ChannelClosedTableComponent implements OnInit, OnDestroy {
const selChannel = this.closedChannels.data.filter(closedChannel => {
return closedChannel.chan_id === selRow.chan_id;
})[0];
const reorderedChannel = JSON.parse(JSON.stringify(selChannel, ['close_type', 'channel_point', 'chan_id', 'closing_tx_hash', 'remote_pubkey', 'capacity',
'close_height', 'settled_balance', 'time_locked_balance'] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const reorderedChannel = [
[{key: 'close_type', value: selChannel.close_type, title: 'Close Type', width: 40, type: DataTypeEnum.STRING},
{key: 'time_locked_balance', value: selChannel.time_locked_balance, title: 'Time Locked Balance', width: 30, type: DataTypeEnum.NUMBER},
{key: 'settled_balance', value: selChannel.settled_balance, title: 'Settled Balance', width: 30, type: DataTypeEnum.NUMBER}],
[{key: 'remote_pubkey', value: selChannel.remote_pubkey, title: 'Peer Public Key', width: 100}],
[{key: 'channel_point', value: selChannel.channel_point, title: 'Channel Point', width: 100}],
[{key: 'chan_id', value: selChannel.chan_id, title: 'Channel ID', width: 40},
{key: 'capacity', value: selChannel.capacity, title: 'capacity', width: 30, type: DataTypeEnum.NUMBER},
{key: 'close_height', value: selChannel.close_height, title: 'Close Height', width: 30, type: DataTypeEnum.NUMBER}],
[{key: 'closing_tx_hash', value: selChannel.closing_tx_hash, title: 'Closing Transaction Hash', width: 100, type: DataTypeEnum.STRING}]
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Closed Channel Information',
message: JSON.stringify(reorderedChannel)
message: reorderedChannel
}}));
}

@ -26,9 +26,17 @@
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Received ({{information?.smaller_currency_unit}}) </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">{{channel.total_satoshis_received | number}} </span></td>
</ng-container>
<ng-container matColumnDef="local_balance">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Local Balance </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">{{channel.local_balance | number}} </span></td>
</ng-container>
<ng-container matColumnDef="remote_balance">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Remote Balance </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">{{channel.remote_balance | number}} </span></td>
</ng-container>
<ng-container matColumnDef="capacity">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Capacity</th>
<td mat-cell *matCellDef="let channel">
<th mat-header-cell *matHeaderCellDef mat-sort-header class="px-3">Capacity</th>
<td mat-cell *matCellDef="let channel" class="px-3">
<div fxLayout="row">
<mat-hint fxFlex="50" fxLayoutAlign="start center" class="font-size-80"><strong class="font-weight-900">Local: </strong>{{channel.local_balance || 0 | number}} {{information?.smaller_currency_unit}}</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}} {{information?.smaller_currency_unit}}</mat-hint>

@ -1,6 +1,6 @@
.mat-column-remote_alias {
flex: 0 0 28%;
width: 28%;
flex: 0 0 20%;
width: 20%;
& .ellipsis-parent {
display: flex;
max-width: 25rem;
@ -10,14 +10,21 @@
.mat-column-capacity {
padding-left: 3rem;
padding-right: 3rem;
flex: 0 0 40%;
width: 40%;
flex: 0 0 30%;
width: 30%;
}
.mat-column-total_satoshis_sent, .mat-column-total_satoshis_received {
.mat-column-local_balance, .mat-column-remote_balance, .mat-column-total_satoshis_sent, .mat-column-total_satoshis_received {
flex: 0 0 10%;
width: 10%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mat-column-actions {
width: 12rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

@ -5,7 +5,7 @@ import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { Channel, GetInfo } from '../../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum } from '../../../../../shared/services/consts-enums-functions';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum } from '../../../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../../../shared/services/logger.service';
import { LNDEffects } from '../../../../store/lnd.effects';
@ -47,15 +47,15 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'actions'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'capacity', 'actions'];
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'local_balance', 'remote_balance', 'capacity', 'actions'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'capacity', 'actions'];
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'local_balance', 'remote_balance', 'capacity', 'actions'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'capacity', 'actions'];
this.displayedColumns = ['remote_alias', 'total_satoshis_sent', 'total_satoshis_received', 'local_balance', 'remote_balance', 'capacity', 'actions'];
break;
}
}
@ -85,12 +85,19 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
onChannelUpdate(channelToUpdate: any) {
if (channelToUpdate === 'all') {
const titleMsg = 'Updated Values for ALL Channels';
const confirmationMsg = {};
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Channel Update', titleMessage: titleMsg, noBtnText: 'Cancel', yesBtnText: 'Update', message: JSON.stringify(confirmationMsg), flgShowInput: true, getInputs: [
{placeholder: 'Base Fee msat', inputType: 'number', inputValue: 1000},
{placeholder: 'Fee Rate mili msat', inputType: 'number', inputValue: 1, min: 1},
{placeholder: 'Time Lock Delta', inputType: 'number', inputValue: 144}
const confirmationMsg = [];
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '55%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Update Channel',
titleMessage: titleMsg,
noBtnText: 'Cancel',
yesBtnText: 'Update All Channels',
message: confirmationMsg,
flgShowInput: true,
getInputs: [
{placeholder: 'Base Fee (mSat)', inputType: DataTypeEnum.NUMBER.toLowerCase(), inputValue: 1000},
{placeholder: 'Fee Rate (mili mSat)', inputType: DataTypeEnum.NUMBER.toLowerCase(), inputValue: 1, min: 1},
{placeholder: 'Time Lock Delta', inputType: DataTypeEnum.NUMBER.toLowerCase(), inputValue: 144}
]
}}));
this.rtlEffects.closeConfirm
@ -121,13 +128,20 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
}
this.logger.info(this.myChanPolicy);
this.store.dispatch(new RTLActions.CloseSpinner());
const titleMsg = 'Updated Values for Channel Point: ' + channelToUpdate.channel_point;
const confirmationMsg = {};
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Channel Update', titleMessage: titleMsg, noBtnText: 'Cancel', yesBtnText: 'Update', message: JSON.stringify(confirmationMsg), flgShowInput: true, getInputs: [
{placeholder: 'Base Fee msat', inputType: 'number', inputValue: (this.myChanPolicy.fee_base_msat === '') ? 0 : this.myChanPolicy.fee_base_msat},
{placeholder: 'Fee Rate mili msat', inputType: 'number', inputValue: this.myChanPolicy.fee_rate_milli_msat, min: 1},
{placeholder: 'Time Lock Delta', inputType: 'number', inputValue: this.myChanPolicy.time_lock_delta}
const titleMsg = 'Update values for channel point: ' + channelToUpdate.channel_point;
const confirmationMsg = [];
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '55%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Update Channel',
titleMessage: titleMsg,
noBtnText: 'Cancel',
yesBtnText: 'Update Channel',
message: confirmationMsg,
flgShowInput: true,
getInputs: [
{placeholder: 'Base Fee (mSat)', inputType: DataTypeEnum.NUMBER.toLowerCase(), inputValue: (this.myChanPolicy.fee_base_msat === '') ? 0 : this.myChanPolicy.fee_base_msat},
{placeholder: 'Fee Rate (mili mSat)', inputType: DataTypeEnum.NUMBER.toLowerCase(), inputValue: this.myChanPolicy.fee_rate_milli_msat, min: 1},
{placeholder: 'Time Lock Delta', inputType: DataTypeEnum.NUMBER.toLowerCase(), inputValue: this.myChanPolicy.time_lock_delta}
]
}}));
});
@ -147,8 +161,12 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
}
onChannelClose(channelToClose: Channel) {
this.store.dispatch(new RTLActions.OpenConfirmation({
width: '70%', data: { type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Channel Closing', titleMessage: 'Closing channel: ' + channelToClose.chan_id, noBtnText: 'Cancel', yesBtnText: 'Close Channel'
this.store.dispatch(new RTLActions.OpenConfirmation({width: '55%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Close Channel',
titleMessage: 'Closing channel: ' + channelToClose.channel_point,
noBtnText: 'Cancel',
yesBtnText: 'Close Channel'
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unSubs[4]))
@ -171,14 +189,30 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
const selChannel = this.channels.data.filter(channel => {
return channel.chan_id === selRow.chan_id;
})[0];
const reorderedChannel = JSON.parse(JSON.stringify(selChannel, [
'active', 'remote_pubkey', 'remote_alias', 'channel_point', 'chan_id', 'capacity', 'local_balance', 'remote_balance', 'commit_fee', 'commit_weight',
'fee_per_kw', 'unsettled_balance', 'total_satoshis_sent', 'total_satoshis_received', 'num_updates', 'pending_htlcs', 'csv_delay', 'private'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const reorderedChannel = [
[{key: 'remote_alias', value: selChannel.remote_alias, title: 'Peer Alias', width: 40},
{key: 'active', value: selChannel.active, title: 'Active', width: 30, type: DataTypeEnum.BOOLEAN},
{key: 'private', value: selChannel.private, title: 'Private', width: 30, type: DataTypeEnum.BOOLEAN}],
[{key: 'remote_pubkey', value: selChannel.remote_pubkey, title: 'Peer Public Key', width: 100}],
[{key: 'channel_point', value: selChannel.channel_point, title: 'Channel Point', width: 100}],
[{key: 'chan_id', value: selChannel.chan_id, title: 'Channel ID', width: 50},
{key: 'capacity', value: selChannel.capacity, title: 'Capacity', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'local_balance', value: selChannel.local_balance, title: 'Local Balance', width: 50, type: DataTypeEnum.NUMBER},
{key: 'remote_balance', value: selChannel.remote_balance, title: 'Remote Balance', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'commit_fee', value: selChannel.commit_fee, title: 'Commit Fee', width: 50, type: DataTypeEnum.NUMBER},
{key: 'commit_weight', value: selChannel.commit_weight, title: 'Commit Weight', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'fee_per_kw', value: selChannel.fee_per_kw, title: 'Fee/KW', width: 50, type: DataTypeEnum.NUMBER},
{key: 'unsettled_balance', value: selChannel.unsettled_balance, title: 'Unsettled Balance', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'total_satoshis_sent', value: selChannel.total_satoshis_sent, title: 'Total Satoshis Sent', width: 50, type: DataTypeEnum.NUMBER},
{key: 'total_satoshis_received', value: selChannel.total_satoshis_received, title: 'Total Satoshis Received', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'num_updates', value: selChannel.num_updates, title: 'Number of Updates', width: 40, type: DataTypeEnum.NUMBER},
{key: 'pending_htlcs', value: selChannel.pending_htlcs, title: 'Pending HTLCs', width: 30, type: DataTypeEnum.NUMBER},
{key: 'csv_delay', value: selChannel.csv_delay, title: 'CSV Delay', width: 30, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Channel Information',
message: JSON.stringify(reorderedChannel)
message: reorderedChannel
}}));
}

@ -11,7 +11,7 @@ import { LoggerService } from '../../../../../shared/services/logger.service';
import { RTLEffects } from '../../../../../store/rtl.effects';
import * as RTLActions from '../../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../../store/rtl.reducers';
import { AlertTypeEnum } from '../../../../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../../../../shared/services/consts-enums-functions';
@Component({
selector: 'rtl-channel-pending-table',
@ -115,12 +115,23 @@ export class ChannelPendingTableComponent implements OnInit, OnDestroy {
})[0];
const fcChannelObj1 = JSON.parse(JSON.stringify(selChannel, ['commit_weight', 'confirmation_height', 'fee_per_kw', 'commit_fee'], 2));
const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2));
const reorderedChannel = {};
Object.assign(reorderedChannel, fcChannelObj1, fcChannelObj2);
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const preOrderedChannel: any = {};
Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2);
const reorderedChannel = [
[{key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING}],
[{key: 'remote_node_pub', value: preOrderedChannel.remote_node_pub, title: 'Peer Node Pubkey', width: 100, type: DataTypeEnum.STRING}],
[{key: 'remote_balance', value: preOrderedChannel.remote_balance, title: 'Remote Balance', width: 50, type: DataTypeEnum.NUMBER},
{key: 'local_balance', value: preOrderedChannel.local_balance, title: 'Local Balance', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'capacity', value: preOrderedChannel.capacity, title: 'Capacity', width: 50, type: DataTypeEnum.NUMBER},
{key: 'confirmation_height', value: preOrderedChannel.confirmation_height, title: 'Confirmation Height', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'fee_per_kw', value: preOrderedChannel.fee_per_kw, title: 'Fee/KW', width: 40, type: DataTypeEnum.NUMBER},
{key: 'commit_weight', value: preOrderedChannel.commit_weight, title: 'Commit Weight', width: 30, type: DataTypeEnum.NUMBER},
{key: 'commit_fee', value: preOrderedChannel.commit_fee, title: 'Commit Fee', width: 30, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Opening Channel Information',
message: JSON.stringify(reorderedChannel)
message: reorderedChannel
}}));
}
@ -130,12 +141,24 @@ export class ChannelPendingTableComponent implements OnInit, OnDestroy {
})[0];
const fcChannelObj1 = JSON.parse(JSON.stringify(selChannel, ['closing_txid', 'limbo_balance', 'maturity_height', 'blocks_til_maturity', 'recovered_balance'], 2));
const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2));
const reorderedChannel = {};
Object.assign(reorderedChannel, fcChannelObj1, fcChannelObj2);
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const preOrderedChannel: any = {};
Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2);
const reorderedChannel = [
[{key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING}],
[{key: 'remote_node_pub', value: preOrderedChannel.remote_node_pub, title: 'Peer Node Pubkey', width: 100, type: DataTypeEnum.STRING}],
[{key: 'remote_balance', value: preOrderedChannel.remote_balance, title: 'Remote Balance', width: 50, type: DataTypeEnum.NUMBER},
{key: 'local_balance', value: preOrderedChannel.local_balance, title: 'Local Balance', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'capacity', value: preOrderedChannel.capacity, title: 'Capacity', width: 50, type: DataTypeEnum.NUMBER},
{key: 'limbo_balance', value: preOrderedChannel.limbo_balance, title: 'Limbo Balance', width: 100, type: DataTypeEnum.NUMBER}],
[{key: 'closing_txid', value: preOrderedChannel.closing_txid, title: 'Closing Transaction ID', width: 100, type: DataTypeEnum.STRING}],
[{key: 'maturity_height', value: preOrderedChannel.maturity_height, title: 'Maturity Height', width: 40, type: DataTypeEnum.NUMBER},
{key: 'blocks_til_maturity', value: preOrderedChannel.blocks_til_maturity, title: 'Blocks Till Maturity', width: 30, type: DataTypeEnum.NUMBER},
{key: 'recovered_balance', value: preOrderedChannel.recovered_balance, title: 'Recovered Balance', width: 30, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Force Closing Channel Information',
message: JSON.stringify(reorderedChannel)
message: reorderedChannel
}}));
}
@ -145,12 +168,20 @@ export class ChannelPendingTableComponent implements OnInit, OnDestroy {
})[0];
const fcChannelObj1 = JSON.parse(JSON.stringify(selChannel, ['closing_txid'], 2));
const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2));
const reorderedChannel = {};
Object.assign(reorderedChannel, fcChannelObj1, fcChannelObj2);
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const preOrderedChannel: any = {};
Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2);
const reorderedChannel = [
[{key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING}],
[{key: 'remote_node_pub', value: preOrderedChannel.remote_node_pub, title: 'Peer Node Pubkey', width: 100, type: DataTypeEnum.STRING}],
[{key: 'remote_balance', value: preOrderedChannel.remote_balance, title: 'Remote Balance', width: 50, type: DataTypeEnum.NUMBER},
{key: 'local_balance', value: preOrderedChannel.local_balance, title: 'Local Balance', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'capacity', value: preOrderedChannel.capacity, title: 'Capacity', width: 50, type: DataTypeEnum.NUMBER},
{key: 'closing_txid', value: preOrderedChannel.closing_txid, title: 'Closing Transaction ID', width: 50, type: DataTypeEnum.STRING}]
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Closing Channel Information',
message: JSON.stringify(reorderedChannel)
message: reorderedChannel
}}));
}
@ -160,12 +191,20 @@ export class ChannelPendingTableComponent implements OnInit, OnDestroy {
})[0];
const fcChannelObj1 = JSON.parse(JSON.stringify(selChannel, ['limbo_balance'], 2));
const fcChannelObj2 = JSON.parse(JSON.stringify(selChannel.channel, ['channel_point', 'remote_balance', 'local_balance', 'remote_node_pub', 'capacity'], 2));
const reorderedChannel = {};
Object.assign(reorderedChannel, fcChannelObj1, fcChannelObj2);
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const preOrderedChannel: any = {};
Object.assign(preOrderedChannel, fcChannelObj1, fcChannelObj2);
const reorderedChannel = [
[{key: 'channel_point', value: preOrderedChannel.channel_point, title: 'Channel Point', width: 100, type: DataTypeEnum.STRING}],
[{key: 'remote_node_pub', value: preOrderedChannel.remote_node_pub, title: 'Peer Node Pubkey', width: 100, type: DataTypeEnum.STRING}],
[{key: 'remote_balance', value: preOrderedChannel.remote_balance, title: 'Remote Balance', width: 50, type: DataTypeEnum.NUMBER},
{key: 'local_balance', value: preOrderedChannel.local_balance, title: 'Local Balance', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'capacity', value: preOrderedChannel.capacity, title: 'Capacity', width: 50, type: DataTypeEnum.NUMBER},
{key: 'limbo_balance', value: preOrderedChannel.limbo_balance, title: 'Limbo Balance', width: 50, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Wait Closing Channel Information',
message: JSON.stringify(reorderedChannel)
message: reorderedChannel
}}));
}

@ -6,7 +6,7 @@ import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { SelNodeChild } from '../../../../../shared/models/RTLconfig';
import { Channel } from '../../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum } from '../../../../../shared/services/consts-enums-functions';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum } from '../../../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../../../shared/services/logger.service';
import { LNDEffects } from '../../../../store/lnd.effects';
@ -69,25 +69,6 @@ export class ChannelRestoreTableComponent implements OnInit {
this.channels.filter = selFilter;
}
onChannelClick(selRow: Channel, event: any) {
const flgButtonsClicked = event.target.className.includes('mat-icon')
|| event.target.className.includes('mat-column-backup')
|| event.target.className.includes('mat-column-verify');
if (flgButtonsClicked) { return; }
const selChannel = this.channels.data.filter(channel => {
return channel.chan_id === selRow.chan_id;
})[0];
const reorderedChannel = JSON.parse(JSON.stringify(selChannel, [
'active', 'remote_pubkey', 'remote_alias', 'channel_point', 'chan_id', 'capacity', 'local_balance', 'remote_balance', 'commit_fee', 'commit_weight',
'fee_per_kw', 'unsettled_balance', 'total_satoshis_sent', 'total_satoshis_received', 'num_updates', 'pending_htlcs', 'csv_delay', 'private'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Restored Channel Information',
message: JSON.stringify(reorderedChannel)
}}));
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();

@ -9,7 +9,7 @@ import { faUsers } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { Peer, GetInfo } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum } from '../../../shared/services/consts-enums-functions';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service';
import { OpenChannelComponent } from '../../../shared/components/data-modal/open-channel/open-channel.component';
import { newlyAddedRowAnimation } from '../../../shared/animation/row-animation';
@ -137,10 +137,20 @@ export class PeersComponent implements OnInit, OnDestroy {
const selPeer = this.peers.data.filter(peer => {
return peer.pub_key === selRow.pub_key;
})[0];
const reorderedPeer = JSON.parse(JSON.stringify(selPeer, [
'alias', 'pub_key', 'address', 'bytes_sent', 'bytes_recv', 'sat_sent', 'sat_recv', 'inbound', 'ping_time'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: { type: AlertTypeEnum.INFORMATION, alertTitle: 'Peer Information', message: JSON.stringify(reorderedPeer)}}));
const reorderedPeer = [
[{key: 'pub_key', value: selPeer.pub_key, title: 'Public Key', width: 100}],
[{key: 'address', value: selPeer.address, title: 'Address', width: 100}],
[{key: 'alias', value: selPeer.alias, title: 'Alias', width: 40}, {key: 'inbound', value: selPeer.inbound ? 'True' : 'False', title: 'Inbound', width: 30}, {key: 'ping_time', value: selPeer.ping_time, title: 'Ping Time', width: 30, type: DataTypeEnum.NUMBER}],
[{key: 'sat_sent', value: selPeer.sat_sent, title: 'Satoshis Sent', width: 50, type: DataTypeEnum.NUMBER}, {key: 'sat_recv', value: selPeer.sat_recv, title: 'Satoshis Received', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'bytes_sent', value: selPeer.bytes_sent, title: 'Bytes Sent', width: 50, type: DataTypeEnum.NUMBER}, {key: 'bytes_recv', value: selPeer.bytes_recv, title: 'Bytes Received', width: 50, type: DataTypeEnum.NUMBER}],
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Peer Information',
showQRName: 'Public Key',
showQRField: selPeer.pub_key,
message: reorderedPeer
}}));
}
resetData() {
@ -148,17 +158,33 @@ export class PeersComponent implements OnInit, OnDestroy {
}
onOpenChannel(peerToAddChannel: Peer) {
this.store.dispatch(new RTLActions.OpenAlert({ width: '50%', data: { type: AlertTypeEnum.INFORMATION, alertTitle: 'Open Channel', message: JSON.stringify({peer: peerToAddChannel, information: this.information, balance: this.availableBalance}), newlyAdded: false, component: OpenChannelComponent}}));
const peerToAddChannelMessage = {
peer: peerToAddChannel,
information: this.information,
balance: this.availableBalance
};
this.store.dispatch(new RTLActions.OpenAlert({ width: '50%', data: {
alertTitle: 'Open Channel',
message: peerToAddChannelMessage,
newlyAdded: false,
component: OpenChannelComponent
}}));
}
onPeerDetach(peerToDetach: Peer) {
const msg = 'Disconnect peer: ' + peerToDetach.pub_key;
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: { type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Peer Disconnect', titleMessage: msg, noBtnText: 'Cancel', yesBtnText: 'Detach'}}));
const msg = 'Disconnect peer: ' + ((peerToDetach.alias) ? peerToDetach.alias : peerToDetach.pub_key);
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '55%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Disconnect Peer',
titleMessage: msg,
noBtnText: 'Cancel',
yesBtnText: 'Disconnect'
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unSubs[3]))
.subscribe(confirmRes => {
if (confirmRes) {
this.store.dispatch(new RTLActions.OpenSpinner('Detaching Peer...'));
this.store.dispatch(new RTLActions.OpenSpinner('Disconnecting Peer...'));
this.store.dispatch(new RTLActions.DetachPeer({pubkey: peerToDetach.pub_key}));
}
});

@ -11,7 +11,7 @@ import { CommonService } from '../../shared/services/common.service';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
import { AlertTypeEnum } from '../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../shared/services/consts-enums-functions';
@Component({
selector: 'rtl-routing-peers',
@ -86,7 +86,7 @@ export class RoutingPeersComponent implements OnInit, OnDestroy {
}
onRoutingPeerClick(selRow: RoutingPeers, event: any, direction: string) {
let selRPeer = {};
let selRPeer: RoutingPeers = {};
if (direction === 'in') {
selRPeer = this.RoutingPeersIncoming.data.find(rPeer => {
return rPeer.chan_id === selRow.chan_id;
@ -96,11 +96,14 @@ export class RoutingPeersComponent implements OnInit, OnDestroy {
return rPeer.chan_id === selRow.chan_id;
});
}
const reorderedRoutingPeer = JSON.parse(JSON.stringify(selRPeer, ['chan_id', 'alias', 'events', 'total_amount'] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const reorderedRoutingPeer = [
[{key: 'chan_id', value: selRPeer.chan_id, title: 'Channel ID', width: 100, type: DataTypeEnum.STRING}]
// 'chan_id', 'alias', 'events', 'total_amount'
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Route Information',
message: JSON.stringify(reorderedRoutingPeer)
message: reorderedRoutingPeer
}}));
}

@ -20,6 +20,7 @@ import { CurrencyUnitEnum, AlertTypeEnum } from '../../shared/services/consts-en
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
import * as fromLNDReducers from '../store/lnd.reducers';
import { ErrorMessageComponent } from '../../shared/components/data-modal/error-message/error-message.component';
@Injectable()
export class LNDEffects implements OnDestroy {
@ -129,10 +130,20 @@ export class LNDEffects implements OnDestroy {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.SetPeers((postRes && postRes.length > 0) ? postRes : []));
const peerToAddChannelMessage = {
peer: postRes[0],
information: lndData.information,
balance: lndData.blockchainBalance.total_balance || 0
};
return {
type: RTLActions.OPEN_ALERT,
payload: { width: '50%', data: { type: AlertTypeEnum.INFORMATION, alertTitle: 'Peer Connected', message: JSON.stringify({peer: postRes[0], information: lndData.information, balance: lndData.blockchainBalance.total_balance || 0}), newlyAdded: true}},
component: OpenChannelComponent
payload: { width: '50%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Peer Connected',
message: peerToAddChannelMessage,
newlyAdded: true,
component: OpenChannelComponent
}}
};
}),
catchError((err: any) => {
@ -152,7 +163,11 @@ export class LNDEffects implements OnDestroy {
map((postRes: any) => {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({ width: '70%', data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Peer Disconnected', titleMessage: 'Peer Disconnected Successfully!' }}));
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.SUCCESS,
alertTitle: 'Peer Disconnected',
titleMessage: 'Peer Disconnected Successfully!'
}}));
return {
type: RTLActions.REMOVE_PEER,
payload: { pubkey: action.payload.pubkey }
@ -184,8 +199,10 @@ export class LNDEffects implements OnDestroy {
postRes.creation_date_str = new Date(+postRes.creation_date * 1000).toUTCString().substring(5, 22).replace(' ', '/').replace(' ', '/').toUpperCase();
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
width: '58%', data: { type: AlertTypeEnum.INFORMATION, alertTitle: 'Invoice Created', message: JSON.stringify(postRes), newlyAdded: true, component: InvoiceInformationComponent
this.store.dispatch(new RTLActions.OpenAlert({ width: '58%', data: {
invoice: postRes,
newlyAdded: true,
component: InvoiceInformationComponent
}}));
return {
type: RTLActions.FETCH_INVOICES,
@ -238,7 +255,7 @@ export class LNDEffects implements OnDestroy {
map((postRes: any) => {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({ width: '70%', data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Channel Updated', titleMessage: 'Channel Updated Successfully!' }}));
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: '' }
@ -591,29 +608,23 @@ export class LNDEffects implements OnDestroy {
this.store.dispatch(new RTLActions.CloseSpinner());
if (sendRes.payment_error) {
this.logger.error('Error: ' + sendRes.payment_error);
return {
type: RTLActions.OPEN_ALERT,
payload: {config : {
width: '70%', data: {
type: 'ERROR', titleMessage: 'Send Payment Failed',
message: JSON.stringify(
{ code: sendRes.payment_error.status, Message: sendRes.payment_error.error.message, URL: this.CHILD_API_URL + environment.CHANNELS_API + '/transactions/' + action.payload[0] }
)
}
}}
};
const myErr = {status: sendRes.payment_error.status, error: sendRes.payment_error.error.message};
this.handleErrorWithAlert('ERROR', 'Send Payment Failed', this.CHILD_API_URL + environment.CHANNELS_API + '/transactions/' + action.payload[0], myErr);
return of({type: RTLActions.VOID});
} else {
const confirmationMsg = { 'Destination': action.payload[1].destination, 'Timestamp': action.payload[1].timestamp_str, 'Expiry': action.payload[1].expiry };
confirmationMsg['Amount (' + ((undefined === store.nodeData.smaller_currency_unit) ?
CurrencyUnitEnum.SATS : store.nodeData.smaller_currency_unit) + ')'] = action.payload[1].num_satoshis;
const msg = {};
const msg = [];
msg['Total Fee (' + ((undefined === store.nodeData.smaller_currency_unit) ? CurrencyUnitEnum.SATS : store.nodeData.smaller_currency_unit) + ')'] =
(sendRes.payment_route.total_fees_msat / 1000);
Object.assign(msg, confirmationMsg);
this.store.dispatch(new RTLActions.OpenAlert({
width: '70%',
data: { type: AlertTypeEnum.SUCCESS, alertTitle: 'Payment Sent', titleMessage: 'Payment Sent Successfully!', message: JSON.stringify(msg) }
}));
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.SUCCESS,
alertTitle: 'Payment Sent',
titleMessage: 'Payment Sent Successfully!',
message: msg
}}));
this.store.dispatch(new RTLActions.FetchChannels({ routeParam: 'all' }));
this.store.dispatch(new RTLActions.FetchBalance('channels'));
this.store.dispatch(new RTLActions.FetchPayments());
@ -624,7 +635,8 @@ export class LNDEffects implements OnDestroy {
}
}),
catchError((err: any) => {
this.handleErrorWithAlert('ERROR', 'Send Payment Failed', this.CHILD_API_URL + environment.CHANNELS_API + '/transactions', err);
const myErr = {status: err.status, error: typeof(err.error.error) === 'object' ? err.error.error : {error: err.error.error}};
this.handleErrorWithAlert('ERROR', 'Send Payment Failed', this.CHILD_API_URL + environment.CHANNELS_API + '/transactions', myErr);
return of({type: RTLActions.VOID});
})
);
@ -1066,9 +1078,11 @@ export class LNDEffects implements OnDestroy {
} else {
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
width: '70%', data: {
type: alertType, alertTitle: alertType, titleMessage: alertTitle,
message: JSON.stringify({ code: err.status, Message: err.error.error, URL: errURL })
width: '55%', data: {
type: alertType,
alertTitle: alertTitle,
message: { code: err.status, message: err.error.error, URL: errURL },
component: ErrorMessageComponent
}
}));
}

@ -10,7 +10,7 @@ import { LoggerService } from '../../shared/services/logger.service';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
import { AlertTypeEnum } from '../../shared/services/consts-enums-functions';
import { AlertTypeEnum, DataTypeEnum } from '../../shared/services/consts-enums-functions';
@Component({
selector: 'rtl-forwarding-history',
@ -82,11 +82,14 @@ export class ForwardingHistoryComponent implements OnInit, OnDestroy {
const selFEvent = this.forwardingHistoryEvents.data.filter(fhEvent => {
return (fhEvent.chan_id_in === selRow.chan_id_in && fhEvent.timestamp === selRow.timestamp);
})[0];
const reorderedFHEvent = JSON.parse(JSON.stringify(selFEvent, ['timestamp_str', 'chan_id_in', 'alias_in', 'chan_id_out', 'alias_out', 'amt_out', 'amt_in', 'fee'] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const reorderedFHEvent = [
[{key: 'alias', value: selFEvent.alias, title: 'Alias', width: 100, type: DataTypeEnum.STRING}]
// 'timestamp_str', 'chan_id_in', 'alias_in', 'chan_id_out', 'alias_out', 'amt_out', 'amt_in', 'fee'
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Event Information',
message: JSON.stringify(reorderedFHEvent)
message: reorderedFHEvent
}}));
}

@ -6,7 +6,7 @@ import { Store } from '@ngrx/store';
import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginatorIntl } from '@angular/material';
import { TimeUnitEnum, CurrencyUnitEnum, TIME_UNITS, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum } from '../../../shared/services/consts-enums-functions';
import { TimeUnitEnum, CurrencyUnitEnum, TIME_UNITS, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum } from '../../../shared/services/consts-enums-functions';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { GetInfo, Invoice } from '../../../shared/models/lndModels';
import { LoggerService } from '../../../shared/services/logger.service';
@ -119,16 +119,9 @@ export class LightningInvoicesComponent implements OnInit, OnDestroy {
const selInvoice = this.invoices.data.filter(invoice => {
return invoice.payment_request === selRow.payment_request;
})[0];
const reorderedInvoice = JSON.parse(JSON.stringify(selInvoice, [
'settled', 'creation_date_str', 'settle_date_str', 'memo', 'receipt', 'r_preimage', 'r_hash', 'value', 'payment_request',
'description_hash', 'expiry', 'fallback_addr', 'cltv_expiry', 'route_hints', 'private', 'add_index', 'settle_index',
'amt_paid', 'amt_paid_sat', 'amt_paid_msat'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '58%',
data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Invoice Information',
message: JSON.stringify(reorderedInvoice),
invoice: selInvoice,
newlyAdded: false,
component: InvoiceInformationComponent
}}));

@ -56,7 +56,7 @@
</ng-container>
<tr mat-footer-row *matFooterRowDef="['no_payment']" [ngClass]="{'display-none': payments.data && payments.data.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.payment_hash === newlyAddedPayment && flgAnimate) ? 'added' : 'notAdded'"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.payment_hash === newlyAddedPayment && flgAnimate) ? 'added' : 'notAdded'"></tr>
</table>
</div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" showFirstLastButtons class="mb-4"></mat-paginator>

@ -6,7 +6,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { GetInfo, Payment, PayRequest } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum } from '../../../shared/services/consts-enums-functions';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service';
import { newlyAddedRowAnimation } from '../../../shared/animation/row-animation';
@ -116,10 +116,25 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
this.flgAnimate = true;
this.newlyAddedPayment = this.paymentDecoded.payment_hash;
if (undefined === this.paymentDecoded.num_satoshis || this.paymentDecoded.num_satoshis === '' || this.paymentDecoded.num_satoshis === '0') {
const reorderedPaymentDecoded = [
[{key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100}],
[{key: 'destination', value: this.paymentDecoded.destination, title: 'Destination', width: 100}],
[{key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100}],
[{key: 'timestamp_str', value: this.paymentDecoded.timestamp_str, title: 'Creation Date', width: 40},
{key: 'expiry', value: this.paymentDecoded.expiry, title: 'Expiry', width: 30, type: DataTypeEnum.NUMBER},
{key: 'cltv_expiry', value: this.paymentDecoded.cltv_expiry, title: 'CLTV Expiry', width: 30}]
];
const titleMsg = 'It is an open amount invoice. Enter the amount (Sats) to pay.';
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Enter Amount and Confirm Send Payment', titleMessage: titleMsg, message: JSON.stringify(this.paymentDecoded), noBtnText: 'Cancel', yesBtnText: 'Send', flgShowInput: true, getInputs: [
{placeholder: 'Amount (Sats)', inputType: 'number', inputValue: ''}
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '55%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Enter Amount and Confirm Send Payment',
titleMessage: titleMsg,
message: reorderedPaymentDecoded,
noBtnText: 'Cancel',
yesBtnText: 'Send Payment',
flgShowInput: true,
getInputs: [
{placeholder: 'Amount (Sats)', inputType: DataTypeEnum.NUMBER.toLowerCase(), inputValue: ''}
]
}}));
this.rtlEffects.closeConfirm
@ -133,8 +148,21 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
}
});
} else {
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '70%', data: {
type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Send Payment', titleMessage: 'Send Payment', noBtnText: 'Cancel', yesBtnText: 'Send', message: JSON.stringify(this.paymentDecoded)
const reorderedPaymentDecoded = [
[{key: 'payment_hash', value: this.paymentDecoded.payment_hash, title: 'Payment Hash', width: 100}],
[{key: 'destination', value: this.paymentDecoded.destination, title: 'Destination', width: 100}],
[{key: 'description', value: this.paymentDecoded.description, title: 'Description', width: 100}],
[{key: 'timestamp_str', value: this.paymentDecoded.timestamp_str, title: 'Creation Date', width: 50},
{key: 'num_satoshis', value: this.paymentDecoded.num_satoshis, title: 'Amount (Sats)', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'expiry', value: this.paymentDecoded.expiry, title: 'Expiry', width: 50, type: DataTypeEnum.NUMBER},
{key: 'cltv_expiry', value: this.paymentDecoded.cltv_expiry, title: 'CLTV Expiry', width: 50}]
];
this.store.dispatch(new RTLActions.OpenConfirmation({ width: '55%', data: {
type: AlertTypeEnum.CONFIRM,
alertTitle: 'Send Payment',
noBtnText: 'Cancel',
yesBtnText: 'Send',
message: reorderedPaymentDecoded
}}));
this.rtlEffects.closeConfirm
.pipe(take(1))
@ -170,13 +198,20 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
const selPayment = this.payments.data.filter(payment => {
return payment.payment_hash === selRow.payment_hash;
})[0];
const reorderedPayment = JSON.parse(JSON.stringify(selPayment, [
'creation_date_str', 'payment_hash', 'fee', 'value_msat', 'value_sat', 'value', 'payment_preimage', 'path'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
const reorderedPayment = [
[{key: 'payment_hash', value: selPayment.payment_hash, title: 'Payment Hash', width: 100, type: DataTypeEnum.STRING}],
[{key: 'payment_preimage', value: selPayment.payment_preimage, title: 'Payment Preimage', width: 100, type: DataTypeEnum.STRING}],
[{key: 'path', value: selPayment.path, title: 'Path', width: 100, type: DataTypeEnum.ARRAY}],
[{key: 'creation_date_str', value: selPayment.creation_date_str, title: 'Creation Date', width: 50, type: DataTypeEnum.DATE_TIME},
{key: 'fee', value: selPayment.fee, title: 'Fee', width: 50, type: DataTypeEnum.NUMBER}],
[{key: 'value_msat', value: selPayment.value_msat, title: 'Value (mSats)', width: 50, type: DataTypeEnum.NUMBER},
{key: 'value_sat', value: selPayment.value, title: 'Value (Sats)', width: 50, type: DataTypeEnum.NUMBER}]
];
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: 'Payment Information',
message: JSON.stringify(reorderedPayment)
message: reorderedPayment
}}));
}

@ -118,7 +118,7 @@ export class AppSettingsComponent implements OnInit, OnDestroy {
let defaultNodeIndex = (this.previousDefaultNode !== this.appConfig.defaultNodeIndex) ? this.appConfig.defaultNodeIndex : null;
this.logger.info(this.selNode.settings);
if (!updatedSettings && !defaultNodeIndex) {
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
this.store.dispatch(new RTLActions.OpenAlert({ width: '55%', data: {
type: AlertTypeEnum.WARNING,
alertTitle: 'Configuration Not Updated',
titleMessage: 'Nothing has been updated to save!'

@ -1,30 +1,42 @@
<div fxLayout="row">
<div fxFlex="100" class="padding-gap-large">
<div *ngIf="showQRField !== ''" fxFlex="35" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap-large">
<qrcode [qrdata]="showQRField" [size]="230" [level]="'L'" [allowEmptyString]="true" class="qr-border"></qrcode>
</div>
<div [fxFlex]="showQRField !== '' ? '65' : '100'" class="padding-gap-large">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">{{data.alertTitle || alertTypeEnum[data.type]}}</span>
</div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header>
<mat-card-content class="mt-5px">
<mat-card-content class="mt-5px mb-0">
<div fxLayout="column">
<p *ngIf="data.titleMessage" fxLayoutAlign="start center" class="title-message pb-1 pl-1">{{data.titleMessage | titlecase}}</p>
<p *ngIf="data.titleMessage" fxLayoutAlign="start center" class="pb-1">{{data.titleMessage}}</p>
<div *ngIf="messageObjs?.length>0">
<div *ngFor="let objs of messageObjs; index as i;">
<div fxLayout="row wrap" fxLayoutAlign="start center" fxLayoutAlign.gt-md="space-between start">
<div fxLayout="column" fxFlex="100" fxFlex.gt-md="{{100/messageFieldsBreakdown[i]}}" *ngFor="let obj of objs">
<h4 fxLayoutAlign="start" class="font-bold-500">{{obj[0] | titlecase}}</h4>
<span fxFlex="100" class="foreground-secondary-text" *ngIf="isNumber(obj[1], obj[0]);else notNumberTemplate">{{obj[1] | number:'1.0-3'}}</span>
<ng-template #notNumberTemplate>
<span fxFlex="100" class="foreground-secondary-text">{{obj[1]}}</span>
<div fxLayout="column" fxFlex="100" fxFlex.gt-md="{{obj.width}}" *ngFor="let obj of objs; index as j;">
<h4 fxLayoutAlign="start" class="font-bold-500">{{obj.title}}</h4>
<span *ngIf="obj && obj.value; else emptyField">
<span [ngSwitch]="obj.type" class="foreground-secondary-text">
<ng-container *ngSwitchCase="dataTypeEnum.ARRAY"><span *ngFor="let arrayObj of obj.value" class="display-block">{{arrayObj}}</span></ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.NUMBER">{{obj.value | number:'1.0-3'}}</ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.BOOLEAN">{{obj.value === true ? 'True' : 'False'}}</ng-container>
<ng-container *ngSwitchDefault>{{obj.value}}</ng-container>
</span>
</span>
<ng-template #emptyField>
<span fxFlex="100" class="foreground-secondary-text">&nbsp;</span>
</ng-template>
<mat-divider class="w-100 my-1"></mat-divider>
</div>
</div>
</div>
</div>
<div class="mt-2" fxLayout="row" fxLayoutAlign="end center">
<button fxLayoutAlign="center center" tabindex="1" autoFocus mat-raised-button color="primary" fxFlex="20" type="submit" [mat-dialog-close]="false" default>OK</button>
<div fxLayout="row" fxLayoutAlign="end center">
<button *ngIf="!showQRField || showQRField == ''" fxLayoutAlign="center center" tabindex="1" autoFocus mat-raised-button color="primary" fxFlex="20" type="submit" [mat-dialog-close]="false" default>OK</button>
<button *ngIf="showQRField !== ''" fxLayoutAlign="center center" tabindex="1" class="mr-2" mat-stroked-button color="primary" type="button" [mat-dialog-close]="false" default>OK</button>
<button *ngIf="showQRField !== ''" fxFlex="30" fxLayoutAlign="center center" autoFocus mat-raised-button color="primary" tabindex="2" type="submit" rtlClipboard [payload]="showQRField" (copied)="onCopyField($event)">Copy {{showQRName}}</button>
</div>
</div>
</mat-card-content>

@ -1,40 +1,3 @@
.p-2 {
padding: 1rem;
}
.pb-1 {
padding-bottom: 0.3rem;
}
.pb-2 {
padding-bottom: 1rem;
}
.mb-1 {
margin-bottom: 0.5rem;
}
.wrap-text {
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
hyphens: auto;
}
.mat-icon[type="button"] {
cursor: pointer;
}
.new-line {
white-space: pre-wrap;
}
.title-message {
font-size: 110%;
}
.mt-minus-40px {
margin-top:-40px;
}
.display-block {
display: block;
}

@ -1,10 +1,9 @@
import { Component, OnInit, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { faCopy } from '@fortawesome/free-solid-svg-icons';
import { MatDialogRef, MAT_DIALOG_DATA, MatSnackBar } from '@angular/material';
import { LoggerService } from '../../../services/logger.service';
import { AlertData } from '../../../models/alertData';
import { AlertTypeEnum } from '../../../services/consts-enums-functions';
import { AlertData, ErrorData } from '../../../models/alertData';
import { AlertTypeEnum, DataTypeEnum } from '../../../services/consts-enums-functions';
@Component({
selector: 'rtl-alert-message',
@ -12,107 +11,32 @@ import { AlertTypeEnum } from '../../../services/consts-enums-functions';
styleUrls: ['./alert-message.component.scss']
})
export class AlertMessageComponent implements OnInit {
public msgTypeBackground = 'bg-primary p-1';
public msgTypeForeground = 'primary';
public messageObjsArr = [];
public showQRField = '';
public showQRName = '';
public errorMessage = '';
public messageObjs = [];
public messageFieldsBreakdown = [];
public flgCopied = false;
public faCopy = faCopy;
public alertTypeEnum = AlertTypeEnum;
public dataTypeEnum = DataTypeEnum;
constructor(public dialogRef: MatDialogRef<AlertMessageComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private logger: LoggerService) { }
constructor(public dialogRef: MatDialogRef<AlertMessageComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private logger: LoggerService, private snackBar: MatSnackBar) { }
ngOnInit() {
this.messageFieldsBreakdown = this.data.messageFieldsBreakdown;
this.setStyleOnAlertType();
this.convertJSONData();
}
setStyleOnAlertType() {
if (this.data.type === AlertTypeEnum.WARNING) {
this.msgTypeBackground = 'bg-primary p-1';
this.msgTypeForeground = 'primary';
}
this.messageObjs = this.data.message;
this.showQRField = this.data.showQRField ? this.data.showQRField : '';
this.showQRName = this.data.showQRName ? this.data.showQRName : '';
if (this.data.type === AlertTypeEnum.ERROR) {
this.msgTypeBackground = 'bg-warn p-1';
this.msgTypeForeground = 'warn';
if (undefined === this.data.message && undefined === this.data.titleMessage && this.messageObjsArr.length <= 0 ) {
if (undefined === this.data.message && undefined === this.data.titleMessage && this.messageObjs.length <= 0) {
this.data.titleMessage = 'Please Check Server Connection';
}
}
this.logger.info(this.messageObjs);
}
convertJSONData() {
this.data.message = (undefined === this.data.message) ? '' : this.data.message.replace(/{/g, '').replace(/"/g, '').replace(/}/g, '').replace(/\n/g, '');
// Start: For Payment Path
const arrayStartIdx = this.data.message.search('\\[');
const arrayEndIdx = this.data.message.search('\\]');
if (arrayStartIdx > -1 && arrayEndIdx > -1) {
this.data.message = this.data.message.substring(0, arrayStartIdx).concat(
this.data.message.substring(arrayStartIdx + 1, arrayEndIdx).replace(/,/g, '\n'),
this.data.message.substring(arrayEndIdx + 1));
}
// End: For Payment Path
this.messageObjsArr = (this.data.message === '') ? [] : this.data.message.split(',');
this.messageObjsArr.forEach((obj, idx) => {
this.messageObjsArr[idx] = obj.split(':');
this.messageObjsArr[idx][0] = this.messageObjsArr[idx][0].replace('_str', '');
this.messageObjsArr[idx][0] = this.messageObjsArr[idx][0].replace(/_/g, ' '); // To replace Backend Data's '_'
// Start: To Merge Time Value Again with ':', example Payment Creation Time
if (this.messageObjsArr[idx].length > 2) {
this.messageObjsArr[idx].forEach((dataValue, j) => {
if (j === 0 || j === 1) {
return;
} else {
this.messageObjsArr[idx][1] = this.messageObjsArr[idx][1] + ':' + this.messageObjsArr[idx][j];
}
});
}
// End: To Merge Time Value Again with ':', example Payment Creation Time
});
for (let i = 0; i < this.messageFieldsBreakdown.length; i++) {
this.messageObjs[i] = [];
for (let j = 0, k = i; k < (i + this.messageFieldsBreakdown[i]); j++, k++) {
this.messageObjs[i][j] = this.messageObjsArr[k];
}
}
console.warn(this.messageObjs);
}
showCopyOption(key): boolean {
let flgFoundKey = false;
const showCopyOnKeys = ['payment request', 'bolt11'];
showCopyOnKeys.filter((arrKey) => {
if (arrKey === key) {
flgFoundKey = true;
return true;
}
});
return flgFoundKey;
}
copiedText(payload) {
this.flgCopied = true;
setTimeout(() => {this.flgCopied = false; }, 5000);
onCopyField(payload: string) {
this.snackBar.open(this.showQRName + ' copied');
this.logger.info('Copied Text: ' + payload);
}
isNumber(value, key): boolean {
let flgFoundKey = false;
const notNumberKeys = ['chan id', 'creation date', 'chan id out', 'chan id in'];
notNumberKeys.filter((arrKey) => {
if (arrKey === key) {
flgFoundKey = true;
}
});
if (!flgFoundKey) {
return new RegExp(/^[0-9]+$/).test(value);
} else {
return false;
}
}
onClose() {
this.dialogRef.close(false);
}

@ -8,34 +8,38 @@
</mat-card-header>
<mat-card-content class="mt-5px">
<div fxLayout="column">
<p *ngIf="data.titleMessage" fxLayoutAlign="start center" class="title-message pb-1 pl-1">{{data.titleMessage | titlecase}}</p>
<div *ngIf="flgShowInput" fxLayoutAlign="start center">
<mat-form-field class="pl-2" *ngFor="let getInput of getInputs; index as i">
<p *ngIf="data.titleMessage" fxLayoutAlign="start center" class="pb-1">{{data.titleMessage}}</p>
<div *ngIf="flgShowInput" fxLayoutAlign="space-between center">
<mat-form-field *ngFor="let getInput of getInputs; index as i" [fxFlex]="(getInputs.length > 0 && getInputs.length < 3) ? 25: ((100/getInputs.length) - getInputs.length)">
<input matInput [placeholder]="getInput.placeholder" name="input{{i}}" [min]="getInput.min" [type]="getInput.inputType" [(ngModel)]="getInput.inputValue" [tabindex]="i+1" required>
</mat-form-field>
</div>
<div *ngIf="messageObj?.length>0">
<div *ngFor="let obj of messageObj" fxLayout="row" fxLayoutAlign="center flex-start">
<div fxFlex="20">{{obj[0] | titlecase}}</div>
<div fxFlex="2">:</div>
<div fxFlex="75">
<div *ngIf="isNumber(obj[1], obj[0]);else notNumberTemplate">
<span>{{obj[1] | number:'1.0-3'}}</span>
</div>
<ng-template #notNumberTemplate>
<span>{{obj[1]}}</span>
</ng-template>
<fa-icon *ngIf="showCopyOption(obj[0])" rtlClipboard [payload]="obj[1]" (copied)="copiedText($event)" [icon]="faCopy"></fa-icon>
<span *ngIf="showCopyOption(obj[0])" [hidden]="!flgCopied">Copied</span>
</div>
<div *ngIf="messageObjs?.length>0">
<div *ngFor="let objs of messageObjs; index as i;">
<div fxLayout="row wrap" fxLayoutAlign="start center" fxLayoutAlign.gt-md="space-between start">
<div fxLayout="column" fxFlex="100" fxFlex.gt-md="{{obj.width}}" *ngFor="let obj of objs; index as j;">
<h4 fxLayoutAlign="start" class="font-bold-500">{{obj.title}}</h4>
<span *ngIf="obj && obj.value; else emptyField">
<span [ngSwitch]="obj.type" class="foreground-secondary-text">
<ng-container *ngSwitchCase="dataTypeEnum.ARRAY"><span *ngFor="let arrayObj of obj.value" class="display-block">{{arrayObj}}</span></ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.NUMBER">{{obj.value | number:'1.0-3'}}</ng-container>
<ng-container *ngSwitchCase="dataTypeEnum.BOOLEAN">{{obj.value === true ? 'True' : 'False'}}</ng-container>
<ng-container *ngSwitchDefault>{{obj.value}}</ng-container>
</span>
</span>
<ng-template #emptyField>
<span fxFlex="100" class="foreground-secondary-text">&nbsp;</span>
</ng-template>
<mat-divider class="w-100 my-1"></mat-divider>
</div>
</div>
</div>
</div>
</div>
<mat-divider class="pb-1"></mat-divider>
<div fxLayoutAlign="center">
<button mat-stroked-button color="primary" fxFlex="20" type="button" fxLayoutAlign="center center" class="mr-2" (click)="onClose(false)" tabindex="2" default>{{noBtnText}}</button>
<button *ngIf="flgShowInput" mat-raised-button [color]="msgTypeForeground" fxLayoutAlign="center center" fxFlex="20" type="button" tabindex="3" (click)="onClose(getInputs)" [disabled]="!getInputs[0].inputValue">{{yesBtnText}}</button>
<button *ngIf="!flgShowInput" mat-raised-button [color]="msgTypeForeground" fxLayoutAlign="center center" fxFlex="20" type="button" tabindex="4" (click)="onClose(true)">{{yesBtnText}}</button>
<div fxLayout="row" fxLayoutAlign="end center">
<button autoFocus mat-stroked-button color="primary" fxFlex="20" type="button" fxLayoutAlign="center center" class="mr-2" (click)="onClose(false)" tabindex="2" default>{{noBtnText}}</button>
<button *ngIf="flgShowInput" mat-raised-button color="primary" fxLayoutAlign="center center" fxFlex="25" type="button" tabindex="3" (click)="onClose(getInputs)" [disabled]="!getInputs[0].inputValue">{{yesBtnText}}</button>
<button *ngIf="!flgShowInput" mat-raised-button color="primary" fxLayoutAlign="center center" fxFlex="25" type="button" tabindex="4" (click)="onClose(true)">{{yesBtnText}}</button>
</div>
</div>
</mat-card-content>
</div>

@ -1,16 +0,0 @@
.new-line {
white-space: pre-wrap;
}
.wrap-text {
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
hyphens: auto;
}
.title-message {
font-size: 110%;
}

@ -1,11 +1,10 @@
import { Component, OnInit, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { Store } from '@ngrx/store';
import { faCopy } from '@fortawesome/free-solid-svg-icons';
import { LoggerService } from '../../../services/logger.service';
import { AlertData, InputData } from '../../../models/alertData';
import { AlertTypeEnum } from '../../../services/consts-enums-functions';
import { InputData, ConfirmationData } from '../../../models/alertData';
import { AlertTypeEnum, DataTypeEnum } from '../../../services/consts-enums-functions';
import * as RTLActions from '../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../store/rtl.reducers';
@ -16,18 +15,15 @@ import * as fromRTLReducer from '../../../../store/rtl.reducers';
styleUrls: ['./confirmation-message.component.scss']
})
export class ConfirmationMessageComponent implements OnInit {
public msgTypeBackground = 'bg-primary p-1';
public msgTypeForeground = 'primary';
public noBtnText = 'No';
public yesBtnText = 'Yes';
public messageObj = [];
public flgCopied = false;
public messageObjs = [];
public flgShowInput = false;
public faCopy = faCopy;
public alertTypeEnum = AlertTypeEnum;
public dataTypeEnum = DataTypeEnum;
public getInputs: Array<InputData> = [{placeholder: '', inputType: 'text', inputValue: ''}];
constructor(public dialogRef: MatDialogRef<ConfirmationMessageComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private logger: LoggerService,
constructor(public dialogRef: MatDialogRef<ConfirmationMessageComponent>, @Inject(MAT_DIALOG_DATA) public data: ConfirmationData, private logger: LoggerService,
private store: Store<fromRTLReducer.RTLState>) { }
ngOnInit() {
@ -35,70 +31,13 @@ export class ConfirmationMessageComponent implements OnInit {
this.getInputs = this.data.getInputs;
this.noBtnText = (undefined !== this.data.noBtnText) ? this.data.noBtnText : 'No';
this.yesBtnText = (undefined !== this.data.yesBtnText) ? this.data.yesBtnText : 'Yes';
// INFORMATION/WARNING/ERROR/SUCCESS/CONFIRM
if (this.data.type === 'ERROR') {
this.msgTypeBackground = 'bg-warn p-1';
this.msgTypeForeground = 'warn';
}
this.data.message = (undefined === this.data.message) ? '' : this.data.message.replace(/{/g, '').replace(/"/g, '').replace(/}/g, '').replace(/\n/g, '');
// Start: For Payment Path
const arrayStartIdx = this.data.message.search('\\[');
const arrayEndIdx = this.data.message.search('\\]');
if (arrayStartIdx > -1 && arrayEndIdx > -1) {
this.data.message = this.data.message.substring(0, arrayStartIdx).concat(
this.data.message.substring(arrayStartIdx + 1, arrayEndIdx).replace(/,/g, '\n'),
this.data.message.substring(arrayEndIdx + 1));
}
// End: For Payment Path
this.messageObj = (this.data.message === '') ? [] : this.data.message.split(',');
this.messageObj.forEach((obj, idx) => {
this.messageObj[idx] = obj.split(':');
this.messageObj[idx][0] = this.messageObj[idx][0].replace(/_/g, ' '); // To replace Backend Data's '_'
// Start: To Merge Time Value Again with ':', example Payment Creation Time
if (this.messageObj[idx].length > 2) {
this.messageObj[idx].forEach((dataValue, j) => {
if (j === 0 || j === 1) {
return;
} else {
this.messageObj[idx][1] = this.messageObj[idx][1] + ':' + this.messageObj[idx][j];
}
});
}
// End: To Merge Time Value Again with ':', example Payment Creation Time
});
}
showCopyOption(key): boolean {
let flgFoundKey = false;
const showCopyOnKeys = ['payment request', 'bolt11'];
showCopyOnKeys.filter((arrKey) => {
if (arrKey === key) {
flgFoundKey = true;
return true;
}
});
return flgFoundKey;
}
copiedText(payload) {
this.flgCopied = true;
setTimeout(() => {this.flgCopied = false; }, 5000);
this.logger.info('Copied Text: ' + payload);
}
isNumber(value, key): boolean {
let flgFoundKey = false;
const notNumberKeys = ['chan id', 'creation date'];
notNumberKeys.filter((arrKey) => {
if (arrKey === key) {
flgFoundKey = true;
this.messageObjs = this.data.message;
if (this.data.type === AlertTypeEnum.ERROR) {
if (undefined === this.data.message && undefined === this.data.titleMessage && this.messageObjs.length <= 0) {
this.data.titleMessage = 'Please Check Server Connection';
}
});
if (!flgFoundKey) {
return new RegExp(/^[0-9]+$/).test(value);
} else {
return false;
}
this.logger.warn(this.messageObjs);
}
onClose(dialogRes: any) {

@ -0,0 +1,27 @@
<div fxLayout="row">
<div fxFlex="100" class="padding-gap-large">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">{{data.alertTitle || 'ERROR'}}</span>
</div>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header>
<mat-card-content class="mt-5px mb-0 error-alert-block">
<div fxLayout="column">
<p *ngIf="data.titleMessage" fxLayoutAlign="start center" class="pb-1">{{data.titleMessage}}</p>
<h4 fxLayoutAlign="start" class="font-bold-500">Error Code</h4>
<span>{{data.message.code}}</span>
<mat-divider class="w-100 my-1"></mat-divider>
<h4 fxLayoutAlign="start" class="font-bold-500">Error Message</h4>
<span class="word-break">{{errorMessage}}</span>
<mat-divider class="w-100 my-1"></mat-divider>
<h4 fxLayoutAlign="start" class="font-bold-500">API URL</h4>
<span class="word-break">{{data.message.URL}}</span>
<mat-divider class="w-100 my-1"></mat-divider>
<div fxLayout="row" fxLayoutAlign="end center">
<button fxLayoutAlign="center center" tabindex="1" autoFocus mat-raised-button color="primary" fxFlex="20" type="submit" [mat-dialog-close]="false" default>OK</button>
</div>
</div>
</mat-card-content>
</div>
</div>

@ -0,0 +1,28 @@
import { Component, OnInit, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { LoggerService } from '../../../services/logger.service';
import { ErrorData } from '../../../models/alertData';
@Component({
selector: 'rtl-error-message',
templateUrl: './error-message.component.html',
styleUrls: ['./error-message.component.scss']
})
export class ErrorMessageComponent implements OnInit {
public errorMessage = '';
constructor(public dialogRef: MatDialogRef<ErrorMessageComponent>, @Inject(MAT_DIALOG_DATA) public data: ErrorData, private logger: LoggerService) { }
ngOnInit() {
this.errorMessage = (typeof(this.data.message.message) === 'object') ? JSON.stringify(this.data.message.message) : this.data.message.message;
if (undefined === this.data.message && undefined === this.data.titleMessage && !this.data.message) {
this.data.titleMessage = 'Please Check Server Connection';
}
this.logger.info(this.data.message);
}
onClose() {
this.dialogRef.close(false);
}
}

@ -4,7 +4,7 @@ import { faReceipt } from '@fortawesome/free-solid-svg-icons';
import { MatSnackBar } from '@angular/material/snack-bar';
import { LoggerService } from '../../../services/logger.service';
import { AlertData } from '../../../models/alertData';
import { InvoiceInformation } from '../../../models/alertData';
import { Invoice } from '../../../models/lndModels';
@Component({
@ -18,10 +18,10 @@ export class InvoiceInformationComponent implements OnInit {
public newlyAdded = false;
public invoice: Invoice;
constructor(public dialogRef: MatDialogRef<InvoiceInformationComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private logger: LoggerService, private snackBar: MatSnackBar) { }
constructor(public dialogRef: MatDialogRef<InvoiceInformationComponent>, @Inject(MAT_DIALOG_DATA) public data: InvoiceInformation, private logger: LoggerService, private snackBar: MatSnackBar) { }
ngOnInit() {
this.invoice = JSON.parse(this.data.message);
this.invoice = this.data.invoice;
this.newlyAdded = this.data.newlyAdded;
}

@ -1,6 +1,6 @@
<div fxLayout="row">
<div fxFlex="35" fxLayoutAlign="center start" class="modal-qr-code-container padding-gap-large">
<qrcode [qrdata]="address.address" [size]="230" [level]="'L'" [allowEmptyString]="true" class="qr-border"></qrcode>
<qrcode [qrdata]="address" [size]="230" [level]="'L'" [allowEmptyString]="true" class="qr-border"></qrcode>
</div>
<div fxFlex="65" class="padding-gap-large">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header mb-2">
@ -15,19 +15,19 @@
<div fxLayout="row">
<div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">Address Type</h4>
<span class="foreground-secondary-text">{{address.addressType}}</span>
<span class="foreground-secondary-text">{{addressType}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">Address</h4>
<span class="overflow-wrap foreground-secondary-text">{{address.address}}</span>
<span class="overflow-wrap foreground-secondary-text">{{address}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<div class="mt-2" fxLayout="row" fxLayoutAlign="end center">
<button autoFocus fxFlex="33" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="1" type="submit" rtlClipboard [payload]="address.address" (copied)="onCopyAddress($event)">Copy Address</button>
<button autoFocus fxFlex="33" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="1" type="submit" rtlClipboard [payload]="address" (copied)="onCopyAddress($event)">Copy Address</button>
</div>
</div>
</mat-card-content>

@ -4,7 +4,7 @@ import { faReceipt } from '@fortawesome/free-solid-svg-icons';
import { MatSnackBar } from '@angular/material/snack-bar';
import { LoggerService } from '../../../services/logger.service';
import { AlertData } from '../../../models/alertData';
import { OnChainAddressInformation } from '../../../models/alertData';
@Component({
selector: 'rtl-on-chain-generated-address',
@ -13,12 +13,14 @@ import { AlertData } from '../../../models/alertData';
})
export class OnChainGeneratedAddressComponent implements OnInit {
public faReceipt = faReceipt;
public address: {address: '', addressType: ''};
public address = '';
public addressType = '';
constructor(public dialogRef: MatDialogRef<OnChainGeneratedAddressComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private logger: LoggerService, private snackBar: MatSnackBar) { }
constructor(public dialogRef: MatDialogRef<OnChainGeneratedAddressComponent>, @Inject(MAT_DIALOG_DATA) public data: OnChainAddressInformation, private logger: LoggerService, private snackBar: MatSnackBar) { }
ngOnInit() {
this.address = JSON.parse(this.data.message);
this.address = this.data.address;
this.addressType = this.data.addressType;
}
onClose() {

@ -3,7 +3,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { Store } from '@ngrx/store';
import { Peer, GetInfo } from '../../../models/lndModels';
import { AlertData } from '../../../models/alertData';
import { OpenChannelAlert } from '../../../models/alertData';
import { TRANS_TYPES } from '../../../services/consts-enums-functions';
import * as RTLActions from '../../../../store/rtl.actions';
@ -27,13 +27,12 @@ export class OpenChannelComponent implements OnInit {
public transTypeValue = {blocks: '', fees: ''};
public transTypes = TRANS_TYPES;
constructor(public dialogRef: MatDialogRef<OpenChannelComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private store: Store<fromRTLReducer.RTLState>) { }
constructor(public dialogRef: MatDialogRef<OpenChannelComponent>, @Inject(MAT_DIALOG_DATA) public data: OpenChannelAlert, private store: Store<fromRTLReducer.RTLState>) { }
ngOnInit() {
let JSONdata = JSON.parse(this.data.message);
this.peer = JSONdata.peer;
this.information = JSONdata.information;
this.totalBalance = JSONdata.balance;
this.peer = this.data.message.peer;
this.information = this.data.message.information;
this.totalBalance = this.data.message.balance;
this.newlyAdded = this.data.newlyAdded;
this.alertTitle = this.data.alertTitle;
}

@ -4,7 +4,7 @@ import { faReceipt } from '@fortawesome/free-solid-svg-icons';
import { MatSnackBar } from '@angular/material/snack-bar';
import { LoggerService } from '../../../services/logger.service';
import { AlertData } from '../../../models/alertData';
import { ShowPubkeyData } from '../../../models/alertData';
import { GetInfoRoot } from '../../../models/RTLconfig';
@Component({
@ -18,11 +18,10 @@ export class ShowPubkeyComponent implements OnInit {
public infoTypes = [{infoID: 0, infoKey: 'node pubkey', infoName: 'Node pubkey'}, { infoID: 1, infoKey: 'node URI', infoName: 'Node URI'}];
public selInfoType = this.infoTypes[0];
constructor(public dialogRef: MatDialogRef<ShowPubkeyComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private logger: LoggerService, private snackBar: MatSnackBar) { }
constructor(public dialogRef: MatDialogRef<ShowPubkeyComponent>, @Inject(MAT_DIALOG_DATA) public data: ShowPubkeyData, private logger: LoggerService, private snackBar: MatSnackBar) { }
ngOnInit() {
this.information = JSON.parse(this.data.message);
this.information.uris[0]
this.information = this.data.information;
}
onClose() {

@ -1,15 +1,17 @@
<div fxLayout="column" fxLayoutAlign="center center">
<mat-card class="mat-elevation-z24 not-found-box">
<div fxLayout="column" fxLayoutAlign="center center" class="bg-primary py-2">
<button mat-fab color="accent" class="mat-elevation-z12">
<mat-icon>error</mat-icon>
</button>
<h1 class="error">{{error.errorCode}}</h1>
</div>
<mat-card-content fxLayout="row" fxLayoutAlign="center center">
<mat-card fxLayout="column" fxLayoutAlign="center center" class="mat-elevation-z12 w-100">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faTimes" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Error {{error.errorCode}}</span>
</div>
<div fxLayout="column" class="padding-gap-x">
<mat-card>
<mat-card-content fxLayout="column" class="padding-gap-large">
<div fxLayout="column" fxLayoutAlign="start start">
<div class="box-text">{{error.errorMessage}}</div>
</mat-card>
<span fxLayout="row" fxLayoutAlign="center" fxFlex="80">
<button mat-raised-button color="primary" class="mt-2" type="button" (click)="goToHelp()">Go To Help</button>
</span>
</div>
</mat-card-content>
</mat-card>
</div>

@ -1,8 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { Subject } from 'rxjs';
import { filter, map, takeUntil } from 'rxjs/operators';
import { takeUntil } from 'rxjs/operators';
import { faTimes } from '@fortawesome/free-solid-svg-icons';
@Component({
selector: 'rtl-error',
@ -10,9 +11,10 @@ import { filter, map, takeUntil } from 'rxjs/operators';
})
export class ErrorComponent implements OnInit {
error = {errorCode: '', errorMessage: ''};
public faTimes = faTimes;
private unsubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(private router: Router, private activatedRoute: ActivatedRoute) { }
constructor(private activatedRoute: ActivatedRoute, private router: Router) { }
ngOnInit() {
this.activatedRoute.paramMap
@ -22,4 +24,8 @@ export class ErrorComponent implements OnInit {
});
}
goToHelp(): void {
this.router.navigate(['/help']);
}
}

@ -1,12 +1,11 @@
<div fxLayout="column">
<div class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Help</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content *ngFor="let helpTopic of helpTopics">
<div fxLayout="column" fxFlex="100">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faQuestion" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Help</span>
</div>
<div fxLayout="row" fxFlex="100" class="padding-gap-x" fxLayoutAlign="start start">
<mat-card fxLayout="column" fxFlex="100" class="padding-gap-large">
<mat-card-content fxFlex="100" *ngFor="let helpTopic of helpTopics">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>{{helpTopic.question}}</mat-panel-title>
@ -17,4 +16,5 @@
</mat-card-content>
</mat-card>
</div>
</div>
</div>

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { faQuestion } from '@fortawesome/free-solid-svg-icons';
export class HelpTopic {
question: string;
@ -17,13 +18,13 @@ export class HelpTopic {
})
export class HelpComponent implements OnInit {
public helpTopics: Array<HelpTopic> = [];
public faQuestion = faQuestion;
constructor() {}
ngOnInit() {
// this.helpTopics.push(new HelpTopic('Set LND home directory?',
// 'Pass the directroy information while getting the server up with --lndir "local-lnd-path".<br>Example: node rtl --lndir C:\lnd\dir\path'));
this.helpTopics.push(new HelpTopic('Change theme?', 'Click on rotating setting icon on the right side of the screen and choose from the given options.'));
this.helpTopics.push(new HelpTopic('Change setting?', 'Click on setting icon on the navigation and choose from the given options.'));
// this.helpTopics.push(new HelpTopic('', ''));
}
}

@ -69,7 +69,7 @@ export class HorizontalNavigationComponent implements OnInit, OnDestroy {
onClick(node) {
if (node.name === 'Logout') {
this.store.dispatch(new RTLActions.OpenConfirmation({
width: '70%', data: { type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Logout', titleMessage: 'Logout from this device?', noBtnText: 'Cancel', yesBtnText: 'Logout'
width: '55%', data: { type: AlertTypeEnum.CONFIRM, alertTitle: 'Logout', titleMessage: 'Logout from this device?', noBtnText: 'Cancel', yesBtnText: 'Logout'
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unSubs[2]))

@ -118,7 +118,7 @@ export class SideNavigationComponent implements OnInit, OnDestroy {
onClick(node: MenuChildNode) {
if (node.name === 'Logout') {
this.store.dispatch(new RTLActions.OpenConfirmation({
width: '70%', data: { type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Logout', titleMessage: 'Logout from this device?', noBtnText: 'Cancel', yesBtnText: 'Logout'
width: '55%', data: { type: AlertTypeEnum.CONFIRM, alertTitle: 'Logout', titleMessage: 'Logout from this device?', noBtnText: 'Cancel', yesBtnText: 'Logout'
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unSubs[3]))

@ -79,7 +79,7 @@ export class TopMenuComponent implements OnInit, OnDestroy {
onClick() {
this.store.dispatch(new RTLActions.OpenConfirmation({
width: '70%', data: { type: AlertTypeEnum.CONFIRM, alertTitle: 'Confirm Logout', titleMessage: 'Logout from this device?', noBtnText: 'Cancel', yesBtnText: 'Logout'
width: '55%', data: { type: AlertTypeEnum.CONFIRM, alertTitle: 'Logout', titleMessage: 'Logout from this device?', noBtnText: 'Cancel', yesBtnText: 'Logout'
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unSubs[3]))

@ -1,16 +1,16 @@
<div fxLayout="column" fxLayoutAlign="center center">
<mat-card class="mat-elevation-z24 not-found-box">
<div fxLayout="column" fxLayoutAlign="center center" class="bg-primary">
<button mat-fab color="accent" class="mat-elevation-z12">
<mat-icon>error</mat-icon>
</button>
<h1 class="error">404</h1>
</div>
<mat-card-content fxLayout="row" fxLayoutAlign="center center">
<mat-card fxLayout="column" fxLayoutAlign="center center" class="mat-elevation-z12 w-100">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faTimes" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Page Not Found</span>
</div>
<div fxLayout="column" class="padding-gap-x">
<mat-card>
<mat-card-content fxLayout="column" class="padding-gap-large">
<div fxLayout="column" fxLayoutAlign="start start">
<div class="box-text">This page does not exist!</div>
<button mat-raised-button color="primary" class="mat-elevation-z12 padding-gap-x" type="button" (click)="goToHelp()">HELP</button>
</mat-card>
<span fxLayout="row" fxLayoutAlign="center" fxFlex="80">
<button mat-raised-button color="primary" class="mt-2" type="button" (click)="goToHelp()">Go To Help</button>
</span>
</div>
</mat-card-content>
</mat-card>
</div>

@ -1,12 +1,14 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { faTimes } from '@fortawesome/free-solid-svg-icons';
@Component({
selector: 'rtl-not-found',
templateUrl: './not-found.component.html'
})
export class NotFoundComponent {
public faTimes = faTimes;
constructor(public router: Router) {}
goToHelp(): void {

@ -1,27 +1,28 @@
<div fxLayout="column">
<div class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Show Configurations</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-md="row wrap" class="mb-2">
<mat-radio-group fxFlex="20" fxLayoutAlign="start" (change)="onSelectionChange($event)" class="mt-1 mb-1">
<mat-radio-button class="pr-5" value="rtl" [checked]="selectedNodeType=='rtl'">RTL</mat-radio-button>
<mat-radio-button class="pr-5" value="ln" *ngIf="showLnConfig" [checked]="selectedNodeType=='ln'">{{lnImplementationStr}}</mat-radio-button>
<mat-radio-button class="pr-5" value="bitcoind" *ngIf="showBitcoind" [checked]="selectedNodeType=='bitcoind'">BITCOIND</mat-radio-button>
<div fxLayout="column" fxFlex="100">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-title-container">
<fa-icon [icon]="faCog" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Show Configurations</span>
</div>
<div fxLayout="row" class="padding-gap-x" fxLayoutAlign="start start">
<mat-card fxLayout="column" fxFlex="100" class="padding-gap-large">
<mat-card-content class="card-content-gap">
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-md="row wrap">
<mat-radio-group color="primary" fxFlex="20" fxLayoutAlign="start" (change)="onSelectionChange($event)" class="mt-1 mb-1">
<mat-radio-button tabindex="1" class="pr-5" value="rtl" [checked]="selectedNodeType=='rtl'">RTL</mat-radio-button>
<mat-radio-button tabindex="2" class="pr-5" value="ln" *ngIf="showLnConfig" [checked]="selectedNodeType=='ln'">{{lnImplementationStr}}</mat-radio-button>
<mat-radio-button tabindex="3" class="pr-5" value="bitcoind" *ngIf="showBitcoind" [checked]="selectedNodeType=='bitcoind'">BITCOIND</mat-radio-button>
</mat-radio-group>
<div fxFlex="30" fxLayoutAlign="space-between stretch">
<button fxFlex="50" fxLayoutAlign="center center" mat-raised-button color="primary" (click)="onShowConfig()" tabindex="2">Show Config</button>
<button fxFlex="50" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="3" type="reset" class="ml-2" (click)="resetData()">Clear</button>
<div fxFlex="30" fxLayoutAlign="space-between center">
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="4" type="reset" (click)="resetData()">Clear</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" (click)="onShowConfig()" tabindex="5">Show Config</button>
</div>
</form>
<div *ngIf="configData !== '' && fileFormat === 'JSON'">
<mat-divider *ngIf="configData !== ''" class="my-1"></mat-divider>
<div *ngIf="configData !== '' && fileFormat === 'JSON'" class="mt-2 mb-6">
<pre>{{configData | json}}</pre>
<mat-divider *ngIf="configData !== ''" class="my-1"></mat-divider>
</div>
<div *ngIf="configData !== '' && fileFormat === 'INI'">
<div *ngIf="configData !== '' && fileFormat === 'INI'" class="mt-2">
<mat-list>
<mat-list-item *ngFor="let conf of configData; index as i;">
<mat-card-subtitle class="my-1">
@ -38,3 +39,4 @@
</mat-card>
</div>
</div>

@ -7,6 +7,7 @@ import { LightningNode } from '../../models/RTLconfig';
import { RTLEffects } from '../../../store/rtl.effects';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
import { faCog } from '@fortawesome/free-solid-svg-icons';
@Component({
selector: 'rtl-server-config',
@ -21,18 +22,17 @@ export class ServerConfigComponent implements OnInit, OnDestroy {
public showBitcoind = false;
public configData = '';
public fileFormat = 'INI';
private unsubs: Array<Subject<void>> = [new Subject(), new Subject()];
public faCog = faCog;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects) {}
ngOnInit() {
this.store.select('root')
.pipe(takeUntil(this.unsubs[0]))
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsRoot.forEach(effectsErr => {
if (effectsErr.action === 'fetchConfig') {
this.resetData();
}
if (effectsErr.action === 'fetchConfig') { this.resetData(); }
});
this.configData = '';
this.showLnConfig = false;
@ -63,7 +63,7 @@ export class ServerConfigComponent implements OnInit, OnDestroy {
this.store.dispatch(new RTLActions.OpenSpinner('Opening Config File...'));
this.store.dispatch(new RTLActions.FetchConfig(this.selectedNodeType));
this.rtlEffects.showLnConfig
.pipe(takeUntil(this.unsubs[1]))
.pipe(takeUntil(this.unSubs[1]))
.subscribe((config: any) => {
const configFile = config.data;
this.fileFormat = config.format;
@ -83,7 +83,7 @@ export class ServerConfigComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
this.unsubs.forEach(completeSub => {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});

@ -1,3 +1,21 @@
import { DataTypeEnum } from '../services/consts-enums-functions';
import { GetInfoRoot } from './RTLconfig';
import { GetInfo, Invoice } from './lndModels';
export interface MessageErrorField {
code: number;
message: string | any;
URL: string;
}
export interface MessageDataField {
key: string;
value: any;
title: string;
width: number;
type?: DataTypeEnum;
}
export interface InputData {
placeholder: string;
inputValue?: string | number | boolean;
@ -7,21 +25,63 @@ export interface InputData {
step?: number;
}
export interface OpenChannelAlert {
alertTitle?: string;
titleMessage?: string;
message?: { peer: any, information: GetInfo, balance: number };
newlyAdded?: boolean;
component?: any;
}
export interface InvoiceInformation {
invoice: Invoice;
newlyAdded?: boolean;
component?: any;
}
export interface OnChainAddressInformation {
alertTitle?: string;
address: string;
addressType: string;
component?: any;
}
export interface ShowPubkeyData {
information: GetInfoRoot;
component?: any;
}
export interface AlertData {
type: string; // INFORMATION/WARNING/ERROR/SUCCESS/CONFIRM
type: string; // INFORMATION/WARNING/SUCCESS/ERROR
alertTitle?: string;
titleMessage?: string;
message?: string;
messageFieldsBreakdown?: Array<number>;
message?: Array<Array<MessageDataField>>;
showQRName?: string;
showQRField?: string;
newlyAdded?: boolean;
component?: any;
}
export interface ConfirmationData {
type: string; // INFORMATION/WARNING/SUCCESS/ERROR
alertTitle?: string;
titleMessage?: string;
message?: any;
noBtnText?: string;
yesBtnText?: string;
flgShowInput?: boolean;
getInputs?: Array<InputData>;
newlyAdded?: boolean;
component?: any;
}
export interface ErrorData {
alertTitle?: string;
titleMessage?: string;
message?: MessageErrorField;
component?: any;
}
export interface DialogConfig {
width: string;
data: AlertData;
data: AlertData | ConfirmationData | ErrorData | OpenChannelAlert | InvoiceInformation | OnChainAddressInformation | ShowPubkeyData;
}

@ -1,4 +1,4 @@
import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faProjectDiagram, faCog, faLifeRing, faSearch, faTools } from '@fortawesome/free-solid-svg-icons';
import { faTachometerAlt, faLink, faBolt, faExchangeAlt, faUsers, faProjectDiagram, faCog, faQuestion, faSearch, faTools } from '@fortawesome/free-solid-svg-icons';
export const MENU_DATA: MenuRootNode = {
LNDChildren: [
@ -12,7 +12,7 @@ export const MENU_DATA: MenuRootNode = {
]},
{id: 4, parentId: 0, name: 'Advanced', iconType: 'FA', icon: faCog, link: '/sconfig'},
{id: 5, parentId: 0, name: 'Settings', iconType: 'FA', icon: faTools, link: '/settings'},
{id: 6, parentId: 0, name: 'Help', iconType: 'FA', icon: faLifeRing, link: '/help'}
{id: 6, parentId: 0, name: 'Help', iconType: 'FA', icon: faQuestion, link: '/help'}
],
CLChildren: [
{id: 1, parentId: 0, name: 'Dashboard', iconType: 'FA', icon: faTachometerAlt, link: '/cl/home'},
@ -25,7 +25,7 @@ export const MENU_DATA: MenuRootNode = {
]},
{id: 4, parentId: 0, name: 'Advanced', iconType: 'FA', icon: faCog, link: '/sconfig'},
{id: 5, parentId: 0, name: 'Settings', iconType: 'FA', icon: faTools, link: '/settings'},
{id: 6, parentId: 0, name: 'Help', iconType: 'FA', icon: faLifeRing, link: '/help'}
{id: 6, parentId: 0, name: 'Help', iconType: 'FA', icon: faQuestion, link: '/help'}
]
};

@ -52,3 +52,13 @@ export enum CurrencyUnitEnum {
LTC = 'LTC',
OTHER = 'OTHER'
}
export enum DataTypeEnum {
ARRAY = 'ARRAY',
NUMBER = 'NUMBER',
STRING = 'STRING',
BOOLEAN = 'BOOLEAN',
PASSWORD = 'PASSWORD',
DATE = 'DATE',
DATE_TIME = 'DATE_TIME'
}

@ -21,6 +21,7 @@ import { OnChainGeneratedAddressComponent } from './components/data-modal/on-cha
import { AppSettingsComponent } from './components/app-settings/app-settings.component';
import { AlertMessageComponent } from './components/data-modal/alert-message/alert-message.component';
import { ConfirmationMessageComponent } from './components/data-modal/confirmation-message/confirmation-message.component';
import { ErrorMessageComponent } from './components/data-modal/error-message/error-message.component';
import { SpinnerDialogComponent } from './components/data-modal/spinner-dialog/spinner-dialog.component';
import { NotFoundComponent } from './components/not-found/not-found.component';
import { SigninComponent } from './components/signin/signin.component';
@ -120,6 +121,7 @@ import { ShowPubkeyComponent } from './components/data-modal/show-pubkey/show-pu
OnChainGeneratedAddressComponent,
AlertMessageComponent,
ConfirmationMessageComponent,
ErrorMessageComponent,
SpinnerDialogComponent,
NotFoundComponent,
SideNavigationComponent,
@ -141,6 +143,7 @@ import { ShowPubkeyComponent } from './components/data-modal/show-pubkey/show-pu
OnChainGeneratedAddressComponent,
AlertMessageComponent,
ConfirmationMessageComponent,
ErrorMessageComponent,
SpinnerDialogComponent,
NotFoundComponent,
SideNavigationComponent,
@ -164,7 +167,8 @@ import { ShowPubkeyComponent } from './components/data-modal/show-pubkey/show-pu
ShowPubkeyComponent,
SpinnerDialogComponent,
AlertMessageComponent,
ConfirmationMessageComponent
ConfirmationMessageComponent,
ErrorMessageComponent
],
providers: [
{ provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { hasBackdrop: true, autoFocus: true, disableClose: true, role: 'dialog', width: '700px' } },

@ -259,10 +259,18 @@ body {
margin-top: 1rem !important;
}
.mb-0 {
margin-bottom: 0 !important;
}
.mb-1 {
margin-bottom: 1rem !important;
}
.mb-6 {
margin-bottom: 6rem !important;
}
.ml-1 {
margin-left: 1rem !important;
}
@ -343,6 +351,10 @@ body {
margin: 2rem 0 !important;
}
.my-4 {
margin: 4rem 0 !important;
}
.m-2 {
margin: 2rem !important;
}
@ -435,6 +447,10 @@ body {
padding: 0 2rem !important;
}
.px-3 {
padding: 0 3rem !important;
}
.px-4 {
padding: 0 4rem !important;
}
@ -653,7 +669,7 @@ body {
}
.not-found-box {
min-width: 30%;
min-width: 50%;
}
.w-100 {
@ -771,10 +787,6 @@ table {
width:100%;
}
// .mat-button-focus-overlay {
// background-color: transparent!important;
// }
.green-dot {
display: inline-flex;
width: $dot-size;

@ -13,7 +13,7 @@ import { environment, API_URL } from '../../environments/environment';
import { LoggerService } from '../shared/services/logger.service';
import { SessionService } from '../shared/services/session.service';
import { Settings, RTLConfiguration } from '../shared/models/RTLconfig';
import { AuthenticateWith, CURRENCY_UNITS, AlertTypeEnum } from '../shared/services/consts-enums-functions';
import { AuthenticateWith, CURRENCY_UNITS, AlertTypeEnum, DataTypeEnum } from '../shared/services/consts-enums-functions';
import { SpinnerDialogComponent } from '../shared/components/data-modal/spinner-dialog/spinner-dialog.component';
import { AlertMessageComponent } from '../shared/components/data-modal/alert-message/alert-message.component';
@ -22,6 +22,7 @@ import { ShowPubkeyComponent } from '../shared/components/data-modal/show-pubkey
import * as RTLActions from './rtl.actions';
import * as fromRTLReducer from './rtl.reducers';
import { ErrorMessageComponent } from '../shared/components/data-modal/error-message/error-message.component';
@Injectable()
export class RTLEffects implements OnDestroy {
@ -102,11 +103,8 @@ export class RTLEffects implements OnDestroy {
if (!this.sessionService.getItem('token') || !rootData.nodeData.identity_pubkey) {
this.snackBar.open('Node Pubkey does not exist.');
} else {
this.store.dispatch(new RTLActions.OpenAlert({width: '70%',
data: {
type: AlertTypeEnum.INFORMATION,
alertTitle: '',
message: JSON.stringify(rootData.nodeData),
this.store.dispatch(new RTLActions.OpenAlert({width: '70%', data: {
information: rootData.nodeData,
component: ShowPubkeyComponent
}}));
}
@ -156,7 +154,11 @@ export class RTLEffects implements OnDestroy {
this.logger.info(updateStatus);
return {
type: RTLActions.OPEN_ALERT,
payload: { config : { width: '70%', data: { type: AlertTypeEnum.SUCCESS, titleMessage: (!updateStatus.length) ? updateStatus.message : updateStatus[0].message + '. ' + updateStatus[1].message }}}
payload: { width: '55%', data: {
type: AlertTypeEnum.SUCCESS,
alertTitle: 'Settings updated',
titleMessage: (!updateStatus.length) ? updateStatus.message : updateStatus[0].message + '. ' + updateStatus[1].message
}}
};
},
catchError((err) => {
@ -352,11 +354,11 @@ export class RTLEffects implements OnDestroy {
} else {
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
width: '70%', data: {
width: '55%', data: {
type: alertType,
alertTitle: alertTitle,
titleMessage: alertTitle,
message: JSON.stringify({ code: err.status, Message: err.error.error, URL: errURL })
message: { code: err.status, message: err.error.error, URL: errURL },
component: ErrorMessageComponent
}
}));
}

@ -18,7 +18,7 @@ const initNodeAuthentication = { nodeAuthType: 'CUSTOM', configPath: '', bitcoin
const initRootState: RootState = {
effectErrorsRoot: [],
selNode: {settings: initNodeSettings, authentication: initNodeAuthentication},
selNode: {settings: initNodeSettings, authentication: initNodeAuthentication, lnImplementation: 'LND'},
appConfig: {
defaultNodeIndex: -1,
selectedNodeIndex: -1,

Loading…
Cancel
Save