Invert the tooltip legends order.
Fix default data to title tooltip MM/dd HH:mm. Add symbol to tx chart tooltip . Add accumulative total for tooltip information. Add 3th column to tooltip with a progress bar. Add and max span zoom span. Add feeRate limit input to mempool graph component. Add showZoom option to mempool graph component. Remove start animation to match the layout for future SSR. Remove mouse wheel zoom from small template. Fix small template style.
This commit is contained in:
parent
1a7decb91d
commit
f434e50a2c
@ -15,8 +15,8 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
|
||||
@Input() height: number | string = '200';
|
||||
@Input() right: number | string = '10';
|
||||
@Input() top: number | string = '20';
|
||||
@Input() left: number | string = '50';
|
||||
@Input() size: ('small' | 'big') = 'small';
|
||||
@Input() left: number | string = '0';
|
||||
@Input() template: ('widget' | 'advanced') = 'widget';
|
||||
|
||||
mempoolStatsChartOption: EChartsOption = {};
|
||||
windowPreference: string;
|
||||
@ -43,11 +43,15 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
|
||||
top: this.top,
|
||||
left: this.left,
|
||||
},
|
||||
animation: false,
|
||||
dataZoom: [{
|
||||
type: 'inside',
|
||||
realtime: true,
|
||||
zoomOnMouseWheel: (this.template === 'advanced') ? true : false,
|
||||
maxSpan: 100,
|
||||
minSpan: 10,
|
||||
}, {
|
||||
show: (this.size === 'big') ? true : false,
|
||||
show: (this.template === 'advanced') ? true : false,
|
||||
type: 'slider',
|
||||
brushSelect: false,
|
||||
realtime: true,
|
||||
@ -68,7 +72,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
|
||||
obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 80;
|
||||
return obj;
|
||||
},
|
||||
extraCssText: `width: ${(['2h', '24h'].includes(this.windowPreference) || this.size === 'small') ? '125px' : '135px'};
|
||||
extraCssText: `width: ${(['2h', '24h'].includes(this.windowPreference) || this.template === 'widget') ? '125px' : '135px'};
|
||||
background: transparent;
|
||||
border: none;
|
||||
box-shadow: none;`,
|
||||
@ -76,18 +80,18 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges {
|
||||
type: 'line',
|
||||
},
|
||||
formatter: (params: any) => {
|
||||
const colorSpan = (color: string) => `<div class="indicator" style="background-color: ` + color + `"></div>`;
|
||||
const colorSpan = (color: string) => `<span class="indicator" style="background-color: ` + color + `"></span>`;
|
||||
let itemFormatted = '<div class="title">' + params[0].axisValue + '</div>';
|
||||
params.map((item: any, index: number) => {
|
||||
if (index < 26) {
|
||||
itemFormatted += `<div class="item">
|
||||
${colorSpan(item.color)}
|
||||
<div class="indicator-container">${colorSpan(item.color)}</div>
|
||||
<div class="grow"></div>
|
||||
<div class="value">${item.value} <span class="symbol">vB/s</span></div>
|
||||
</div>`;
|
||||
}
|
||||
});
|
||||
return `<div class="tx-wrapper-tooltip-chart ${(this.size === 'big') ? 'tx-wrapper-tooltip-chart-big' : ''}">${itemFormatted}</div>`;
|
||||
return `<div class="tx-wrapper-tooltip-chart ${(this.template === 'advanced') ? 'tx-wrapper-tooltip-chart-advanced' : ''}">${itemFormatted}</div>`;
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
|
@ -14,18 +14,19 @@ import { feeLevels, chartColors } from 'src/app/app.constants';
|
||||
})
|
||||
export class MempoolGraphComponent implements OnInit, OnChanges {
|
||||
@Input() data: any[];
|
||||
@Input() limitFee = 300;
|
||||
@Input() limitFee = 350;
|
||||
@Input() height: number | string = 200;
|
||||
@Input() top: number | string = 20;
|
||||
@Input() right: number | string = 10;
|
||||
@Input() left: number | string = 75;
|
||||
@Input() small = false;
|
||||
@Input() size: ('small' | 'big') = 'small';
|
||||
@Input() template: ('widget' | 'advanced') = 'widget';
|
||||
@Input() showZoom = true;
|
||||
|
||||
mempoolVsizeFeesData: any;
|
||||
mempoolVsizeFeesOptions: EChartsOption;
|
||||
windowPreference: string;
|
||||
hoverIndexSerie: -1;
|
||||
feeLimitIndex: number;
|
||||
|
||||
constructor(
|
||||
private vbytesPipe: VbytesPipe,
|
||||
@ -93,15 +94,17 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
||||
const { labels, series } = this.mempoolVsizeFeesData;
|
||||
|
||||
const feeLevelsOrdered = feeLevels.map((sat, i, arr) => {
|
||||
if (i <= 26) {
|
||||
if (arr[i] === this.limitFee) { this.feeLimitIndex = i; }
|
||||
if (arr[i] < this.limitFee) {
|
||||
if (i === 0) { return '0 - 1'; }
|
||||
if (i === 26) { return '350+'; }
|
||||
return arr[i - 1] + ' - ' + sat;
|
||||
return `${arr[i - 1]} - ${arr[i]}`;
|
||||
} else {
|
||||
return `${this.limitFee}+`;
|
||||
}
|
||||
});
|
||||
|
||||
const yAxisSeries = series.map((value: Array<number>, index: number) => {
|
||||
if (index <= 26){
|
||||
if (index <= this.feeLimitIndex){
|
||||
return {
|
||||
name: feeLevelsOrdered[index],
|
||||
type: 'line',
|
||||
@ -114,7 +117,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
||||
width: 0,
|
||||
opacity: 0,
|
||||
},
|
||||
symbolSize: (this.size === 'big') ? 15 : 10,
|
||||
symbolSize: (this.template === 'advanced') ? 20 : 10,
|
||||
showSymbol: false,
|
||||
areaStyle: {
|
||||
opacity: 1,
|
||||
@ -122,11 +125,14 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
select: {
|
||||
areaStyle: {
|
||||
opacity: 1,
|
||||
}
|
||||
},
|
||||
},
|
||||
itemStyle: {
|
||||
borderWidth: 30,
|
||||
color: chartColors[index],
|
||||
borderColor: chartColors[index],
|
||||
},
|
||||
data: this.vbytesPipe.transform(value, 2, 'vB', 'MvB', true)
|
||||
};
|
||||
@ -138,11 +144,11 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
position: (pos, params, el, elRect, size) => {
|
||||
const positions = { top: -20 };
|
||||
positions[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 80;
|
||||
const positions = { top: (this.template === 'advanced') ? 30 : -30 };
|
||||
positions[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 60;
|
||||
return positions;
|
||||
},
|
||||
extraCssText: `width: ${(this.size === 'big') ? '200px' : '170px'};
|
||||
extraCssText: `width: ${(this.template === 'advanced') ? '210px' : '200px'};
|
||||
background: transparent;
|
||||
border: none;
|
||||
box-shadow: none;`,
|
||||
@ -150,36 +156,69 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
||||
type: 'line',
|
||||
},
|
||||
formatter: (params: any) => {
|
||||
const colorSpan = (index: number) => `<div class="indicator" style="background-color: ` + chartColors[index] + `"></div>`;
|
||||
const legendName = (index: number) => feeLevelsOrdered[index];
|
||||
let itemFormatted = `<div class="title">${params[0].axisValue}</div>`;
|
||||
const colorSpan = (index: number) => `<span class="indicator" style="background-color: ${chartColors[index]}"></span><span>${legendName(index)}</span>`;
|
||||
const title = `<div class="title">${params[0].axisValue}</div>`;
|
||||
const rangeLines = params;
|
||||
let total = 0;
|
||||
params.map((item: any, index: number) => {
|
||||
rangeLines.map((item: any) => {
|
||||
total += item.value;
|
||||
if (index <= 26) {
|
||||
});
|
||||
const itemFormatted = [];
|
||||
let totalParcial = 0;
|
||||
let progressPercentageText = '';
|
||||
rangeLines.map((item: any, index: number) => {
|
||||
totalParcial += item.value;
|
||||
let progressPercentage = 0;
|
||||
let progressPercentageTotalParcial = 0;
|
||||
if (index <= this.feeLimitIndex) {
|
||||
progressPercentage = (item.value / total) * 100;
|
||||
progressPercentageTotalParcial = (totalParcial / total) * 100;
|
||||
let activeItemClass = '';
|
||||
if (this.hoverIndexSerie === index){
|
||||
if (this.hoverIndexSerie === index) {
|
||||
progressPercentageText = `<div class="total-parcial-active">
|
||||
<span>${this.vbytesPipe.transform(totalParcial, 2, 'vB', 'MvB', false)}</span>
|
||||
<div class="total-percentage-bar"><span><span style="width: ${progressPercentageTotalParcial}%; background: ${chartColors[index]}"></span></span></div>
|
||||
</div>`;
|
||||
activeItemClass = 'active';
|
||||
}
|
||||
itemFormatted += `<div class="item ${activeItemClass}">
|
||||
${colorSpan(index)} ${legendName(index)}
|
||||
<div class="grow"></div>
|
||||
<div class="value">${this.vbytesPipe.transform(item.value, 2, 'vB', 'MvB', false)}</div>
|
||||
</div>`;
|
||||
itemFormatted.push(`<tr class="item ${activeItemClass}">
|
||||
<td class="indicator-container">${colorSpan(index)}</td>
|
||||
<td class="value">${this.vbytesPipe.transform(item.value, 2, 'vB', 'MvB', false)}</td>
|
||||
<td class="total-percentage-bar"><span><span style="width: ${progressPercentage}%; background: ${chartColors[index]}"></span></span></td>
|
||||
</tr>`);
|
||||
}
|
||||
});
|
||||
const progressActiveDiv = `<span class="total-value">${progressPercentageText}</span>`;
|
||||
const totalDiv = `<div class="total-label">Total
|
||||
<span class="total-value">${this.vbytesPipe.transform(total, 2, 'vB', 'MvB', true)}</span>
|
||||
<span class="total-value">${this.vbytesPipe.transform(total, 2, 'vB', 'MvB', false)}</span>
|
||||
</div>`;
|
||||
const advancedClass = (this.template === 'advanced') ? 'fees-wrapper-tooltip-chart-advanced' : '';
|
||||
return `<div class="fees-wrapper-tooltip-chart ${advancedClass}">
|
||||
${title}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Range</th>
|
||||
<th>Size</th>
|
||||
<th>%</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>${itemFormatted.reverse().join('')}</tbody>
|
||||
</table>
|
||||
${progressActiveDiv}
|
||||
${totalDiv}
|
||||
</div>`;
|
||||
const bigClass = (this.size === 'big') ? 'fees-wrapper-tooltip-chart-big' : '';
|
||||
return `<div class="fees-wrapper-tooltip-chart ${bigClass}">${itemFormatted} ${totalDiv}</div>`;
|
||||
}
|
||||
},
|
||||
dataZoom: [{
|
||||
type: 'inside',
|
||||
realtime: true,
|
||||
zoomOnMouseWheel: (this.template === 'advanced') ? true : false,
|
||||
maxSpan: 100,
|
||||
minSpan: 10,
|
||||
}, {
|
||||
show: (this.size === 'big') ? true : false,
|
||||
show: (this.template === 'advanced' && this.showZoom) ? true : false,
|
||||
type: 'slider',
|
||||
brushSelect: false,
|
||||
realtime: true,
|
||||
@ -193,6 +232,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
}],
|
||||
animation: false,
|
||||
grid: {
|
||||
height: this.height,
|
||||
right: this.right,
|
||||
|
@ -42,10 +42,10 @@
|
||||
<div class="incoming-transactions-graph">
|
||||
<app-mempool-graph
|
||||
dir="ltr"
|
||||
[size]="'big'"
|
||||
[limitFee]="1200"
|
||||
[template]="'advanced'"
|
||||
[limitFee]="500"
|
||||
[height]="500"
|
||||
[left]="60"
|
||||
[left]="50"
|
||||
[data]="mempoolStats"
|
||||
></app-mempool-graph>
|
||||
</div>
|
||||
@ -62,8 +62,8 @@
|
||||
<div class="incoming-transactions-graph">
|
||||
<app-incoming-transactions-graph
|
||||
[height]="500"
|
||||
[left]="60"
|
||||
[size]="'big'"
|
||||
[left]="50"
|
||||
[template]="'advanced'"
|
||||
[data]="mempoolTransactionsWeightPerSecondData"
|
||||
></app-incoming-transactions-graph>
|
||||
</div>
|
||||
|
@ -7,12 +7,12 @@
|
||||
<div class="tv-container" *ngIf="mempoolStats.length">
|
||||
<div class="chart-holder">
|
||||
<app-mempool-graph
|
||||
dir="ltr"
|
||||
[size]="'big'"
|
||||
[limitFee]="1200"
|
||||
[height]="500"
|
||||
[template]="'advanced'"
|
||||
[limitFee]="500"
|
||||
[height]="600"
|
||||
[left]="60"
|
||||
[data]="mempoolStats"
|
||||
[showZoom]="false"
|
||||
></app-mempool-graph>
|
||||
</div>
|
||||
<div class="blockchain-wrapper">
|
||||
|
@ -48,7 +48,11 @@
|
||||
<hr>
|
||||
</div>
|
||||
<div class="mempool-graph" *ngIf="(mempoolStats$ | async) as mempoolStats; else loadingSpinner">
|
||||
<app-mempool-graph [data]="mempoolStats.mempool"></app-mempool-graph>
|
||||
<app-mempool-graph
|
||||
[template]="'widget'"
|
||||
[limitFee]="150"
|
||||
[data]="mempoolStats.mempool"
|
||||
></app-mempool-graph>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -266,16 +266,29 @@ html:lang(ru) .card-title {
|
||||
min-height: 180px;
|
||||
}
|
||||
|
||||
.tx-wrapper-tooltip-chart, .fees-wrapper-tooltip-chart {
|
||||
background: rgba(#11131f, 0.85);
|
||||
.tx-wrapper-tooltip-chart,
|
||||
.fees-wrapper-tooltip-chart {
|
||||
background: rgba(#11131f, 0.95);
|
||||
border-radius: 4px;
|
||||
box-shadow: 1px 1px 10px rgba(0,0,0,0.2);
|
||||
box-shadow: 1px 1px 10px rgba(0,0,0,0.5);
|
||||
color: #b1b1b1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 10px 15px;
|
||||
text-align: left;
|
||||
thead {
|
||||
th {
|
||||
font-size: 9px;
|
||||
color: #b1b1b1;
|
||||
text-align: right;
|
||||
&:first-child {
|
||||
text-align: left;
|
||||
left: -1px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
@ -284,21 +297,25 @@ html:lang(ru) .card-title {
|
||||
}
|
||||
.active {
|
||||
color: yellow !important;
|
||||
font-weight: 900;
|
||||
.value {
|
||||
.value,
|
||||
.total-partial {
|
||||
color: yellow !important;
|
||||
.symbol {
|
||||
color: yellow !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item {
|
||||
display: flex;
|
||||
.indicator {
|
||||
margin-right: 5px;
|
||||
border-radius: 0px;
|
||||
margin-top: 5px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
line-height: 0.8;
|
||||
.indicator-container {
|
||||
.indicator {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
border-radius: 0px;
|
||||
margin-top: 5px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
}
|
||||
}
|
||||
.value {
|
||||
text-align: right;
|
||||
@ -307,24 +324,81 @@ html:lang(ru) .card-title {
|
||||
font-size: 9px !important;
|
||||
}
|
||||
}
|
||||
.total-partial {
|
||||
text-align: right;
|
||||
font-size: 10px;
|
||||
width: 70px;
|
||||
}
|
||||
.total-percentage-bar {
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
.total-label {
|
||||
width: 100%;
|
||||
margin-top: 0px;
|
||||
font-size: 10px;
|
||||
text-align: left;
|
||||
color: #fff;
|
||||
margin-top: 5px;
|
||||
font-size: 14px;
|
||||
span {
|
||||
font-weight: 700;
|
||||
float: right !important;
|
||||
float: right;
|
||||
}
|
||||
.symbol {
|
||||
margin-left: 3px;
|
||||
font-size: 9px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
}
|
||||
.total-percentage-bar {
|
||||
margin: auto;
|
||||
width: 35px;
|
||||
position: relative;
|
||||
span {
|
||||
display: block;
|
||||
background: #282d47;
|
||||
height: 5px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
.total-parcial-active {
|
||||
text-align: right;
|
||||
margin: 5px auto 5px;
|
||||
padding-left: 0px;
|
||||
span {
|
||||
font-size: 10px;
|
||||
}
|
||||
.symbol {
|
||||
font-size: 9px;
|
||||
}
|
||||
.total-percentage-bar {
|
||||
width: 100%;
|
||||
span {
|
||||
transition: 1000 all ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tx-wrapper-tooltip-chart {
|
||||
.item {
|
||||
display: flex;
|
||||
}
|
||||
.value {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.indicator-container {
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.fee-distribution-chart {
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.fees-wrapper-tooltip-chart {
|
||||
.item {
|
||||
font-size: 9px;
|
||||
line-height: 1;
|
||||
line-height: 0.8;
|
||||
margin: 0px;
|
||||
}
|
||||
.indicator {
|
||||
@ -334,8 +408,9 @@ html:lang(ru) .card-title {
|
||||
}
|
||||
}
|
||||
|
||||
.fees-wrapper-tooltip-chart-big, .tx-wrapper-tooltip-chart-big {
|
||||
background: rgba(#1d1f31, 0.85);
|
||||
.fees-wrapper-tooltip-chart-big,
|
||||
.tx-wrapper-tooltip-chart-big {
|
||||
background: rgba(#1d1f31, 0.98);
|
||||
.title {
|
||||
font-size: 15px;
|
||||
margin-bottom: 5px;
|
||||
@ -343,7 +418,6 @@ html:lang(ru) .card-title {
|
||||
.item {
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
margin: 2px 0px;
|
||||
.value {
|
||||
.symbol {
|
||||
font-size: 12px !important;
|
||||
@ -351,25 +425,40 @@ html:lang(ru) .card-title {
|
||||
}
|
||||
}
|
||||
.total-label {
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
font-size: 14px;
|
||||
span {
|
||||
font-weight: 700;
|
||||
float: right !important;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.total-parcial-active {
|
||||
text-align: right;
|
||||
margin: 5px auto 5px;
|
||||
span {
|
||||
font-size: 10px;
|
||||
}
|
||||
.total-percentage-bar {
|
||||
width: 100%;
|
||||
left: 0;
|
||||
span {
|
||||
transition: 1000 all ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tx-wrapper-tooltip-chart-big {
|
||||
.indicator {
|
||||
margin: 0px !important;;
|
||||
.indicator-container {
|
||||
.indicator {
|
||||
margin-right: 5px;
|
||||
border-radius: 0px;
|
||||
margin-top: 5px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fee-distribution-chart {
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
/* MEMPOOL CHARTS - end */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user