Lightning Invoice

Lightning Invoice
pull/260/head
Shahana Farooqui 5 years ago
parent a629cb235c
commit 1f13f7bce7

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -9,8 +9,8 @@
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicon/favicon-16x16.png">
<link rel="manifest" href="assets/images/favicon/site.webmanifest">
<link rel="stylesheet" href="styles.58896416c21696e94583.css"></head>
<link rel="stylesheet" href="styles.bec74f2f13e5712d0bd8.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.10fdea7ff19f81f29517.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.d5c80aae84fe3f881d64.js"></script></body>
<script src="runtime.624cb39eb39feee9569a.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.92172f3208b83ec77830.js"></script></body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
!function(e){function r(r){for(var n,i,a=r[0],c=r[1],f=r[2],p=0,s=[];p<a.length;p++)o[i=a[p]]&&s.push(o[i][0]),o[i]=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,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:"df9093d1e13d9e6f0394",6:"156118a5fd225700d103",7:"325ae7790ee297067bcc"}[e]+".js"}(e);var c=new Error;u=function(r){a.onerror=a.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: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||[],c=a.push.bind(a);a.push=r,a=a.slice();for(var f=0;f<a.length;f++)r(a[f]);var l=c;t()}([]);
!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:"1f534535205fd170f4b8",6:"fcf8cc2d0ffb9c7af5ec",7:"5148e351b6e8445fab11"}[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()}([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -90,7 +90,7 @@ common.convertToBTC = (num) => {
};
common.convertTimestampToDate = (num) => {
return new Date(+num * 1000).toUTCString();
return new Date(+num * 1000).toUTCString().substring(5, 22).replace(' ', '/').replace(' ', '/').toUpperCase();
};
common.sortAscByKey = (array, key) => {

@ -85,10 +85,10 @@ 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! Logging out!');
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: {
type: 'WARN',
titleMessage: 'Time limit exceeded for session inactivity! Logging out!'
}}));
}}}));
this.store.dispatch(new RTLActions.Signout());
this.userIdle.resetTimer();
}

@ -72,10 +72,10 @@
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="channels" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="close">
<th mat-header-cell *matHeaderCellDef> Close Channel </th>
<td mat-cell *matCellDef="let channel">

@ -179,10 +179,10 @@ 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({ config: { width: '75%', data: {
type: 'WARN',
titleMessage: 'Channel can not be closed when it is in AWAITING UNILATERAL state.'
}}));
}}}));
} else {
this.store.dispatch(new RTLActions.OpenConfirmation({
width: '70%', data: { type: 'CONFIRM', titleMessage: 'Closing channel: ' + channelToClose.channel_id, noBtnText: 'Cancel', yesBtnText: 'Close Channel'
@ -217,10 +217,10 @@ export class CLChannelsComponent implements OnInit, OnDestroy {
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));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedChannel)
}}));
}}}));
}
loadChannelsTable(channels) {

@ -42,10 +42,10 @@
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="forwardingHistoryEvents" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Status</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent?.status}}</td>

@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -85,19 +84,15 @@ export class CLForwardingHistoryComponent implements OnInit, OnDestroy {
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: {
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedFHEvent)
}}));
}}}));
}
loadForwardingEventsTable(forwardingEvents: ForwardingEventCL[]) {
this.forwardingHistoryEvents = new MatTableDataSource<ForwardingEventCL>([...forwardingEvents]);
this.forwardingHistoryEvents.sort = this.sort;
this.forwardingHistoryEvents.data.forEach(event => {
event.received_time_str = (event.received_time_str === '') ? '' : formatDate(event.received_time_str, 'dd/MMM/yyyy HH:mm', 'en-US');
event.resolved_time_str = (event.resolved_time_str === '') ? '' : formatDate(event.resolved_time_str, 'dd/MMM/yyyy HH:mm', 'en-US');
});
this.logger.info(this.forwardingHistoryEvents);
}

@ -45,10 +45,10 @@
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="invoices" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th>
<td mat-cell *matCellDef="let invoice">

@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -122,23 +121,15 @@ export class CLInvoicesComponent implements OnInit, OnDestroy {
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: {
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedInvoice)
}}));
}}}));
}
loadInvoicesTable(invoices) {
this.invoices = new MatTableDataSource<InvoiceCL>([...invoices]);
this.invoices.sort = this.sort;
this.invoices.data.forEach(invoice => {
if (undefined !== invoice.paid_at_str) {
invoice.paid_at_str = (invoice.paid_at_str === '') ? '' : formatDate(invoice.paid_at_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
if (undefined !== invoice.expires_at_str) {
invoice.expires_at_str = (invoice.expires_at_str === '') ? '' : formatDate(invoice.expires_at_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
});
setTimeout(() => { this.flgAnimate = false; }, 5000);
this.logger.info(this.invoices);
}

@ -1,5 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -21,14 +20,6 @@ export class CLChannelLookupComponent implements OnInit {
constructor(private store: Store<fromRTLReducer.RTLState>) { }
ngOnInit() {
if (this.lookupResult.length > 0 && undefined !== this.lookupResult[0].last_update_str) {
this.lookupResult[0].last_update_str = (this.lookupResult[0].last_update_str === '') ?
'' : formatDate(this.lookupResult[0].last_update_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
if (this.lookupResult.length > 1 && undefined !== this.lookupResult[1].last_update_str) {
this.lookupResult[1].last_update_str = (this.lookupResult[1].last_update_str === '') ?
'' : formatDate(this.lookupResult[1].last_update_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
this.store.select('cl')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {

@ -1,5 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { formatDate } from '@angular/common';
import { LoggerService } from '../../../shared/services/logger.service';
import { LookupNodeCL } from '../../../shared/models/clModels';
@ -15,12 +14,6 @@ export class CLNodeLookupComponent implements OnInit {
constructor(private logger: LoggerService) { }
ngOnInit() {
this.logger.info(this.lookupResult);
if (undefined !== this.lookupResult && undefined !== this.lookupResult.last_timestamp_str) {
this.lookupResult.last_timestamp_str = (this.lookupResult.last_timestamp_str === '') ?
'' : formatDate(this.lookupResult.last_timestamp_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
}
ngOnInit() {}
}

@ -40,10 +40,10 @@
<div class="padding-gap">
<mat-card>
<mat-card-content class="table-card-content">
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="qRoutes" matSort
[ngClass]="{'mat-elevation-z8 overflow-x-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-x-auto': true}">
[ngClass]="{'overflow-x-auto error-border': flgLoading[0]==='error','overflow-x-auto': true}">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header> ID </th>
<td mat-cell *matCellDef="let route"> {{route?.id}} </td>

@ -85,7 +85,7 @@ export class CLQueryRoutesComponent implements OnInit, OnDestroy {
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: 'INFO', message: JSON.stringify(reorderedRoute)}}));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: { type: 'INFO', message: JSON.stringify(reorderedRoute)}}}));
}
ngOnDestroy() {

@ -38,10 +38,10 @@
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="payments" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let payment">{{payment?.id}}</td>

@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -72,9 +71,6 @@ export class CLPaymentsComponent implements OnInit, OnDestroy {
this.payments = (undefined === rtlStore.payments || null == rtlStore.payments) ? new MatTableDataSource([]) : new MatTableDataSource<PaymentCL>([...this.paymentJSONArr]);
this.payments.data = this.paymentJSONArr;
this.payments.sort = this.sort;
this.payments.data.forEach(payment => {
payment.created_at_str = (payment.created_at_str === '') ? '' : formatDate(payment.created_at_str, 'dd/MMM/yyyy HH:mm', 'en-US');
});
setTimeout(() => { this.flgAnimate = false; }, 3000);
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== this.paymentJSONArr) ? false : true;
@ -94,18 +90,10 @@ export class CLPaymentsComponent implements OnInit, OnDestroy {
.pipe(take(1))
.subscribe(decodedPayment => {
this.paymentDecoded = decodedPayment;
if (undefined !== this.paymentDecoded.created_at_str) {
this.paymentDecoded.created_at_str = (this.paymentDecoded.created_at_str === '') ? '' :
formatDate(this.paymentDecoded.created_at_str, 'dd/MMM/yyyy HH:mm', 'en-US');
this.paymentDecoded.expire_at_str = (this.paymentDecoded.expire_at_str === '') ? '' :
formatDate(this.paymentDecoded.expire_at_str, 'dd/MMM/yyyy HH:mm', 'en-US');
if (undefined === this.paymentDecoded.msatoshi) {
this.paymentDecoded.msatoshi = 0;
}
this.sendPayment();
} else {
this.resetData();
if (undefined === this.paymentDecoded.msatoshi) {
this.paymentDecoded.msatoshi = 0;
}
this.sendPayment();
});
}
}
@ -172,10 +160,10 @@ export class CLPaymentsComponent implements OnInit, OnDestroy {
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: {
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedPayment)
}}));
}}}));
}
applyFilter(selFilter: string) {

@ -32,9 +32,9 @@
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="peers" matSort [ngClass]="{'mat-elevation-z8 overflow-x-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-x-auto': true}">
<table mat-table #table [dataSource]="peers" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="detach">
<th mat-header-cell *matHeaderCellDef>Detach</th>
<td mat-cell *matCellDef="let peer"><mat-icon color="accent" (click)="onPeerDetach(peer)">link_off</mat-icon></td>

@ -106,7 +106,7 @@ export class CLPeersComponent implements OnInit, OnDestroy {
const reorderedPeer = JSON.parse(JSON.stringify(selPeer, [
'id', 'alias', 'connected', 'netaddr', 'globalfeatures', 'localfeatures'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: { type: 'INFO', message: JSON.stringify(reorderedPeer)}}));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: { type: 'INFO', message: JSON.stringify(reorderedPeer)}}}));
}
resetData() {

@ -5,7 +5,6 @@ import { Store } from '@ngrx/store';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { Subject, of } from 'rxjs';
import { map, mergeMap, catchError, withLatestFrom } from 'rxjs/operators';
import { formatDate } from '@angular/common';
import { Location } from '@angular/common';
import { environment, API_URL } from '../../../environments/environment';
@ -211,7 +210,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: 'SUCCESS', titleMessage: 'Peer Added Successfully!' } }));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '70%', data: { type: 'SUCCESS', titleMessage: 'Peer Added Successfully!' }}}));
return {
type: RTLActions.SET_PEERS_CL,
payload: (undefined !== postRes && postRes.length > 0) ? postRes : []
@ -234,7 +233,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: 'SUCCESS', titleMessage: 'Peer Detached Successfully!' } }));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '70%', data: { type: 'SUCCESS', titleMessage: 'Peer Detached Successfully!' }}}));
return {
type: RTLActions.REMOVE_PEER_CL,
payload: { id: action.payload.id }
@ -303,7 +302,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: 'SUCCESS', titleMessage: 'Channel Updated Successfully!' } }));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '70%', data: { type: 'SUCCESS', titleMessage: 'Channel Updated Successfully!' }}}));
return {
type: RTLActions.FETCH_CHANNELS_CL
};
@ -404,10 +403,10 @@ 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 {
this.store.dispatch(new RTLActions.OpenAlert({
this.store.dispatch(new RTLActions.OpenAlert({ config: {
width: '70%',
data: { type: 'SUCCESS', titleMessage: 'Payment Sent Successfully!', message: JSON.stringify(sendRes) }
}));
}}));
this.store.dispatch(new RTLActions.FetchChannelsCL());
this.store.dispatch(new RTLActions.FetchBalanceCL());
this.store.dispatch(new RTLActions.FetchPaymentsCL());
@ -573,10 +572,10 @@ export class CLEffects implements OnDestroy {
map((postRes: any) => {
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
this.store.dispatch(new RTLActions.OpenAlert({ config: {
width: '70%',
data: { type: 'SUCCESS', titleMessage: 'Invoices Deleted Successfully!' }
}));
}}));
return {
type: RTLActions.FETCH_INVOICES_CL,
payload: { num_max_invoices: 100, reversed: true }
@ -602,14 +601,14 @@ export class CLEffects implements OnDestroy {
postRes.label = action.payload.label;
postRes.msatoshi = action.payload.amount;
postRes.description = action.payload.description;
postRes.expires_at_str = new Date(postRes.expires_at * 1000).toUTCString();
postRes.expires_at_str = formatDate(postRes.expires_at_str, 'dd/MMM/yyyy HH:mm', 'en-US');
postRes.expires_at = Math.round(new Date().getTime() / 1000);
postRes.expires_at_str = new Date(+postRes.expires_at * 1000).toUTCString();
this.logger.info(postRes);
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
this.store.dispatch(new RTLActions.OpenAlert({ config: {
width: '70%',
data: { type: 'SUCCESS', titleMessage: 'Invoice Added Successfully!', message: JSON.stringify(postRes) }
}));
}}));
return {
type: RTLActions.FETCH_INVOICES_CL,
payload: { num_max_invoices: 100, reversed: true }
@ -705,12 +704,11 @@ export class CLEffects implements OnDestroy {
this.store.dispatch(new RTLActions.FetchFeeRatesCL('perkb'));
this.store.dispatch(new RTLActions.FetchPeersCL());
let newRoute = this.location.path();
if(newRoute.includes('/lnd/')) {
newRoute = newRoute.replace('/lnd/', '/cl/');
}
if (newRoute.includes('/login') || newRoute.includes('/error') || newRoute === '' || landingPage === 'HOME' || newRoute.includes('?access-key=')) {
newRoute = '/cl/home';
} else {
if(newRoute.includes('/lnd/')) {
newRoute = newRoute.replace('/lnd/', '/cl/');
}
}
this.router.navigate([newRoute]);
}
@ -732,12 +730,12 @@ export class CLEffects implements OnDestroy {
this.store.dispatch(new RTLActions.Signout());
} else {
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
this.store.dispatch(new RTLActions.OpenAlert({ config: {
width: '70%', data: {
type: alerType, titleMessage: alertTitle,
message: JSON.stringify({ code: err.status, Message: err.error.error, URL: errURL })
}
}));
}}));
}
}

@ -26,9 +26,9 @@
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="channels" matSort [ngClass]="{'mat-elevation-z8 overflow-x-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-x-auto': true}">
<table mat-table #table [dataSource]="channels" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="chan_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Channel Point </th>
<td mat-cell *matCellDef="let channel">{{channel?.channel_point}}</td>

@ -94,10 +94,10 @@ export class ChannelBackupComponent implements OnInit, OnDestroy {
'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: {
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedChannel)
}}));
}}}));
}
applyFilter(selFilter: string) {

@ -12,9 +12,9 @@
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="closedChannels" matSort [ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
<table mat-table #table [dataSource]="closedChannels" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="close_type">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Close Type </th>
<td mat-cell *matCellDef="let channel"> {{channel.close_type}} </td>

@ -85,10 +85,10 @@ export class ChannelClosedComponent implements OnInit, OnDestroy {
})[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: {
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedChannel)
}}));
}}}));
}
loadClosedChannelsTable(closedChannels) {

@ -63,9 +63,9 @@
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="channels" matSort [ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
<table mat-table #table [dataSource]="channels" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="close">
<th mat-header-cell *matHeaderCellDef> Close Channel </th>
<td mat-cell *matCellDef="let channel"><mat-icon color="accent" (click)="onChannelClose(channel)">link_off</mat-icon></td>

@ -209,10 +209,10 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
'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: {
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedChannel)
}}));
}}}));
}
loadChannelsTable(channels) {

@ -26,7 +26,7 @@
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<mat-table #table perfectScrollbar [dataSource]="pendingOpenChannels" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="remote_node_pub">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Remote Node Pub </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.remote_node_pub}}</mat-cell>
@ -90,7 +90,7 @@
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<mat-table #table perfectScrollbar [dataSource]="pendingForceClosingChannels" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="remote_node_pub">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Remote Node Pub </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.remote_node_pub}}</mat-cell>
@ -160,7 +160,7 @@
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<mat-table #table perfectScrollbar [dataSource]="pendingClosingChannels" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="remote_node_pub">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Remote Node Pub </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.remote_node_pub}}</mat-cell>
@ -206,7 +206,7 @@
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<mat-table #table perfectScrollbar [dataSource]="pendingWaitClosingChannels" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="remote_node_pub">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Remote Node Pub </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.remote_node_pub}}</mat-cell>

@ -139,10 +139,10 @@ export class ChannelPendingComponent implements OnInit, OnDestroy {
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: {
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedChannel)
}}));
}}}));
}
onForceClosingClick(selRow: any, event: any) {
@ -153,10 +153,10 @@ export class ChannelPendingComponent implements OnInit, OnDestroy {
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: {
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedChannel)
}}));
}}}));
}
onClosingClick(selRow: any, event: any) {
@ -167,10 +167,10 @@ export class ChannelPendingComponent implements OnInit, OnDestroy {
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: {
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedChannel)
}}));
}}}));
}
onWaitClosingClick(selRow: any, event: any) {
@ -181,10 +181,10 @@ export class ChannelPendingComponent implements OnInit, OnDestroy {
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: {
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedChannel)
}}));
}}}));
}
loadOpenChannelsTable(channels) {

@ -45,10 +45,10 @@
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="channels" matSort
[ngClass]="{'mat-elevation-z8 overflow-x-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-x-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="chan_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Channel Point </th>
<td mat-cell *matCellDef="let channel">{{channel?.channel_point}}</td>

@ -1,84 +0,0 @@
<div fxLayout="column">
<div class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Invoices</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<form fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign.gt-sm="space-between center" (ngSubmit)="addInvoiceForm.form.valid && onAddInvoice(addInvoiceForm)" #addInvoiceForm="ngForm">
<mat-form-field fxFlex="30" fxLayoutAlign="start end">
<input matInput [(ngModel)]="memo" placeholder="Memo" tabindex="1" name="memo">
</mat-form-field>
<mat-form-field fxFlex="15" fxLayoutAlign="start end">
<input matInput [(ngModel)]="invoiceValue" placeholder="Invoice Value ({{information?.smaller_currency_unit}})" type="number" step="100" min="1" tabindex="2" name="invoiceValue">
</mat-form-field>
<mat-form-field fxFlex="15" fxLayoutAlign="start end">
<input matInput [(ngModel)]="expiry" placeholder="Expiry (Sec)" type="number" step="100" min="1" tabindex="3" name="expiry">
</mat-form-field>
<div fxFlex="15" tabindex="4" fxLayoutAlign="start center" class="chkbox-private">
<mat-checkbox [(ngModel)]="private" matTooltip="Include routing hints for private channels" [matTooltipPosition]="'above'" name="private">Private</mat-checkbox>
</div>
<button fxFlex="10" fxLayoutAlign="center center" mat-raised-button color="primary" type="submit" tabindex="5">Add</button>
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="6" type="reset" (click)="resetData()">Clear</button>
</form>
</mat-card-content>
</mat-card>
</div>
<div class="padding-gap">
<mat-card>
<mat-card-content class="table-card-content">
<div fxLayout="row" fxLayoutAlign="start start">
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="invoices" matSort [ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
<ng-container matColumnDef="settled">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Settled </th>
<td mat-cell *matCellDef="let invoice">
<span *ngIf="invoice.settled"><i class="material-icons primary">done_all</i></span>
<span *ngIf="!invoice.settled"><i class="material-icons accent">done</i></span>
</td>
</ng-container>
<ng-container matColumnDef="creation_date">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Creation Date </th>
<td mat-cell *matCellDef="let invoice">{{invoice.creation_date_str}}</td>
</ng-container>
<ng-container matColumnDef="settle_date">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Settle Date </th>
<td mat-cell *matCellDef="let invoice">{{invoice.settle_date_str}}</td>
</ng-container>
<ng-container matColumnDef="memo">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Memo </th>
<td mat-cell *matCellDef="let invoice">{{invoice.memo}}</td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Value ({{(selNode?.satsToBTC) ? information?.currency_unit : information?.smaller_currency_unit}}) </th>
<td mat-cell *matCellDef="let invoice"><span fxLayoutAlign="end center"> {{(selNode?.satsToBTC) ? (invoice?.btc_value | number:'1.0-3') : (invoice?.value | number)}} </span></td>
</ng-container>
<ng-container matColumnDef="expiry">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Expiry (Sec)</th>
<td mat-cell *matCellDef="let invoice"><span fxLayoutAlign="end center"> {{invoice.expiry | number}} </span></td>
</ng-container>
<ng-container matColumnDef="cltv_expiry">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> CLTV Expiry </th>
<td mat-cell *matCellDef="let invoice"><span fxLayoutAlign="end center"> {{invoice.cltv_expiry | number}} </span></td>
</ng-container>
<ng-container matColumnDef="amt_paid_sat">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Amount Paid ({{(selNode?.satsToBTC) ? information?.currency_unit : information?.smaller_currency_unit}})</th>
<td mat-cell *matCellDef="let invoice"><span fxLayoutAlign="end center"> {{(selNode?.satsToBTC) ? (invoice?.btc_amt_paid_sat | number:'1.0-3') : (invoice?.amt_paid_sat | number)}} </span></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.memo == newlyAddedInvoiceMemo && row.value == newlyAddedInvoiceValue && flgAnimate) ? 'added' : 'notAdded'" (click)="onInvoiceClick(row, $event)" class="row-invoices"
[ngClass]="{'settled': row.settled, 'unsettled': !row.settled}"></tr>
</table>
<mat-paginator [length]="totalInvoices" [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" (page)="onPageChange($event)"></mat-paginator>
</div>
</mat-card-content>
</mat-card>
</div>
</div>

@ -1,16 +0,0 @@
.mat-column-value {
padding-right: 1rem;
}
.mat-column-settled {
padding-left: 1rem;
}
.chkbox-private:focus {
outline: none !important;
}
table {
width:100%;
border-collapse: collapse;
}

@ -1,164 +0,0 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { SelNodeChild } from '../../shared/models/RTLconfig';
import { GetInfo, Invoice } from '../../shared/models/lndModels';
import { LoggerService } from '../../shared/services/logger.service';
import { newlyAddedRowAnimation } from '../../shared/animation/row-animation';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
@Component({
selector: 'rtl-invoices',
templateUrl: './invoices.component.html',
styleUrls: ['./invoices.component.scss'],
animations: [newlyAddedRowAnimation]
})
export class InvoicesComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
public selNode: SelNodeChild = {};
public newlyAddedInvoiceMemo = '';
public newlyAddedInvoiceValue = 0;
public flgAnimate = true;
public memo = '';
public expiry: number;
public invoiceValue: number;
public displayedColumns = [];
public invoicePaymentReq = '';
public invoices: any;
public information: GetInfo = {};
public flgLoading: Array<Boolean | 'error'> = [true];
public flgSticky = false;
public private = false;
public totalInvoices = 100;
public pageSize = 25;
public pageSizeOptions = [5, 10, 25, 100];
private firstOffset = -1;
private lastOffset = -1;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions) {
switch (true) {
case (window.innerWidth <= 415):
this.displayedColumns = ['settled', 'creation_date', 'memo', 'value'];
break;
case (window.innerWidth > 415 && window.innerWidth <= 730):
this.displayedColumns = ['settled', 'creation_date', 'settle_date', 'memo', 'value', 'amt_paid_sat'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['settled', 'creation_date', 'settle_date', 'memo', 'value', 'amt_paid_sat'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['settled', 'creation_date', 'settle_date', 'memo', 'value', 'amt_paid_sat', 'expiry', 'cltv_expiry'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['settled', 'creation_date', 'settle_date', 'memo', 'value', 'amt_paid_sat', 'expiry', 'cltv_expiry'];
break;
}
}
ngOnInit() {
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsLnd.forEach(effectsErr => {
if (effectsErr.action === 'FetchInvoices') {
this.flgLoading[0] = 'error';
}
});
this.selNode = rtlStore.nodeSettings;
this.information = rtlStore.information;
this.totalInvoices = rtlStore.totalInvoices;
this.firstOffset = +rtlStore.invoices.first_index_offset;
this.lastOffset = +rtlStore.invoices.last_index_offset;
this.logger.info(rtlStore);
this.loadInvoicesTable(rtlStore.invoices.invoices ? rtlStore.invoices.invoices : []);
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== rtlStore.invoices) ? false : true;
}
});
}
onAddInvoice(form: any) {
this.flgAnimate = true;
this.newlyAddedInvoiceMemo = this.memo;
this.newlyAddedInvoiceValue = this.invoiceValue;
this.store.dispatch(new RTLActions.OpenSpinner('Adding Invoice...'));
this.store.dispatch(new RTLActions.SaveNewInvoice({
memo: this.memo, invoiceValue: this.invoiceValue, private: this.private, expiry: (this.expiry ? this.expiry : 3600), pageSize: this.pageSize
}));
this.resetData();
}
onInvoiceClick(selRow: Invoice, event: any) {
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: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedInvoice)
}}));
}
loadInvoicesTable(invoices) {
this.invoices = new MatTableDataSource<Invoice>([...invoices]);
this.invoices.sort = this.sort;
this.invoices.data.forEach(invoice => {
if (undefined !== invoice.creation_date_str) {
invoice.creation_date_str = (invoice.creation_date_str === '') ? '' : formatDate(invoice.creation_date_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
if (undefined !== invoice.settle_date_str) {
invoice.settle_date_str = (invoice.settle_date_str === '') ? '' : formatDate(invoice.settle_date_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
});
setTimeout(() => { this.flgAnimate = false; }, 5000);
this.logger.info(this.invoices);
}
resetData() {
this.memo = '';
this.invoiceValue = 0;
this.private = false;
this.expiry = undefined;
}
applyFilter(selFilter: string) {
this.invoices.filter = selFilter;
}
onPageChange(event: any) {
let reversed = true;
let index_offset = this.firstOffset;
if (event.pageIndex < event.previousPageIndex) {
reversed = false;
index_offset = this.lastOffset;
}
if (event.pageIndex === event.previousPageIndex) {
reversed = true;
index_offset = 0;
}
this.store.dispatch(new RTLActions.FetchInvoices({num_max_invoices: event.pageSize, index_offset: index_offset, reversed: reversed}));
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -8,7 +8,7 @@ import { LNDRootComponent } from './lnd-root.component';
import { HomeComponent } from './home/home.component';
import { PeersComponent } from './peers/peers.component';
import { SendReceiveTransComponent } from './old-transactions/send-receive/send-receive-trans.component';
import { InvoicesComponent } from './invoices/invoices.component';
import { LightningInvoicesComponent } from './transactions/invoices/lightning-invoices.component';
import { UnlockLNDComponent } from './unlock-lnd/unlock-lnd.component';
import { LightningPaymentsComponent } from './transactions/payments/lightning-payments.component';
import { ChannelManageComponent } from './channels/channel-manage/channel-manage.component';
@ -39,7 +39,7 @@ import { LNDUnlockedGuard } from '../shared/services/auth.guard';
HomeComponent,
PeersComponent,
SendReceiveTransComponent,
InvoicesComponent,
LightningInvoicesComponent,
UnlockLNDComponent,
LightningPaymentsComponent,
ChannelManageComponent,

@ -11,9 +11,7 @@ import { PeersComponent } from './peers/peers.component';
import { TransactionsComponent } from './transactions/transactions.component';
import { SendReceiveTransComponent } from './old-transactions/send-receive/send-receive-trans.component';
import { ListTransactionsComponent } from './old-transactions/list-transactions/list-transactions.component';
import { LightningPaymentsComponent } from './transactions/payments/lightning-payments.component';
import { QueryRoutesComponent } from './payments/query-routes/query-routes.component';
import { InvoicesComponent } from './invoices/invoices.component';
import { LookupsComponent } from './lookups/lookups.component';
import { ForwardingHistoryComponent } from './switch/forwarding-history.component';
import { RoutingPeersComponent } from './routing-peers/routing-peers.component';
@ -37,9 +35,7 @@ export const LndRoutes: Routes = [
{ path: 'transactions', component: TransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'transsendreceive', component: SendReceiveTransComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'translist', component: ListTransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'paymentsend', component: LightningPaymentsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'queryroutes', component: QueryRoutesComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'invoices', component: InvoicesComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'switch', component: ForwardingHistoryComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'routingpeers', component: RoutingPeersComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'lookups', component: LookupsComponent, canActivate: [LNDUnlockedGuard] },

@ -1,5 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -21,10 +20,6 @@ export class ChannelLookupComponent implements OnInit {
constructor(private store: Store<fromRTLReducer.RTLState>) { }
ngOnInit() {
if (undefined !== this.lookupResult && undefined !== this.lookupResult.last_update_str) {
this.lookupResult.last_update_str = (this.lookupResult.last_update_str === '') ?
'' : formatDate(this.lookupResult.last_update_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {

@ -1,5 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { formatDate } from '@angular/common';
import { GraphNode } from '../../../shared/models/lndModels';
@ -14,11 +13,6 @@ export class NodeLookupComponent implements OnInit {
constructor() { }
ngOnInit() {
if (undefined !== this.lookupResult && undefined !== this.lookupResult.node && undefined !== this.lookupResult.node.last_update_str) {
this.lookupResult.node.last_update_str = (this.lookupResult.node.last_update_str === '') ?
'' : formatDate(this.lookupResult.node.last_update_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
}
ngOnInit() {}
}

@ -12,9 +12,9 @@
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="listTransactions" matSort [ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
<table mat-table #table [dataSource]="listTransactions" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="dest_addresses">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Destination Addresses</th>
<td mat-cell *matCellDef="let trans">{{trans?.dest_addresses?.length || 0}} Addr</td>

@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -88,20 +87,15 @@ export class ListTransactionsComponent implements OnInit, OnDestroy {
const reorderedTransactions = JSON.parse(JSON.stringify(selTransaction, [
'dest_addresses', 'time_stamp_str', 'num_confirmations', 'total_fees', 'block_hash', 'block_height', 'tx_hash', 'amount'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedTransactions)
}}));
}}}));
}
loadTransactionsTable(transactions) {
this.listTransactions = new MatTableDataSource<Transaction>([...transactions]);
this.listTransactions.sort = this.sort;
this.listTransactions.data.forEach(transaction => {
if (undefined !== transaction.time_stamp_str) {
transaction.time_stamp_str = (transaction.time_stamp_str === '') ? '' : formatDate(transaction.time_stamp_str, 'dd/MMM/yyyy HH:mm', 'en-US');
}
});
this.logger.info(this.listTransactions);
}

@ -38,10 +38,10 @@
<div class="padding-gap">
<mat-card>
<mat-card-content class="table-card-content">
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="qrHops" matSort
[ngClass]="{'mat-elevation-z8 overflow-x-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-x-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="hop_sequence">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Hop </th>
<td mat-cell *matCellDef="let hop"> {{hop?.hop_sequence}} </td>

@ -85,7 +85,7 @@ export class QueryRoutesComponent implements OnInit, OnDestroy {
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: 'INFO', message: JSON.stringify(reorderedHop)}}));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: { type: 'INFO', message: JSON.stringify(reorderedHop)}}}));
}
ngOnDestroy() {

@ -32,9 +32,9 @@
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="peers" matSort [ngClass]="{'mat-elevation-z8 overflow-x-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-x-auto': true}">
<table mat-table #table [dataSource]="peers" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="detach">
<th mat-header-cell *matHeaderCellDef>Detach</th>
<td mat-cell *matCellDef="let peer"><mat-icon color="accent" (click)="onPeerDetach(peer)">link_off</mat-icon></td>

@ -129,7 +129,7 @@ export class PeersComponent implements OnInit, OnDestroy {
const reorderedPeer = JSON.parse(JSON.stringify(selPeer, [
'pub_key', 'alias', 'address', 'bytes_sent', 'bytes_recv', 'sat_sent', 'sat_recv', 'inbound', 'ping_time'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: { type: 'INFO', message: JSON.stringify(reorderedPeer)}}));
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: { type: 'INFO', message: JSON.stringify(reorderedPeer)}}}));
}
resetData() {

@ -43,10 +43,10 @@
</mat-card-subtitle>
</mat-card-header>
<mat-card-content class="table-card-content" fxFlex="100">
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableIn [dataSource]="RoutingPeersIncoming" matSort fxFlex="100"
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Chan Id</th>
<td mat-cell *matCellDef="let rPeer" class="ellipsis-parent"><span class="ellipsis-child">{{rPeer.chan_id}}</span></td>
@ -79,10 +79,10 @@
</mat-card-subtitle>
</mat-card-header>
<mat-card-content class="table-card-content" fxFlex="100">
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableOut [dataSource]="RoutingPeersOutgoing" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Chan Id</th>
<td mat-cell *matCellDef="let rPeer" class="ellipsis-parent"><span

@ -96,10 +96,10 @@ export class RoutingPeersComponent implements OnInit, OnDestroy {
});
}
const reorderedRoutingPeer = JSON.parse(JSON.stringify(selRPeer, ['chan_id', 'alias', 'events', 'total_amount'] , 2));
this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedRoutingPeer)
}}));
}}}));
}
loadRoutingPeersTable(forwardingEvents: ForwardingEvent[]) {

@ -13,6 +13,7 @@ import { environment, API_URL } from '../../../environments/environment';
import { LoggerService } from '../../shared/services/logger.service';
import { SessionService } from '../../shared/services/session.service';
import { GetInfo, GetInfoChain, Fees, Balance, NetworkInfo, Payment, GraphNode, Transaction, SwitchReq, ListInvoices } from '../../shared/models/lndModels';
import { InvoiceInformationComponent } from '../../../shared/components/invoice-information/invoice-information.component';
import * as RTLActions from '../../store/rtl.actions';
import * as fromRTLReducer from '../../store/rtl.reducers';
@ -122,7 +123,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: 'SUCCESS', titleMessage: 'Peer Added Successfully!' } }));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '70%', data: { type: 'SUCCESS', titleMessage: 'Peer Added Successfully!' }}}));
return {
type: RTLActions.SET_PEERS,
payload: (undefined !== postRes && postRes.length > 0) ? postRes : []
@ -145,7 +146,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: 'SUCCESS', titleMessage: 'Peer Detached Successfully!' } }));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '70%', data: { type: 'SUCCESS', titleMessage: 'Peer Detached Successfully!' }}}));
return {
type: RTLActions.REMOVE_PEER,
payload: { pubkey: action.payload.pubkey }
@ -178,9 +179,13 @@ export class LNDEffects implements OnDestroy {
this.store.dispatch(new RTLActions.CloseSpinner());
const msg = { payment_request: postRes.payment_request };
this.store.dispatch(new RTLActions.OpenAlert({
width: '70%',
data: { type: 'SUCCESS', titleMessage: 'Invoice Added Successfully!', message: JSON.stringify(msg) }
}));
config: { width: '58%', data: { type: 'INFO', message: JSON.stringify(postRes)}},
component: InvoiceInformationComponent
}));
// this.store.dispatch(new RTLActions.OpenAlert({ config: {
// width: '70%',
// data: { type: 'SUCCESS', titleMessage: 'Invoice Added Successfully!', message: JSON.stringify(msg) }
// }}));
return {
type: RTLActions.FETCH_INVOICES,
payload: { num_max_invoices: action.payload.pageSize, reversed: true }
@ -232,7 +237,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: 'SUCCESS', titleMessage: 'Channel Updated Successfully!' } }));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '70%', data: { type: 'SUCCESS', titleMessage: 'Channel Updated Successfully!' }}}));
return {
type: RTLActions.FETCH_CHANNELS,
payload: { routeParam: 'all', channelStatus: '' }
@ -287,7 +292,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: 'SUCCESS', titleMessage: action.payload.showMessage + ' ' + postRes.message } }));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '70%', data: { type: 'SUCCESS', titleMessage: action.payload.showMessage + ' ' + postRes.message }}}));
return {
type: RTLActions.BACKUP_CHANNELS_RES,
payload: postRes.message
@ -312,7 +317,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: 'SUCCESS', titleMessage: postRes.message } }));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '70%', data: { type: 'SUCCESS', titleMessage: postRes.message }}}));
return {
type: RTLActions.VERIFY_CHANNELS_RES,
payload: postRes.message
@ -337,7 +342,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: 'SUCCESS', titleMessage: postRes.message } }));
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '70%', data: { type: 'SUCCESS', titleMessage: postRes.message }}}));
this.store.dispatch(new RTLActions.SetRestoreChannelsList(postRes.list));
return {
type: RTLActions.RESTORE_CHANNELS_RES,
@ -587,14 +592,14 @@ export class LNDEffects implements OnDestroy {
this.logger.error('Error: ' + sendRes.payment_error);
return {
type: RTLActions.OPEN_ALERT,
payload: {
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] }
)
}
}
}}
};
} else {
const confirmationMsg = { 'Destination': action.payload[1].destination, 'Timestamp': action.payload[1].timestamp_str, 'Expiry': action.payload[1].expiry };
@ -604,10 +609,10 @@ export class LNDEffects implements OnDestroy {
msg['Total Fee (' + ((undefined === store.nodeData.smaller_currency_unit) ? 'Sats' : store.nodeData.smaller_currency_unit) + ')'] =
(sendRes.payment_route.total_fees_msat / 1000);
Object.assign(msg, confirmationMsg);
this.store.dispatch(new RTLActions.OpenAlert({
this.store.dispatch(new RTLActions.OpenAlert({ config: {
width: '70%',
data: { type: 'SUCCESS', titleMessage: 'Payment Sent Successfully!', message: JSON.stringify(msg) }
}));
}}));
this.store.dispatch(new RTLActions.FetchChannels({ routeParam: 'all' }));
this.store.dispatch(new RTLActions.FetchBalance('channels'));
this.store.dispatch(new RTLActions.FetchPayments());
@ -1032,12 +1037,11 @@ export class LNDEffects implements OnDestroy {
this.store.dispatch(new RTLActions.FetchInvoices({num_max_invoices: 25, reversed: true}));
this.store.dispatch(new RTLActions.FetchPayments());
let newRoute = this.location.path();
if (newRoute.includes('/unlock') || newRoute.includes('/login') || newRoute.includes('/error') || newRoute === '' || landingPage === 'HOME' || newRoute.includes('?access-key=')) {
if(newRoute.includes('/cl/')) {
newRoute = newRoute.replace('/cl/', '/lnd/');
}
if(newRoute.includes('/unlock') || newRoute.includes('/login') || newRoute.includes('/error') || newRoute === '' || landingPage === 'HOME' || newRoute.includes('?access-key=')) {
newRoute = '/lnd/home';
} else {
if(newRoute.includes('/cl/')) {
newRoute = newRoute.replace('/cl/', '/lnd/');
}
}
this.router.navigate([newRoute]);
}
@ -1059,12 +1063,12 @@ export class LNDEffects implements OnDestroy {
this.store.dispatch(new RTLActions.Signout());
} else {
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
this.store.dispatch(new RTLActions.OpenAlert({config: {
width: '70%', data: {
type: alertType, titleMessage: alertTitle,
message: JSON.stringify({ code: err.status, Message: err.error.error, URL: errURL })
}
}));
}}));
}
}

@ -37,10 +37,10 @@
<div class="padding-gap">
<mat-card>
<mat-card-content class="table-card-content">
<div perfectScrollbar class="table-container mat-elevation-z8">
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="forwardingHistoryEvents" matSort
[ngClass]="{'mat-elevation-z8 overflow-auto error-border': flgLoading[0]==='error','mat-elevation-z8 overflow-auto': true}">
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="timestamp">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Timestamp</th>
<td mat-cell *matCellDef="let fhEvent">{{fhEvent.timestamp_str}}</td>

@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -83,19 +82,15 @@ export class ForwardingHistoryComponent implements OnInit, OnDestroy {
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: {
this.store.dispatch(new RTLActions.OpenAlert({ config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedFHEvent)
}}));
}}}));
}
loadForwardingEventsTable(forwardingEvents: ForwardingEvent[]) {
this.forwardingHistoryEvents = new MatTableDataSource<ForwardingEvent>([...forwardingEvents]);
this.forwardingHistoryEvents.sort = this.sort;
this.forwardingHistoryEvents.data.forEach(event => {
event.timestamp_str = (event.timestamp_str === '') ? '' : formatDate(event.timestamp_str, 'dd/MMM/yyyy HH:mm', 'en-US');
});
this.logger.info(this.forwardingHistoryEvents);
}

@ -0,0 +1,81 @@
<div fxLayout="column">
<form #addInvoiceForm="ngForm">
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign.gt-sm="start center">
<mat-form-field fxFlex="100" fxLayoutAlign="start end">
<input matInput [(ngModel)]="memo" placeholder="Memo" tabindex="1" name="memo">
</mat-form-field>
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxFlex="60" fxLayoutAlign.gt-sm="space-between center">
<mat-form-field fxFlex="50" fxLayoutAlign="start end">
<input matInput [(ngModel)]="invoiceValue" (keyup)="onInvoiceValueChange()" placeholder="Amount" type="number" step="100" min="1" tabindex="2" name="invoiceValue">
<span matSuffix> {{information?.smaller_currency_unit}} </span>
<mat-hint>{{invoiceValueHint}}</mat-hint>
</mat-form-field>
<mat-form-field fxFlex="15" fxLayoutAlign="start end">
<input matInput [(ngModel)]="expiry" placeholder="Expiry" type="number" step="{{selTimeUnit === 'Secs' ? 300 : selTimeUnit === 'Mins' ? 10 : selTimeUnit === 'Hours' ? 2 : 1}}" min="1" tabindex="3" name="expiry">
<span matSuffix> {{selTimeUnit}} </span>
</mat-form-field>
<mat-form-field fxFlex="15" fxLayoutAlign="start end">
<mat-select [value]="selTimeUnit" tabindex="4" required name="timeUnit" (selectionChange)="onTimeUnitChange($event)">
<mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">{{timeUnit}}</mat-option>
</mat-select>
</mat-form-field>
<div fxFlex="15" tabindex="4" fxLayoutAlign="start center">
<mat-slide-toggle color="primary" [(ngModel)]="private" matTooltip="Include routing hints for private channels" [matTooltipPosition]="'above'" name="private">Private</mat-slide-toggle>
</div>
</div>
</div>
<div class="mt-2">
<button fxFlex="48" fxFlex.gt-md="10" fxLayoutAlign="center center" class="mr-2" mat-raised-button color="primary" [disabled]="addInvoiceForm.form.invalid" (click)="onAddInvoice(addInvoiceForm)" tabindex="5" class="mr-2">
<p *ngIf="addInvoiceForm.form.invalid; else createText">Invalid values</p>
<ng-template #createText><p>Create Invoice</p></ng-template>
</button>
<button fxFlex="10" fxLayoutAlign="center center" mat-stroked-button color="accent" tabindex="6" type="reset" (click)="resetData()">Clear Field</button>
</div>
</form>
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-2">
<div fxFlex="70">
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Invoices History</span>
</div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="invoices" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="settled">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Settled </th>
<td mat-cell *matCellDef="let invoice">
<span *ngIf="invoice.settled"><i class="material-icons primary">done_all</i></span>
<span *ngIf="!invoice.settled"><i class="material-icons primary">done</i></span>
</td>
</ng-container>
<ng-container matColumnDef="creation_date">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Date Created </th>
<td mat-cell *matCellDef="let invoice">{{invoice.creation_date_str}}</td>
</ng-container>
<ng-container matColumnDef="memo">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Memo </th>
<td mat-cell *matCellDef="let invoice">{{invoice.memo}}</td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Value ({{(selNode?.satsToBTC) ? information?.currency_unit : information?.smaller_currency_unit}}) </th>
<td mat-cell *matCellDef="let invoice"><span fxLayoutAlign="end center"> {{(selNode?.satsToBTC) ? (invoice?.btc_value | number:'1.0-3') : (invoice?.value | number)}} </span></td>
</ng-container>
<ng-container matColumnDef="settle_date">
<th mat-header-cell *matHeaderCellDef mat-sort-header class="pl-4"> Date Settled </th>
<td mat-cell *matCellDef="let invoice" class="pl-4">{{invoice.settle_date_str || '-'}}</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="pr-3"><span fxLayoutAlign="end center">Actions</span></th>
<td mat-cell *matCellDef="let invoice">
<button mat-stroked-button color="accent" type="button" tabindex="4" (click)="onInvoiceClick(invoice, $event)">View Info</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.memo == newlyAddedInvoiceMemo && row.value == newlyAddedInvoiceValue && flgAnimate) ? 'added' : 'notAdded'" class="row-invoices"></tr>
</table>
<mat-paginator [length]="totalInvoices" [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" (page)="onPageChange($event)" showFirstLastButtons class="mb-4"></mat-paginator>
</div>
</div>

@ -0,0 +1,4 @@
.mat-column-actions {
flex: 0 0 5%;
width: 5%;
}

@ -0,0 +1,270 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort } from '@angular/material';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { GetInfo, Invoice } from '../../../shared/models/lndModels';
import { CurrencyUnitConvertPipe } from '../../../shared/pipes/app.pipe';
import { LoggerService } from '../../../shared/services/logger.service';
import { InvoiceInformationComponent } from '../../../shared/components/invoice-information/invoice-information.component';
import { newlyAddedRowAnimation } from '../../../shared/animation/row-animation';
import * as RTLActions from '../../../store/rtl.actions';
import * as fromRTLReducer from '../../../store/rtl.reducers';
@Component({
selector: 'rtl-lightning-invoices',
templateUrl: './lightning-invoices.component.html',
styleUrls: ['./lightning-invoices.component.scss'],
animations: [newlyAddedRowAnimation]
})
export class LightningInvoicesComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
faHistory = faHistory;
public currencyUnits = [];
public currConvertorRate = null;
public selNode: SelNodeChild = {};
public newlyAddedInvoiceMemo = '';
public newlyAddedInvoiceValue = 0;
public flgAnimate = true;
public memo = '';
public expiry: number;
public invoiceValue: number;
public invoiceValueHint = '';
public displayedColumns = [];
public invoicePaymentReq = '';
public invoices: any;
public information: GetInfo = {};
public flgLoading: Array<Boolean | 'error'> = [true];
public flgSticky = false;
public private = false;
public timeUnits = ['Secs', 'Mins', 'Hours', 'Days'];
public selTimeUnit = 'Secs';
public expiryStep = 100;
public totalInvoices = 100;
public pageSize = 10;
public pageSizeOptions = [5, 10, 25, 100];
private firstOffset = -1;
private lastOffset = -1;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private httpClient: HttpClient, private currencyConvert: CurrencyUnitConvertPipe, private decimalPipe: DecimalPipe) {
switch (true) {
case (window.innerWidth <= 415):
this.displayedColumns = ['settled', 'creation_date', 'value', 'actions'];
break;
case (window.innerWidth > 415 && window.innerWidth <= 730):
this.displayedColumns = ['settled', 'creation_date', 'value', 'settle_date', 'actions'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['settled', 'creation_date', 'memo', 'value', 'settle_date', 'actions'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['settled', 'creation_date', 'memo', 'value', 'settle_date', 'actions'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['settled', 'creation_date', 'memo', 'value', 'settle_date', 'actions'];
break;
}
}
ngOnInit() {
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsLnd.forEach(effectsErr => {
if (effectsErr.action === 'FetchInvoices') {
this.flgLoading[0] = 'error';
}
});
this.currencyUnits = rtlStore.nodeSettings.currencyUnits;
this.selNode = rtlStore.nodeSettings;
this.information = rtlStore.information;
this.totalInvoices = rtlStore.totalInvoices;
this.firstOffset = +rtlStore.invoices.first_index_offset;
this.lastOffset = +rtlStore.invoices.last_index_offset;
this.logger.info(rtlStore);
this.loadInvoicesTable(rtlStore.invoices.invoices ? rtlStore.invoices.invoices : []);
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = (undefined !== rtlStore.invoices) ? false : true;
}
});
}
onAddInvoice(form: any) {
let expiryInSecs = (this.expiry ? this.expiry : 3600);
if (this.selTimeUnit !== this.timeUnits[0]) {
switch (this.selTimeUnit) {
case this.timeUnits[1]:
expiryInSecs = this.expiry * 60;
break;
case this.timeUnits[2]:
expiryInSecs = this.expiry * 3600;
break;
case this.timeUnits[3]:
expiryInSecs = this.expiry * 3600 * 24;
break;
default:
expiryInSecs = this.expiry;
break;
}
}
this.flgAnimate = true;
this.newlyAddedInvoiceMemo = this.memo;
this.newlyAddedInvoiceValue = this.invoiceValue;
this.store.dispatch(new RTLActions.OpenSpinner('Adding Invoice...'));
this.store.dispatch(new RTLActions.SaveNewInvoice({
memo: this.memo, invoiceValue: this.invoiceValue, private: this.private, expiry: expiryInSecs, pageSize: this.pageSize
}));
this.resetData();
}
onInvoiceClick(selRow: Invoice, event: any) {
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({
config: { width: '58%', data: { type: 'INFO', message: JSON.stringify(reorderedInvoice)}},
component: InvoiceInformationComponent
}));
}
loadInvoicesTable(invoices) {
this.invoices = new MatTableDataSource<Invoice>([...invoices]);
this.invoices.sort = this.sort;
setTimeout(() => { this.flgAnimate = false; }, 5000);
this.logger.info(this.invoices);
}
resetData() {
this.memo = '';
this.invoiceValue = 0;
this.private = false;
this.expiry = undefined;
}
applyFilter(selFilter: string) {
this.invoices.filter = selFilter;
}
onPageChange(event: any) {
let reversed = true;
let index_offset = this.firstOffset;
if (event.pageIndex < event.previousPageIndex) {
reversed = false;
index_offset = this.lastOffset;
}
if (event.pageIndex === event.previousPageIndex) {
reversed = true;
index_offset = 0;
}
this.store.dispatch(new RTLActions.FetchInvoices({num_max_invoices: event.pageSize, index_offset: index_offset, reversed: reversed}));
}
onInvoiceValueChange() {
let self = this;
if(this.currencyUnits[2] && this.invoiceValue && this.invoiceValue.toString().length > 2) {
if(!this.currConvertorRate) {
this.httpClient.get('https://blockchain.info/ticker')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((currConvertorData: any) => {
self.currConvertorRate = currConvertorData;
self.invoiceValueHint = '= ' + currConvertorData[self.currencyUnits[2]].symbol + self.decimalPipe.transform(self.currencyConvert.transform(self.invoiceValue.toString(), currConvertorData[self.currencyUnits[2]].last * 0.00000001), '1.2-2') + ' ' + self.currencyUnits[2];
});
} else {
self.invoiceValueHint = '= ' + this.currConvertorRate[self.currencyUnits[2]].symbol + self.decimalPipe.transform(self.currencyConvert.transform(self.invoiceValue.toString(), this.currConvertorRate[self.currencyUnits[2]].last * 0.00000001), '1.2-2') + ' ' + self.currencyUnits[2];
}
}
}
onTimeUnitChange(event: any) {
if(this.expiry && this.selTimeUnit !== event.value) {
switch (this.selTimeUnit) {
case this.timeUnits[0]:
switch (event.value) {
case this.timeUnits[1]:
this.expiry = this.expiry / 60;
break;
case this.timeUnits[2]:
this.expiry = this.expiry / 3600;
break;
case this.timeUnits[3]:
this.expiry = this.expiry / (3600 * 24);
break;
default:
break;
}
break;
case this.timeUnits[1]:
switch (event.value) {
case this.timeUnits[0]:
this.expiry = this.expiry * 60;
break;
case this.timeUnits[2]:
this.expiry = this.expiry / 60;
break;
case this.timeUnits[3]:
this.expiry = this.expiry / (60 * 24);
break;
default:
break;
}
break;
case this.timeUnits[2]:
switch (event.value) {
case this.timeUnits[0]:
this.expiry = this.expiry * 3600;
break;
case this.timeUnits[1]:
this.expiry = this.expiry * 60;
break;
case this.timeUnits[3]:
this.expiry = this.expiry / 24;
break;
default:
break;
}
break;
case this.timeUnits[3]:
switch (event.value) {
case this.timeUnits[0]:
this.expiry = this.expiry * 3600 * 24;
break;
case this.timeUnits[1]:
this.expiry = this.expiry * 60 * 24;
break;
case this.timeUnits[2]:
this.expiry = this.expiry * 24;
break;
default:
break;
}
break;
default:
break;
}
}
this.selTimeUnit = event.value;
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -1,17 +1,17 @@
<div fxLayout="column">
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-md="row wrap" #sendPaymentForm="ngForm" class="mb-2">
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-md="row wrap" #sendPaymentForm="ngForm">
<mat-form-field class="w-100">
<input matInput placeholder="Payment Request" name="paymentRequest" [(ngModel)]="paymentRequest" tabindex="1" required #paymentReq="ngModel">
</mat-form-field>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between start" fxLayoutAlign.gt-md="start start">
<button fxFlex="48" fxFlex.gt-md="10" fxLayoutAlign="center center" class="mr-2" mat-raised-button color="primary" [disabled]="paymentReq.invalid" (click)="onSendPayment()" tabindex="2">
<button fxFlex="48" fxFlex.gt-md="10" fxLayoutAlign="center center" class="mr-2" mat-raised-button color="primary" [disabled]="paymentReq.invalid" (click)="onSendPayment();" tabindex="2">
<p *ngIf="paymentReq.invalid && (paymentReq.dirty || paymentReq.touched); else sendText">Invalid Req</p>
<ng-template #sendText><p>Send Payment</p></ng-template>
</button>
<button fxFlex="48" fxFlex.gt-md="10" mat-stroked-button color="accent" type="reset" tabindex="3" type="reset" (click)="resetData()">Clear Field</button>
</div>
</form>
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-2">
<div fxFlex="70">
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Payments History</span>
@ -36,11 +36,11 @@
<td mat-cell *matCellDef="let payment"><span fxLayoutAlign="end center">{{payment?.fee | number}}</span></td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Value (sats)</th>
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Value (Sats)</th>
<td mat-cell *matCellDef="let payment"><span fxLayoutAlign="end center">{{payment?.value | number}}</span></td>
</ng-container>
<ng-container matColumnDef="path">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Path (hops)</th>
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Path (Hops)</th>
<td mat-cell *matCellDef="let payment"><span fxLayoutAlign="end center">{{payment?.path?.length || 0}}</span></td>
</ng-container>
<ng-container matColumnDef="actions">
@ -53,5 +53,5 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.payment_hash === newlyAddedPayment && flgAnimate) ? 'added' : 'notAdded'"></tr>
</table>
</div>
<mat-paginator [pageSizeOptions]="pageSizeOptions" showFirstLastButtons class="mb-4"></mat-paginator>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" showFirstLastButtons class="mb-4"></mat-paginator>
</div>

@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { formatDate } from '@angular/common';
import { Subject } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -30,6 +29,7 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
@ViewChild('sendPaymentForm', { static: true }) form;
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
faHistory = faHistory;
public pageSize = 10;
public newlyAddedPayment = '';
public flgAnimate = true;
public flgLoading: Array<Boolean | 'error'> = [true];
@ -80,9 +80,6 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
this.payments = (undefined === rtlStore.payments || null == rtlStore.payments) ? new MatTableDataSource([]) : new MatTableDataSource<Payment>([...this.paymentJSONArr]);
this.payments.data = this.paymentJSONArr;
this.payments.sort = this.sort;
this.payments.data.forEach(payment => {
payment.creation_date_str = (payment.creation_date_str === '') ? '' : formatDate(payment.creation_date_str, 'dd/MMM/yyyy HH:mm', 'en-US');
});
this.payments.paginator = this.paginator;
setTimeout(() => { this.flgAnimate = false; }, 3000);
if (this.flgLoading[0] !== 'error') {
@ -104,8 +101,6 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
.subscribe(decodedPayment => {
this.paymentDecoded = decodedPayment;
if (undefined !== this.paymentDecoded.timestamp_str) {
this.paymentDecoded.timestamp_str = (this.paymentDecoded.timestamp_str === '') ? '' :
formatDate(this.paymentDecoded.timestamp_str, 'dd/MMM/yyyy HH:mm', 'en-US');
if (undefined === this.paymentDecoded.num_satoshis) {
this.paymentDecoded.num_satoshis = '0';
}
@ -159,18 +154,13 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
this.store.dispatch(new RTLActions.DecodePayment(this.paymentRequest));
this.lndEffects.setDecodedPayment.subscribe(decodedPayment => {
this.paymentDecoded = decodedPayment;
if (undefined !== this.paymentDecoded.timestamp_str) {
this.paymentDecoded.timestamp_str = (this.paymentDecoded.timestamp_str === '') ? '' :
formatDate(this.paymentDecoded.timestamp_str, 'dd/MMM/yyyy HH:mm', 'en-US');
} else {
this.resetData();
}
});
}
resetData() {
this.form.reset();
this.paymentDecoded = {};
this.paymentRequest = '';
this.form.reset();
}
onPaymentClick(selRow: Payment, event: any) {
@ -184,10 +174,10 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
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: {
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: {
type: 'INFO',
message: JSON.stringify(reorderedPayment)
}}));
}}}));
}
applyFilter(selFilter: string) {

@ -18,7 +18,7 @@
<mat-card-content fxLayout="column">
<mat-tab-group>
<mat-tab label="Payments"><rtl-lightning-payments></rtl-lightning-payments></mat-tab>
<mat-tab label="Invoices">Invoices</mat-tab>
<mat-tab label="Invoices"><rtl-lightning-invoices></rtl-lightning-invoices></mat-tab>
</mat-tab-group>
</mat-card-content>
</mat-card>

@ -0,0 +1,84 @@
<div fxLayout="row">
<div fxFlex="35" fxLayoutAlign="center start" class="invoice-qr-code-container padding-gap-large">
<qrcode [qrdata]="invoice.payment_request" [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="invoice-info-header mb-2">
<div fxFlex="95" fxLayoutAlign="start start">
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Invoice Information</span>
</div>
<mat-icon fxFlex="5" type="button" (click)="onClose()" class="cursor-pointer icon-medium">close</mat-icon>
</mat-card-header>
<mat-card-content>
<div fxLayout="column">
<div fxLayout="row">
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Amount Requested</h4>
<span class="foreground-secondary-text">{{(invoice.value || 0) | number}} Sats</span>
</div>
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Memo</h4>
<span class="foreground-secondary-text">{{invoice.memo}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Date Created</h4>
<span class="foreground-secondary-text">{{invoice.creation_date_str}}</span>
</div>
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Date Settled</h4>
<span class="foreground-secondary-text">{{invoice.settle_date_str || '-'}}</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">Payment Request</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.payment_request}}</span>
</div>
</div>
<div *ngIf="showAdvanced">
<mat-divider class="w-100 my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">R Hash</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.r_hash}}</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">R Preimage</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.r_preimage || '-'}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
<div fxLayout="row">
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Expiry</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.expiry}}</span>
</div>
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">CLTV Expiry</h4>
<span class="overflow-wrap foreground-secondary-text">{{invoice.cltv_expiry}}</span>
</div>
</div>
<mat-divider class="w-100 my-1"></mat-divider>
</div>
<div [ngClass]="{'mt-2': !showAdvanced, 'mt-1': showAdvanced}" fxLayout="row" fxLayoutAlign="end center">
<button fxFlex="25" fxLayoutAlign="center center" class="mr-2" mat-stroked-button color="accent" type="reset" (click)="onShowAdvanced()" tabindex="1">
<p *ngIf="!showAdvanced; else hideAdvancedText">Show Advanced</p>
<ng-template #hideAdvancedText><p>Hide Advanced</p></ng-template>
</button>
<button fxFlex="33" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="2" type="submit" rtlClipboard [payload]="invoice.payment_request" (copied)="onCopyPayment($event)">
<p *ngIf="!flgCopied; else copiedText">Copy Payment Request</p>
<ng-template #copiedText><p>Copied</p></ng-template>
</button>
</div>
</div>
</mat-card-content>
</div>
</div>

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

@ -0,0 +1,39 @@
import { Component, OnInit, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { faReceipt } from '@fortawesome/free-solid-svg-icons';
import { LoggerService } from '../../../shared/services/logger.service';
import { AlertData } from '../../../shared/models/alertData';
import { Invoice } from '../../../shared/models/lndModels';
@Component({
selector: 'rtl-invoice-information',
templateUrl: './invoice-information.component.html',
styleUrls: ['./invoice-information.component.scss']
})
export class InvoiceInformationComponent implements OnInit {
public faReceipt = faReceipt;
public flgCopied = false;
public showAdvanced = false;
public invoice: Invoice;
constructor(public dialogRef: MatDialogRef<InvoiceInformationComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private logger: LoggerService) { }
ngOnInit() {
this.invoice = JSON.parse(this.data.message);
}
onClose() {
this.dialogRef.close(false);
}
onShowAdvanced() {
this.showAdvanced = !this.showAdvanced;
}
onCopyPayment(payload) {
this.flgCopied = true;
setTimeout(() => {this.flgCopied = false; }, 5000);
this.logger.info('Copied Text: ' + payload);
}
}

@ -4,7 +4,7 @@
{{node.lnNode}} ({{node.lnImplementation}})
</mat-option>
</mat-select>
<mat-divider class="w-100 mb-2"></mat-divider>
<mat-divider class="w-100 mb-1"></mat-divider>
<mat-tree [dataSource]="navMenus" [treeControl]="treeControlNested" *ngIf="settings.menuType === 'regular'">
<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle routerLinkActive="active-link" routerLink="{{node.link}}">
<div (click)="onChildNavClicked(node)">
@ -103,7 +103,7 @@
<fa-icon *ngIf="node.iconType === 'FA'" [icon]="node.icon" class="fa-icon-regular" matTooltip="{{node.name}}" matTooltipPosition="right"></fa-icon>
</mat-tree-node>
</mat-tree>
<mat-divider class="w-100 mt-2"></mat-divider>
<mat-divider class="w-100 mt-1"></mat-divider>
<mat-tree [dataSource]="navMenusShowData" [treeControl]="treeControlShowData" *ngIf="settings.menuType === 'regular'">
<mat-tree-node *matTreeNodeDef="let node" (click)="onShowData(node)">
<fa-icon *ngIf="node.iconType === 'FA'" [icon]="node.icon" class="fa-icon-small mr-4" matTooltip="{{node.name}}" matTooltipPosition="right"></fa-icon>

@ -14,7 +14,9 @@ import {
import { QRCodeModule } from 'angularx-qrcode';
import { NgxChartsModule } from '@swimlane/ngx-charts';
import { DecimalPipe } from '@angular/common';
import { InvoiceInformationComponent } from './components/invoice-information/invoice-information.component';
import { AppSettingsComponent } from './components/app-settings/app-settings.component';
import { AlertMessageComponent } from './components/alert-message/alert-message.component';
import { ConfirmationMessageComponent } from './components/confirmation-message/confirmation-message.component';
@ -108,6 +110,7 @@ import { CommonService } from './services/common.service';
MatSliderModule,
MatTabsModule,
AppSettingsComponent,
InvoiceInformationComponent,
AlertMessageComponent,
ConfirmationMessageComponent,
SpinnerDialogComponent,
@ -127,6 +130,7 @@ import { CommonService } from './services/common.service';
],
declarations: [
AppSettingsComponent,
InvoiceInformationComponent,
AlertMessageComponent,
ConfirmationMessageComponent,
SpinnerDialogComponent,
@ -144,13 +148,14 @@ import { CommonService } from './services/common.service';
CurrencyUnitConvertPipe
],
entryComponents: [
InvoiceInformationComponent,
AlertMessageComponent,
SpinnerDialogComponent,
ConfirmationMessageComponent
],
providers: [
{ provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { hasBackdrop: true, autoFocus: true, disableClose: true, role: 'dialog', width: '700px' } },
CommonService
CommonService, CurrencyUnitConvertPipe, DecimalPipe
]
})
export class SharedModule { }

@ -0,0 +1,231 @@
@import "constants";
@include mat-core();
@mixin change-font($typography) {
@include mat-core($typography);
&.small-font {
.mat-header-cell {
font-weight: 700;
}
.mr-4 {
margin-right: 1rem !important;
}
.mat-menu-item, .mat-tree .mat-tree-node, .mat-tree .mat-nested-tree-node-parent {
min-height: $tree-node-height * 0.7;
height: $tree-node-height * 0.7;
}
.mat-primary .mat-select-panel .mat-option.mat-selected:not(.mat-option-multiple),
.mat-primary .mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled) {
font-size: $small-font-size * 1.1;
}
.genseed-message, .insecure-message, .validation-error-icon, .fa-icon-small, .top-icon-small {
font-size: $small-font-size * 1.2;
}
.page-title-container, .page-sub-title-container {
font-size: $small-font-size * 1.1;
& .page-title-img {
width: $small-font-size * 1.8;
height: $small-font-size * 1.8;
font-size: $small-font-size * 1.5;
}
}
.mat-icon-button .top-toolbar-icon.icon-pinned {
padding-top: 1rem;
}
.top-toolbar-icon .top-toolbar-img, .sidenav-img svg {
width: $small-font-size * 1.8;
height: $small-font-size * 1.8;
font-size: 1.5rem;
}
.horizontal-button .sidenav-img svg {
width: $small-font-size * 2.1;
height: $small-font-size * 2.1;
font-size: 2.2rem;
}
.material-icons, .invoice-info-header {
font-size: $small-font-size * 1.5;
line-height: 2rem;
}
.mat-expansion-panel-header, .mat-menu-item, .mat-list .mat-list-item, .mat-nav-list .mat-list-item, .mat-option, .mat-select, .mat-selection-list .mat-list-item {
font-size: $small-font-size !important;
}
.logo {
font-size: $small-font-size * 2;
}
.font-60-percent {
font-size: $small-font-size * 0.6;
}
.fa-icon-regular {
font-size: $small-font-size * 1.75;
}
.icon-large {
font-size: $small-font-size * 5;
}
.icon-medium {
font-size: $small-font-size * 2 !important;
}
.icon-small {
font-size: $small-font-size * 1.5 !important;
}
.icon-smaller {
font-size: $small-font-size * 0.75 !important;
}
.size-triple {
font-size: $small-font-size * 3;
}
.mat-icon-36 {
font-size: $small-font-size;
}
}
&.regular-font {
.mat-header-cell {
font-weight: 700;
}
.inner-sidenav-content {
padding-top: $regular-font-size;
}
.mat-tree .mat-tree-node, .mat-tree .mat-nested-tree-node-parent {
height: $tree-node-height;
}
.mat-primary .mat-select-panel .mat-option.mat-selected:not(.mat-option-multiple),
.mat-primary .mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled) {
font-size: $regular-font-size * 1.1;
}
.genseed-message, .insecure-message, .validation-error-icon {
font-size: $regular-font-size * 1.2;
}
.page-title-container, .page-sub-title-container {
font-size: $regular-font-size * 1.1;
& .page-title-img {
width: 2rem;
height: 2rem;
font-size: $regular-font-size * 1.3;
}
}
.mat-button .mat-icon-button .top-toolbar-icon.icon-pinned {
font-size: $regular-font-size;
}
.fa-icon-small, .top-icon-small, .invoice-info-header {
font-size: $regular-font-size * 1.5;
}
.top-toolbar-icon.icon-pinned {
font-size: $regular-font-size * 1.3;
}
.top-toolbar-icon .top-toolbar-img, .sidenav-img svg {
width: $regular-font-size * 1.8;
height: $regular-font-size * 1.8;
font-size: $regular-font-size * 1.3;
}
.horizontal-button .sidenav-img svg {
width: $regular-font-size * 2.2;
height: $regular-font-size * 2.2;
font-size: 2.5rem;
}
.material-icons {
font-size: $regular-font-size * 2;
}
.mat-expansion-panel-header, .mat-menu-item, .mat-list .mat-list-item, .mat-nav-list .mat-list-item, .mat-option, .mat-select, .mat-selection-list .mat-list-item {
font-size: $regular-font-size !important;
}
.logo {
font-size: $regular-font-size * 2;
}
.font-60-percent {
font-size: $regular-font-size * 0.6;
}
.fa-icon-regular {
font-size: $regular-font-size * 1.75;
}
.icon-large {
font-size: $regular-font-size * 5;
}
.icon-medium {
font-size: $regular-font-size * 2 !important;
}
.icon-small {
font-size: $regular-font-size * 1.5 !important;
}
.icon-smaller {
font-size: $regular-font-size * 0.75 !important;
}
.size-triple {
font-size: $regular-font-size * 3;
}
.mat-icon-36 {
font-size: $regular-font-size;
}
}
&.large-font {
.mat-header-cell {
font-weight: 800;
}
.mat-tree .mat-tree-node, .mat-tree .mat-nested-tree-node-parent {
height: $tree-node-height;
}
.mat-primary .mat-select-panel .mat-option.mat-selected:not(.mat-option-multiple),
.mat-primary .mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled) {
font-size: $large-font-size * 1.1;
}
.genseed-message, .insecure-message, .validation-error-icon {
font-size: $large-font-size * 1.2;
}
.page-title-container, .page-sub-title-container {
margin-top: 0.5rem;
font-size: $large-font-size * 1.1;
& .page-title-img {
width: $large-font-size * 2;
height: $large-font-size * 2;
font-size: $large-font-size * 2.1;
}
}
.fa-icon-small, .top-icon-small, .invoice-info-header {
font-size: $large-font-size * 1.4;
}
.top-toolbar-icon.icon-pinned {
font-size: $large-font-size * 1.25;
}
.top-toolbar-icon .top-toolbar-img, .sidenav-img svg {
width: $large-font-size * 2;
height: $large-font-size * 2;
font-size: $large-font-size * 1.25;
}
.horizontal-button .sidenav-img svg {
width: $large-font-size * 2.25;
height: $large-font-size * 2.25;
font-size: $large-font-size * 2;
}
.material-icons {
font-size: $large-font-size * 2.5;
}
.mat-expansion-panel-header, .mat-menu-item, .mat-list .mat-list-item, .mat-nav-list .mat-list-item, .mat-option, .mat-select, .mat-selection-list .mat-list-item {
font-size: $large-font-size !important;
}
.logo {
font-size: $large-font-size * 2;
}
.font-60-percent {
font-size: $large-font-size * 0.6;
}
.fa-icon-regular {
font-size: $large-font-size * 1.75;
}
.icon-large {
font-size: $large-font-size * 5;
}
.icon-medium {
font-size: $large-font-size * 2 !important;
}
.icon-small {
font-size: $large-font-size * 1.5 !important;
}
.icon-smaller {
font-size: $large-font-size * 0.75 !important;
}
.size-triple {
font-size: $large-font-size * 3;
}
.mat-icon-36 {
font-size: $large-font-size;
}
}
}

@ -42,7 +42,7 @@
}
}
&.day {
.ng-fa-icon, .mat-nested-tree-node-parent .mat-icon {
.ng-fa-icon, .mat-nested-tree-node-parent .mat-icon, .mat-form-field-suffix {
color: $foreground-secondary-text;
}
.selected-color {
@ -56,6 +56,10 @@
}
}
.foreground-secondary-text {
color: $foreground-secondary-text !important;
}
.foreground.mat-progress-spinner circle, .foreground.mat-spinner circle {
stroke: $foreground-text;
}
@ -134,7 +138,7 @@
width:100%;
}
.page-title-container, .page-sub-title-container {
.page-title-container, .page-sub-title-container, .mat-form-field-infix .mat-form-field-label-wrapper .mat-form-field-label {
color: $foreground-text;
}
@ -216,4 +220,16 @@
}
}
.invoice-info-header {
color: $foreground-text;
font-weight: 500;
& .page-title-img svg {
color: $foreground-text;
}
}
.invoice-qr-code-container {
background: $foreground-divider;
}
}

@ -30,234 +30,6 @@ body {
.mat-nested-tree-node-child>.mat-tree-node {
padding-left: 4rem;
}
&.small-font {
.mr-4 {
margin-right: 1rem !important;
}
.mat-menu-item, .mat-tree .mat-tree-node, .mat-tree .mat-nested-tree-node-parent {
min-height: $tree-node-height * 0.7;
height: $tree-node-height * 0.7;
}
.mat-primary .mat-select-panel .mat-option.mat-selected:not(.mat-option-multiple),
.mat-primary .mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled) {
font-size: $small-font-size * 1.1;
}
.validation-error-icon {
font-size: $small-font-size * 1.2;
}
.genseed-message {
font-size: $small-font-size * 1.2;
}
.insecure-message {
font-size: $small-font-size * 1.2;
}
.page-title-container, .page-sub-title-container {
font-size: $small-font-size * 1.1;
& .page-title-img {
width: $small-font-size * 1.8;
height: $small-font-size * 1.8;
font-size: $small-font-size * 1.5;
}
}
.fa-icon-small, .top-icon-small {
font-size: $small-font-size * 1.2;
}
.mat-icon-button .top-toolbar-icon.icon-pinned {
padding-top: 1rem;
}
.top-toolbar-icon .top-toolbar-img, .sidenav-img svg {
width: $small-font-size * 1.8;
height: $small-font-size * 1.8;
font-size: 1.5rem;
}
.horizontal-button .sidenav-img svg {
width: $small-font-size * 2.1;
height: $small-font-size * 2.1;
font-size: 2.2rem;
}
.material-icons {
font-size: $small-font-size * 1.5;
line-height: 2rem;
}
.mat-expansion-panel-header, .mat-menu-item, .mat-list .mat-list-item, .mat-nav-list .mat-list-item, .mat-option, .mat-select, .mat-selection-list .mat-list-item {
font-size: $small-font-size !important;
}
.logo {
font-size: $small-font-size * 2;
}
.font-60-percent {
font-size: $small-font-size * 0.6;
}
.fa-icon-regular {
font-size: $small-font-size * 1.75;
}
.icon-large {
font-size: $small-font-size * 5;
}
.icon-small {
font-size: $small-font-size * 1.5 !important;
}
.icon-smaller {
font-size: $small-font-size * 0.75 !important;
}
.size-triple {
font-size: $small-font-size * 3;
}
.mat-icon-36 {
font-size: $small-font-size;
}
}
&.regular-font {
.inner-sidenav-content {
padding-top: $regular-font-size;
}
.mat-tree .mat-tree-node, .mat-tree .mat-nested-tree-node-parent {
height: $tree-node-height;
}
.mat-primary .mat-select-panel .mat-option.mat-selected:not(.mat-option-multiple),
.mat-primary .mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled) {
font-size: $regular-font-size * 1.1;
}
.validation-error-icon {
font-size: $regular-font-size * 1.2;
}
.genseed-message {
font-size: $regular-font-size * 1.2;
}
.insecure-message {
font-size: $regular-font-size * 1.2;
}
.page-title-container, .page-sub-title-container {
font-size: $regular-font-size * 1.1;
& .page-title-img {
width: 2rem;
height: 2rem;
font-size: $regular-font-size * 1.3;
}
}
.mat-button .mat-icon-button .top-toolbar-icon.icon-pinned {
font-size: $regular-font-size;
}
.fa-icon-small, .top-icon-small {
font-size: $regular-font-size * 1.5;
}
.top-toolbar-icon.icon-pinned {
font-size: $regular-font-size * 1.3;
}
.top-toolbar-icon .top-toolbar-img, .sidenav-img svg {
width: $regular-font-size * 1.8;
height: $regular-font-size * 1.8;
font-size: $regular-font-size * 1.3;
}
.horizontal-button .sidenav-img svg {
width: $regular-font-size * 2.2;
height: $regular-font-size * 2.2;
font-size: 2.5rem;
}
.material-icons {
font-size: $regular-font-size * 2;
}
.mat-expansion-panel-header, .mat-menu-item, .mat-list .mat-list-item, .mat-nav-list .mat-list-item, .mat-option, .mat-select, .mat-selection-list .mat-list-item {
font-size: $regular-font-size !important;
}
.logo {
font-size: $regular-font-size * 2;
}
.font-60-percent {
font-size: $regular-font-size * 0.6;
}
.fa-icon-regular {
font-size: $regular-font-size * 1.75;
}
.icon-large {
font-size: $regular-font-size * 5;
}
.icon-small {
font-size: $regular-font-size * 1.5 !important;
}
.icon-smaller {
font-size: $regular-font-size * 0.75 !important;
}
.size-triple {
font-size: $regular-font-size * 3;
}
.mat-icon-36 {
font-size: $regular-font-size;
}
}
&.large-font {
.mat-tree .mat-tree-node, .mat-tree .mat-nested-tree-node-parent {
height: $tree-node-height;
}
.mat-primary .mat-select-panel .mat-option.mat-selected:not(.mat-option-multiple),
.mat-primary .mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled) {
font-size: $large-font-size * 1.1;
}
.validation-error-icon {
font-size: $large-font-size * 1.2;
}
.genseed-message {
font-size: $large-font-size * 1.2;
}
.insecure-message {
font-size: $large-font-size * 1.2;
}
.page-title-container, .page-sub-title-container {
margin-top: 0.5rem;
font-size: $large-font-size * 1.1;
& .page-title-img {
width: $large-font-size * 2;
height: $large-font-size * 2;
font-size: $large-font-size * 2.1;
}
}
.fa-icon-small, .top-icon-small {
font-size: $large-font-size * 1.4;
}
.top-toolbar-icon.icon-pinned {
font-size: $large-font-size * 1.25;
}
.top-toolbar-icon .top-toolbar-img, .sidenav-img svg {
width: $large-font-size * 2;
height: $large-font-size * 2;
font-size: $large-font-size * 1.25;
}
.horizontal-button .sidenav-img svg {
width: $large-font-size * 2.25;
height: $large-font-size * 2.25;
font-size: $large-font-size * 2;
}
.material-icons {
font-size: $large-font-size * 2.5;
}
.mat-expansion-panel-header, .mat-menu-item, .mat-list .mat-list-item, .mat-nav-list .mat-list-item, .mat-option, .mat-select, .mat-selection-list .mat-list-item {
font-size: $large-font-size !important;
}
.logo {
font-size: $large-font-size * 2;
}
.font-60-percent {
font-size: $large-font-size * 0.6;
}
.fa-icon-regular {
font-size: $large-font-size * 1.75;
}
.icon-large {
font-size: $large-font-size * 5;
}
.icon-small {
font-size: $large-font-size * 1.5 !important;
}
.icon-smaller {
font-size: $large-font-size * 0.75 !important;
}
.size-triple {
font-size: $large-font-size * 3;
}
.mat-icon-36 {
font-size: $large-font-size;
}
}
&.horizontal {
.horizontal-nav {
height: $horizontal-toolbar-height !important;
@ -393,6 +165,18 @@ body {
padding: 0 $gap 0 $gap !important;
}
.padding-gap-large {
padding: $gap * 2 !important;
}
.padding-gap-x-large {
padding: 0 ($gap*2) 0 ($gap*2) !important;
}
.overflow-wrap {
overflow-wrap: break-word !important;
}
.mat-raised-button {
width: 100%;
margin-top: 0.5rem;
@ -888,8 +672,12 @@ a {
word-break: break-all !important;
}
.qr-border {
border: 2px solid white;
.font-bold-500 {
font-weight: 500 !important;
}
.qr-border img {
border: 1.2rem solid white;
}
.pubkey-info-top {
@ -953,3 +741,7 @@ a {
table {
width:100%;
}
.mat-button-focus-overlay {
background-color: transparent!important;
}

@ -1,14 +1,15 @@
@import '~@angular/material/theming';
@include mat-core();
@import 'change-font';
@import 'change-theme';
@import 'typography';
@include mat-core();
.rtl-container{
&.purple {
@import "../skins/purple";
&.small-font {@include mat-core($small-typography);}
&.regular-font {@include mat-core($regular-typography);}
&.large-font {@include mat-core($large-typography);}
&.small-font {@include change-font($small-typography);}
&.regular-font {@include change-font($regular-typography);}
&.large-font {@include change-font($large-typography);}
&.day {
@include angular-material-theme($purple-day-theme);
@include change-theme($purple-day-theme);
@ -20,9 +21,9 @@
}
&.blue{
@import "../skins/blue";
&.small-font {@include mat-core($small-typography);}
&.regular-font {@include mat-core($regular-typography);}
&.large-font {@include mat-core($large-typography);}
&.small-font {@include change-font($small-typography);}
&.regular-font {@include change-font($regular-typography);}
&.large-font {@include change-font($large-typography);}
&.day {
@include angular-material-theme($blue-day-theme);
@include change-theme($blue-day-theme);
@ -34,9 +35,9 @@
}
&.green{
@import "../skins/green";
&.small-font {@include mat-core($small-typography);}
&.regular-font {@include mat-core($regular-typography);}
&.large-font {@include mat-core($large-typography);}
&.small-font {@include change-font($small-typography);}
&.regular-font {@include change-font($regular-typography);}
&.large-font {@include change-font($large-typography);}
&.day {
@include angular-material-theme($green-day-theme);
@include change-theme($green-day-theme);
@ -48,9 +49,9 @@
}
&.pink{
@import "../skins/pink";
&.small-font {@include mat-core($small-typography);}
&.regular-font {@include mat-core($regular-typography);}
&.large-font {@include mat-core($large-typography);}
&.small-font {@include change-font($small-typography);}
&.regular-font {@include change-font($regular-typography);}
&.large-font {@include change-font($large-typography);}
&.day {
@include angular-material-theme($pink-day-theme);
@include change-theme($pink-day-theme);

@ -194,7 +194,7 @@ export class CloseSpinner implements Action {
export class OpenAlert implements Action {
readonly type = OPEN_ALERT;
constructor(public payload: MatDialogConfig) {}
constructor(public payload: {config: MatDialogConfig, component?: any}) {}
}
export class CloseAlert implements Action {

@ -56,7 +56,11 @@ export class RTLEffects implements OnDestroy {
openAlert = this.actions$.pipe(
ofType(RTLActions.OPEN_ALERT),
map((action: RTLActions.OpenAlert) => {
this.dialogRef = this.dialog.open(AlertMessageComponent, action.payload);
if(action.payload.component) {
this.dialogRef = this.dialog.open(action.payload.component, action.payload.config);
} else {
this.dialogRef = this.dialog.open(AlertMessageComponent, action.payload.config);
}
}
));
@ -327,12 +331,12 @@ export class RTLEffects implements OnDestroy {
this.store.dispatch(new RTLActions.Signout());
} else {
this.store.dispatch(new RTLActions.CloseSpinner());
this.store.dispatch(new RTLActions.OpenAlert({
this.store.dispatch(new RTLActions.OpenAlert({ config: {
width: '70%', data: {
type: alertType, titleMessage: alertTitle,
message: JSON.stringify({ code: err.status, Message: err.error.error, URL: errURL })
}
}));
}}));
}
}

Loading…
Cancel
Save