Search bar refactored with Nodes and Channels
This commit is contained in:
parent
1ed4c93b94
commit
8604869e5e
@ -21,7 +21,7 @@ export class QrcodeComponent implements AfterViewInit {
|
|||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
if (!this.canvas.nativeElement) {
|
if (!this.canvas || !this.canvas.nativeElement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.render();
|
this.render();
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
<form [formGroup]="searchForm" (submit)="searchForm.valid && search()" novalidate>
|
<form [formGroup]="searchForm" (submit)="searchForm.valid && search()" novalidate>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div class="search-box-container mr-2">
|
<div class="search-box-container mr-2">
|
||||||
<input #instance="ngbTypeahead" [ngbTypeahead]="typeaheadSearchFn" [resultFormatter]="formatterFn" (selectItem)="itemSelected()" (focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)" formControlName="searchText" type="text" class="form-control" i18n-placeholder="search-form.searchbar-placeholder" placeholder="TXID, block height, hash or address">
|
<input (focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)" formControlName="searchText" type="text" class="form-control" i18n-placeholder="search-form.searchbar-placeholder" placeholder="TXID, block height, hash or address">
|
||||||
|
|
||||||
|
<app-search-results #searchResults [results]="typeAhead$ | async" [searchTerm]="searchForm.get('searchText').value" (selectedResult)="selectedResult($event)"></app-search-results>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button [disabled]="isSearching" type="submit" class="btn btn-block btn-primary"><fa-icon [icon]="['fas', 'search']" [fixedWidth]="true" i18n-title="search-form.search-title" title="Search"></fa-icon></button>
|
<button [disabled]="isSearching" type="submit" class="btn btn-block btn-primary"><fa-icon [icon]="['fas', 'search']" [fixedWidth]="true" i18n-title="search-form.search-title" title="Search"></fa-icon></button>
|
||||||
|
@ -32,6 +32,7 @@ form {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.search-box-container {
|
.search-box-container {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
min-width: 400px;
|
min-width: 400px;
|
||||||
@ -48,4 +49,4 @@ form {
|
|||||||
.btn {
|
.btn {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,41 +1,40 @@
|
|||||||
import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output, ViewChild } from '@angular/core';
|
import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output, ViewChild, HostListener } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { AssetsService } from 'src/app/services/assets.service';
|
import { AssetsService } from 'src/app/services/assets.service';
|
||||||
import { StateService } from 'src/app/services/state.service';
|
import { StateService } from 'src/app/services/state.service';
|
||||||
import { Observable, of, Subject, merge } from 'rxjs';
|
import { Observable, of, Subject, merge, zip } from 'rxjs';
|
||||||
import { debounceTime, distinctUntilChanged, switchMap, filter, catchError, map } from 'rxjs/operators';
|
import { debounceTime, distinctUntilChanged, switchMap, filter, catchError, map } from 'rxjs/operators';
|
||||||
import { ElectrsApiService } from 'src/app/services/electrs-api.service';
|
import { ElectrsApiService } from 'src/app/services/electrs-api.service';
|
||||||
import { NgbTypeahead } from '@ng-bootstrap/ng-bootstrap';
|
|
||||||
import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe';
|
import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe';
|
||||||
import { ShortenStringPipe } from 'src/app/shared/pipes/shorten-string-pipe/shorten-string.pipe';
|
import { ApiService } from 'src/app/services/api.service';
|
||||||
|
import { SearchResultsComponent } from './search-results/search-results.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-search-form',
|
selector: 'app-search-form',
|
||||||
templateUrl: './search-form.component.html',
|
templateUrl: './search-form.component.html',
|
||||||
styleUrls: ['./search-form.component.scss'],
|
styleUrls: ['./search-form.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class SearchFormComponent implements OnInit {
|
export class SearchFormComponent implements OnInit {
|
||||||
network = '';
|
network = '';
|
||||||
assets: object = {};
|
assets: object = {};
|
||||||
isSearching = false;
|
isSearching = false;
|
||||||
typeaheadSearchFn: ((text: Observable<string>) => Observable<readonly any[]>);
|
typeAhead$: Observable<any>;
|
||||||
|
|
||||||
searchForm: FormGroup;
|
searchForm: FormGroup;
|
||||||
isMobile = (window.innerWidth <= 767.98);
|
|
||||||
@Output() searchTriggered = new EventEmitter();
|
|
||||||
|
|
||||||
regexAddress = /^([a-km-zA-HJ-NP-Z1-9]{26,35}|[a-km-zA-HJ-NP-Z1-9]{80}|[a-z]{2,5}1[ac-hj-np-z02-9]{8,100}|[A-Z]{2,5}1[AC-HJ-NP-Z02-9]{8,100})$/;
|
regexAddress = /^([a-km-zA-HJ-NP-Z1-9]{26,35}|[a-km-zA-HJ-NP-Z1-9]{80}|[a-z]{2,5}1[ac-hj-np-z02-9]{8,100}|[A-Z]{2,5}1[AC-HJ-NP-Z02-9]{8,100})$/;
|
||||||
regexBlockhash = /^[0]{8}[a-fA-F0-9]{56}$/;
|
regexBlockhash = /^[0]{8}[a-fA-F0-9]{56}$/;
|
||||||
regexTransaction = /^([a-fA-F0-9]{64}):?(\d+)?$/;
|
regexTransaction = /^([a-fA-F0-9]{64}):?(\d+)?$/;
|
||||||
regexBlockheight = /^[0-9]+$/;
|
regexBlockheight = /^[0-9]+$/;
|
||||||
|
|
||||||
@ViewChild('instance', {static: true}) instance: NgbTypeahead;
|
|
||||||
focus$ = new Subject<string>();
|
focus$ = new Subject<string>();
|
||||||
click$ = new Subject<string>();
|
click$ = new Subject<string>();
|
||||||
|
|
||||||
formatterFn = (address: string) => this.shortenStringPipe.transform(address, this.isMobile ? 33 : 40);
|
@Output() searchTriggered = new EventEmitter();
|
||||||
|
@ViewChild('searchResults') searchResults: SearchResultsComponent;
|
||||||
|
@HostListener('keydown', ['$event']) keydown($event) {
|
||||||
|
this.handleKeyDown($event);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
@ -43,12 +42,11 @@ export class SearchFormComponent implements OnInit {
|
|||||||
private assetsService: AssetsService,
|
private assetsService: AssetsService,
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private electrsApiService: ElectrsApiService,
|
private electrsApiService: ElectrsApiService,
|
||||||
|
private apiService: ApiService,
|
||||||
private relativeUrlPipe: RelativeUrlPipe,
|
private relativeUrlPipe: RelativeUrlPipe,
|
||||||
private shortenStringPipe: ShortenStringPipe,
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.typeaheadSearchFn = this.typeaheadSearch;
|
|
||||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||||
|
|
||||||
this.searchForm = this.formBuilder.group({
|
this.searchForm = this.formBuilder.group({
|
||||||
@ -61,43 +59,63 @@ export class SearchFormComponent implements OnInit {
|
|||||||
this.assets = assets;
|
this.assets = assets;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
typeaheadSearch = (text$: Observable<string>) => {
|
this.typeAhead$ = this.searchForm.get('searchText').valueChanges
|
||||||
const debouncedText$ = text$.pipe(
|
|
||||||
map((text) => {
|
|
||||||
if (this.network === 'bisq' && text.match(/^(b)[^c]/i)) {
|
|
||||||
return text.substr(1);
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}),
|
|
||||||
debounceTime(200),
|
|
||||||
distinctUntilChanged()
|
|
||||||
);
|
|
||||||
const clicksWithClosedPopup$ = this.click$.pipe(filter(() => !this.instance.isPopupOpen()));
|
|
||||||
const inputFocus$ = this.focus$;
|
|
||||||
|
|
||||||
return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$)
|
|
||||||
.pipe(
|
.pipe(
|
||||||
|
map((text) => {
|
||||||
|
if (this.network === 'bisq' && text.match(/^(b)[^c]/i)) {
|
||||||
|
return text.substr(1);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}),
|
||||||
|
debounceTime(300),
|
||||||
|
distinctUntilChanged(),
|
||||||
switchMap((text) => {
|
switchMap((text) => {
|
||||||
if (!text.length) {
|
if (!text.length) {
|
||||||
return of([]);
|
return of([
|
||||||
|
[],
|
||||||
|
{
|
||||||
|
nodes: [],
|
||||||
|
channels: [],
|
||||||
|
}
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
return this.electrsApiService.getAddressesByPrefix$(text).pipe(catchError(() => of([])));
|
return zip(
|
||||||
|
this.electrsApiService.getAddressesByPrefix$(text).pipe(catchError(() => of([]))),
|
||||||
|
this.apiService.lightningSearch$(text),
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
map((result: string[]) => {
|
map((result: any[]) => {
|
||||||
if (this.network === 'bisq') {
|
if (this.network === 'bisq') {
|
||||||
return result.map((address: string) => 'B' + address);
|
return result[0].map((address: string) => 'B' + address);
|
||||||
}
|
}
|
||||||
return result;
|
return {
|
||||||
|
addresses: result[0],
|
||||||
|
nodes: result[1].nodes,
|
||||||
|
channels: result[1].channels,
|
||||||
|
totalResults: result[0].length + result[1].nodes.length + result[1].channels.length,
|
||||||
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
handleKeyDown($event) {
|
||||||
|
this.searchResults.handleKeyDown($event);
|
||||||
|
}
|
||||||
|
|
||||||
itemSelected() {
|
itemSelected() {
|
||||||
setTimeout(() => this.search());
|
setTimeout(() => this.search());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectedResult(result: any) {
|
||||||
|
if (typeof result === 'string') {
|
||||||
|
this.navigate('/address/', result);
|
||||||
|
} else if (result.alias) {
|
||||||
|
this.navigate('/lightning/node/', result.public_key);
|
||||||
|
} else if (result.short_id) {
|
||||||
|
this.navigate('/lightning/channel/', result.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
search() {
|
search() {
|
||||||
const searchText = this.searchForm.value.searchText.trim();
|
const searchText = this.searchForm.value.searchText.trim();
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
<div class="dropdown-menu show" *ngIf="results" [hidden]="!results.addresses.length && !results.nodes.length && !results.channels.length">
|
||||||
|
<ng-template [ngIf]="results.addresses.length">
|
||||||
|
<div class="card-title">Bitcoin Addresses</div>
|
||||||
|
<ng-template ngFor [ngForOf]="results.addresses" let-address let-i="index">
|
||||||
|
<button (click)="clickItem(i)" [class.active]="i === activeIdx" type="button" role="option" class="dropdown-item">
|
||||||
|
<ngb-highlight [result]="address | shortenString : isMobile ? 25 : 36" [term]="searchTerm"></ngb-highlight>
|
||||||
|
</button>
|
||||||
|
</ng-template>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template [ngIf]="results.nodes.length">
|
||||||
|
<div class="card-title">Lightning Nodes</div>
|
||||||
|
<ng-template ngFor [ngForOf]="results.nodes" let-node let-i="index">
|
||||||
|
<button (click)="clickItem(results.addresses.length + i)" [class.active]="results.addresses.length + i === activeIdx" [routerLink]="['/lightning/node' | relativeUrl, node.public_key]" type="button" role="option" class="dropdown-item">
|
||||||
|
<ngb-highlight [result]="node.alias" [term]="searchTerm"></ngb-highlight> <span class="symbol">{{ node.public_key | shortenString : 10 }}</span>
|
||||||
|
</button>
|
||||||
|
</ng-template>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template [ngIf]="results.channels.length">
|
||||||
|
<div class="card-title">Lightning Channels</div>
|
||||||
|
<ng-template [class.active]="results.addresses.length + results.nodes.length + i === activeIdx" ngFor [ngForOf]="results.channels" let-channel let-i="index">
|
||||||
|
<button (click)="clickItem(results.addresses.length + results.nodes.length + i)" type="button" role="option" class="dropdown-item">
|
||||||
|
<ngb-highlight [result]="channel.short_id" [term]="searchTerm"></ngb-highlight> <span class="symbol">{{ channel.id }}</span>
|
||||||
|
</button>
|
||||||
|
</ng-template>
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
@ -0,0 +1,16 @@
|
|||||||
|
.card-title {
|
||||||
|
color: #4a68b9;
|
||||||
|
font-size: 10px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 1rem;
|
||||||
|
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: 42px;
|
||||||
|
left: 0px;
|
||||||
|
box-shadow: 0.125rem 0.125rem 0.25rem rgba(0,0,0,0.075);
|
||||||
|
width: 100%;
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-search-results',
|
||||||
|
templateUrl: './search-results.component.html',
|
||||||
|
styleUrls: ['./search-results.component.scss'],
|
||||||
|
})
|
||||||
|
export class SearchResultsComponent implements OnChanges {
|
||||||
|
@Input() results: any = {};
|
||||||
|
@Input() searchTerm = '';
|
||||||
|
@Output() selectedResult = new EventEmitter();
|
||||||
|
|
||||||
|
isMobile = (window.innerWidth <= 767.98);
|
||||||
|
resultsFlattened = [];
|
||||||
|
activeIdx = 0;
|
||||||
|
focusFirst = true;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnChanges() {
|
||||||
|
this.activeIdx = 0;
|
||||||
|
if (this.results) {
|
||||||
|
this.resultsFlattened = [...this.results.addresses, ...this.results.nodes, ...this.results.channels];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleKeyDown(event: KeyboardEvent) {
|
||||||
|
switch (event.key) {
|
||||||
|
case 'ArrowDown':
|
||||||
|
event.preventDefault();
|
||||||
|
this.next();
|
||||||
|
break;
|
||||||
|
case 'ArrowUp':
|
||||||
|
event.preventDefault();
|
||||||
|
this.prev();
|
||||||
|
break;
|
||||||
|
case 'Enter':
|
||||||
|
event.preventDefault();
|
||||||
|
this.selectedResult.emit(this.resultsFlattened[this.activeIdx]);
|
||||||
|
this.results = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clickItem(id: number) {
|
||||||
|
this.selectedResult.emit(this.resultsFlattened[id]);
|
||||||
|
this.results = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
next() {
|
||||||
|
if (this.activeIdx === this.resultsFlattened.length - 1) {
|
||||||
|
this.activeIdx = this.focusFirst ? (this.activeIdx + 1) % this.resultsFlattened.length : -1;
|
||||||
|
} else {
|
||||||
|
this.activeIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev() {
|
||||||
|
if (this.activeIdx < 0) {
|
||||||
|
this.activeIdx = this.resultsFlattened.length - 1;
|
||||||
|
} else if (this.activeIdx === 0) {
|
||||||
|
this.activeIdx = this.focusFirst ? this.resultsFlattened.length - 1 : -1;
|
||||||
|
} else {
|
||||||
|
this.activeIdx--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,7 +5,7 @@ import { Outspend, Transaction, Vin, Vout } from '../../interfaces/electrs.inter
|
|||||||
import { ElectrsApiService } from '../../services/electrs-api.service';
|
import { ElectrsApiService } from '../../services/electrs-api.service';
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
import { AssetsService } from 'src/app/services/assets.service';
|
import { AssetsService } from 'src/app/services/assets.service';
|
||||||
import { map, tap, switchMap } from 'rxjs/operators';
|
import { filter, map, tap, switchMap } from 'rxjs/operators';
|
||||||
import { BlockExtended } from 'src/app/interfaces/node-api.interface';
|
import { BlockExtended } from 'src/app/interfaces/node-api.interface';
|
||||||
import { ApiService } from 'src/app/services/api.service';
|
import { ApiService } from 'src/app/services/api.service';
|
||||||
|
|
||||||
@ -78,6 +78,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
|||||||
),
|
),
|
||||||
this.refreshChannels$
|
this.refreshChannels$
|
||||||
.pipe(
|
.pipe(
|
||||||
|
filter(() => this.stateService.env.LIGHTNING),
|
||||||
switchMap((txIds) => this.apiService.getChannelByTxIds$(txIds)),
|
switchMap((txIds) => this.apiService.getChannelByTxIds$(txIds)),
|
||||||
map((channels) => {
|
map((channels) => {
|
||||||
this.channels = channels;
|
this.channels = channels;
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<thead>
|
<thead>
|
||||||
<th class="alias text-left" i18n="nodes.alias">Node Alias</th>
|
<th class="alias text-left" i18n="nodes.alias">Node Alias</th>
|
||||||
<th class="alias text-left" i18n="channels.transaction">Node ID</th>
|
<th class="alias text-left d-none d-md-table-cell" i18n="channels.transaction">Node ID</th>
|
||||||
<th class="alias text-left" i18n="nodes.alias">Status</th>
|
<th class="alias text-left d-none d-md-table-cell" i18n="nodes.alias">Status</th>
|
||||||
<th class="channels text-right" i18n="channels.rate">Fee Rate</th>
|
<th class="channels text-right d-none d-md-table-cell" i18n="channels.rate">Fee Rate</th>
|
||||||
<th class="capacity text-right" i18n="nodes.capacity">Capacity</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>
|
<th class="capacity text-right" i18n="channels.id">Channel ID</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody *ngIf="channels$ | async as channels; else skeleton">
|
<tbody *ngIf="channels$ | async as channels; else skeleton">
|
||||||
@ -15,18 +15,18 @@
|
|||||||
<td class="alias text-left">
|
<td class="alias text-left">
|
||||||
{{ channel.alias_left || '?' }}
|
{{ channel.alias_left || '?' }}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-left">
|
<td class="text-left d-none d-md-table-cell">
|
||||||
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]">
|
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node1_public_key]">
|
||||||
<span>{{ channel.node1_public_key | shortenString : 10 }}</span>
|
<span>{{ channel.node1_public_key | shortenString : 10 }}</span>
|
||||||
</a>
|
</a>
|
||||||
<app-clipboard [text]="channel.node1_public_key"></app-clipboard>
|
<app-clipboard [text]="channel.node1_public_key"></app-clipboard>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="d-none d-md-table-cell">
|
||||||
<span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
|
<span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
|
||||||
<span class="badge rounded-pill badge-success" *ngIf="channel.status === 1">Active</span>
|
<span class="badge rounded-pill badge-success" *ngIf="channel.status === 1">Active</span>
|
||||||
<span class="badge rounded-pill badge-danger" *ngIf="channel.status === 2">Closed</span>
|
<span class="badge rounded-pill badge-danger" *ngIf="channel.status === 2">Closed</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="capacity text-right">
|
<td class="capacity text-right d-none d-md-table-cell">
|
||||||
{{ channel.node1_fee_rate / 10000 | number }}%
|
{{ channel.node1_fee_rate / 10000 | number }}%
|
||||||
</td>
|
</td>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -34,22 +34,22 @@
|
|||||||
<td class="alias text-left">
|
<td class="alias text-left">
|
||||||
{{ channel.alias_right || '?' }}
|
{{ channel.alias_right || '?' }}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-left">
|
<td class="text-left d-none d-md-table-cell">
|
||||||
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]">
|
<a [routerLink]="['/lightning/node' | relativeUrl, channel.node2_public_key]">
|
||||||
<span>{{ channel.node2_public_key | shortenString : 10 }}</span>
|
<span>{{ channel.node2_public_key | shortenString : 10 }}</span>
|
||||||
</a>
|
</a>
|
||||||
<app-clipboard [text]="channel.node2_public_key"></app-clipboard>
|
<app-clipboard [text]="channel.node2_public_key"></app-clipboard>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="d-none d-md-table-cell">
|
||||||
<span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
|
<span class="badge rounded-pill badge-secondary" *ngIf="channel.status === 0">Inactive</span>
|
||||||
<span class="badge rounded-pill badge-success" *ngIf="channel.status === 1">Active</span>
|
<span class="badge rounded-pill badge-success" *ngIf="channel.status === 1">Active</span>
|
||||||
<span class="badge rounded-pill badge-danger" *ngIf="channel.status === 2">Closed</span>
|
<span class="badge rounded-pill badge-danger" *ngIf="channel.status === 2">Closed</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="capacity text-right">
|
<td class="capacity text-right d-none d-md-table-cell">
|
||||||
{{ channel.node2_fee_rate / 10000 | number }}%
|
{{ channel.node2_fee_rate / 10000 | number }}%
|
||||||
</td>
|
</td>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<td class="capacity text-right">
|
<td class="capacity text-right d-none d-md-table-cell">
|
||||||
<app-amount [satoshis]="channel.capacity" digitsInfo="1.2-2"></app-amount>
|
<app-amount [satoshis]="channel.capacity" digitsInfo="1.2-2"></app-amount>
|
||||||
</td>
|
</td>
|
||||||
<td class="capacity text-right">
|
<td class="capacity text-right">
|
||||||
@ -66,13 +66,13 @@
|
|||||||
<td class="alias text-left">
|
<td class="alias text-left">
|
||||||
<span class="skeleton-loader"></span>
|
<span class="skeleton-loader"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="capacity text-left">
|
<td class="capacity text-left d-none d-md-table-cell">
|
||||||
<span class="skeleton-loader"></span>
|
<span class="skeleton-loader"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="channels text-left">
|
<td class="channels text-left d-none d-md-table-cell">
|
||||||
<span class="skeleton-loader"></span>
|
<span class="skeleton-loader"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="channels text-right">
|
<td class="channels text-right d-none d-md-table-cell">
|
||||||
<span class="skeleton-loader"></span>
|
<span class="skeleton-loader"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="channels text-right">
|
<td class="channels text-right">
|
||||||
|
@ -47,7 +47,6 @@ export class NodeComponent implements OnInit {
|
|||||||
socket: node.public_key + '@' + socket,
|
socket: node.public_key + '@' + socket,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log(socketsObject);
|
|
||||||
node.socketsObject = socketsObject;
|
node.socketsObject = socketsObject;
|
||||||
return node;
|
return node;
|
||||||
}),
|
}),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user