parent
b3d85d30fc
commit
1b4f55761e
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
@ -1 +0,0 @@
|
||||
!function(e){function r(r){for(var n,a,i=r[0],c=r[1],f=r[2],p=0,s=[];p<i.length;p++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"77d491bf73b15683870f",6:"b4a9bd707a549a4eb404",7:"84e864ea895f0d630a75"}[e]+".js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var l=c;t()}([]);
|
@ -0,0 +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++)i=a[p],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&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:"77d491bf73b15683870f",6:"b479355282ea9b377ebc",7:"22cd396798191c8cb98f"}[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
@ -1,69 +0,0 @@
|
||||
<mat-card [ngClass]="{'custom-card error-border': flgLoading==='error','custom-card': true}">
|
||||
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
|
||||
<mat-card-title class="m-0 pt-2">
|
||||
<h5>Fee Rates - per{{feeRateStyle}}</h5>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div fxLayout="column" class="px-4">
|
||||
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Urgent</mat-list-item>
|
||||
<mat-list-item fxFlex="45" fxLayoutAlign="end start">
|
||||
<p class="mat-button-text">{{perkbw?.urgent | number}}</p>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Normal</mat-list-item>
|
||||
<mat-list-item fxFlex="45" fxLayoutAlign="end start">
|
||||
<p class="mat-button-text">{{perkbw?.normal | number}}</p>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Slow</mat-list-item>
|
||||
<mat-list-item fxFlex="45" fxLayoutAlign="end start">
|
||||
<p class="mat-button-text">{{perkbw?.slow | number}}</p>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Min Acceptable</mat-list-item>
|
||||
<mat-list-item fxFlex="45" fxLayoutAlign="end start">
|
||||
<p class="mat-button-text">{{perkbw?.min_acceptable | number}}</p>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Max Acceptable</mat-list-item>
|
||||
<mat-list-item fxFlex="45" fxLayoutAlign="end start">
|
||||
<p class="mat-button-text">{{perkbw?.max_acceptable | number}}</p>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Opening Channel</mat-list-item>
|
||||
<mat-list-item fxFlex="45" fxLayoutAlign="end start">
|
||||
<p class="mat-button-text">{{feeRates?.onchain_fee_estimates?.opening_channel_satoshis | number}}</p>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Mutual Close</mat-list-item>
|
||||
<mat-list-item fxFlex="45" fxLayoutAlign="end start">
|
||||
<p class="mat-button-text">{{feeRates?.onchain_fee_estimates?.mutual_close_satoshis | number}}</p>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list class="fee-rate-list" fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="50" fxLayoutAlign="start start">Unilateral Close</mat-list-item>
|
||||
<mat-list-item fxFlex="45" fxLayoutAlign="end start">
|
||||
<p class="mat-button-text">{{feeRates?.onchain_fee_estimates?.unilateral_close_satoshis | number}}</p>
|
||||
</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
</div>
|
||||
<mat-progress-bar *ngIf="flgLoading===true" mode="indeterminate" class="mt-minus-5"></mat-progress-bar>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
@ -0,0 +1,38 @@
|
||||
<div fxLayout="row" fxFlex="100" fxLayoutAlign="stretch" class="h-100">
|
||||
<div fxLayout="column" fxFlex="50" fxLayoutAlign="space-between stretch">
|
||||
<div>
|
||||
<h4 fxLayoutAlign="start" class="dashboard-info-title">Urgent</h4>
|
||||
<div class="overflow-wrap dashboard-info-value">{{perkbw?.urgent | number}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 fxLayoutAlign="start" class="dashboard-info-title">Normal</h4>
|
||||
<div class="overflow-wrap dashboard-info-value">{{perkbw?.normal | number}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 fxLayoutAlign="start" class="dashboard-info-title">Slow</h4>
|
||||
<div class="overflow-wrap dashboard-info-value">{{perkbw?.slow | number}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 fxLayoutAlign="start" class="dashboard-info-title">Opening Channel</h4>
|
||||
<div class="overflow-wrap dashboard-info-value">{{feeRates?.onchain_fee_estimates?.opening_channel_satoshis | number}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div fxLayout="column" fxFlex="50" fxLayoutAlign="space-between stretch">
|
||||
<div>
|
||||
<h4 fxLayoutAlign="start" class="dashboard-info-title">Min Acceptable</h4>
|
||||
<div class="overflow-wrap dashboard-info-value">{{perkbw?.min_acceptable | number}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 fxLayoutAlign="start" class="dashboard-info-title">Max Acceptable</h4>
|
||||
<div class="overflow-wrap dashboard-info-value">{{perkbw?.max_acceptable | number}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 fxLayoutAlign="start" class="dashboard-info-title">Mutual Close</h4>
|
||||
<div class="overflow-wrap dashboard-info-value">{{feeRates?.onchain_fee_estimates?.mutual_close_satoshis | number}}</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 fxLayoutAlign="start" class="dashboard-info-title">Unilateral Close</h4>
|
||||
<div class="overflow-wrap dashboard-info-value">{{feeRates?.onchain_fee_estimates?.unilateral_close_satoshis | number}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,52 @@
|
||||
<div fxLayout="column" fxLayoutAlign="space-between stretch" class="mb-4">
|
||||
<mat-grid-list *ngIf="selNode.userPersona === userPersonaEnum.OPERATOR" cols="6" rowHeight="110px">
|
||||
<mat-grid-tile class="node-grid-tile" *ngFor="let card of nodeCardsOperator" [colspan]="card.cols" [rowspan]="card.rows">
|
||||
<div fxLayout="column" fxLayoutAlign="stretch start" fxFlex="100" class="h-100">
|
||||
<div fxLayout="row" fxLayoutAlign="start start" class="w-100">
|
||||
<div fxLayout="row" fxLayoutAlign="start start" class="page-title-container pl-2">
|
||||
<fa-icon [icon]="card.icon" class="mr-1"></fa-icon>
|
||||
<span>{{card.title}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div fxLayout="column" fxLayoutAlign="stretch center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="center stretch" class="w-100 h-93">
|
||||
<mat-card fxLayout="row" fxFlex="95" fxLayoutAlign="start stretch" class="dashboard-card p-24 w-96 h-93">
|
||||
<mat-card-content fxFlex="100" class="dashboard-card-content">
|
||||
<div [ngSwitch]="card.id" fxLayout="column" fxFlex="100">
|
||||
<rtl-cl-node-info fxFlex="100" *ngSwitchCase="'node'" [information]="information" [showColorFieldSeparately]="false" [ngClass]="{'error-border': flgLoading[0]==='error'}"></rtl-cl-node-info>
|
||||
<rtl-cl-channel-status-info fxFlex="100" *ngSwitchCase="'status'" [channelsStatus]="channelsStatus" [ngClass]="{'error-border': flgLoading[0]==='error'}"></rtl-cl-channel-status-info>
|
||||
<rtl-cl-fee-info fxFlex="100" *ngSwitchCase="'fee'" [fees]="fees" [ngClass]="{'error-border': flgLoading[1]==='error'}"></rtl-cl-fee-info>
|
||||
<rtl-cl-fee-rates *ngSwitchCase="'feeRatesKB'" [flgLoading]="flgLoading[2]" [feeRates]="feeRatesPerKB" [feeRateStyle]="'KB'" class="h-100"></rtl-cl-fee-rates>
|
||||
<rtl-cl-fee-rates *ngSwitchCase="'feeRatesKW'" [flgLoading]="flgLoading[2]" [feeRates]="feeRatesPerKW" [feeRateStyle]="'KW'" class="h-100"></rtl-cl-fee-rates>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
<mat-grid-list *ngIf="selNode.userPersona === userPersonaEnum.MERCHANT" cols="6" rowHeight="110px">
|
||||
<mat-grid-tile class="node-grid-tile" *ngFor="let card of nodeCardsMerchant" [colspan]="card.cols" [rowspan]="card.rows">
|
||||
<div fxLayout="column" fxLayoutAlign="stretch start" fxFlex="100" class="h-100">
|
||||
<div fxLayout="row" fxLayoutAlign="start start" class="w-100">
|
||||
<div fxLayout="row" fxLayoutAlign="start start" class="page-title-container pl-15px">
|
||||
<fa-icon [icon]="card.icon" class="mr-1"></fa-icon>
|
||||
<span>{{card.title}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div fxLayout="column" fxLayoutAlign="stretch center" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="center stretch" class="w-100 h-93">
|
||||
<mat-card fxLayout="row" fxFlex="95" fxLayoutAlign="start stretch" class="dashboard-card p-24 w-96 h-93">
|
||||
<mat-card-content fxFlex="100" class="dashboard-card-content">
|
||||
<div [ngSwitch]="card.id" fxLayout="column" fxFlex="100">
|
||||
<rtl-cl-node-info fxFlex="100" *ngSwitchCase="'node'" [information]="information" [showColorFieldSeparately]="false" [ngClass]="{'error-border': flgLoading[0]==='error'}"></rtl-cl-node-info>
|
||||
<rtl-cl-channel-status-info fxFlex="100" *ngSwitchCase="'status'" [channelsStatus]="channelsStatus" [ngClass]="{'error-border': flgLoading[0]==='error'}"></rtl-cl-channel-status-info>
|
||||
<rtl-cl-fee-info fxFlex="100" *ngSwitchCase="'fee'" [fees]="fees" [ngClass]="{'error-border': flgLoading[1]==='error'}"></rtl-cl-fee-info>
|
||||
<rtl-cl-fee-rates *ngSwitchCase="'feeRatesKB'" [flgLoading]="flgLoading[2]" [feeRates]="feeRatesPerKB" [feeRateStyle]="'KB'" class="h-100"></rtl-cl-fee-rates>
|
||||
<rtl-cl-fee-rates *ngSwitchCase="'feeRatesKW'" [flgLoading]="flgLoading[2]" [feeRates]="feeRatesPerKW" [feeRateStyle]="'KW'" class="h-100"></rtl-cl-fee-rates>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
</div>
|
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NetworkInfoComponent } from './network-info.component';
|
||||
|
||||
describe('NetworkInfoComponent', () => {
|
||||
let component: NetworkInfoComponent;
|
||||
let fixture: ComponentFixture<NetworkInfoComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ NetworkInfoComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NetworkInfoComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,119 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { faBolt, faServer, faNetworkWired } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import { LoggerService } from '../../shared/services/logger.service';
|
||||
import { GetInfoCL, FeesCL, ChannelsStatusCL, FeeRatesCL } from '../../shared/models/clModels';
|
||||
import { SelNodeChild } from '../../shared/models/RTLconfig';
|
||||
|
||||
import * as fromRTLReducer from '../../store/rtl.reducers';
|
||||
import { CommonService } from '../../shared/services/common.service';
|
||||
import { ScreenSizeEnum, UserPersonaEnum } from '../../shared/services/consts-enums-functions';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-cl-network-info',
|
||||
templateUrl: './network-info.component.html',
|
||||
styleUrls: ['./network-info.component.scss']
|
||||
})
|
||||
export class CLNetworkInfoComponent implements OnInit, OnDestroy {
|
||||
public faBolt = faBolt;
|
||||
public faServer = faServer;
|
||||
public faNetworkWired = faNetworkWired;
|
||||
public selNode: SelNodeChild = {};
|
||||
public information: GetInfoCL = {};
|
||||
public fees: FeesCL;
|
||||
public channelsStatus: ChannelsStatusCL = {};
|
||||
feeRatesPerKB: FeeRatesCL = {};
|
||||
feeRatesPerKW: FeeRatesCL = {};
|
||||
public nodeCardsOperator = [];
|
||||
public nodeCardsMerchant = [];
|
||||
public screenSize = '';
|
||||
public screenSizeEnum = ScreenSizeEnum;
|
||||
public userPersonaEnum = UserPersonaEnum;
|
||||
public flgLoading: Array<Boolean | 'error'> = [true, true, true];
|
||||
private unSubs: Array<Subject<void>> = [new Subject()];
|
||||
|
||||
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<fromRTLReducer.RTLState>) {
|
||||
this.screenSize = this.commonService.getScreenSize();
|
||||
if(this.screenSize === ScreenSizeEnum.XS) {
|
||||
this.nodeCardsMerchant = [
|
||||
{ id: 'node', icon: this.faServer, title: 'Node Information', cols: 6, rows: 3 },
|
||||
{ id: 'status', icon: this.faNetworkWired, title: 'Channels', cols: 6, rows: 3 },
|
||||
{ id: 'fee', icon: this.faBolt, title: 'Routing Fee', cols: 6, rows: 1 },
|
||||
{ id: 'feeRatesKB', icon: this.faServer, title: 'Fee Rate Per KB', cols: 6, rows: 4 },
|
||||
{ id: 'feeRatesKW', icon: this.faNetworkWired, title: 'Fee Rate Per KW', cols: 6, rows: 4 }
|
||||
];
|
||||
this.nodeCardsOperator = [
|
||||
{ id: 'feeRatesKB', icon: this.faServer, title: 'Fee Rate Per KB', cols: 6, rows: 4 },
|
||||
{ id: 'feeRatesKW', icon: this.faNetworkWired, title: 'Fee Rate Per KW', cols: 6, rows: 4 }
|
||||
];
|
||||
} else {
|
||||
this.nodeCardsMerchant = [
|
||||
{ id: 'node', icon: this.faServer, title: 'Node Information', cols: 2, rows: 3 },
|
||||
{ id: 'status', icon: this.faNetworkWired, title: 'Channels', cols: 2, rows: 3 },
|
||||
{ id: 'fee', icon: this.faBolt, title: 'Routing Fee', cols: 2, rows: 3 },
|
||||
{ id: 'feeRatesKB', icon: this.faServer, title: 'Fee Rate Per KB', cols: 3, rows: 4 },
|
||||
{ id: 'feeRatesKW', icon: this.faNetworkWired, title: 'Fee Rate Per KW', cols: 3, rows: 4 }
|
||||
];
|
||||
this.nodeCardsOperator = [
|
||||
{ id: 'feeRatesKB', icon: this.faServer, title: 'Fee Rate Per KB', cols: 3, rows: 4 },
|
||||
{ id: 'feeRatesKW', icon: this.faNetworkWired, title: 'Fee Rate Per KW', cols: 3, rows: 4 }
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.store.select('cl')
|
||||
.pipe(takeUntil(this.unSubs[0]))
|
||||
.subscribe((rtlStore) => {
|
||||
rtlStore.effectErrorsCl.forEach(effectsErr => {
|
||||
if (effectsErr.action === 'FetchInfoCL') {
|
||||
this.flgLoading[0] = 'error';
|
||||
}
|
||||
if (effectsErr.action === 'FetchFeesCL') {
|
||||
this.flgLoading[1] = 'error';
|
||||
}
|
||||
if (effectsErr.action === 'FetchFeeRatesCL') {
|
||||
this.flgLoading[2] = 'error';
|
||||
}
|
||||
});
|
||||
this.selNode = rtlStore.nodeSettings;
|
||||
this.information = rtlStore.information;
|
||||
if (this.flgLoading[0] !== 'error') {
|
||||
this.flgLoading[0] = (undefined !== this.information.id) ? false : true;
|
||||
}
|
||||
|
||||
this.fees = rtlStore.fees;
|
||||
this.fees.totalTxCount = 0;
|
||||
if (rtlStore.forwardingHistory && rtlStore.forwardingHistory.forwarding_events && rtlStore.forwardingHistory.forwarding_events.length) {
|
||||
this.fees.totalTxCount = rtlStore.forwardingHistory.forwarding_events.filter(event => event.status === 'settled').length
|
||||
}
|
||||
if (this.flgLoading[1] !== 'error') {
|
||||
this.flgLoading[1] = (undefined !== this.fees.feeCollected) ? false : true;
|
||||
}
|
||||
|
||||
this.channelsStatus = {
|
||||
active: { channels: rtlStore.information.num_active_channels, capacity: 0 },
|
||||
inactive: { channels: rtlStore.information.num_inactive_channels, capacity: 0 },
|
||||
pending: { channels: rtlStore.information.num_pending_channels, capacity: 0 }
|
||||
};
|
||||
|
||||
this.feeRatesPerKB = rtlStore.feeRatesPerKB;
|
||||
this.feeRatesPerKW = rtlStore.feeRatesPerKW;
|
||||
if (this.flgLoading[2] !== 'error') {
|
||||
this.flgLoading[2] = (undefined !== this.feeRatesPerKB && undefined !== this.feeRatesPerKW) ? false : true;
|
||||
}
|
||||
|
||||
this.logger.info(rtlStore);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unSubs.forEach(completeSub => {
|
||||
completeSub.next();
|
||||
completeSub.complete();
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<div fxLayout="column" class="padding-gap">
|
||||
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="padding-gap-x page-sub-title-container">
|
||||
<div fxFlex="70"></div>
|
||||
<mat-form-field fxFlex="30">
|
||||
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div perfectScrollbar fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container w-100">
|
||||
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
|
||||
<table mat-table #table [dataSource]="channels" matSort [ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
|
||||
<ng-container matColumnDef="short_channel_id">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Short Channel ID </th>
|
||||
<td mat-cell *matCellDef="let channel"> {{channel?.short_channel_id}}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="alias">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Alias </th>
|
||||
<td mat-cell *matCellDef="let channel">{{channel?.alias}}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="connected">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Connected </th>
|
||||
<td mat-cell *matCellDef="let channel"> {{(channel?.connected) ? 'Connected' : 'Disconnected'}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="private">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Private </th>
|
||||
<td mat-cell *matCellDef="let channel"> {{(channel?.private ? 'Private' : 'Public')}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="state">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> State </th>
|
||||
<td mat-cell *matCellDef="let channel"> {{channel?.state}}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="msatoshi_to_us">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> mSatoshi To Us </th>
|
||||
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">
|
||||
{{channel?.msatoshi_to_us | number}} </span></td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="msatoshi_total">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Total mSatoshis </th>
|
||||
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">
|
||||
{{channel?.msatoshi_total | number}} </span></td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="spendable_msatoshi">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Spendable Satoshi </th>
|
||||
<td mat-cell *matCellDef="let channel"><span fxLayoutAlign="end center">
|
||||
{{channel?.spendable_msatoshi | 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 channel"><span fxLayoutAlign="end center">
|
||||
<button mat-stroked-button color="primary" type="button" tabindex="4" (click)="onChannelClick(channel, $event)">View Info</button>
|
||||
</span></td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="no_peer">
|
||||
<td mat-footer-cell *matFooterCellDef colspan="4">
|
||||
<p *ngIf="numPeers<1">No peers connected. Add a peer in order to open a channel.</p>
|
||||
<p *ngIf="numPeers>0 && (!channels.data || channels.data.length<1)">No channels available.</p>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-footer-row *matFooterRowDef="['no_peer']" [ngClass]="{'display-none': numPeers>0 && channels.data && channels.data.length>0}"></tr>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
</div>
|
||||
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator>
|
||||
</div>
|
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CLChannelPendingTableComponent } from './channel-pending-table.component';
|
||||
|
||||
describe('CLChannelPendingTableComponent', () => {
|
||||
let component: CLChannelPendingTableComponent;
|
||||
let fixture: ComponentFixture<CLChannelPendingTableComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CLChannelPendingTableComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CLChannelPendingTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,140 @@
|
||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { take, takeUntil } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
import { MatTableDataSource, MatSort, MatPaginator, MatPaginatorIntl } from '@angular/material';
|
||||
import { ChannelCL, GetInfoCL } from '../../../../../shared/models/clModels';
|
||||
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, FEE_RATE_TYPES } from '../../../../../shared/services/consts-enums-functions';
|
||||
import { LoggerService } from '../../../../../shared/services/logger.service';
|
||||
import { CommonService } from '../../../../../shared/services/common.service';
|
||||
|
||||
import { CLEffects } from '../../../../store/cl.effects';
|
||||
import { RTLEffects } from '../../../../../store/rtl.effects';
|
||||
import * as RTLActions from '../../../../../store/rtl.actions';
|
||||
import * as fromRTLReducer from '../../../../../store/rtl.reducers';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-cl-channel-pending-table',
|
||||
templateUrl: './channel-pending-table.component.html',
|
||||
styleUrls: ['./channel-pending-table.component.scss'],
|
||||
providers: [
|
||||
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Channels') }
|
||||
]
|
||||
})
|
||||
export class CLChannelPendingTableComponent implements OnInit, OnDestroy {
|
||||
@ViewChild(MatSort, { static: true }) sort: MatSort;
|
||||
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
|
||||
public totalBalance = 0;
|
||||
public displayedColumns = [];
|
||||
public channels: any;
|
||||
public myChanPolicy: any = {};
|
||||
public information: GetInfoCL = {};
|
||||
public numPeers = -1;
|
||||
public feeRateTypes = FEE_RATE_TYPES;
|
||||
public flgLoading: Array<Boolean | 'error'> = [true];
|
||||
public selectedFilter = '';
|
||||
public selFilter = '';
|
||||
public flgSticky = false;
|
||||
public pageSize = PAGE_SIZE;
|
||||
public pageSizeOptions = PAGE_SIZE_OPTIONS;
|
||||
public screenSize = '';
|
||||
public screenSizeEnum = ScreenSizeEnum;
|
||||
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
|
||||
|
||||
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private rtlEffects: RTLEffects, private clEffects: CLEffects, private commonService: CommonService) {
|
||||
this.screenSize = this.commonService.getScreenSize();
|
||||
if(this.screenSize === ScreenSizeEnum.XS) {
|
||||
this.flgSticky = false;
|
||||
this.displayedColumns = ['short_channel_id', 'state', 'msatoshi_total', 'actions'];
|
||||
} else if(this.screenSize === ScreenSizeEnum.SM) {
|
||||
this.flgSticky = false;
|
||||
this.displayedColumns = ['short_channel_id', 'alias', 'state', 'msatoshi_total', 'actions'];
|
||||
} else if(this.screenSize === ScreenSizeEnum.MD) {
|
||||
this.flgSticky = false;
|
||||
this.displayedColumns = ['short_channel_id', 'alias', 'state', 'msatoshi_total', 'actions'];
|
||||
} else {
|
||||
this.flgSticky = true;
|
||||
this.displayedColumns = ['short_channel_id', 'alias', 'state', 'msatoshi_total', 'actions'];
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.store.select('cl')
|
||||
.pipe(takeUntil(this.unSubs[0]))
|
||||
.subscribe((rtlStore) => {
|
||||
rtlStore.effectErrorsCl.forEach(effectsErr => {
|
||||
if (effectsErr.action === 'FetchChannelsCL') {
|
||||
this.flgLoading[0] = 'error';
|
||||
}
|
||||
});
|
||||
this.information = rtlStore.information;
|
||||
this.numPeers = (rtlStore.peers && rtlStore.peers.length) ? rtlStore.peers.length : 0;
|
||||
this.totalBalance = rtlStore.balance.totalBalance;
|
||||
if (rtlStore.allChannels) {
|
||||
this.loadChannelsTable(rtlStore.allChannels.filter(channel => channel.state !== 'CHANNELD_NORMAL'));
|
||||
}
|
||||
if (this.flgLoading[0] !== 'error') {
|
||||
this.flgLoading[0] = (rtlStore.allChannels) ? false : true;
|
||||
}
|
||||
this.logger.info(rtlStore);
|
||||
});
|
||||
}
|
||||
|
||||
applyFilter() {
|
||||
this.selectedFilter = this.selFilter;
|
||||
this.channels.filter = this.selFilter;
|
||||
}
|
||||
|
||||
onChannelClick(selChannel: ChannelCL, event: any) {
|
||||
const reorderedChannel = [
|
||||
[{key: 'alias', value: selChannel.alias, title: 'Peer Alias', width: 40},
|
||||
{key: 'connected', value: selChannel.connected, title: 'Connected', width: 30, type: DataTypeEnum.BOOLEAN},
|
||||
{key: 'private', value: selChannel.private, title: 'Private', width: 30, type: DataTypeEnum.BOOLEAN}],
|
||||
[{key: 'id', value: selChannel.id, title: 'Peer Public Key', width: 100}],
|
||||
[{key: 'short_channel_id', value: selChannel.short_channel_id, title: 'Short Channel ID', width: 100}],
|
||||
[{key: 'channel_id', value: selChannel.channel_id, title: 'Channel ID', width: 50},
|
||||
{key: 'state', value: selChannel.state, title: 'State', width: 50, type: DataTypeEnum.NUMBER}],
|
||||
[{key: 'our_channel_reserve_satoshis', value: selChannel.our_channel_reserve_satoshis, title: 'Our Channel Reserve Satoshis', width: 50, type: DataTypeEnum.NUMBER},
|
||||
{key: 'their_channel_reserve_satoshis', value: selChannel.their_channel_reserve_satoshis, title: 'Their Channel Reserve Satoshis', width: 50, type: DataTypeEnum.NUMBER}],
|
||||
[{key: 'msatoshi_to_us', value: selChannel.msatoshi_to_us, title: 'mSatoshi to Us', width: 50, type: DataTypeEnum.NUMBER},
|
||||
{key: 'spendable_msatoshi', value: selChannel.spendable_msatoshi, title: 'Spendable mSatoshi', width: 50, type: DataTypeEnum.NUMBER}],
|
||||
[{key: 'msatoshi_total', value: selChannel.msatoshi_total, title: 'Total mSatoshi', width: 50, type: DataTypeEnum.NUMBER},
|
||||
{key: 'funding_txid', value: selChannel.funding_txid, title: 'Funding Transaction Id', width: 50, type: DataTypeEnum.NUMBER}]
|
||||
];
|
||||
this.store.dispatch(new RTLActions.OpenAlert({ data: {
|
||||
type: AlertTypeEnum.INFORMATION,
|
||||
alertTitle: 'Channel Information',
|
||||
showCopyName: 'Short Channel ID',
|
||||
showCopyField: selChannel.short_channel_id,
|
||||
message: reorderedChannel
|
||||
}}));
|
||||
}
|
||||
|
||||
loadChannelsTable(mychannels) {
|
||||
mychannels.sort(function(a, b) {
|
||||
return (a.active === b.active) ? 0 : ((b.active) ? 1 : -1);
|
||||
});
|
||||
this.channels = new MatTableDataSource<ChannelCL>([...mychannels]);
|
||||
this.channels.filterPredicate = (channel: ChannelCL, fltr: string) => {
|
||||
const newChannel = ((channel.connected) ? 'connected' : 'disconnected') + (channel.channel_id ? channel.channel_id : '') +
|
||||
(channel.short_channel_id ? channel.short_channel_id : '') + (channel.id ? channel.id : '') + (channel.alias ? channel.alias : '') +
|
||||
(channel.private ? 'private' : 'public') + (channel.state ? channel.state.toLowerCase() : '') +
|
||||
(channel.funding_txid ? channel.funding_txid : '') + (channel.msatoshi_to_us ? channel.msatoshi_to_us : '') +
|
||||
(channel.msatoshi_total ? channel.msatoshi_total : '') + (channel.their_channel_reserve_satoshis ? channel.their_channel_reserve_satoshis : '') +
|
||||
(channel.our_channel_reserve_satoshis ? channel.our_channel_reserve_satoshis : '') + (channel.spendable_msatoshi ? channel.spendable_msatoshi : '');
|
||||
return newChannel.includes(fltr.toLowerCase());
|
||||
};
|
||||
this.channels.sort = this.sort;
|
||||
this.channels.paginator = this.paginator;
|
||||
this.logger.info(this.channels);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unSubs.forEach(completeSub => {
|
||||
completeSub.next();
|
||||
completeSub.complete();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue