From 5a385c20f03302c5ed6adfb511890d23d973bd58 Mon Sep 17 00:00:00 2001 From: mrv777 Date: Fri, 22 Nov 2024 10:26:12 -0600 Subject: [PATCH] Swarm styles, refresh on load, more combined stats, more info in table (#491) * fix: swarm add less white space * fix: On mount refresh swarm data * fix: Allow setable swarm refresh time * fix: Increase swarm warning temp * fix: Add total power and best diff of swarm * fix: Add VR temp to swarm * fix: Increase extra swarm data font size * add rejected shares too on swarm page --- main/http_server/axe-os/src/app/app.module.ts | 4 +- .../app/components/swarm/swarm.component.html | 69 ++++++++++++++++--- .../app/components/swarm/swarm.component.scss | 8 +-- .../app/components/swarm/swarm.component.ts | 64 +++++++++++++---- .../axe-os/src/app/local-storage.service.ts | 9 +++ 5 files changed, 123 insertions(+), 31 deletions(-) diff --git a/main/http_server/axe-os/src/app/app.module.ts b/main/http_server/axe-os/src/app/app.module.ts index fb3fd7c5b..78f4701b7 100644 --- a/main/http_server/axe-os/src/app/app.module.ts +++ b/main/http_server/axe-os/src/app/app.module.ts @@ -24,6 +24,7 @@ import { DateAgoPipe } from './pipes/date-ago.pipe'; import { HashSuffixPipe } from './pipes/hash-suffix.pipe'; import { PrimeNGModule } from './prime-ng.module'; import { MessageModule } from 'primeng/message'; +import { TooltipModule } from 'primeng/tooltip'; const components = [ AppComponent, @@ -59,7 +60,8 @@ const components = [ CommonModule, PrimeNGModule, AppLayoutModule, - MessageModule + MessageModule, + TooltipModule ], providers: [ { provide: LocationStrategy, useClass: HashLocationStrategy }, diff --git a/main/http_server/axe-os/src/app/components/swarm/swarm.component.html b/main/http_server/axe-os/src/app/components/swarm/swarm.component.html index 58a806a5d..b858a5d1f 100644 --- a/main/http_server/axe-os/src/app/components/swarm/swarm.component.html +++ b/main/http_server/axe-os/src/app/components/swarm/swarm.component.html @@ -1,7 +1,7 @@ -
+
-
+
@@ -14,15 +14,35 @@
-
+
-
- Total Hash Rate: {{totalHashRate * 1000000000 | hashSuffix}} +
+ + + + {{refreshTimeSet}}s +
+
+ +
+
+ Total Hash Rate: {{totals.hashRate * 1000000000 | hashSuffix}} +
+
+ Total Power: {{totals.power | number: '1.1-1'}} W +
+
+ Best Diff: {{totals.bestDiff}}
@@ -32,7 +52,7 @@ IP Hash Rate Uptime - Accepted + Shares Power Temp Best Diff @@ -45,14 +65,43 @@ {{axe.IP}} -
{{axe.hostname}}
+
{{axe.hostname}}
{{axe.hashRate * 1000000000 | hashSuffix}} {{axe.uptimeSeconds | dateAgo}} - {{axe.sharesAccepted | number: '1.0-0'}} + +
+ {{axe.sharesAccepted | number: '1.0-0'}} +
+
+ {{axe.sharesRejected | number: '1.0-0'}} +
+ {{axe.power | number: '1.1-1'}} W - {{axe.temp | number: '1.0-1'}}°C - {{axe.bestDiff}} + +
+ {{axe.temp | number: '1.0-1'}}°C +
+
+ {{axe.vrTemp | number: '1.0-1'}}°C +
+ + +
{{axe.bestDiff}}
+
+ {{axe.bestSessionDiff}} +
+ {{axe.version}} diff --git a/main/http_server/axe-os/src/app/components/swarm/swarm.component.scss b/main/http_server/axe-os/src/app/components/swarm/swarm.component.scss index 92bb2e1a1..885da09ce 100644 --- a/main/http_server/axe-os/src/app/components/swarm/swarm.component.scss +++ b/main/http_server/axe-os/src/app/components/swarm/swarm.component.scss @@ -1,11 +1,5 @@ -form { - margin-bottom: 20px; -} - table { width: 100%; - margin-top: 40px; - margin-bottom: 40px; border: 1px solid #304562; } @@ -57,7 +51,7 @@ a { .table-container { width: 100%; overflow-x: auto; - margin: 1rem 0; + margin: 0; table { min-width: 100%; diff --git a/main/http_server/axe-os/src/app/components/swarm/swarm.component.ts b/main/http_server/axe-os/src/app/components/swarm/swarm.component.ts index 2fdbfa299..a59cdb708 100644 --- a/main/http_server/axe-os/src/app/components/swarm/swarm.component.ts +++ b/main/http_server/axe-os/src/app/components/swarm/swarm.component.ts @@ -1,12 +1,12 @@ import { HttpClient } from '@angular/common/http'; import { Component, OnDestroy, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms'; import { ToastrService } from 'ngx-toastr'; import { catchError, from, map, mergeMap, of, take, timeout, toArray } from 'rxjs'; import { LocalStorageService } from 'src/app/local-storage.service'; import { SystemService } from 'src/app/services/system.service'; -const REFRESH_TIME_SECONDS = 30; const SWARM_DATA = 'SWARM_DATA' +const SWARM_REFRESH_TIME = 'SWARM_REFRESH_TIME'; @Component({ selector: 'app-swarm', templateUrl: './swarm.component.html', @@ -24,12 +24,15 @@ export class SwarmComponent implements OnInit, OnDestroy { public scanning = false; public refreshIntervalRef!: number; - public refreshIntervalTime = REFRESH_TIME_SECONDS; + public refreshIntervalTime = 30; + public refreshTimeSet = 30; - public totalHashRate: number = 0; + public totals: { hashRate: number, power: number, bestDiff: string } = { hashRate: 0, power: 0, bestDiff: '0' }; public isRefreshing = false; + public refreshIntervalControl: FormControl; + constructor( private fb: FormBuilder, private systemService: SystemService, @@ -40,7 +43,18 @@ export class SwarmComponent implements OnInit, OnDestroy { this.form = this.fb.group({ manualAddIp: [null, [Validators.required, Validators.pattern('(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)')]] - }) + }); + + const storedRefreshTime = this.localStorageService.getNumber(SWARM_REFRESH_TIME) ?? 30; + this.refreshIntervalTime = storedRefreshTime; + this.refreshTimeSet = storedRefreshTime; + this.refreshIntervalControl = new FormControl(storedRefreshTime); + + this.refreshIntervalControl.valueChanges.subscribe(value => { + this.refreshIntervalTime = value; + this.refreshTimeSet = value; + this.localStorageService.setNumber(SWARM_REFRESH_TIME, value); + }); } @@ -52,7 +66,7 @@ export class SwarmComponent implements OnInit, OnDestroy { //this.swarm$ = this.scanNetwork('192.168.1.23', '255.255.255.0').pipe(take(1)); } else { this.swarm = swarmData; - this.calculateTotalHashRate(); + this.refreshList(); } this.refreshIntervalRef = window.setInterval(() => { @@ -118,7 +132,7 @@ export class SwarmComponent implements OnInit, OnDestroy { const newItems = result.filter(item => !existingIps.has(item.IP)); this.swarm = [...this.swarm, ...newItems].sort(this.sortByIp.bind(this)); this.localStorageService.setObject(SWARM_DATA, this.swarm); - this.calculateTotalHashRate(); + this.calculateTotals(); }, complete: () => { this.scanning = false; @@ -140,7 +154,7 @@ export class SwarmComponent implements OnInit, OnDestroy { this.swarm.push({ IP: newIp, ...res }); this.swarm = this.swarm.sort(this.sortByIp.bind(this)); this.localStorageService.setObject(SWARM_DATA, this.swarm); - this.calculateTotalHashRate(); + this.calculateTotals(); } }); } @@ -166,11 +180,11 @@ export class SwarmComponent implements OnInit, OnDestroy { public remove(axeOs: any) { this.swarm = this.swarm.filter(axe => axe.IP != axeOs.IP); this.localStorageService.setObject(SWARM_DATA, this.swarm); - this.calculateTotalHashRate(); + this.calculateTotals(); } public refreshList() { - this.refreshIntervalTime = REFRESH_TIME_SECONDS; + this.refreshIntervalTime = this.refreshTimeSet; const ips = this.swarm.map(axeOs => axeOs.IP); this.isRefreshing = true; @@ -209,7 +223,7 @@ export class SwarmComponent implements OnInit, OnDestroy { next: (result) => { this.swarm = result.sort(this.sortByIp.bind(this)); this.localStorageService.setObject(SWARM_DATA, this.swarm); - this.calculateTotalHashRate(); + this.calculateTotals(); this.isRefreshing = false; }, complete: () => { @@ -222,8 +236,32 @@ export class SwarmComponent implements OnInit, OnDestroy { return this.ipToInt(a.IP) - this.ipToInt(b.IP); } - private calculateTotalHashRate() { - this.totalHashRate = this.swarm.reduce((sum, axe) => sum + (axe.hashRate || 0), 0); + private convertBestDiffToNumber(bestDiff: string): number { + if (!bestDiff) return 0; + const value = parseFloat(bestDiff); + const unit = bestDiff.slice(-1).toUpperCase(); + switch (unit) { + case 'T': return value * 1000000000000; + case 'G': return value * 1000000000; + case 'M': return value * 1000000; + case 'K': return value * 1000; + default: return value; + } + } + + private formatBestDiff(value: number): string { + if (value >= 1000000000000) return `${(value / 1000000000000).toFixed(2)}T`; + if (value >= 1000000000) return `${(value / 1000000000).toFixed(2)}G`; + if (value >= 1000000) return `${(value / 1000000).toFixed(2)}M`; + if (value >= 1000) return `${(value / 1000).toFixed(2)}K`; + return value.toFixed(2); + } + + private calculateTotals() { + this.totals.hashRate = this.swarm.reduce((sum, axe) => sum + (axe.hashRate || 0), 0); + this.totals.power = this.swarm.reduce((sum, axe) => sum + (axe.power || 0), 0); + const maxDiff = Math.max(...this.swarm.map(axe => this.convertBestDiffToNumber(axe.bestDiff))); + this.totals.bestDiff = this.formatBestDiff(maxDiff); } } diff --git a/main/http_server/axe-os/src/app/local-storage.service.ts b/main/http_server/axe-os/src/app/local-storage.service.ts index adeb596db..4f06460e6 100644 --- a/main/http_server/axe-os/src/app/local-storage.service.ts +++ b/main/http_server/axe-os/src/app/local-storage.service.ts @@ -34,4 +34,13 @@ export class LocalStorageService { } return JSON.parse(item); } + + setNumber(key: string, value: number) { + localStorage.setItem(key, value.toString()); + } + + getNumber(key: string): number | null { + const value = localStorage.getItem(key); + return value ? Number(value) : null; + } }