diff --git a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.html b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.html index 3fbbaa4e2..ff00f5b15 100644 --- a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.html +++ b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.html @@ -37,25 +37,18 @@
- +
- -
-
+
+
Lightning network history
- + +
diff --git a/frontend/src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.scss b/frontend/src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.scss index fa044a4d6..760e782ca 100644 --- a/frontend/src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.scss +++ b/frontend/src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.scss @@ -51,8 +51,7 @@ } .chart-widget { width: 100%; - height: 100%; - max-height: 270px; + height: 145px; } .formRadioGroup { diff --git a/frontend/src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts b/frontend/src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts index 70d02de28..dbbb49483 100644 --- a/frontend/src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts +++ b/frontend/src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core'; -import { EChartsOption} from 'echarts'; +import { EChartsOption, graphic} from 'echarts'; import { Observable } from 'rxjs'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { formatNumber } from '@angular/common'; @@ -9,6 +9,7 @@ import { MiningService } from 'src/app/services/mining.service'; import { download } from 'src/app/shared/graphs.utils'; import { SeoService } from 'src/app/services/seo.service'; import { LightningApiService } from '../lightning-api.service'; +import { AmountShortenerPipe } from 'src/app/shared/pipes/amount-shortener.pipe'; @Component({ selector: 'app-nodes-networks-chart', @@ -26,7 +27,7 @@ import { LightningApiService } from '../lightning-api.service'; }) export class NodesNetworksChartComponent implements OnInit { @Input() right: number | string = 45; - @Input() left: number | string = 55; + @Input() left: number | string = 45; @Input() widget = false; miningWindowPreference: string; @@ -51,7 +52,8 @@ export class NodesNetworksChartComponent implements OnInit { private lightningApiService: LightningApiService, private formBuilder: FormBuilder, private storageService: StorageService, - private miningService: MiningService + private miningService: MiningService, + private amountShortenerPipe: AmountShortenerPipe, ) { } @@ -82,11 +84,17 @@ export class NodesNetworksChartComponent implements OnInit { .pipe( tap((response) => { const data = response.body; - this.prepareChartOptions({ + const chartData = { tor_nodes: data.map(val => [val.added * 1000, val.tor_nodes]), clearnet_nodes: data.map(val => [val.added * 1000, val.clearnet_nodes]), unannounced_nodes: data.map(val => [val.added * 1000, val.unannounced_nodes]), - }); + }; + let maxYAxis = 0; + for (const day of data) { + maxYAxis = Math.max(maxYAxis, day.tor_nodes + day.clearnet_nodes + day.unannounced_nodes); + } + maxYAxis = Math.ceil(maxYAxis / 3000) * 3000; + this.prepareChartOptions(chartData, maxYAxis); this.isLoading = false; }), map((response) => { @@ -100,7 +108,7 @@ export class NodesNetworksChartComponent implements OnInit { ); } - prepareChartOptions(data) { + prepareChartOptions(data, maxYAxis) { let title: object; if (data.tor_nodes.length === 0) { title = { @@ -110,24 +118,30 @@ export class NodesNetworksChartComponent implements OnInit { }, text: $localize`:@@23555386d8af1ff73f297e89dd4af3f4689fb9dd:Indexing blocks`, left: 'center', - top: 'center' + top: 'top', + }; + } else if (this.widget) { + title = { + textStyle: { + color: 'grey', + fontSize: 11 + }, + text: $localize`Nodes per network`, + left: 'center', + top: 11, + zlevel: 10, }; } this.chartOptions = { title: title, animation: false, - color: [ - '#D81B60', - '#039BE5', - '#7CB342', - '#FFB300', - ], grid: { - top: 40, - bottom: this.widget ? 30 : 70, - right: this.right, - left: this.left, + height: this.widget ? 100 : undefined, + top: this.widget ? 10 : 40, + bottom: this.widget ? 0 : 70, + right: (this.isMobile() && this.widget) ? 35 : this.right, + left: (this.isMobile() && this.widget) ? 40 :this.left, }, tooltip: { show: !this.isMobile() || !this.widget, @@ -171,7 +185,7 @@ export class NodesNetworksChartComponent implements OnInit { hideOverlap: true, } }, - legend: data.tor_nodes.length === 0 ? undefined : { + legend: this.widget || data.tor_nodes.length === 0 ? undefined : { padding: 10, data: [ { @@ -207,7 +221,7 @@ export class NodesNetworksChartComponent implements OnInit { icon: 'roundRect', }, ], - selected: JSON.parse(this.storageService.getValue('nodes_networks_legend')) ?? { + selected: this.widget ? undefined : JSON.parse(this.storageService.getValue('nodes_networks_legend')) ?? { 'Total': true, 'Tor': true, 'Clearnet': true, @@ -218,13 +232,14 @@ export class NodesNetworksChartComponent implements OnInit { { type: 'value', position: 'left', - min: (value) => { - return value.min * 0.9; - }, axisLabel: { color: 'rgb(110, 112, 121)', - formatter: (val) => { - return `${formatNumber(Math.round(val * 100) / 100, this.locale, '1.0-0')}`; + formatter: (val: number): string => { + if (this.widget) { + return `${this.amountShortenerPipe.transform(val, 0)}`; + } else { + return `${formatNumber(Math.round(val), this.locale, '1.0-0')}`; + } } }, splitLine: { @@ -232,8 +247,35 @@ export class NodesNetworksChartComponent implements OnInit { type: 'dotted', color: '#ffffff66', opacity: 0.25, + }, + }, + max: maxYAxis, + min: 0, + interval: 3000, + }, + { + type: 'value', + position: 'right', + axisLabel: { + color: 'rgb(110, 112, 121)', + formatter: (val: number): string => { + if (this.widget) { + return `${this.amountShortenerPipe.transform(val, 0)}`; + } else { + return `${formatNumber(Math.round(val), this.locale, '1.0-0')}`; + } } }, + splitLine: { + lineStyle: { + type: 'dotted', + color: '#ffffff66', + opacity: 0.25, + }, + }, + max: maxYAxis, + min: 0, + interval: 3000, } ], series: data.tor_nodes.length === 0 ? [] : [ @@ -252,7 +294,12 @@ export class NodesNetworksChartComponent implements OnInit { opacity: 0.5, }, stack: 'Total', - color: '#FDD835', + color: new graphic.LinearGradient(0, 0.75, 0, 1, [ + { offset: 0, color: '#D81B60' }, + { offset: 1, color: '#D81B60AA' }, + ]), + + smooth: true, }, { zlevel: 1, @@ -269,11 +316,15 @@ export class NodesNetworksChartComponent implements OnInit { opacity: 0.5, }, stack: 'Total', - color: '#00ACC1', + color: new graphic.LinearGradient(0, 0.75, 0, 1, [ + { offset: 0, color: '#FFB300' }, + { offset: 1, color: '#FFB300AA' }, + ]), + smooth: true, }, { zlevel: 1, - yAxisIndex: 0, + yAxisIndex: 1, name: $localize`Tor`, showSymbol: false, symbol: 'none', @@ -286,7 +337,11 @@ export class NodesNetworksChartComponent implements OnInit { opacity: 0.5, }, stack: 'Total', - color: '#7D4698', + color: new graphic.LinearGradient(0, 0.75, 0, 1, [ + { offset: 0, color: '#7D4698' }, + { offset: 1, color: '#7D4698AA' }, + ]), + smooth: true, }, ], dataZoom: this.widget ? null : [{ diff --git a/frontend/src/app/lightning/nodes-per-isp-chart/nodes-per-isp-chart.component.html b/frontend/src/app/lightning/nodes-per-isp-chart/nodes-per-isp-chart.component.html index 5e14ac67b..01be4f036 100644 --- a/frontend/src/app/lightning/nodes-per-isp-chart/nodes-per-isp-chart.component.html +++ b/frontend/src/app/lightning/nodes-per-isp-chart/nodes-per-isp-chart.component.html @@ -8,18 +8,18 @@ {{ stats.taggedISP }}

-
-
Tagged capacity
-

- -

-
Tagged nodes

{{ stats.taggedNodeCount }}

+
+
Tagged capacity
+

+ +

+
diff --git a/frontend/src/app/lightning/statistics-chart/lightning-statistics-chart.component.scss b/frontend/src/app/lightning/statistics-chart/lightning-statistics-chart.component.scss index 5f59539e3..760e782ca 100644 --- a/frontend/src/app/lightning/statistics-chart/lightning-statistics-chart.component.scss +++ b/frontend/src/app/lightning/statistics-chart/lightning-statistics-chart.component.scss @@ -51,7 +51,7 @@ } .chart-widget { width: 100%; - height: 320px; + height: 145px; } .formRadioGroup { diff --git a/frontend/src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts b/frontend/src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts index 1727d1f68..d889dd254 100644 --- a/frontend/src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts +++ b/frontend/src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts @@ -9,6 +9,7 @@ import { StorageService } from 'src/app/services/storage.service'; import { MiningService } from 'src/app/services/mining.service'; import { download } from 'src/app/shared/graphs.utils'; import { LightningApiService } from '../lightning-api.service'; +import { AmountShortenerPipe } from 'src/app/shared/pipes/amount-shortener.pipe'; @Component({ selector: 'app-lightning-statistics-chart', @@ -25,7 +26,7 @@ import { LightningApiService } from '../lightning-api.service'; }) export class LightningStatisticsChartComponent implements OnInit { @Input() right: number | string = 45; - @Input() left: number | string = 55; + @Input() left: number | string = 45; @Input() widget = false; miningWindowPreference: string; @@ -51,6 +52,7 @@ export class LightningStatisticsChartComponent implements OnInit { private formBuilder: FormBuilder, private storageService: StorageService, private miningService: MiningService, + private amountShortenerPipe: AmountShortenerPipe, ) { } @@ -105,24 +107,39 @@ export class LightningStatisticsChartComponent implements OnInit { color: 'grey', fontSize: 15 }, - text: `Indexing in progess`, + text: $localize`Indexing in progess`, left: 'center', top: 'center' }; + } else if (this.widget) { + title = { + textStyle: { + color: 'grey', + fontSize: 11 + }, + text: $localize`Channels & Capacity`, + left: 'center', + top: 11, + zlevel: 10, + }; } this.chartOptions = { title: title, animation: false, color: [ - '#FDD835', - '#D81B60', + '#FFB300', + new graphic.LinearGradient(0, 0.75, 0, 1, [ + { offset: 0, color: '#D81B60' }, + { offset: 1, color: '#D81B60AA' }, + ]), ], grid: { - top: 40, - bottom: this.widget ? 30 : 70, - right: this.right, - left: this.left, + height: this.widget ? 100 : undefined, + top: this.widget ? 10 : 40, + bottom: this.widget ? 0 : 70, + right: (this.isMobile() && this.widget) ? 35 : this.right, + left: (this.isMobile() && this.widget) ? 40 :this.left, }, tooltip: { show: !this.isMobile(), @@ -166,7 +183,7 @@ export class LightningStatisticsChartComponent implements OnInit { hideOverlap: true, } }, - legend: data.channel_count.length === 0 ? undefined : { + legend: this.widget || data.channel_count.length === 0 ? undefined : { padding: 10, data: [ { @@ -178,7 +195,7 @@ export class LightningStatisticsChartComponent implements OnInit { icon: 'roundRect', }, { - name: 'Capacity (BTC)', + name: 'Capacity', inactiveColor: 'rgb(110, 112, 121)', textStyle: { color: 'white', @@ -188,17 +205,20 @@ export class LightningStatisticsChartComponent implements OnInit { ], selected: JSON.parse(this.storageService.getValue('sizes_ln_legend')) ?? { 'Channels': true, - 'Capacity (BTC)': true, + 'Capacity': true, } }, yAxis: data.channel_count.length === 0 ? undefined : [ { - min: 0, type: 'value', axisLabel: { color: 'rgb(110, 112, 121)', - formatter: (val) => { - return `${formatNumber(Math.round(val), this.locale, '1.0-0')}`; + formatter: (val: number): string => { + if (this.widget) { + return `${this.amountShortenerPipe.transform(val, 0)}`; + } else { + return `${formatNumber(Math.round(val), this.locale, '1.0-0')}`; + } } }, splitLine: { @@ -208,6 +228,7 @@ export class LightningStatisticsChartComponent implements OnInit { opacity: 0.25, } }, + minInterval: this.widget ? 20000 : undefined, }, { min: 0, @@ -215,8 +236,12 @@ export class LightningStatisticsChartComponent implements OnInit { position: 'right', axisLabel: { color: 'rgb(110, 112, 121)', - formatter: (val) => { - return `${formatNumber(Math.round(val / 100000000), this.locale, '1.0-0')}`; + formatter: (val: number): string => { + if (this.widget) { + return `${this.amountShortenerPipe.transform(Math.round(val / 100000000), 0)}`; + } else { + return `${formatNumber(Math.round(val / 100000000), this.locale, '1.0-0')}`; + } } }, splitLine: { @@ -244,20 +269,49 @@ export class LightningStatisticsChartComponent implements OnInit { opacity: 1, width: 1, }, - } + }, + smooth: true, }, { zlevel: 0, yAxisIndex: 1, - name: 'Capacity (BTC)', + name: $localize`Capacity`, showSymbol: false, symbol: 'none', stack: 'Total', data: data.capacity, - areaStyle: {}, + areaStyle: { + opacity: 0.5, + }, type: 'line', + smooth: true, } ], + dataZoom: this.widget ? null : [{ + type: 'inside', + realtime: true, + zoomLock: true, + maxSpan: 100, + minSpan: 5, + moveOnMouseMove: false, + }, { + showDetail: false, + show: true, + type: 'slider', + brushSelect: false, + realtime: true, + left: 20, + right: 15, + selectedDataBackground: { + lineStyle: { + color: '#fff', + opacity: 0.45, + }, + areaStyle: { + opacity: 0, + } + }, + }], }; } diff --git a/frontend/src/app/shared/pipes/amount-shortener.pipe.ts b/frontend/src/app/shared/pipes/amount-shortener.pipe.ts index a31a5712e..db3d94284 100644 --- a/frontend/src/app/shared/pipes/amount-shortener.pipe.ts +++ b/frontend/src/app/shared/pipes/amount-shortener.pipe.ts @@ -5,7 +5,7 @@ import { Pipe, PipeTransform } from '@angular/core'; }) export class AmountShortenerPipe implements PipeTransform { transform(num: number, ...args: any[]): unknown { - const digits = args[0] || 1; + const digits = args[0] ?? 1; const unit = args[1] || undefined; if (num < 1000) {