Browse Source

web-ui: improvements on block details view (#19)

transactions for the block are now retrieved separately, the
transactions table is paginated and shows more info and
finally the view now is mobile friendly
prometheus-integration
Mario Mejia 7 years ago
committed by Alexis Hernandez
parent
commit
b6a98d1ffa
  1. 70
      web-ui/src/app/components/block-details/block-details.component.html
  2. 35
      web-ui/src/app/components/block-details/block-details.component.ts
  3. 7
      web-ui/src/app/services/blocks.service.ts

70
web-ui/src/app/components/block-details/block-details.component.html

@ -4,15 +4,15 @@
</div> </div>
<div *ngIf="blockDetails != null"> <div *ngIf="blockDetails != null">
<div class="row"> <div class="row">
<h2 class="col-xs-12 col-sm-12 col-md-12 col-lg-12">{{'label.block' | translate}} #{{blockDetails.block.height}}</h2> <h2 class="col-xs-12">{{'label.block' | translate}} #{{blockDetails.block.height}}</h2>
</div>
<div class="col-xs-12 col-sm-12 col-md-7 col-lg-7"> <div class="col-xs-12 col-md-7">
<div class="table-responsive">
<table class="table table-condensed table-bordered table-striped table-hover"> <table class="table table-condensed table-bordered table-striped table-hover">
<thead> <thead>
<tr> <tr>
<th class="col-xs-4 col-sm-4 col-md-3 col-lg-9">{{'label.summary' | translate}}</th> <th class="col-xs-4 col-md-3 col-lg-9">{{'label.summary' | translate}}</th>
<th class="col-xs-8 col-sm-8 col-md-3 col-lg-9"></th> <th class="col-xs-8 col-md-3 col-lg-9"></th>
</tr> </tr>
</thead> </thead>
@ -24,7 +24,9 @@
</tr> </tr>
<tr *ngIf="isTPoS(blockDetails)"> <tr *ngIf="isTPoS(blockDetails)">
<td>{{'label.tposContract' | translate}}</td> <td>{{'label.tposContract' | translate}}</td>
<td><a routerLink="/transactions/{{blockDetails.block.tposContract}}">{{blockDetails.block.tposContract}}</a></td> <td>
<a routerLink="/transactions/{{blockDetails.block.tposContract}}">{{blockDetails.block.tposContract}}</a>
</td>
</tr> </tr>
<tr> <tr>
<td>{{'label.blockhash' | translate}}</td> <td>{{'label.blockhash' | translate}}</td>
@ -89,24 +91,27 @@
</tbody> </tbody>
</table> </table>
</div> </div>
</div>
<!-- rewards --> <!-- rewards -->
<div class="col-xs-12 col-sm-12 col-md-offset-1 col-md-4 col-lg-offset-1 col-lg-4"> <div class="col-xs-12 col-md-offset-1 col-md-4">
<div class="table-responsive">
<!-- PoW --> <!-- PoW -->
<div *ngIf="isPoW(blockDetails)"> <div *ngIf="isPoW(blockDetails)">
<table class="table table-condensed table-bordered table-striped table-hover"> <table class="table table-condensed table-bordered table-striped table-hover">
<thead> <thead>
<tr> <tr>
<th class="col-xs-2 col-sm-2 col-md-1 col-lg-1">{{'label.blockReward' | translate}}</th> <th class="col-xs-2 col-md-1">{{'label.blockReward' | translate}}</th>
<th class="col-xs-2 col-sm-2 col-md-1 col-lg-1">{{blockDetails.rewards.reward.value}} {{'label.coinName' | translate}}</th> <th class="col-xs-2 col-md-1">{{blockDetails.rewards.reward.value}} {{'label.coinName' | translate}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td>{{'label.address' | translate}}</td> <td>{{'label.address' | translate}}</td>
<td><a routerLink="/addresses/{{blockDetails.rewards.reward.address}}">{{blockDetails.rewards.reward.address}}</a></td> <td>
<a routerLink="/addresses/{{blockDetails.rewards.reward.address}}">{{blockDetails.rewards.reward.address}}</a>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -117,8 +122,8 @@
<table class="table table-condensed table-bordered table-striped table-hover"> <table class="table table-condensed table-bordered table-striped table-hover">
<thead> <thead>
<tr> <tr>
<th class="col-xs-2 col-sm-2 col-md-1 col-lg-1">{{'label.rewards' | translate}}</th> <th class="col-xs-2 col-md-1">{{'label.rewards' | translate}}</th>
<th class="col-xs-2 col-sm-2 col-md-1 col-lg-1">{{getPoSTotalReward(blockDetails)}} {{'label.coinName' | translate}}</th> <th class="col-xs-2 col-md-1">{{getPoSTotalReward(blockDetails)}} {{'label.coinName' | translate}}</th>
</tr> </tr>
</thead> </thead>
@ -128,7 +133,9 @@
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td><strong>{{'label.coinstake' | translate}}</strong></td> <td>
<strong>{{'label.coinstake' | translate}}</strong>
</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
@ -146,7 +153,9 @@
<td></td> <td></td>
</tr> </tr>
<tr *ngIf="blockDetails.rewards.masternode != null"> <tr *ngIf="blockDetails.rewards.masternode != null">
<td><strong>{{'label.masternode' | translate}}</strong></td> <td>
<strong>{{'label.masternode' | translate}}</strong>
</td>
<td></td> <td></td>
</tr> </tr>
<tr *ngIf="blockDetails.rewards.masternode != null"> <tr *ngIf="blockDetails.rewards.masternode != null">
@ -168,8 +177,8 @@
<table class="table table-condensed table-bordered table-striped table-hover"> <table class="table table-condensed table-bordered table-striped table-hover">
<thead> <thead>
<tr> <tr>
<th class="col-xs-2 col-sm-2 col-md-1 col-lg-1">{{'label.rewards' | translate}}</th> <th class="col-xs-2 col-md-1">{{'label.rewards' | translate}}</th>
<th class="col-xs-2 col-sm-2 col-md-1 col-lg-1">{{getTPoSTotalReward(blockDetails)}} {{'label.coinName' | translate}}</th> <th class="col-xs-2 col-md-1">{{getTPoSTotalReward(blockDetails)}} {{'label.coinName' | translate}}</th>
</tr> </tr>
</thead> </thead>
@ -240,24 +249,43 @@
</table> </table>
</div> </div>
</div> </div>
</div>
<!-- transactions --> <!-- transactions -->
<div class="col-xs-12 col-sm-12 col-md-offset-2 col-md-8 col-lg-offset-2 col-lg-8"> <div class="col-xs-12 col-md-offset-2 col-md-8">
<div class="table-responsive">
<table class="table table-condensed table-bordered table-striped table-hover"> <table class="table table-condensed table-bordered table-striped table-hover">
<thead> <thead>
<tr> <tr>
<th class="col-xs-2 col-sm-2 col-md-1 col-lg-1">{{'label.transactions' | translate}}</th> <th class="col-xs-1">#</th>
<th class="col-xs-4">{{'label.transaction' | translate}}</th>
<th class="col-xs-3">{{'label.date' | translate}}</th>
<th class="col-xs-2">{{'label.value' | translate}}</th>
<th class="col-xs-2">{{'label.size' | translate}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let item of blockDetails.block.transactions"> <tr *ngFor="let index = index; let item of asyncItems | async | paginate: { id: 'transactions', itemsPerPage: pageSize, currentPage: currentPage, totalItems: total }">
<td>{{(currentPage - 1) * pageSize + index + 1}}</td>
<td> <td>
<a routerLink="/transactions/{{item}}">{{item}}</a> <a routerLink="/transactions/{{item.id}}">{{item.id | slice:0:35}}...</a>
</td> </td>
<td>{{item.time * 1000 | explorerDatetime}}</td>
<td>{{item.sent}} {{'label.coinName' | translate}}</td>
<td>{{item.size}} bytes</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="row">
<div class="col-xs-11 col-xs-offset-1 col-sm-5 col-sm-offset-4">
<pagination-controls (pageChange)="getPage($event)" id="transactions" previousLabel="" nextLabel="">
</pagination-controls>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>

35
web-ui/src/app/components/block-details/block-details.component.ts

@ -1,9 +1,10 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs/Observable';
import { BlockDetails } from '../../models/block'; import { BlockDetails } from '../../models/block';
import { Transaction } from '../../models/transaction';
import { BlocksService } from '../../services/blocks.service'; import { BlocksService } from '../../services/blocks.service';
import { ErrorService } from '../../services/error.service'; import { ErrorService } from '../../services/error.service';
@ -16,8 +17,15 @@ import { NavigatorService } from '../../services/navigator.service';
}) })
export class BlockDetailsComponent implements OnInit { export class BlockDetailsComponent implements OnInit {
blockhash: string;
blockDetails: BlockDetails; blockDetails: BlockDetails;
// pagination
total = 0;
currentPage = 1;
pageSize = 10;
asyncItems: Observable<Transaction[]>;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
@ -30,17 +38,40 @@ export class BlockDetailsComponent implements OnInit {
} }
private onBlockhash(blockhash: string) { private onBlockhash(blockhash: string) {
this.blockDetails = null; this.clearCurrentValues();
this.blockhash = blockhash;
this.blocksService.get(blockhash).subscribe( this.blocksService.get(blockhash).subscribe(
response => this.onBlockRetrieved(response), response => this.onBlockRetrieved(response),
response => this.onError(response) response => this.onError(response)
); );
this.getPage(this.currentPage);
}
private clearCurrentValues() {
this.blockhash = null;
this.blockDetails = null;
this.total = 0;
this.currentPage = 1;
this.pageSize = 10;
this.asyncItems = null;
} }
private onBlockRetrieved(response: BlockDetails) { private onBlockRetrieved(response: BlockDetails) {
this.blockDetails = response; this.blockDetails = response;
} }
getPage(page: number) {
const offset = (page - 1) * this.pageSize;
const limit = this.pageSize;
const order = 'time:desc';
this.asyncItems = this.blocksService
.getTransactions(this.blockhash, offset, limit, order)
.do(response => this.total = response.total)
.do(response => this.currentPage = 1 + (response.offset / this.pageSize))
.map(response => response.data)
}
private onError(response: any) { private onError(response: any) {
this.errorService.renderServerErrors(null, response); this.errorService.renderServerErrors(null, response);
} }

7
web-ui/src/app/services/blocks.service.ts

@ -5,6 +5,8 @@ import { Observable } from 'rxjs/Observable';
import { environment } from '../../environments/environment'; import { environment } from '../../environments/environment';
import { Block, BlockDetails } from '../models/block'; import { Block, BlockDetails } from '../models/block';
import { PaginatedResult } from '../models/paginated-result';
import { Transaction } from '../models/transaction';
const httpOptions = { const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }) headers: new HttpHeaders({ 'Content-Type': 'application/json' })
@ -27,6 +29,11 @@ export class BlocksService {
return this.http.get<any>(url); return this.http.get<any>(url);
} }
getTransactions(hash: string, offset: number = 0, limit: number = 10, orderBy: string = ''): Observable<PaginatedResult<Transaction>> {
const url = `${this.baseUrl}/${hash}/transactions?offset=${offset}&limit=${limit}&orderBy=${orderBy}`;
return this.http.get<PaginatedResult<Transaction>>(url);
}
getLatest(): Observable<Block[]> { getLatest(): Observable<Block[]> {
return this.http.get<Block[]>(this.baseUrl); return this.http.get<Block[]>(this.baseUrl);
} }

Loading…
Cancel
Save