Outputs methods implementation and navbar daemon methods implementation

This commit is contained in:
everoddandeven 2024-10-01 17:23:22 +02:00
parent 3ca4c45923
commit b0060fde8a
9 changed files with 183 additions and 8 deletions

View file

@ -33,7 +33,7 @@ function createWindow(): BrowserWindow {
webPreferences: { webPreferences: {
preload: path.join(__dirname, 'preload.js'), preload: path.join(__dirname, 'preload.js'),
nodeIntegration: false, nodeIntegration: false,
allowRunningInsecureContent: true, allowRunningInsecureContent: (serve),
contextIsolation: true, contextIsolation: true,
devTools: true devTools: true
}, },

View file

@ -709,6 +709,14 @@ export class DaemonService {
console.warn("Daemon not running"); console.warn("Daemon not running");
return; return;
} }
if (this.stopping) {
console.warn("Daemon already stopping");
return;
}
if (this.starting) {
console.warn("Daemon is starting");
return;
}
this.stopping = true; this.stopping = true;
this.onDaemonStopStart.emit(); this.onDaemonStopStart.emit();

View file

@ -51,6 +51,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
} }
public cards: Card[]; public cards: Card[];
public firstLoading: boolean = true;
constructor( constructor(
private router: Router,private daemonService: DaemonService, private router: Router,private daemonService: DaemonService,
@ -234,7 +235,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
if (!this.daemonRunning && !this.daemonService.starting) { if (!this.daemonRunning && !this.daemonService.starting) {
return []; return [];
} }
if (this.isLoading || this.daemonService.starting) { if (this.firstLoading || this.daemonService.starting) {
return this.createLoadingCards(); return this.createLoadingCards();
} }
return [ return [
@ -326,6 +327,8 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
} }
this.isLoading = false; this.isLoading = false;
this.firstLoading = false;
} }
public async isBlockchainPruned(): Promise<boolean> { public async isBlockchainPruned(): Promise<boolean> {

View file

@ -10,6 +10,60 @@
</ul> </ul>
</div> </div>
</div> </div>
<div *ngIf="daemonRunning" class="tab-content" id="pills-tabContent">
<div class="tab-pane fade show active" id="pills-outputs-overview" role="tabpanel" aria-labelledby="pills-outputs-overview-tab" tabindex="0">
<table
[hidden]="getOutsOuts.length == 0"
id="outsTable"
data-toggle="outsTable"
data-toolbar="#toolbar"
data-height="460"
>
<thead>
<tr>
<th data-field="height">Height</th>
<th data-field="key">Key</th>
<th data-field="mask">Mask</th>
<th data-field="txId">Tx ID</th>
<th data-field="unlocked">Unlocked</th>
</tr>
</thead>
</table>
</div>
<div class="tab-pane fade" id="pills-is-key-image-spent" role="tabpanel" aria-labelledby="pills-is-key-image-spent-tab" tabindex="0">
<div *ngIf="isKeyImageSpentError != ''" class="alert alert-danger d-flex align-items-center justify-content-center text-center" role="alert">
<h4><i class="bi bi-exclamation-triangle m-2"></i></h4>&nbsp;&nbsp;
<div>
{{ isKeyImageSpentError }}
</div>
</div>
<div class="row g-5 p-2">
<div class="cold-md-7 col-lg-12">
<div class="row gy-3">
<h4 class="mb-3">Check if outputs have been spent using the key image associated with the output</h4>
<div class="col-sm-12">
<label for="key-images" class="form-label">Key images</label>
<textarea [(ngModel)]="keyImages" [ngModelOptions]="{standalone: true}" type="text" class="form-control" id="key-images" placeholder=""
rows="15" cols="15" ></textarea>
<div class="invalid-feedback">
Invalid key images.
</div>
</div>
</div>
</div>
<hr class="my-4">
<button *ngIf="!gettingKeyImages" class="w-100 btn btn-primary btn-lg" type="button" (click)="isKeyImageSpent()">Is Key Image Spent</button>
<button *ngIf="gettingKeyImages" class="w-100 btn btn-primary btn-lg" type="button" disabled>Checking Key Images ...</button>
</div>
</div>
</div>
<app-daemon-not-running></app-daemon-not-running> <app-daemon-not-running></app-daemon-not-running>
<app-daemon-stopping></app-daemon-stopping> <app-daemon-stopping></app-daemon-stopping>

View file

@ -1,7 +1,8 @@
import { AfterViewInit, Component } from '@angular/core'; import { AfterViewInit, Component, NgZone } from '@angular/core';
import { NavbarLink } from '../../shared/components/navbar/navbar.model'; import { NavbarLink } from '../../shared/components/navbar/navbar.model';
import { DaemonService } from '../../core/services/daemon/daemon.service'; import { DaemonService } from '../../core/services/daemon/daemon.service';
import { NavbarService } from '../../shared/components/navbar/navbar.service'; import { NavbarService } from '../../shared/components/navbar/navbar.service';
import { Output } from '../../../common';
@Component({ @Component({
selector: 'app-outputs', selector: 'app-outputs',
@ -11,16 +12,92 @@ import { NavbarService } from '../../shared/components/navbar/navbar.service';
export class OutputsComponent implements AfterViewInit { export class OutputsComponent implements AfterViewInit {
public readonly navbarLinks: NavbarLink[]; public readonly navbarLinks: NavbarLink[];
constructor(private daemonService: DaemonService, private navbarService: NavbarService) { public daemonRunning: boolean = false;
public getOutsJsonString: string = '';
public getOutsGetTxId: boolean = false;
public keyImages: string = '';
public isKeyImageSpentError: string = '';
public isKeyImageSpentResult?: boolean;
public gettingKeyImages: boolean = false;
constructor(private daemonService: DaemonService, private navbarService: NavbarService, private ngZone: NgZone) {
this.navbarLinks = [ this.navbarLinks = [
new NavbarLink('pills-outputs-overview-tab', '#pills-outputs-overview', 'outputs-overview', true, 'Overview'), new NavbarLink('pills-outputs-overview-tab', '#pills-outputs-overview', 'outputs-overview', true, 'Overview'),
new NavbarLink('pills-outputs-histogram-tab', '#pills-outputs-histogram', 'outputs-histogram', false, 'Histogram'), new NavbarLink('pills-outputs-histogram-tab', '#pills-outputs-histogram', 'outputs-histogram', false, 'Histogram'),
new NavbarLink('pills-outputs-distribution-tab', '#pills-outputs-distribution', 'outputs-distribution', false, 'Distribution'), new NavbarLink('pills-outputs-distribution-tab', '#pills-outputs-distribution', 'outputs-distribution', false, 'Distribution'),
new NavbarLink('pills-is-key-image-spent-tab', '#pills-is-key-image-spent', 'is-key-image-spent', false, 'Is Key Image Spent') new NavbarLink('pills-is-key-image-spent-tab', '#pills-is-key-image-spent', 'is-key-image-spent', false, 'Is Key Image Spent')
]; ];
this.daemonService.isRunning().then((value) => {
this.daemonRunning = value;
})
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {
this.navbarService.setLinks(this.navbarLinks); this.navbarService.setLinks(this.navbarLinks);
this.ngZone.run(() => {
//const $ = require('jquery');
//const bootstrapTable = require('bootstrap-table');
const $table = $('#outsTable');
$table.bootstrapTable({
});
$table.bootstrapTable('refreshOptions', {
classes: 'table table-bordered table-hover table-dark table-striped'
});
$table.bootstrapTable('showLoading');
this.load();
});
}
public get getOutsOuts() {
try {
const _outs: any[] = JSON.parse(this.getOutsJsonString);
const outs: Output[] = [];
_outs.forEach((_out) => outs.push(Output.parse(_out)));
return outs;
}
catch(error) {
return []
}
}
public validOuts(): boolean {
try {
const _outs: any[] = JSON.parse(this.getOutsJsonString);
if (!Array.isArray(_outs)) {
return false;
}
_outs.forEach((_out) => Output.parse(_out));
return true;
} catch(error) {
return false;
}
}
public async getOuts() {
const $table = $('#outsTable');
$table.bootstrapTable({});
const outs = await this.daemonService.getOuts(this.getOutsOuts, this.getOutsGetTxId);
$table.bootstrapTable('load', outs)
}
public async isKeyImageSpent(): Promise<void> {
}
public async load() {
await this.getOuts();
} }
} }

View file

@ -25,22 +25,22 @@
<ul class="navbar-nav flex-row"> <ul class="navbar-nav flex-row">
<li *ngIf="!running && !stopping && !starting" class="nav-item text-nowrap"> <li *ngIf="!running && !stopping && !starting" class="nav-item text-nowrap">
<button class="nav-link px-3 text-white" type="button" data-bs-toggle="collapse" aria-expanded="false" aria-label="Start daemon"> <button class="nav-link px-3 text-white" type="button" data-bs-toggle="collapse" aria-expanded="false" aria-label="Start daemon" (click)="startDaemon()">
<i class="bi bi-play-fill"></i> <i class="bi bi-play-fill"></i>
</button> </button>
</li> </li>
<li *ngIf="running && !stopping && !starting" class="nav-item text-nowrap"> <li *ngIf="running && !stopping && !starting" class="nav-item text-nowrap">
<button class="nav-link px-3 text-white" type="button" data-bs-toggle="collapse" aria-expanded="false" aria-label="Stop daemon"> <button class="nav-link px-3 text-white" type="button" data-bs-toggle="collapse" aria-expanded="false" aria-label="Stop daemon" (click)="stopDaemon()">
<i class="bi bi-stop-fill"></i> <i class="bi bi-stop-fill"></i>
</button> </button>
</li> </li>
<li *ngIf="running && !stopping && !starting" class="nav-item text-nowrap"> <li *ngIf="running && !stopping && !starting" class="nav-item text-nowrap">
<button class="nav-link px-3 text-white" type="button" data-bs-toggle="collapse" aria-expanded="false" aria-label="Restart daemon"> <button class="nav-link px-3 text-white" type="button" data-bs-toggle="collapse" aria-expanded="false" aria-label="Restart daemon" (click)="restartDaemon()">
<i class="bi bi-arrow-clockwise"></i> <i class="bi bi-arrow-clockwise"></i>
</button> </button>
</li> </li>
<li class="nav-item text-nowrap"> <li class="nav-item text-nowrap">
<button class="nav-link px-3 text-white" type="button" data-bs-toggle="offcanvas" aria-label="Quit" [disabled]="stopping || starting"> <button class="nav-link px-3 text-white" type="button" data-bs-toggle="offcanvas" aria-label="Quit" [disabled]="stopping || starting" (click)="quit()">
<i class="bi bi-power"></i> <i class="bi bi-power"></i>
</button> </button>
</li> </li>

View file

@ -43,4 +43,30 @@ export class NavbarComponent {
}); });
} }
public async startDaemon(): Promise<void> {
try {
await this.daemonService.startDaemon();
} catch(error) {
console.error(error);
}
}
public async stopDaemon(): Promise<void> {
try {
await this.daemonService.stopDaemon();
} catch(error) {
console.error(error);
}
}
public async restartDaemon(): Promise<void> {
await this.stopDaemon();
await this.startDaemon();
}
public async quit(): Promise<void> {
}
} }

View file

@ -13,4 +13,8 @@ export class Output {
'index': this.index 'index': this.index
} }
} }
public static parse(out: any): Output {
return new Output(out.amount, out.index);
}
} }

View file

@ -9,6 +9,9 @@
<link rel="icon" type="image/x-icon" href="assets/icons/favicon.ico"> <link rel="icon" type="image/x-icon" href="assets/icons/favicon.ico">
</head> </head>
<body> <body>
<script>
const global = globalThis;
</script>
<app-root></app-root> <app-root></app-root>
</body> </body>
</html> </html>