From 1ead34d42d5ec3753b6a2d6c34c7564e2555d7a7 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Tue, 6 Sep 2022 12:05:23 +0200 Subject: [PATCH 1/3] Show tor+clearnet node series in chart --- backend/src/api/explorer/statistics.api.ts | 3 +- .../nodes-networks-chart.component.ts | 37 ++++++++++++++----- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/backend/src/api/explorer/statistics.api.ts b/backend/src/api/explorer/statistics.api.ts index 558ee86fd..cab8bfc29 100644 --- a/backend/src/api/explorer/statistics.api.ts +++ b/backend/src/api/explorer/statistics.api.ts @@ -6,7 +6,8 @@ class StatisticsApi { public async $getStatistics(interval: string | null = null): Promise { interval = Common.getSqlInterval(interval); - let query = `SELECT UNIX_TIMESTAMP(added) AS added, channel_count, total_capacity, tor_nodes, clearnet_nodes, unannounced_nodes + let query = `SELECT UNIX_TIMESTAMP(added) AS added, channel_count, total_capacity, + tor_nodes, clearnet_nodes, unannounced_nodes, clearnet_tor_nodes FROM lightning_stats`; if (interval) { 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 a6278658a..1d87b7929 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 @@ -89,10 +89,11 @@ export class NodesNetworksChartComponent implements OnInit { 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]), + clearnet_tor_nodes: data.map(val => [val.added * 1000, val.clearnet_tor_nodes]), }; let maxYAxis = 0; for (const day of data) { - maxYAxis = Math.max(maxYAxis, day.tor_nodes + day.clearnet_nodes + day.unannounced_nodes); + maxYAxis = Math.max(maxYAxis, day.tor_nodes + day.clearnet_nodes + day.unannounced_nodes + day.clearnet_tor_nodes); } maxYAxis = Math.ceil(maxYAxis / 3000) * 3000; this.prepareChartOptions(chartData, maxYAxis); @@ -163,13 +164,16 @@ export class NodesNetworksChartComponent implements OnInit { const date = new Date(ticks[0].data[0]).toLocaleDateString(this.locale, { year: 'numeric', month: 'short', day: 'numeric' }); let tooltip = `${date}
`; - for (const tick of ticks.reverse()) { + console.log(ticks); + for (const tick of ticks) { if (tick.seriesIndex === 0) { // Tor tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`; } else if (tick.seriesIndex === 1) { // Clearnet tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`; } else if (tick.seriesIndex === 2) { // Unannounced tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`; + } else if (tick.seriesIndex === 3) { // Tor + Clearnet + tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`; } tooltip += `
`; total += tick.data[1]; @@ -189,14 +193,6 @@ export class NodesNetworksChartComponent implements OnInit { legend: this.widget || data.tor_nodes.length === 0 ? undefined : { padding: 10, data: [ - { - name: $localize`Total`, - inactiveColor: 'rgb(110, 112, 121)', - textStyle: { - color: 'white', - }, - icon: 'roundRect', - }, { name: $localize`Tor`, inactiveColor: 'rgb(110, 112, 121)', @@ -323,6 +319,27 @@ export class NodesNetworksChartComponent implements OnInit { ]), smooth: false, }, + { + zlevel: 1, + yAxisIndex: 1, + name: $localize`Clearnet & Tor`, + showSymbol: false, + symbol: 'none', + data: data.clearnet_tor_nodes, + type: 'line', + lineStyle: { + width: 2, + }, + areaStyle: { + opacity: 0.5, + }, + stack: 'Total', + color: new graphic.LinearGradient(0, 0.75, 0, 1, [ + { offset: 0, color: '#be7d4c' }, + { offset: 1, color: '#be7d4cAA' }, + ]), + smooth: false, + }, { zlevel: 1, yAxisIndex: 1, From 0f218ced47fa230e2ed748e89314cf052469c732 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Thu, 8 Sep 2022 19:03:37 +0200 Subject: [PATCH 2/3] Fix legend --- .../nodes-networks-chart.component.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) 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 1d87b7929..ba75661fe 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 @@ -209,6 +209,14 @@ export class NodesNetworksChartComponent implements OnInit { }, icon: 'roundRect', }, + { + name: $localize`Clearnet & Tor`, + inactiveColor: 'rgb(110, 112, 121)', + textStyle: { + color: 'white', + }, + icon: 'roundRect', + }, { name: $localize`Unannounced`, inactiveColor: 'rgb(110, 112, 121)', @@ -219,10 +227,10 @@ export class NodesNetworksChartComponent implements OnInit { }, ], selected: this.widget ? undefined : JSON.parse(this.storageService.getValue('nodes_networks_legend')) ?? { - 'Total': true, - 'Tor': true, - 'Clearnet': true, - 'Unannounced': true, + '$localize`Tor`': true, + '$localize`Clearnet`': true, + '$localize`Clearnet & Tor`': true, + '$localize`Unannounced`': true, } }, yAxis: data.tor_nodes.length === 0 ? undefined : [ From b7b1dfdeb5091f14ccdc85634a158348a5e16e70 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Thu, 22 Sep 2022 16:09:26 +0200 Subject: [PATCH 3/3] Change naming in networks line chart + Fix y axis scaling --- .../nodes-networks-chart.component.ts | 221 ++++++++++-------- 1 file changed, 121 insertions(+), 100 deletions(-) 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 ba75661fe..c1647cd25 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, graphic} from 'echarts'; +import { EChartsOption, graphic, LineSeriesOption} from 'echarts'; import { Observable } from 'rxjs'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { formatNumber } from '@angular/common'; @@ -135,6 +135,94 @@ export class NodesNetworksChartComponent implements OnInit { }; } + const series: LineSeriesOption[] = [ + { + zlevel: 1, + yAxisIndex: 0, + name: $localize`Unknown`, + showSymbol: false, + symbol: 'none', + data: data.unannounced_nodes, + type: 'line', + lineStyle: { + width: 2, + }, + areaStyle: { + opacity: 0.5, + }, + stack: 'Total', + color: new graphic.LinearGradient(0, 0.75, 0, 1, [ + { offset: 0, color: '#D81B60' }, + { offset: 1, color: '#D81B60AA' }, + ]), + + smooth: false, + }, + { + zlevel: 1, + yAxisIndex: 0, + name: $localize`Reachable on Clearnet Only`, + showSymbol: false, + symbol: 'none', + data: data.clearnet_nodes, + type: 'line', + lineStyle: { + width: 2, + }, + areaStyle: { + opacity: 0.5, + }, + stack: 'Total', + color: new graphic.LinearGradient(0, 0.75, 0, 1, [ + { offset: 0, color: '#FFB300' }, + { offset: 1, color: '#FFB300AA' }, + ]), + smooth: false, + }, + { + zlevel: 1, + yAxisIndex: 0, + name: $localize`Reachable on Clearnet and Darknet`, + showSymbol: false, + symbol: 'none', + data: data.clearnet_tor_nodes, + type: 'line', + lineStyle: { + width: 2, + }, + areaStyle: { + opacity: 0.5, + }, + stack: 'Total', + color: new graphic.LinearGradient(0, 0.75, 0, 1, [ + { offset: 0, color: '#be7d4c' }, + { offset: 1, color: '#be7d4cAA' }, + ]), + smooth: false, + }, + { + zlevel: 1, + yAxisIndex: 0, + name: $localize`Reachable on Darknet Only`, + showSymbol: false, + symbol: 'none', + data: data.tor_nodes, + type: 'line', + lineStyle: { + width: 2, + }, + areaStyle: { + opacity: 0.5, + }, + stack: 'Total', + color: new graphic.LinearGradient(0, 0.75, 0, 1, [ + { offset: 0, color: '#7D4698' }, + { offset: 1, color: '#7D4698AA' }, + ]), + smooth: false, + }, + ]; + this.chartOptions = { title: title, animation: false, @@ -164,8 +252,10 @@ export class NodesNetworksChartComponent implements OnInit { const date = new Date(ticks[0].data[0]).toLocaleDateString(this.locale, { year: 'numeric', month: 'short', day: 'numeric' }); let tooltip = `${date}
`; - console.log(ticks); - for (const tick of ticks) { + for (const tick of ticks.reverse()) { + if (tick.seriesName.indexOf('ignored') !== -1) { + continue; + } if (tick.seriesIndex === 0) { // Tor tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`; } else if (tick.seriesIndex === 1) { // Clearnet @@ -194,7 +284,7 @@ export class NodesNetworksChartComponent implements OnInit { padding: 10, data: [ { - name: $localize`Tor`, + name: $localize`Reachable on Darknet Only`, inactiveColor: 'rgb(110, 112, 121)', textStyle: { color: 'white', @@ -202,7 +292,7 @@ export class NodesNetworksChartComponent implements OnInit { icon: 'roundRect', }, { - name: $localize`Clearnet`, + name: $localize`Reachable on Clearnet and Darknet`, inactiveColor: 'rgb(110, 112, 121)', textStyle: { color: 'white', @@ -210,7 +300,7 @@ export class NodesNetworksChartComponent implements OnInit { icon: 'roundRect', }, { - name: $localize`Clearnet & Tor`, + name: $localize`Reachable on Clearnet Only`, inactiveColor: 'rgb(110, 112, 121)', textStyle: { color: 'white', @@ -218,7 +308,7 @@ export class NodesNetworksChartComponent implements OnInit { icon: 'roundRect', }, { - name: $localize`Unannounced`, + name: $localize`Unknown`, inactiveColor: 'rgb(110, 112, 121)', textStyle: { color: 'white', @@ -227,10 +317,10 @@ export class NodesNetworksChartComponent implements OnInit { }, ], selected: this.widget ? undefined : JSON.parse(this.storageService.getValue('nodes_networks_legend')) ?? { - '$localize`Tor`': true, - '$localize`Clearnet`': true, - '$localize`Clearnet & Tor`': true, - '$localize`Unannounced`': true, + '$localize`Reachable on Darknet Only`': true, + '$localize`Reachable on Clearnet Only`': true, + '$localize`Reachable on Clearnet and Darknet`': true, + '$localize`Unknown`': true, } }, yAxis: data.tor_nodes.length === 0 ? undefined : [ @@ -254,7 +344,6 @@ export class NodesNetworksChartComponent implements OnInit { opacity: 0.25, }, }, - max: maxYAxis, min: 0, interval: 3000, }, @@ -278,98 +367,25 @@ export class NodesNetworksChartComponent implements OnInit { opacity: 0.25, }, }, - max: maxYAxis, min: 0, interval: 3000, } ], - series: data.tor_nodes.length === 0 ? [] : [ - { - zlevel: 1, - yAxisIndex: 0, - name: $localize`Unannounced`, - showSymbol: false, - symbol: 'none', - data: data.unannounced_nodes, - type: 'line', - lineStyle: { - width: 2, - }, - areaStyle: { - opacity: 0.5, - }, - stack: 'Total', - color: new graphic.LinearGradient(0, 0.75, 0, 1, [ - { offset: 0, color: '#D81B60' }, - { offset: 1, color: '#D81B60AA' }, - ]), - - smooth: false, - }, - { - zlevel: 1, - yAxisIndex: 0, - name: $localize`Clearnet`, - showSymbol: false, - symbol: 'none', - data: data.clearnet_nodes, - type: 'line', - lineStyle: { - width: 2, - }, - areaStyle: { - opacity: 0.5, - }, - stack: 'Total', - color: new graphic.LinearGradient(0, 0.75, 0, 1, [ - { offset: 0, color: '#FFB300' }, - { offset: 1, color: '#FFB300AA' }, - ]), - smooth: false, - }, - { - zlevel: 1, - yAxisIndex: 1, - name: $localize`Clearnet & Tor`, - showSymbol: false, - symbol: 'none', - data: data.clearnet_tor_nodes, - type: 'line', - lineStyle: { - width: 2, - }, - areaStyle: { - opacity: 0.5, - }, - stack: 'Total', - color: new graphic.LinearGradient(0, 0.75, 0, 1, [ - { offset: 0, color: '#be7d4c' }, - { offset: 1, color: '#be7d4cAA' }, - ]), - smooth: false, - }, - { - zlevel: 1, - yAxisIndex: 1, - name: $localize`Tor`, - showSymbol: false, - symbol: 'none', - data: data.tor_nodes, - type: 'line', - lineStyle: { - width: 2, - }, - areaStyle: { - opacity: 0.5, - }, - stack: 'Total', - color: new graphic.LinearGradient(0, 0.75, 0, 1, [ - { offset: 0, color: '#7D4698' }, - { offset: 1, color: '#7D4698AA' }, - ]), - smooth: false, - }, - ], + series: data.tor_nodes.length === 0 ? [] : series.concat(series.map((serie) => { + // We create dummy duplicated series so when we use the data zoom, the y axis + // both scales properly + const invisibleSerie = {...serie}; + invisibleSerie.name = 'ignored' + Math.random().toString(); + invisibleSerie.stack = 'ignored'; + invisibleSerie.yAxisIndex = 1; + invisibleSerie.lineStyle = { + opacity: 0, + }; + invisibleSerie.areaStyle = { + opacity: 0, + }; + return invisibleSerie; + })), dataZoom: this.widget ? null : [{ type: 'inside', realtime: true, @@ -396,6 +412,11 @@ export class NodesNetworksChartComponent implements OnInit { }, }], }; + + if (isMobile()) { + // @ts-ignore + this.chartOptions.legend.left = 50; + } } onChartInit(ec): void {