Merge branch 'master' into ops/add-unfurl-install
This commit is contained in:
commit
2e891eb926
@ -6,7 +6,7 @@ class StatisticsApi {
|
|||||||
public async $getStatistics(interval: string | null = null): Promise<any> {
|
public async $getStatistics(interval: string | null = null): Promise<any> {
|
||||||
interval = Common.getSqlInterval(interval);
|
interval = Common.getSqlInterval(interval);
|
||||||
|
|
||||||
let query = `SELECT UNIX_TIMESTAMP(added) AS added, channel_count, node_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
|
||||||
FROM lightning_stats`;
|
FROM lightning_stats`;
|
||||||
|
|
||||||
if (interval) {
|
if (interval) {
|
||||||
|
@ -15,6 +15,11 @@ li.nav-item {
|
|||||||
margin: auto 10px;
|
margin: auto 10px;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
|
@media (max-width: 992px) {
|
||||||
|
margin: auto 7px;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
@media (min-width: 992px) {
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Top Capacity Nodes</h5>
|
<h5 class="card-title">Top Capacity Nodes</h5>
|
||||||
<app-nodes-list [nodes$]="nodesByCapacity$"></app-nodes-list>
|
<app-nodes-list [nodes$]="nodesByCapacity$"></app-nodes-list>
|
||||||
<div><a [routerLink]="['/lightning/nodes' | relativeUrl]" i18n="dashboard.view-more">View more »</a></div>
|
<!-- <div><a [routerLink]="['/lightning/nodes' | relativeUrl]" i18n="dashboard.view-more">View more »</a></div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -63,7 +63,7 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Most Connected Nodes</h5>
|
<h5 class="card-title">Most Connected Nodes</h5>
|
||||||
<app-nodes-list [nodes$]="nodesByChannels$"></app-nodes-list>
|
<app-nodes-list [nodes$]="nodesByChannels$"></app-nodes-list>
|
||||||
<div><a [routerLink]="['/lightning/nodes' | relativeUrl]" i18n="dashboard.view-more">View more »</a></div>
|
<!-- <div><a [routerLink]="['/lightning/nodes' | relativeUrl]" i18n="dashboard.view-more">View more »</a></div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
.widget > .chart {
|
.widget > .chart {
|
||||||
-webkit-mask: linear-gradient(180deg, #11131f00 0%, #11131fff 20%);
|
-webkit-mask: linear-gradient(180deg, #11131f00 0%, #11131fff 20%);
|
||||||
|
min-height: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart {
|
.chart {
|
||||||
@ -43,23 +44,18 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
|
|
||||||
@media (max-width: 992px) {
|
@media (max-width: 992px) {
|
||||||
padding-bottom: 25px;
|
padding-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 829px) {
|
@media (max-width: 829px) {
|
||||||
padding-bottom: 50px;
|
padding-bottom: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
padding-bottom: 25px;
|
padding-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 629px) {
|
@media (max-width: 629px) {
|
||||||
padding-bottom: 55px;
|
padding-bottom: 55px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 567px) {
|
@media (max-width: 567px) {
|
||||||
padding-bottom: 55px;
|
padding-bottom: 55px;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Input, NgZone, OnDestroy, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, HostListener, Input, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||||
import { SeoService } from 'src/app/services/seo.service';
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
import { ApiService } from 'src/app/services/api.service';
|
import { ApiService } from 'src/app/services/api.service';
|
||||||
import { Observable, switchMap, tap, zip } from 'rxjs';
|
import { Observable, switchMap, tap, zip } from 'rxjs';
|
||||||
@ -26,7 +26,7 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
|||||||
chartOptions: EChartsOption = {};
|
chartOptions: EChartsOption = {};
|
||||||
chartInitOptions = {
|
chartInitOptions = {
|
||||||
renderer: 'canvas',
|
renderer: 'canvas',
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private seoService: SeoService,
|
private seoService: SeoService,
|
||||||
@ -98,6 +98,7 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.chartOptions = {
|
this.chartOptions = {
|
||||||
|
silent: true,
|
||||||
title: title ?? undefined,
|
title: title ?? undefined,
|
||||||
geo3D: {
|
geo3D: {
|
||||||
map: 'world',
|
map: 'world',
|
||||||
@ -110,9 +111,10 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
viewControl: {
|
viewControl: {
|
||||||
center: this.style === 'widget' ? [0, 0, -1] : undefined,
|
center: this.style === 'widget' ? [0, 0, -10] : undefined,
|
||||||
minDistance: 0.1,
|
minDistance: this.style === 'widget' ? 22 : 0.1,
|
||||||
distance: this.style === 'widget' ? 45 : 60,
|
maxDistance: this.style === 'widget' ? 22 : 60,
|
||||||
|
distance: this.style === 'widget' ? 22 : 60,
|
||||||
alpha: 90,
|
alpha: 90,
|
||||||
panMouseButton: 'left',
|
panMouseButton: 'left',
|
||||||
rotateMouseButton: undefined,
|
rotateMouseButton: undefined,
|
||||||
@ -167,6 +169,14 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@HostListener('window:wheel', ['$event'])
|
||||||
|
onWindowScroll(e): void {
|
||||||
|
// Not very smooth when using the mouse
|
||||||
|
if (this.style === 'widget' && e.target.tagName === 'CANVAS') {
|
||||||
|
window.scrollBy({left: 0, top: e.deltaY, behavior: 'auto'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onChartInit(ec) {
|
onChartInit(ec) {
|
||||||
if (this.chartInstance !== undefined) {
|
if (this.chartInstance !== undefined) {
|
||||||
return;
|
return;
|
||||||
@ -174,6 +184,15 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.chartInstance = ec;
|
this.chartInstance = ec;
|
||||||
|
|
||||||
|
if (this.style === 'widget') {
|
||||||
|
this.chartInstance.getZr().on('click', (e) => {
|
||||||
|
this.zone.run(() => {
|
||||||
|
const url = new RelativeUrlPipe(this.stateService).transform(`/graphs/lightning/nodes-channels-map`);
|
||||||
|
this.router.navigate([url]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.chartInstance.on('click', (e) => {
|
this.chartInstance.on('click', (e) => {
|
||||||
if (e.data && e.data.publicKey) {
|
if (e.data && e.data.publicKey) {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
|
@ -83,7 +83,6 @@ export class NodesNetworksChartComponent implements OnInit {
|
|||||||
tap((response) => {
|
tap((response) => {
|
||||||
const data = response.body;
|
const data = response.body;
|
||||||
this.prepareChartOptions({
|
this.prepareChartOptions({
|
||||||
node_count: data.map(val => [val.added * 1000, val.node_count]),
|
|
||||||
tor_nodes: data.map(val => [val.added * 1000, val.tor_nodes]),
|
tor_nodes: data.map(val => [val.added * 1000, val.tor_nodes]),
|
||||||
clearnet_nodes: data.map(val => [val.added * 1000, val.clearnet_nodes]),
|
clearnet_nodes: data.map(val => [val.added * 1000, val.clearnet_nodes]),
|
||||||
unannounced_nodes: data.map(val => [val.added * 1000, val.unannounced_nodes]),
|
unannounced_nodes: data.map(val => [val.added * 1000, val.unannounced_nodes]),
|
||||||
@ -103,7 +102,7 @@ export class NodesNetworksChartComponent implements OnInit {
|
|||||||
|
|
||||||
prepareChartOptions(data) {
|
prepareChartOptions(data) {
|
||||||
let title: object;
|
let title: object;
|
||||||
if (data.node_count.length === 0) {
|
if (data.tor_nodes.length === 0) {
|
||||||
title = {
|
title = {
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: 'grey',
|
color: 'grey',
|
||||||
@ -145,33 +144,34 @@ export class NodesNetworksChartComponent implements OnInit {
|
|||||||
},
|
},
|
||||||
borderColor: '#000',
|
borderColor: '#000',
|
||||||
formatter: (ticks) => {
|
formatter: (ticks) => {
|
||||||
|
let total = 0;
|
||||||
const date = new Date(ticks[0].data[0]).toLocaleDateString(this.locale, { year: 'numeric', month: 'short', day: 'numeric' });
|
const date = new Date(ticks[0].data[0]).toLocaleDateString(this.locale, { year: 'numeric', month: 'short', day: 'numeric' });
|
||||||
let tooltip = `<b style="color: white; margin-left: 2px">${date}</b><br>`;
|
let tooltip = `<b style="color: white; margin-left: 2px">${date}</b><br>`;
|
||||||
|
|
||||||
for (const tick of ticks) {
|
for (const tick of ticks.reverse()) {
|
||||||
if (tick.seriesIndex === 0) { // Total
|
if (tick.seriesIndex === 0) { // Tor
|
||||||
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`;
|
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`;
|
||||||
} else if (tick.seriesIndex === 1) { // Tor
|
} else if (tick.seriesIndex === 1) { // Clearnet
|
||||||
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`;
|
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`;
|
||||||
} else if (tick.seriesIndex === 2) { // Clearnet
|
} 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) { // Unannounced
|
|
||||||
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`;
|
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}`;
|
||||||
}
|
}
|
||||||
tooltip += `<br>`;
|
tooltip += `<br>`;
|
||||||
|
total += tick.data[1];
|
||||||
}
|
}
|
||||||
|
tooltip += `<b>Total:</b> ${formatNumber(total, this.locale, '1.0-0')} nodes`;
|
||||||
|
|
||||||
return tooltip;
|
return tooltip;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
xAxis: data.node_count.length === 0 ? undefined : {
|
xAxis: data.tor_nodes.length === 0 ? undefined : {
|
||||||
type: 'time',
|
type: 'time',
|
||||||
splitNumber: (this.isMobile() || this.widget) ? 5 : 10,
|
splitNumber: (this.isMobile() || this.widget) ? 5 : 10,
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
hideOverlap: true,
|
hideOverlap: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
legend: data.node_count.length === 0 ? undefined : {
|
legend: data.tor_nodes.length === 0 ? undefined : {
|
||||||
padding: 10,
|
padding: 10,
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
@ -214,7 +214,7 @@ export class NodesNetworksChartComponent implements OnInit {
|
|||||||
'Unannounced': true,
|
'Unannounced': true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
yAxis: data.node_count.length === 0 ? undefined : [
|
yAxis: data.tor_nodes.length === 0 ? undefined : [
|
||||||
{
|
{
|
||||||
type: 'value',
|
type: 'value',
|
||||||
position: 'left',
|
position: 'left',
|
||||||
@ -236,45 +236,23 @@ export class NodesNetworksChartComponent implements OnInit {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
series: data.node_count.length === 0 ? [] : [
|
series: data.tor_nodes.length === 0 ? [] : [
|
||||||
{
|
|
||||||
zlevel: 1,
|
|
||||||
name: $localize`Total`,
|
|
||||||
showSymbol: false,
|
|
||||||
symbol: 'none',
|
|
||||||
data: data.node_count,
|
|
||||||
type: 'line',
|
|
||||||
lineStyle: {
|
|
||||||
width: 2,
|
|
||||||
},
|
|
||||||
markLine: {
|
|
||||||
silent: true,
|
|
||||||
symbol: 'none',
|
|
||||||
lineStyle: {
|
|
||||||
type: 'solid',
|
|
||||||
color: '#ffffff66',
|
|
||||||
opacity: 1,
|
|
||||||
width: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
opacity: 0.25,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
zlevel: 1,
|
zlevel: 1,
|
||||||
yAxisIndex: 0,
|
yAxisIndex: 0,
|
||||||
name: $localize`Tor`,
|
name: $localize`Unannounced`,
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
symbol: 'none',
|
symbol: 'none',
|
||||||
data: data.tor_nodes,
|
data: data.unannounced_nodes,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
width: 2,
|
width: 2,
|
||||||
},
|
},
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
opacity: 0.25,
|
opacity: 0.5,
|
||||||
},
|
},
|
||||||
|
stack: 'Total',
|
||||||
|
color: '#FDD835',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
zlevel: 1,
|
zlevel: 1,
|
||||||
@ -288,24 +266,28 @@ export class NodesNetworksChartComponent implements OnInit {
|
|||||||
width: 2,
|
width: 2,
|
||||||
},
|
},
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
opacity: 0.25,
|
opacity: 0.5,
|
||||||
},
|
},
|
||||||
|
stack: 'Total',
|
||||||
|
color: '#00ACC1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
zlevel: 1,
|
zlevel: 1,
|
||||||
yAxisIndex: 0,
|
yAxisIndex: 0,
|
||||||
name: $localize`Unannounced`,
|
name: $localize`Tor`,
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
symbol: 'none',
|
symbol: 'none',
|
||||||
data: data.unannounced_nodes,
|
data: data.tor_nodes,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
width: 2,
|
width: 2,
|
||||||
},
|
},
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
opacity: 0.25,
|
opacity: 0.5,
|
||||||
},
|
},
|
||||||
}
|
stack: 'Total',
|
||||||
|
color: '#7D4698',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
dataZoom: this.widget ? null : [{
|
dataZoom: this.widget ? null : [{
|
||||||
type: 'inside',
|
type: 'inside',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user