Payments incomplete & max column validation

pull/1127/head
ShahanaFarooqui 2 years ago
parent 7a0bd37d91
commit 24013f6f89

@ -27,11 +27,22 @@
<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>
<table mat-table #table fxFlex="100" [dataSource]="payments" matSort [ngClass]="{'overflow-auto error-border': errorMessage !== '','overflow-auto': true}">
<ng-container matColumnDef="created_at">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Created At</th>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header></th>
<td mat-cell *matCellDef="let payment">
<span *ngIf="payment.status === 'complete'" class="dot green" matTooltip="Completed" matTooltipPosition="right" [ngClass]="{'mr-0': screenSize === screenSizeEnum.XS}"></span>
<span *ngIf="payment.status !== 'complete'" class="dot yellow" matTooltip="Failed" matTooltipPosition="right" [ngClass]="{'mr-0': screenSize === screenSizeEnum.XS}"></span>
</td>
</ng-container>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let payment">
{{payment?.id}}
</td>
</ng-container>
<ng-container matColumnDef="created_at">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Created At</th>
<td mat-cell *matCellDef="let payment">
{{(payment?.created_at * 1000) | date:'dd/MMM/y HH:mm'}}
</td>
</ng-container>
@ -47,16 +58,48 @@
</span>
</td>
</ng-container>
<ng-container matColumnDef="bolt11">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Invoice</th>
<td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '20rem'}">
<span class="ellipsis-child">{{payment?.bolt11}}</span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="label">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Label</th>
<td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '30rem'}">
<span class="ellipsis-child">{{payment?.label}}</span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="destination">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Destination</th>
<td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '30rem'}">
<span class="ellipsis-child">{{payment?.destination}}</span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="memo">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Memo</th>
<td mat-cell *matCellDef="let payment">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '30rem'}">
<span class="ellipsis-child">{{payment?.memo}}</span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="msatoshi_sent">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Sats Sent</th>
<td mat-cell *matCellDef="let payment"><span fxLayoutAlign="end center">{{payment?.msatoshi_sent/1000 | number:payment?.msatoshi_sent < 1000 ? '1.0-4' : '1.0-0'}}</span></td>
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before" class="px-1">Sats Sent</th>
<td mat-cell *matCellDef="let payment" class="px-1"><span fxLayoutAlign="end center">{{payment?.msatoshi_sent/1000 | number:payment?.msatoshi_sent < 1000 ? '1.0-4' : '1.0-0'}}</span></td>
</ng-container>
<ng-container matColumnDef="msatoshi">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before">Sats Received</th>
<td mat-cell *matCellDef="let payment"><span fxLayoutAlign="end center">{{payment?.msatoshi/1000 | number:payment?.msatoshi < 1000 ? '1.0-4' : '1.0-0'}}</span></td>
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before" class="px-1">Sats Received</th>
<td mat-cell *matCellDef="let payment" class="px-1"><span fxLayoutAlign="end center">{{payment?.msatoshi/1000 | number:payment?.msatoshi < 1000 ? '1.0-4' : '1.0-0'}}</span></td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="px-3">
<th mat-header-cell *matHeaderCellDef class="pr-3">
<div class="bordered-box table-actions-select">
<mat-select placeholder="Actions" tabindex="1" class="mr-0">
<mat-select-trigger></mat-select-trigger>
@ -64,15 +107,15 @@
</mat-select>
</div>
</th>
<td mat-cell *matCellDef="let payment" class="px-3" fxLayoutAlign="end center">
<td mat-cell *matCellDef="let payment" class="pr-3" fxLayoutAlign="end center">
<button mat-stroked-button color="primary" type="button" tabindex="4" (click)="onPaymentClick(payment)">View Info</button>
</td>
</ng-container>
<ng-container matColumnDef="no_payment">
<td mat-footer-cell *matFooterCellDef colspan="4">
<p *ngIf="(!payments?.data || payments?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.COMPLETED">No payment available.</p>
<p *ngIf="(!payments?.data || payments?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.INITIATED">Getting payments...</p>
<p *ngIf="(!payments?.data || payments?.data?.length<1) && apiCallStatus?.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
<p *ngIf="(!payments?.data || !payments?.data?.length) && apiCallStatus?.status === apiCallStatusEnum.COMPLETED">No payment available.</p>
<p *ngIf="(!payments?.data || !payments?.data?.length) && apiCallStatus?.status === apiCallStatusEnum.INITIATED">Getting payments...</p>
<p *ngIf="(!payments?.data || !payments?.data?.length) && apiCallStatus?.status === apiCallStatusEnum.ERROR">{{errorMessage}}</p>
</td>
</ng-container>
@ -145,7 +188,7 @@
</ng-container>
<tr mat-row *matRowDef="let row; columns: mppColumns; when: is_group;"></tr>
<!-- Payment Group Row End -->
<tr mat-footer-row *matFooterRowDef="['no_payment']" [ngClass]="{'display-none': payments?.data && payments?.data?.length>0}"></tr>
<tr mat-footer-row *matFooterRowDef="['no_payment']" [ngClass]="{'display-none': payments?.data && payments?.data?.length && payments?.data?.length>0}"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns; when: !is_group;"></tr>
</table>

@ -1,6 +1,10 @@
.mat-column-payment_hash {
flex: 0 0 25%;
width: 25%;
.mat-column-status {
max-width: 0.1rem;
}
.mat-column-payment_hash, .mat-column-bolt11, .mat-column-destination, .mat-column-label, .mat-column-memo {
flex: 0 0 10%;
width: 10%;
& .ellipsis-parent {
display: flex;
}

@ -9,7 +9,7 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
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 } 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_TABLES_DEF, CLN_DEFAULT_PAGE_SETTINGS } from '../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../shared/models/apiCallsPayload';
import { DataService } from '../../../shared/services/data.service';
import { LoggerService } from '../../../shared/services/logger.service';
@ -23,7 +23,8 @@ import { RTLEffects } from '../../../store/rtl.effects';
import { RTLState } from '../../../store/rtl.state';
import { openAlert, openConfirmation } from '../../../store/rtl.actions';
import { sendPayment } from '../../store/cln.actions';
import { clnNodeInformation, clnNodeSettings, payments } from '../../store/cln.selector';
import { clnNodeInformation, clnNodeSettings, clnPageSettings, payments } from '../../store/cln.selector';
import { PageSettingsCLN } from '../../../shared/models/pageSettings';
@Component({
selector: 'rtl-cln-lightning-payments',
@ -39,6 +40,8 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
@ViewChild('sendPaymentForm', { static: false }) form;
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
public PAGE_ID = 'payments';
public TABLE_ID = 'payments';
public faHistory = faHistory;
public newlyAddedPayment = '';
public selNode: SelNodeChild | null = {};
@ -56,28 +59,29 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
public screenSize = '';
public screenSizeEnum = ScreenSizeEnum;
public errorMessage = '';
public pageSettings: PageSettingsCLN[] = [];
public selFilter = '';
public apiCallStatus: ApiCallStatusPayload | null = null;
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(), 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) {
this.screenSize = this.commonService.getScreenSize();
if (this.screenSize === ScreenSizeEnum.XS) {
this.flgSticky = false;
this.displayedColumns = ['created_at', 'actions'];
// this.displayedColumns = ['created_at', 'actions'];
this.mppColumns = ['groupTotal', 'groupAction'];
} else if (this.screenSize === ScreenSizeEnum.SM) {
this.flgSticky = false;
this.displayedColumns = ['created_at', 'msatoshi', 'actions'];
// this.displayedColumns = ['created_at', 'msatoshi', 'actions'];
this.mppColumns = ['groupTotal', 'groupAmtRecv', 'groupAction'];
} else if (this.screenSize === ScreenSizeEnum.MD) {
this.flgSticky = false;
this.displayedColumns = ['created_at', 'type', 'msatoshi_sent', 'msatoshi', 'actions'];
// this.displayedColumns = ['created_at', 'type', 'msatoshi_sent', 'msatoshi', 'actions'];
this.mppColumns = ['groupTotal', 'groupType', 'groupAmtSent', 'groupAmtRecv', 'groupAction'];
} else {
this.flgSticky = true;
this.displayedColumns = ['created_at', 'type', 'payment_hash', 'msatoshi_sent', 'msatoshi', 'actions'];
// this.displayedColumns = ['created_at', 'type', 'payment_hash', 'msatoshi_sent', 'msatoshi', 'actions'];
this.mppColumns = ['groupTotal', 'groupType', 'groupHash', 'groupAmtSent', 'groupAmtRecv', 'groupAction'];
}
}
@ -89,7 +93,20 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
this.store.select(clnNodeInformation).pipe(takeUntil(this.unSubs[1])).subscribe((nodeInfo: GetInfo) => {
this.information = nodeInfo;
});
this.store.select(payments).pipe(takeUntil(this.unSubs[2])).
this.store.select(clnPageSettings).pipe(takeUntil(this.unSubs[2])).
subscribe((settings: { pageSettings: PageSettingsCLN[], apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessage = '';
this.apiCallStatus = settings.apiCallStatus;
if (this.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessage = this.apiCallStatus.message || '';
}
this.pageSettings = settings.pageSettings;
this.displayedColumns = JSON.parse(JSON.stringify(this.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.TABLE_ID)?.showColumns || CLN_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.TABLE_ID)?.showColumns));
this.displayedColumns.unshift('status');
this.displayedColumns.push('actions');
this.logger.info(this.displayedColumns);
});
this.store.select(payments).pipe(takeUntil(this.unSubs[3])).
subscribe((paymentsSeletor: { payments: Payment[], apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessage = '';
this.apiCallStatus = paymentsSeletor.apiCallStatus;
@ -97,7 +114,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
this.errorMessage = !this.apiCallStatus.message ? '' : (typeof (this.apiCallStatus.message) === 'object') ? JSON.stringify(this.apiCallStatus.message) : this.apiCallStatus.message;
}
this.paymentJSONArr = paymentsSeletor.payments || [];
if (this.paymentJSONArr.length > 0 && this.sort && this.paginator) {
if (this.paymentJSONArr.length && this.paymentJSONArr.length > 0 && this.sort && this.paginator) {
this.loadPaymentsTable(this.paymentJSONArr);
}
this.logger.info(paymentsSeletor);
@ -105,7 +122,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
}
ngAfterViewInit() {
if (this.paymentJSONArr.length > 0 && this.sort && this.paginator) {
if (this.paymentJSONArr.length && this.paymentJSONArr.length > 0 && this.sort && this.paginator) {
this.loadPaymentsTable(this.paymentJSONArr);
}
}
@ -122,7 +139,7 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
this.sendPayment();
} else {
this.dataService.decodePayment(this.paymentRequest, false).
pipe(takeUntil(this.unSubs[1])).subscribe((decodedPayment: PayRequest) => {
pipe(takeUntil(this.unSubs[4])).subscribe((decodedPayment: PayRequest) => {
this.paymentDecoded = decodedPayment;
if (this.paymentDecoded.created_at) {
if (!this.paymentDecoded.msatoshi) {
@ -210,12 +227,12 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
this.paymentDecodedHint = '';
if (this.paymentRequest && this.paymentRequest.length > 100) {
this.dataService.decodePayment(this.paymentRequest, false).
pipe(takeUntil(this.unSubs[1])).subscribe((decodedPayment: PayRequest) => {
pipe(takeUntil(this.unSubs[5])).subscribe((decodedPayment: PayRequest) => {
this.paymentDecoded = decodedPayment;
if (this.paymentDecoded.msatoshi) {
if (this.selNode?.fiatConversion) {
this.commonService.convertCurrency(this.paymentDecoded.msatoshi ? this.paymentDecoded.msatoshi / 1000 : 0, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, (this.selNode.currencyUnits && this.selNode.currencyUnits.length > 2 ? this.selNode.currencyUnits[2] : ''), this.selNode.fiatConversion).
pipe(takeUntil(this.unSubs[3])).
pipe(takeUntil(this.unSubs[6])).
subscribe({
next: (data) => {
this.paymentDecodedHint = 'Sending: ' + this.decimalPipe.transform(this.paymentDecoded.msatoshi ? this.paymentDecoded.msatoshi / 1000 : 0) + ' Sats (' + data.symbol + this.decimalPipe.transform((data.OTHER ? data.OTHER : 0), CURRENCY_UNIT_FORMATS.OTHER) + ') | Memo: ' + this.paymentDecoded.description;

@ -34,10 +34,11 @@
</mat-form-field>
<mat-form-field fxFlex="68">
<mat-select [(ngModel)]="table.showColumns" (selectionChange)="onShowColumnsChange(table)" placeholder="Show Columns" name="{{table.tableId}}-show-columns" tabindex="4" multiple required>
<mat-option *ngFor="let field of tableFieldsDef[table.tableId]" [value]="field" [disabled]="table.showColumns.length < 3 && table.showColumns.includes(field)">
<mat-option *ngFor="let field of tableFieldsDef[table.tableId].allowedColumns" [value]="field" [disabled]="(table.showColumns.length <= 2 && table.showColumns.includes(field)) || (table.showColumns.length >= tableFieldsDef[table.tableId].maxColumns && !table.showColumns.includes(field))">
{{field | camelcaseWithReplace:'_'}}
</mat-option>
</mat-select>
<mat-hint>Total selected columns should be between 2 and {{tableFieldsDef[table.tableId].maxColumns}}</mat-hint>
</mat-form-field>
</div>
</div>

@ -5,7 +5,7 @@ import { Store } from '@ngrx/store';
import { Actions } from '@ngrx/effects';
import { faPenRuler, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import { APICallStatusEnum, CLNActions, CLN_DEFAULT_PAGE_SETTINGS, CLN_TABLE_FIELDS_DEF, PAGE_SIZE_OPTIONS, ScreenSizeEnum, SORT_ORDERS } from '../../../services/consts-enums-functions';
import { APICallStatusEnum, CLNActions, CLN_DEFAULT_PAGE_SETTINGS, CLN_TABLES_DEF, PAGE_SIZE_OPTIONS, ScreenSizeEnum, SORT_ORDERS } from '../../../services/consts-enums-functions';
import { LoggerService } from '../../../services/logger.service';
import { CommonService } from '../../../services/common.service';
import { RTLState } from '../../../../store/rtl.state';
@ -28,7 +28,7 @@ export class PageSettingsComponent implements OnInit, OnDestroy {
public pageSizeOptions = PAGE_SIZE_OPTIONS;
public pageSettings: PageSettingsCLN[] = [];
public initialPageSettings: PageSettingsCLN[] = CLN_DEFAULT_PAGE_SETTINGS;
public tableFieldsDef = CLN_TABLE_FIELDS_DEF;
public tableFieldsDef = CLN_TABLES_DEF;
public sortOrders = SORT_ORDERS;
public apiCallStatus: ApiCallStatusPayload | null = null;
public apiCallStatusEnum = APICallStatusEnum;

@ -681,7 +681,13 @@ export const CLN_DEFAULT_PAGE_SETTINGS: PageSettingsCLN[] = [
showColumns: ['expires_at', 'paid_at', 'type', 'description', 'msatoshi', 'msatoshi_received'] }] }
];
export const CLN_TABLE_FIELDS_DEF = {
payments: ['created_at', 'type', 'payment_hash', 'msatoshi_sent', 'msatoshi', 'amount_msat', 'amount_sent_msat', 'destination', 'status', 'memo'],
invoices: ['expires_at', 'paid_at', 'type', 'description', 'msatoshi', 'msatoshi_received', 'label', 'payment_hash', 'amount_msat', 'status', 'amount_received_msat']
export const CLN_TABLES_DEF = {
payments: {
maxColumns: 6,
allowedColumns: ['id', 'created_at', 'type', 'payment_hash', 'msatoshi_sent', 'msatoshi', 'bolt11', 'destination', 'memo', 'label']
},
invoices: {
maxColumns: 5,
allowedColumns: ['expires_at', 'paid_at', 'type', 'description', 'msatoshi', 'msatoshi_received', 'label', 'payment_hash', 'status']
}
};

Loading…
Cancel
Save