From f434e50a2c39d0c55060c187f770c5fb62874f6f Mon Sep 17 00:00:00 2001 From: Miguel Medeiros Date: Thu, 26 Aug 2021 23:30:57 -0300 Subject: [PATCH] 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. --- .../incoming-transactions-graph.component.ts | 18 ++- .../mempool-graph/mempool-graph.component.ts | 94 ++++++++---- .../statistics/statistics.component.html | 10 +- .../television/television.component.html | 8 +- .../app/dashboard/dashboard.component.html | 6 +- frontend/src/styles.scss | 145 ++++++++++++++---- 6 files changed, 209 insertions(+), 72 deletions(-) diff --git a/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts b/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts index 0e43bfbb6..35aee245c 100644 --- a/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts +++ b/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts @@ -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) => `
`; + const colorSpan = (color: string) => ``; let itemFormatted = '
' + params[0].axisValue + '
'; params.map((item: any, index: number) => { if (index < 26) { itemFormatted += `
- ${colorSpan(item.color)} +
${colorSpan(item.color)}
${item.value} vB/s
`; } }); - return `
${itemFormatted}
`; + return `
${itemFormatted}
`; } }, xAxis: { diff --git a/frontend/src/app/components/mempool-graph/mempool-graph.component.ts b/frontend/src/app/components/mempool-graph/mempool-graph.component.ts index f7df31fb2..25d0371bc 100644 --- a/frontend/src/app/components/mempool-graph/mempool-graph.component.ts +++ b/frontend/src/app/components/mempool-graph/mempool-graph.component.ts @@ -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, 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) => `
`; const legendName = (index: number) => feeLevelsOrdered[index]; - let itemFormatted = `
${params[0].axisValue}
`; + const colorSpan = (index: number) => `${legendName(index)}`; + const title = `
${params[0].axisValue}
`; + 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 = `
+ ${this.vbytesPipe.transform(totalParcial, 2, 'vB', 'MvB', false)} +
+
`; activeItemClass = 'active'; } - itemFormatted += `
- ${colorSpan(index)} ${legendName(index)} -
-
${this.vbytesPipe.transform(item.value, 2, 'vB', 'MvB', false)}
-
`; + itemFormatted.push(` + ${colorSpan(index)} + ${this.vbytesPipe.transform(item.value, 2, 'vB', 'MvB', false)} + + `); } }); + const progressActiveDiv = `${progressPercentageText}`; const totalDiv = `
Total - ${this.vbytesPipe.transform(total, 2, 'vB', 'MvB', true)} + ${this.vbytesPipe.transform(total, 2, 'vB', 'MvB', false)} +
`; + const advancedClass = (this.template === 'advanced') ? 'fees-wrapper-tooltip-chart-advanced' : ''; + return `
+ ${title} + + + + + + + + + ${itemFormatted.reverse().join('')} +
RangeSize%
+ ${progressActiveDiv} + ${totalDiv}
`; - const bigClass = (this.size === 'big') ? 'fees-wrapper-tooltip-chart-big' : ''; - return `
${itemFormatted} ${totalDiv}
`; } }, 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, diff --git a/frontend/src/app/components/statistics/statistics.component.html b/frontend/src/app/components/statistics/statistics.component.html index 8e8677267..04cfb5548 100644 --- a/frontend/src/app/components/statistics/statistics.component.html +++ b/frontend/src/app/components/statistics/statistics.component.html @@ -42,10 +42,10 @@
@@ -62,8 +62,8 @@
diff --git a/frontend/src/app/components/television/television.component.html b/frontend/src/app/components/television/television.component.html index 5b8d52bb3..e5134c9bd 100644 --- a/frontend/src/app/components/television/television.component.html +++ b/frontend/src/app/components/television/television.component.html @@ -7,12 +7,12 @@
diff --git a/frontend/src/app/dashboard/dashboard.component.html b/frontend/src/app/dashboard/dashboard.component.html index 5eab01618..6a521e4d2 100644 --- a/frontend/src/app/dashboard/dashboard.component.html +++ b/frontend/src/app/dashboard/dashboard.component.html @@ -48,7 +48,11 @@
- +
diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss index 39c7292f0..bbbfc1e03 100644 --- a/frontend/src/styles.scss +++ b/frontend/src/styles.scss @@ -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 */