CLT Show the output lists on the On-chain section #403pull/412/head
parent
d953277d83
commit
541e47b6e5
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
!function(e){function r(r){for(var n,a,i=r[0],f=r[1],c=r[2],p=0,s=[];p<i.length;p++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,c||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"9bb271dd8dffd2d994a5",6:"7fdbfcfcbc66f0a2e343",7:"8bea433e66622a5b697f",8:"cb92f279297c13fff1d8"}[e]+".js"}(e);var f=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(c);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;f.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",f.name="ChunkLoadError",f.type=n,f.request=u,t[1](f)}o[e]=void 0}};var c=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],f=i.push.bind(i);i.push=r,i=i.slice();for(var c=0;c<i.length;c++)r(i[c]);var l=f;t()}([]);
|
||||
!function(e){function r(r){for(var n,a,i=r[0],f=r[1],c=r[2],p=0,s=[];p<i.length;p++)a=i[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,c||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++)0!==o[t[i]]&&(n=!1);n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={0:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+""+({}[e]||e)+"."+{1:"9bb271dd8dffd2d994a5",6:"f4a00973b8204a828cfd",7:"8bea433e66622a5b697f",8:"cb92f279297c13fff1d8"}[e]+".js"}(e);var f=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(c);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;f.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",f.name="ChunkLoadError",f.type=n,f.request=u,t[1](f)}o[e]=void 0}};var c=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,(function(r){return e[r]}).bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="",a.oe=function(e){throw console.error(e),e};var i=window.webpackJsonp=window.webpackJsonp||[],f=i.push.bind(i);i.push=r,i=i.slice();for(var c=0;c<i.length;c++)r(i[c]);var l=f;t()}([]);
|
@ -0,0 +1,68 @@
|
||||
<div fxLayout="row wrap" fxLayoutAlign="start start" fxLayout.gt-sm="column" fxFlex="100" fxLayoutAlign.gt-sm="start stretch" class="padding-gap-x-large">
|
||||
<div fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
|
||||
<div fxFlex="70">
|
||||
<fa-icon [icon]="faHistory" class="page-title-img mr-1"></fa-icon>
|
||||
<span class="page-title">UTXOs</span>
|
||||
</div>
|
||||
<mat-form-field fxFlex="30">
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div fxLayout="row" fxLayoutAlign="start start">
|
||||
<div perfectScrollbar class="table-container" fxFlex="100">
|
||||
<mat-progress-bar *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
|
||||
<table mat-table #table [dataSource]="listTransactions" matSort
|
||||
[ngClass]="{'overflow-auto error-border': flgLoading[0]==='error','overflow-auto': true}">
|
||||
<ng-container matColumnDef="txid">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Transaction ID </th>
|
||||
<td mat-cell *matCellDef="let transaction">
|
||||
<div class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '50rem'}">
|
||||
<span *ngIf="transaction.status === 'confirmed'" class="dot green" matTooltip="Confirmed" matTooltipPosition="right"></span>
|
||||
<span *ngIf="transaction.status !== 'confirmed'" class="dot yellow" matTooltip="{{transaction.status | titlecase}}" matTooltipPosition="right"></span>
|
||||
<span class="ellipsis-child">{{transaction.txid}}</span>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="output">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Output </th>
|
||||
<td mat-cell *matCellDef="let transaction"><span fxLayoutAlign="end center">
|
||||
{{transaction?.output | number}} </span></td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="value">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Value (Sats) </th>
|
||||
<td mat-cell *matCellDef="let transaction">
|
||||
<span fxLayoutAlign="end center" *ngIf="transaction.value > 0 || transaction.value === 0">{{transaction.value | number}}</span>
|
||||
<span fxLayoutAlign="end center" class="red" *ngIf="transaction.value < 0">({{transaction.value * -1 | number}})</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="blockheight">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Blockheight </th>
|
||||
<td mat-cell *matCellDef="let transaction"><span fxLayoutAlign="end center">
|
||||
{{transaction?.blockheight | number}} </span></td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef class="px-3">
|
||||
<div class="bordered-box table-actions-select">
|
||||
<mat-select placeholder="Actions" tabindex="1" class="mr-0">
|
||||
<mat-select-trigger></mat-select-trigger>
|
||||
<mat-option (click)="onDownloadCSV()">Download CSV</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let transaction" class="pl-3" fxLayoutAlign="end center">
|
||||
<button mat-stroked-button color="primary" type="button" tabindex="4" (click)="onTransactionClick(transaction, $event)">View Info</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="no_transaction">
|
||||
<td mat-footer-cell *matFooterCellDef colspan="4">
|
||||
<p *ngIf="!listTransactions.data || listTransactions.data.length<1">No transactions available.</p>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-footer-row *matFooterRowDef="['no_transaction']" [ngClass]="{'display-none': listTransactions.data && listTransactions.data.length>0}"></tr>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: flgSticky;"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="pageSizeOptions" [showFirstLastButtons]="screenSize === screenSizeEnum.XS ? false : true" class="mb-4"></mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,11 @@
|
||||
.mat-column-txid {
|
||||
flex: 0 0 15%;
|
||||
width: 15%;
|
||||
& .ellipsis-parent {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-column-actions {
|
||||
min-height: 4.8rem;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CLOnChainTransactionHistoryComponent } from './on-chain-transaction-history.component';
|
||||
|
||||
describe('CLOnChainTransactionHistoryComponent', () => {
|
||||
let component: CLOnChainTransactionHistoryComponent;
|
||||
let fixture: ComponentFixture<CLOnChainTransactionHistoryComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CLOnChainTransactionHistoryComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CLOnChainTransactionHistoryComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,121 @@
|
||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Actions } from '@ngrx/effects';
|
||||
import { faHistory } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { Transaction } from '../../../shared/models/clModels';
|
||||
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum } from '../../../shared/services/consts-enums-functions';
|
||||
import { LoggerService } from '../../../shared/services/logger.service';
|
||||
import { CommonService } from '../../../shared/services/common.service';
|
||||
|
||||
import * as CLActions from '../../store/cl.actions';
|
||||
import * as RTLActions from '../../../store/rtl.actions';
|
||||
import * as fromRTLReducer from '../../../store/rtl.reducers';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-cl-on-chain-transaction-history',
|
||||
templateUrl: './on-chain-transaction-history.component.html',
|
||||
styleUrls: ['./on-chain-transaction-history.component.scss'],
|
||||
providers: [
|
||||
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('Transactions') }
|
||||
]
|
||||
})
|
||||
export class CLOnChainTransactionHistoryComponent implements OnInit, OnDestroy {
|
||||
@ViewChild(MatSort, { static: true }) sort: MatSort;
|
||||
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
|
||||
faHistory = faHistory;
|
||||
public displayedColumns = [];
|
||||
public listTransactions: any;
|
||||
public flgLoading: Array<Boolean | 'error'> = [true];
|
||||
public flgSticky = false;
|
||||
public pageSize = PAGE_SIZE;
|
||||
public pageSizeOptions = PAGE_SIZE_OPTIONS;
|
||||
public screenSize = '';
|
||||
public screenSizeEnum = ScreenSizeEnum;
|
||||
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
|
||||
|
||||
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<fromRTLReducer.RTLState>, private actions$: Actions) {
|
||||
this.screenSize = this.commonService.getScreenSize();
|
||||
if(this.screenSize === ScreenSizeEnum.XS) {
|
||||
this.flgSticky = false;
|
||||
this.displayedColumns = ['txid', 'value', 'actions'];
|
||||
} else if(this.screenSize === ScreenSizeEnum.SM) {
|
||||
this.flgSticky = false;
|
||||
this.displayedColumns = ['txid', 'output', 'value', 'blockheight', 'actions'];
|
||||
} else if(this.screenSize === ScreenSizeEnum.MD) {
|
||||
this.flgSticky = false;
|
||||
this.displayedColumns = ['txid', 'output', 'value', 'blockheight', 'actions'];
|
||||
} else {
|
||||
this.flgSticky = true;
|
||||
this.displayedColumns = ['txid', 'output', 'value', 'blockheight', 'actions'];
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.store.dispatch(new CLActions.FetchTransactions());
|
||||
this.store.select('cl')
|
||||
.pipe(takeUntil(this.unsub[0]))
|
||||
.subscribe((rtlStore) => {
|
||||
rtlStore.effectErrors.forEach(effectsErr => {
|
||||
if (effectsErr.action === 'FetchTransactions') {
|
||||
this.flgLoading[0] = 'error';
|
||||
}
|
||||
});
|
||||
if (rtlStore.transactions) {
|
||||
this.loadTransactionsTable(rtlStore.transactions);
|
||||
}
|
||||
if (this.flgLoading[0] !== 'error') {
|
||||
this.flgLoading[0] = (rtlStore.transactions) ? false : true;
|
||||
}
|
||||
this.logger.info(rtlStore);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
applyFilter(selFilter: string) {
|
||||
this.listTransactions.filter = selFilter;
|
||||
}
|
||||
|
||||
onTransactionClick(selTransaction: Transaction, event: any) {
|
||||
const reorderedTransactions = [
|
||||
[{key: 'txid', value: selTransaction.txid, title: 'Transaction ID', width: 100}],
|
||||
[{key: 'output', value: selTransaction.output, title: 'Output', width: 50, type: DataTypeEnum.NUMBER},
|
||||
{key: 'value', value: selTransaction.value, title: 'Value (Sats)', width: 50, type: DataTypeEnum.NUMBER}],
|
||||
[{key: 'status', value: this.commonService.titleCase(selTransaction.status), title: 'Status', width: 50, type: DataTypeEnum.STRING},
|
||||
{key: 'blockheight', value: selTransaction.blockheight, title: 'Blockheight', width: 50, type: DataTypeEnum.NUMBER}],
|
||||
[{key: 'address', value: selTransaction.address, title: 'Address', width: 100}],
|
||||
];
|
||||
this.store.dispatch(new RTLActions.OpenAlert({ data: {
|
||||
type: AlertTypeEnum.INFORMATION,
|
||||
alertTitle: 'Transaction Information',
|
||||
message: reorderedTransactions
|
||||
}}));
|
||||
}
|
||||
|
||||
loadTransactionsTable(transactions) {
|
||||
this.listTransactions = new MatTableDataSource<Transaction>([...transactions]);
|
||||
this.listTransactions.sort = this.sort;
|
||||
this.listTransactions.sortingDataAccessor = (data, sortHeaderId) => (data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : +data[sortHeaderId];
|
||||
this.listTransactions.paginator = this.paginator;
|
||||
this.logger.info(this.listTransactions);
|
||||
}
|
||||
|
||||
onDownloadCSV() {
|
||||
if(this.listTransactions.data && this.listTransactions.data.length > 0) {
|
||||
this.commonService.downloadFile(this.listTransactions.data, 'Transactions');
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unsub.forEach(completeSub => {
|
||||
completeSub.next();
|
||||
completeSub.complete();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1 +1 @@
|
||||
export const VERSION = '0.8.4-beta';
|
||||
export const VERSION = '0.9.0-beta';
|
Loading…
Reference in New Issue