Selected Column Filter Incomplete

Selected Column Filter Incomplete
pull/1127/head
ShahanaFarooqui 2 years ago
parent 211b6fdca4
commit 3b8ca9177a

@ -29,7 +29,7 @@
<ng-container matColumnDef="id"> <ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let hop"> <td mat-cell *matCellDef="let hop">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{hop?.id}}</span> <span class="ellipsis-child">{{hop?.id}}</span>
</div> </div>
</td> </td>
@ -37,7 +37,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
<td mat-cell *matCellDef="let hop"> <td mat-cell *matCellDef="let hop">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{hop?.alias}}</span> <span class="ellipsis-child">{{hop?.alias}}</span>
</div> </div>
</td> </td>

@ -51,11 +51,16 @@
<fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Liquidity Providing Peers</span> <span class="page-title">Liquidity Providing Peers</span>
</div> </div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<div fxLayout="row" fxLayoutAlign="start start"> <mat-form-field fxFlex="49">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
</div> <mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-form-field> </mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -63,7 +68,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
<td mat-cell *matCellDef="let lqNode"> <td mat-cell *matCellDef="let lqNode">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span fxLayout="row" fxLayoutAlign="start center" class="ellipsis-child"> <span fxLayout="row" fxLayoutAlign="start center" class="ellipsis-child">
{{lqNode?.alias}} {{lqNode?.alias}}
<mat-chip-list class="ml-half" aria-label="Address Types"> <mat-chip-list class="ml-half" aria-label="Address Types">
@ -78,7 +83,7 @@
<ng-container matColumnDef="nodeid"> <ng-container matColumnDef="nodeid">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th>
<td mat-cell *matCellDef="let lqNode"> <td mat-cell *matCellDef="let lqNode">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{lqNode?.nodeid}}</span> <span class="ellipsis-child">{{lqNode?.nodeid}}</span>
</div> </div>
</td> </td>

@ -10,7 +10,7 @@ import { faBullhorn, faExclamationTriangle, faUsers } from '@fortawesome/free-so
import { DataService } from '../../../shared/services/data.service'; import { DataService } from '../../../shared/services/data.service';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
import { AlertTypeEnum, APICallStatusEnum, DataTypeEnum, getPaginatorLabel, PAGE_SIZE, PAGE_SIZE_OPTIONS, ScreenSizeEnum, NODE_FEATURES_CLN, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { AlertTypeEnum, APICallStatusEnum, DataTypeEnum, getPaginatorLabel, PAGE_SIZE, PAGE_SIZE_OPTIONS, ScreenSizeEnum, NODE_FEATURES_CLN, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { GetInfo, LookupNode } from '../../../shared/models/clnModels'; import { GetInfo, LookupNode } from '../../../shared/models/clnModels';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { openAlert, openConfirmation } from '../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../store/rtl.actions';
@ -20,7 +20,8 @@ import { RTLEffects } from '../../../store/rtl.effects';
import { CLNOpenLiquidityChannelComponent } from '../open-liquidity-channel-modal/open-liquidity-channel-modal.component'; import { CLNOpenLiquidityChannelComponent } from '../open-liquidity-channel-modal/open-liquidity-channel-modal.component';
import { clnPageSettings, nodeInfoAndNodeSettingsAndBalance } from '../../store/cln.selector'; import { clnPageSettings, nodeInfoAndNodeSettingsAndBalance } from '../../store/cln.selector';
import { DecimalPipe } from '@angular/common'; import { DecimalPipe } from '@angular/common';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-liquidity-ads-list', selector: 'rtl-cln-liquidity-ads-list',
@ -34,6 +35,8 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'liquidity_ads'; public PAGE_ID = 'liquidity_ads';
public tableSetting: TableSetting = { tableId: 'liquidity_ads', recordsPerPage: PAGE_SIZE, sortBy: 'channel_opening_fee', sortOrder: SortOrderEnum.ASCENDING }; public tableSetting: TableSetting = { tableId: 'liquidity_ads', recordsPerPage: PAGE_SIZE, sortBy: 'channel_opening_fee', sortOrder: SortOrderEnum.ASCENDING };
@ -61,7 +64,7 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private dataService: DataService, private commonService: CommonService, private rtlEffects: RTLEffects, private decimalPipe: DecimalPipe) { constructor(private logger: LoggerService, private store: Store<RTLState>, private dataService: DataService, private commonService: CommonService, private rtlEffects: RTLEffects, private decimalPipe: DecimalPipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.askTooltipMsg = 'Specify the liquidity requirements for your node: \n 1. Channel Amount - Amount in Sats you need on the channel opened to your node \n 2. Channel opening fee rate - Rate in Sats/vByte that you are willing to pay to open the channel to you'; this.askTooltipMsg = 'Specify the liquidity requirements for your node: \n 1. Channel Amount - Amount in Sats you need on the channel opened to your node \n 2. Channel opening fee rate - Rate in Sats/vByte that you are willing to pay to open the channel to you';
this.nodesTooltipMsg = 'These nodes are advertising their liquidity offering on the network.\nYou should pay attention to the following aspects to evaluate each node offer: \n- The total bitcoin deployed on the node, the more the better\n'; this.nodesTooltipMsg = 'These nodes are advertising their liquidity offering on the network.\nYou should pay attention to the following aspects to evaluate each node offer: \n- The total bitcoin deployed on the node, the more the better\n';
this.nodesTooltipMsg = this.nodesTooltipMsg + '- The number of channels open on the node, the more the better' + this.nodesTooltipMsg = this.nodesTooltipMsg + '- The number of channels open on the node, the more the better' +
@ -135,11 +138,12 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
this.liquidityNodes.filter = this.selFilter.trim().toLowerCase(); this.liquidityNodes.filter = this.selFilter.trim().toLowerCase();
} }
loadLiqNodesTable(liqNodes: LookupNode[]) { getLabel(column: string) {
this.liquidityNodes = new MatTableDataSource<LookupNode>([...liqNodes]); const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
this.liquidityNodes.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
this.liquidityNodes.sort = this.sort; }
this.liquidityNodes.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
setFilterPredicate() {
this.liquidityNodes.filterPredicate = (node: LookupNode, fltr: string) => { this.liquidityNodes.filterPredicate = (node: LookupNode, fltr: string) => {
const newNode = ((node.alias) ? node.alias.toLocaleLowerCase() : '') + (node.channel_opening_fee ? node.channel_opening_fee + ' Sats' : '') + const newNode = ((node.alias) ? node.alias.toLocaleLowerCase() : '') + (node.channel_opening_fee ? node.channel_opening_fee + ' Sats' : '') +
(node.option_will_fund?.lease_fee_base_msat ? (node.option_will_fund?.lease_fee_base_msat / 1000) + ' Sats' : '') + (node.option_will_fund?.lease_fee_basis ? (this.decimalPipe.transform(node.option_will_fund?.lease_fee_basis / 100, '1.2-2') + '%') : '') + (node.option_will_fund?.lease_fee_base_msat ? (node.option_will_fund?.lease_fee_base_msat / 1000) + ' Sats' : '') + (node.option_will_fund?.lease_fee_basis ? (this.decimalPipe.transform(node.option_will_fund?.lease_fee_basis / 100, '1.2-2') + '%') : '') +
@ -147,9 +151,40 @@ export class CLNLiquidityAdsListComponent implements OnInit, OnDestroy {
(node.address_types ? node.address_types.reduce((acc, curr) => acc + (curr === 'tor' ? ' tor' : curr === 'ipv' ? ' clearnet' : (' ' + curr.toLowerCase())), '') : ''); (node.address_types ? node.address_types.reduce((acc, curr) => acc + (curr === 'tor' ? ' tor' : curr === 'ipv' ? ' clearnet' : (' ' + curr.toLowerCase())), '') : '');
return newNode.includes(fltr); return newNode.includes(fltr);
}; };
// this.liquidityNodes.filterPredicate = (rowData: LookupNode, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadLiqNodesTable(liqNodes: LookupNode[]) {
this.liquidityNodes = new MatTableDataSource<LookupNode>([...liqNodes]);
this.liquidityNodes.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.liquidityNodes.sort = this.sort;
this.liquidityNodes.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.liquidityNodes.paginator = this.paginator; this.liquidityNodes.paginator = this.paginator;
// this.liquidityNodes.filterPredicate = (node: LookupNode, fltr: string) => node.channel_count >= this.channel_count && node.node_capacity >= this.node_capacity; // this.liquidityNodes.filterPredicate = (rowData: LookupNode, fltr: string) => rowData.channel_count >= this.channel_count && rowData.node_capacity >= this.node_capacity;
// this.onFilter(); // this.onFilter();
} }

@ -1,9 +1,16 @@
<div fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100" class="padding-gap-x-large"> <div fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100" class="padding-gap-x-large">
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70" fxLayoutAlign="start start" fxLayoutAlign.gt-sm="start center"></div> <div fxFlex="70" fxLayoutAlign="start start" fxLayoutAlign.gt-sm="start center"></div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start start"> <div fxLayout="row" fxLayoutAlign="start start">
<div [perfectScrollbar] class="table-container" fxFlex="100"> <div [perfectScrollbar] class="table-container" fxFlex="100">
@ -26,7 +33,7 @@
<ng-container matColumnDef="txid"> <ng-container matColumnDef="txid">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Transaction ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Transaction ID</th>
<td mat-cell *matCellDef="let utxo"> <td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{utxo.txid}}</span> <span class="ellipsis-child">{{utxo.txid}}</span>
</span> </span>
</td> </td>
@ -34,7 +41,7 @@
<ng-container matColumnDef="address"> <ng-container matColumnDef="address">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th>
<td mat-cell *matCellDef="let utxo"> <td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{utxo.address}}</span> <span class="ellipsis-child">{{utxo.address}}</span>
</span> </span>
</td> </td>
@ -42,7 +49,7 @@
<ng-container matColumnDef="scriptpubkey"> <ng-container matColumnDef="scriptpubkey">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Script Pubkey</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Script Pubkey</th>
<td mat-cell *matCellDef="let utxo"> <td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{utxo.scriptpubkey}}</span> <span class="ellipsis-child">{{utxo.scriptpubkey}}</span>
</span> </span>
</td> </td>

@ -8,7 +8,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { UTXO } from '../../../../shared/models/clnModels'; import { UTXO } from '../../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS } from '../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../../shared/services/logger.service'; import { LoggerService } from '../../../../shared/services/logger.service';
import { CommonService } from '../../../../shared/services/common.service'; import { CommonService } from '../../../../shared/services/common.service';
@ -16,7 +16,8 @@ import { CommonService } from '../../../../shared/services/common.service';
import { RTLState } from '../../../../store/rtl.state'; import { RTLState } from '../../../../store/rtl.state';
import { openAlert } from '../../../../store/rtl.actions'; import { openAlert } from '../../../../store/rtl.actions';
import { clnPageSettings, utxos } from '../../../store/cln.selector'; import { clnPageSettings, utxos } from '../../../store/cln.selector';
import { PageSettings, TableSetting } from '../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-on-chain-utxos', selector: 'rtl-cln-on-chain-utxos',
@ -32,6 +33,8 @@ export class CLNOnChainUtxosComponent implements OnInit, AfterViewInit, OnDestro
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
@Input() numDustUTXOs = 0; @Input() numDustUTXOs = 0;
@Input() isDustUTXO = false; @Input() isDustUTXO = false;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'on_chain'; public PAGE_ID = 'on_chain';
public tableSetting: TableSetting = { tableId: 'utxos', recordsPerPage: PAGE_SIZE, sortBy: 'status', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'utxos', recordsPerPage: PAGE_SIZE, sortBy: 'status', sortOrder: SortOrderEnum.DESCENDING };
@ -48,7 +51,7 @@ export class CLNOnChainUtxosComponent implements OnInit, AfterViewInit, OnDestro
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private router: Router) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private router: Router, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -100,6 +103,38 @@ export class CLNOnChainUtxosComponent implements OnInit, AfterViewInit, OnDestro
this.listUTXOs.filter = this.selFilter.trim().toLowerCase(); this.listUTXOs.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.listUTXOs.filterPredicate = (utxo: UTXO, fltr: string) => JSON.stringify(utxo).toLowerCase().includes(fltr);
// this.listUTXOs.filterPredicate = (rowData: UTXO, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
onUTXOClick(selUtxo: UTXO, event: any) { onUTXOClick(selUtxo: UTXO, event: any) {
const reorderedUTXO = [ const reorderedUTXO = [
[{ key: 'txid', value: selUtxo.txid, title: 'Transaction ID', width: 100 }], [{ key: 'txid', value: selUtxo.txid, title: 'Transaction ID', width: 100 }],
@ -125,8 +160,8 @@ export class CLNOnChainUtxosComponent implements OnInit, AfterViewInit, OnDestro
this.listUTXOs.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.listUTXOs.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.listUTXOs.sort = this.sort; this.listUTXOs.sort = this.sort;
this.listUTXOs.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.listUTXOs.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.listUTXOs.filterPredicate = (utxo: UTXO, fltr: string) => JSON.stringify(utxo).toLowerCase().includes(fltr);
this.listUTXOs.paginator = this.paginator; this.listUTXOs.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.listUTXOs); this.logger.info(this.listUTXOs);
} }

@ -1,9 +1,16 @@
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<div [perfectScrollbar] fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container w-100"> <div [perfectScrollbar] fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container w-100">
@ -18,7 +25,7 @@
<ng-container matColumnDef="short_channel_id"> <ng-container matColumnDef="short_channel_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Short Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Short Channel ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.short_channel_id}}</span> <span class="ellipsis-child">{{channel?.short_channel_id}}</span>
</div> </div>
</td> </td>
@ -26,7 +33,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.alias}}</span> <span class="ellipsis-child">{{channel?.alias}}</span>
</div> </div>
</td> </td>
@ -34,7 +41,7 @@
<ng-container matColumnDef="id"> <ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.id}}</span> <span class="ellipsis-child">{{channel?.id}}</span>
</div> </div>
</td> </td>
@ -42,7 +49,7 @@
<ng-container matColumnDef="channel_id"> <ng-container matColumnDef="channel_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.channel_id}}</span> <span class="ellipsis-child">{{channel?.channel_id}}</span>
</div> </div>
</td> </td>
@ -50,7 +57,7 @@
<ng-container matColumnDef="funding_txid"> <ng-container matColumnDef="funding_txid">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Funding Transaction ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Funding Transaction ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.funding_txid}}</span> <span class="ellipsis-child">{{channel?.funding_txid}}</span>
</div> </div>
</td> </td>

@ -9,7 +9,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { Channel, GetInfo, ChannelEdge, Balance } from '../../../../../shared/models/clnModels'; import { Channel, GetInfo, ChannelEdge, Balance } from '../../../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, FEE_RATE_TYPES, APICallStatusEnum, UI_MESSAGES, CLN_DEFAULT_PAGE_SETTINGS, SortOrderEnum } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, FEE_RATE_TYPES, APICallStatusEnum, UI_MESSAGES, CLN_DEFAULT_PAGE_SETTINGS, SortOrderEnum, CLN_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../../../shared/services/logger.service'; import { LoggerService } from '../../../../../shared/services/logger.service';
import { CommonService } from '../../../../../shared/services/common.service'; import { CommonService } from '../../../../../shared/services/common.service';
@ -22,7 +22,8 @@ import { openAlert, openConfirmation } from '../../../../../store/rtl.actions';
import { RTLState } from '../../../../../store/rtl.state'; import { RTLState } from '../../../../../store/rtl.state';
import { channelLookup, closeChannel, updateChannel } from '../../../../store/cln.actions'; import { channelLookup, closeChannel, updateChannel } from '../../../../store/cln.actions';
import { channels, clnPageSettings, nodeInfoAndBalanceAndNumPeers } from '../../../../store/cln.selector'; import { channels, clnPageSettings, nodeInfoAndBalanceAndNumPeers } from '../../../../store/cln.selector';
import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-channel-open-table', selector: 'rtl-cln-channel-open-table',
@ -38,6 +39,8 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faEye = faEye; public faEye = faEye;
public faEyeSlash = faEyeSlash; public faEyeSlash = faEyeSlash;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'open_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'open_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING };
@ -59,7 +62,7 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private clnEffects: CLNEffects, private commonService: CommonService, private router: Router) { constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private clnEffects: CLNEffects, private commonService: CommonService, private router: Router, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
this.selFilter = this.router?.getCurrentNavigation()?.extras?.state?.filter ? this.router?.getCurrentNavigation()?.extras?.state?.filter : ''; this.selFilter = this.router?.getCurrentNavigation()?.extras?.state?.filter ? this.router?.getCurrentNavigation()?.extras?.state?.filter : '';
} }
@ -251,10 +254,6 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
}); });
} }
applyFilter() {
this.channels.filter = this.selFilter.trim().toLowerCase();
}
onChannelClick(selChannel: Channel, event: any) { onChannelClick(selChannel: Channel, event: any) {
this.store.dispatch(openAlert({ this.store.dispatch(openAlert({
payload: { payload: {
@ -267,12 +266,16 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
})); }));
} }
loadChannelsTable(mychannels) { applyFilter() {
// mychannels.sort((a, b) => ((a.active === b.active) ? 0 : ((b.active) ? 1 : -1))); this.channels.filter = this.selFilter.trim().toLowerCase();
this.channels = new MatTableDataSource<Channel>([...mychannels]); }
this.channels.sort = this.sort;
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); getLabel(column: string) {
this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.channels.filterPredicate = (channel: Channel, fltr: string) => { this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = ((channel.connected) ? 'connected' : 'disconnected') + (channel.channel_id ? channel.channel_id.toLowerCase() : '') + const newChannel = ((channel.connected) ? 'connected' : 'disconnected') + (channel.channel_id ? channel.channel_id.toLowerCase() : '') +
(channel.short_channel_id ? channel.short_channel_id.toLowerCase() : '') + (channel.id ? channel.id.toLowerCase() : '') + (channel.alias ? channel.alias.toLowerCase() : '') + (channel.short_channel_id ? channel.short_channel_id.toLowerCase() : '') + (channel.id ? channel.id.toLowerCase() : '') + (channel.alias ? channel.alias.toLowerCase() : '') +
@ -282,7 +285,38 @@ export class CLNChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
(channel.our_channel_reserve_satoshis ? channel.our_channel_reserve_satoshis : '') + (channel.spendable_msatoshi ? channel.spendable_msatoshi : ''); (channel.our_channel_reserve_satoshis ? channel.our_channel_reserve_satoshis : '') + (channel.spendable_msatoshi ? channel.spendable_msatoshi : '');
return newChannel.includes(fltr); return newChannel.includes(fltr);
}; };
// this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadChannelsTable(mychannels) {
this.channels = new MatTableDataSource<Channel>([...mychannels]);
this.channels.sort = this.sort;
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.channels.paginator = this.paginator; this.channels.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.channels); this.logger.info(this.channels);
} }

@ -1,9 +1,16 @@
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<div [perfectScrollbar] fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container w-100"> <div [perfectScrollbar] fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container w-100">
@ -18,7 +25,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.alias}}</span> <span class="ellipsis-child">{{channel?.alias}}</span>
</div> </div>
</td> </td>
@ -26,7 +33,7 @@
<ng-container matColumnDef="id"> <ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.id}}</span> <span class="ellipsis-child">{{channel?.id}}</span>
</div> </div>
</td> </td>
@ -34,7 +41,7 @@
<ng-container matColumnDef="channel_id"> <ng-container matColumnDef="channel_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.channel_id}}</span> <span class="ellipsis-child">{{channel?.channel_id}}</span>
</div> </div>
</td> </td>
@ -42,7 +49,7 @@
<ng-container matColumnDef="funding_txid"> <ng-container matColumnDef="funding_txid">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Funding Transaction ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Funding Transaction ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.funding_txid}}</span> <span class="ellipsis-child">{{channel?.funding_txid}}</span>
</div> </div>
</td> </td>
@ -53,7 +60,7 @@
</ng-container> </ng-container>
<ng-container matColumnDef="state"> <ng-container matColumnDef="state">
<th mat-header-cell *matHeaderCellDef mat-sort-header>State</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>State</th>
<td mat-cell *matCellDef="let channel" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">{{CLNChannelPendingState[channel?.state]}}</td> <td mat-cell *matCellDef="let channel" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">{{CLNChannelPendingState[channel?.state]}}</td>
</ng-container> </ng-container>
<ng-container matColumnDef="our_channel_reserve_satoshis"> <ng-container matColumnDef="our_channel_reserve_satoshis">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Local Reserve (Sats)</th> <th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Local Reserve (Sats)</th>

@ -8,7 +8,7 @@ import { MatTableDataSource } from '@angular/material/table';
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { GetInfo, Channel, Balance } from '../../../../../shared/models/clnModels'; import { GetInfo, Channel, Balance } from '../../../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, FEE_RATE_TYPES, AlertTypeEnum, APICallStatusEnum, CLNChannelPendingState, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, FEE_RATE_TYPES, AlertTypeEnum, APICallStatusEnum, CLNChannelPendingState, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../../../shared/services/logger.service'; import { LoggerService } from '../../../../../shared/services/logger.service';
import { CommonService } from '../../../../../shared/services/common.service'; import { CommonService } from '../../../../../shared/services/common.service';
@ -20,7 +20,8 @@ import { openAlert, openConfirmation } from '../../../../../store/rtl.actions';
import { RTLState } from '../../../../../store/rtl.state'; import { RTLState } from '../../../../../store/rtl.state';
import { closeChannel } from '../../../../store/cln.actions'; import { closeChannel } from '../../../../store/cln.actions';
import { channels, clnPageSettings, nodeInfoAndBalanceAndNumPeers } from '../../../../store/cln.selector'; import { channels, clnPageSettings, nodeInfoAndBalanceAndNumPeers } from '../../../../store/cln.selector';
import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-channel-pending-table', selector: 'rtl-cln-channel-pending-table',
@ -36,6 +37,8 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faEye = faEye; public faEye = faEye;
public faEyeSlash = faEyeSlash; public faEyeSlash = faEyeSlash;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'pending_inactive_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'pending_inactive_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING };
@ -59,7 +62,7 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService) { constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -115,10 +118,6 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
} }
} }
applyFilter() {
this.channels.filter = this.selFilter.trim().toLowerCase();
}
onBumpFee(selChannel: Channel) { onBumpFee(selChannel: Channel) {
this.store.dispatch(openAlert({ this.store.dispatch(openAlert({
payload: { payload: {
@ -165,9 +164,16 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
}); });
} }
loadChannelsTable(mychannels) { applyFilter() {
// mychannels.sort((a, b) => ((a.active === b.active) ? 0 : ((b.active) ? 1 : -1))); this.channels.filter = this.selFilter.trim().toLowerCase();
this.channels = new MatTableDataSource<Channel>([...mychannels]); }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.channels.filterPredicate = (channel: Channel, fltr: string) => { this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = ((channel.connected) ? 'connected' : 'disconnected') + (channel.channel_id ? channel.channel_id.toLowerCase() : '') + const newChannel = ((channel.connected) ? 'connected' : 'disconnected') + (channel.channel_id ? channel.channel_id.toLowerCase() : '') +
(channel.short_channel_id ? channel.short_channel_id.toLowerCase() : '') + (channel.id ? channel.id.toLowerCase() : '') + (channel.alias ? channel.alias.toLowerCase() : '') + (channel.short_channel_id ? channel.short_channel_id.toLowerCase() : '') + (channel.id ? channel.id.toLowerCase() : '') + (channel.alias ? channel.alias.toLowerCase() : '') +
@ -177,6 +183,33 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
(channel.our_channel_reserve_satoshis ? channel.our_channel_reserve_satoshis : '') + (channel.spendable_msatoshi ? channel.spendable_msatoshi : ''); (channel.our_channel_reserve_satoshis ? channel.our_channel_reserve_satoshis : '') + (channel.spendable_msatoshi ? channel.spendable_msatoshi : '');
return newChannel.includes(fltr); return newChannel.includes(fltr);
}; };
// this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadChannelsTable(mychannels) {
this.channels = new MatTableDataSource<Channel>([...mychannels]);
this.channels.sort = this.sort; this.channels.sort = this.sort;
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => { this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => {
switch (sortHeaderId) { switch (sortHeaderId) {
@ -189,6 +222,8 @@ export class CLNChannelPendingTableComponent implements OnInit, AfterViewInit, O
}; };
this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.channels.paginator = this.paginator; this.channels.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter();
this.logger.info(this.channels); this.logger.info(this.channels);
} }

@ -8,11 +8,16 @@
<fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Connected Peers</span> <span class="page-title">Connected Peers</span>
</div> </div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<div fxLayout="row" fxLayoutAlign="start start"> <mat-form-field fxFlex="49">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
</div> <mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-form-field> </mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -27,7 +32,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
<td mat-cell *matCellDef="let peer"> <td mat-cell *matCellDef="let peer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{peer?.alias}}</span> <span class="ellipsis-child">{{peer?.alias}}</span>
</div> </div>
</td> </td>
@ -35,7 +40,7 @@
<ng-container matColumnDef="id"> <ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let peer"> <td mat-cell *matCellDef="let peer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{peer?.id}}</span> <span class="ellipsis-child">{{peer?.id}}</span>
</div> </div>
</td> </td>
@ -43,7 +48,7 @@
<ng-container matColumnDef="netaddr"> <ng-container matColumnDef="netaddr">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Network Address</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Network Address</th>
<td mat-cell *matCellDef="let peer"> <td mat-cell *matCellDef="let peer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child" *ngFor="let addr of peer?.netaddr; last as isLast">{{addr}}<span *ngIf="!isLast">,<br></span></span> <span class="ellipsis-child" *ngFor="let addr of peer?.netaddr; last as isLast">{{addr}}<span *ngIf="!isLast">,<br></span></span>
</div> </div>
</td> </td>

@ -10,7 +10,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { Peer, GetInfo, Balance } from '../../../shared/models/clnModels'; import { Peer, GetInfo, Balance } from '../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNActions, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNActions, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -22,7 +22,8 @@ import { RTLState } from '../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../store/rtl.actions';
import { detachPeer } from '../../store/cln.actions'; import { detachPeer } from '../../store/cln.actions';
import { clnPageSettings, nodeInfoAndBalance, peers } from '../../store/cln.selector'; import { clnPageSettings, nodeInfoAndBalance, peers } from '../../store/cln.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-peers', selector: 'rtl-cln-peers',
@ -37,6 +38,8 @@ export class CLNPeersComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faUsers = faUsers; public faUsers = faUsers;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'peers', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'peers', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING };
@ -57,7 +60,7 @@ export class CLNPeersComponent implements OnInit, AfterViewInit, OnDestroy {
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private actions: Actions, private commonService: CommonService) { constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private actions: Actions, private commonService: CommonService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -189,6 +192,38 @@ export class CLNPeersComponent implements OnInit, AfterViewInit, OnDestroy {
this.peers.filter = this.selFilter.trim().toLowerCase(); this.peers.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.peers.filterPredicate = (peer: Peer, fltr: string) => JSON.stringify(peer).toLowerCase().includes(fltr);
// this.peers.filterPredicate = (rowData: Peer, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadPeersTable(peersArr: Peer[]) { loadPeersTable(peersArr: Peer[]) {
this.peers = new MatTableDataSource<Peer>([...peersArr]); this.peers = new MatTableDataSource<Peer>([...peersArr]);
this.peers.sortingDataAccessor = (data: any, sortHeaderId: string) => { this.peers.sortingDataAccessor = (data: any, sortHeaderId: string) => {
@ -206,8 +241,8 @@ export class CLNPeersComponent implements OnInit, AfterViewInit, OnDestroy {
}; };
this.peers.sort = this.sort; this.peers.sort = this.sort;
this.peers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.peers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.peers.filterPredicate = (peer: Peer, fltr: string) => JSON.stringify(peer).toLowerCase().includes(fltr);
this.peers.paginator = this.paginator; this.peers.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
} }

@ -42,7 +42,7 @@
</ngx-charts-bar-vertical> </ngx-charts-bar-vertical>
</div> </div>
<div class="mt-1"> <div class="mt-1">
<rtl-cln-forwarding-history *ngIf="filteredEventsBySelectedPeriod && filteredEventsBySelectedPeriod.length > 0" [pageId]="'reports'" [tableId]="'routing'" [eventsData]="filteredEventsBySelectedPeriod" [filterValue]="eventFilterValue"></rtl-cln-forwarding-history> <rtl-cln-forwarding-history *ngIf="filteredEventsBySelectedPeriod && filteredEventsBySelectedPeriod.length > 0" [pageId]="'reports'" [tableId]="'routing'" [eventsData]="filteredEventsBySelectedPeriod" [selFilter]="eventFilterValue"></rtl-cln-forwarding-history>
</div> </div>
</div> </div>
</div> </div>

@ -35,7 +35,7 @@
</ngx-charts-bar-vertical-2d> </ngx-charts-bar-vertical-2d>
</div> </div>
<div class="mt-1"> <div class="mt-1">
<rtl-transactions-report-table *ngIf="transactionsNonZeroReportData.length > 0" [displayedColumns]="displayedColumns" [tableSetting]="tableSetting" [dataList]="transactionsNonZeroReportData" [dataRange]="reportPeriod" [filterValue]="transactionFilterValue"></rtl-transactions-report-table> <rtl-transactions-report-table *ngIf="transactionsNonZeroReportData.length > 0" [displayedColumns]="displayedColumns" [tableSetting]="tableSetting" [dataList]="transactionsNonZeroReportData" [dataRange]="reportPeriod" [selFilter]="transactionFilterValue"></rtl-transactions-report-table>
</div> </div>
</div> </div>
</div> </div>

@ -7,9 +7,16 @@
</div> </div>
<div fxFlex="100"> <div fxFlex="100">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
</div> </div>
<div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
@ -30,7 +37,7 @@
<ng-container matColumnDef="in_channel_alias"> <ng-container matColumnDef="in_channel_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.in_channel_alias}}</span> <span class="ellipsis-child">{{fhEvent?.in_channel_alias}}</span>
</span> </span>
</td> </td>
@ -42,7 +49,7 @@
<ng-container matColumnDef="out_channel_alias"> <ng-container matColumnDef="out_channel_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.out_channel_alias}}</span> <span class="ellipsis-child">{{fhEvent?.out_channel_alias}}</span>
</span> </span>
</td> </td>

@ -9,7 +9,7 @@ import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { ForwardingEvent, ListForwards } from '../../../shared/models/clnModels'; import { ForwardingEvent, ListForwards } from '../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -19,7 +19,8 @@ import { openAlert } from '../../../store/rtl.actions';
import { getForwardingHistory } from '../../store/cln.actions'; import { getForwardingHistory } from '../../store/cln.actions';
import { clnPageSettings, failedForwardingHistory } from '../../store/cln.selector'; import { clnPageSettings, failedForwardingHistory } from '../../store/cln.selector';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-failed-history', selector: 'rtl-cln-failed-history',
@ -33,6 +34,8 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'routing'; public PAGE_ID = 'routing';
public tableSetting: TableSetting = { tableId: 'failed', recordsPerPage: PAGE_SIZE, sortBy: 'received_time', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'failed', recordsPerPage: PAGE_SIZE, sortBy: 'received_time', sortOrder: SortOrderEnum.DESCENDING };
@ -51,7 +54,7 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private router: Router) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private router: Router, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -123,11 +126,16 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
})); }));
} }
loadFailedEventsTable(forwardingEvents: ForwardingEvent[]) { applyFilter() {
this.failedForwardingEvents = new MatTableDataSource<ForwardingEvent>([...forwardingEvents]); this.failedForwardingEvents.filter = this.selFilter.trim().toLowerCase();
this.failedForwardingEvents.sort = this.sort; }
this.failedForwardingEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.failedForwardingEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.failedForwardingEvents.filterPredicate = (event: ForwardingEvent, fltr: string) => { this.failedForwardingEvents.filterPredicate = (event: ForwardingEvent, fltr: string) => {
const newEvent = const newEvent =
(event.received_time ? this.datePipe.transform(new Date(event.received_time * 1000), 'dd/MMM/YYYY HH:mm')!.toLowerCase() : '') + (event.received_time ? this.datePipe.transform(new Date(event.received_time * 1000), 'dd/MMM/YYYY HH:mm')!.toLowerCase() : '') +
@ -138,7 +146,38 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
(event.in_msatoshi ? (event.in_msatoshi / 1000) : '') + (event.out_msatoshi ? (event.out_msatoshi / 1000) : '') + (event.fee ? event.fee : ''); (event.in_msatoshi ? (event.in_msatoshi / 1000) : '') + (event.out_msatoshi ? (event.out_msatoshi / 1000) : '') + (event.fee ? event.fee : '');
return newEvent?.includes(fltr) || false; return newEvent?.includes(fltr) || false;
}; };
// this.failedForwardingEvents.filterPredicate = (rowData: ForwardingEvent, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadFailedEventsTable(forwardingEvents: ForwardingEvent[]) {
this.failedForwardingEvents = new MatTableDataSource<ForwardingEvent>([...forwardingEvents]);
this.failedForwardingEvents.sort = this.sort;
this.failedForwardingEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.failedForwardingEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.failedForwardingEvents.paginator = this.paginator; this.failedForwardingEvents.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.failedForwardingEvents); this.logger.info(this.failedForwardingEvents);
} }
@ -149,10 +188,6 @@ export class CLNFailedTransactionsComponent implements OnInit, AfterViewInit, On
} }
} }
applyFilter() {
this.failedForwardingEvents.filter = this.selFilter.trim().toLowerCase();
}
ngOnDestroy() { ngOnDestroy() {
this.unSubs.forEach((completeSub) => { this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null); completeSub.next(<any>null);

@ -2,9 +2,16 @@
<div class="p-2 error-border my-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div> <div class="p-2 error-border my-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput [(ngModel)]="filterValue" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -24,7 +31,7 @@
<ng-container matColumnDef="in_channel_alias"> <ng-container matColumnDef="in_channel_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.in_channel_alias}}</span> <span class="ellipsis-child">{{fhEvent?.in_channel_alias}}</span>
</div> </div>
</td> </td>
@ -36,7 +43,7 @@
<ng-container matColumnDef="out_channel_alias"> <ng-container matColumnDef="out_channel_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.out_channel_alias}}</span> <span class="ellipsis-child">{{fhEvent?.out_channel_alias}}</span>
</div> </div>
</td> </td>
@ -44,7 +51,7 @@
<ng-container matColumnDef="payment_hash"> <ng-container matColumnDef="payment_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.payment_hash}}</span> <span class="ellipsis-child">{{fhEvent?.payment_hash}}</span>
</div> </div>
</td> </td>

@ -9,7 +9,7 @@ import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { ForwardingEvent, ListForwards } from '../../../shared/models/clnModels'; import { ForwardingEvent, ListForwards } from '../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -18,7 +18,8 @@ import { RTLState } from '../../../store/rtl.state';
import { openAlert } from '../../../store/rtl.actions'; import { openAlert } from '../../../store/rtl.actions';
import { clnPageSettings, forwardingHistory } from '../../store/cln.selector'; import { clnPageSettings, forwardingHistory } from '../../store/cln.selector';
import { getForwardingHistory } from '../../store/cln.actions'; import { getForwardingHistory } from '../../store/cln.actions';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-forwarding-history', selector: 'rtl-cln-forwarding-history',
@ -35,7 +36,9 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
@Input() pageId = 'routing'; @Input() pageId = 'routing';
@Input() tableId = 'forwarding_history'; @Input() tableId = 'forwarding_history';
@Input() eventsData = []; @Input() eventsData = [];
@Input() filterValue = ''; @Input() selFilter = '';
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public tableSetting: TableSetting = { tableId: 'forwarding_history', recordsPerPage: PAGE_SIZE, sortBy: 'received_time', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'forwarding_history', recordsPerPage: PAGE_SIZE, sortBy: 'received_time', sortOrder: SortOrderEnum.DESCENDING };
public successfulEvents: ForwardingEvent[] = []; public successfulEvents: ForwardingEvent[] = [];
@ -51,7 +54,7 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private router: Router) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private router: Router, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -117,7 +120,7 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
this.loadForwardingEventsTable(this.successfulEvents); this.loadForwardingEventsTable(this.successfulEvents);
} }
} }
if (changes.filterValue && !changes.filterValue.firstChange) { if (changes.selFilter && !changes.selFilter.firstChange) {
this.applyFilter(); this.applyFilter();
} }
} }
@ -145,11 +148,18 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
})); }));
} }
loadForwardingEventsTable(forwardingEvents: ForwardingEvent[]) { applyFilter() {
this.forwardingHistoryEvents = new MatTableDataSource<ForwardingEvent>([...forwardingEvents]); if (this.forwardingHistoryEvents) {
this.forwardingHistoryEvents.sort = this.sort; this.forwardingHistoryEvents.filter = this.selFilter.trim().toLowerCase();
this.forwardingHistoryEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); }
this.forwardingHistoryEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.pageId][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.forwardingHistoryEvents.filterPredicate = (event: ForwardingEvent, fltr: string) => { this.forwardingHistoryEvents.filterPredicate = (event: ForwardingEvent, fltr: string) => {
const newEvent = (event.received_time ? this.datePipe.transform(new Date(event.received_time * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() + ' ' : '') + const newEvent = (event.received_time ? this.datePipe.transform(new Date(event.received_time * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() + ' ' : '') +
(event.resolved_time ? this.datePipe.transform(new Date(event.resolved_time * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() + ' ' : '') + (event.resolved_time ? this.datePipe.transform(new Date(event.resolved_time * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() + ' ' : '') +
@ -158,7 +168,38 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
(event.in_msatoshi ? (event.in_msatoshi / 1000) + ' ' : '') + (event.out_msatoshi ? (event.out_msatoshi / 1000) + ' ' : '') + (event.fee ? event.fee + ' ' : ''); (event.in_msatoshi ? (event.in_msatoshi / 1000) + ' ' : '') + (event.out_msatoshi ? (event.out_msatoshi / 1000) + ' ' : '') + (event.fee ? event.fee + ' ' : '');
return newEvent.includes(fltr); return newEvent.includes(fltr);
}; };
// this.forwardingHistoryEvents.filterPredicate = (rowData: ForwardingEvent, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadForwardingEventsTable(forwardingEvents: ForwardingEvent[]) {
this.forwardingHistoryEvents = new MatTableDataSource<ForwardingEvent>([...forwardingEvents]);
this.forwardingHistoryEvents.sort = this.sort;
this.forwardingHistoryEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.forwardingHistoryEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.forwardingHistoryEvents.paginator = this.paginator; this.forwardingHistoryEvents.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.forwardingHistoryEvents); this.logger.info(this.forwardingHistoryEvents);
} }
@ -169,12 +210,6 @@ export class CLNForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
} }
} }
applyFilter() {
if (this.forwardingHistoryEvents) {
this.forwardingHistoryEvents.filter = this.filterValue.trim().toLowerCase();
}
}
ngOnDestroy() { ngOnDestroy() {
this.unSubs.forEach((completeSub) => { this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null); completeSub.next(<any>null);

@ -7,9 +7,16 @@
</div> </div>
<div fxFlex="100"> <div fxFlex="100">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
</div> </div>
<div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
@ -26,7 +33,7 @@
<ng-container matColumnDef="in_channel_alias"> <ng-container matColumnDef="in_channel_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.in_channel_alias}}</span> <span class="ellipsis-child">{{fhEvent?.in_channel_alias}}</span>
</span> </span>
</td> </td>
@ -38,7 +45,7 @@
<ng-container matColumnDef="out_channel_alias"> <ng-container matColumnDef="out_channel_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.out_channel_alias}}</span> <span class="ellipsis-child">{{fhEvent?.out_channel_alias}}</span>
</span> </span>
</td> </td>

@ -9,7 +9,7 @@ import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { ListForwards, LocalFailedEvent } from '../../../shared/models/clnModels'; import { ListForwards, LocalFailedEvent } from '../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNFailReason, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, CLNFailReason, CLNForwardingEventsStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -19,7 +19,8 @@ import { openAlert } from '../../../store/rtl.actions';
import { getForwardingHistory } from '../../store/cln.actions'; import { getForwardingHistory } from '../../store/cln.actions';
import { clnPageSettings, localFailedForwardingHistory } from '../../store/cln.selector'; import { clnPageSettings, localFailedForwardingHistory } from '../../store/cln.selector';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-local-failed-history', selector: 'rtl-cln-local-failed-history',
@ -34,6 +35,8 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faExclamationTriangle = faExclamationTriangle; public faExclamationTriangle = faExclamationTriangle;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'routing'; public PAGE_ID = 'routing';
public tableSetting: TableSetting = { tableId: 'local_failed', recordsPerPage: PAGE_SIZE, sortBy: 'received_time', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'local_failed', recordsPerPage: PAGE_SIZE, sortBy: 'received_time', sortOrder: SortOrderEnum.DESCENDING };
@ -52,7 +55,7 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private router: Router) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private router: Router, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -118,6 +121,48 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
})); }));
} }
applyFilter() {
this.failedLocalForwardingEvents.filter = this.selFilter.trim().toLowerCase();
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.failedLocalForwardingEvents.filterPredicate = (event: LocalFailedEvent, fltr: string) => {
const newEvent = (event.received_time ? this.datePipe.transform(new Date(event.received_time * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') +
(event.in_channel_alias ? event.in_channel_alias.toLowerCase() : '') +
((event.failreason && this.CLNFailReason[event.failreason]) ? this.CLNFailReason[event.failreason].toLowerCase() : '') +
(event.in_msatoshi ? (event.in_msatoshi / 1000) : '');
return newEvent?.includes(fltr) || false;
};
// this.failedLocalForwardingEvents.filterPredicate = (rowData: LocalFailedEvent, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadLocalfailedLocalEventsTable(forwardingEvents: LocalFailedEvent[]) { loadLocalfailedLocalEventsTable(forwardingEvents: LocalFailedEvent[]) {
this.failedLocalForwardingEvents = new MatTableDataSource<LocalFailedEvent>([...forwardingEvents]); this.failedLocalForwardingEvents = new MatTableDataSource<LocalFailedEvent>([...forwardingEvents]);
this.failedLocalForwardingEvents.sort = this.sort; this.failedLocalForwardingEvents.sort = this.sort;
@ -131,14 +176,8 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
} }
}; };
this.failedLocalForwardingEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.failedLocalForwardingEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.failedLocalForwardingEvents.filterPredicate = (event: LocalFailedEvent, fltr: string) => {
const newEvent = (event.received_time ? this.datePipe.transform(new Date(event.received_time * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') +
(event.in_channel_alias ? event.in_channel_alias.toLowerCase() : '') +
((event.failreason && this.CLNFailReason[event.failreason]) ? this.CLNFailReason[event.failreason].toLowerCase() : '') +
(event.in_msatoshi ? (event.in_msatoshi / 1000) : '');
return newEvent?.includes(fltr) || false;
};
this.failedLocalForwardingEvents.paginator = this.paginator; this.failedLocalForwardingEvents.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.failedLocalForwardingEvents); this.logger.info(this.failedLocalForwardingEvents);
} }
@ -149,10 +188,6 @@ export class CLNLocalFailedTransactionsComponent implements OnInit, AfterViewIni
} }
} }
applyFilter() {
this.failedLocalForwardingEvents.filter = this.selFilter.trim().toLowerCase();
}
ngOnDestroy() { ngOnDestroy() {
this.unSubs.forEach((completeSub) => { this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null); completeSub.next(<any>null);

@ -4,17 +4,24 @@
<div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch"> <div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}">
<div fxFlex="70">Incoming</div> <div fxFlex="70">Incoming</div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyIncomingFilter()" [(ngModel)]="filterIn" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterByIn" (selectionChange)="selFilterIn=''; applyIncomingFilter()" name="filterByIn">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilterIn" (input)="applyIncomingFilter()" (keyup)="applyIncomingFilter()" name="filterin" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableIn [dataSource]="RoutingPeersIncoming" matSort class="overflow-auto incoming-table"> <table mat-table #tableIn [dataSource]="routingPeersIncoming" matSort class="overflow-auto incoming-table">
<ng-container matColumnDef="channel_id"> <ng-container matColumnDef="channel_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer.channel_id}}</span> <span class="ellipsis-child">{{rPeer.channel_id}}</span>
</div> </div>
</td> </td>
@ -22,7 +29,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer.alias}}</span> <span class="ellipsis-child">{{rPeer.alias}}</span>
</div> </div>
</td> </td>
@ -42,12 +49,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="no_incoming_event"> <ng-container matColumnDef="no_incoming_event">
<td mat-footer-cell *matFooterCellDef colspan="4"> <td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.COMPLETED">No incoming routing peer available.</p> <p *ngIf="(!routingPeersIncoming?.data || routingPeersIncoming?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.COMPLETED">No incoming routing peer available.</p>
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.INITIATED">Getting incoming routing peers...</p> <p *ngIf="(!routingPeersIncoming?.data || routingPeersIncoming?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.INITIATED">Getting incoming routing peers...</p>
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p> <p *ngIf="(!routingPeersIncoming?.data || routingPeersIncoming?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td> </td>
</ng-container> </ng-container>
<tr mat-footer-row *matFooterRowDef="['no_incoming_event']" [ngClass]="{'display-none': RoutingPeersIncoming?.data && RoutingPeersIncoming?.data?.length>0}"></tr> <tr mat-footer-row *matFooterRowDef="['no_incoming_event']" [ngClass]="{'display-none': routingPeersIncoming?.data && routingPeersIncoming?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
@ -57,17 +64,24 @@
<div fxLayout="column" fxFlex="49" fxLayoutAlign="end stretch"> <div fxLayout="column" fxFlex="49" fxLayoutAlign="end stretch">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}">
<div fxFlex="70">Outgoing</div> <div fxFlex="70">Outgoing</div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyOutgoingFilter()" [(ngModel)]="filterOut" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterByOut" (selectionChange)="selFilterOut=''; applyOutgoingFilter()" name="filterByOut">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilterOut" (input)="applyOutgoingFilter()" (keyup)="applyOutgoingFilter()" name="filterout" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableOut [dataSource]="RoutingPeersOutgoing" matSort class="overflow-auto outgoing-table"> <table mat-table #tableOut [dataSource]="routingPeersOutgoing" matSort class="overflow-auto outgoing-table">
<ng-container matColumnDef="channel_id"> <ng-container matColumnDef="channel_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer.channel_id}}</span> <span class="ellipsis-child">{{rPeer.channel_id}}</span>
</div> </div>
</td> </td>
@ -75,7 +89,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer.alias}}</span> <span class="ellipsis-child">{{rPeer.alias}}</span>
</div> </div>
</td> </td>
@ -95,12 +109,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="no_outgoing_event"> <ng-container matColumnDef="no_outgoing_event">
<td mat-footer-cell *matFooterCellDef colspan="4"> <td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.COMPLETED">No outgoing routing peer available.</p> <p *ngIf="(!routingPeersOutgoing?.data || routingPeersOutgoing?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.COMPLETED">No outgoing routing peer available.</p>
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.INITIATED">Getting outgoing routing peers...</p> <p *ngIf="(!routingPeersOutgoing?.data || routingPeersOutgoing?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.INITIATED">Getting outgoing routing peers...</p>
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p> <p *ngIf="(!routingPeersOutgoing?.data || routingPeersOutgoing?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td> </td>
</ng-container> </ng-container>
<tr mat-footer-row *matFooterRowDef="['no_outgoing_event']" [ngClass]="{'display-none': RoutingPeersOutgoing?.data && RoutingPeersOutgoing?.data?.length>0}"></tr> <tr mat-footer-row *matFooterRowDef="['no_outgoing_event']" [ngClass]="{'display-none': routingPeersOutgoing?.data && routingPeersOutgoing?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>

@ -6,7 +6,7 @@ import { Store } from '@ngrx/store';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLNForwardingEventsStatusEnum } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLNForwardingEventsStatusEnum, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ForwardingEvent, ListForwards, RoutingPeer } from '../../../shared/models/clnModels'; import { ForwardingEvent, ListForwards, RoutingPeer } from '../../../shared/models/clnModels';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
@ -14,8 +14,9 @@ import { CommonService } from '../../../shared/services/common.service';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { clnPageSettings, forwardingHistory } from '../../store/cln.selector'; import { clnPageSettings, forwardingHistory } from '../../store/cln.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { getForwardingHistory } from '../../store/cln.actions'; import { getForwardingHistory } from '../../store/cln.actions';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-routing-peers', selector: 'rtl-cln-routing-peers',
@ -32,14 +33,17 @@ export class CLNRoutingPeersComponent implements OnInit, OnChanges, AfterViewIni
@ViewChild('paginatorIn', { static: false }) paginatorIn: MatPaginator | undefined; @ViewChild('paginatorIn', { static: false }) paginatorIn: MatPaginator | undefined;
@ViewChild('paginatorOut', { static: false }) paginatorOut: MatPaginator | undefined; @ViewChild('paginatorOut', { static: false }) paginatorOut: MatPaginator | undefined;
@Input() eventsData = []; @Input() eventsData = [];
@Input() filterValue = ''; @Input() selFilter = '';
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterByIn = 'all';
public selFilterByOut = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'routing'; public PAGE_ID = 'routing';
public tableSetting: TableSetting = { tableId: 'routing_peers', recordsPerPage: PAGE_SIZE, sortBy: 'total_fee', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'routing_peers', recordsPerPage: PAGE_SIZE, sortBy: 'total_fee', sortOrder: SortOrderEnum.DESCENDING };
public successfulEvents: ForwardingEvent[] = []; public successfulEvents: ForwardingEvent[] = [];
public displayedColumns: any[] = []; public displayedColumns: any[] = [];
public RoutingPeersIncoming: any = []; public routingPeersIncoming: any = [];
public RoutingPeersOutgoing: any = []; public routingPeersOutgoing: any = [];
public pageSize = PAGE_SIZE; public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS; public pageSizeOptions = PAGE_SIZE_OPTIONS;
public screenSize = ''; public screenSize = '';
@ -51,7 +55,7 @@ export class CLNRoutingPeersComponent implements OnInit, OnChanges, AfterViewIni
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -112,30 +116,70 @@ export class CLNRoutingPeersComponent implements OnInit, OnChanges, AfterViewIni
} }
} }
applyIncomingFilter() {
this.routingPeersIncoming.filter = this.filterIn.toLowerCase();
}
applyOutgoingFilter() {
this.routingPeersOutgoing.filter = this.filterOut.toLowerCase();
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.routingPeersIncoming.filterPredicate = (rpIn: RoutingPeer, fltr: string) => JSON.stringify(rpIn).toLowerCase().includes(fltr);
this.routingPeersOutgoing.filterPredicate = (rpOut: RoutingPeer, fltr: string) => JSON.stringify(rpOut).toLowerCase().includes(fltr);
// this.routingPeersIncoming.filterPredicate = (rowData: RoutingPeer, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadRoutingPeersTable(events: ForwardingEvent[]) { loadRoutingPeersTable(events: ForwardingEvent[]) {
if (events.length > 0) { if (events.length > 0) {
const results = this.groupRoutingPeers(events); const results = this.groupRoutingPeers(events);
this.RoutingPeersIncoming = new MatTableDataSource<RoutingPeer[]>(results[0]); this.routingPeersIncoming = new MatTableDataSource<RoutingPeer[]>(results[0]);
this.RoutingPeersIncoming.sort = this.sortIn; this.routingPeersIncoming.sort = this.sortIn;
this.RoutingPeersIncoming.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.routingPeersIncoming.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.RoutingPeersIncoming.filterPredicate = (rpIn: RoutingPeer, fltr: string) => JSON.stringify(rpIn).toLowerCase().includes(fltr); this.routingPeersIncoming.paginator = this.paginatorIn;
this.RoutingPeersIncoming.paginator = this.paginatorIn; this.logger.info(this.routingPeersIncoming);
this.logger.info(this.RoutingPeersIncoming); this.routingPeersOutgoing = new MatTableDataSource<RoutingPeer[]>(results[1]);
this.RoutingPeersOutgoing = new MatTableDataSource<RoutingPeer[]>(results[1]); this.routingPeersOutgoing.sort = this.sortOut;
this.RoutingPeersOutgoing.sort = this.sortOut; this.routingPeersOutgoing.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.RoutingPeersOutgoing.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.routingPeersOutgoing.paginator = this.paginatorOut;
this.RoutingPeersOutgoing.filterPredicate = (rpOut: RoutingPeer, fltr: string) => JSON.stringify(rpOut).toLowerCase().includes(fltr); this.logger.info(this.routingPeersOutgoing);
this.RoutingPeersOutgoing.paginator = this.paginatorOut;
this.logger.info(this.RoutingPeersOutgoing);
} else { } else {
// To reset table after other Forwarding history calls // To reset table after other Forwarding history calls
this.RoutingPeersIncoming = new MatTableDataSource<RoutingPeer>([]); this.routingPeersIncoming = new MatTableDataSource<RoutingPeer>([]);
this.RoutingPeersOutgoing = new MatTableDataSource<RoutingPeer>([]); this.routingPeersOutgoing = new MatTableDataSource<RoutingPeer>([]);
} }
this.setFilterPredicate();
this.applyIncomingFilter(); this.applyIncomingFilter();
this.applyOutgoingFilter(); this.applyOutgoingFilter();
this.logger.info(this.RoutingPeersIncoming); this.logger.info(this.routingPeersIncoming);
this.logger.info(this.RoutingPeersOutgoing); this.logger.info(this.routingPeersOutgoing);
} }
groupRoutingPeers(forwardingEvents: ForwardingEvent[]) { groupRoutingPeers(forwardingEvents: ForwardingEvent[]) {
@ -162,14 +206,6 @@ export class CLNRoutingPeersComponent implements OnInit, OnChanges, AfterViewIni
return [this.commonService.sortDescByKey(incomingResults, 'total_fee'), this.commonService.sortDescByKey(outgoingResults, 'total_fee')]; return [this.commonService.sortDescByKey(incomingResults, 'total_fee'), this.commonService.sortDescByKey(outgoingResults, 'total_fee')];
} }
applyIncomingFilter() {
this.RoutingPeersIncoming.filter = this.filterIn.toLowerCase();
}
applyOutgoingFilter() {
this.RoutingPeersOutgoing.filter = this.filterOut.toLowerCase();
}
ngOnDestroy() { ngOnDestroy() {
this.unSubs.forEach((completeSub) => { this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null); completeSub.next(<any>null);

@ -23,9 +23,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Invoices History</span> <span class="page-title">Invoices History</span>
</div> </div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -55,7 +62,7 @@
<ng-container matColumnDef="description"> <ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.description}}</span> <span class="ellipsis-child">{{invoice?.description}}</span>
</div> </div>
</td> </td>
@ -63,7 +70,7 @@
<ng-container matColumnDef="label"> <ng-container matColumnDef="label">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Label</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Label</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.label}}</span> <span class="ellipsis-child">{{invoice?.label}}</span>
</div> </div>
</td> </td>
@ -71,7 +78,7 @@
<ng-container matColumnDef="payment_hash"> <ng-container matColumnDef="payment_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.payment_hash}}</span> <span class="ellipsis-child">{{invoice?.payment_hash}}</span>
</div> </div>
</td> </td>
@ -79,7 +86,7 @@
<ng-container matColumnDef="bolt11"> <ng-container matColumnDef="bolt11">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.bolt11}}</span> <span class="ellipsis-child">{{invoice?.bolt11}}</span>
</div> </div>
</td> </td>

@ -9,7 +9,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, UI_MESSAGES, CLNActions, CLN_DEFAULT_PAGE_SETTINGS, SortOrderEnum } from '../../../../shared/services/consts-enums-functions'; import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, UI_MESSAGES, CLNActions, CLN_DEFAULT_PAGE_SETTINGS, SortOrderEnum, CLN_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload';
import { SelNodeChild } from '../../../../shared/models/RTLconfig'; import { SelNodeChild } from '../../../../shared/models/RTLconfig';
import { GetInfo, Invoice, ListInvoices } from '../../../../shared/models/clnModels'; import { GetInfo, Invoice, ListInvoices } from '../../../../shared/models/clnModels';
@ -24,7 +24,8 @@ import { RTLState } from '../../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../../store/rtl.actions';
import { deleteExpiredInvoice, invoiceLookup, saveNewInvoice } from '../../../store/cln.actions'; import { deleteExpiredInvoice, invoiceLookup, saveNewInvoice } from '../../../store/cln.actions';
import { clnNodeInformation, clnNodeSettings, clnPageSettings, listInvoices } from '../../../store/cln.selector'; import { clnNodeInformation, clnNodeSettings, clnPageSettings, listInvoices } from '../../../store/cln.selector';
import { PageSettings, TableSetting } from '../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-lightning-invoices-table', selector: 'rtl-cln-lightning-invoices-table',
@ -40,6 +41,8 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
faHistory = faHistory; faHistory = faHistory;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'transactions'; public PAGE_ID = 'transactions';
public tableSetting: TableSetting = { tableId: 'invoices', recordsPerPage: PAGE_SIZE, sortBy: 'expires_at', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'invoices', recordsPerPage: PAGE_SIZE, sortBy: 'expires_at', sortOrder: SortOrderEnum.DESCENDING };
@ -67,7 +70,7 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private decimalPipe: DecimalPipe, private commonService: CommonService, private rtlEffects: RTLEffects, private datePipe: DatePipe, private actions: Actions) { constructor(private logger: LoggerService, private store: Store<RTLState>, private decimalPipe: DecimalPipe, private commonService: CommonService, private rtlEffects: RTLEffects, private datePipe: DatePipe, private actions: Actions, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -203,6 +206,43 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
this.invoices.filter = this.selFilter.trim().toLowerCase(); this.invoices.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
const newRowData = this.datePipe.transform(new Date((rowData.paid_at || 0) * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase()! +
(this.datePipe.transform(new Date((rowData.expires_at || 0) * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase()) +
((rowData.bolt12) ? 'bolt12' : (rowData.bolt11) ? 'bolt11' : 'keysend') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
// this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
onInvoiceValueChange() { onInvoiceValueChange() {
if (this.selNode && this.selNode.fiatConversion && this.invoiceValue! > 99) { if (this.selNode && this.selNode.fiatConversion && this.invoiceValue! > 99) {
this.invoiceValueHint = ''; this.invoiceValueHint = '';
@ -231,14 +271,9 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
this.invoices.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.invoices.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.invoices.sort = this.sort; this.invoices.sort = this.sort;
this.invoices.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.invoices.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
const newRowData = this.datePipe.transform(new Date((rowData.paid_at || 0) * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase()! +
(this.datePipe.transform(new Date((rowData.expires_at || 0) * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase()) +
((rowData.bolt12) ? 'bolt12' : (rowData.bolt11) ? 'bolt11' : 'keysend') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.invoices.paginator = this.paginator; this.invoices.paginator = this.paginator;
this.applyFilter(); this.applyFilter();
this.setFilterPredicate();
} }
onDownloadCSV() { onDownloadCSV() {

@ -6,9 +6,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Offer Bookmarks</span> <span class="page-title">Offer Bookmarks</span>
</div> </div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -20,7 +27,7 @@
<ng-container matColumnDef="title"> <ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Title</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Title</th>
<td mat-cell *matCellDef="let offersbookmark"> <td mat-cell *matCellDef="let offersbookmark">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{offersbookmark.title}}</span> <span class="ellipsis-child">{{offersbookmark.title}}</span>
</div> </div>
</td> </td>
@ -28,7 +35,7 @@
<ng-container matColumnDef="description"> <ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th>
<td mat-cell *matCellDef="let offersbookmark"> <td mat-cell *matCellDef="let offersbookmark">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{offersbookmark.description}}</span> <span class="ellipsis-child">{{offersbookmark.description}}</span>
</div> </div>
</td> </td>
@ -40,7 +47,7 @@
<ng-container matColumnDef="bolt12"> <ng-container matColumnDef="bolt12">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th>
<td mat-cell *matCellDef="let offersbookmark"> <td mat-cell *matCellDef="let offersbookmark">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{offersbookmark.bolt12}}</span> <span class="ellipsis-child">{{offersbookmark.bolt12}}</span>
</div> </div>
</td> </td>

@ -7,7 +7,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, PaymentTypes, AlertTypeEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, UI_MESSAGES } from '../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, PaymentTypes, AlertTypeEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, UI_MESSAGES, CLN_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload';
import { OfferBookmark } from '../../../../shared/models/clnModels'; import { OfferBookmark } from '../../../../shared/models/clnModels';
import { LoggerService } from '../../../../shared/services/logger.service'; import { LoggerService } from '../../../../shared/services/logger.service';
@ -20,7 +20,8 @@ import { clnPageSettings, offerBookmarks } from '../../../store/cln.selector';
import { CLNOfferInformationComponent } from '../offer-information-modal/offer-information.component'; import { CLNOfferInformationComponent } from '../offer-information-modal/offer-information.component';
import { CLNLightningSendPaymentsComponent } from '../../send-payment-modal/send-payment.component'; import { CLNLightningSendPaymentsComponent } from '../../send-payment-modal/send-payment.component';
import { deleteOfferBookmark, sendPayment } from '../../../store/cln.actions'; import { deleteOfferBookmark, sendPayment } from '../../../store/cln.actions';
import { PageSettings, TableSetting } from '../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-offer-bookmarks-table', selector: 'rtl-cln-offer-bookmarks-table',
@ -35,6 +36,8 @@ export class CLNOfferBookmarksTableComponent implements OnInit, AfterViewInit, O
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
faHistory = faHistory; faHistory = faHistory;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'transactions'; public PAGE_ID = 'transactions';
public tableSetting: TableSetting = { tableId: 'offer_bookmarks', recordsPerPage: PAGE_SIZE, sortBy: 'lastUpdatedAt', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'offer_bookmarks', recordsPerPage: PAGE_SIZE, sortBy: 'lastUpdatedAt', sortOrder: SortOrderEnum.DESCENDING };
@ -51,7 +54,7 @@ export class CLNOfferBookmarksTableComponent implements OnInit, AfterViewInit, O
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private commonService: CommonService, private rtlEffects: RTLEffects) { constructor(private logger: LoggerService, private store: Store<RTLState>, private commonService: CommonService, private rtlEffects: RTLEffects, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -143,13 +146,45 @@ export class CLNOfferBookmarksTableComponent implements OnInit, AfterViewInit, O
this.offersBookmarks.filter = this.selFilter.trim().toLowerCase(); this.offersBookmarks.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.offersBookmarks.filterPredicate = (Ofrbm: OfferBookmark, fltr: string) => JSON.stringify(Ofrbm).toLowerCase().includes(fltr);
// this.offersBookmarks.filterPredicate = (rowData: OfferBookmark, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadOffersTable(OffrBMs: OfferBookmark[]) { loadOffersTable(OffrBMs: OfferBookmark[]) {
this.offersBookmarks = (OffrBMs) ? new MatTableDataSource<OfferBookmark>([...OffrBMs]) : new MatTableDataSource([]); this.offersBookmarks = (OffrBMs) ? new MatTableDataSource<OfferBookmark>([...OffrBMs]) : new MatTableDataSource([]);
this.offersBookmarks.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.offersBookmarks.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.offersBookmarks.sort = this.sort; this.offersBookmarks.sort = this.sort;
this.offersBookmarks.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.offersBookmarks.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.offersBookmarks.filterPredicate = (Ofrbm: OfferBookmark, fltr: string) => JSON.stringify(Ofrbm).toLowerCase().includes(fltr);
this.offersBookmarks.paginator = this.paginator; this.offersBookmarks.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
} }

@ -8,9 +8,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Offers History</span> <span class="page-title">Offers History</span>
</div> </div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -25,7 +32,7 @@
<ng-container matColumnDef="offer_id"> <ng-container matColumnDef="offer_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Offer ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Offer ID</th>
<td mat-cell *matCellDef="let offer"> <td mat-cell *matCellDef="let offer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child"> <span class="ellipsis-child">
{{offer.offer_id}} {{offer.offer_id}}
</span> </span>
@ -45,7 +52,7 @@
<ng-container matColumnDef="bolt12"> <ng-container matColumnDef="bolt12">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th>
<td mat-cell *matCellDef="let offer"> <td mat-cell *matCellDef="let offer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child"> <span class="ellipsis-child">
{{offer.bolt12}} {{offer.bolt12}}
</span> </span>

@ -1,6 +1,6 @@
/* eslint-disable max-len */ /* eslint-disable max-len */
import { Component, OnInit, OnDestroy, ViewChild, AfterViewInit } from '@angular/core'; import { Component, OnInit, OnDestroy, ViewChild, AfterViewInit } from '@angular/core';
import { DecimalPipe, DatePipe } from '@angular/common'; import { DecimalPipe } from '@angular/common';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators'; import { take, takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
@ -11,7 +11,7 @@ import { MatTableDataSource } from '@angular/material/table';
import * as pdfMake from 'pdfmake/build/pdfmake'; import * as pdfMake from 'pdfmake/build/pdfmake';
import * as pdfFonts from 'pdfmake/build/vfs_fonts'; import * as pdfFonts from 'pdfmake/build/vfs_fonts';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, AlertTypeEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS } from '../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, AlertTypeEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS, CLN_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload';
import { SelNodeChild } from '../../../../shared/models/RTLconfig'; import { SelNodeChild } from '../../../../shared/models/RTLconfig';
import { GetInfo, Offer, OfferRequest } from '../../../../shared/models/clnModels'; import { GetInfo, Offer, OfferRequest } from '../../../../shared/models/clnModels';
@ -27,7 +27,8 @@ import { RTLState } from '../../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../../store/rtl.actions';
import { disableOffer } from '../../../store/cln.actions'; import { disableOffer } from '../../../store/cln.actions';
import { clnNodeInformation, clnNodeSettings, clnPageSettings, offers } from '../../../store/cln.selector'; import { clnNodeInformation, clnNodeSettings, clnPageSettings, offers } from '../../../store/cln.selector';
import { PageSettings, TableSetting } from '../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-offers-table', selector: 'rtl-cln-offers-table',
@ -42,6 +43,8 @@ export class CLNOffersTableComponent implements OnInit, AfterViewInit, OnDestroy
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
faHistory = faHistory; faHistory = faHistory;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'transactions'; public PAGE_ID = 'transactions';
public tableSetting: TableSetting = { tableId: 'offers', recordsPerPage: PAGE_SIZE, sortBy: 'offer_id', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'offers', recordsPerPage: PAGE_SIZE, sortBy: 'offer_id', sortOrder: SortOrderEnum.DESCENDING };
@ -69,7 +72,7 @@ export class CLNOffersTableComponent implements OnInit, AfterViewInit, OnDestroy
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private commonService: CommonService, private rtlEffects: RTLEffects, private dataService: DataService, private decimalPipe: DecimalPipe, private datePipe: DatePipe) { constructor(private logger: LoggerService, private store: Store<RTLState>, private commonService: CommonService, private rtlEffects: RTLEffects, private dataService: DataService, private decimalPipe: DecimalPipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -226,11 +229,12 @@ export class CLNOffersTableComponent implements OnInit, AfterViewInit, OnDestroy
this.offers.filter = this.selFilter.trim().toLowerCase(); this.offers.filter = this.selFilter.trim().toLowerCase();
} }
loadOffersTable(offrs: Offer[]) { getLabel(column: string) {
this.offers = (offrs) ? new MatTableDataSource<Offer>([...offrs]) : new MatTableDataSource([]); const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
this.offers.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
this.offers.sort = this.sort; }
this.offers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
setFilterPredicate() {
this.offers.filterPredicate = (rowData: Offer, fltr: string) => { this.offers.filterPredicate = (rowData: Offer, fltr: string) => {
const newRowData = ((rowData.active) ? ' active' : ' inactive') + ((rowData.used) ? ' used' : ' unused') + ((rowData.single_use) ? ' single' : ' multiple') + JSON.stringify(rowData).toLowerCase(); const newRowData = ((rowData.active) ? ' active' : ' inactive') + ((rowData.used) ? ' used' : ' unused') + ((rowData.single_use) ? ' single' : ' multiple') + JSON.stringify(rowData).toLowerCase();
if (fltr === 'active' || fltr === 'inactive' || fltr === 'used' || fltr === 'unused' || fltr === 'single' || fltr === 'multiple') { if (fltr === 'active' || fltr === 'inactive' || fltr === 'used' || fltr === 'unused' || fltr === 'single' || fltr === 'multiple') {
@ -238,7 +242,38 @@ export class CLNOffersTableComponent implements OnInit, AfterViewInit, OnDestroy
} }
return newRowData.includes(fltr); return newRowData.includes(fltr);
}; };
// this.offers.filterPredicate = (rowData: Offer, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadOffersTable(offrs: Offer[]) {
this.offers = (offrs) ? new MatTableDataSource<Offer>([...offrs]) : new MatTableDataSource([]);
this.offers.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.offers.sort = this.sort;
this.offers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.offers.paginator = this.paginator; this.offers.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
} }

@ -19,9 +19,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Payments History</span> <span class="page-title">Payments History</span>
</div> </div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start start"> <div fxLayout="row" fxLayoutAlign="start start">
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
@ -47,7 +54,7 @@
<ng-container matColumnDef="payment_hash"> <ng-container matColumnDef="payment_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.payment_hash}}</span> <span class="ellipsis-child">{{payment?.payment_hash}}</span>
</span> </span>
</td> </td>
@ -55,7 +62,7 @@
<ng-container matColumnDef="bolt11"> <ng-container matColumnDef="bolt11">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.bolt11}}</span> <span class="ellipsis-child">{{payment?.bolt11}}</span>
</span> </span>
</td> </td>
@ -63,7 +70,7 @@
<ng-container matColumnDef="label"> <ng-container matColumnDef="label">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Label</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Label</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.label}}</span> <span class="ellipsis-child">{{payment?.label}}</span>
</span> </span>
</td> </td>
@ -71,7 +78,7 @@
<ng-container matColumnDef="destination"> <ng-container matColumnDef="destination">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Destination</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Destination</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.destination}}</span> <span class="ellipsis-child">{{payment?.destination}}</span>
</span> </span>
</td> </td>
@ -79,7 +86,7 @@
<ng-container matColumnDef="memo"> <ng-container matColumnDef="memo">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Memo</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Memo</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.memo}}</span> <span class="ellipsis-child">{{payment?.memo}}</span>
</span> </span>
</td> </td>
@ -148,7 +155,7 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_payment_hash"> <ng-container matColumnDef="group_payment_hash">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.payment_hash}}</span> <span class="ellipsis-child">{{payment?.payment_hash}}</span>
</span> </span>
<span *ngIf="payment.is_expanded"> <span *ngIf="payment.is_expanded">
@ -160,11 +167,11 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_bolt11"> <ng-container matColumnDef="group_bolt11">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.bolt11}}</span> <span class="ellipsis-child">{{payment?.bolt11}}</span>
</span> </span>
<span *ngIf="payment.is_expanded"> <span *ngIf="payment.is_expanded">
<span *ngFor="let mpp of payment?.mpps" fxLayoutAlign="start center" class="ellipsis-parent mpp-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span *ngFor="let mpp of payment?.mpps" fxLayoutAlign="start center" class="ellipsis-parent mpp-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child"></span> <span class="ellipsis-child"></span>
</span> </span>
</span> </span>
@ -172,11 +179,11 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_label"> <ng-container matColumnDef="group_label">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.label}}</span> <span class="ellipsis-child">{{payment?.label}}</span>
</span> </span>
<span *ngIf="payment.is_expanded"> <span *ngIf="payment.is_expanded">
<span *ngFor="let mpp of payment?.mpps" fxLayoutAlign="start center" class="ellipsis-parent mpp-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span *ngFor="let mpp of payment?.mpps" fxLayoutAlign="start center" class="ellipsis-parent mpp-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child"></span> <span class="ellipsis-child"></span>
</span> </span>
</span> </span>
@ -184,11 +191,11 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_destination"> <ng-container matColumnDef="group_destination">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.destination}}</span> <span class="ellipsis-child">{{payment?.destination}}</span>
</span> </span>
<span *ngIf="payment.is_expanded"> <span *ngIf="payment.is_expanded">
<span *ngFor="let mpp of payment?.mpps" fxLayoutAlign="start center" class="ellipsis-parent mpp-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span *ngFor="let mpp of payment?.mpps" fxLayoutAlign="start center" class="ellipsis-parent mpp-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child"></span> <span class="ellipsis-child"></span>
</span> </span>
</span> </span>
@ -196,11 +203,11 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_memo"> <ng-container matColumnDef="group_memo">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent mpp-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.memo}}</span> <span class="ellipsis-child">{{payment?.memo}}</span>
</span> </span>
<span *ngIf="payment.is_expanded"> <span *ngIf="payment.is_expanded">
<span *ngFor="let mpp of payment?.mpps" fxLayoutAlign="start center" class="ellipsis-parent mpp-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span *ngFor="let mpp of payment?.mpps" fxLayoutAlign="start center" class="ellipsis-parent mpp-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child"></span> <span class="ellipsis-child"></span>
</span> </span>
</span> </span>

@ -9,7 +9,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { GetInfo, Payment, PayRequest } from '../../../shared/models/clnModels'; import { GetInfo, Payment, PayRequest } from '../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, APICallStatusEnum, UI_MESSAGES, PaymentTypes, CLN_DEFAULT_PAGE_SETTINGS, SortOrderEnum } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, APICallStatusEnum, UI_MESSAGES, PaymentTypes, CLN_DEFAULT_PAGE_SETTINGS, SortOrderEnum, CLN_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { DataService } from '../../../shared/services/data.service'; import { DataService } from '../../../shared/services/data.service';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
@ -24,7 +24,8 @@ import { RTLState } from '../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../store/rtl.actions';
import { sendPayment } from '../../store/cln.actions'; import { sendPayment } from '../../store/cln.actions';
import { clnNodeInformation, clnNodeSettings, clnPageSettings, payments } from '../../store/cln.selector'; import { clnNodeInformation, clnNodeSettings, clnPageSettings, payments } from '../../store/cln.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-cln-lightning-payments', selector: 'rtl-cln-lightning-payments',
@ -40,6 +41,8 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
@ViewChild('sendPaymentForm', { static: false }) form; @ViewChild('sendPaymentForm', { static: false }) form;
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = CLN_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'transactions'; public PAGE_ID = 'transactions';
public tableSetting: TableSetting = { tableId: 'payments', recordsPerPage: PAGE_SIZE, sortBy: 'created_at', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'payments', recordsPerPage: PAGE_SIZE, sortBy: 'created_at', sortOrder: SortOrderEnum.DESCENDING };
@ -64,7 +67,16 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private clnEffects: CLNEffects, private decimalPipe: DecimalPipe, private titleCasePipe: TitleCasePipe, private datePipe: DatePipe, private dataService: DataService) { constructor(
private logger: LoggerService,
private commonService: CommonService,
private store: Store<RTLState>,
private rtlEffects: RTLEffects,
private decimalPipe: DecimalPipe,
private titleCasePipe: TitleCasePipe,
private datePipe: DatePipe,
private dataService: DataService,
private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -301,16 +313,48 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
this.payments.filter = this.selFilter.trim().toLowerCase(); this.payments.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.payments.filterPredicate = (rowData: Payment, fltr: string) => {
const newRowData = ((rowData.created_at) ? this.datePipe.transform(new Date(rowData.created_at * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + ((rowData.bolt12) ? 'bolt12' : (rowData.bolt11) ? 'bolt11' : 'keysend') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
// this.payments.filterPredicate = (rowData: Payment, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadPaymentsTable(payments: Payment[]) { loadPaymentsTable(payments: Payment[]) {
this.payments = (payments) ? new MatTableDataSource<Payment>([...payments]) : new MatTableDataSource([]); this.payments = (payments) ? new MatTableDataSource<Payment>([...payments]) : new MatTableDataSource([]);
this.payments.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.payments.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.payments.sort = this.sort; this.payments.sort = this.sort;
this.payments.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.payments.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.payments.filterPredicate = (rowData: Payment, fltr: string) => {
const newRowData = ((rowData.created_at) ? this.datePipe.transform(new Date(rowData.created_at * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + ((rowData.bolt12) ? 'bolt12' : (rowData.bolt11) ? 'bolt11' : 'keysend') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.payments.paginator = this.paginator; this.payments.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
} }

@ -4,9 +4,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Transaction History</span> <span class="page-title">Transaction History</span>
</div> </div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start start"> <div fxLayout="row" fxLayoutAlign="start start">
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container">
@ -20,7 +27,7 @@
<ng-container matColumnDef="address"> <ng-container matColumnDef="address">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th>
<td mat-cell *matCellDef="let transaction"> <td mat-cell *matCellDef="let transaction">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{transaction?.address}}</span> <span class="ellipsis-child">{{transaction?.address}}</span>
</div> </div>
</td> </td>
@ -28,7 +35,7 @@
<ng-container matColumnDef="blockHash"> <ng-container matColumnDef="blockHash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Blockhash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Blockhash</th>
<td mat-cell *matCellDef="let transaction"> <td mat-cell *matCellDef="let transaction">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{transaction?.blockHash}}</span> <span class="ellipsis-child">{{transaction?.blockHash}}</span>
</div> </div>
</td> </td>
@ -36,7 +43,7 @@
<ng-container matColumnDef="txid"> <ng-container matColumnDef="txid">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Transaction ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Transaction ID</th>
<td mat-cell *matCellDef="let transaction"> <td mat-cell *matCellDef="let transaction">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{transaction?.txid}}</span> <span class="ellipsis-child">{{transaction?.txid}}</span>
</div> </div>
</td> </td>

@ -10,7 +10,7 @@ import { MatTableDataSource } from '@angular/material/table';
import { Transaction } from '../../../shared/models/eclModels'; import { Transaction } from '../../../shared/models/eclModels';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -18,7 +18,8 @@ import { RTLState } from '../../../store/rtl.state';
import { openAlert } from '../../../store/rtl.actions'; import { openAlert } from '../../../store/rtl.actions';
import { fetchTransactions } from '../../store/ecl.actions'; import { fetchTransactions } from '../../store/ecl.actions';
import { eclPageSettings, transactions } from '../../store/ecl.selector'; import { eclPageSettings, transactions } from '../../store/ecl.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-ecl-on-chain-transaction-history', selector: 'rtl-ecl-on-chain-transaction-history',
@ -33,6 +34,8 @@ export class ECLOnChainTransactionHistoryComponent implements OnInit, OnDestroy
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faHistory = faHistory; public faHistory = faHistory;
public nodePageDefs = ECL_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'on_chain'; public PAGE_ID = 'on_chain';
public tableSetting: TableSetting = { tableId: 'transaction', recordsPerPage: PAGE_SIZE, sortBy: 'timestamp', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'transaction', recordsPerPage: PAGE_SIZE, sortBy: 'timestamp', sortOrder: SortOrderEnum.DESCENDING };
@ -48,7 +51,7 @@ export class ECLOnChainTransactionHistoryComponent implements OnInit, OnDestroy
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -90,6 +93,41 @@ export class ECLOnChainTransactionHistoryComponent implements OnInit, OnDestroy
this.listTransactions.filter = this.selFilter.trim().toLowerCase(); this.listTransactions.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.listTransactions.filterPredicate = (rowData: Transaction, fltr: string) => {
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
// this.listTransactions.filterPredicate = (rowData: Transaction, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
onTransactionClick(selTransaction: Transaction, event: any) { onTransactionClick(selTransaction: Transaction, event: any) {
const reorderedTransactions = [ const reorderedTransactions = [
[{ key: 'blockHash', value: selTransaction.blockHash, title: 'Block Hash', width: 100 }], [{ key: 'blockHash', value: selTransaction.blockHash, title: 'Block Hash', width: 100 }],
@ -116,11 +154,8 @@ export class ECLOnChainTransactionHistoryComponent implements OnInit, OnDestroy
this.listTransactions.sort = this.sort; this.listTransactions.sort = this.sort;
this.listTransactions.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.listTransactions.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.listTransactions.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.listTransactions.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.listTransactions.filterPredicate = (rowData: Transaction, fltr: string) => {
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.listTransactions.paginator = this.paginator; this.listTransactions.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.listTransactions); this.logger.info(this.listTransactions);
} }

@ -1,9 +1,16 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -26,7 +33,7 @@
<ng-container matColumnDef="channelId"> <ng-container matColumnDef="channelId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.channelId}}</span> <span class="ellipsis-child">{{channel?.channelId}}</span>
</div> </div>
</td> </td>
@ -34,7 +41,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.alias}}</span> <span class="ellipsis-child">{{channel.alias}}</span>
</div> </div>
</td> </td>
@ -42,7 +49,7 @@
<ng-container matColumnDef="nodeId"> <ng-container matColumnDef="nodeId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.nodeId}}</span> <span class="ellipsis-child">{{channel?.nodeId}}</span>
</div> </div>
</td> </td>

@ -8,7 +8,7 @@ import { MatTableDataSource } from '@angular/material/table';
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { Channel, ChannelsStatus, GetInfo, LightningBalance, OnChainBalance, Peer } from '../../../../../shared/models/eclModels'; import { Channel, ChannelsStatus, GetInfo, LightningBalance, OnChainBalance, Peer } from '../../../../../shared/models/eclModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, FEE_RATE_TYPES, AlertTypeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, FEE_RATE_TYPES, AlertTypeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../../../shared/services/logger.service'; import { LoggerService } from '../../../../../shared/services/logger.service';
import { CommonService } from '../../../../../shared/services/common.service'; import { CommonService } from '../../../../../shared/services/common.service';
@ -19,7 +19,8 @@ import { openAlert, openConfirmation } from '../../../../../store/rtl.actions';
import { RTLState } from '../../../../../store/rtl.state'; import { RTLState } from '../../../../../store/rtl.state';
import { closeChannel } from '../../../../store/ecl.actions'; import { closeChannel } from '../../../../store/ecl.actions';
import { allChannelsInfo, eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../../../store/ecl.selector'; import { allChannelsInfo, eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../../../store/ecl.selector';
import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-ecl-channel-inactive-table', selector: 'rtl-ecl-channel-inactive-table',
@ -35,6 +36,8 @@ export class ECLChannelInactiveTableComponent implements OnInit, AfterViewInit,
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faEye = faEye; public faEye = faEye;
public faEyeSlash = faEyeSlash; public faEyeSlash = faEyeSlash;
public nodePageDefs = ECL_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'inactive_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'inactive_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING };
@ -56,7 +59,7 @@ export class ECLChannelInactiveTableComponent implements OnInit, AfterViewInit,
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService) { constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -141,10 +144,6 @@ export class ECLChannelInactiveTableComponent implements OnInit, AfterViewInit,
}); });
} }
applyFilter() {
this.channels.filter = this.selFilter.trim().toLocaleLowerCase();
}
onChannelClick(selChannel: Channel, event: any) { onChannelClick(selChannel: Channel, event: any) {
this.store.dispatch(openAlert({ this.store.dispatch(openAlert({
payload: { payload: {
@ -157,13 +156,49 @@ export class ECLChannelInactiveTableComponent implements OnInit, AfterViewInit,
})); }));
} }
applyFilter() {
this.channels.filter = this.selFilter.trim().toLocaleLowerCase();
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.channels.filterPredicate = (channel: Channel, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr);
// this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadChannelsTable() { loadChannelsTable() {
this.channels = new MatTableDataSource<Channel>([...this.inactiveChannels]); this.channels = new MatTableDataSource<Channel>([...this.inactiveChannels]);
this.channels.sort = this.sort; this.channels.sort = this.sort;
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.channels.filterPredicate = (channel: Channel, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr);
this.channels.paginator = this.paginator; this.channels.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.channels); this.logger.info(this.channels);
} }

@ -1,9 +1,16 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -22,7 +29,7 @@
<ng-container matColumnDef="channelId"> <ng-container matColumnDef="channelId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.channelId}}</span> <span class="ellipsis-child">{{channel?.channelId}}</span>
</div> </div>
</td> </td>
@ -30,7 +37,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.alias}}</span> <span class="ellipsis-child">{{channel?.alias}}</span>
</div> </div>
</td> </td>
@ -38,7 +45,7 @@
<ng-container matColumnDef="nodeId"> <ng-container matColumnDef="nodeId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.nodeId}}</span> <span class="ellipsis-child">{{channel?.nodeId}}</span>
</div> </div>
</td> </td>

@ -9,7 +9,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { Channel, ChannelsStatus, GetInfo, LightningBalance, OnChainBalance, Peer } from '../../../../../shared/models/eclModels'; import { Channel, ChannelsStatus, GetInfo, LightningBalance, OnChainBalance, Peer } from '../../../../../shared/models/eclModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, FEE_RATE_TYPES, AlertTypeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, FEE_RATE_TYPES, AlertTypeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../../../shared/services/logger.service'; import { LoggerService } from '../../../../../shared/services/logger.service';
import { CommonService } from '../../../../../shared/services/common.service'; import { CommonService } from '../../../../../shared/services/common.service';
@ -20,7 +20,8 @@ import { openAlert, openConfirmation } from '../../../../../store/rtl.actions';
import { RTLState } from '../../../../../store/rtl.state'; import { RTLState } from '../../../../../store/rtl.state';
import { closeChannel, updateChannel } from '../../../../store/ecl.actions'; import { closeChannel, updateChannel } from '../../../../store/ecl.actions';
import { allChannelsInfo, eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../../../store/ecl.selector'; import { allChannelsInfo, eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../../../store/ecl.selector';
import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-ecl-channel-open-table', selector: 'rtl-ecl-channel-open-table',
@ -36,6 +37,8 @@ export class ECLChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faEye = faEye; public faEye = faEye;
public faEyeSlash = faEyeSlash; public faEyeSlash = faEyeSlash;
public nodePageDefs = ECL_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'open_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'open_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING };
@ -57,7 +60,7 @@ export class ECLChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService, private router: Router) { constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService, private router: Router, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
this.selFilter = this.router.getCurrentNavigation()?.extras?.state?.filter ? this.router.getCurrentNavigation()?.extras?.state?.filter : ''; this.selFilter = this.router.getCurrentNavigation()?.extras?.state?.filter ? this.router.getCurrentNavigation()?.extras?.state?.filter : '';
} }
@ -211,10 +214,6 @@ export class ECLChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
}); });
} }
applyFilter() {
this.channels.filter = this.selFilter.trim().toLowerCase();
}
onChannelClick(selChannel: Channel, event: any) { onChannelClick(selChannel: Channel, event: any) {
this.store.dispatch(openAlert({ this.store.dispatch(openAlert({
payload: { payload: {
@ -227,13 +226,49 @@ export class ECLChannelOpenTableComponent implements OnInit, AfterViewInit, OnDe
})); }));
} }
applyFilter() {
this.channels.filter = this.selFilter.trim().toLowerCase();
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.channels.filterPredicate = (channel: Channel, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr);
// this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadChannelsTable() { loadChannelsTable() {
this.channels = new MatTableDataSource<Channel>([...this.activeChannels]); this.channels = new MatTableDataSource<Channel>([...this.activeChannels]);
this.channels.sort = this.sort; this.channels.sort = this.sort;
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.channels.filterPredicate = (channel: Channel, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr);
this.channels.paginator = this.paginator; this.channels.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.channels); this.logger.info(this.channels);
} }

@ -1,9 +1,16 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -22,7 +29,7 @@
<ng-container matColumnDef="channelId"> <ng-container matColumnDef="channelId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.channelId}}</span> <span class="ellipsis-child">{{channel?.channelId}}</span>
</div> </div>
</td> </td>
@ -34,7 +41,7 @@
<ng-container matColumnDef="nodeId"> <ng-container matColumnDef="nodeId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.nodeId}}</span> <span class="ellipsis-child">{{channel?.nodeId}}</span>
</div> </div>
</td> </td>

@ -9,7 +9,7 @@ import { MatTableDataSource } from '@angular/material/table';
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { Channel, ChannelsStatus, GetInfo, LightningBalance, OnChainBalance, Peer } from '../../../../../shared/models/eclModels'; import { Channel, ChannelsStatus, GetInfo, LightningBalance, OnChainBalance, Peer } from '../../../../../shared/models/eclModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, FEE_RATE_TYPES, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, FEE_RATE_TYPES, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload';
import { ECLChannelInformationComponent } from '../../channel-information-modal/channel-information.component'; import { ECLChannelInformationComponent } from '../../channel-information-modal/channel-information.component';
import { LoggerService } from '../../../../../shared/services/logger.service'; import { LoggerService } from '../../../../../shared/services/logger.service';
@ -18,7 +18,8 @@ import { CommonService } from '../../../../../shared/services/common.service';
import { openAlert } from '../../../../../store/rtl.actions'; import { openAlert } from '../../../../../store/rtl.actions';
import { RTLState } from '../../../../../store/rtl.state'; import { RTLState } from '../../../../../store/rtl.state';
import { allChannelsInfo, eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../../../store/ecl.selector'; import { allChannelsInfo, eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../../../store/ecl.selector';
import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
@Component({ @Component({
@ -35,6 +36,8 @@ export class ECLChannelPendingTableComponent implements OnInit, AfterViewInit, O
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faEye = faEye; public faEye = faEye;
public faEyeSlash = faEyeSlash; public faEyeSlash = faEyeSlash;
public nodePageDefs = ECL_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'pending_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'pending_channels', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING };
@ -56,7 +59,7 @@ export class ECLChannelPendingTableComponent implements OnInit, AfterViewInit, O
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private commonService: CommonService) { constructor(private logger: LoggerService, private store: Store<RTLState>, private commonService: CommonService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -111,10 +114,6 @@ export class ECLChannelPendingTableComponent implements OnInit, AfterViewInit, O
} }
} }
applyFilter() {
this.channels.filter = this.selFilter.trim().toLowerCase();
}
onChannelClick(selChannel: Channel, event: any) { onChannelClick(selChannel: Channel, event: any) {
this.store.dispatch(openAlert({ this.store.dispatch(openAlert({
payload: { payload: {
@ -127,13 +126,49 @@ export class ECLChannelPendingTableComponent implements OnInit, AfterViewInit, O
})); }));
} }
applyFilter() {
this.channels.filter = this.selFilter.trim().toLowerCase();
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.channels.filterPredicate = (channel: Channel, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr);
// this.channels.filterPredicate = (rowData: Channel, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadChannelsTable() { loadChannelsTable() {
this.channels = new MatTableDataSource<Channel>([...this.pendingChannels]); this.channels = new MatTableDataSource<Channel>([...this.pendingChannels]);
this.channels.sort = this.sort; this.channels.sort = this.sort;
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.channels.filterPredicate = (channel: Channel, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr);
this.channels.paginator = this.paginator; this.channels.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.channels); this.logger.info(this.channels);
} }

@ -8,11 +8,16 @@
<fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Peers</span> <span class="page-title">Peers</span>
</div> </div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<div fxLayout="row" fxLayoutAlign="start start"> <mat-form-field fxFlex="49">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
</div> <mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-form-field> </mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -27,7 +32,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
<td mat-cell *matCellDef="let peer"> <td mat-cell *matCellDef="let peer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{peer?.alias}}</span> <span class="ellipsis-child">{{peer?.alias}}</span>
</div> </div>
</td> </td>
@ -35,7 +40,7 @@
<ng-container matColumnDef="nodeId"> <ng-container matColumnDef="nodeId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th>
<td mat-cell *matCellDef="let peer"> <td mat-cell *matCellDef="let peer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{peer?.nodeId}}</span> <span class="ellipsis-child">{{peer?.nodeId}}</span>
</div> </div>
</td> </td>

@ -10,7 +10,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { Peer, GetInfo, OnChainBalance } from '../../../shared/models/eclModels'; import { Peer, GetInfo, OnChainBalance } from '../../../shared/models/eclModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, ScreenSizeEnum, APICallStatusEnum, ECLActions, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, ScreenSizeEnum, APICallStatusEnum, ECLActions, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
@ -22,7 +22,8 @@ import { RTLState } from '../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../store/rtl.actions';
import { disconnectPeer } from '../../store/ecl.actions'; import { disconnectPeer } from '../../store/ecl.actions';
import { eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../store/ecl.selector'; import { eclNodeInformation, eclPageSettings, onchainBalance, peers } from '../../store/ecl.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-ecl-peers', selector: 'rtl-ecl-peers',
@ -36,6 +37,8 @@ export class ECLPeersComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = ECL_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'peers', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'peers', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING };
@ -57,7 +60,7 @@ export class ECLPeersComponent implements OnInit, AfterViewInit, OnDestroy {
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private actions: Actions, private commonService: CommonService) { constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private actions: Actions, private commonService: CommonService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -204,13 +207,45 @@ export class ECLPeersComponent implements OnInit, AfterViewInit, OnDestroy {
this.peers.filter = this.selFilter.trim().toLowerCase(); this.peers.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.peers.filterPredicate = (peer: Peer, fltr: string) => JSON.stringify(peer).toLowerCase().includes(fltr);
// this.peers.filterPredicate = (rowData: Peer, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadPeersTable(peers: Peer[]) { loadPeersTable(peers: Peer[]) {
this.peers = (peers) ? new MatTableDataSource<Peer>([...peers]) : new MatTableDataSource([]); this.peers = (peers) ? new MatTableDataSource<Peer>([...peers]) : new MatTableDataSource([]);
this.peers.sort = this.sort; this.peers.sort = this.sort;
this.peers.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.peers.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.peers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.peers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.peers.filterPredicate = (peer: Peer, fltr: string) => JSON.stringify(peer).toLowerCase().includes(fltr);
this.peers.paginator = this.paginator; this.peers.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
} }

@ -37,7 +37,7 @@
</ngx-charts-bar-vertical> </ngx-charts-bar-vertical>
</div> </div>
<div class="mt-1"> <div class="mt-1">
<rtl-ecl-forwarding-history *ngIf="filteredEventsBySelectedPeriod.length > 0" [pageId]="'reports'" [tableId]="'routing'"[eventsData]="filteredEventsBySelectedPeriod" [filterValue]="eventFilterValue"></rtl-ecl-forwarding-history> <rtl-ecl-forwarding-history *ngIf="filteredEventsBySelectedPeriod.length > 0" [pageId]="'reports'" [tableId]="'routing'"[eventsData]="filteredEventsBySelectedPeriod" [selFilter]="eventFilterValue"></rtl-ecl-forwarding-history>
</div> </div>
</div> </div>
</div> </div>

@ -35,7 +35,7 @@
</ngx-charts-bar-vertical-2d> </ngx-charts-bar-vertical-2d>
</div> </div>
<div class="mt-1"> <div class="mt-1">
<rtl-transactions-report-table *ngIf="transactionsNonZeroReportData.length > 0" [displayedColumns]="displayedColumns" [tableSetting]="tableSetting" [dataList]="transactionsNonZeroReportData" [dataRange]="reportPeriod" [filterValue]="transactionFilterValue"></rtl-transactions-report-table> <rtl-transactions-report-table *ngIf="transactionsNonZeroReportData.length > 0" [displayedColumns]="displayedColumns" [tableSetting]="tableSetting" [dataList]="transactionsNonZeroReportData" [dataRange]="reportPeriod" [selFilter]="transactionFilterValue"></rtl-transactions-report-table>
</div> </div>
</div> </div>
</div> </div>

@ -2,9 +2,16 @@
<div class="p-2 error-border my-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div> <div class="p-2 error-border my-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput [(ngModel)]="filterValue" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -24,7 +31,7 @@
<ng-container matColumnDef="fromChannelId"> <ng-container matColumnDef="fromChannelId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel ID</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.fromChannelId}}</span> <span class="ellipsis-child">{{fhEvent?.fromChannelId}}</span>
</div> </div>
</td> </td>
@ -36,7 +43,7 @@
<ng-container matColumnDef="fromChannelAlias"> <ng-container matColumnDef="fromChannelAlias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>In Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.fromChannelAlias}}</span> <span class="ellipsis-child">{{fhEvent?.fromChannelAlias}}</span>
</div> </div>
</td> </td>
@ -44,7 +51,7 @@
<ng-container matColumnDef="toChannelId"> <ng-container matColumnDef="toChannelId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel ID</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.toChannelId}}</span> <span class="ellipsis-child">{{fhEvent?.toChannelId}}</span>
</div> </div>
</td> </td>
@ -56,7 +63,7 @@
<ng-container matColumnDef="toChannelAlias"> <ng-container matColumnDef="toChannelAlias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Out Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.toChannelAlias}}</span> <span class="ellipsis-child">{{fhEvent?.toChannelAlias}}</span>
</div> </div>
</td> </td>
@ -64,7 +71,7 @@
<ng-container matColumnDef="paymentHash"> <ng-container matColumnDef="paymentHash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.paymentHash}}</span> <span class="ellipsis-child">{{fhEvent?.paymentHash}}</span>
</div> </div>
</td> </td>

@ -8,7 +8,7 @@ import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { PaymentRelayed, Payments } from '../../../shared/models/eclModels'; import { PaymentRelayed, Payments } from '../../../shared/models/eclModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -16,7 +16,8 @@ import { CommonService } from '../../../shared/services/common.service';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { openAlert } from '../../../store/rtl.actions'; import { openAlert } from '../../../store/rtl.actions';
import { eclPageSettings, payments } from '../../store/ecl.selector'; import { eclPageSettings, payments } from '../../store/ecl.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-ecl-forwarding-history', selector: 'rtl-ecl-forwarding-history',
@ -33,7 +34,9 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
@Input() pageId = 'routing'; @Input() pageId = 'routing';
@Input() tableId = 'forwarding_history'; @Input() tableId = 'forwarding_history';
@Input() eventsData: PaymentRelayed[] = []; @Input() eventsData: PaymentRelayed[] = [];
@Input() filterValue = ''; @Input() selFilter = '';
public nodePageDefs = ECL_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public tableSetting: TableSetting = { tableId: 'forwarding_history', recordsPerPage: PAGE_SIZE, sortBy: 'timestamp', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'forwarding_history', recordsPerPage: PAGE_SIZE, sortBy: 'timestamp', sortOrder: SortOrderEnum.DESCENDING };
public displayedColumns: any[] = []; public displayedColumns: any[] = [];
@ -47,7 +50,7 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -103,7 +106,7 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
this.loadForwardingEventsTable(this.eventsData); this.loadForwardingEventsTable(this.eventsData);
} }
} }
if (changes.filterValue && !changes.filterValue.firstChange) { if (changes.selFilter && !changes.selFilter.firstChange) {
this.applyFilter(); this.applyFilter();
} }
} }
@ -136,6 +139,47 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
})); }));
} }
applyFilter() {
if (this.forwardingHistoryEvents) {
this.forwardingHistoryEvents.filter = this.selFilter.trim().toLowerCase();
}
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.pageId][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.forwardingHistoryEvents.filterPredicate = (rowData: PaymentRelayed, fltr: string) => {
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
// this.forwardingHistoryEvents.filterPredicate = (rowData: PaymentRelayed, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadForwardingEventsTable(forwardingEvents: PaymentRelayed[]) { loadForwardingEventsTable(forwardingEvents: PaymentRelayed[]) {
this.forwardingHistoryEvents = new MatTableDataSource<PaymentRelayed>([...forwardingEvents]); this.forwardingHistoryEvents = new MatTableDataSource<PaymentRelayed>([...forwardingEvents]);
this.forwardingHistoryEvents.sort = this.sort; this.forwardingHistoryEvents.sort = this.sort;
@ -149,11 +193,8 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
} }
}; };
this.forwardingHistoryEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.forwardingHistoryEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.forwardingHistoryEvents.filterPredicate = (rowData: PaymentRelayed, fltr: string) => {
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.forwardingHistoryEvents.paginator = this.paginator; this.forwardingHistoryEvents.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.forwardingHistoryEvents); this.logger.info(this.forwardingHistoryEvents);
} }
@ -164,12 +205,6 @@ export class ECLForwardingHistoryComponent implements OnInit, OnChanges, AfterVi
} }
} }
applyFilter() {
if (this.forwardingHistoryEvents) {
this.forwardingHistoryEvents.filter = this.filterValue.trim().toLowerCase();
}
}
ngOnDestroy() { ngOnDestroy() {
this.unSubs.forEach((completeSub) => { this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null); completeSub.next(<any>null);

@ -4,17 +4,24 @@
<div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch" class="mb-4"> <div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch" class="mb-4">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}">
<div fxFlex="70">Incoming</div> <div fxFlex="70">Incoming</div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyIncomingFilter()" [(ngModel)]="filterIn" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterByIn" (selectionChange)="selFilterIn=''; applyIncomingFilter()" name="filterByIn">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilterIn" (input)="applyIncomingFilter()" (keyup)="applyIncomingFilter()" name="filterin" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start start" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start start" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableIn [dataSource]="RoutingPeersIncoming" matSort class="overflow-auto incoming-table"> <table mat-table #tableIn [dataSource]="routingPeersIncoming" matSort class="overflow-auto incoming-table">
<ng-container matColumnDef="channelId"> <ng-container matColumnDef="channelId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer?.channelId}}</span> <span class="ellipsis-child">{{rPeer?.channelId}}</span>
</div> </div>
</td> </td>
@ -22,7 +29,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer?.alias}}</span> <span class="ellipsis-child">{{rPeer?.alias}}</span>
</div> </div>
</td> </td>
@ -42,12 +49,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="no_incoming_event"> <ng-container matColumnDef="no_incoming_event">
<td mat-footer-cell *matFooterCellDef colspan="4"> <td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">No incoming routing peer available.</p> <p *ngIf="(!routingPeersIncoming?.data || routingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">No incoming routing peer available.</p>
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting incoming routing peers...</p> <p *ngIf="(!routingPeersIncoming?.data || routingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting incoming routing peers...</p>
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p> <p *ngIf="(!routingPeersIncoming?.data || routingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td> </td>
</ng-container> </ng-container>
<tr mat-footer-row *matFooterRowDef="['no_incoming_event']" [ngClass]="{'display-none': RoutingPeersIncoming?.data && RoutingPeersIncoming?.data?.length>0}"></tr> <tr mat-footer-row *matFooterRowDef="['no_incoming_event']" [ngClass]="{'display-none': routingPeersIncoming?.data && routingPeersIncoming?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
@ -57,17 +64,24 @@
<div fxLayout="column" fxFlex="49" fxLayoutAlign="end stretch" class="mb-4"> <div fxLayout="column" fxFlex="49" fxLayoutAlign="end stretch" class="mb-4">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}">
<div fxFlex="70">Outgoing</div> <div fxFlex="70">Outgoing</div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyOutgoingFilter()" [(ngModel)]="filterOut" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterByOut" (selectionChange)="selFilterOut=''; applyOutgoingFilter()" name="filterByOut">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilterOut" (input)="applyOutgoingFilter()" (keyup)="applyOutgoingFilter()" name="filterout" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableOut [dataSource]="RoutingPeersOutgoing" matSort class="overflow-auto outgoing-table"> <table mat-table #tableOut [dataSource]="routingPeersOutgoing" matSort class="overflow-auto outgoing-table">
<ng-container matColumnDef="channelId"> <ng-container matColumnDef="channelId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer?.channelId}}</span> <span class="ellipsis-child">{{rPeer?.channelId}}</span>
</div> </div>
</td> </td>
@ -75,7 +89,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer?.alias}}</span> <span class="ellipsis-child">{{rPeer?.alias}}</span>
</div> </div>
</td> </td>
@ -95,12 +109,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="no_outgoing_event"> <ng-container matColumnDef="no_outgoing_event">
<td mat-footer-cell *matFooterCellDef colspan="4"> <td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">No outgoing routing peer available.</p> <p *ngIf="(!routingPeersOutgoing?.data || routingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">No outgoing routing peer available.</p>
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting outgoing routing peers...</p> <p *ngIf="(!routingPeersOutgoing?.data || routingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting outgoing routing peers...</p>
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p> <p *ngIf="(!routingPeersOutgoing?.data || routingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td> </td>
</ng-container> </ng-container>
<tr mat-footer-row *matFooterRowDef="['no_outgoing_event']" [ngClass]="{'display-none': RoutingPeersOutgoing?.data && RoutingPeersOutgoing?.data?.length>0}"></tr> <tr mat-footer-row *matFooterRowDef="['no_outgoing_event']" [ngClass]="{'display-none': routingPeersOutgoing?.data && routingPeersOutgoing?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>

@ -7,7 +7,7 @@ import { MatSort } from '@angular/material/sort';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { PaymentRelayed, Payments, RoutingPeers } from '../../../shared/models/eclModels'; import { PaymentRelayed, Payments, RoutingPeers } from '../../../shared/models/eclModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -15,6 +15,7 @@ import { CommonService } from '../../../shared/services/common.service';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { eclPageSettings, payments } from '../../store/ecl.selector'; import { eclPageSettings, payments } from '../../store/ecl.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-ecl-routing-peers', selector: 'rtl-ecl-routing-peers',
@ -30,13 +31,16 @@ export class ECLRoutingPeersComponent implements OnInit, AfterViewInit, OnDestro
@ViewChild('tableOut', { read: MatSort, static: false }) sortOut: MatSort; @ViewChild('tableOut', { read: MatSort, static: false }) sortOut: MatSort;
@ViewChild('paginatorIn', { static: false }) paginatorIn: MatPaginator | undefined; @ViewChild('paginatorIn', { static: false }) paginatorIn: MatPaginator | undefined;
@ViewChild('paginatorOut', { static: false }) paginatorOut: MatPaginator | undefined; @ViewChild('paginatorOut', { static: false }) paginatorOut: MatPaginator | undefined;
public nodePageDefs = ECL_PAGE_DEFS;
public selFilterByIn = 'all';
public selFilterByOut = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'routing'; public PAGE_ID = 'routing';
public tableSetting: TableSetting = { tableId: 'routing_peers', recordsPerPage: PAGE_SIZE, sortBy: 'totalFee', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'routing_peers', recordsPerPage: PAGE_SIZE, sortBy: 'totalFee', sortOrder: SortOrderEnum.DESCENDING };
public routingPeersData: PaymentRelayed[] = []; public routingPeersData: PaymentRelayed[] = [];
public displayedColumns: any[] = []; public displayedColumns: any[] = [];
public RoutingPeersIncoming: any = new MatTableDataSource([]); public routingPeersIncoming: any = new MatTableDataSource([]);
public RoutingPeersOutgoing: any = new MatTableDataSource([]); public routingPeersOutgoing: any = new MatTableDataSource([]);
public pageSize = PAGE_SIZE; public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS; public pageSizeOptions = PAGE_SIZE_OPTIONS;
public screenSize = ''; public screenSize = '';
@ -48,7 +52,7 @@ export class ECLRoutingPeersComponent implements OnInit, AfterViewInit, OnDestro
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -94,22 +98,22 @@ export class ECLRoutingPeersComponent implements OnInit, AfterViewInit, OnDestro
loadRoutingPeersTable(forwardingEvents: PaymentRelayed[]) { loadRoutingPeersTable(forwardingEvents: PaymentRelayed[]) {
if (forwardingEvents.length > 0) { if (forwardingEvents.length > 0) {
const results = this.groupRoutingPeers(forwardingEvents); const results = this.groupRoutingPeers(forwardingEvents);
this.RoutingPeersIncoming = new MatTableDataSource<RoutingPeers>(results[0]); this.routingPeersIncoming = new MatTableDataSource<RoutingPeers>(results[0]);
this.RoutingPeersIncoming.sort = this.sortIn; this.routingPeersIncoming.sort = this.sortIn;
this.RoutingPeersIncoming.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.routingPeersIncoming.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.RoutingPeersIncoming.filterPredicate = (rpIn: RoutingPeers, fltr: string) => JSON.stringify(rpIn).toLowerCase().includes(fltr); this.routingPeersIncoming.filterPredicate = (rpIn: RoutingPeers, fltr: string) => JSON.stringify(rpIn).toLowerCase().includes(fltr);
this.RoutingPeersIncoming.paginator = this.paginatorIn; this.routingPeersIncoming.paginator = this.paginatorIn;
this.logger.info(this.RoutingPeersIncoming); this.logger.info(this.routingPeersIncoming);
this.RoutingPeersOutgoing = new MatTableDataSource<RoutingPeers>(results[1]); this.routingPeersOutgoing = new MatTableDataSource<RoutingPeers>(results[1]);
this.RoutingPeersOutgoing.sort = this.sortOut; this.routingPeersOutgoing.sort = this.sortOut;
this.RoutingPeersOutgoing.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.routingPeersOutgoing.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.RoutingPeersOutgoing.filterPredicate = (rpOut: RoutingPeers, fltr: string) => JSON.stringify(rpOut).toLowerCase().includes(fltr); this.routingPeersOutgoing.filterPredicate = (rpOut: RoutingPeers, fltr: string) => JSON.stringify(rpOut).toLowerCase().includes(fltr);
this.RoutingPeersOutgoing.paginator = this.paginatorOut; this.routingPeersOutgoing.paginator = this.paginatorOut;
this.logger.info(this.RoutingPeersOutgoing); this.logger.info(this.routingPeersOutgoing);
} else { } else {
// To reset table after other Forwarding history calls // To reset table after other Forwarding history calls
this.RoutingPeersIncoming = new MatTableDataSource<RoutingPeers>([]); this.routingPeersIncoming = new MatTableDataSource<RoutingPeers>([]);
this.RoutingPeersOutgoing = new MatTableDataSource<RoutingPeers>([]); this.routingPeersOutgoing = new MatTableDataSource<RoutingPeers>([]);
} }
this.applyIncomingFilter(); this.applyIncomingFilter();
this.applyOutgoingFilter(); this.applyOutgoingFilter();
@ -140,11 +144,11 @@ export class ECLRoutingPeersComponent implements OnInit, AfterViewInit, OnDestro
} }
applyIncomingFilter() { applyIncomingFilter() {
this.RoutingPeersIncoming.filter = this.filterIn.toLowerCase(); this.routingPeersIncoming.filter = this.filterIn.toLowerCase();
} }
applyOutgoingFilter() { applyOutgoingFilter() {
this.RoutingPeersOutgoing.filter = this.filterOut.toLowerCase(); this.routingPeersOutgoing.filter = this.filterOut.toLowerCase();
} }
ngOnDestroy() { ngOnDestroy() {

@ -23,9 +23,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Invoices History</span> <span class="page-title">Invoices History</span>
</div> </div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -53,7 +60,7 @@
<ng-container matColumnDef="nodeId"> <ng-container matColumnDef="nodeId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Node ID</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.nodeId}}</span> <span class="ellipsis-child">{{invoice?.nodeId}}</span>
</div> </div>
</td> </td>
@ -61,7 +68,7 @@
<ng-container matColumnDef="description"> <ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.description}}</span> <span class="ellipsis-child">{{invoice?.description}}</span>
</div> </div>
</td> </td>
@ -69,7 +76,7 @@
<ng-container matColumnDef="paymentHash"> <ng-container matColumnDef="paymentHash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.paymentHash}}</span> <span class="ellipsis-child">{{invoice?.paymentHash}}</span>
</div> </div>
</td> </td>

@ -9,7 +9,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, ECLActions, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, ECLActions, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { SelNodeChild } from '../../../shared/models/RTLconfig'; import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { GetInfo, Invoice } from '../../../shared/models/eclModels'; import { GetInfo, Invoice } from '../../../shared/models/eclModels';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
@ -23,7 +23,8 @@ import { RTLState } from '../../../store/rtl.state';
import { openAlert } from '../../../store/rtl.actions'; import { openAlert } from '../../../store/rtl.actions';
import { createInvoice, invoiceLookup } from '../../store/ecl.actions'; import { createInvoice, invoiceLookup } from '../../store/ecl.actions';
import { eclNodeInformation, eclNodeSettings, eclPageSettings, invoices } from '../../store/ecl.selector'; import { eclNodeInformation, eclNodeSettings, eclPageSettings, invoices } from '../../store/ecl.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-ecl-lightning-invoices', selector: 'rtl-ecl-lightning-invoices',
@ -39,6 +40,8 @@ export class ECLLightningInvoicesComponent implements OnInit, AfterViewInit, OnD
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
faHistory = faHistory; faHistory = faHistory;
public nodePageDefs = ECL_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'transactions'; public PAGE_ID = 'transactions';
public tableSetting: TableSetting = { tableId: 'invoices', recordsPerPage: PAGE_SIZE, sortBy: 'expiresAt', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'invoices', recordsPerPage: PAGE_SIZE, sortBy: 'expiresAt', sortOrder: SortOrderEnum.DESCENDING };
@ -64,7 +67,7 @@ export class ECLLightningInvoicesComponent implements OnInit, AfterViewInit, OnD
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private decimalPipe: DecimalPipe, private commonService: CommonService, private datePipe: DatePipe, private actions: Actions) { constructor(private logger: LoggerService, private store: Store<RTLState>, private decimalPipe: DecimalPipe, private commonService: CommonService, private datePipe: DatePipe, private actions: Actions, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -174,16 +177,52 @@ export class ECLLightningInvoicesComponent implements OnInit, AfterViewInit, OnD
this.invoiceJSONArr = this.invoiceJSONArr?.map((invoice) => ((invoice.paymentHash === newInvoice.paymentHash) ? newInvoice : invoice)); this.invoiceJSONArr = this.invoiceJSONArr?.map((invoice) => ((invoice.paymentHash === newInvoice.paymentHash) ? newInvoice : invoice));
} }
applyFilter() {
this.invoices.filter = this.selFilter.trim().toLowerCase();
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
// this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadInvoicesTable(invs: Invoice[]) { loadInvoicesTable(invs: Invoice[]) {
this.invoices = invs ? new MatTableDataSource<Invoice>([...invs]) : new MatTableDataSource<Invoice>([]); this.invoices = invs ? new MatTableDataSource<Invoice>([...invs]) : new MatTableDataSource<Invoice>([]);
this.invoices.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.invoices.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.invoices.sort = this.sort; this.invoices.sort = this.sort;
this.invoices.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.invoices.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.invoices.paginator = this.paginator; this.invoices.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
} }
@ -194,10 +233,6 @@ export class ECLLightningInvoicesComponent implements OnInit, AfterViewInit, OnD
this.invoiceValueHint = ''; this.invoiceValueHint = '';
} }
applyFilter() {
this.invoices.filter = this.selFilter.trim().toLowerCase();
}
onInvoiceValueChange() { onInvoiceValueChange() {
if (this.selNode && this.selNode.fiatConversion && this.invoiceValue && this.invoiceValue > 99) { if (this.selNode && this.selNode.fiatConversion && this.invoiceValue && this.invoiceValue > 99) {
this.invoiceValueHint = ''; this.invoiceValueHint = '';

@ -19,9 +19,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Payments History</span> <span class="page-title">Payments History</span>
</div> </div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start start"> <div fxLayout="row" fxLayoutAlign="start start">
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="colWidth" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="colWidth" class="table-container">
@ -34,7 +41,7 @@
<ng-container matColumnDef="id"> <ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.id}}</span> <span class="ellipsis-child">{{payment?.id}}</span>
</div> </div>
</td> </td>
@ -42,7 +49,7 @@
<ng-container matColumnDef="recipientNodeId"> <ng-container matColumnDef="recipientNodeId">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Destination Node ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Destination Node ID</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.recipientNodeId}}</span> <span class="ellipsis-child">{{payment?.recipientNodeId}}</span>
</div> </div>
</td> </td>
@ -50,7 +57,7 @@
<ng-container matColumnDef="recipientNodeAlias"> <ng-container matColumnDef="recipientNodeAlias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Destination</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Destination</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.recipientNodeAlias}}</span> <span class="ellipsis-child">{{payment?.recipientNodeAlias}}</span>
</div> </div>
</td> </td>
@ -58,7 +65,7 @@
<ng-container matColumnDef="description"> <ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.description}}</span> <span class="ellipsis-child">{{payment?.description}}</span>
</div> </div>
</td> </td>
@ -66,7 +73,7 @@
<ng-container matColumnDef="paymentHash"> <ng-container matColumnDef="paymentHash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.paymentHash}}</span> <span class="ellipsis-child">{{payment?.paymentHash}}</span>
</div> </div>
</td> </td>
@ -74,7 +81,7 @@
<ng-container matColumnDef="paymentPreimage"> <ng-container matColumnDef="paymentPreimage">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Preimage</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Preimage</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.paymentPreimage}}</span> <span class="ellipsis-child">{{payment?.paymentPreimage}}</span>
</div> </div>
</td> </td>
@ -119,12 +126,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_id"> <ng-container matColumnDef="group_id">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.id}}</span> <span class="ellipsis-child">{{payment?.id}}</span>
</div> </div>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
<span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span"> <span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span">
<span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{part.id}}</span> <span class="ellipsis-child">{{part.id}}</span>
</span> </span>
</span> </span>
@ -133,12 +140,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_recipientNodeId"> <ng-container matColumnDef="group_recipientNodeId">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.recipientNodeId}}</span> <span class="ellipsis-child">{{payment?.recipientNodeId}}</span>
</div> </div>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
<span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span"> <span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span">
<span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{part.toChannelId}}</span> <span class="ellipsis-child">{{part.toChannelId}}</span>
</span> </span>
</span> </span>
@ -147,12 +154,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_recipientNodeAlias"> <ng-container matColumnDef="group_recipientNodeAlias">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.recipientNodeAlias}}</span> <span class="ellipsis-child">{{payment?.recipientNodeAlias}}</span>
</div> </div>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
<span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span"> <span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span">
<span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{part.toChannelAlias}}</span> <span class="ellipsis-child">{{part.toChannelAlias}}</span>
</span> </span>
</span> </span>
@ -171,12 +178,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_description"> <ng-container matColumnDef="group_description">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.description}}</span> <span class="ellipsis-child">{{payment?.description}}</span>
</div> </div>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
<span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span"> <span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span">
<span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">Fee Paid: {{part.feesPaid | number:'1.0-0'}} (Sats)</span> <span class="ellipsis-child">Fee Paid: {{part.feesPaid | number:'1.0-0'}} (Sats)</span>
</span> </span>
</span> </span>
@ -185,12 +192,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_paymentHash"> <ng-container matColumnDef="group_paymentHash">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.paymentHash}}</span> <span class="ellipsis-child">{{payment?.paymentHash}}</span>
</div> </div>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
<span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span"> <span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span">
<span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">Fee Paid: {{part.feesPaid | number:'1.0-0'}} (Sats)</span> <span class="ellipsis-child">Fee Paid: {{part.feesPaid | number:'1.0-0'}} (Sats)</span>
</span> </span>
</span> </span>
@ -199,12 +206,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_paymentPreimage"> <ng-container matColumnDef="group_paymentPreimage">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.paymentPreimage}}</span> <span class="ellipsis-child">{{payment?.paymentPreimage}}</span>
</div> </div>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
<span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span"> <span *ngFor="let part of payment?.parts" fxLayoutAlign="start center" class="part-row-span">
<span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayoutAlign="start center" class="ellipsis-parent part-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">Fee Paid: {{part.feesPaid | number:'1.0-0'}} (Sats)</span> <span class="ellipsis-child">Fee Paid: {{part.feesPaid | number:'1.0-0'}} (Sats)</span>
</span> </span>
</span> </span>

@ -9,7 +9,7 @@ import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { GetInfo, PayRequest, PaymentSent, PaymentSentPart, Payments } from '../../../shared/models/eclModels'; import { GetInfo, PayRequest, PaymentSent, PaymentSentPart, Payments } from '../../../shared/models/eclModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, APICallStatusEnum, SortOrderEnum, ECL_DEFAULT_PAGE_SETTINGS, ECL_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -24,7 +24,8 @@ import { RTLState } from '../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../store/rtl.actions';
import { sendPayment } from '../../store/ecl.actions'; import { sendPayment } from '../../store/ecl.actions';
import { eclNodeInformation, eclNodeSettings, eclPageSettings, payments } from '../../store/ecl.selector'; import { eclNodeInformation, eclNodeSettings, eclPageSettings, payments } from '../../store/ecl.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-ecl-lightning-payments', selector: 'rtl-ecl-lightning-payments',
@ -40,6 +41,8 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
@ViewChild('sendPaymentForm', { static: false }) form; @ViewChild('sendPaymentForm', { static: false }) form;
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = ECL_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'transactions'; public PAGE_ID = 'transactions';
public tableSetting: TableSetting = { tableId: 'payments', recordsPerPage: PAGE_SIZE, sortBy: 'firstPartTimestamp', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'payments', recordsPerPage: PAGE_SIZE, sortBy: 'firstPartTimestamp', sortOrder: SortOrderEnum.DESCENDING };
@ -64,7 +67,7 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private decimalPipe: DecimalPipe, private dataService: DataService, private datePipe: DatePipe) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private decimalPipe: DecimalPipe, private dataService: DataService, private datePipe: DatePipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -118,6 +121,45 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
} }
} }
applyFilter() {
this.payments.filter = this.selFilter.trim().toLowerCase();
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.payments.filterPredicate = (rowData: PaymentSent, fltr: string) => {
const newRowData = ((rowData.firstPartTimestamp) ? this.datePipe.transform(new Date(rowData.firstPartTimestamp), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
// this.payments.filterPredicate = (rowData: PaymentSent, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadPaymentsTable(payms: PaymentSent[]) { loadPaymentsTable(payms: PaymentSent[]) {
this.payments = payms ? new MatTableDataSource<PaymentSent>([...payms]) : new MatTableDataSource<PaymentSent>([]); this.payments = payms ? new MatTableDataSource<PaymentSent>([...payms]) : new MatTableDataSource<PaymentSent>([]);
this.payments.sort = this.sort; this.payments.sort = this.sort;
@ -144,11 +186,8 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
} }
}; };
this.payments.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.payments.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.payments.filterPredicate = (rowData: PaymentSent, fltr: string) => {
const newRowData = ((rowData.firstPartTimestamp) ? this.datePipe.transform(new Date(rowData.firstPartTimestamp), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.payments.paginator = this.paginator; this.payments.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
} }
@ -363,10 +402,6 @@ export class ECLLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
})); }));
} }
applyFilter() {
this.payments.filter = this.selFilter.trim().toLowerCase();
}
onDownloadCSV() { onDownloadCSV() {
if (this.payments.data && this.payments.data.length > 0) { if (this.payments.data && this.payments.data.length > 0) {
const paymentsDataCopy: PaymentSent[] = JSON.parse(JSON.stringify(this.payments.data)); const paymentsDataCopy: PaymentSent[] = JSON.parse(JSON.stringify(this.payments.data));

@ -19,9 +19,12 @@
<fa-icon [icon]="faArchive" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faArchive" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Backups</span> <span class="page-title">Backups</span>
</div> </div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <div fxFlex="49"></div>
</mat-form-field> <mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>

@ -14,9 +14,12 @@
</div> </div>
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container mt-2"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container mt-2">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <div fxFlex="49"></div>
</mat-form-field> <mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="row" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>

@ -33,7 +33,7 @@
<ng-container matColumnDef="pubkey_alias"> <ng-container matColumnDef="pubkey_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th>
<td mat-cell *matCellDef="let hop"> <td mat-cell *matCellDef="let hop">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{hop?.pubkey_alias}}</span> <span class="ellipsis-child">{{hop?.pubkey_alias}}</span>
</div> </div>
</td> </td>
@ -41,7 +41,7 @@
<ng-container matColumnDef="pub_key"> <ng-container matColumnDef="pub_key">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Pubkey</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Pubkey</th>
<td mat-cell *matCellDef="let hop"> <td mat-cell *matCellDef="let hop">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{hop?.pub_key}}</span> <span class="ellipsis-child">{{hop?.pub_key}}</span>
</div> </div>
</td> </td>
@ -49,7 +49,7 @@
<ng-container matColumnDef="chan_id"> <ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let hop"> <td mat-cell *matCellDef="let hop">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{hop?.chan_id}}</span> <span class="ellipsis-child">{{hop?.chan_id}}</span>
</div> </div>
</td> </td>

@ -1,8 +1,15 @@
<div fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch" class="padding-gap-x-large"> <div fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch" class="padding-gap-x-large">
<div fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign.gt-xs="end stretch" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign.gt-xs="end stretch" fxLayoutAlign="start stretch" class="page-sub-title-container">
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start start"> <div fxLayout="row" fxLayoutAlign="start start">
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container">
@ -15,7 +22,7 @@
<ng-container matColumnDef="label"> <ng-container matColumnDef="label">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Label</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Label</th>
<td mat-cell *matCellDef="let transaction"> <td mat-cell *matCellDef="let transaction">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{transaction?.label}}</span> <span class="ellipsis-child">{{transaction?.label}}</span>
</div> </div>
</td> </td>
@ -23,7 +30,7 @@
<ng-container matColumnDef="block_hash"> <ng-container matColumnDef="block_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Block Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Block Hash</th>
<td mat-cell *matCellDef="let transaction"> <td mat-cell *matCellDef="let transaction">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{transaction?.block_hash}}</span> <span class="ellipsis-child">{{transaction?.block_hash}}</span>
</div> </div>
</td> </td>
@ -31,7 +38,7 @@
<ng-container matColumnDef="tx_hash"> <ng-container matColumnDef="tx_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Transaction Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Transaction Hash</th>
<td mat-cell *matCellDef="let transaction"> <td mat-cell *matCellDef="let transaction">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{transaction?.tx_hash}}</span> <span class="ellipsis-child">{{transaction?.tx_hash}}</span>
</div> </div>
</td> </td>

@ -9,7 +9,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { Transaction } from '../../../../shared/models/lndModels'; import { Transaction } from '../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS } from '../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../../shared/services/logger.service'; import { LoggerService } from '../../../../shared/services/logger.service';
import { CommonService } from '../../../../shared/services/common.service'; import { CommonService } from '../../../../shared/services/common.service';
@ -17,7 +17,8 @@ import { CommonService } from '../../../../shared/services/common.service';
import { RTLState } from '../../../../store/rtl.state'; import { RTLState } from '../../../../store/rtl.state';
import { openAlert } from '../../../../store/rtl.actions'; import { openAlert } from '../../../../store/rtl.actions';
import { lndPageSettings, transactions } from '../../../store/lnd.selector'; import { lndPageSettings, transactions } from '../../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-on-chain-transaction-history', selector: 'rtl-on-chain-transaction-history',
@ -31,6 +32,8 @@ export class OnChainTransactionHistoryComponent implements OnInit, OnChanges, On
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'on_chain'; public PAGE_ID = 'on_chain';
public tableSetting: TableSetting = { tableId: 'transactions', recordsPerPage: PAGE_SIZE, sortBy: 'time_stamp', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'transactions', recordsPerPage: PAGE_SIZE, sortBy: 'time_stamp', sortOrder: SortOrderEnum.DESCENDING };
@ -48,7 +51,7 @@ export class OnChainTransactionHistoryComponent implements OnInit, OnChanges, On
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -92,10 +95,6 @@ export class OnChainTransactionHistoryComponent implements OnInit, OnChanges, On
} }
} }
applyFilter() {
this.listTransactions.filter = this.selFilter.trim().toLowerCase();
}
onTransactionClick(selTransaction: Transaction) { onTransactionClick(selTransaction: Transaction) {
const reorderedTransactions = [ const reorderedTransactions = [
[{ key: 'block_hash', value: selTransaction.block_hash, title: 'Block Hash', width: 100 }], [{ key: 'block_hash', value: selTransaction.block_hash, title: 'Block Hash', width: 100 }],
@ -120,16 +119,52 @@ export class OnChainTransactionHistoryComponent implements OnInit, OnChanges, On
})); }));
} }
applyFilter() {
this.listTransactions.filter = this.selFilter.trim().toLowerCase();
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.listTransactions.filterPredicate = (rowData: Transaction, fltr: string) => {
const newRowData = ((rowData.time_stamp) ? this.datePipe.transform(new Date(rowData.time_stamp * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
// this.listTransactions.filterPredicate = (rowData: Transaction, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case 'time_stamp':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadTransactionsTable(transactions) { loadTransactionsTable(transactions) {
this.listTransactions = new MatTableDataSource<Transaction>([...transactions]); this.listTransactions = new MatTableDataSource<Transaction>([...transactions]);
this.listTransactions.sort = this.sort; this.listTransactions.sort = this.sort;
this.listTransactions.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.listTransactions.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.listTransactions.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.listTransactions.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.listTransactions.filterPredicate = (rowData: Transaction, fltr: string) => {
const newRowData = ((rowData.time_stamp) ? this.datePipe.transform(new Date(rowData.time_stamp * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.listTransactions.paginator = this.paginator; this.listTransactions.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.listTransactions); this.logger.info(this.listTransactions);
} }

@ -7,7 +7,7 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="49"> <mat-form-field fxFlex="49">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
@ -26,7 +26,7 @@
<ng-container matColumnDef="tx_id"> <ng-container matColumnDef="tx_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Transaction ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Transaction ID</th>
<td mat-cell *matCellDef="let utxo"> <td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{utxo.outpoint.txid_str}}</span> <span class="ellipsis-child">{{utxo.outpoint.txid_str}}</span>
</span> </span>
</td> </td>
@ -40,7 +40,7 @@
<ng-container matColumnDef="label"> <ng-container matColumnDef="label">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Label</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Label</th>
<td mat-cell *matCellDef="let utxo"> <td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{utxo.label}}</span> <span class="ellipsis-child">{{utxo.label}}</span>
</span> </span>
</td> </td>
@ -56,7 +56,7 @@
<ng-container matColumnDef="address"> <ng-container matColumnDef="address">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th>
<td mat-cell *matCellDef="let utxo"> <td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{utxo?.address}}</span> <span class="ellipsis-child">{{utxo?.address}}</span>
</span> </span>
</td> </td>

@ -111,50 +111,50 @@ export class OnChainUTXOsComponent implements OnInit, OnChanges, OnDestroy {
} }
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'All';
}
applyFilter() { applyFilter() {
this.listUTXOs.filter = this.selFilter.trim().toLowerCase(); this.listUTXOs.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() { setFilterPredicate() {
this.listUTXOs.filterPredicate = (utxo: UTXO, fltr: string) => { this.listUTXOs.filterPredicate = (rowData: UTXO, fltr: string) => {
let newUTXO = ''; let rowToFilter = '';
switch (this.selFilterBy) { switch (this.selFilterBy) {
case 'all': case 'all':
for (let i = 0; i < this.displayedColumns.length - 1; i++) { for (let i = 0; i < this.displayedColumns.length - 1; i++) {
newUTXO = newUTXO + ( rowToFilter = rowToFilter + (
(this.displayedColumns[i] === 'tx_id') ? (this.displayedColumns[i] === 'tx_id') ?
(utxo.outpoint && utxo.outpoint.txid_str ? utxo.outpoint.txid_str.toLowerCase() : '') : (rowData.outpoint && rowData.outpoint.txid_str ? rowData.outpoint.txid_str.toLowerCase() : '') :
(this.displayedColumns[i] === 'output') ? (this.displayedColumns[i] === 'output') ?
(utxo.outpoint && utxo.outpoint.output_index ? utxo.outpoint.output_index.toString() : '0') : (rowData.outpoint && rowData.outpoint.output_index ? rowData.outpoint.output_index.toString() : '0') :
(this.displayedColumns[i] === 'address_type') ? (this.displayedColumns[i] === 'address_type') ?
(utxo.address_type && this.addressType[utxo.address_type] && this.addressType[utxo.address_type].name ? this.addressType[utxo.address_type].name.toLowerCase() : '') : (rowData.address_type && this.addressType[rowData.address_type] && this.addressType[rowData.address_type].name ? this.addressType[rowData.address_type].name.toLowerCase() : '') :
(utxo[this.displayedColumns[i]] ? utxo[this.displayedColumns[i]].toLowerCase() : '') (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
) + ', '; ) + ', ';
} }
break; break;
case 'tx_id': case 'tx_id':
newUTXO = (utxo.outpoint && utxo.outpoint.txid_str ? utxo.outpoint.txid_str.toLowerCase() : ''); rowToFilter = (rowData.outpoint && rowData.outpoint.txid_str ? rowData.outpoint.txid_str.toLowerCase() : '');
break; break;
case 'output': case 'output':
newUTXO = (utxo.outpoint && utxo.outpoint.output_index ? utxo.outpoint.output_index.toString() : '0'); rowToFilter = (rowData.outpoint && rowData.outpoint.output_index ? rowData.outpoint.output_index.toString() : '0');
break; break;
case 'address_type': case 'address_type':
newUTXO = (utxo.address_type && this.addressType[utxo.address_type] && this.addressType[utxo.address_type].name ? this.addressType[utxo.address_type].name.toLowerCase() : ''); rowToFilter = (rowData.address_type && this.addressType[rowData.address_type] && this.addressType[rowData.address_type].name ? this.addressType[rowData.address_type].name.toLowerCase() : '');
break; break;
default: default:
newUTXO = (utxo[this.selFilterBy] ? utxo[this.selFilterBy].toLowerCase() : ''); rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
break; break;
} }
return newUTXO.includes(fltr); return rowToFilter.includes(fltr);
}; };
} }

@ -1,9 +1,16 @@
<div fxLayout="column" class="padding-gap"> <div fxLayout="column" class="padding-gap">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>

@ -8,7 +8,7 @@ import { MatTableDataSource } from '@angular/material/table';
import { ChannelInformationComponent } from '../../channel-information-modal/channel-information.component'; import { ChannelInformationComponent } from '../../channel-information-modal/channel-information.component';
import { Channel, ChannelHTLC, ChannelsSummary, LightningBalance } from '../../../../../shared/models/lndModels'; import { Channel, ChannelHTLC, ChannelsSummary, LightningBalance } from '../../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../../../shared/services/logger.service'; import { LoggerService } from '../../../../../shared/services/logger.service';
import { CommonService } from '../../../../../shared/services/common.service'; import { CommonService } from '../../../../../shared/services/common.service';
@ -16,7 +16,8 @@ import { CommonService } from '../../../../../shared/services/common.service';
import { openAlert } from '../../../../../store/rtl.actions'; import { openAlert } from '../../../../../store/rtl.actions';
import { RTLState } from '../../../../../store/rtl.state'; import { RTLState } from '../../../../../store/rtl.state';
import { channels, lndPageSettings } from '../../../../store/lnd.selector'; import { channels, lndPageSettings } from '../../../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-channel-active-htlcs-table', selector: 'rtl-channel-active-htlcs-table',
@ -30,6 +31,8 @@ export class ChannelActiveHTLCsTableComponent implements OnInit, AfterViewInit,
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'active_HTLCs', recordsPerPage: PAGE_SIZE, sortBy: 'expiration_height', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'active_HTLCs', recordsPerPage: PAGE_SIZE, sortBy: 'expiration_height', sortOrder: SortOrderEnum.DESCENDING };
@ -47,7 +50,7 @@ export class ChannelActiveHTLCsTableComponent implements OnInit, AfterViewInit,
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -122,6 +125,42 @@ export class ChannelActiveHTLCsTableComponent implements OnInit, AfterViewInit,
this.channels.filter = this.selFilter.trim().toLowerCase(); this.channels.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = (channel.remote_alias ? channel.remote_alias.toLowerCase() : '') +
channel.pending_htlcs?.map((htlc) => JSON.stringify(htlc) + (htlc.incoming ? 'yes' : 'no'));
return newChannel.includes(fltr);
};
// this.channels.filterPredicate = (rowData: Channel, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadHTLCsTable(channels: Channel[]) { loadHTLCsTable(channels: Channel[]) {
this.channels = (channels) ? new MatTableDataSource<Channel>([...channels]) : new MatTableDataSource([]); this.channels = (channels) ? new MatTableDataSource<Channel>([...channels]) : new MatTableDataSource([]);
this.channels.sort = this.sort; this.channels.sort = this.sort;
@ -149,11 +188,7 @@ export class ChannelActiveHTLCsTableComponent implements OnInit, AfterViewInit,
}; };
this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.channels.paginator = this.paginator; this.channels.paginator = this.paginator;
this.channels.filterPredicate = (channel: Channel, fltr: string) => { this.setFilterPredicate();
const newChannel = (channel.remote_alias ? channel.remote_alias.toLowerCase() : '') +
channel.pending_htlcs?.map((htlc) => JSON.stringify(htlc) + (htlc.incoming ? 'yes' : 'no'));
return newChannel.includes(fltr);
};
this.applyFilter(); this.applyFilter();
} }

@ -1,9 +1,16 @@
<div fxLayout="column"> <div fxLayout="column">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -20,7 +27,7 @@
<ng-container matColumnDef="remote_alias"> <ng-container matColumnDef="remote_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.remote_alias}}</span> <span class="ellipsis-child">{{channel?.remote_alias}}</span>
</div> </div>
</td> </td>
@ -28,7 +35,7 @@
<ng-container matColumnDef="remote_pubkey"> <ng-container matColumnDef="remote_pubkey">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.remote_pubkey}}</span> <span class="ellipsis-child">{{channel?.remote_pubkey}}</span>
</div> </div>
</td> </td>
@ -36,7 +43,7 @@
<ng-container matColumnDef="channel_point"> <ng-container matColumnDef="channel_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.channel_point}}</span> <span class="ellipsis-child">{{channel?.channel_point}}</span>
</div> </div>
</td> </td>
@ -44,7 +51,7 @@
<ng-container matColumnDef="chan_id"> <ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.chan_id}}</span> <span class="ellipsis-child">{{channel?.chan_id}}</span>
</div> </div>
</td> </td>
@ -52,7 +59,7 @@
<ng-container matColumnDef="closing_tx_hash"> <ng-container matColumnDef="closing_tx_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Closing Tx Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Closing Tx Hash</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.closing_tx_hash}}</span> <span class="ellipsis-child">{{channel?.closing_tx_hash}}</span>
</div> </div>
</td> </td>
@ -60,7 +67,7 @@
<ng-container matColumnDef="chain_hash"> <ng-container matColumnDef="chain_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Chain Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Chain Hash</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel?.chain_hash}}</span> <span class="ellipsis-child">{{channel?.chain_hash}}</span>
</div> </div>
</td> </td>

@ -8,7 +8,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { ClosedChannel } from '../../../../../shared/models/lndModels'; import { ClosedChannel } from '../../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CHANNEL_CLOSURE_TYPE, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CHANNEL_CLOSURE_TYPE, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../../../shared/services/logger.service'; import { LoggerService } from '../../../../../shared/services/logger.service';
import { CommonService } from '../../../../../shared/services/common.service'; import { CommonService } from '../../../../../shared/services/common.service';
@ -16,7 +16,8 @@ import { CommonService } from '../../../../../shared/services/common.service';
import { openAlert } from '../../../../../store/rtl.actions'; import { openAlert } from '../../../../../store/rtl.actions';
import { RTLState } from '../../../../../store/rtl.state'; import { RTLState } from '../../../../../store/rtl.state';
import { closedChannels, lndPageSettings } from '../../../../store/lnd.selector'; import { closedChannels, lndPageSettings } from '../../../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-channel-closed-table', selector: 'rtl-channel-closed-table',
@ -30,6 +31,8 @@ export class ChannelClosedTableComponent implements OnInit, AfterViewInit, OnDes
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'closed', recordsPerPage: PAGE_SIZE, sortBy: 'close_type', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'closed', recordsPerPage: PAGE_SIZE, sortBy: 'close_type', sortOrder: SortOrderEnum.DESCENDING };
@ -48,7 +51,7 @@ export class ChannelClosedTableComponent implements OnInit, AfterViewInit, OnDes
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private commonService: CommonService) { constructor(private logger: LoggerService, private store: Store<RTLState>, private commonService: CommonService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -96,6 +99,38 @@ export class ChannelClosedTableComponent implements OnInit, AfterViewInit, OnDes
this.closedChannels.filter = this.selFilter.trim().toLowerCase(); this.closedChannels.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.closedChannels.filterPredicate = (channel: ClosedChannel, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr);
// this.closedChannels.filterPredicate = (rowData: ClosedChannel, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
onClosedChannelClick(selChannel: ClosedChannel, event: any) { onClosedChannelClick(selChannel: ClosedChannel, event: any) {
const reorderedChannel = [ const reorderedChannel = [
[{ key: 'close_type', value: this.channelClosureType[selChannel.close_type].name, title: 'Close Type', width: 30, type: DataTypeEnum.STRING }, [{ key: 'close_type', value: this.channelClosureType[selChannel.close_type].name, title: 'Close Type', width: 30, type: DataTypeEnum.STRING },
@ -125,8 +160,8 @@ export class ChannelClosedTableComponent implements OnInit, AfterViewInit, OnDes
this.closedChannels.sort = this.sort; this.closedChannels.sort = this.sort;
this.closedChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.closedChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.closedChannels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.closedChannels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.closedChannels.filterPredicate = (channel: ClosedChannel, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr);
this.closedChannels.paginator = this.paginator; this.closedChannels.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.closedChannels); this.logger.info(this.closedChannels);
} }

@ -1,9 +1,16 @@
<div fxLayout="column" class="padding-gap-x"> <div fxLayout="column" class="padding-gap-x">
<div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -25,7 +32,7 @@
<ng-container matColumnDef="remote_alias"> <ng-container matColumnDef="remote_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.remote_alias || channel.remote_pubkey}}</span> <span class="ellipsis-child">{{channel.remote_alias || channel.remote_pubkey}}</span>
</div> </div>
</td> </td>
@ -33,7 +40,7 @@
<ng-container matColumnDef="remote_pubkey"> <ng-container matColumnDef="remote_pubkey">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.remote_pubkey}}</span> <span class="ellipsis-child">{{channel.remote_pubkey}}</span>
</div> </div>
</td> </td>
@ -41,7 +48,7 @@
<ng-container matColumnDef="channel_point"> <ng-container matColumnDef="channel_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel_point}}</span> <span class="ellipsis-child">{{channel.channel_point}}</span>
</div> </div>
</td> </td>
@ -49,7 +56,7 @@
<ng-container matColumnDef="chan_id"> <ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.chan_id}}</span> <span class="ellipsis-child">{{channel.chan_id}}</span>
</div> </div>
</td> </td>

@ -12,7 +12,7 @@ import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { ChannelInformationComponent } from '../../channel-information-modal/channel-information.component'; import { ChannelInformationComponent } from '../../channel-information-modal/channel-information.component';
import { SelNodeChild } from '../../../../../shared/models/RTLconfig'; import { SelNodeChild } from '../../../../../shared/models/RTLconfig';
import { BlockchainBalance, Channel, ChannelsSummary, GetInfo, LightningBalance, Peer } from '../../../../../shared/models/lndModels'; import { BlockchainBalance, Channel, ChannelsSummary, GetInfo, LightningBalance, Peer } from '../../../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, UserPersonaEnum, LoopTypeEnum, APICallStatusEnum, UI_MESSAGES, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS } from '../../../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, UserPersonaEnum, LoopTypeEnum, APICallStatusEnum, UI_MESSAGES, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../../../shared/services/logger.service'; import { LoggerService } from '../../../../../shared/services/logger.service';
import { LoopService } from '../../../../../shared/services/loop.service'; import { LoopService } from '../../../../../shared/services/loop.service';
@ -27,7 +27,8 @@ import { RTLState } from '../../../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../../../store/rtl.actions';
import { channelLookup, fetchChannels, updateChannel } from '../../../../store/lnd.actions'; import { channelLookup, fetchChannels, updateChannel } from '../../../../store/lnd.actions';
import { blockchainBalance, channels, lndNodeInformation, lndNodeSettings, lndPageSettings, peers } from '../../../../store/lnd.selector'; import { blockchainBalance, channels, lndNodeInformation, lndNodeSettings, lndPageSettings, peers } from '../../../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-channel-open-table', selector: 'rtl-channel-open-table',
@ -41,6 +42,8 @@ export class ChannelOpenTableComponent implements OnInit, AfterViewInit, OnDestr
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'open', recordsPerPage: PAGE_SIZE, sortBy: 'balancedness', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'open', recordsPerPage: PAGE_SIZE, sortBy: 'balancedness', sortOrder: SortOrderEnum.DESCENDING };
@ -68,7 +71,16 @@ export class ChannelOpenTableComponent implements OnInit, AfterViewInit, OnDestr
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private lndEffects: LNDEffects, private commonService: CommonService, private rtlEffects: RTLEffects, private decimalPipe: DecimalPipe, private loopService: LoopService, private router: Router) { constructor(
private logger: LoggerService,
private store: Store<RTLState>,
private lndEffects: LNDEffects,
private commonService: CommonService,
private rtlEffects: RTLEffects,
private decimalPipe: DecimalPipe,
private loopService: LoopService,
private router: Router,
private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
this.selFilter = this.router.getCurrentNavigation()?.extras?.state?.filter ? this.router.getCurrentNavigation()?.extras?.state?.filter : ''; this.selFilter = this.router.getCurrentNavigation()?.extras?.state?.filter ? this.router.getCurrentNavigation()?.extras?.state?.filter : '';
} }
@ -283,10 +295,6 @@ export class ChannelOpenTableComponent implements OnInit, AfterViewInit, OnDestr
})); }));
} }
applyFilter() {
this.channels.filter = this.selFilter.trim().toLowerCase();
}
onChannelClick(selChannel: Channel, event: any) { onChannelClick(selChannel: Channel, event: any) {
this.store.dispatch(openAlert({ this.store.dispatch(openAlert({
payload: { payload: {
@ -299,9 +307,16 @@ export class ChannelOpenTableComponent implements OnInit, AfterViewInit, OnDestr
})); }));
} }
loadChannelsTable(mychannels: Channel[]) { applyFilter() {
mychannels.sort((a, b) => ((a.active === b.active) ? 0 : ((b.active) ? 1 : -1))); this.channels.filter = this.selFilter.trim().toLowerCase();
this.channels = new MatTableDataSource<Channel>([...mychannels]); }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.channels.filterPredicate = (channel: Channel, fltr: string) => { this.channels.filterPredicate = (channel: Channel, fltr: string) => {
const newChannel = ((channel.active) ? 'active' : 'inactive') + (channel.chan_id ? channel.chan_id.toLowerCase() : '') + const newChannel = ((channel.active) ? 'active' : 'inactive') + (channel.chan_id ? channel.chan_id.toLowerCase() : '') +
(channel.remote_pubkey ? channel.remote_pubkey.toLowerCase() : '') + (channel.remote_alias ? channel.remote_alias.toLowerCase() : '') + (channel.remote_pubkey ? channel.remote_pubkey.toLowerCase() : '') + (channel.remote_alias ? channel.remote_alias.toLowerCase() : '') +
@ -311,10 +326,38 @@ export class ChannelOpenTableComponent implements OnInit, AfterViewInit, OnDestr
(channel.private ? 'private' : 'public'); (channel.private ? 'private' : 'public');
return newChannel.includes(fltr); return newChannel.includes(fltr);
}; };
// this.channels.filterPredicate = (rowData: Channel, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadChannelsTable(mychannels: Channel[]) {
this.channels = new MatTableDataSource<Channel>([...mychannels]);
this.channels.sort = this.sort; this.channels.sort = this.sort;
this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.channels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.channels.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.channels.paginator = this.paginator; this.channels.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.channels); this.logger.info(this.channels);
} }

@ -12,7 +12,7 @@
<ng-container matColumnDef="remote_alias"> <ng-container matColumnDef="remote_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.remote_alias}}</span> <span class="ellipsis-child">{{channel.channel.remote_alias}}</span>
</div> </div>
</td> </td>
@ -20,7 +20,7 @@
<ng-container matColumnDef="remote_node_pub"> <ng-container matColumnDef="remote_node_pub">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.remote_node_pub}}</span> <span class="ellipsis-child">{{channel.channel.remote_node_pub}}</span>
</div> </div>
</td> </td>
@ -28,7 +28,7 @@
<ng-container matColumnDef="channel_point"> <ng-container matColumnDef="channel_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.channel_point}}</span> <span class="ellipsis-child">{{channel.channel.channel_point}}</span>
</div> </div>
</td> </td>
@ -106,7 +106,7 @@
<ng-container matColumnDef="closing_txid"> <ng-container matColumnDef="closing_txid">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Closing Tx ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Closing Tx ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.closing_txid}}</span> <span class="ellipsis-child">{{channel.closing_txid}}</span>
</div> </div>
</td> </td>
@ -114,7 +114,7 @@
<ng-container matColumnDef="remote_alias"> <ng-container matColumnDef="remote_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.remote_alias}}</span> <span class="ellipsis-child">{{channel.channel.remote_alias}}</span>
</div> </div>
</td> </td>
@ -122,7 +122,7 @@
<ng-container matColumnDef="remote_node_pub"> <ng-container matColumnDef="remote_node_pub">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.remote_node_pub}}</span> <span class="ellipsis-child">{{channel.channel.remote_node_pub}}</span>
</div> </div>
</td> </td>
@ -130,7 +130,7 @@
<ng-container matColumnDef="channel_point"> <ng-container matColumnDef="channel_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.channel_point}}</span> <span class="ellipsis-child">{{channel.channel.channel_point}}</span>
</div> </div>
</td> </td>
@ -202,7 +202,7 @@
<ng-container matColumnDef="closing_txid"> <ng-container matColumnDef="closing_txid">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Closing Tx ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Closing Tx ID</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.closing_txid}}</span> <span class="ellipsis-child">{{channel.closing_txid}}</span>
</div> </div>
</td> </td>
@ -210,7 +210,7 @@
<ng-container matColumnDef="remote_alias"> <ng-container matColumnDef="remote_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.remote_alias}}</span> <span class="ellipsis-child">{{channel.channel.remote_alias}}</span>
</div> </div>
</td> </td>
@ -218,7 +218,7 @@
<ng-container matColumnDef="remote_node_pub"> <ng-container matColumnDef="remote_node_pub">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.remote_node_pub}}</span> <span class="ellipsis-child">{{channel.channel.remote_node_pub}}</span>
</div> </div>
</td> </td>
@ -226,7 +226,7 @@
<ng-container matColumnDef="channel_point"> <ng-container matColumnDef="channel_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.channel_point}}</span> <span class="ellipsis-child">{{channel.channel.channel_point}}</span>
</div> </div>
</td> </td>
@ -282,7 +282,7 @@
<ng-container matColumnDef="remote_alias"> <ng-container matColumnDef="remote_alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.remote_alias}}</span> <span class="ellipsis-child">{{channel.channel.remote_alias}}</span>
</div> </div>
</td> </td>
@ -290,7 +290,7 @@
<ng-container matColumnDef="remote_node_pub"> <ng-container matColumnDef="remote_node_pub">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Pubkey</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.remote_node_pub}}</span> <span class="ellipsis-child">{{channel.channel.remote_node_pub}}</span>
</div> </div>
</td> </td>
@ -298,7 +298,7 @@
<ng-container matColumnDef="channel_point"> <ng-container matColumnDef="channel_point">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel Point</th>
<td mat-cell *matCellDef="let channel"> <td mat-cell *matCellDef="let channel">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{channel.channel.channel_point}}</span> <span class="ellipsis-child">{{channel.channel.channel_point}}</span>
</div> </div>
</td> </td>

@ -28,11 +28,10 @@ export class ChannelPendingTableComponent implements OnInit, AfterViewInit, OnDe
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public openTableSetting: TableSetting = { tableId: 'pending_open', recordsPerPage: PAGE_SIZE, sortBy: 'capacity', sortOrder: SortOrderEnum.DESCENDING }; public openTableSetting: TableSetting = { tableId: 'pending_open', recordsPerPage: PAGE_SIZE, sortBy: 'capacity', sortOrder: SortOrderEnum.DESCENDING };
public forceClosingopenTableSetting: TableSetting = { tableId: 'pending_force_closing', recordsPerPage: PAGE_SIZE, sortBy: 'limbo_balance', sortOrder: SortOrderEnum.DESCENDING }; public forceClosingTableSetting: TableSetting = { tableId: 'pending_force_closing', recordsPerPage: PAGE_SIZE, sortBy: 'limbo_balance', sortOrder: SortOrderEnum.DESCENDING };
public closingOpenTableSetting: TableSetting = { tableId: 'pending_closing', recordsPerPage: PAGE_SIZE, sortBy: 'capacity', sortOrder: SortOrderEnum.DESCENDING }; public closingTableSetting: TableSetting = { tableId: 'pending_closing', recordsPerPage: PAGE_SIZE, sortBy: 'capacity', sortOrder: SortOrderEnum.DESCENDING };
public waitingCloseopenTableSetting: TableSetting = { tableId: 'pending_waiting_close', recordsPerPage: PAGE_SIZE, sortBy: 'limbo_balance', sortOrder: SortOrderEnum.DESCENDING }; public waitingCloseTableSetting: TableSetting = { tableId: 'pending_waiting_close', recordsPerPage: PAGE_SIZE, sortBy: 'limbo_balance', sortOrder: SortOrderEnum.DESCENDING };
public selNode: SelNodeChild | null = {}; public selNode: SelNodeChild | null = {};
public selectedFilter = '';
public information: GetInfo = {}; public information: GetInfo = {};
public pendingChannels: PendingChannels = {}; public pendingChannels: PendingChannels = {};
public displayedOpenColumns: any[] = []; public displayedOpenColumns: any[] = [];
@ -76,30 +75,30 @@ export class ChannelPendingTableComponent implements OnInit, AfterViewInit, OnDe
} }
this.displayedOpenColumns.push('actions'); this.displayedOpenColumns.push('actions');
this.logger.info(this.displayedOpenColumns); this.logger.info(this.displayedOpenColumns);
this.forceClosingopenTableSetting = settings.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.forceClosingopenTableSetting.tableId) || this.forceClosingTableSetting = settings.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.forceClosingTableSetting.tableId) ||
LND_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.forceClosingopenTableSetting.tableId)!; LND_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.forceClosingTableSetting.tableId)!;
if (this.screenSize === ScreenSizeEnum.XS || this.screenSize === ScreenSizeEnum.SM) { if (this.screenSize === ScreenSizeEnum.XS || this.screenSize === ScreenSizeEnum.SM) {
this.displayedForceClosingColumns = JSON.parse(JSON.stringify(this.forceClosingopenTableSetting.columnSelectionSM)); this.displayedForceClosingColumns = JSON.parse(JSON.stringify(this.forceClosingTableSetting.columnSelectionSM));
} else { } else {
this.displayedForceClosingColumns = JSON.parse(JSON.stringify(this.forceClosingopenTableSetting.columnSelection)); this.displayedForceClosingColumns = JSON.parse(JSON.stringify(this.forceClosingTableSetting.columnSelection));
} }
this.displayedForceClosingColumns.push('actions'); this.displayedForceClosingColumns.push('actions');
this.logger.info(this.displayedForceClosingColumns); this.logger.info(this.displayedForceClosingColumns);
this.closingOpenTableSetting = settings.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.closingOpenTableSetting.tableId) || this.closingTableSetting = settings.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.closingTableSetting.tableId) ||
LND_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.closingOpenTableSetting.tableId)!; LND_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.closingTableSetting.tableId)!;
if (this.screenSize === ScreenSizeEnum.XS || this.screenSize === ScreenSizeEnum.SM) { if (this.screenSize === ScreenSizeEnum.XS || this.screenSize === ScreenSizeEnum.SM) {
this.displayedClosingColumns = JSON.parse(JSON.stringify(this.closingOpenTableSetting.columnSelectionSM)); this.displayedClosingColumns = JSON.parse(JSON.stringify(this.closingTableSetting.columnSelectionSM));
} else { } else {
this.displayedClosingColumns = JSON.parse(JSON.stringify(this.closingOpenTableSetting.columnSelection)); this.displayedClosingColumns = JSON.parse(JSON.stringify(this.closingTableSetting.columnSelection));
} }
this.displayedClosingColumns.push('actions'); this.displayedClosingColumns.push('actions');
this.logger.info(this.displayedClosingColumns); this.logger.info(this.displayedClosingColumns);
this.waitingCloseopenTableSetting = settings.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.waitingCloseopenTableSetting.tableId) || this.waitingCloseTableSetting = settings.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.waitingCloseTableSetting.tableId) ||
LND_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.waitingCloseopenTableSetting.tableId)!; LND_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.waitingCloseTableSetting.tableId)!;
if (this.screenSize === ScreenSizeEnum.XS || this.screenSize === ScreenSizeEnum.SM) { if (this.screenSize === ScreenSizeEnum.XS || this.screenSize === ScreenSizeEnum.SM) {
this.displayedWaitClosingColumns = JSON.parse(JSON.stringify(this.waitingCloseopenTableSetting.columnSelectionSM)); this.displayedWaitClosingColumns = JSON.parse(JSON.stringify(this.waitingCloseTableSetting.columnSelectionSM));
} else { } else {
this.displayedWaitClosingColumns = JSON.parse(JSON.stringify(this.waitingCloseopenTableSetting.columnSelection)); this.displayedWaitClosingColumns = JSON.parse(JSON.stringify(this.waitingCloseTableSetting.columnSelection));
} }
this.displayedWaitClosingColumns.push('actions'); this.displayedWaitClosingColumns.push('actions');
this.logger.info(this.displayedWaitClosingColumns); this.logger.info(this.displayedWaitClosingColumns);
@ -264,42 +263,38 @@ export class ChannelPendingTableComponent implements OnInit, AfterViewInit, OnDe
} }
loadOpenChannelsTable(channels) { loadOpenChannelsTable(channels) {
channels.sort((a, b) => ((a.active === b.active) ? 0 : ((b.active) ? -1 : 1)));
this.pendingOpenChannelsLength = (channels.length) ? channels.length : 0; this.pendingOpenChannelsLength = (channels.length) ? channels.length : 0;
this.pendingOpenChannels = new MatTableDataSource<Channel>([...channels]); this.pendingOpenChannels = new MatTableDataSource<Channel>([...channels]);
this.pendingOpenChannels.sort = this.sort; this.pendingOpenChannels.sort = this.sort;
this.pendingOpenChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.pendingOpenChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.pendingOpenChannels.filterPredicate = (channel: any, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr); this.pendingOpenChannels.sort?.sort({ id: this.openTableSetting.sortBy, start: this.openTableSetting.sortOrder, disableClear: true });
this.logger.info(this.pendingOpenChannels); this.logger.info(this.pendingOpenChannels);
} }
loadForceClosingChannelsTable(channels) { loadForceClosingChannelsTable(channels) {
channels.sort((a, b) => ((a.active === b.active) ? 0 : ((b.active) ? -1 : 1)));
this.pendingForceClosingChannelsLength = (channels.length) ? channels.length : 0; this.pendingForceClosingChannelsLength = (channels.length) ? channels.length : 0;
this.pendingForceClosingChannels = new MatTableDataSource<Channel>([...channels]); this.pendingForceClosingChannels = new MatTableDataSource<Channel>([...channels]);
this.pendingForceClosingChannels.sort = this.sort; this.pendingForceClosingChannels.sort = this.sort;
this.pendingForceClosingChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.pendingForceClosingChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.pendingForceClosingChannels.filterPredicate = (channel: any, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr); this.pendingForceClosingChannels.sort?.sort({ id: this.forceClosingTableSetting.sortBy, start: this.forceClosingTableSetting.sortOrder, disableClear: true });
this.logger.info(this.pendingForceClosingChannels); this.logger.info(this.pendingForceClosingChannels);
} }
loadClosingChannelsTable(channels) { loadClosingChannelsTable(channels) {
channels.sort((a, b) => ((a.active === b.active) ? 0 : ((b.active) ? -1 : 1)));
this.pendingClosingChannelsLength = (channels.length) ? channels.length : 0; this.pendingClosingChannelsLength = (channels.length) ? channels.length : 0;
this.pendingClosingChannels = new MatTableDataSource<Channel>([...channels]); this.pendingClosingChannels = new MatTableDataSource<Channel>([...channels]);
this.pendingClosingChannels.sort = this.sort; this.pendingClosingChannels.sort = this.sort;
this.pendingClosingChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.pendingClosingChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.pendingClosingChannels.filterPredicate = (channel: any, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr); this.pendingClosingChannels.sort?.sort({ id: this.closingTableSetting.sortBy, start: this.closingTableSetting.sortOrder, disableClear: true });
this.logger.info(this.pendingClosingChannels); this.logger.info(this.pendingClosingChannels);
} }
loadWaitClosingChannelsTable(channels) { loadWaitClosingChannelsTable(channels) {
channels.sort((a, b) => ((a.active === b.active) ? 0 : ((b.active) ? -1 : 1)));
this.pendingWaitClosingChannelsLength = (channels.length) ? channels.length : 0; this.pendingWaitClosingChannelsLength = (channels.length) ? channels.length : 0;
this.pendingWaitClosingChannels = new MatTableDataSource<Channel>([...channels]); this.pendingWaitClosingChannels = new MatTableDataSource<Channel>([...channels]);
this.pendingWaitClosingChannels.sort = this.sort; this.pendingWaitClosingChannels.sort = this.sort;
this.pendingWaitClosingChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.pendingWaitClosingChannels.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.pendingWaitClosingChannels.filterPredicate = (channel: any, fltr: string) => JSON.stringify(channel).toLowerCase().includes(fltr); this.pendingWaitClosingChannels.sort?.sort({ id: this.waitingCloseTableSetting.sortBy, start: this.waitingCloseTableSetting.sortOrder, disableClear: true });
this.logger.info(this.pendingWaitClosingChannels); this.logger.info(this.pendingWaitClosingChannels);
} }

@ -8,9 +8,16 @@
<fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faUsers" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Connected Peers</span> <span class="page-title">Connected Peers</span>
</div> </div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -18,7 +25,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Alias</th>
<td mat-cell *matCellDef="let peer"> <td mat-cell *matCellDef="let peer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{peer?.alias}}</span> <span class="ellipsis-child">{{peer?.alias}}</span>
</div> </div>
</td> </td>
@ -26,7 +33,7 @@
<ng-container matColumnDef="pub_key"> <ng-container matColumnDef="pub_key">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Public Key</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Public Key</th>
<td mat-cell *matCellDef="let peer"> <td mat-cell *matCellDef="let peer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{peer?.pub_key}}</span> <span class="ellipsis-child">{{peer?.pub_key}}</span>
</div> </div>
</td> </td>
@ -34,7 +41,7 @@
<ng-container matColumnDef="address"> <ng-container matColumnDef="address">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Address</th>
<td mat-cell *matCellDef="let peer"> <td mat-cell *matCellDef="let peer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{peer?.address}}</span> <span class="ellipsis-child">{{peer?.address}}</span>
</div> </div>
</td> </td>

@ -8,7 +8,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { Peer, GetInfo, BlockchainBalance } from '../../../shared/models/lndModels'; import { Peer, GetInfo, BlockchainBalance } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -20,7 +20,8 @@ import { RTLState } from '../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../store/rtl.actions';
import { detachPeer } from '../../store/lnd.actions'; import { detachPeer } from '../../store/lnd.actions';
import { blockchainBalance, lndNodeInformation, lndPageSettings, peers } from '../../store/lnd.selector'; import { blockchainBalance, lndNodeInformation, lndPageSettings, peers } from '../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-peers', selector: 'rtl-peers',
@ -34,6 +35,8 @@ export class PeersComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'peers_channels'; public PAGE_ID = 'peers_channels';
public tableSetting: TableSetting = { tableId: 'peers', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'peers', recordsPerPage: PAGE_SIZE, sortBy: 'alias', sortOrder: SortOrderEnum.DESCENDING };
@ -53,7 +56,7 @@ export class PeersComponent implements OnInit, AfterViewInit, OnDestroy {
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService) { constructor(private logger: LoggerService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private commonService: CommonService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -177,13 +180,45 @@ export class PeersComponent implements OnInit, AfterViewInit, OnDestroy {
this.peers.filter = this.selFilter.trim().toLowerCase(); this.peers.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.peers.filterPredicate = (peer: Peer, fltr: string) => JSON.stringify(peer).toLowerCase().includes(fltr);
// this.peers.filterPredicate = (rowData: Peer, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadPeersTable(peers: Peer[]) { loadPeersTable(peers: Peer[]) {
this.peers = peers ? new MatTableDataSource<Peer>([...peers]) : new MatTableDataSource([]); this.peers = peers ? new MatTableDataSource<Peer>([...peers]) : new MatTableDataSource([]);
this.peers.sort = this.sort; this.peers.sort = this.sort;
this.peers.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.peers.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.peers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.peers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.peers.filterPredicate = (peer: Peer, fltr: string) => JSON.stringify(peer).toLowerCase().includes(fltr);
this.peers.paginator = this.paginator; this.peers.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
} }

@ -41,7 +41,7 @@
</div> </div>
<div fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100" class="padding-gap-x"> <div fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100" class="padding-gap-x">
<div class="mt-1"> <div class="mt-1">
<rtl-forwarding-history *ngIf="events && events?.forwarding_events && events.forwarding_events.length && events.forwarding_events.length > 0" [pageId]="'reports'" [tableId]="'routing'" [eventsData]="events?.forwarding_events" [filterValue]="eventFilterValue"></rtl-forwarding-history> <rtl-forwarding-history *ngIf="events && events?.forwarding_events && events.forwarding_events.length && events.forwarding_events.length > 0" [pageId]="'reports'" [tableId]="'routing'" [eventsData]="events?.forwarding_events" [selFilter]="eventFilterValue"></rtl-forwarding-history>
</div> </div>
</div> </div>
</div> </div>

@ -41,7 +41,7 @@
</ngx-charts-bar-vertical-2d> </ngx-charts-bar-vertical-2d>
</div> </div>
<div class="mt-1"> <div class="mt-1">
<rtl-transactions-report-table *ngIf="transactionsNonZeroReportData.length > 0 && apiCallStatus.status === apiCallStatusEnum.COMPLETED" [displayedColumns]="displayedColumns" [tableSetting]="tableSetting" [dataList]="transactionsNonZeroReportData" [dataRange]="reportPeriod" [filterValue]="transactionFilterValue"></rtl-transactions-report-table> <rtl-transactions-report-table *ngIf="transactionsNonZeroReportData.length > 0 && apiCallStatus.status === apiCallStatusEnum.COMPLETED" [displayedColumns]="displayedColumns" [tableSetting]="tableSetting" [dataList]="transactionsNonZeroReportData" [dataRange]="reportPeriod" [selFilter]="transactionFilterValue"></rtl-transactions-report-table>
</div> </div>
</div> </div>
</div> </div>

@ -2,9 +2,16 @@
<div class="p-2 error-border my-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div> <div class="p-2 error-border my-2" *ngIf="errorMessage !== ''">{{errorMessage}}</div>
<div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput [(ngModel)]="filterValue" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -16,7 +23,7 @@
<ng-container matColumnDef="alias_in"> <ng-container matColumnDef="alias_in">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Inbound Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Inbound Alias</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.alias_in}}</span> <span class="ellipsis-child">{{fhEvent?.alias_in}}</span>
</div> </div>
</td> </td>
@ -24,7 +31,7 @@
<ng-container matColumnDef="chan_id_in"> <ng-container matColumnDef="chan_id_in">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Inbound Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Inbound Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.chan_id_in}}</span> <span class="ellipsis-child">{{fhEvent?.chan_id_in}}</span>
</div> </div>
</td> </td>
@ -32,7 +39,7 @@
<ng-container matColumnDef="alias_out"> <ng-container matColumnDef="alias_out">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Outbound Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Outbound Alias</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.alias_out}}</span> <span class="ellipsis-child">{{fhEvent?.alias_out}}</span>
</div> </div>
</td> </td>
@ -40,7 +47,7 @@
<ng-container matColumnDef="chan_id_out"> <ng-container matColumnDef="chan_id_out">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Outbound Channel</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Outbound Channel</th>
<td mat-cell *matCellDef="let fhEvent"> <td mat-cell *matCellDef="let fhEvent">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{fhEvent?.chan_id_out}}</span> <span class="ellipsis-child">{{fhEvent?.chan_id_out}}</span>
</div> </div>
</td> </td>

@ -8,7 +8,7 @@ import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { ForwardingEvent, SwitchRes } from '../../../shared/models/lndModels'; import { ForwardingEvent, SwitchRes } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -16,7 +16,8 @@ import { openAlert } from '../../../store/rtl.actions';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { forwardingHistory, lndPageSettings } from '../../store/lnd.selector'; import { forwardingHistory, lndPageSettings } from '../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-forwarding-history', selector: 'rtl-forwarding-history',
@ -33,7 +34,9 @@ export class ForwardingHistoryComponent implements OnInit, AfterViewInit, OnChan
@Input() pageId = 'routing'; @Input() pageId = 'routing';
@Input() tableId = 'forwarding_history'; @Input() tableId = 'forwarding_history';
@Input() eventsData = []; @Input() eventsData = [];
@Input() filterValue = ''; @Input() selFilter = '';
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'routing'; public PAGE_ID = 'routing';
public tableSetting: TableSetting = { tableId: 'forwarding_history', recordsPerPage: PAGE_SIZE, sortBy: 'timestamp', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'forwarding_history', recordsPerPage: PAGE_SIZE, sortBy: 'timestamp', sortOrder: SortOrderEnum.DESCENDING };
@ -49,7 +52,7 @@ export class ForwardingHistoryComponent implements OnInit, AfterViewInit, OnChan
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -104,7 +107,7 @@ export class ForwardingHistoryComponent implements OnInit, AfterViewInit, OnChan
this.loadForwardingEventsTable(this.forwardingHistoryData); this.loadForwardingEventsTable(this.forwardingHistoryData);
} }
} }
if (changes.filterValue && !changes.filterValue.firstChange) { if (changes.selFilter && !changes.selFilter.firstChange) {
this.applyFilter(); this.applyFilter();
} }
} }
@ -131,16 +134,55 @@ export class ForwardingHistoryComponent implements OnInit, AfterViewInit, OnChan
})); }));
} }
applyFilter() {
if (this.forwardingHistoryEvents) {
this.forwardingHistoryEvents.filter = this.selFilter.trim().toLowerCase();
}
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.forwardingHistoryEvents.filterPredicate = (rowData: ForwardingEvent, fltr: string) => {
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
// this.forwardingHistoryEvents.filterPredicate = (rowData: ForwardingEvent, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadForwardingEventsTable(forwardingEvents: ForwardingEvent[]) { loadForwardingEventsTable(forwardingEvents: ForwardingEvent[]) {
this.forwardingHistoryEvents = forwardingEvents ? new MatTableDataSource<ForwardingEvent>([...forwardingEvents]) : new MatTableDataSource([]); this.forwardingHistoryEvents = forwardingEvents ? new MatTableDataSource<ForwardingEvent>([...forwardingEvents]) : new MatTableDataSource([]);
this.forwardingHistoryEvents.sort = this.sort; this.forwardingHistoryEvents.sort = this.sort;
this.forwardingHistoryEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.forwardingHistoryEvents.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.forwardingHistoryEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.forwardingHistoryEvents.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.forwardingHistoryEvents.filterPredicate = (rowData: ForwardingEvent, fltr: string) => {
const newRowData = ((rowData.timestamp) ? this.datePipe.transform(new Date(rowData.timestamp * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.forwardingHistoryEvents.paginator = this.paginator; this.forwardingHistoryEvents.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter();
this.logger.info(this.forwardingHistoryEvents); this.logger.info(this.forwardingHistoryEvents);
} }
@ -150,12 +192,6 @@ export class ForwardingHistoryComponent implements OnInit, AfterViewInit, OnChan
} }
} }
applyFilter() {
if (this.forwardingHistoryEvents) {
this.forwardingHistoryEvents.filter = this.filterValue.trim().toLowerCase();
}
}
ngOnDestroy() { ngOnDestroy() {
this.unSubs.forEach((completeSub) => { this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null); completeSub.next(<any>null);

@ -3,13 +3,20 @@
<div *ngIf="errorMessage === ''" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch"> <div *ngIf="errorMessage === ''" fxLayout="column" fxFlex="100" fxLayoutAlign="start stretch">
<div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container"> <div *ngIf="errorMessage === ''" fxLayout="column" fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70">Non Routing Peers</div> <div fxFlex="70">Non Routing Peers</div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container"> <div *ngIf="errorMessage === ''" [perfectScrollbar] fxLayout="column" fxLayoutAlign="start center" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="NonRoutingPeers" matSort class="overflow-auto"> <table mat-table #table [dataSource]="nonRoutingPeers" matSort class="overflow-auto">
<ng-container matColumnDef="chan_id"> <ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let nonRPeer"> <td mat-cell *matCellDef="let nonRPeer">
@ -110,12 +117,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="no_non_routing_event"> <ng-container matColumnDef="no_non_routing_event">
<td mat-footer-cell *matFooterCellDef colspan="4"> <td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!NonRoutingPeers?.data || NonRoutingPeers?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">All peers are routing.</p> <p *ngIf="(!nonRoutingPeers?.data || nonRoutingPeers?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">All peers are routing.</p>
<p *ngIf="(!NonRoutingPeers?.data || NonRoutingPeers?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting non routing peers...</p> <p *ngIf="(!nonRoutingPeers?.data || nonRoutingPeers?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting non routing peers...</p>
<p *ngIf="(!NonRoutingPeers?.data || NonRoutingPeers?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p> <p *ngIf="(!nonRoutingPeers?.data || nonRoutingPeers?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td> </td>
</ng-container> </ng-container>
<tr mat-footer-row *matFooterRowDef="['no_non_routing_event']" [ngClass]="{'display-none': NonRoutingPeers?.data?.length>0}"></tr> <tr mat-footer-row *matFooterRowDef="['no_non_routing_event']" [ngClass]="{'display-none': nonRoutingPeers?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>

@ -8,14 +8,15 @@ import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { ForwardingEvent, SwitchRes, Channel, ChannelsSummary, LightningBalance } from '../../../shared/models/lndModels'; import { ForwardingEvent, SwitchRes, Channel, ChannelsSummary, LightningBalance } from '../../../shared/models/lndModels';
import { APICallStatusEnum, getPaginatorLabel, LND_DEFAULT_PAGE_SETTINGS, PAGE_SIZE, PAGE_SIZE_OPTIONS, ScreenSizeEnum, SortOrderEnum } from '../../../shared/services/consts-enums-functions'; import { APICallStatusEnum, getPaginatorLabel, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS, PAGE_SIZE, PAGE_SIZE_OPTIONS, ScreenSizeEnum, SortOrderEnum } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { channels, forwardingHistory, lndPageSettings } from '../../store/lnd.selector'; import { channels, forwardingHistory, lndPageSettings } from '../../store/lnd.selector';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-non-routing-peers', selector: 'rtl-non-routing-peers',
@ -29,25 +30,27 @@ export class NonRoutingPeersComponent implements OnInit, AfterViewInit, OnDestro
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'routing'; public PAGE_ID = 'routing';
public tableSetting: TableSetting = { tableId: 'non_routing_peers', recordsPerPage: PAGE_SIZE, sortBy: 'remote_alias', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'non_routing_peers', recordsPerPage: PAGE_SIZE, sortBy: 'remote_alias', sortOrder: SortOrderEnum.DESCENDING };
public routingPeersData: any[] = []; public routingPeersData: any[] = [];
public displayedColumns: any[] = []; public displayedColumns: any[] = [];
public NonRoutingPeers: any = new MatTableDataSource<any>([]); public nonRoutingPeers: any = new MatTableDataSource<any>([]);
public pageSize = PAGE_SIZE; public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS; public pageSizeOptions = PAGE_SIZE_OPTIONS;
public screenSize = ''; public screenSize = '';
public screenSizeEnum = ScreenSizeEnum; public screenSizeEnum = ScreenSizeEnum;
public errorMessage = ''; public errorMessage = '';
public filter = ''; public selFilter = '';
public activeChannels: Channel[] = []; public activeChannels: Channel[] = [];
public timeUnit = 'mins:secs'; public timeUnit = 'mins:secs';
public apiCallStatus: ApiCallStatusPayload | null = null; public apiCallStatus: ApiCallStatusPayload | null = null;
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private router: Router, private activatedRoute: ActivatedRoute, private decimalPipe: DecimalPipe) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private router: Router, private activatedRoute: ActivatedRoute, private decimalPipe: DecimalPipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -186,26 +189,59 @@ export class NonRoutingPeersComponent implements OnInit, AfterViewInit, OnDestro
// return this.commonService.sortDescByKey(results, 'alias'); // return this.commonService.sortDescByKey(results, 'alias');
// } // }
applyFilter() {
this.nonRoutingPeers.filter = this.selFilter.toLowerCase();
}
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.nonRoutingPeers.filterPredicate = (nrchnl: Channel, fltr: string) => JSON.stringify(nrchnl).toLowerCase().includes(fltr);
// this.peers.filterPredicate = (rowData: Peer, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadNonRoutingPeersTable(forwardingEvents: ForwardingEvent[]) { loadNonRoutingPeersTable(forwardingEvents: ForwardingEvent[]) {
if (forwardingEvents.length > 0) { if (forwardingEvents.length > 0) {
// const grpdRoutingPeers = this.groupRoutingPeers(forwardingEvents); // const grpdRoutingPeers = this.groupRoutingPeers(forwardingEvents);
const filteredNonRoutingChannels = this.calculateUptime(this.activeChannels?.filter((actvChnl) => forwardingEvents.findIndex((evnt) => (evnt.chan_id_in === actvChnl.chan_id || evnt.chan_id_out === actvChnl.chan_id)) < 0)); const filteredNonRoutingChannels = this.calculateUptime(this.activeChannels?.filter((actvChnl) => forwardingEvents.findIndex((evnt) => (evnt.chan_id_in === actvChnl.chan_id || evnt.chan_id_out === actvChnl.chan_id)) < 0));
this.NonRoutingPeers = new MatTableDataSource<Channel>(filteredNonRoutingChannels); this.nonRoutingPeers = new MatTableDataSource<Channel>(filteredNonRoutingChannels);
this.NonRoutingPeers.sort = this.sort; this.nonRoutingPeers.sort = this.sort;
this.NonRoutingPeers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.nonRoutingPeers.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.NonRoutingPeers.filterPredicate = (nrchnl: Channel, fltr: string) => JSON.stringify(nrchnl).toLowerCase().includes(fltr); this.nonRoutingPeers.paginator = this.paginator;
this.NonRoutingPeers.paginator = this.paginator; this.setFilterPredicate();
this.logger.info(this.NonRoutingPeers); this.applyFilter();
this.logger.info(this.nonRoutingPeers);
} else { } else {
this.NonRoutingPeers = new MatTableDataSource<Channel>([]); this.nonRoutingPeers = new MatTableDataSource<Channel>([]);
} }
this.applyFilter(); this.applyFilter();
} }
applyFilter() {
this.NonRoutingPeers.filter = this.filter.toLowerCase();
}
ngOnDestroy() { ngOnDestroy() {
this.unSubs.forEach((completeSub) => { this.unSubs.forEach((completeSub) => {
completeSub.next(<any>null); completeSub.next(<any>null);

@ -4,17 +4,24 @@
<div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch" class="mb-4"> <div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch" class="mb-4">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize === screenSizeEnum.XS, 'mt-1': screenSize === screenSizeEnum.SM}">
<div fxFlex="70">Incoming</div> <div fxFlex="70">Incoming</div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyIncomingFilter()" [(ngModel)]="filterIn" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterByIn" (selectionChange)="selFilterIn=''; applyIncomingFilter()" name="filterByIn">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilterIn" (input)="applyIncomingFilter()" (keyup)="applyIncomingFilter()" name="filterin" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start start" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start start" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableIn [dataSource]="RoutingPeersIncoming" matSort class="overflow-auto incoming-table"> <table mat-table #tableIn [dataSource]="routingPeersIncoming" matSort class="overflow-auto incoming-table">
<ng-container matColumnDef="chan_id"> <ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer?.chan_id}}</span> <span class="ellipsis-child">{{rPeer?.chan_id}}</span>
</div> </div>
</td> </td>
@ -22,7 +29,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer?.alias}}</span> <span class="ellipsis-child">{{rPeer?.alias}}</span>
</div> </div>
</td> </td>
@ -46,12 +53,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="no_incoming_event"> <ng-container matColumnDef="no_incoming_event">
<td mat-footer-cell *matFooterCellDef colspan="4"> <td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">No incoming routing peer available.</p> <p *ngIf="(!routingPeersIncoming?.data || routingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">No incoming routing peer available.</p>
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting incoming routing peers...</p> <p *ngIf="(!routingPeersIncoming?.data || routingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting incoming routing peers...</p>
<p *ngIf="(!RoutingPeersIncoming?.data || RoutingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p> <p *ngIf="(!routingPeersIncoming?.data || routingPeersIncoming?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td> </td>
</ng-container> </ng-container>
<tr mat-footer-row *matFooterRowDef="['no_incoming_event']" [ngClass]="{'display-none': RoutingPeersIncoming?.data?.length>0}"></tr> <tr mat-footer-row *matFooterRowDef="['no_incoming_event']" [ngClass]="{'display-none': routingPeersIncoming?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>
@ -61,17 +68,24 @@
<div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch" class="mb-4"> <div fxLayout="column" fxFlex="49" fxLayoutAlign="start stretch" class="mb-4">
<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}"> <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="start stretch" class="page-sub-title-container w-100" [ngClass]="{'mt-2': screenSize !== screenSizeEnum.LG}">
<div fxFlex="70">Outgoing</div> <div fxFlex="70">Outgoing</div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyOutgoingFilter()" [(ngModel)]="filterOut" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterByOut" (selectionChange)="selFilterOut=''; applyOutgoingFilter()" name="filterByOut">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilterOut" (input)="applyOutgoingFilter()" (keyup)="applyOutgoingFilter()" name="filterout" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start start" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start start" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #tableOut [dataSource]="RoutingPeersOutgoing" matSort class="overflow-auto outgoing-table"> <table mat-table #tableOut [dataSource]="routingPeersOutgoing" matSort class="overflow-auto outgoing-table">
<ng-container matColumnDef="chan_id"> <ng-container matColumnDef="chan_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Channel ID</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer?.chan_id}}</span> <span class="ellipsis-child">{{rPeer?.chan_id}}</span>
</div> </div>
</td> </td>
@ -79,7 +93,7 @@
<ng-container matColumnDef="alias"> <ng-container matColumnDef="alias">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Peer Alias</th>
<td mat-cell *matCellDef="let rPeer"> <td mat-cell *matCellDef="let rPeer">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{rPeer?.alias}}</span> <span class="ellipsis-child">{{rPeer?.alias}}</span>
</div> </div>
</td> </td>
@ -95,12 +109,12 @@
</ng-container> </ng-container>
<ng-container matColumnDef="no_outgoing_event"> <ng-container matColumnDef="no_outgoing_event">
<td mat-footer-cell *matFooterCellDef colspan="4"> <td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">No outgoing routing peer available.</p> <p *ngIf="(!routingPeersOutgoing?.data || routingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.COMPLETED">No outgoing routing peer available.</p>
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting outgoing routing peers...</p> <p *ngIf="(!routingPeersOutgoing?.data || routingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.INITIATED">Getting outgoing routing peers...</p>
<p *ngIf="(!RoutingPeersOutgoing?.data || RoutingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p> <p *ngIf="(!routingPeersOutgoing?.data || routingPeersOutgoing?.data?.length<1) && apiCallStatus.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td> </td>
</ng-container> </ng-container>
<tr mat-footer-row *matFooterRowDef="['no_outgoing_event']" [ngClass]="{'display-none': RoutingPeersOutgoing?.data?.length>0}"></tr> <tr mat-footer-row *matFooterRowDef="['no_outgoing_event']" [ngClass]="{'display-none': routingPeersOutgoing?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> </table>

@ -7,7 +7,7 @@ import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { ForwardingEvent, RoutingPeers, SwitchRes } from '../../../shared/models/lndModels'; import { ForwardingEvent, RoutingPeers, SwitchRes } from '../../../shared/models/lndModels';
import { AlertTypeEnum, APICallStatusEnum, DataTypeEnum, getPaginatorLabel, LND_DEFAULT_PAGE_SETTINGS, PAGE_SIZE, PAGE_SIZE_OPTIONS, ScreenSizeEnum, SortOrderEnum } from '../../../shared/services/consts-enums-functions'; import { AlertTypeEnum, APICallStatusEnum, DataTypeEnum, getPaginatorLabel, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS, PAGE_SIZE, PAGE_SIZE_OPTIONS, ScreenSizeEnum, SortOrderEnum } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
@ -15,6 +15,7 @@ import { openAlert } from '../../../store/rtl.actions';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { forwardingHistory, lndPageSettings } from '../../store/lnd.selector'; import { forwardingHistory, lndPageSettings } from '../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-routing-peers', selector: 'rtl-routing-peers',
@ -30,13 +31,16 @@ export class RoutingPeersComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('tableOut', { read: MatSort, static: false }) sortOut: MatSort; @ViewChild('tableOut', { read: MatSort, static: false }) sortOut: MatSort;
@ViewChild('paginatorIn', { static: false }) paginatorIn: MatPaginator | undefined; @ViewChild('paginatorIn', { static: false }) paginatorIn: MatPaginator | undefined;
@ViewChild('paginatorOut', { static: false }) paginatorOut: MatPaginator | undefined; @ViewChild('paginatorOut', { static: false }) paginatorOut: MatPaginator | undefined;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterByIn = 'all';
public selFilterByOut = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'routing'; public PAGE_ID = 'routing';
public tableSetting: TableSetting = { tableId: 'routing_peers', recordsPerPage: PAGE_SIZE, sortBy: 'total_amount', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'routing_peers', recordsPerPage: PAGE_SIZE, sortBy: 'total_amount', sortOrder: SortOrderEnum.DESCENDING };
public routingPeersData: any[] = []; public routingPeersData: any[] = [];
public displayedColumns: any[] = []; public displayedColumns: any[] = [];
public RoutingPeersIncoming = new MatTableDataSource<RoutingPeers>([]); public routingPeersIncoming = new MatTableDataSource<RoutingPeers>([]);
public RoutingPeersOutgoing = new MatTableDataSource<RoutingPeers>([]); public routingPeersOutgoing = new MatTableDataSource<RoutingPeers>([]);
public pageSize = PAGE_SIZE; public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS; public pageSizeOptions = PAGE_SIZE_OPTIONS;
public screenSize = ''; public screenSize = '';
@ -48,7 +52,7 @@ export class RoutingPeersComponent implements OnInit, AfterViewInit, OnDestroy {
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -123,22 +127,22 @@ export class RoutingPeersComponent implements OnInit, AfterViewInit, OnDestroy {
loadRoutingPeersTable(forwardingEvents: ForwardingEvent[]) { loadRoutingPeersTable(forwardingEvents: ForwardingEvent[]) {
if (forwardingEvents.length > 0) { if (forwardingEvents.length > 0) {
const results = this.groupRoutingPeers(forwardingEvents); const results = this.groupRoutingPeers(forwardingEvents);
this.RoutingPeersIncoming = new MatTableDataSource<RoutingPeers>(results[0]); this.routingPeersIncoming = new MatTableDataSource<RoutingPeers>(results[0]);
this.RoutingPeersIncoming.sort = this.sortIn; this.routingPeersIncoming.sort = this.sortIn;
this.RoutingPeersIncoming.sort.sort({ id: this.tableSetting.sortBy || 'total_amount', start: this.tableSetting.sortOrder || SortOrderEnum.DESCENDING, disableClear: true }); this.routingPeersIncoming.sort.sort({ id: this.tableSetting.sortBy || 'total_amount', start: this.tableSetting.sortOrder || SortOrderEnum.DESCENDING, disableClear: true });
this.RoutingPeersIncoming.filterPredicate = (rpIn: RoutingPeers, fltr: string) => JSON.stringify(rpIn).toLowerCase().includes(fltr); this.routingPeersIncoming.filterPredicate = (rpIn: RoutingPeers, fltr: string) => JSON.stringify(rpIn).toLowerCase().includes(fltr);
this.RoutingPeersIncoming.paginator = this.paginatorIn!; this.routingPeersIncoming.paginator = this.paginatorIn!;
this.logger.info(this.RoutingPeersIncoming); this.logger.info(this.routingPeersIncoming);
this.RoutingPeersOutgoing = new MatTableDataSource<RoutingPeers>(results[1]); this.routingPeersOutgoing = new MatTableDataSource<RoutingPeers>(results[1]);
this.RoutingPeersOutgoing.sort = this.sortOut; this.routingPeersOutgoing.sort = this.sortOut;
this.RoutingPeersOutgoing.sort.sort({ id: this.tableSetting.sortBy || 'total_amount', start: this.tableSetting.sortOrder || SortOrderEnum.DESCENDING, disableClear: true }); this.routingPeersOutgoing.sort.sort({ id: this.tableSetting.sortBy || 'total_amount', start: this.tableSetting.sortOrder || SortOrderEnum.DESCENDING, disableClear: true });
this.RoutingPeersOutgoing.filterPredicate = (rpOut: RoutingPeers, fltr: string) => JSON.stringify(rpOut).toLowerCase().includes(fltr); this.routingPeersOutgoing.filterPredicate = (rpOut: RoutingPeers, fltr: string) => JSON.stringify(rpOut).toLowerCase().includes(fltr);
this.RoutingPeersOutgoing.paginator = this.paginatorOut!; this.routingPeersOutgoing.paginator = this.paginatorOut!;
this.logger.info(this.RoutingPeersOutgoing); this.logger.info(this.routingPeersOutgoing);
} else { } else {
// To reset table after other Forwarding history calls // To reset table after other Forwarding history calls
this.RoutingPeersIncoming = new MatTableDataSource<RoutingPeers>([]); this.routingPeersIncoming = new MatTableDataSource<RoutingPeers>([]);
this.RoutingPeersOutgoing = new MatTableDataSource<RoutingPeers>([]); this.routingPeersOutgoing = new MatTableDataSource<RoutingPeers>([]);
} }
this.applyIncomingFilter(); this.applyIncomingFilter();
this.applyOutgoingFilter(); this.applyOutgoingFilter();
@ -167,11 +171,11 @@ export class RoutingPeersComponent implements OnInit, AfterViewInit, OnDestroy {
} }
applyIncomingFilter() { applyIncomingFilter() {
this.RoutingPeersIncoming.filter = this.filterIn.toLowerCase(); this.routingPeersIncoming.filter = this.filterIn.toLowerCase();
} }
applyOutgoingFilter() { applyOutgoingFilter() {
this.RoutingPeersOutgoing.filter = this.filterOut.toLowerCase(); this.routingPeersOutgoing.filter = this.filterOut.toLowerCase();
} }
ngOnDestroy() { ngOnDestroy() {

@ -22,9 +22,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Invoices History</span> <span class="page-title">Invoices History</span>
</div> </div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" tabindex="6" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container">
<mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="apiCallStatus.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
@ -70,7 +77,7 @@
<ng-container matColumnDef="memo"> <ng-container matColumnDef="memo">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Memo</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Memo</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.memo}}</span> <span class="ellipsis-child">{{invoice?.memo}}</span>
</div> </div>
</td> </td>
@ -78,7 +85,7 @@
<ng-container matColumnDef="r_preimage"> <ng-container matColumnDef="r_preimage">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Preimage</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Preimage</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.r_preimage}}</span> <span class="ellipsis-child">{{invoice?.r_preimage}}</span>
</div> </div>
</td> </td>
@ -86,7 +93,7 @@
<ng-container matColumnDef="r_hash"> <ng-container matColumnDef="r_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Preimage Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Preimage Hash</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.r_hash}}</span> <span class="ellipsis-child">{{invoice?.r_hash}}</span>
</div> </div>
</td> </td>
@ -94,7 +101,7 @@
<ng-container matColumnDef="payment_addr"> <ng-container matColumnDef="payment_addr">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Address</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Address</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.payment_addr}}</span> <span class="ellipsis-child">{{invoice?.payment_addr}}</span>
</div> </div>
</td> </td>
@ -102,7 +109,7 @@
<ng-container matColumnDef="payment_request"> <ng-container matColumnDef="payment_request">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Request</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Request</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.payment_request}}</span> <span class="ellipsis-child">{{invoice?.payment_request}}</span>
</div> </div>
</td> </td>
@ -110,7 +117,7 @@
<ng-container matColumnDef="description_hash"> <ng-container matColumnDef="description_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Description Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Description Hash</th>
<td mat-cell *matCellDef="let invoice"> <td mat-cell *matCellDef="let invoice">
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <div class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{invoice?.description_hash}}</span> <span class="ellipsis-child">{{invoice?.description_hash}}</span>
</div> </div>
</td> </td>

@ -9,7 +9,7 @@ import { MatPaginator, MatPaginatorIntl, PageEvent } from '@angular/material/pag
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, UI_MESSAGES, LNDActions, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions'; import { CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, ScreenSizeEnum, APICallStatusEnum, UI_MESSAGES, LNDActions, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { SelNodeChild } from '../../../shared/models/RTLconfig'; import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { GetInfo, Invoice, ListInvoices } from '../../../shared/models/lndModels'; import { GetInfo, Invoice, ListInvoices } from '../../../shared/models/lndModels';
@ -23,7 +23,8 @@ import { RTLState } from '../../../store/rtl.state';
import { openAlert } from '../../../store/rtl.actions'; import { openAlert } from '../../../store/rtl.actions';
import { fetchInvoices, invoiceLookup, saveNewInvoice } from '../../store/lnd.actions'; import { fetchInvoices, invoiceLookup, saveNewInvoice } from '../../store/lnd.actions';
import { invoices, lndNodeInformation, lndNodeSettings, lndPageSettings } from '../../store/lnd.selector'; import { invoices, lndNodeInformation, lndNodeSettings, lndPageSettings } from '../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-lightning-invoices', selector: 'rtl-lightning-invoices',
@ -45,6 +46,8 @@ export class LightningInvoicesComponent implements OnInit, AfterViewInit, OnDest
public faArrowsTurnRight = faArrowsTurnRight; public faArrowsTurnRight = faArrowsTurnRight;
public faBurst = faBurst; public faBurst = faBurst;
public faMoneyBill1 = faMoneyBill1; public faMoneyBill1 = faMoneyBill1;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'transactions'; public PAGE_ID = 'transactions';
public tableSetting: TableSetting = { tableId: 'invoices', recordsPerPage: PAGE_SIZE, sortBy: 'creation_date', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'invoices', recordsPerPage: PAGE_SIZE, sortBy: 'creation_date', sortOrder: SortOrderEnum.DESCENDING };
@ -75,7 +78,7 @@ export class LightningInvoicesComponent implements OnInit, AfterViewInit, OnDest
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private decimalPipe: DecimalPipe, private commonService: CommonService, private datePipe: DatePipe, private actions: Actions) { constructor(private logger: LoggerService, private store: Store<RTLState>, private decimalPipe: DecimalPipe, private commonService: CommonService, private datePipe: DatePipe, private actions: Actions, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -169,16 +172,53 @@ export class LightningInvoicesComponent implements OnInit, AfterViewInit, OnDest
this.invoicesData = this.invoicesData?.map((invoice) => ((invoice.r_hash === newInvoice.r_hash) ? newInvoice : invoice)); this.invoicesData = this.invoicesData?.map((invoice) => ((invoice.r_hash === newInvoice.r_hash) ? newInvoice : invoice));
} }
loadInvoicesTable(invoices) {
this.invoices = invoices ? new MatTableDataSource<Invoice>([...invoices]) : new MatTableDataSource<Invoice>([]); applyFilter() {
this.invoices.sort = this.sort; this.invoices.filter = this.selFilter.trim().toLowerCase();
this.invoices.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); }
this.invoices.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.invoices.filterPredicate = (invoice: Invoice, fltr: string) => { this.invoices.filterPredicate = (invoice: Invoice, fltr: string) => {
const newInvoice = (invoice.creation_date ? this.datePipe.transform(new Date(invoice.creation_date * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '')! + const newInvoice = (invoice.creation_date ? this.datePipe.transform(new Date(invoice.creation_date * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '')! +
(invoice.settle_date ? this.datePipe.transform(new Date(invoice.settle_date * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(invoice).toLowerCase(); (invoice.settle_date ? this.datePipe.transform(new Date(invoice.settle_date * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(invoice).toLowerCase();
return newInvoice.includes(fltr); return newInvoice.includes(fltr);
}; };
// this.invoices.filterPredicate = (rowData: Invoice, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadInvoicesTable(invoices) {
this.invoices = invoices ? new MatTableDataSource<Invoice>([...invoices]) : new MatTableDataSource<Invoice>([]);
this.invoices.sort = this.sort;
this.invoices.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.invoices.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.invoices); this.logger.info(this.invoices);
} }
@ -191,10 +231,6 @@ export class LightningInvoicesComponent implements OnInit, AfterViewInit, OnDest
this.invoiceValueHint = ''; this.invoiceValueHint = '';
} }
applyFilter() {
this.invoices.filter = this.selFilter.trim().toLowerCase();
}
onPageChange(event: PageEvent) { onPageChange(event: PageEvent) {
let reverse = true; let reverse = true;
let index_offset = this.lastOffset; let index_offset = this.lastOffset;

@ -19,9 +19,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Payments History</span> <span class="page-title">Payments History</span>
</div> </div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start start"> <div fxLayout="row" fxLayoutAlign="start start">
<div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container"> <div [perfectScrollbar] fxLayout="column" fxLayoutAlign="start end" fxFlex="100" class="table-container">
@ -43,7 +50,7 @@
<ng-container matColumnDef="payment_hash"> <ng-container matColumnDef="payment_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Hash</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.payment_hash}}</span> <span class="ellipsis-child">{{payment?.payment_hash}}</span>
</span> </span>
</td> </td>
@ -51,7 +58,7 @@
<ng-container matColumnDef="payment_request"> <ng-container matColumnDef="payment_request">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Request</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Request</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.payment_request}}</span> <span class="ellipsis-child">{{payment?.payment_request}}</span>
</span> </span>
</td> </td>
@ -59,7 +66,7 @@
<ng-container matColumnDef="payment_preimage"> <ng-container matColumnDef="payment_preimage">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Preimage</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Payment Preimage</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.payment_preimage}}</span> <span class="ellipsis-child">{{payment?.payment_preimage}}</span>
</span> </span>
</td> </td>
@ -67,7 +74,7 @@
<ng-container matColumnDef="description"> <ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Description</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.description}}</span> <span class="ellipsis-child">{{payment?.description}}</span>
</span> </span>
</td> </td>
@ -75,7 +82,7 @@
<ng-container matColumnDef="description_hash"> <ng-container matColumnDef="description_hash">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Description Hash</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Description Hash</th>
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.description_hash}}</span> <span class="ellipsis-child">{{payment?.description_hash}}</span>
</span> </span>
</td> </td>
@ -151,7 +158,7 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_payment_hash"> <ng-container matColumnDef="group_payment_hash">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.payment_hash}}</span> <span class="ellipsis-child">{{payment?.payment_hash}}</span>
</span> </span>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
@ -163,7 +170,7 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_payment_request"> <ng-container matColumnDef="group_payment_request">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.payment_request}}</span> <span class="ellipsis-child">{{payment?.payment_request}}</span>
</span> </span>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
@ -174,7 +181,7 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_payment_preimage"> <ng-container matColumnDef="group_payment_preimage">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.payment_preimage}}</span> <span class="ellipsis-child">{{payment?.payment_preimage}}</span>
</span> </span>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
@ -186,7 +193,7 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_description"> <ng-container matColumnDef="group_description">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.description}}</span> <span class="ellipsis-child">{{payment?.description}}</span>
</span> </span>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">
@ -197,7 +204,7 @@
</ng-container> </ng-container>
<ng-container matColumnDef="group_description_hash"> <ng-container matColumnDef="group_description_hash">
<td mat-cell *matCellDef="let payment"> <td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent htlc-row-span" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{payment?.description_hash}}</span> <span class="ellipsis-child">{{payment?.description_hash}}</span>
</span> </span>
<span *ngIf="payment?.is_expanded"> <span *ngIf="payment?.is_expanded">

@ -8,8 +8,8 @@ import { faHistory } from '@fortawesome/free-solid-svg-icons';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { GetInfo, Payment, PayRequest, PaymentHTLC, Peer, Hop, ListPayments, ListInvoices } from '../../../shared/models/lndModels'; import { GetInfo, Payment, PayRequest, PaymentHTLC, Peer, Hop, ListPayments } from '../../../shared/models/lndModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, APICallStatusEnum, UI_MESSAGES, LND_DEFAULT_PAGE_SETTINGS, SortOrderEnum } from '../../../shared/services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, CurrencyUnitEnum, CURRENCY_UNIT_FORMATS, APICallStatusEnum, UI_MESSAGES, LND_DEFAULT_PAGE_SETTINGS, SortOrderEnum, LND_PAGE_DEFS } from '../../../shared/services/consts-enums-functions';
import { LoggerService } from '../../../shared/services/logger.service'; import { LoggerService } from '../../../shared/services/logger.service';
import { CommonService } from '../../../shared/services/common.service'; import { CommonService } from '../../../shared/services/common.service';
import { DataService } from '../../../shared/services/data.service'; import { DataService } from '../../../shared/services/data.service';
@ -18,13 +18,13 @@ import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { SelNodeChild } from '../../../shared/models/RTLconfig'; import { SelNodeChild } from '../../../shared/models/RTLconfig';
import { LightningSendPaymentsComponent } from '../send-payment-modal/send-payment.component'; import { LightningSendPaymentsComponent } from '../send-payment-modal/send-payment.component';
import { LNDEffects } from '../../store/lnd.effects';
import { RTLEffects } from '../../../store/rtl.effects'; import { RTLEffects } from '../../../store/rtl.effects';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../store/rtl.actions'; import { openAlert, openConfirmation } from '../../../store/rtl.actions';
import { sendPayment } from '../../store/lnd.actions'; import { sendPayment } from '../../store/lnd.actions';
import { lndNodeInformation, lndNodeSettings, lndPageSettings, payments, peers } from '../../store/lnd.selector'; import { lndNodeInformation, lndNodeSettings, lndPageSettings, payments, peers } from '../../store/lnd.selector';
import { PageSettings, TableSetting } from '../../../shared/models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../shared/models/pageSettings';
import { CamelCaseWithReplacePipe } from '../../../shared/pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-lightning-payments', selector: 'rtl-lightning-payments',
@ -41,6 +41,8 @@ export class LightningPaymentsComponent implements OnInit, AfterViewInit, OnDest
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public faHistory = faHistory; public faHistory = faHistory;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'transactions'; public PAGE_ID = 'transactions';
public tableSetting: TableSetting = { tableId: 'payments', recordsPerPage: PAGE_SIZE, sortBy: 'creation_date', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'payments', recordsPerPage: PAGE_SIZE, sortBy: 'creation_date', sortOrder: SortOrderEnum.DESCENDING };
@ -68,7 +70,7 @@ export class LightningPaymentsComponent implements OnInit, AfterViewInit, OnDest
public apiCallStatusEnum = APICallStatusEnum; public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private dataService: DataService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private lndEffects: LNDEffects, private decimalPipe: DecimalPipe, private datePipe: DatePipe) { constructor(private logger: LoggerService, private commonService: CommonService, private dataService: DataService, private store: Store<RTLState>, private rtlEffects: RTLEffects, private decimalPipe: DecimalPipe, private datePipe: DatePipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -432,6 +434,41 @@ export class LightningPaymentsComponent implements OnInit, AfterViewInit, OnDest
this.payments.filter = this.selFilter.trim().toLowerCase(); this.payments.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.payments.filterPredicate = (payment: Payment, fltr: string) => {
const newPayment = ((payment.creation_date) ? this.datePipe.transform(new Date(payment.creation_date * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(payment).toLowerCase();
return newPayment.includes(fltr);
};
// this.channels.filterPredicate = (rowData: Channel, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadPaymentsTable(payms) { loadPaymentsTable(payms) {
this.payments = payms ? new MatTableDataSource<Payment>([...payms]) : new MatTableDataSource([]); this.payments = payms ? new MatTableDataSource<Payment>([...payms]) : new MatTableDataSource([]);
this.payments.sortingDataAccessor = (data: any, sortHeaderId: string) => { this.payments.sortingDataAccessor = (data: any, sortHeaderId: string) => {
@ -445,10 +482,7 @@ export class LightningPaymentsComponent implements OnInit, AfterViewInit, OnDest
}; };
this.payments.sort = this.sort; this.payments.sort = this.sort;
this.payments.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.payments.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.payments.filterPredicate = (payment: Payment, fltr: string) => { this.setFilterPredicate();
const newPayment = ((payment.creation_date) ? this.datePipe.transform(new Date(payment.creation_date * 1000), 'dd/MMM/YYYY HH:mm')?.toLowerCase() : '') + JSON.stringify(payment).toLowerCase();
return newPayment.includes(fltr);
};
this.applyFilter(); this.applyFilter();
} }

@ -4,9 +4,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">{{swapCaption}} History</span> <span class="page-title">{{swapCaption}} History</span>
</div> </div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start center" class="w-100"> <div fxLayout="row" fxLayoutAlign="start center" class="w-100">
<div [perfectScrollbar] class="table-container" fxFlex="100"> <div [perfectScrollbar] class="table-container" fxFlex="100">
@ -23,7 +30,7 @@
<ng-container matColumnDef="claimAddress"> <ng-container matColumnDef="claimAddress">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Claim Address</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Claim Address</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.claimAddress}}</span> <span class="ellipsis-child">{{swap?.claimAddress}}</span>
</span> </span>
</td> </td>
@ -31,7 +38,7 @@
<ng-container matColumnDef="lockupAddress"> <ng-container matColumnDef="lockupAddress">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Lockup Address</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Lockup Address</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.lockupAddress}}</span> <span class="ellipsis-child">{{swap?.lockupAddress}}</span>
</span> </span>
</td> </td>
@ -51,7 +58,7 @@
<ng-container matColumnDef="error"> <ng-container matColumnDef="error">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Error</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Error</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.error}}</span> <span class="ellipsis-child">{{swap?.error}}</span>
</span> </span>
</td> </td>
@ -59,7 +66,7 @@
<ng-container matColumnDef="privateKey"> <ng-container matColumnDef="privateKey">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Private Key</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Private Key</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.privateKey}}</span> <span class="ellipsis-child">{{swap?.privateKey}}</span>
</span> </span>
</td> </td>
@ -67,7 +74,7 @@
<ng-container matColumnDef="preimage"> <ng-container matColumnDef="preimage">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Preimage</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Preimage</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.preimage}}</span> <span class="ellipsis-child">{{swap?.preimage}}</span>
</span> </span>
</td> </td>
@ -75,7 +82,7 @@
<ng-container matColumnDef="redeemScript"> <ng-container matColumnDef="redeemScript">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Redeem Script</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Redeem Script</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.redeemScript}}</span> <span class="ellipsis-child">{{swap?.redeemScript}}</span>
</span> </span>
</td> </td>
@ -83,7 +90,7 @@
<ng-container matColumnDef="invoice"> <ng-container matColumnDef="invoice">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.invoice}}</span> <span class="ellipsis-child">{{swap?.invoice}}</span>
</span> </span>
</td> </td>

@ -8,16 +8,17 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { Swap, ReverseSwap } from '../../../../models/boltzModels'; import { Swap, ReverseSwap } from '../../../../models/boltzModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, SwapTypeEnum, SwapStateEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS } from '../../../../services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, SwapTypeEnum, SwapStateEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../services/consts-enums-functions';
import { LoggerService } from '../../../../services/logger.service'; import { LoggerService } from '../../../../services/logger.service';
import { CommonService } from '../../../../services/common.service'; import { CommonService } from '../../../../services/common.service';
import { BoltzService } from '../../../../services/boltz.service'; import { BoltzService } from '../../../../services/boltz.service';
import { openAlert } from '../../../../../store/rtl.actions'; import { openAlert } from '../../../../../store/rtl.actions';
import { RTLState } from '../../../../../store/rtl.state'; import { RTLState } from '../../../../../store/rtl.state';
import { PageSettings, TableSetting } from '../../../../models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../models/pageSettings';
import { lndPageSettings } from '../../../../../lnd/store/lnd.selector'; import { lndPageSettings } from '../../../../../lnd/store/lnd.selector';
import { ApiCallStatusPayload } from '../../../../models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../models/apiCallsPayload';
import { CamelCaseWithReplacePipe } from '../../../../pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-boltz-swaps', selector: 'rtl-boltz-swaps',
@ -35,6 +36,8 @@ export class BoltzSwapsComponent implements OnInit, AfterViewInit, OnChanges, On
@Input() emptyTableMessage = 'No swaps available.'; @Input() emptyTableMessage = 'No swaps available.';
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'boltz'; public PAGE_ID = 'boltz';
public tableSettingSwapOut: TableSetting = { tableId: 'swap_out', recordsPerPage: PAGE_SIZE, sortBy: 'status', sortOrder: SortOrderEnum.DESCENDING }; public tableSettingSwapOut: TableSetting = { tableId: 'swap_out', recordsPerPage: PAGE_SIZE, sortBy: 'status', sortOrder: SortOrderEnum.DESCENDING };
@ -51,7 +54,7 @@ export class BoltzSwapsComponent implements OnInit, AfterViewInit, OnChanges, On
public screenSizeEnum = ScreenSizeEnum; public screenSizeEnum = ScreenSizeEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private boltzService: BoltzService) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private boltzService: BoltzService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -111,6 +114,39 @@ export class BoltzSwapsComponent implements OnInit, AfterViewInit, OnChanges, On
} }
} }
getLabel(column: string) {
const tableId = (this.selectedSwapType === SwapTypeEnum.SWAP_IN) ? this.tableSettingSwapIn.tableId : this.tableSettingSwapOut.tableId;
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.listSwaps.filterPredicate = (swap: Swap, fltr: string) => JSON.stringify(swap).toLowerCase().includes(fltr);
// this.listSwaps.filterPredicate = (rowData: Swap, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
onSwapClick(selSwap: Swap | ReverseSwap, event: any) { onSwapClick(selSwap: Swap | ReverseSwap, event: any) {
this.boltzService.swapInfo(selSwap.id || '').pipe(takeUntil(this.unSubs[1])). this.boltzService.swapInfo(selSwap.id || '').pipe(takeUntil(this.unSubs[1])).
subscribe((fetchedSwap: any) => { subscribe((fetchedSwap: any) => {
@ -153,11 +189,11 @@ export class BoltzSwapsComponent implements OnInit, AfterViewInit, OnChanges, On
} else { } else {
this.listSwaps.sort?.sort({ id: this.tableSettingSwapOut.sortBy, start: this.tableSettingSwapOut.sortOrder, disableClear: true }); this.listSwaps.sort?.sort({ id: this.tableSettingSwapOut.sortBy, start: this.tableSettingSwapOut.sortOrder, disableClear: true });
} }
this.listSwaps.filterPredicate = (swap: Swap, fltr: string) => JSON.stringify(swap).toLowerCase().includes(fltr);
if (this.paginator) { if (this.paginator) {
this.paginator.firstPage(); this.paginator.firstPage();
} }
this.listSwaps.paginator = this.paginator; this.listSwaps.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.listSwaps); this.logger.info(this.listSwaps);
} }

@ -4,9 +4,16 @@
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon> <fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
<span class="page-title">{{swapCaption}} History</span> <span class="page-title">{{swapCaption}} History</span>
</div> </div>
<mat-form-field fxFlex="30"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start center" class="w-100"> <div fxLayout="row" fxLayoutAlign="start center" class="w-100">
<div [perfectScrollbar] class="table-container" fxFlex="100"> <div [perfectScrollbar] class="table-container" fxFlex="100">
@ -46,7 +53,7 @@
<ng-container matColumnDef="htlc_address"> <ng-container matColumnDef="htlc_address">
<th mat-header-cell *matHeaderCellDef mat-sort-header>HTLC Address</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>HTLC Address</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.htlc_address}}</span> <span class="ellipsis-child">{{swap?.htlc_address}}</span>
</span> </span>
</td> </td>
@ -54,7 +61,7 @@
<ng-container matColumnDef="id"> <ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.id}}</span> <span class="ellipsis-child">{{swap?.id}}</span>
</span> </span>
</td> </td>
@ -62,7 +69,7 @@
<ng-container matColumnDef="id_bytes"> <ng-container matColumnDef="id_bytes">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID (Bytes)</th> <th mat-header-cell *matHeaderCellDef mat-sort-header>ID (Bytes)</th>
<td mat-cell *matCellDef="let swap"> <td mat-cell *matCellDef="let swap">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}"> <span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'width': (screenSize === screenSizeEnum.XS) ? '10rem' : colWidth}">
<span class="ellipsis-child">{{swap?.id_bytes}}</span> <span class="ellipsis-child">{{swap?.id_bytes}}</span>
</span> </span>
</td> </td>

@ -8,16 +8,17 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { LoopSwapStatus } from '../../../../models/loopModels'; import { LoopSwapStatus } from '../../../../models/loopModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, LoopTypeEnum, LoopStateEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS } from '../../../../services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, LoopTypeEnum, LoopStateEnum, SortOrderEnum, LND_DEFAULT_PAGE_SETTINGS, LND_PAGE_DEFS } from '../../../../services/consts-enums-functions';
import { LoggerService } from '../../../../services/logger.service'; import { LoggerService } from '../../../../services/logger.service';
import { CommonService } from '../../../../services/common.service'; import { CommonService } from '../../../../services/common.service';
import { LoopService } from '../../../../services/loop.service'; import { LoopService } from '../../../../services/loop.service';
import { RTLState } from '../../../../../store/rtl.state'; import { RTLState } from '../../../../../store/rtl.state';
import { openAlert } from '../../../../../store/rtl.actions'; import { openAlert } from '../../../../../store/rtl.actions';
import { PageSettings, TableSetting } from '../../../../models/pageSettings'; import { ColumnDefinition, PageSettings, TableSetting } from '../../../../models/pageSettings';
import { lndPageSettings } from '../../../../../lnd/store/lnd.selector'; import { lndPageSettings } from '../../../../../lnd/store/lnd.selector';
import { ApiCallStatusPayload } from '../../../../models/apiCallsPayload'; import { ApiCallStatusPayload } from '../../../../models/apiCallsPayload';
import { CamelCaseWithReplacePipe } from '../../../../pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-swaps', selector: 'rtl-swaps',
@ -35,6 +36,8 @@ export class SwapsComponent implements OnInit, AfterViewInit, OnChanges, OnDestr
@Input() emptyTableMessage = 'No swaps available.'; @Input() emptyTableMessage = 'No swaps available.';
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs = LND_PAGE_DEFS;
public selFilterBy = 'all';
public colWidth = '20rem'; public colWidth = '20rem';
public PAGE_ID = 'loop'; public PAGE_ID = 'loop';
public tableSetting: TableSetting = { tableId: 'loop', recordsPerPage: PAGE_SIZE, sortBy: 'initiation_time', sortOrder: SortOrderEnum.DESCENDING }; public tableSetting: TableSetting = { tableId: 'loop', recordsPerPage: PAGE_SIZE, sortBy: 'initiation_time', sortOrder: SortOrderEnum.DESCENDING };
@ -50,7 +53,7 @@ export class SwapsComponent implements OnInit, AfterViewInit, OnChanges, OnDestr
public screenSizeEnum = ScreenSizeEnum; public screenSizeEnum = ScreenSizeEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()]; private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private loopService: LoopService) { constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private loopService: LoopService, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
@ -88,6 +91,38 @@ export class SwapsComponent implements OnInit, AfterViewInit, OnChanges, OnDestr
this.listSwaps.filter = this.selFilter.trim().toLowerCase(); this.listSwaps.filter = this.selFilter.trim().toLowerCase();
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs[this.PAGE_ID][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.listSwaps.filterPredicate = (swap: LoopSwapStatus, fltr: string) => JSON.stringify(swap).toLowerCase().includes(fltr);
// this.listSwaps.filterPredicate = (rowData: LoopSwapStatus, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
onSwapClick(selSwap: LoopSwapStatus, event: any) { onSwapClick(selSwap: LoopSwapStatus, event: any) {
this.loopService.getSwap(selSwap.id_bytes?.replace(/\//g, '_')?.replace(/\+/g, '-') || '').pipe(takeUntil(this.unSubs[1])). this.loopService.getSwap(selSwap.id_bytes?.replace(/\//g, '_')?.replace(/\+/g, '-') || '').pipe(takeUntil(this.unSubs[1])).
subscribe((fetchedSwap: LoopSwapStatus) => { subscribe((fetchedSwap: LoopSwapStatus) => {
@ -120,8 +155,8 @@ export class SwapsComponent implements OnInit, AfterViewInit, OnChanges, OnDestr
this.listSwaps.sort = this.sort; this.listSwaps.sort = this.sort;
this.listSwaps.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.listSwaps.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.listSwaps.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.listSwaps.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.listSwaps.filterPredicate = (swap: LoopSwapStatus, fltr: string) => JSON.stringify(swap).toLowerCase().includes(fltr);
this.listSwaps.paginator = this.paginator; this.listSwaps.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter(); this.applyFilter();
this.logger.info(this.listSwaps); this.logger.info(this.listSwaps);
} }

@ -2,9 +2,16 @@
<div fxLayout="column" fxLayoutAlign="start stretch"> <div fxLayout="column" fxLayoutAlign="start stretch">
<div fxLayout="column" fxLayoutAlign="start stretch" fxLayout.gt-sm="row wrap" class="page-sub-title-container mt-1"> <div fxLayout="column" fxLayoutAlign="start stretch" fxLayout.gt-sm="row wrap" class="page-sub-title-container mt-1">
<div fxFlex="70"></div> <div fxFlex="70"></div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end"> <div fxFlex="30" fxLayoutAlign.gt-xs="space-between center" fxLayout="row" fxLayoutAlign="space-between stretch">
<input matInput [(ngModel)]="filterValue" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter"> <mat-form-field fxFlex="49">
</mat-form-field> <mat-select placeholder="Filter By" tabindex="1" [(ngModel)]="selFilterBy" (selectionChange)="selFilter=''; applyFilter()" name="filterBy">
<mat-option *ngFor="let column of ['all'].concat(displayedColumns.slice(0, -1))" [value]="column">{{getLabel(column)}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="49">
<input matInput [(ngModel)]="selFilter" (input)="applyFilter()" (keyup)="applyFilter()" name="filter" placeholder="Filter">
</mat-form-field>
</div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start start"> <div fxLayout="row" fxLayoutAlign="start start">
<div [perfectScrollbar] fxLayout="column" class="table-container" fxFlex="100"> <div [perfectScrollbar] fxLayout="column" class="table-container" fxFlex="100">

@ -1,16 +1,19 @@
import { Component, ViewChild, Input, AfterViewInit, OnChanges, SimpleChanges, OnInit } from '@angular/core'; import { Component, ViewChild, Input, AfterViewInit, OnChanges, SimpleChanges, OnInit, OnDestroy } from '@angular/core';
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, SCROLL_RANGES, SortOrderEnum } from '../../services/consts-enums-functions'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, SCROLL_RANGES, SortOrderEnum, LND_PAGE_DEFS, CLN_PAGE_DEFS, ECL_PAGE_DEFS } from '../../services/consts-enums-functions';
import { CommonService } from '../../services/common.service'; import { CommonService } from '../../services/common.service';
import { RTLState } from '../../../store/rtl.state'; import { RTLState } from '../../../store/rtl.state';
import { openAlert } from '../../../store/rtl.actions'; import { openAlert } from '../../../store/rtl.actions';
import { TableSetting } from '../../models/pageSettings'; import { ColumnDefinition, TableSetting } from '../../models/pageSettings';
import { Subject, takeUntil } from 'rxjs';
import { rootSelectedNode } from '../../../store/rtl.selector';
import { CamelCaseWithReplacePipe } from '../../pipes/app.pipe';
@Component({ @Component({
selector: 'rtl-transactions-report-table', selector: 'rtl-transactions-report-table',
@ -20,15 +23,17 @@ import { TableSetting } from '../../models/pageSettings';
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Transactions') } { provide: MatPaginatorIntl, useValue: getPaginatorLabel('Transactions') }
] ]
}) })
export class TransactionsReportTableComponent implements OnInit, AfterViewInit, OnChanges { export class TransactionsReportTableComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy {
@Input() dataRange = SCROLL_RANGES[0]; @Input() dataRange = SCROLL_RANGES[0];
@Input() dataList = []; @Input() dataList = [];
@Input() filterValue = ''; @Input() selFilter = '';
@Input() displayedColumns: any[] = ['date', 'amount_paid', 'num_payments', 'amount_received', 'num_invoices']; @Input() displayedColumns: any[] = ['date', 'amount_paid', 'num_payments', 'amount_received', 'num_invoices'];
@Input() tableSetting: TableSetting = { tableId: 'transactions', recordsPerPage: PAGE_SIZE, sortBy: 'date', sortOrder: SortOrderEnum.DESCENDING }; @Input() tableSetting: TableSetting = { tableId: 'transactions', recordsPerPage: PAGE_SIZE, sortBy: 'date', sortOrder: SortOrderEnum.DESCENDING };
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined; @ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined; @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public nodePageDefs: any = LND_PAGE_DEFS;
public selFilterBy = 'all';
public timezoneOffset = new Date(Date.now()).getTimezoneOffset() * 60; public timezoneOffset = new Date(Date.now()).getTimezoneOffset() * 60;
public scrollRanges = SCROLL_RANGES; public scrollRanges = SCROLL_RANGES;
public transactions: any = new MatTableDataSource([]); public transactions: any = new MatTableDataSource([]);
@ -36,12 +41,17 @@ export class TransactionsReportTableComponent implements OnInit, AfterViewInit,
public pageSizeOptions = PAGE_SIZE_OPTIONS; public pageSizeOptions = PAGE_SIZE_OPTIONS;
public screenSize = ''; public screenSize = '';
public screenSizeEnum = ScreenSizeEnum; public screenSizeEnum = ScreenSizeEnum;
unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
constructor(private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe) { constructor(private commonService: CommonService, private store: Store<RTLState>, private datePipe: DatePipe, private camelCaseWithReplace: CamelCaseWithReplacePipe) {
this.screenSize = this.commonService.getScreenSize(); this.screenSize = this.commonService.getScreenSize();
} }
ngOnInit() { ngOnInit() {
this.store.select(rootSelectedNode).pipe(takeUntil(this.unSubs[0])).subscribe((selNode) => {
this.nodePageDefs = (selNode.lnImplementation === 'CLN') ? CLN_PAGE_DEFS : (selNode.lnImplementation === 'ECL') ? ECL_PAGE_DEFS : LND_PAGE_DEFS;
});
this.pageSize = this.tableSetting.recordsPerPage ? +this.tableSetting.recordsPerPage : PAGE_SIZE; this.pageSize = this.tableSetting.recordsPerPage ? +this.tableSetting.recordsPerPage : PAGE_SIZE;
if (this.dataList && this.dataList.length > 0) { if (this.dataList && this.dataList.length > 0) {
this.loadTransactionsTable(this.dataList); this.loadTransactionsTable(this.dataList);
@ -57,7 +67,7 @@ export class TransactionsReportTableComponent implements OnInit, AfterViewInit,
this.pageSize = this.tableSetting.recordsPerPage ? +this.tableSetting.recordsPerPage : PAGE_SIZE; this.pageSize = this.tableSetting.recordsPerPage ? +this.tableSetting.recordsPerPage : PAGE_SIZE;
this.loadTransactionsTable(this.dataList); this.loadTransactionsTable(this.dataList);
} }
if (changes.filterValue && !changes.filterValue.firstChange) { if (changes.selFilter && !changes.selFilter.firstChange) {
this.applyFilter(); this.applyFilter();
} }
} }
@ -83,10 +93,45 @@ export class TransactionsReportTableComponent implements OnInit, AfterViewInit,
applyFilter() { applyFilter() {
if (this.transactions) { if (this.transactions) {
this.transactions.filter = this.filterValue.trim().toLowerCase(); this.transactions.filter = this.selFilter.trim().toLowerCase();
} }
} }
getLabel(column: string) {
const returnColumn: ColumnDefinition = this.nodePageDefs['reports'][this.tableSetting.tableId].allowedColumns.find((col) => col.column === column);
return returnColumn ? returnColumn.label ? returnColumn.label : this.camelCaseWithReplace.transform(returnColumn.column, '_') : 'all';
}
setFilterPredicate() {
this.transactions.filterPredicate = (rowData: any, fltr: string) => {
const newRowData = ((rowData.date) ? (this.datePipe.transform(rowData.date, 'dd/MMM') + '/' + rowData.date.getFullYear()).toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
// this.transactions.filterPredicate = (rowData: LoopSwapStatus, fltr: string) => {
// let rowToFilter = '';
// switch (this.selFilterBy) {
// case 'all':
// for (let i = 0; i < this.displayedColumns.length - 1; i++) {
// rowToFilter = rowToFilter + (
// (this.displayedColumns[i] === '') ?
// (rowData ? rowData..toLowerCase() : '') :
// (rowData[this.displayedColumns[i]] ? rowData[this.displayedColumns[i]].toLowerCase() : '')
// ) + ', ';
// }
// break;
// case '':
// rowToFilter = (rowData ? rowData..toLowerCase() : '');
// break;
// default:
// rowToFilter = (rowData[this.selFilterBy] ? rowData[this.selFilterBy].toLowerCase() : '');
// break;
// }
// return rowToFilter.includes(fltr);
// };
}
loadTransactionsTable(trans: any[]) { loadTransactionsTable(trans: any[]) {
this.transactions = trans ? new MatTableDataSource([...trans]) : new MatTableDataSource([]); this.transactions = trans ? new MatTableDataSource([...trans]) : new MatTableDataSource([]);
this.setTableWidgets(); this.setTableWidgets();
@ -97,11 +142,9 @@ export class TransactionsReportTableComponent implements OnInit, AfterViewInit,
this.transactions.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null); this.transactions.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.transactions.sort = this.sort; this.transactions.sort = this.sort;
this.transactions.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true }); this.transactions.sort?.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.transactions.filterPredicate = (rowData: any, fltr: string) => {
const newRowData = ((rowData.date) ? (this.datePipe.transform(rowData.date, 'dd/MMM') + '/' + rowData.date.getFullYear()).toLowerCase() : '') + JSON.stringify(rowData).toLowerCase();
return newRowData.includes(fltr);
};
this.transactions.paginator = this.paginator; this.transactions.paginator = this.paginator;
this.setFilterPredicate();
this.applyFilter();
} }
} }
@ -111,4 +154,11 @@ export class TransactionsReportTableComponent implements OnInit, AfterViewInit,
} }
} }
ngOnDestroy(): void {
this.unSubs.forEach((unsub) => {
unsub.next();
unsub.complete();
});
}
} }

Loading…
Cancel
Save