Channel pagination
This commit is contained in:
@@ -34,7 +34,7 @@ export class AddressLabelsComponent implements OnChanges {
|
||||
}
|
||||
|
||||
handleChannel() {
|
||||
this.label = `Channel open: ${this.channel.alias_left} <> ${this.channel.alias_right}`;
|
||||
this.label = `Channel open: ${this.channel.node_left.alias} <> ${this.channel.node_right.alias}`;
|
||||
}
|
||||
|
||||
handleVin() {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ChannelBoxComponent } from './channel-box.component';
|
||||
|
||||
describe('ChannelBoxComponent', () => {
|
||||
let component: ChannelBoxComponent;
|
||||
let fixture: ComponentFixture<ChannelBoxComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ChannelBoxComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ChannelBoxComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,44 +1,39 @@
|
||||
<div>
|
||||
<div *ngIf="channels$ | async as response; else skeleton">
|
||||
<h2 class="float-left">Channels ({{ response.totalItems }})</h2>
|
||||
|
||||
<form [formGroup]="channelStatusForm" class="formRadioGroup float-right">
|
||||
<div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="status">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'open'" fragment="open"> Open
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'closed'" fragment="closed"> Closed
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<th class="alias text-left" i18n="nodes.alias">Node Alias</th>
|
||||
<th class="alias text-left d-none d-md-table-cell" i18n="channels.transaction"> </th>
|
||||
<th class="alias text-left d-none d-md-table-cell" i18n="nodes.alias">Status</th>
|
||||
<th class="channels text-left d-none d-md-table-cell" i18n="channels.rate">Fee Rate</th>
|
||||
<th class="capacity text-right d-none d-md-table-cell" i18n="nodes.capacity">Capacity</th>
|
||||
<th class="capacity text-left" i18n="channels.id">Channel ID</th>
|
||||
</thead>
|
||||
<tbody *ngIf="channels$ | async as channels; else skeleton">
|
||||
<tr *ngFor="let channel of channels; let i = index;">
|
||||
<ng-container *ngTemplateOutlet="tableHeader"></ng-container>
|
||||
<tbody>
|
||||
<tr *ngFor="let channel of response.channels; let i = index;">
|
||||
<ng-container *ngTemplateOutlet="tableTemplate; context: { $implicit: channel, node: channel.node_left.public_key === publicKey ? channel.node_right : channel.node_left }"></ng-container>
|
||||
</tr>
|
||||
</tbody>
|
||||
<ng-template #skeleton>
|
||||
<tbody>
|
||||
<tr *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
|
||||
<td class="alias text-left" style="width: 370px;">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="alias text-left">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="capacity text-left d-none d-md-table-cell">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="channels text-left d-none d-md-table-cell">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="channels text-right d-none d-md-table-cell">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="channels text-left">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</ng-template>
|
||||
</table>
|
||||
|
||||
<ngb-pagination class="pagination-container float-right" [size]="paginationSize" [collectionSize]="response.totalItems" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="page" (pageChange)="pageChange(page)" [maxSize]="paginationMaxSize" [boundaryLinks]="true" [ellipses]="false"></ngb-pagination>
|
||||
</div>
|
||||
|
||||
<ng-template #tableHeader>
|
||||
<thead>
|
||||
<th class="alias text-left" i18n="nodes.alias">Node Alias</th>
|
||||
<th class="alias text-left d-none d-md-table-cell" i18n="channels.transaction"> </th>
|
||||
<th class="alias text-left d-none d-md-table-cell" i18n="nodes.alias">Status</th>
|
||||
<th class="channels text-left d-none d-md-table-cell" i18n="channels.rate">Fee Rate</th>
|
||||
<th class="capacity text-right d-none d-md-table-cell" i18n="nodes.capacity">Capacity</th>
|
||||
<th class="capacity text-right" i18n="channels.id">Channel ID</th>
|
||||
</thead>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #tableTemplate let-channel let-node="node">
|
||||
<td class="alias text-left">
|
||||
@@ -50,7 +45,7 @@
|
||||
<app-clipboard [text]="node.public_key" size="small"></app-clipboard>
|
||||
</div>
|
||||
</td>
|
||||
<td class="alias text-left">
|
||||
<td class="alias text-left d-none d-md-table-cell">
|
||||
<div class="second-line">{{ node.channels }} channels</div>
|
||||
<div class="second-line"><app-amount [satoshis]="node.capacity" digitsInfo="1.2-2"></app-amount></div>
|
||||
</td>
|
||||
@@ -65,7 +60,37 @@
|
||||
<td class="capacity text-right d-none d-md-table-cell">
|
||||
<app-amount [satoshis]="channel.capacity" digitsInfo="1.2-2"></app-amount>
|
||||
</td>
|
||||
<td class="capacity text-left">
|
||||
<td class="capacity text-right">
|
||||
<a [routerLink]="['/lightning/channel' | relativeUrl, channel.id]">{{ channel.short_id }}</a>
|
||||
</td>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #skeleton>
|
||||
<h2 class="float-left">Channels</h2>
|
||||
|
||||
<table class="table table-borderless">
|
||||
<ng-container *ngTemplateOutlet="tableHeader"></ng-container>
|
||||
<tbody>
|
||||
<tr *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
|
||||
<td class="alias text-left" style="width: 370px;">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="alias text-left">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="capacity text-left d-none d-md-table-cell">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="channels text-left d-none d-md-table-cell">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="channels text-right d-none d-md-table-cell">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
<td class="channels text-left">
|
||||
<span class="skeleton-loader"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</ng-template>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { BehaviorSubject, combineLatest, merge, Observable, of } from 'rxjs';
|
||||
import { map, startWith, switchMap } from 'rxjs/operators';
|
||||
import { LightningApiService } from '../lightning-api.service';
|
||||
|
||||
@Component({
|
||||
@@ -8,16 +10,53 @@ import { LightningApiService } from '../lightning-api.service';
|
||||
styleUrls: ['./channels-list.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ChannelsListComponent implements OnChanges {
|
||||
export class ChannelsListComponent implements OnInit, OnChanges {
|
||||
@Input() publicKey: string;
|
||||
channels$: Observable<any[]>;
|
||||
channels$: Observable<any>;
|
||||
|
||||
// @ts-ignore
|
||||
paginationSize: 'sm' | 'lg' = 'md';
|
||||
paginationMaxSize = 10;
|
||||
itemsPerPage = 25;
|
||||
page = 1;
|
||||
channelsPage$ = new BehaviorSubject<number>(1);
|
||||
channelStatusForm: FormGroup;
|
||||
defaultStatus = 'open';
|
||||
|
||||
constructor(
|
||||
private lightningApiService: LightningApiService,
|
||||
) { }
|
||||
private formBuilder: FormBuilder,
|
||||
) {
|
||||
this.channelStatusForm = this.formBuilder.group({
|
||||
status: [this.defaultStatus],
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (document.body.clientWidth < 670) {
|
||||
this.paginationSize = 'sm';
|
||||
this.paginationMaxSize = 3;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.channels$ = this.lightningApiService.getChannelsByNodeId$(this.publicKey);
|
||||
this.channels$ = combineLatest([
|
||||
this.channelsPage$,
|
||||
this.channelStatusForm.get('status').valueChanges.pipe(startWith(this.defaultStatus))
|
||||
])
|
||||
.pipe(
|
||||
switchMap(([page, status]) =>this.lightningApiService.getChannelsByNodeId$(this.publicKey, (page -1) * this.itemsPerPage, status)),
|
||||
map((response) => {
|
||||
return {
|
||||
channels: response.body,
|
||||
totalItems: parseInt(response.headers.get('x-total-count'), 10)
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
pageChange(page: number) {
|
||||
this.channelsPage$.next(page);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,12 +20,14 @@ export class LightningApiService {
|
||||
return this.httpClient.get<any>(API_BASE_URL + '/channels/' + shortId);
|
||||
}
|
||||
|
||||
getChannelsByNodeId$(publicKey: string): Observable<any> {
|
||||
getChannelsByNodeId$(publicKey: string, index: number = 0, status = 'open'): Observable<any> {
|
||||
let params = new HttpParams()
|
||||
.set('public_key', publicKey)
|
||||
.set('index', index)
|
||||
.set('status', status)
|
||||
;
|
||||
|
||||
return this.httpClient.get<any>(API_BASE_URL + '/channels', { params });
|
||||
return this.httpClient.get<any>(API_BASE_URL + '/channels', { params, observe: 'response' });
|
||||
}
|
||||
|
||||
getLatestStatistics$(): Observable<any> {
|
||||
|
||||
@@ -88,7 +88,6 @@
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<h2>Channels</h2>
|
||||
|
||||
<app-channels-list [publicKey]="node.public_key"></app-channels-list>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user