mirror of
https://github.com/everoddandeven/monerod-gui.git
synced 2025-01-03 17:39:49 +00:00
Daemon data service implementation
This commit is contained in:
parent
b0060fde8a
commit
131199113d
11 changed files with 391 additions and 313 deletions
15
app/main.ts
15
app/main.ts
|
@ -113,11 +113,11 @@ function getMonerodVersion(monerodFilePath: string): void {
|
|||
const monerodProcess = spawn(getMonerodPath(), [ '--version' ]);
|
||||
|
||||
monerodProcess.stdout.on('data', (data) => {
|
||||
win?.webContents.send('on-monerod-version', `${data}`);
|
||||
win?.webContents.send('monero-version', `${data}`);
|
||||
})
|
||||
|
||||
monerodProcess.stderr.on('data', (data) => {
|
||||
win?.webContents.send('on-monerod-version-error', `${data}`);
|
||||
win?.webContents.send('monero-version-error', `${data}`);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -290,14 +290,6 @@ const verifyFileHash = (filePath: string): Promise<string> => {
|
|||
});
|
||||
};
|
||||
|
||||
// Funzione per estrarre tar.bz2
|
||||
const extractTarBz2Old = (filePath: string, destination: string): Promise<void> => {
|
||||
return tar.x({
|
||||
file: filePath,
|
||||
cwd: destination,
|
||||
});
|
||||
};
|
||||
|
||||
const extractTarBz2 = (filePath: string, destination: string): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Crea il file decomprimendo il .bz2 in uno .tar temporaneo
|
||||
|
@ -354,11 +346,10 @@ try {
|
|||
startMoneroDaemon(configFilePath);
|
||||
})
|
||||
|
||||
ipcMain.on('get-monerod-version', (event, configFilePath: string) => {
|
||||
ipcMain.handle('get-monero-version', (event, configFilePath: string) => {
|
||||
getMonerodVersion(configFilePath);
|
||||
});
|
||||
|
||||
|
||||
// Gestione IPC
|
||||
ipcMain.handle('download-monero', async (event, downloadUrl: string, destination: string) => {
|
||||
try {
|
||||
|
|
|
@ -10,5 +10,14 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
|||
},
|
||||
onMoneroClose: (callback) => {
|
||||
ipcRenderer.on('monero-close', callback);
|
||||
},
|
||||
getMoneroVersion: () => {
|
||||
ipcRenderer.invoke('get-monero-version');
|
||||
},
|
||||
onMoneroVersion: (callback) => {
|
||||
ipcRenderer.on('monero-version', callback);
|
||||
},
|
||||
onMoneroVersionError: (callback) => {
|
||||
ipcRenderer.on('monero-version-error', callback);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -3,6 +3,8 @@ import { ElectronService } from './core/services';
|
|||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { APP_CONFIG } from '../environments/environment';
|
||||
import { DaemonService } from './core/services/daemon/daemon.service';
|
||||
import { DaemonDataService } from './core/services/daemon/daemon-data.service';
|
||||
import { LogsService } from './pages/logs/logs.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
|
@ -13,10 +15,16 @@ export class AppComponent {
|
|||
public loading: boolean;
|
||||
public daemonRunning: boolean;
|
||||
|
||||
public get initializing(): boolean {
|
||||
return this.daemonData.initializing;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private electronService: ElectronService,
|
||||
private translate: TranslateService,
|
||||
private daemonService: DaemonService
|
||||
private daemonService: DaemonService,
|
||||
private daemonData: DaemonDataService,
|
||||
private LogService: LogsService
|
||||
) {
|
||||
this.translate.setDefaultLang('en');
|
||||
console.log('APP_CONFIG', APP_CONFIG);
|
||||
|
|
16
src/app/core/services/daemon/daemon-data.service.spec.ts
Normal file
16
src/app/core/services/daemon/daemon-data.service.spec.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DaemonDataService } from './daemon-data.service';
|
||||
|
||||
describe('DaemonDataService', () => {
|
||||
let service: DaemonDataService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(DaemonDataService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
203
src/app/core/services/daemon/daemon-data.service.ts
Normal file
203
src/app/core/services/daemon/daemon-data.service.ts
Normal file
|
@ -0,0 +1,203 @@
|
|||
import { EventEmitter, Injectable } from '@angular/core';
|
||||
import { DaemonService } from './daemon.service';
|
||||
import { BlockCount, BlockHeader, DaemonInfo, SyncInfo } from '../../../../common';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DaemonDataService {
|
||||
|
||||
private refreshTimeoutMs: number = 5000;
|
||||
private refreshInterval?: NodeJS.Timeout;
|
||||
private _refreshing: boolean = false;
|
||||
private _firstRefresh: boolean = true;
|
||||
private _lastRefresh: number = Date.now();
|
||||
|
||||
private _daemonRunning: boolean = false;
|
||||
private _daemonRestarting: boolean = false;
|
||||
|
||||
private _daemonInfo?: DaemonInfo;
|
||||
private _gettingDaemonInfo: boolean = false;
|
||||
|
||||
private _syncInfo?: SyncInfo;
|
||||
private _gettingSyncInfo: boolean = false;
|
||||
|
||||
private _blockCount?: BlockCount;
|
||||
private _gettingBlockCount: boolean = false;
|
||||
|
||||
private _isBlockchainPruned: boolean = false;
|
||||
private _gettingIsBlockchainPruned: boolean = false;
|
||||
|
||||
private _lastBlockHeader?: BlockHeader;
|
||||
private _gettingLastBlockHeader: boolean = false;
|
||||
|
||||
public readonly syncStart: EventEmitter<void> = new EventEmitter<void>();
|
||||
public readonly syncEnd: EventEmitter<void> = new EventEmitter<void>();
|
||||
public readonly syncError: EventEmitter<Error> = new EventEmitter<Error>();
|
||||
|
||||
public readonly syncInfoRefreshStart: EventEmitter<void> = new EventEmitter<void>();
|
||||
public readonly syncInfoRefreshEnd: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
constructor(private daemonService: DaemonService) {
|
||||
this.startLoop();
|
||||
|
||||
this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => {
|
||||
if (running) {
|
||||
this.startLoop();
|
||||
}
|
||||
else {
|
||||
this.stopLoop();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public get initializing(): boolean {
|
||||
return this._firstRefresh;
|
||||
}
|
||||
|
||||
public get running(): boolean {
|
||||
return this._daemonRunning;
|
||||
}
|
||||
|
||||
public get starting(): boolean {
|
||||
return this.daemonService.starting;
|
||||
}
|
||||
|
||||
public get stopping(): boolean {
|
||||
return this.daemonService.stopping;
|
||||
}
|
||||
|
||||
public get restarting(): boolean {
|
||||
return this._daemonRestarting;
|
||||
}
|
||||
|
||||
public get refreshing(): boolean {
|
||||
return this._refreshing;
|
||||
}
|
||||
|
||||
public get info(): DaemonInfo | undefined {
|
||||
return this._daemonInfo;
|
||||
}
|
||||
|
||||
public get gettingInfo(): boolean {
|
||||
return this._gettingDaemonInfo;
|
||||
}
|
||||
|
||||
public get syncInfo(): SyncInfo | undefined {
|
||||
return this._syncInfo;
|
||||
}
|
||||
|
||||
public get gettingSyncInfo(): boolean {
|
||||
return this._gettingSyncInfo;
|
||||
}
|
||||
|
||||
public get blockCount(): BlockCount | undefined {
|
||||
return this._blockCount;
|
||||
}
|
||||
|
||||
public get gettingBlockCount(): boolean {
|
||||
return this._gettingBlockCount;
|
||||
}
|
||||
|
||||
public get isBlockchainPruned(): boolean {
|
||||
return this._isBlockchainPruned;
|
||||
}
|
||||
|
||||
public get gettingIsBlockchainPruned(): boolean {
|
||||
return this._gettingIsBlockchainPruned;
|
||||
}
|
||||
|
||||
public get lastBlockHeader(): BlockHeader | undefined {
|
||||
return this._lastBlockHeader;
|
||||
}
|
||||
|
||||
public get gettingLastBlockHeader(): boolean {
|
||||
return this._gettingLastBlockHeader;
|
||||
}
|
||||
|
||||
public setRefreshTimeout(ms: number = 5000): void {
|
||||
this.refreshTimeoutMs = ms;
|
||||
}
|
||||
|
||||
private startLoop(): void {
|
||||
if (this.refreshInterval != undefined) {
|
||||
throw new Error("Loop already started");
|
||||
}
|
||||
this._firstRefresh = true;
|
||||
this.refreshInterval = setInterval(() => {
|
||||
this.refresh();
|
||||
},this.refreshTimeoutMs);
|
||||
}
|
||||
|
||||
private stopLoop(): void {
|
||||
if (this.refreshInterval == undefined) {
|
||||
throw new Error("Loop already stopped");
|
||||
}
|
||||
|
||||
clearInterval(this.refreshInterval);
|
||||
|
||||
this.refreshInterval = undefined;
|
||||
this._refreshing = false;
|
||||
}
|
||||
|
||||
private get tooEarlyForRefresh(): boolean {
|
||||
return Date.now() - this._lastRefresh <= this.refreshTimeoutMs;
|
||||
}
|
||||
|
||||
private async refresh(): Promise<void> {
|
||||
if (this.refreshing || this.tooEarlyForRefresh) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._refreshing = true;
|
||||
this.syncStart.emit();
|
||||
|
||||
try {
|
||||
const firstRefresh = this._firstRefresh;
|
||||
this._daemonRunning = await this.daemonService.isRunning();
|
||||
this._firstRefresh = false;
|
||||
|
||||
this._gettingDaemonInfo = true;
|
||||
this._daemonInfo = await this.daemonService.getInfo();
|
||||
this._gettingDaemonInfo = false;
|
||||
|
||||
this._gettingSyncInfo = true;
|
||||
this.syncInfoRefreshStart.emit();
|
||||
this._syncInfo = await this.daemonService.syncInfo();
|
||||
this._gettingSyncInfo = false;
|
||||
this.syncInfoRefreshEnd.emit();
|
||||
|
||||
this._gettingBlockCount = true;
|
||||
this._blockCount = await this.daemonService.getBlockCount();
|
||||
this._gettingBlockCount = false;
|
||||
|
||||
this._gettingLastBlockHeader = true;
|
||||
this._lastBlockHeader = await this.daemonService.getLastBlockHeader(true);
|
||||
this._gettingLastBlockHeader = false;
|
||||
|
||||
this._gettingIsBlockchainPruned = true;
|
||||
if (firstRefresh) this._isBlockchainPruned = (await this.daemonService.pruneBlockchain(true)).pruned;
|
||||
this._gettingIsBlockchainPruned = false;
|
||||
|
||||
this._lastRefresh = Date.now();
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
this._gettingDaemonInfo = false;
|
||||
this._gettingSyncInfo = false;
|
||||
this._gettingBlockCount = false;
|
||||
this._gettingLastBlockHeader = false;
|
||||
this._gettingIsBlockchainPruned = false;
|
||||
|
||||
this.syncError.emit(<Error>error);
|
||||
|
||||
if (!await this.daemonService.isRunning()) {
|
||||
this.stopLoop();
|
||||
}
|
||||
}
|
||||
|
||||
this.syncEnd.emit();
|
||||
this._firstRefresh = false;
|
||||
this._refreshing = false;
|
||||
}
|
||||
|
||||
}
|
|
@ -256,13 +256,6 @@ export class DaemonService {
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!this.electronService.isElectron) {
|
||||
console.error("Could not start monero daemon: not electron app");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
this.starting = true;
|
||||
|
||||
console.log("Starting daemon");
|
||||
|
@ -270,7 +263,7 @@ export class DaemonService {
|
|||
|
||||
if (this.electronService.ipcRenderer) this.electronService.ipcRenderer.send('start-monerod', settings.toCommandOptions());
|
||||
else {
|
||||
const wdw = (window as any).electronAPI.startMonerod(settings.toCommandOptions());
|
||||
(window as any).electronAPI.startMonerod(settings.toCommandOptions());
|
||||
}
|
||||
|
||||
await this.delay(3000);
|
||||
|
@ -546,17 +539,29 @@ export class DaemonService {
|
|||
}
|
||||
else if (dontUseRpc) {
|
||||
const monerodPath: string = ''; // TO DO get local monerod path
|
||||
const wdw = (window as any);
|
||||
|
||||
return new Promise<DaemonVersion>((resolve, reject) => {
|
||||
this.electronService.ipcRenderer.on('on-monerod-version', (event, version: string) => {
|
||||
resolve(DaemonVersion.parse(version));
|
||||
});
|
||||
if (this.electronService.isElectron) {
|
||||
this.electronService.ipcRenderer.on('on-monerod-version', (event, version: string) => {
|
||||
resolve(DaemonVersion.parse(version));
|
||||
});
|
||||
|
||||
this.electronService.ipcRenderer.on('on-monerod-version-error', (event, version: string) => {
|
||||
reject(version);
|
||||
});
|
||||
this.electronService.ipcRenderer.on('on-monerod-version-error', (event, version: string) => {
|
||||
reject(version);
|
||||
});
|
||||
|
||||
this.electronService.ipcRenderer.send('get-monerod-version', monerodPath);
|
||||
this.electronService.ipcRenderer.send('get-monerod-version', monerodPath);
|
||||
}
|
||||
else if (wdw.electronAPI && wdw.electronAPI.getMoneroVersion) {
|
||||
wdw.electronAPI.onMoneroVersion((event: any, version: string) => {
|
||||
resolve(DaemonVersion.parse(version));
|
||||
})
|
||||
wdw.electronAPI.onMoneroVersionError((event: any, error: string) => {
|
||||
reject(error);
|
||||
});
|
||||
wdw.electronAPI.getMoneroVersion();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from './electron/electron.service';
|
||||
export * from './daemon/daemon.service';
|
||||
export * from './daemon/daemon-data.service';
|
||||
export { MoneroInstallerService } from './monero-installer/monero-installer.service';
|
||||
|
|
|
@ -17,19 +17,6 @@
|
|||
<div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab" tabindex="0">
|
||||
<div class="row d-flex justify-content-center">
|
||||
|
||||
<div *ngIf="daemonRunning" class="card text-bg-dark m-3 text-center" style="max-width: 18rem;">
|
||||
<div class="card-header"><strong>Daemon running</strong></div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<button *ngIf="!stoppingDaemon" type="button" class="btn btn-danger btn-lg" (click)="stopDaemon()"><i class="bi bi-stop-circle"></i> Stop</button>
|
||||
<button *ngIf="stoppingDaemon" class="btn btn-danger-light" type="button" disabled>
|
||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
Stopping daemon
|
||||
</button>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@for(card of cards; track card.header) {
|
||||
@if(card.loading && !stoppingDaemon) {
|
||||
<div class="card text-bg-dark m-3 text-center" style="max-width: 18rem;" aria-hidden="true">
|
||||
|
@ -57,8 +44,6 @@
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="pills-profile" role="tabpanel" aria-labelledby="pills-profile-tab" tabindex="0">
|
||||
|
|
|
@ -1,81 +1,107 @@
|
|||
import { Component, OnInit, AfterViewInit, NgZone, OnDestroy } from '@angular/core';
|
||||
import { DaemonService } from '../../core/services/daemon/daemon.service';
|
||||
import { SyncInfo } from '../../../common/SyncInfo';
|
||||
import { Component, AfterViewInit, NgZone } from '@angular/core';
|
||||
import { Peer } from '../../../common/Peer';
|
||||
import { NavbarLink } from '../../shared/components/navbar/navbar.model';
|
||||
import { NavbarService } from '../../shared/components/navbar/navbar.service';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { DaemonInfo } from '../../../common/DaemonInfo';
|
||||
|
||||
|
||||
import { LogsService } from '../logs/logs.service';
|
||||
import { ElectronService } from '../../core/services';
|
||||
import { DaemonService, DaemonDataService } from '../../core/services';
|
||||
|
||||
@Component({
|
||||
selector: 'app-detail',
|
||||
templateUrl: './detail.component.html',
|
||||
styleUrls: ['./detail.component.scss']
|
||||
})
|
||||
export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
export class DetailComponent implements AfterViewInit {
|
||||
|
||||
public daemonRunning: boolean;
|
||||
public startingDaemon: boolean;
|
||||
public stoppingDaemon: boolean;
|
||||
private syncInfo?: SyncInfo;
|
||||
private daemonInfo?: DaemonInfo;
|
||||
public readonly navbarLinks: NavbarLink[];
|
||||
|
||||
private syncStatus: string;
|
||||
private height: number;
|
||||
private targetHeight: number;
|
||||
private nextNeededPruningSeed: number;
|
||||
private overview: string;
|
||||
private blockCount: number;
|
||||
private version: string;
|
||||
|
||||
private blockchainSize: string;
|
||||
private diskUsage: string;
|
||||
private networkType: string;
|
||||
private connectionStatus: string;
|
||||
private txCount: number;
|
||||
private poolSize: number;
|
||||
private nodeType: string;
|
||||
private syncProgress: string;
|
||||
|
||||
private isLoading: boolean;
|
||||
|
||||
private loadInterval?: any;
|
||||
|
||||
public get loading(): boolean {
|
||||
return this.isLoading;
|
||||
public get daemonRunning(): boolean {
|
||||
return this.daemonData.running;
|
||||
}
|
||||
|
||||
public get startingDaemon(): boolean {
|
||||
return this.daemonData.starting;
|
||||
}
|
||||
|
||||
public get stoppingDaemon(): boolean {
|
||||
return this.daemonData.stopping;
|
||||
}
|
||||
|
||||
public readonly navbarLinks: NavbarLink[];
|
||||
|
||||
//private get syncStatus: string;
|
||||
|
||||
//#region Sync Info
|
||||
|
||||
private get height(): number {
|
||||
return this.daemonData.syncInfo ? this.daemonData.syncInfo.height : 0;
|
||||
}
|
||||
|
||||
private get targetHeight(): number {
|
||||
return this.daemonData.syncInfo ? this.daemonData.syncInfo.targetHeight : 0;
|
||||
}
|
||||
|
||||
private get nextNeededPruningSeed(): number {
|
||||
return this.daemonData.syncInfo ? this.daemonData.syncInfo.nextNeededPruningSeed : 0;
|
||||
}
|
||||
|
||||
private get overview(): string {
|
||||
return this.daemonData.syncInfo ? this.daemonData.syncInfo.overview : '[]';
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
private get blockCount(): number {
|
||||
return this.daemonData.blockCount ? this.daemonData.blockCount.count : 0;
|
||||
}
|
||||
|
||||
//#region Daemon Info
|
||||
|
||||
private get version(): string {
|
||||
return this.daemonData.info ? this.daemonData.info.version : 'Unknown';
|
||||
}
|
||||
|
||||
private get blockchainSize(): number {
|
||||
return this.daemonData.info ? parseFloat((this.daemonData.info.databaseSize / 1000 / 1000 / 1000).toFixed(2)) : 0;
|
||||
}
|
||||
|
||||
private get capacity(): number {
|
||||
return this.daemonData.info ? this.daemonData.info.freeSpace + this.daemonData.info.databaseSize : 0;
|
||||
}
|
||||
|
||||
private get diskUsage(): number {
|
||||
return this.daemonData.info ? parseFloat((this.daemonData.info.databaseSize * 100 / this.capacity).toFixed(2)) : 0;
|
||||
}
|
||||
|
||||
private get networkType(): string {
|
||||
return this.daemonData.info ? this.daemonData.info.nettype : 'unknown';
|
||||
}
|
||||
|
||||
private get connectionStatus(): string {
|
||||
return this.daemonData.info ? this.daemonData.info.offline ? 'offline' : 'online' : 'offline';
|
||||
}
|
||||
|
||||
private get txCount(): number {
|
||||
return this.daemonData.info ? this.daemonData.info.txCount : 0;
|
||||
}
|
||||
|
||||
private get poolSize(): number {
|
||||
return this.daemonData.info ? this.daemonData.info.txPoolSize : 0;
|
||||
}
|
||||
|
||||
private get nodeType(): string {
|
||||
return this.daemonData.isBlockchainPruned ? 'pruned' : 'full';
|
||||
}
|
||||
|
||||
private get syncProgress(): string {
|
||||
return `${(this.height*100/this.targetHeight).toFixed(2)} %`;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
public cards: Card[];
|
||||
public firstLoading: boolean = true;
|
||||
|
||||
constructor(
|
||||
private router: Router,private daemonService: DaemonService,
|
||||
private navbarService: NavbarService, private logsService: LogsService,
|
||||
private ngZone: NgZone, private electronService: ElectronService) {
|
||||
this.daemonRunning = false;
|
||||
this.startingDaemon = false;
|
||||
this.stoppingDaemon = false;
|
||||
this.syncStatus = 'Not synced';
|
||||
this.height = 0;
|
||||
this.targetHeight = 0;
|
||||
this.nextNeededPruningSeed = 0;
|
||||
this.overview = '';
|
||||
this.blockCount = 0;
|
||||
this.version = '';
|
||||
this.diskUsage = '0 %';
|
||||
this.networkType = '';
|
||||
this.connectionStatus = 'offline';
|
||||
this.txCount = 0;
|
||||
this.poolSize = 0;
|
||||
this.nodeType = 'unknown';
|
||||
this.blockchainSize = '0 GB';
|
||||
this.syncProgress = '0 %';
|
||||
this.isLoading = false;
|
||||
private daemonService: DaemonService,
|
||||
private navbarService: NavbarService,
|
||||
private daemonData: DaemonDataService,
|
||||
private ngZone: NgZone) {
|
||||
|
||||
this.navbarLinks = [
|
||||
new NavbarLink('pills-home-tab', '#pills-home', 'pills-home', true, 'Overview', true),
|
||||
|
@ -83,135 +109,40 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
new NavbarLink('pills-spans-tab', '#pills-spans', 'pills-spans', false, 'Spans', true)
|
||||
];
|
||||
|
||||
this.cards = this.createLoadingCards();
|
||||
this.cards = this.createCards();
|
||||
|
||||
this.router.events.subscribe((event) => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
if (event.url != '/detail') return;
|
||||
//this.onNavigationEnd();
|
||||
this.daemonData.syncInfoRefreshEnd.subscribe(() => {
|
||||
const $table = $('#table');
|
||||
//$table.bootstrapTable({});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
if (this.getPeers().length == 0) $table.bootstrapTable('showLoading');
|
||||
else
|
||||
{
|
||||
$table.bootstrapTable('load', this.getPeers());
|
||||
$table.bootstrapTable('hideLoading');
|
||||
}
|
||||
});
|
||||
|
||||
this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => {
|
||||
this.ngZone.run(() => {
|
||||
this.daemonRunning = running;
|
||||
if (!running && this.stoppingDaemon) {
|
||||
this.stoppingDaemon = false;
|
||||
}
|
||||
})
|
||||
});
|
||||
this.cards = this.createCards();
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
console.log('DetailComponent INIT');
|
||||
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
console.log('DetailComponent AFTER VIEW INIT');
|
||||
this.navbarService.setLinks(this.navbarLinks);
|
||||
setTimeout(() => {
|
||||
this.ngZone.run(() => {
|
||||
|
||||
const $table = $('#table');
|
||||
$table.bootstrapTable({});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
$table.bootstrapTable('showLoading');
|
||||
/*
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
*/
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
|
||||
if (this.loadInterval != null) return;
|
||||
|
||||
this.ngZone.run(() => {
|
||||
this.load().then(() => {
|
||||
this.cards = this.createCards();
|
||||
});
|
||||
});
|
||||
|
||||
this.loadInterval = setInterval(() => {
|
||||
/*
|
||||
const $table = $('#table');
|
||||
$table.bootstrapTable({});
|
||||
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
*/
|
||||
if (this.stoppingDaemon) return;
|
||||
|
||||
this.ngZone.run(() => {
|
||||
$table.bootstrapTable('showLoading');
|
||||
|
||||
this.load().then(() => {
|
||||
this.cards = this.createCards();
|
||||
});
|
||||
}, 5000);
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
console.log("DetailComponent ON DESTROY");
|
||||
|
||||
if(this.loadInterval != null) {
|
||||
clearInterval(this.loadInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public async startDaemon(): Promise<void> {
|
||||
if (this.daemonRunning) {
|
||||
console.warn("Daemon already running");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.startingDaemon || this.stoppingDaemon) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.startingDaemon = true;
|
||||
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
await this.daemonService.startDaemon();
|
||||
this.daemonRunning = await this.daemonService.isRunning();
|
||||
}
|
||||
catch(error) {
|
||||
console.error(error);
|
||||
this.daemonRunning = false;
|
||||
}
|
||||
|
||||
this.cards = this.createLoadingCards();
|
||||
|
||||
this.startingDaemon = false;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
public async stopDaemon(): Promise<void> {
|
||||
if (this.stoppingDaemon || this.startingDaemon || !this.daemonRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.stoppingDaemon = true;
|
||||
|
||||
try {
|
||||
if (this.loadInterval) clearInterval(this.loadInterval);
|
||||
|
||||
await this.daemonService.stopDaemon();
|
||||
|
||||
if(!this.electronService.isElectron) this.daemonRunning = false;
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if(!this.electronService.isElectron) this.stoppingDaemon = false;
|
||||
});
|
||||
}
|
||||
|
||||
private createLoadingCards(): Card[] {
|
||||
|
@ -224,8 +155,8 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
new Card('Next needed pruning seed', `${this.nextNeededPruningSeed}`, true),
|
||||
new Card('Block count', `${this.blockCount}`, true),
|
||||
new Card('Monero version', this.version, true),
|
||||
new Card('Blockchain size', this.blockchainSize, true),
|
||||
new Card('Disk usage', this.diskUsage, true),
|
||||
new Card('Blockchain size', `${this.blockchainSize} GB`, true),
|
||||
new Card('Disk usage', `${this.diskUsage} %`, true),
|
||||
new Card('Transaction count', `${this.txCount}`, true),
|
||||
new Card('Pool size', `${this.poolSize}`, true)
|
||||
];
|
||||
|
@ -235,7 +166,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
if (!this.daemonRunning && !this.daemonService.starting) {
|
||||
return [];
|
||||
}
|
||||
if (this.firstLoading || this.daemonService.starting) {
|
||||
if (this.daemonData.initializing || this.daemonService.starting) {
|
||||
return this.createLoadingCards();
|
||||
}
|
||||
return [
|
||||
|
@ -247,102 +178,19 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
new Card('Next needed pruning seed', `${this.nextNeededPruningSeed}`),
|
||||
new Card('Block count', `${this.blockCount}`),
|
||||
new Card('Monero version', this.version),
|
||||
new Card('Blockchain size', this.blockchainSize),
|
||||
new Card('Disk usage', this.diskUsage),
|
||||
new Card('Blockchain size', `${this.blockchainSize} GB`),
|
||||
new Card('Disk usage', `${this.diskUsage} %`),
|
||||
new Card('Transaction count', `${this.txCount}`),
|
||||
new Card('Pool size', `${this.poolSize}`)
|
||||
];
|
||||
}
|
||||
|
||||
private async load(): Promise<void> {
|
||||
if (this.isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.isLoading = true;
|
||||
this.daemonRunning = await this.daemonService.isRunning();
|
||||
|
||||
if (!this.daemonRunning) {
|
||||
this.navbarService.disableLinks();
|
||||
this.isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.navbarService.enableLinks();
|
||||
|
||||
const $table = $('#table');
|
||||
$table.bootstrapTable({});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
if (this.getPeers().length == 0) $table.bootstrapTable('showLoading');
|
||||
|
||||
this.syncInfo = await this.daemonService.syncInfo();
|
||||
this.height = this.syncInfo.height;
|
||||
this.targetHeight = this.syncInfo.targetHeight;
|
||||
this.nextNeededPruningSeed = this.syncInfo.nextNeededPruningSeed;
|
||||
|
||||
if (this.height > 0 && this.targetHeight == 0) {
|
||||
this.targetHeight = this.height;
|
||||
this.syncStatus = 'Daemon synced';
|
||||
}
|
||||
else if (this.height > 0 && this.targetHeight > 0 && this.height == this.targetHeight) {
|
||||
this.syncStatus = 'Daemon synced';
|
||||
}
|
||||
|
||||
this.overview = this.syncInfo.overview;
|
||||
|
||||
const blockCount = await this.daemonService.getBlockCount();
|
||||
|
||||
this.blockCount = blockCount.count;
|
||||
|
||||
//const version = await this.daemonService.getVersion();
|
||||
|
||||
//this.version = `${version.version}`;
|
||||
|
||||
this.daemonInfo = await this.daemonService.getInfo();
|
||||
|
||||
const capacity: number = this.daemonInfo.freeSpace + this.daemonInfo.databaseSize;
|
||||
const diskUsage = parseInt(`${this.daemonInfo.databaseSize * 100 / capacity}`);
|
||||
const blockchainSize = (this.daemonInfo.databaseSize / 1000 / 1000 / 1000).toFixed(2);
|
||||
this.blockchainSize = `${blockchainSize} GB`;
|
||||
this.diskUsage = `${diskUsage} %`;
|
||||
this.networkType = this.daemonInfo.nettype;
|
||||
this.connectionStatus = this.daemonInfo.offline ? 'offline' : 'online';
|
||||
this.txCount = this.daemonInfo.txCount;
|
||||
this.poolSize = this.daemonInfo.txPoolSize;
|
||||
this.version = this.daemonInfo.version;
|
||||
this.syncProgress = `${(this.height*100/this.targetHeight).toFixed(2)} %`;
|
||||
|
||||
const blockchainPruned = await this.isBlockchainPruned();
|
||||
//const blockchainPruned = false;
|
||||
this.nodeType = blockchainPruned ? 'pruned' : 'full';
|
||||
$table.bootstrapTable('load', this.getPeers());
|
||||
$table.bootstrapTable('hideLoading');
|
||||
|
||||
}
|
||||
catch(error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
this.firstLoading = false;
|
||||
|
||||
}
|
||||
|
||||
public async isBlockchainPruned(): Promise<boolean> {
|
||||
const result = await this.daemonService.pruneBlockchain(true);
|
||||
|
||||
return result.pruned;
|
||||
}
|
||||
|
||||
public getPeers(): any[] {
|
||||
if (!this.syncInfo) return [];
|
||||
if (!this.daemonData.syncInfo) return [];
|
||||
|
||||
const peers: any[] = [];
|
||||
|
||||
this.syncInfo.peers.forEach((peer: Peer) => peers.push({
|
||||
this.daemonData.syncInfo.peers.forEach((peer: Peer) => peers.push({
|
||||
'address': peer.info.address,
|
||||
'peerId': peer.info.peerId,
|
||||
'height': peer.info.height,
|
||||
|
|
|
@ -56,7 +56,8 @@ export class VersionComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
public async load(): Promise<void> {
|
||||
const version = await this.daemonService.getVersion(this.electronService.isElectron);
|
||||
const isElectron = this.electronService.isElectron || (window as any).electronAPI != null;
|
||||
const version = await this.daemonService.getVersion(isElectron);
|
||||
const latestVersion = await this.daemonService.getLatestVersion();
|
||||
|
||||
this.currentVersion = version;
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { NavbarLink } from './navbar.model';
|
||||
import { DaemonService } from '../../../core/services';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class NavbarService {
|
||||
private _navbarLinks: NavbarLink[] = [];
|
||||
private daemonRunning: boolean = false;
|
||||
|
||||
public get links(): NavbarLink[] {
|
||||
return this._navbarLinks;
|
||||
}
|
||||
|
||||
constructor() { }
|
||||
constructor(private daemonService: DaemonService) {
|
||||
this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => {
|
||||
this.daemonRunning = running;
|
||||
if (!running) this.disableLinks();
|
||||
if (running) this.enableLinks();
|
||||
})
|
||||
}
|
||||
|
||||
public addLink(... navbarLinks: NavbarLink[]): void {
|
||||
navbarLinks.forEach((navLink: NavbarLink) => this._navbarLinks.push(navLink));
|
||||
|
@ -19,6 +27,9 @@ export class NavbarService {
|
|||
|
||||
public setLinks(navbarLinks: NavbarLink[]): void {
|
||||
this._navbarLinks = navbarLinks;
|
||||
|
||||
if (this.daemonRunning) this.enableLinks();
|
||||
else this.disableLinks();
|
||||
}
|
||||
|
||||
public removeLinks(): void {
|
||||
|
|
Loading…
Reference in a new issue