mirror of
https://github.com/everoddandeven/monerod-gui.git
synced 2024-10-29 18:37:34 +00:00
Network methods implementation
This commit is contained in:
parent
ca4745578e
commit
203fbc9968
9 changed files with 264 additions and 24 deletions
50
package-lock.json
generated
50
package-lock.json
generated
|
@ -19,7 +19,9 @@
|
||||||
"@angular/router": "17.3.6",
|
"@angular/router": "17.3.6",
|
||||||
"bootstrap": "5.3.3",
|
"bootstrap": "5.3.3",
|
||||||
"bootstrap-icons": "1.11.3",
|
"bootstrap-icons": "1.11.3",
|
||||||
"bootstrap-table": "1.23.4",
|
"bootstrap-table": "1.23.5",
|
||||||
|
"chart.js": "4.4.4",
|
||||||
|
"chartjs": "0.3.24",
|
||||||
"crypto": "1.0.1",
|
"crypto": "1.0.1",
|
||||||
"idb": "8.0.0",
|
"idb": "8.0.0",
|
||||||
"jquery": "3.7.1",
|
"jquery": "3.7.1",
|
||||||
|
@ -44,6 +46,7 @@
|
||||||
"@ngx-translate/http-loader": "8.0.0",
|
"@ngx-translate/http-loader": "8.0.0",
|
||||||
"@playwright/test": "1.43.1",
|
"@playwright/test": "1.43.1",
|
||||||
"@types/bootstrap": "5.2.10",
|
"@types/bootstrap": "5.2.10",
|
||||||
|
"@types/chart.js": "2.9.41",
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "29.5.12",
|
||||||
"@types/jquery": "3.5.30",
|
"@types/jquery": "3.5.30",
|
||||||
"@types/node": "20.12.7",
|
"@types/node": "20.12.7",
|
||||||
|
@ -4579,6 +4582,11 @@
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@kurkle/color": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
|
||||||
|
},
|
||||||
"node_modules/@leichtgewicht/ip-codec": {
|
"node_modules/@leichtgewicht/ip-codec": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
|
||||||
|
@ -5807,6 +5815,15 @@
|
||||||
"@types/responselike": "^1.0.0"
|
"@types/responselike": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/chart.js": {
|
||||||
|
"version": "2.9.41",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.41.tgz",
|
||||||
|
"integrity": "sha512-3dvkDvueckY83UyUXtJMalYoH6faOLkWQoaTlJgB4Djde3oORmNP0Jw85HtzTuXyliUHcdp704s0mZFQKio/KQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"moment": "^2.10.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/connect": {
|
"node_modules/@types/connect": {
|
||||||
"version": "3.4.38",
|
"version": "3.4.38",
|
||||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
||||||
|
@ -8278,9 +8295,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/bootstrap-table": {
|
"node_modules/bootstrap-table": {
|
||||||
"version": "1.23.4",
|
"version": "1.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.23.4.tgz",
|
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.23.5.tgz",
|
||||||
"integrity": "sha512-3HHBJzzpg5z03F4eY8AHpLdW26FlzI0hFcmCb+8HRd5CbqLTd4ZJ5dfJUWFE+euU29rr6vkTyhSu44ucueYPDw==",
|
"integrity": "sha512-9WByoSpJvA73gi2YYIlX6IWR74oZtBmSixul/Th8FTBtBd/kZRpbKESGTjhA3BA3AYTnfyY8Iy1KeRWPlV2GWQ==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"jquery": "3"
|
"jquery": "3"
|
||||||
}
|
}
|
||||||
|
@ -8988,6 +9005,22 @@
|
||||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/chart.js": {
|
||||||
|
"version": "4.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.4.tgz",
|
||||||
|
"integrity": "sha512-emICKGBABnxhMjUjlYRR12PmOXhJ2eJjEHL2/dZlWjxRAZT1D8xplLFq5M0tMQK8ja+wBS/tuVEJB5C6r7VxJA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@kurkle/color": "^0.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"pnpm": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chartjs": {
|
||||||
|
"version": "0.3.24",
|
||||||
|
"resolved": "https://registry.npmjs.org/chartjs/-/chartjs-0.3.24.tgz",
|
||||||
|
"integrity": "sha512-h6G9qcDqmFYnSWqjWCzQMeOLiypS+pM6Fq2Rj7LPty8Kjx5yHonwwJ7oEHImZpQ2u9Pu36XGYfardvvBiQVrhg=="
|
||||||
|
},
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
|
@ -17982,6 +18015,15 @@
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/moment": {
|
||||||
|
"version": "2.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||||
|
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mrmime": {
|
"node_modules/mrmime": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
||||||
|
|
|
@ -56,7 +56,9 @@
|
||||||
"@angular/router": "17.3.6",
|
"@angular/router": "17.3.6",
|
||||||
"bootstrap": "5.3.3",
|
"bootstrap": "5.3.3",
|
||||||
"bootstrap-icons": "1.11.3",
|
"bootstrap-icons": "1.11.3",
|
||||||
"bootstrap-table": "1.23.4",
|
"bootstrap-table": "1.23.5",
|
||||||
|
"chart.js": "4.4.4",
|
||||||
|
"chartjs": "0.3.24",
|
||||||
"crypto": "1.0.1",
|
"crypto": "1.0.1",
|
||||||
"idb": "8.0.0",
|
"idb": "8.0.0",
|
||||||
"jquery": "3.7.1",
|
"jquery": "3.7.1",
|
||||||
|
@ -81,6 +83,7 @@
|
||||||
"@ngx-translate/http-loader": "8.0.0",
|
"@ngx-translate/http-loader": "8.0.0",
|
||||||
"@playwright/test": "1.43.1",
|
"@playwright/test": "1.43.1",
|
||||||
"@types/bootstrap": "5.2.10",
|
"@types/bootstrap": "5.2.10",
|
||||||
|
"@types/chart.js": "2.9.41",
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "29.5.12",
|
||||||
"@types/jquery": "3.5.30",
|
"@types/jquery": "3.5.30",
|
||||||
"@types/node": "20.12.7",
|
"@types/node": "20.12.7",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { EventEmitter, Injectable } from '@angular/core';
|
import { EventEmitter, Injectable } from '@angular/core';
|
||||||
import { DaemonService } from './daemon.service';
|
import { DaemonService } from './daemon.service';
|
||||||
import { BlockCount, BlockHeader, Chain, DaemonInfo, MinerData, MiningStatus, NetStats, SyncInfo } from '../../../../common';
|
import { BlockCount, BlockHeader, Chain, DaemonInfo, MinerData, MiningStatus, NetStats, NetStatsHistory, SyncInfo } from '../../../../common';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -35,6 +35,7 @@ export class DaemonDataService {
|
||||||
private _gettingAltChains: boolean = false;
|
private _gettingAltChains: boolean = false;
|
||||||
|
|
||||||
private _netStats?: NetStats;
|
private _netStats?: NetStats;
|
||||||
|
private _netStatsHistory: NetStatsHistory = new NetStatsHistory();
|
||||||
private _gettingNetStats: boolean = false;
|
private _gettingNetStats: boolean = false;
|
||||||
|
|
||||||
private _miningStatus?: MiningStatus;
|
private _miningStatus?: MiningStatus;
|
||||||
|
@ -50,6 +51,9 @@ export class DaemonDataService {
|
||||||
public readonly syncInfoRefreshStart: EventEmitter<void> = new EventEmitter<void>();
|
public readonly syncInfoRefreshStart: EventEmitter<void> = new EventEmitter<void>();
|
||||||
public readonly syncInfoRefreshEnd: EventEmitter<void> = new EventEmitter<void>();
|
public readonly syncInfoRefreshEnd: EventEmitter<void> = new EventEmitter<void>();
|
||||||
|
|
||||||
|
public readonly netStatsRefreshStart: EventEmitter<void> = new EventEmitter<void>();
|
||||||
|
public readonly netStatsRefreshEnd: EventEmitter<void> = new EventEmitter<void>();
|
||||||
|
|
||||||
constructor(private daemonService: DaemonService) {
|
constructor(private daemonService: DaemonService) {
|
||||||
this.startLoop();
|
this.startLoop();
|
||||||
|
|
||||||
|
@ -139,6 +143,10 @@ export class DaemonDataService {
|
||||||
return this.netStats;
|
return this.netStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get netStatsHistory(): NetStatsHistory {
|
||||||
|
return this._netStatsHistory;
|
||||||
|
}
|
||||||
|
|
||||||
public get gettingNetStats(): boolean {
|
public get gettingNetStats(): boolean {
|
||||||
return this._gettingNetStats;
|
return this._gettingNetStats;
|
||||||
}
|
}
|
||||||
|
@ -271,7 +279,10 @@ export class DaemonDataService {
|
||||||
await this.refreshAltChains();
|
await this.refreshAltChains();
|
||||||
|
|
||||||
this._gettingNetStats = true;
|
this._gettingNetStats = true;
|
||||||
|
this.netStatsRefreshStart.emit();
|
||||||
this._netStats = await this.daemonService.getNetStats();
|
this._netStats = await this.daemonService.getNetStats();
|
||||||
|
this._netStatsHistory.add(this._netStats);
|
||||||
|
this.netStatsRefreshEnd.emit();
|
||||||
this._gettingNetStats = false;
|
this._gettingNetStats = false;
|
||||||
|
|
||||||
await this.refreshMiningStatus();
|
await this.refreshMiningStatus();
|
||||||
|
|
|
@ -12,6 +12,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="daemonRunning" class="tab-content" id="pills-tabContent">
|
<div *ngIf="daemonRunning" class="tab-content" id="pills-tabContent">
|
||||||
|
<div class="tab-pane fade show active" id="pills-net-stats" role="tabpanel" aria-labelledby="pills-net-stats-tab" tabindex="0">
|
||||||
|
<h2>Bytes In</h2>
|
||||||
|
<canvas class="my-4 w-100" id="netStatsBytesInChart" width="900" height="380"></canvas>
|
||||||
|
|
||||||
|
<h2>Bytes Out</h2>
|
||||||
|
<canvas class="my-4 w-100" id="netStatsBytesOutChart" width="900" height="380"></canvas>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-daemon-not-running></app-daemon-not-running>
|
<app-daemon-not-running></app-daemon-not-running>
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import { AfterViewInit, Component } from '@angular/core';
|
import { AfterViewInit, Component } from '@angular/core';
|
||||||
import { NavbarService } from '../../shared/components/navbar/navbar.service';
|
import { NavbarService } from '../../shared/components/navbar/navbar.service';
|
||||||
import { DaemonDataService } from '../../core/services';
|
import { DaemonDataService, DaemonService } from '../../core/services';
|
||||||
import { NavbarLink } from '../../shared/components/navbar/navbar.model';
|
import { NavbarLink } from '../../shared/components/navbar/navbar.model';
|
||||||
|
import { Chart, ChartData } from 'chart.js/auto'
|
||||||
|
import { NetStatsHistoryEntry } from '../../../common';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-network',
|
selector: 'app-network',
|
||||||
|
@ -9,22 +11,149 @@ import { NavbarLink } from '../../shared/components/navbar/navbar.model';
|
||||||
styleUrl: './network.component.scss'
|
styleUrl: './network.component.scss'
|
||||||
})
|
})
|
||||||
export class NetworkComponent implements AfterViewInit {
|
export class NetworkComponent implements AfterViewInit {
|
||||||
public daemonRunning: boolean = false;
|
|
||||||
public readonly navbarLinks: NavbarLink[];
|
public readonly navbarLinks: NavbarLink[];
|
||||||
|
|
||||||
constructor(private navbarService: NavbarService, private daemonData: DaemonDataService) {
|
private netStatsBytesInChart?: Chart;
|
||||||
|
private netStatsBytesOutChart?: Chart;
|
||||||
|
|
||||||
|
public get daemonRunning(): boolean {
|
||||||
|
return this.daemonData.running;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private navbarService: NavbarService, private daemonService: DaemonService, private daemonData: DaemonDataService) {
|
||||||
this.navbarLinks = [
|
this.navbarLinks = [
|
||||||
new NavbarLink('pills-net-stats-tab', '#pills-net-stats', 'pills-net-stats', false, 'Statistics'),
|
new NavbarLink('pills-net-stats-tab', '#pills-net-stats', 'pills-net-stats', false, 'Statistics'),
|
||||||
new NavbarLink('pills-limits-tab', '#pills-limits', 'pills-limits', false, 'Limits'),
|
new NavbarLink('pills-limits-tab', '#pills-limits', 'pills-limits', false, 'Limits'),
|
||||||
new NavbarLink('pills-public-nodes-tab', '#pills-public-nodes', 'pills-public-nodes', false, 'Public Nodes')
|
new NavbarLink('pills-public-nodes-tab', '#pills-public-nodes', 'pills-public-nodes', false, 'Public Nodes')
|
||||||
];
|
];
|
||||||
|
|
||||||
|
this.daemonData.netStatsRefreshEnd.subscribe(() => {
|
||||||
|
this.refreshNetStatsHistory();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => {
|
||||||
|
if (!running) {
|
||||||
|
if (this.netStatsBytesInChart) {
|
||||||
|
this.netStatsBytesInChart.destroy();
|
||||||
|
this.netStatsBytesInChart = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngAfterViewInit(): void {
|
public ngAfterViewInit(): void {
|
||||||
this.daemonRunning = this.daemonData.running;
|
|
||||||
|
|
||||||
this.navbarService.setLinks(this.navbarLinks);
|
this.navbarService.setLinks(this.navbarLinks);
|
||||||
|
this.initNetStatsHistoryChart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private buildChartBytesInData(): ChartData {
|
||||||
|
const labels: string [] = [];
|
||||||
|
const data: number[] = [];
|
||||||
|
this.daemonData.netStatsHistory.history.forEach((entry: NetStatsHistoryEntry) => {
|
||||||
|
labels.push(`${entry.date.toLocaleTimeString()} ${entry.date.toLocaleDateString()}`);
|
||||||
|
data.push(entry.netStats.totalBytesIn);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
data: data,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderColor: '#007bff',
|
||||||
|
borderWidth: 4,
|
||||||
|
pointBackgroundColor: '#007bff'
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildChartBytesOutData(): ChartData {
|
||||||
|
const labels: string [] = [];
|
||||||
|
const data: number[] = [];
|
||||||
|
this.daemonData.netStatsHistory.history.forEach((entry: NetStatsHistoryEntry) => {
|
||||||
|
labels.push(`${entry.date.toLocaleTimeString()} ${entry.date.toLocaleDateString()}`);
|
||||||
|
data.push(entry.netStats.totalBytesOut);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
data: data,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderColor: '#007bff',
|
||||||
|
borderWidth: 4,
|
||||||
|
pointBackgroundColor: '#007bff'
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private initNetStatsHistoryChart(): void {
|
||||||
|
const ctx1 = <HTMLCanvasElement>document.getElementById('netStatsBytesInChart');
|
||||||
|
const ctx2 = <HTMLCanvasElement>document.getElementById('netStatsBytesOutChart');
|
||||||
|
|
||||||
|
if (!ctx1 || !ctx2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.netStatsBytesInChart = new Chart(ctx1, {
|
||||||
|
type: 'line',
|
||||||
|
data: this.buildChartBytesInData(),
|
||||||
|
options: {
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
boxPadding: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.netStatsBytesOutChart = new Chart(ctx2, {
|
||||||
|
type: 'line',
|
||||||
|
data: this.buildChartBytesOutData(),
|
||||||
|
options: {
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
boxPadding: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.netStatsBytesInChart.update();
|
||||||
|
this.netStatsBytesOutChart.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private refreshNetStatsHistory(): void {
|
||||||
|
if (!this.netStatsBytesInChart) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const last = this.daemonData.netStatsHistory.last;
|
||||||
|
|
||||||
|
if (!this.netStatsBytesInChart || !this.netStatsBytesOutChart) {
|
||||||
|
this.initNetStatsHistoryChart();
|
||||||
|
}
|
||||||
|
else if (last) {
|
||||||
|
const label = `${last.date.toLocaleTimeString()} ${last.date.toLocaleDateString()}`;
|
||||||
|
|
||||||
|
this.netStatsBytesInChart.data.labels?.push(label);
|
||||||
|
this.netStatsBytesInChart.data.datasets.forEach((dataset) => {
|
||||||
|
dataset.data.push(last.netStats.totalBytesIn);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.netStatsBytesOutChart.data.labels?.push(label);
|
||||||
|
this.netStatsBytesOutChart.data.datasets.forEach((dataset) => {
|
||||||
|
dataset.data.push(last.netStats.totalBytesOut);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.netStatsBytesInChart.update();
|
||||||
|
this.netStatsBytesOutChart.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -21,23 +21,19 @@
|
||||||
<h4 class="mb-3">Node</h4>
|
<h4 class="mb-3">Node</h4>
|
||||||
|
|
||||||
<div class="row gy-3">
|
<div class="row gy-3">
|
||||||
|
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label for="general-monerod-path" class="form-label">Monerod path</label>
|
<label for="general-monerod-path-control" class="form-label">Monerod path</label>
|
||||||
<input type="file" class="form-control" id="general-monerod-path" [(ngModel)]="currentSettings.monerodPath" [ngModelOptions]="{standalone: true}" (change)="onMonerodPathChange()" placeholder="AAA">
|
<div class="input-group mb-3">
|
||||||
|
<input id="general-monerod-path-control" type="text" class="form-control form-control-sm" placeholder="" aria-label="Monerod path" aria-describedby="basic-addon2" [value]="currentSettings.monerodPath" readonly>
|
||||||
|
<span class="input-group-text" id="basic-addon2"><button type="button" class="btn btn-secondary btn-sm" (click)="chooseMonerodFile()">Choose file</button></span>
|
||||||
|
</div>
|
||||||
|
<input type="file" class="form-control d-none" id="general-monerod-path" [(ngModel)]="currentSettings.monerodPath" [ngModelOptions]="{standalone: true}" (change)="onMonerodPathChange()" placeholder="AAA">
|
||||||
<small class="text-body-secondary">Path to monerod executable</small>
|
<small class="text-body-secondary">Path to monerod executable</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<div class="row gy-3">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<label for="general-xmrig-path" class="form-label">XMRig path</label>
|
|
||||||
<input type="file" class="form-control" id="general-xmrig-path" [(ngModel)]="currentSettings.monerodPath" [ngModelOptions]="{standalone: true}" (change)="onMonerodPathChange()" placeholder="AAA">
|
|
||||||
<small class="text-body-secondary">Path to XMRig executable</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -147,4 +147,24 @@ export class SettingsComponent implements AfterViewInit {
|
||||||
|
|
||||||
this.originalSettings = this.currentSettings.clone();
|
this.originalSettings = this.currentSettings.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public chooseMonerodFile(): void {
|
||||||
|
const input = document.getElementById('general-monerod-path');
|
||||||
|
|
||||||
|
if (!input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
public chooseXmrigFile(): void {
|
||||||
|
const input = document.getElementById('general-xmrig-path');
|
||||||
|
|
||||||
|
if (!input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
31
src/common/NetStatsHistory.ts
Normal file
31
src/common/NetStatsHistory.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import { NetStats } from "./NetStats";
|
||||||
|
|
||||||
|
export type NetStatsHistoryEntry = { date: Date, netStats: NetStats};
|
||||||
|
|
||||||
|
export class NetStatsHistory {
|
||||||
|
private _history: NetStatsHistoryEntry[];
|
||||||
|
private _last?: NetStatsHistoryEntry;
|
||||||
|
|
||||||
|
public get history(): NetStatsHistoryEntry[] {
|
||||||
|
return this._history;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get last(): NetStatsHistoryEntry | undefined {
|
||||||
|
return this._last;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._history = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public add(netStats: NetStats): void {
|
||||||
|
const entry = {
|
||||||
|
date: new Date(),
|
||||||
|
netStats: netStats
|
||||||
|
};
|
||||||
|
|
||||||
|
this._history.push(entry);
|
||||||
|
|
||||||
|
this._last = entry;
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,7 @@ export { TxBacklogEntry } from './TxBacklogEntry';
|
||||||
export { TxInfo } from './TxInfo';
|
export { TxInfo } from './TxInfo';
|
||||||
export { UpdateInfo } from './UpdateInfo';
|
export { UpdateInfo } from './UpdateInfo';
|
||||||
export { LogCategoryLevel, LogCategories } from './LogCategories';
|
export { LogCategoryLevel, LogCategories } from './LogCategories';
|
||||||
|
export { NetStatsHistory, NetStatsHistoryEntry } from './NetStatsHistory';
|
||||||
|
|
||||||
export * from './error';
|
export * from './error';
|
||||||
export * from './request';
|
export * from './request';
|
||||||
|
|
Loading…
Reference in a new issue