2
0
mirror of https://github.com/Ride-The-Lightning/RTL synced 2024-11-07 15:20:31 +00:00

Peers And Channels

Peers And Channels
This commit is contained in:
Shahana Farooqui 2019-11-21 15:33:23 -05:00
parent 2b3f866b58
commit 5bf45be695
45 changed files with 697 additions and 522 deletions

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

View File

@ -9,8 +9,8 @@
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicon/favicon-16x16.png">
<link rel="manifest" href="assets/images/favicon/site.webmanifest">
<link rel="stylesheet" href="styles.71666b4a6e6d3212bd76.css"></head>
<link rel="stylesheet" href="styles.754b1a5321d3de1387e5.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.06930950766225289ad2.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.739be07c83d8207feab7.js"></script></body>
<script src="runtime.af8e8f4b78a7bd889ad1.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.642a811d13ebedcd22b4.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

View File

@ -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:"c7ef37d92d6c98e58e25",6:"37f15cb430ed0162fe8e",7:"610b2060919a150dbffa"}[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],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:"c7ef37d92d6c98e58e25",6:"bb075656f8b4a826eed4",7:"bada1b79d7bc28f5bfed"}[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()}([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort } from '@angular/material';
import { SelNodeChild } from '../../shared/models/RTLconfig';
import { GetInfoCL, InvoiceCL } from '../../shared/models/clModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../../shared/models/enums';
import { LoggerService } from '../../shared/services/logger.service';
import { newlyAddedRowAnimation } from '../../shared/animation/row-animation';
@ -37,8 +38,8 @@ export class CLInvoicesComponent implements OnInit, OnDestroy {
public flgSticky = false;
public private = false;
public totalInvoices = 100;
public pageSize = 25;
public pageSizeOptions = [5, 10, 25, 100];
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
private firstOffset = -1;
private lastOffset = -1;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];

View File

@ -25,8 +25,8 @@ import { ForwardingHistoryComponent } from './switch/forwarding-history.componen
import { RoutingPeersComponent } from './routing-peers/routing-peers.component';
import { ChannelLookupComponent } from './lookups/channel-lookup/channel-lookup.component';
import { NodeLookupComponent } from './lookups/node-lookup/node-lookup.component';
import { ChannelBackupComponent } from './peers-channels/channels/channel-backup/channel-backup.component';
import { ChannelRestoreComponent } from './peers-channels/channels/channel-restore/channel-restore.component';
import { ChannelBackupTableComponent } from './peers-channels/channels/channels-tables/channel-backup-table/channel-backup-table.component';
import { ChannelRestoreTableComponent } from './peers-channels/channels/channels-tables/channel-restore-table/channel-restore-table.component';
import { QueryRoutesComponent } from './payments/query-routes/query-routes.component';
import { LoggerService, ConsoleLoggerService } from '../shared/services/logger.service';
@ -56,9 +56,9 @@ import { ChannelOpenTableComponent } from './peers-channels/channels/channels-ta
RoutingPeersComponent,
ChannelLookupComponent,
NodeLookupComponent,
ChannelBackupComponent,
ChannelBackupTableComponent,
QueryRoutesComponent,
ChannelRestoreComponent,
ChannelRestoreTableComponent,
OnChainSendComponent,
OnChainReceiveComponent,
OnChainComponent,

View File

@ -10,8 +10,6 @@ import { QueryRoutesComponent } from './payments/query-routes/query-routes.compo
import { LookupsComponent } from './lookups/lookups.component';
import { ForwardingHistoryComponent } from './switch/forwarding-history.component';
import { RoutingPeersComponent } from './routing-peers/routing-peers.component';
import { ChannelBackupComponent } from './peers-channels/channels/channel-backup/channel-backup.component';
import { ChannelRestoreComponent } from './peers-channels/channels/channel-restore/channel-restore.component';
import { OnChainComponent } from './on-chain/on-chain.component';
import { AuthGuard, LNDUnlockedGuard } from '../shared/services/auth.guard';
@ -25,8 +23,6 @@ export const LndRoutes: Routes = [
{ path: 'peerschannels', component: PeersChannelsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'transactions', component: TransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'onchain', component: OnChainComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlbackup', component: ChannelBackupComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlrestore', component: ChannelRestoreComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'queryroutes', component: QueryRoutesComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'forwardinghistory', component: ForwardingHistoryComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'routingpeers', component: RoutingPeersComponent, canActivate: [LNDUnlockedGuard] },

View File

@ -7,6 +7,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { Transaction } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../../../shared/models/enums';
import { LoggerService } from '../../../shared/services/logger.service';
import { getPaginatorLabel } from '../../../shared/services/paginator.service';
@ -19,7 +20,7 @@ import * as fromRTLReducer from '../../../store/rtl.reducers';
templateUrl: './on-chain-transaction-history.component.html',
styleUrls: ['./on-chain-transaction-history.component.scss'],
providers: [
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Transactions') },
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Transactions') }
]
})
export class OnChainTransactionHistoryComponent implements OnInit, OnDestroy {
@ -30,8 +31,8 @@ export class OnChainTransactionHistoryComponent implements OnInit, OnDestroy {
public listTransactions: any;
public flgLoading: Array<Boolean | 'error'> = [true];
public flgSticky = false;
public pageSize = 10;
public pageSizeOptions = [5, 10, 25, 100];
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private actions$: Actions) {

View File

@ -6,6 +6,7 @@ import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort } from '@angular/material';
import { Channel, Peer, GetInfo } from '../../../../shared/models/lndModels';
import { TRANS_TYPES } from '../../../../shared/models/enums';
import { LoggerService } from '../../../../shared/services/logger.service';
import { LNDEffects } from '../../../store/lnd.effects';
@ -31,7 +32,7 @@ export class ChannelManageComponent implements OnInit, OnDestroy {
public selectedFilter = '';
public myChanPolicy: any = {};
public selFilter = '';
public transTypes = [{id: '0', name: 'Default Priority'}, {id: '1', name: 'Target Confirmation Blocks'}, {id: '2', name: 'Fee'}];
public transTypes = TRANS_TYPES;
public selTransType = '0';
public transTypeValue = {blocks: '', fees: ''};
public spendUnconfirmed = false;

View File

@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChannelRestoreComponent } from './channel-restore.component';
import { ChannelBackupTableComponent } from './channel-backup-table.component';
describe('ChannelRestoreComponent', () => {
let component: ChannelRestoreComponent;
let fixture: ComponentFixture<ChannelRestoreComponent>;
describe('ChannelBackupTableComponent', () => {
let component: ChannelBackupTableComponent;
let fixture: ComponentFixture<ChannelBackupTableComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChannelRestoreComponent ]
declarations: [ ChannelBackupTableComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChannelRestoreComponent);
fixture = TestBed.createComponent(ChannelBackupTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -7,20 +7,20 @@ import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { SelNodeChild } from '../../../../shared/models/RTLconfig';
import { Channel } from '../../../../shared/models/lndModels';
import { LoggerService } from '../../../../shared/services/logger.service';
import { SelNodeChild } from '../../../../../shared/models/RTLconfig';
import { Channel } from '../../../../../shared/models/lndModels';
import { LoggerService } from '../../../../../shared/services/logger.service';
import { RTLEffects } from '../../../../store/rtl.effects';
import * as RTLActions from '../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../store/rtl.reducers';
import { RTLEffects } from '../../../../../store/rtl.effects';
import * as RTLActions from '../../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../../store/rtl.reducers';
@Component({
selector: 'rtl-channel-backup',
templateUrl: './channel-backup.component.html',
styleUrls: ['./channel-backup.component.scss']
selector: 'rtl-channel-backup-table',
templateUrl: './channel-backup-table.component.html',
styleUrls: ['./channel-backup-table.component.scss']
})
export class ChannelBackupComponent implements OnInit, OnDestroy {
export class ChannelBackupTableComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
public selNode: SelNodeChild = {};
public displayedColumns = ['chan_point', 'backup', 'verify'];

View File

@ -1,64 +1,54 @@
<div fxLayout="column">
<div class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Closed Channels</h2>
</mat-card-subtitle>
</mat-card-header>
<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-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<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>
</ng-container>
<ng-container matColumnDef="channel_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Channel Point </th>
<td mat-cell *matCellDef="let channel"> {{channel.channel_point | slice:0:10}}...</td>
</ng-container>
<ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header> ID </th>
<td mat-cell *matCellDef="let channel"> {{channel.chan_id}} </td>
</ng-container>
<ng-container matColumnDef="closing_tx_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Closing Txn Hash </th>
<td mat-cell *matCellDef="let channel">
<div>{{channel.closing_tx_hash | slice:0:10}}...</div></td>
</ng-container>
<ng-container matColumnDef="remote_pubkey">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Pub Key </th>
<td mat-cell *matCellDef="let channel">
<div>{{channel.remote_pubkey | slice:0:10}}...</div></td>
</ng-container>
<ng-container matColumnDef="capacity">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Capacity </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.capacity | number}} </span></td>
</ng-container>
<ng-container matColumnDef="close_height">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Close Height </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.close_height | number}} </span></td>
</ng-container>
<ng-container matColumnDef="settled_balance">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Settled Balance </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.settled_balance | number}} </span></td>
</ng-container>
<ng-container matColumnDef="time_locked_balance">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Time Locked Balance </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.time_locked_balance | number}} </span></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="onClosedChannelClick(row, $event)"></tr>
</table>
</div>
</mat-card-content>
</mat-card>
<div fxLayout="column" class="padding-gap">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-minus-2">
<div fxFlex="70"></div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
</div>
<div perfectScrollbar fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<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>
</ng-container>
<ng-container matColumnDef="channel_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Channel Point </th>
<td mat-cell *matCellDef="let channel"> {{channel.channel_point | slice:0:10}}...</td>
</ng-container>
<ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header> ID </th>
<td mat-cell *matCellDef="let channel"> {{channel.chan_id}} </td>
</ng-container>
<ng-container matColumnDef="closing_tx_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Closing Txn Hash </th>
<td mat-cell *matCellDef="let channel">
<div>{{channel.closing_tx_hash | slice:0:10}}...</div></td>
</ng-container>
<ng-container matColumnDef="remote_pubkey">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Pub Key </th>
<td mat-cell *matCellDef="let channel">
<div>{{channel.remote_pubkey | slice:0:10}}...</div></td>
</ng-container>
<ng-container matColumnDef="capacity">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Capacity </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.capacity | number}} </span></td>
</ng-container>
<ng-container matColumnDef="close_height">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Close Height </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.close_height | number}} </span></td>
</ng-container>
<ng-container matColumnDef="settled_balance">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Settled Balance </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.settled_balance | number}} </span></td>
</ng-container>
<ng-container matColumnDef="time_locked_balance">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Time Locked Balance </th>
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center"> {{channel.time_locked_balance | number}} </span></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="onClosedChannelClick(row, $event)"></tr>
</table>
</div>
</div>

View File

@ -1,5 +1,5 @@
<div fxLayout="column" *ngIf="numPeers > -1">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container">
<div fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start center" class="padding-gap-x page-sub-title-container mt-minus-2">
<div fxFlex="70"></div>
<mat-form-field fxFlex="30">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
@ -25,11 +25,11 @@
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">{{channel.total_satoshis_received | number}} </span></td>
</ng-container>
<ng-container matColumnDef="capacity">
<th mat-header-cell *matHeaderCellDef>Capacity</th>
<th mat-header-cell *matHeaderCellDef mat-sort-header>Capacity</th>
<td mat-cell *matCellDef="let channel">
<div fxLayout="row">
<mat-hint fxFlex="50" fxLayoutAlign="start center"><strong>Local: </strong>{{channel.local_balance || 0 | number}} {{information?.smaller_currency_unit}}</mat-hint>
<mat-hint fxFlex="50" fxLayoutAlign="end center"><strong>Remote: </strong>{{channel.remote_balance || 0 | number}} {{information?.smaller_currency_unit}}</mat-hint>
<mat-hint fxFlex="50" fxLayoutAlign="start center" class="font-size-80"><strong class="font-weight-900">Local: </strong>{{channel.local_balance || 0 | number}} {{information?.smaller_currency_unit}}</mat-hint>
<mat-hint fxFlex="50" fxLayoutAlign="end center" class="font-size-80"><strong class="font-weight-900">Remote: </strong>{{channel.remote_balance || 0 | number}} {{information?.smaller_currency_unit}}</mat-hint>
</div>
<mat-progress-bar mode="determinate" value="{{channel.local_balance && channel.local_balance > 0 ? ((+channel.local_balance/((+channel.local_balance)+(+channel.remote_balance)))*100) : 0}}"></mat-progress-bar>
</td>
@ -54,7 +54,7 @@
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr mat-footer-row *matFooterRowDef="['no_peer']" [ngClass]="{'invisible-footer': numPeers>1}"></tr>
<tr mat-footer-row *matFooterRowDef="['no_peer']" [ngClass]="{'display-none': numPeers>1}"></tr>
</table>
</div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" showFirstLastButtons class="mb-4"></mat-paginator>

View File

@ -8,8 +8,7 @@
.mat-column-total_satoshis_sent, .mat-column-total_satoshis_received {
flex: 0 0 10%;
width: 10%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.invisible-footer {
display: none !important;
}

View File

@ -5,6 +5,7 @@ import { Store } from '@ngrx/store';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { Channel, GetInfo } from '../../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../../../../../shared/models/enums';
import { LoggerService } from '../../../../../shared/services/logger.service';
import { getPaginatorLabel } from '../../../../../shared/services/paginator.service';
@ -18,7 +19,7 @@ import * as fromRTLReducer from '../../../../../store/rtl.reducers';
templateUrl: './channel-open-table.component.html',
styleUrls: ['./channel-open-table.component.scss'],
providers: [
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('channels') },
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Channels') }
]
})
export class ChannelOpenTableComponent implements OnInit, OnDestroy {
@ -34,9 +35,9 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
public selFilter = '';
public flgSticky = false;
public myChanPolicy: any = {};
public pageSize = 10;
public pageSizeOptions = [5, 10, 25, 100];
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
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 rtlEffects: RTLEffects, private lndEffects: LNDEffects) {
switch (true) {
@ -62,7 +63,7 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
ngOnInit() {
this.store.select('lnd')
.pipe(takeUntil(this.unsub[0]))
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
rtlStore.effectErrorsLnd.forEach(effectsErr => {
if (effectsErr.action === 'FetchChannels/all') {
@ -94,7 +95,7 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
]
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[2]))
.pipe(takeUntil(this.unSubs[1]))
.subscribe(confirmRes => {
if (confirmRes) {
const base_fee = confirmRes[0].inputValue;
@ -109,7 +110,7 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
this.store.dispatch(new RTLActions.OpenSpinner('Fetching Channel Policy...'));
this.store.dispatch(new RTLActions.ChannelLookup(channelToUpdate.chan_id.toString()));
this.lndEffects.setLookup
.pipe(takeUntil(this.unsub[3]))
.pipe(takeUntil(this.unSubs[2]))
.subscribe(resLookup => {
this.logger.info(resLookup);
if (resLookup.node1_pub === this.information.identity_pubkey) {
@ -132,7 +133,7 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
}}));
});
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[2]))
.pipe(takeUntil(this.unSubs[3]))
.subscribe(confirmRes => {
if (confirmRes) {
const base_fee = confirmRes[0].inputValue;
@ -151,7 +152,7 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
width: '70%', data: { type: 'CONFIRM', titleMessage: 'Closing channel: ' + channelToClose.chan_id, noBtnText: 'Cancel', yesBtnText: 'Close Channel'
}}));
this.rtlEffects.closeConfirm
.pipe(takeUntil(this.unsub[1]))
.pipe(takeUntil(this.unSubs[4]))
.subscribe(confirmRes => {
if (confirmRes) {
this.store.dispatch(new RTLActions.OpenSpinner('Closing Channel...'));
@ -166,14 +167,8 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
}
onChannelClick(selRow: Channel, event: any) {
console.warn(selRow.local_balance && selRow.local_balance > 0 ? ((+selRow.local_balance/(selRow.local_balance+selRow.remote_balance))*100) : 0);
const flgCloseClicked =
event.target.className.includes('mat-column-close')
|| event.target.className.includes('mat-column-update')
|| event.target.className.includes('mat-icon');
if (flgCloseClicked) {
return;
}
const flgCloseClicked = event.target.className.includes('mat-column-close') || event.target.className.includes('mat-column-update') || event.target.className.includes('mat-icon');
if (flgCloseClicked) { return; }
const selChannel = this.channels.data.filter(channel => {
return channel.chan_id === selRow.chan_id;
})[0];
@ -187,27 +182,27 @@ export class ChannelOpenTableComponent implements OnInit, OnDestroy {
}}}));
}
loadChannelsTable(channels) {
channels.sort(function(a, b) {
loadChannelsTable(mychannels) {
mychannels.sort(function(a, b) {
return (a.active === b.active) ? 0 : ((b.active) ? 1 : -1);
});
this.channels = new MatTableDataSource<Channel>([...channels]);
// this.channels.filterPredicate = (channel: Channel, fltr: string) => {
// const newChannel = ((channel.active) ? 'active' : 'inactive') + (channel.chan_id ? channel.chan_id : '') +
// (channel.remote_pubkey ? channel.remote_pubkey : '') + (channel.remote_alias ? channel.remote_alias : '') +
// (channel.capacity ? channel.capacity : '') + (channel.local_balance ? channel.local_balance : '') +
// (channel.remote_balance ? channel.remote_balance : '') + (channel.total_satoshis_sent ? channel.total_satoshis_sent : '') +
// (channel.total_satoshis_received ? channel.total_satoshis_received : '') + (channel.commit_fee ? channel.commit_fee : '') +
// (channel.private ? 'private' : 'public');
// return newChannel.includes(fltr);
// };
this.channels = new MatTableDataSource<Channel>([...mychannels]);
this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = ((channel.active) ? 'active' : 'inactive') + (channel.chan_id ? channel.chan_id : '') +
(channel.remote_pubkey ? channel.remote_pubkey : '') + (channel.remote_alias ? channel.remote_alias : '') +
(channel.capacity ? channel.capacity : '') + (channel.local_balance ? channel.local_balance : '') +
(channel.remote_balance ? channel.remote_balance : '') + (channel.total_satoshis_sent ? channel.total_satoshis_sent : '') +
(channel.total_satoshis_received ? channel.total_satoshis_received : '') + (channel.commit_fee ? channel.commit_fee : '') +
(channel.private ? 'private' : 'public');
return newChannel.includes(fltr);
};
this.channels.sort = this.sort;
this.channels.paginator = this.paginator;
this.logger.info(this.channels);
}
ngOnDestroy() {
this.unsub.forEach(completeSub => {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});

View File

@ -1,252 +1,234 @@
<div fxLayout="column">
<div fxFlex="100" class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Pending Channels</h2>
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div class="padding-gap">
<h3 *ngIf="selNode?.satsToBTC; else smallerUnit">Total Limbo Balance:
{{pendingChannels.btc_total_limbo_balance | number}} {{information?.currency_unit}}</h3>
<ng-template #smallerUnit>
<h3>Total Limbo Balance: {{pendingChannels.total_limbo_balance | number}}
{{information?.smaller_currency_unit}}</h3>
</ng-template>
</div>
<div class="">
<mat-accordion>
<mat-expansion-panel displayMode="flat">
<mat-expansion-panel-header class="pl-1 pr-1">
<mat-panel-title>
<h3>Pending Open Channels({{pendingOpenChannelsLength}})</h3>
</mat-panel-title>
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<mat-table #table perfectScrollbar [dataSource]="pendingOpenChannels" matSort
[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>
</ng-container>
<ng-container matColumnDef="local_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Local Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.local_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="commit_fee">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Commit Fee </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.commit_fee | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="remote_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Remote Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.remote_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="capacity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Capacity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.capacity |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="commit_weight">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Commit Weight </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.commit_weight | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="fee_per_kw">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Fee Per KW </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.fee_per_kw | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="confirmation_height">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Confirmation Height </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.confirmation_height |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="channel_point">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Channel Point </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.channel_point}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedOpenColumns"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedOpenColumns;"
(click)="onOpenClick(row, $event)"></mat-row>
</mat-table>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header class="pl-1 pr-1">
<mat-panel-title>
<h3>Pending Force Closing Channels({{pendingForceClosingChannelsLength}})</h3>
</mat-panel-title>
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<mat-table #table perfectScrollbar [dataSource]="pendingForceClosingChannels" matSort
[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>
</ng-container>
<ng-container matColumnDef="recovered_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Recovered Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.recovered_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="limbo_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Limbo Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.limbo_balance | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="blocks_til_maturity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Block Till Maturity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.blocks_til_maturity |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="maturity_height">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Maturity Height </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.maturity_height | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="local_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Local Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.local_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="remote_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Remote Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.remote_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="capacity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Capacity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.capacity |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="closing_txid">
<mat-header-cell *matHeaderCellDef mat-sort-header> Transaction Id </mat-header-cell>
<mat-cell *matCellDef="let channel">
<div class="flex-ellipsis">{{channel.closing_txid}}</div>
</mat-cell>
</ng-container>
<ng-container matColumnDef="channel_point">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Channel Point </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.channel_point}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedForceClosingColumns"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedForceClosingColumns;"
(click)="onForceClosingClick(row, $event)"></mat-row>
</mat-table>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header class="pl-1 pr-1">
<mat-panel-title>
<h3>Pending Closing Channels({{pendingClosingChannelsLength}})</h3>
</mat-panel-title>
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<mat-table #table perfectScrollbar [dataSource]="pendingClosingChannels" matSort
[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>
</ng-container>
<ng-container matColumnDef="local_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Local Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.local_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="remote_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Remote Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.remote_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="capacity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Capacity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.capacity |
<span class="page-title">Total Limbo Balance: {{pendingChannels.total_limbo_balance | number}} {{information?.smaller_currency_unit}}</span>
<div class="">
<mat-accordion displayMode="flat">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Pending Open Channels({{pendingOpenChannelsLength}})</mat-panel-title>
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<div perfectScrollbar fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-table #table [dataSource]="pendingOpenChannels" matSort [ngClass]="{'overflow-auto error-border bordered-box': flgLoading[0]==='error','overflow-auto bordered-box': 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>
</ng-container>
<ng-container matColumnDef="local_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Local Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.local_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="closing_txid">
<mat-header-cell *matHeaderCellDef mat-sort-header> Transaction Id </mat-header-cell>
<mat-cell *matCellDef="let channel">
<div class="flex-ellipsis">{{channel.closing_txid}}</div>
</mat-cell>
</ng-container>
<ng-container matColumnDef="channel_point">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Channel Point </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.channel_point}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedClosingColumns"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedClosingColumns;"
(click)="onClosingClick(row, $event)"></mat-row>
</mat-table>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header class="pl-1 pr-1">
<mat-panel-title>
<h3>Waiting Close Channels({{pendingWaitClosingChannelsLength}})</h3>
</mat-panel-title>
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<mat-table #table perfectScrollbar [dataSource]="pendingWaitClosingChannels" matSort
[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>
</ng-container>
<ng-container matColumnDef="limbo_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Limbo Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.limbo_balance | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="local_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Local Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.local_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="remote_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Remote Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.remote_balance |
</ng-container>
<ng-container matColumnDef="commit_fee">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Commit Fee </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.commit_fee | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="remote_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Remote Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.remote_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="capacity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Capacity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.capacity |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="commit_weight">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Commit Weight </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.commit_weight | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="fee_per_kw">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Fee Per KW </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.fee_per_kw | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="confirmation_height">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Confirmation Height </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.confirmation_height |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="capacity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Capacity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.capacity |
</ng-container>
<ng-container matColumnDef="channel_point">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Channel Point </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.channel_point}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedOpenColumns"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedOpenColumns;"
(click)="onOpenClick(row, $event)"></mat-row>
</mat-table>
</div>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Pending Force Closing Channels({{pendingForceClosingChannelsLength}})</mat-panel-title>
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<div perfectScrollbar fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-table #table [dataSource]="pendingForceClosingChannels" matSort
[ngClass]="{'overflow-auto error-border bordered-box': flgLoading[0]==='error','overflow-auto bordered-box': 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>
</ng-container>
<ng-container matColumnDef="recovered_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Recovered Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.recovered_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="limbo_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Limbo Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.limbo_balance | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="blocks_til_maturity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Block Till Maturity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.blocks_til_maturity |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="maturity_height">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Maturity Height </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.maturity_height | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="local_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Local Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.local_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="remote_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Remote Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.remote_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="capacity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Capacity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.capacity |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="closing_txid">
<mat-header-cell *matHeaderCellDef mat-sort-header> Transaction Id </mat-header-cell>
<mat-cell *matCellDef="let channel">
<div class="flex-ellipsis">{{channel.closing_txid}}</div>
</mat-cell>
</ng-container>
<ng-container matColumnDef="channel_point">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Channel Point </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.channel_point}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedForceClosingColumns"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedForceClosingColumns;"
(click)="onForceClosingClick(row, $event)"></mat-row>
</mat-table>
</div>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Pending Closing Channels({{pendingClosingChannelsLength}})</mat-panel-title>
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<div perfectScrollbar fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-table #table [dataSource]="pendingClosingChannels" matSort
[ngClass]="{'overflow-auto error-border bordered-box': flgLoading[0]==='error','overflow-auto bordered-box': 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>
</ng-container>
<ng-container matColumnDef="local_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Local Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.local_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="remote_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Remote Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.remote_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="capacity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Capacity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.capacity |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="channel_point">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Channel Point </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.channel_point}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedWaitClosingColumns"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedWaitClosingColumns;"
(click)="onWaitClosingClick(row, $event)"></mat-row>
</mat-table>
</mat-expansion-panel>
</mat-accordion>
</div>
</mat-card-content>
</mat-card>
</ng-container>
<ng-container matColumnDef="closing_txid">
<mat-header-cell *matHeaderCellDef mat-sort-header> Transaction Id </mat-header-cell>
<mat-cell *matCellDef="let channel">
<div class="flex-ellipsis">{{channel.closing_txid}}</div>
</mat-cell>
</ng-container>
<ng-container matColumnDef="channel_point">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Channel Point </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.channel_point}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedClosingColumns"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedClosingColumns;"
(click)="onClosingClick(row, $event)"></mat-row>
</mat-table>
</div>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Waiting Close Channels({{pendingWaitClosingChannelsLength}})</mat-panel-title>
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
</mat-expansion-panel-header>
<div perfectScrollbar fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-table #table [dataSource]="pendingWaitClosingChannels" matSort
[ngClass]="{'overflow-auto error-border bordered-box': flgLoading[0]==='error','overflow-auto bordered-box': 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>
</ng-container>
<ng-container matColumnDef="limbo_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Limbo Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.limbo_balance | number}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="local_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Local Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.local_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="remote_balance">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Remote Balance </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.remote_balance |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="capacity">
<mat-header-cell fxLayoutAlign="end center" *matHeaderCellDef mat-sort-header arrowPosition="before">
Capacity </mat-header-cell>
<mat-cell fxLayoutAlign="end center" *matCellDef="let channel">{{channel.channel.capacity |
number}}</mat-cell>
</ng-container>
<ng-container matColumnDef="channel_point">
<mat-header-cell class="pl-2" *matHeaderCellDef mat-sort-header> Channel Point </mat-header-cell>
<mat-cell class="pl-2" *matCellDef="let channel">{{channel.channel.channel_point}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedWaitClosingColumns"></mat-header-row>
<mat-row fxLayoutAlign="stretch stretch" *matRowDef="let row; columns: displayedWaitClosingColumns;"
(click)="onWaitClosingClick(row, $event)"></mat-row>
</mat-table>
</div>
</mat-expansion-panel>
</mat-accordion>
</div>
</div>
</div>

View File

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

View File

@ -7,21 +7,21 @@ import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { MatTableDataSource, MatSort } from '@angular/material';
import { SelNodeChild } from '../../../../shared/models/RTLconfig';
import { Channel } from '../../../../shared/models/lndModels';
import { LoggerService } from '../../../../shared/services/logger.service';
import { SelNodeChild } from '../../../../../shared/models/RTLconfig';
import { Channel } from '../../../../../shared/models/lndModels';
import { LoggerService } from '../../../../../shared/services/logger.service';
import { LNDEffects } from '../../../store/lnd.effects';
import { RTLEffects } from '../../../../store/rtl.effects';
import * as RTLActions from '../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../store/rtl.reducers';
import { LNDEffects } from '../../../../store/lnd.effects';
import { RTLEffects } from '../../../../../store/rtl.effects';
import * as RTLActions from '../../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../../store/rtl.reducers';
@Component({
selector: 'rtl-channel-restore',
templateUrl: './channel-restore.component.html',
styleUrls: ['./channel-restore.component.scss']
selector: 'rtl-channel-restore-table',
templateUrl: './channel-restore-table.component.html',
styleUrls: ['./channel-restore-table.component.scss']
})
export class ChannelRestoreComponent implements OnInit {
export class ChannelRestoreTableComponent implements OnInit {
@ViewChild(MatSort, { static: true }) sort: MatSort;
public selNode: SelNodeChild = {};
public displayedColumns = ['chan_point', 'restore'];

View File

@ -18,5 +18,11 @@
</ng-template>
<rtl-channel-closed-table></rtl-channel-closed-table>
</mat-tab>
<mat-tab label="Backup">
<rtl-channel-backup-table></rtl-channel-backup-table>
</mat-tab>
<mat-tab label="Restore">
<rtl-channel-restore-table></rtl-channel-restore-table>
</mat-tab>
</mat-tab-group>
</div>

View File

@ -1,91 +1,77 @@
<div fxLayout="column">
<div class="padding-gap">
<mat-card>
<mat-card-header>
<mat-card-subtitle>
<h2>Connect Peer</h2>
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<form fxLayout="column" fxLayout.gt-sm="row wrap" (ngSubmit)="connectPeerForm.form.valid && onConnectPeer()" #connectPeerForm="ngForm">
<mat-form-field fxFlex="70" fxLayoutAlign="start end">
<input matInput placeholder="Lightning Address (pubkey OR pubkey@ip:port)" name="peerAddress" [(ngModel)]="peerAddress" tabindex="1" required #peerAdd="ngModel">
</mat-form-field>
<div fxFlex="15" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-raised-button color="primary" [disabled]="peerAdd.invalid" type="submit" tabindex="2">
<p *ngIf="peerAdd.invalid && (peerAdd.dirty || peerAdd.touched); else connectText">Invalid Address</p>
<ng-template #connectText><p>Connect</p></ng-template>
</button>
</div>
<div fxFlex="15" fxLayoutAlign="start start">
<button fxFlex="90" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="2" type="reset" (click)="resetData()">Clear</button>
</div>
</form>
</mat-card-content>
</mat-card>
<form fxLayout="column" fxLayoutAlign="space-between stretch" fxLayout.gt-md="row wrap" #peersForm="ngForm">
<mat-form-field fxFlex="100" fxLayoutAlign="start end">
<input matInput placeholder="Lightning Address (pubkey OR pubkey@ip:port)" name="peerAddress" [(ngModel)]="peerAddress" tabindex="1" required #peerAdd="ngModel">
</mat-form-field>
<div fxFlex="30" fxLayoutAlign="space-between start">
<button fxFlex="48" fxLayoutAlign="center center" mat-stroked-button color="primary" tabindex="2" type="reset" (click)="resetData()">Clear Field</button>
<button fxFlex="48" fxLayoutAlign="center center" mat-raised-button color="primary" [disabled]="peerAdd.invalid" type="submit" tabindex="3" (click)="onConnectPeer()">
<p *ngIf="peerAdd.invalid && (peerAdd.dirty || peerAdd.touched); else connectText">Invalid Address</p>
<ng-template #connectText><p>Add Peer</p></ng-template>
</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]="faUsers" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Connected Peers</span>
</div>
<mat-form-field fxFlex="30">
<div fxLayout="row" fxLayoutAlign="start start">
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</div>
</mat-form-field>
</div>
<div class="pconnecting-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-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<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>
</ng-container>
<ng-container matColumnDef="open_channel">
<th mat-header-cell *matHeaderCellDef>Open Channel</th>
<td mat-cell *matCellDef="let peer"><mat-icon color="accent" (click)="onOpenChannel(peer)">playlist_add</mat-icon></td>
</ng-container>
<ng-container matColumnDef="pub_key">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Pub Key </th>
<td mat-cell *matCellDef="let peer">
<div> {{peer?.pub_key | slice:0:10}}... </div>
</td>
</ng-container>
<ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Alias </th>
<td mat-cell *matCellDef="let peer"> {{peer?.alias}} </td>
</ng-container>
<ng-container matColumnDef="address">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Address </th>
<td mat-cell *matCellDef="let peer"> {{peer?.address}} </td>
</ng-container>
<ng-container matColumnDef="bytes_sent">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Bytes Sent </th>
<td mat-cell *matCellDef="let peer"><span fxLayoutAlign="end center"> {{peer?.bytes_sent | number}} </span></td>
</ng-container>
<ng-container matColumnDef="bytes_recv">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Bytes Recv </th>
<td mat-cell *matCellDef="let peer"><span fxLayoutAlign="end center"> {{peer?.bytes_recv | number}} </span></td>
</ng-container>
<ng-container matColumnDef="sat_sent">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> {{information?.smaller_currency_unit}} Sent </th>
<td mat-cell *matCellDef="let peer"><span fxLayoutAlign="end center"> {{peer?.sat_sent | number}} </span></td>
</ng-container>
<ng-container matColumnDef="sat_recv">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> {{information?.smaller_currency_unit}} Recv </th>
<td mat-cell *matCellDef="let peer"><span fxLayoutAlign="end center"> {{peer?.sat_recv | number}} </span></td>
</ng-container>
<ng-container matColumnDef="inbound">
<th mat-header-cell class="pl-4" *matHeaderCellDef mat-sort-header> Inbound </th>
<td mat-cell class="pl-4" *matCellDef="let peer"> {{peer?.inbound}} </td>
</ng-container>
<ng-container matColumnDef="ping_time">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Ping </th>
<td mat-cell *matCellDef="let peer"><span fxLayoutAlign="end center"> {{peer?.ping_time | number}} </span></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.pub_key === newlyAddedPeer && flgAnimate) ? 'added' : 'notAdded'" (click)="onPeerClick(row, $event)"></tr>
</table>
</div>
</mat-card-content>
</mat-card>
<div perfectScrollbar fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="peers" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
<ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Alias </th>
<td mat-cell *matCellDef="let peer"> {{peer?.alias}} </td>
</ng-container>
<ng-container matColumnDef="pub_key">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Pub Key </th>
<td mat-cell *matCellDef="let peer">
<div> {{peer?.pub_key}} </div>
</td>
</ng-container>
<ng-container matColumnDef="sat_sent">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">
{{information?.smaller_currency_unit}} Sent </th>
<td mat-cell *matCellDef="let peer"><span fxLayoutAlign="end center"> {{peer?.sat_sent | number}} </span></td>
</ng-container>
<ng-container matColumnDef="sat_recv">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">
{{information?.smaller_currency_unit}} Recv </th>
<td mat-cell *matCellDef="let peer"><span fxLayoutAlign="end center"> {{peer?.sat_recv | number}} </span></td>
</ng-container>
<ng-container matColumnDef="ping_time">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Ping </th>
<td mat-cell *matCellDef="let peer"><span fxLayoutAlign="end center"> {{peer?.ping_time | number}} </span>
</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 peer" fxLayoutAlign="end center">
<div fxFlex="100" class="bordered-box table-actions-select" fxLayoutAlign="center center">
<mat-select placeholder="Actions" tabindex="1" class="mr-0">
<mat-select-trigger></mat-select-trigger>
<mat-option (click)="onPeerClick(peer, $event)">View Info</mat-option>
<mat-option (click)="onOpenChannel(peer)">Open Channel</mat-option>
<mat-option (click)="onPeerDetach(peer)">Disconnect</mat-option>
</mat-select>
</div>
</td>
</ng-container>
<ng-container matColumnDef="no_peer">
<td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="!peers.data || peers.data.length<1">No connected peers.</p>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [@newlyAddedRowAnimation]="(row.pub_key === newlyAddedPeer && flgAnimate) ? 'added' : 'notAdded'"></tr>
<tr mat-footer-row *matFooterRowDef="['no_peer']" [ngClass]="{'display-none': peers.data && peers.data.length>1}"></tr>
</table>
</div>
</div>
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" showFirstLastButtons class="mb-4"></mat-paginator>
</div>

View File

@ -1,17 +1,20 @@
.mat-column-detach {
flex: 0 0 5%;
min-width: 50px;
}
.mat-column-alias, .mat-column-address {
.mat-column-alias {
flex: 0 0 15%;
min-width: 100px;
width: 15%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mat-cell.mat-column-detach {
cursor: pointer;
.mat-column-pub_key {
flex: 0 0 35%;
width: 35%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 2rem;
}
table {
width:100%;
.mat-column-ping_time {
padding-right: 2rem;
}

View File

@ -5,11 +5,14 @@ import { Subject } from 'rxjs';
import { takeUntil, filter, take } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { faUsers } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort } from '@angular/material';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { Peer, GetInfo } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../../../shared/models/enums';
import { LoggerService } from '../../../shared/services/logger.service';
import { getPaginatorLabel } from '../../../shared/services/paginator.service';
import { OpenChannelComponent } from '../../../shared/components/data-modal/open-channel/open-channel.component';
import { newlyAddedRowAnimation } from '../../../shared/animation/row-animation';
import { LNDEffects } from '../../store/lnd.effects';
import { RTLEffects } from '../../../store/rtl.effects';
@ -20,38 +23,46 @@ import * as fromRTLReducer from '../../../store/rtl.reducers';
selector: 'rtl-peers',
templateUrl: './peers.component.html',
styleUrls: ['./peers.component.scss'],
animations: [newlyAddedRowAnimation]
animations: [newlyAddedRowAnimation],
providers: [
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Peers') },
]
})
export class PeersComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
public faUsers = faUsers;
public newlyAddedPeer = '';
public flgAnimate = true;
public displayedColumns = [];
public peerAddress = '';
public peers: any;
public information: GetInfo = {};
public availableBalance = 0;
public flgLoading: Array<Boolean | 'error'> = [true]; // 0: peers
public flgSticky = false;
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private lndEffects: LNDEffects, private actions$: Actions, private router: Router) {
switch (true) {
case (window.innerWidth <= 415):
this.displayedColumns = ['detach', 'pub_key', 'alias'];
this.displayedColumns = [ 'alias', 'sat_sent', 'sat_recv', 'actions'];
break;
case (window.innerWidth > 415 && window.innerWidth <= 730):
this.displayedColumns = ['detach', 'pub_key', 'alias', 'address', 'sat_sent', 'sat_recv'];
this.displayedColumns = [ 'alias', 'pub_key', 'sat_sent', 'sat_recv', 'actions'];
break;
case (window.innerWidth > 730 && window.innerWidth <= 1024):
this.displayedColumns = ['detach', 'open_channel', 'pub_key', 'alias', 'address', 'sat_sent', 'sat_recv', 'inbound'];
this.displayedColumns = ['alias', 'pub_key', 'sat_sent', 'sat_recv', 'ping_time', 'actions'];
break;
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
this.flgSticky = true;
this.displayedColumns = ['detach', 'open_channel', 'pub_key', 'alias', 'address', 'sat_sent', 'sat_recv', 'inbound', 'ping_time'];
this.displayedColumns = ['alias', 'pub_key', 'sat_sent', 'sat_recv', 'ping_time', 'actions'];
break;
default:
this.flgSticky = true;
this.displayedColumns = ['detach', 'open_channel', 'pub_key', 'alias', 'address', 'bytes_sent', 'bytes_recv', 'sat_sent', 'sat_recv', 'inbound', 'ping_time'];
this.displayedColumns = ['alias', 'pub_key', 'sat_sent', 'sat_recv', 'ping_time', 'actions'];
break;
}
}
@ -66,6 +77,7 @@ export class PeersComponent implements OnInit, OnDestroy {
}
});
this.information = rtlStore.information;
this.availableBalance = rtlStore.blockchainBalance.total_balance || 0;
this.peers = new MatTableDataSource([]);
this.peers.data = [];
if (undefined !== rtlStore.peers) {
@ -74,6 +86,7 @@ export class PeersComponent implements OnInit, OnDestroy {
setTimeout(() => { this.flgAnimate = false; }, 3000);
}
this.peers.sort = this.sort;
this.peers.paginator = this.paginator;
if (this.flgLoading[0] !== 'error') {
this.flgLoading[0] = false;
}
@ -94,7 +107,6 @@ export class PeersComponent implements OnInit, OnDestroy {
const deviderIndex = this.peerAddress.search('@');
let pubkey = '';
let host = '';
if (new RegExp(pattern).test(this.peerAddress)) {
pubkey = this.peerAddress.substring(0, deviderIndex);
host = this.peerAddress.substring(deviderIndex + 1);
@ -127,7 +139,7 @@ export class PeersComponent implements OnInit, OnDestroy {
return peer.pub_key === selRow.pub_key;
})[0];
const reorderedPeer = JSON.parse(JSON.stringify(selPeer, [
'pub_key', 'alias', 'address', 'bytes_sent', 'bytes_recv', 'sat_sent', 'sat_recv', 'inbound', 'ping_time'
'alias', 'pub_key', 'address', 'bytes_sent', 'bytes_recv', 'sat_sent', 'sat_recv', 'inbound', 'ping_time'
] , 2));
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '75%', data: { type: 'INFO', message: JSON.stringify(reorderedPeer)}}}));
}
@ -137,7 +149,7 @@ export class PeersComponent implements OnInit, OnDestroy {
}
onOpenChannel(peerToAddChannel: Peer) {
this.router.navigate(['lnd/chnlmanage'], { state: { peer: peerToAddChannel.pub_key }});
this.store.dispatch(new RTLActions.OpenAlert({config: { width: '50%', data: { type: 'INFO', message: JSON.stringify({peer: peerToAddChannel, information: this.information, balance: this.availableBalance})}}, component: OpenChannelComponent}));
}
onPeerDetach(peerToDetach: Peer) {

View File

@ -7,7 +7,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginatorIntl } from '@angular/material';
import { getPaginatorLabel } from '../../../shared/services/paginator.service';
import { TimeUnitEnum, CurrencyUnitEnum, TIME_UNITS, CURRENCY_UNIT_FORMATS } from '../../../shared/models/enums';
import { TimeUnitEnum, CurrencyUnitEnum, TIME_UNITS, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../../../shared/models/enums';
import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { GetInfo, Invoice } from '../../../shared/models/lndModels';
import { LoggerService } from '../../../shared/services/logger.service';
@ -47,8 +47,8 @@ export class LightningInvoicesComponent implements OnInit, OnDestroy {
public private = false;
public expiryStep = 100;
public totalInvoices = 100;
public pageSize = 10;
public pageSizeOptions = [5, 10, 25, 100];
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
public timeUnitEnum = TimeUnitEnum;
public timeUnits = TIME_UNITS;
public selTimeUnit = TimeUnitEnum.SECS;

View File

@ -6,6 +6,7 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
import { GetInfo, Payment, PayRequest } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../../../shared/models/enums';
import { LoggerService } from '../../../shared/services/logger.service';
import { getPaginatorLabel } from '../../../shared/services/paginator.service';
@ -21,12 +22,12 @@ import * as fromRTLReducer from '../../../store/rtl.reducers';
styleUrls: ['./lightning-payments.component.scss'],
animations: [newlyAddedRowAnimation],
providers: [
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Payments') },
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Payments') }
]
})
export class LightningPaymentsComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild('sendPaymentForm', { static: true }) form;
@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
faHistory = faHistory;
public newlyAddedPayment = '';
@ -39,8 +40,8 @@ export class LightningPaymentsComponent implements OnInit, OnDestroy {
public paymentDecoded: PayRequest = {};
public paymentRequest = '';
public flgSticky = false;
public pageSize = 10;
public pageSizeOptions = [5, 10, 25, 100];
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private lndEffects: LNDEffects) {

View File

@ -73,11 +73,11 @@
<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" mat-stroked-button color="primary" type="reset" (click)="onShowAdvanced()" tabindex="2" class="mr-2">
<button fxFlex="25" fxLayoutAlign="center center" mat-stroked-button color="primary" type="reset" (click)="onShowAdvanced()" tabindex="1" class="mr-2">
<p *ngIf="!showAdvanced; else hideAdvancedText">Show Advanced</p>
<ng-template #hideAdvancedText><p>Hide Advanced</p></ng-template>
</button>
<button autoFocus fxFlex="33" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="1" type="submit" rtlClipboard [payload]="invoice.payment_request" (copied)="onCopyPayment($event)">Copy Payment Request</button>
<button autoFocus fxFlex="33" fxLayoutAlign="center center" mat-raised-button color="primary" tabindex="2" type="submit" rtlClipboard [payload]="invoice.payment_request" (copied)="onCopyPayment($event)">Copy Payment Request</button>
</div>
</div>
</mat-card-content>

View File

@ -8,7 +8,7 @@
<fa-icon [icon]="faReceipt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Generated Address</span>
</div>
<button tabindex="3" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
<button tabindex="2" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header>
<mat-card-content>
<div fxLayout="column">

View File

@ -0,0 +1,89 @@
<div fxLayout="row">
<div fxFlex="100" class="padding-gap-large">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header">
<div fxFlex="95" fxLayoutAlign="start start">
<span class="page-title">Peer Connected</span>
</div>
<button tabindex="8" fxFlex="5" fxLayoutAlign="center" class="btn-close-x p-0" (click)="onClose()" mat-button>X</button>
</mat-card-header>
<mat-card-content class="mt-5px">
<div fxLayout="column">
<div fxLayout="row">
<div fxFlex="100">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
<strong class="font-weight-900">{{peer.alias || peer.address}}</strong>&nbsp; added as a peer.
</mat-panel-title>
</mat-expansion-panel-header>
<div fxLayout="column">
<div fxLayout="row">
<div fxFlex="100">
<h4 fxLayoutAlign="start" class="font-bold-500">Pubkey</h4>
<span class="foreground-secondary-text">{{peer.pub_key}}</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">Address</h4>
<span class="overflow-wrap foreground-secondary-text">{{peer.address}}</span>
</div>
<div fxFlex="50">
<h4 fxLayoutAlign="start" class="font-bold-500">Inbound</h4>
<span class="overflow-wrap foreground-secondary-text">{{peer.inbound ? 'Inbound' : 'Outbound'}}</span>
</div>
</div>
</div>
</mat-expansion-panel>
</div>
</div>
<div fxLayout="column">
<div fxLayout="row" fxFlex="100">
<mat-card-header fxLayout="row" fxLayoutAlign="space-between center" class="modal-info-header mt-2">
<div fxFlex="100" fxLayoutAlign="start start">
<span class="page-title">Open Channel</span>
</div>
</mat-card-header>
</div>
<div fxLayout="row" fxFlex="100">
Available balance: {{totalBalance | number}} {{information.smaller_currency_unit}}
</div>
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between center" class="mt-2">
<mat-form-field fxFlex="20" fxLayoutAlign="start end">
<input matInput [(ngModel)]="fundingAmount" placeholder="Amount" type="number" step="1000" min="1" max="{{totalBalance}}" tabindex="1" required name="amount" #amount="ngModel">
<mat-hint>(Remaining Bal: {{totalBalance - ((fundingAmount) ? fundingAmount : 0)}})</mat-hint>
<span matSuffix> {{information?.smaller_currency_unit}} </span>
</mat-form-field>
<mat-form-field fxFlex="25" fxLayoutAlign="start end">
<mat-select tabindex="2" [(value)]="selTransType">
<mat-option *ngFor="let transType of transTypes" [value]="transType.id">
{{transType.name}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="25" *ngIf="selTransType=='0'">
<input matInput placeholder="Channel Opening Priority" disabled>
</mat-form-field>
<mat-form-field fxFlex="25" *ngIf="selTransType=='1'">
<input matInput [(ngModel)]="transTypeValue.blocks" placeholder="Target Confirmation Blocks" type="number" name="blocks" step="1" min="0" required tabindex="3" #blocks="ngModel">
</mat-form-field>
<mat-form-field fxFlex="25" *ngIf="selTransType=='2'">
<input matInput [(ngModel)]="transTypeValue.fees" placeholder="Fee ({{information?.smaller_currency_unit}}/Byte)" type="number" name="fees" step="1" min="0" required tabindex="4" #fees="ngModel">
</mat-form-field>
<div fxFlex="25" fxLayoutAlign="start center">
<mat-slide-toggle tabindex="5" color="primary" [(ngModel)]="isPrivate" name="isPrivate">Private Channel</mat-slide-toggle>
</div>
</div>
</div>
<div class="mt-2" fxLayout="row" fxLayoutAlign="end center">
<button fxFlex="25" fxLayoutAlign="center center" mat-stroked-button color="primary" (click)="onClose()" tabindex="6" class="mr-2">Do It Later</button>
<button autoFocus fxFlex="33" fxLayoutAlign="center center" mat-raised-button color="primary" (click)="onOpenChannel()" [disabled]="fundingAmount == null || (totalBalance - ((fundingAmount) ? fundingAmount : 0) < 0)" type="submit" tabindex="7">
<p *ngIf="(fundingAmount == null) && (amount.touched || amount.dirty); else openText">Invalid Values</p>
<ng-template #openText><p>Open Channel</p></ng-template>
</button>
</div>
</div>
</mat-card-content>
</div>
</div>

View File

@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChannelBackupComponent } from './channel-backup.component';
import { OpenChannelComponent } from './open-channel.component';
describe('ChannelBackupComponent', () => {
let component: ChannelBackupComponent;
let fixture: ComponentFixture<ChannelBackupComponent>;
describe('OpenChannelComponent', () => {
let component: OpenChannelComponent;
let fixture: ComponentFixture<OpenChannelComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChannelBackupComponent ]
declarations: [ OpenChannelComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChannelBackupComponent);
fixture = TestBed.createComponent(OpenChannelComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -0,0 +1,55 @@
import { Component, OnInit, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { Store } from '@ngrx/store';
import { Peer, GetInfo } from '../../../models/lndModels';
import { AlertData } from '../../../models/alertData';
import { TRANS_TYPES } from '../../../models/enums';
import * as RTLActions from '../../../../store/rtl.actions';
import * as fromRTLReducer from '../../../../store/rtl.reducers';
@Component({
selector: 'rtl-open-channel',
templateUrl: './open-channel.component.html',
styleUrls: ['./open-channel.component.scss']
})
export class OpenChannelComponent implements OnInit {
public peer: Peer;
public information: GetInfo;
public totalBalance = 0;
public fundingAmount: number;
public isPrivate = false;
public selTransType = '0';
public transTypeValue = {blocks: '', fees: ''};
public transTypes = TRANS_TYPES;
constructor(public dialogRef: MatDialogRef<OpenChannelComponent>, @Inject(MAT_DIALOG_DATA) public data: AlertData, private store: Store<fromRTLReducer.RTLState>) { }
ngOnInit() {
let JSONdata = JSON.parse(this.data.message);
this.peer = JSONdata.peer;
this.information = JSONdata.information;
this.totalBalance = JSONdata.balance;
}
onClose() {
this.dialogRef.close(false);
}
onOpenChannel() {
let transTypeValue = '0';
if (this.selTransType === '1') {
transTypeValue = this.transTypeValue.blocks;
} else if (this.selTransType === '2') {
transTypeValue = this.transTypeValue.fees;
}
this.store.dispatch(new RTLActions.OpenSpinner('Opening Channel...'));
this.store.dispatch(new RTLActions.SaveNewChannel({
selectedPeerPubkey: this.peer.pub_key, fundingAmount: this.fundingAmount, private: this.isPrivate,
transType: this.selTransType, transTypeValue: transTypeValue, spendUnconfirmed: false
}));
this.dialogRef.close(false);
}
}

View File

@ -1,14 +1,22 @@
export const CURRENCY_UNITS = [ 'Sats', 'BTC' ];
export const CURRENCY_UNIT_FORMATS = { Sats: '1.0-0', BTC: '1.6-6', OTHER: '1.2-2'};
export const TIME_UNITS = ['SECS', 'MINS', 'HOURS', 'DAYS'];
export const PAGE_SIZE = 10;
export const PAGE_SIZE_OPTIONS = [5, 10, 25, 100];
export const ADDRESS_TYPES = [
{ addressId: '0', addressTp: 'Bech32 (P2WKH)', addressDetails: 'Pay to witness key hash'},
{ addressId: '1', addressTp: 'P2SH (NP2WKH)', addressDetails: 'Pay to nested witness key hash (default)'}
];
export const TRANS_TYPES = [
{id: '0', name: 'Default Priority'},
{id: '1', name: 'Target Confirmation Blocks'},
{id: '2', name: 'Fee'}
];
export enum AuthenticateWith {
TOKEN = 'TOKEN',
PASSWORD = 'PASSWORD'

View File

@ -278,6 +278,7 @@ export interface Peer {
sat_recv?: string;
inbound?: boolean;
ping_time?: number;
sync_type?: string;
}
export interface QueryRoutes {

View File

@ -35,6 +35,7 @@ import { ClipboardDirective } from './directive/clipboard.directive';
import { AutoFocusDirective } from './directive/auto-focus.directive';
import { RemoveLeadingZerosPipe } from './pipes/app.pipe';
import { CommonService } from './services/common.service';
import { OpenChannelComponent } from './components/data-modal/open-channel/open-channel.component';
@NgModule({
imports: [
@ -151,11 +152,13 @@ import { CommonService } from './services/common.service';
ErrorComponent,
ClipboardDirective,
AutoFocusDirective,
RemoveLeadingZerosPipe
RemoveLeadingZerosPipe,
OpenChannelComponent
],
entryComponents: [
InvoiceInformationComponent,
OnChainGeneratedAddressComponent,
OpenChannelComponent,
AlertMessageComponent,
SpinnerDialogComponent,
ConfirmationMessageComponent

View File

@ -249,4 +249,5 @@
.mat-raised-button.mat-primary:disabled {
cursor: not-allowed;
}
}

View File

@ -247,6 +247,10 @@ body {
margin-top: 2px !important;
}
.mt-5px {
margin-top: 5px !important;
}
.my-2px {
margin: 2px 0 !important;
}
@ -299,6 +303,10 @@ body {
margin-top: -1rem !important;
}
.mt-minus-2 {
margin-top: -2rem !important;
}
.mb-2 {
margin-bottom: 2rem !important;
}
@ -775,3 +783,15 @@ table {
margin-right: 1rem;
background-color: $yellow-color;
}
.font-size-80 {
font-size: 80% !important;
}
.font-weight-900 {
font-weight: 900 !important;
}
.display-none {
display: none !important;
}