mirror of
https://github.com/everoddandeven/monerod-gui.git
synced 2025-01-22 10:44:38 +00:00
Save settings to IndexDB and other fixes
This commit is contained in:
parent
bb694c5d7a
commit
5deb58f135
12 changed files with 278 additions and 86 deletions
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -20,6 +20,7 @@
|
||||||
"bootstrap": "5.3.3",
|
"bootstrap": "5.3.3",
|
||||||
"bootstrap-icons": "1.11.3",
|
"bootstrap-icons": "1.11.3",
|
||||||
"bootstrap-table": "1.23.2",
|
"bootstrap-table": "1.23.2",
|
||||||
|
"idb": "8.0.0",
|
||||||
"jquery": "3.7.1",
|
"jquery": "3.7.1",
|
||||||
"rxjs": "7.8.1",
|
"rxjs": "7.8.1",
|
||||||
"tslib": "2.6.2",
|
"tslib": "2.6.2",
|
||||||
|
@ -13593,6 +13594,11 @@
|
||||||
"postcss": "^8.1.0"
|
"postcss": "^8.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/idb": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/idb/-/idb-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw=="
|
||||||
|
},
|
||||||
"node_modules/ieee754": {
|
"node_modules/ieee754": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
"bootstrap": "5.3.3",
|
"bootstrap": "5.3.3",
|
||||||
"bootstrap-icons": "1.11.3",
|
"bootstrap-icons": "1.11.3",
|
||||||
"bootstrap-table": "1.23.2",
|
"bootstrap-table": "1.23.2",
|
||||||
|
"idb": "8.0.0",
|
||||||
"jquery": "3.7.1",
|
"jquery": "3.7.1",
|
||||||
"rxjs": "7.8.1",
|
"rxjs": "7.8.1",
|
||||||
"tslib": "2.6.2",
|
"tslib": "2.6.2",
|
||||||
|
|
|
@ -38,6 +38,21 @@ export class AppComponent {
|
||||||
private async load(): Promise<void> {
|
private async load(): Promise<void> {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
|
if (!window.indexedDB) {
|
||||||
|
console.log("Il tuo browser non supporta indexedDB");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("Browser supports IndexedDB");
|
||||||
|
var request = window.indexedDB.open("dati", 1);
|
||||||
|
console.log(request);
|
||||||
|
|
||||||
|
request.onsuccess = function(event: Event) {
|
||||||
|
if(event.target instanceof IDBOpenDBRequest) {
|
||||||
|
console.log(event.target.result)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.daemonRunning = await this.daemonService.isRunning();
|
this.daemonRunning = await this.daemonService.isRunning();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { EventEmitter, Injectable } from '@angular/core';
|
||||||
import { BlockCount } from '../../../../common/BlockCount';
|
import { BlockCount } from '../../../../common/BlockCount';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
|
@ -72,11 +72,17 @@ import { MiningStatus } from '../../../../common/MiningStatus';
|
||||||
import { TxInfo } from '../../../../common/TxInfo';
|
import { TxInfo } from '../../../../common/TxInfo';
|
||||||
import { DaemonSettings } from '../../../../common/DaemonSettings';
|
import { DaemonSettings } from '../../../../common/DaemonSettings';
|
||||||
import { MethodNotFoundError } from '../../../../common/error/MethodNotFoundError';
|
import { MethodNotFoundError } from '../../../../common/error/MethodNotFoundError';
|
||||||
|
import { openDB, IDBPDatabase } from "idb"
|
||||||
|
import { resolve } from 'path';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class DaemonService {
|
export class DaemonService {
|
||||||
|
private dbName = 'DaemonSettingsDB';
|
||||||
|
private storeName = 'settingsStore';
|
||||||
|
private openDbPromise: Promise<IDBPDatabase>;
|
||||||
|
|
||||||
private daemonRunning?: boolean;
|
private daemonRunning?: boolean;
|
||||||
private url: string = "http://127.0.0.1:28081";
|
private url: string = "http://127.0.0.1:28081";
|
||||||
public settings: DaemonSettings;
|
public settings: DaemonSettings;
|
||||||
|
@ -84,16 +90,58 @@ export class DaemonService {
|
||||||
//private url: string = "https://testnet.xmr.ditatompel.com";
|
//private url: string = "https://testnet.xmr.ditatompel.com";
|
||||||
//private url: string = "https://xmr.yemekyedim.com:18081";
|
//private url: string = "https://xmr.yemekyedim.com:18081";
|
||||||
//private url: string = "https://moneronode.org:18081";
|
//private url: string = "https://moneronode.org:18081";
|
||||||
|
|
||||||
|
public readonly onDaemonStart: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||||
|
|
||||||
private readonly headers: { [key: string]: string } = {
|
private readonly headers: { [key: string]: string } = {
|
||||||
"Access-Control-Allow-Headers": "*", // this will allow all CORS requests
|
"Access-Control-Allow-Headers": "*", // this will allow all CORS requests
|
||||||
"Access-Control-Allow-Methods": 'POST,GET' // this states the allowed methods
|
"Access-Control-Allow-Methods": 'POST,GET' // this states the allowed methods
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient, private electronService: ElectronService) {
|
constructor(private httpClient: HttpClient, private electronService: ElectronService) {
|
||||||
|
this.openDbPromise = this.openDatabase();
|
||||||
this.settings = this.loadSettings();
|
this.settings = this.loadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async openDatabase(): Promise<IDBPDatabase> {
|
||||||
|
return openDB(this.dbName, 1, {
|
||||||
|
upgrade(db) {
|
||||||
|
// Crea un archivio (store) per i settings se non esiste già
|
||||||
|
if (!db.objectStoreNames.contains('settingsStore')) {
|
||||||
|
db.createObjectStore('settingsStore', {
|
||||||
|
keyPath: 'id',
|
||||||
|
autoIncrement: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async saveSettings(settings: DaemonSettings): Promise<void> {
|
||||||
|
const db = await this.openDbPromise;
|
||||||
|
await db.put(this.storeName, { id: 1, ...settings });
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getSettings(): Promise<DaemonSettings> {
|
||||||
|
const db = await this.openDbPromise;
|
||||||
|
const result = await db.get(this.storeName, 1);
|
||||||
|
if (result) {
|
||||||
|
this.settings = DaemonSettings.parse(result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.settings = new DaemonSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deleteSettings(): Promise<void> {
|
||||||
|
const db = await this.openDbPromise;
|
||||||
|
await db.delete(this.storeName, 1);
|
||||||
|
}
|
||||||
|
|
||||||
private loadSettings(): DaemonSettings {
|
private loadSettings(): DaemonSettings {
|
||||||
/*
|
/*
|
||||||
const args = [
|
const args = [
|
||||||
|
@ -164,10 +212,20 @@ export class DaemonService {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Starting daemon");
|
console.log("Starting daemon");
|
||||||
|
const settings = await this.getSettings();
|
||||||
|
this.electronService.ipcRenderer.send('start-monerod', settings.toCommandOptions());
|
||||||
|
|
||||||
this.electronService.ipcRenderer.send('start-monerod', this.settings.toCommandOptions());
|
await new Promise(f => setTimeout(f, 3000));
|
||||||
|
|
||||||
console.log("Daemon started");
|
if (await this.isRunning(true)) {
|
||||||
|
console.log("Daemon started");
|
||||||
|
this.onDaemonStart.emit(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log("Daemon not started");
|
||||||
|
this.onDaemonStart.emit(false);
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
}, 500)
|
}, 500)
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
<app-load [show]="loading"></app-load>
|
<div class="tab-content" id="pills-tabContent">
|
||||||
|
|
||||||
<div class="tab-content" id="pills-tabContent" [hidden]="loading">
|
|
||||||
<div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab" tabindex="0">
|
<div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab" tabindex="0">
|
||||||
<div class="row d-flex">
|
<div class="row d-flex">
|
||||||
|
|
||||||
<div *ngIf="!daemonRunning" class="h-100 p-5 text-bg-dark rounded-3 m-4 text-center">
|
<div *ngIf="!daemonRunning && !loading" class="h-100 p-5 text-bg-dark rounded-3 m-4 text-center">
|
||||||
<h2><i class="bi bi-exclamation-diamond"></i> Daemon not running</h2>
|
<h2><i class="bi bi-exclamation-diamond"></i> Daemon not running</h2>
|
||||||
<p>Start monero daemon</p>
|
<p>Start monero daemon</p>
|
||||||
<button *ngIf="!startingDaemon" class="btn btn-outline-light" type="button" (click)="startDaemon()"><i class="bi bi-play-fill"></i> Start</button>
|
<button *ngIf="!startingDaemon" class="btn btn-outline-light" type="button" (click)="startDaemon()"><i class="bi bi-play-fill"></i> Start</button>
|
||||||
|
@ -15,12 +13,30 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@for(card of cards; track card.header) {
|
@for(card of cards; track card.header) {
|
||||||
<div class="card text-bg-dark m-3 text-center" style="max-width: 18rem;">
|
@if(card.loading) {
|
||||||
<div class="card-header"><strong>{{card.header}}</strong></div>
|
<div class="card text-bg-dark m-3 text-center" style="max-width: 18rem;" aria-hidden="true">
|
||||||
<div class="card-body">
|
<div class="card-header">{{card.header}}</div>
|
||||||
<h5 class="card-title">{{card.content}}</h5>
|
<div class="card-body">
|
||||||
|
|
||||||
|
<p class="card-text placeholder-glow">
|
||||||
|
<span class="placeholder col-7"></span>
|
||||||
|
<span class="placeholder col-4"></span>
|
||||||
|
<span class="placeholder col-4"></span>
|
||||||
|
<span class="placeholder col-6"></span>
|
||||||
|
<span class="placeholder col-8"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
|
@else {
|
||||||
|
<div class="card text-bg-dark m-3 text-center" style="max-width: 18rem;">
|
||||||
|
<div class="card-header"><strong>{{card.header}}</strong></div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">{{card.content}}</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,6 +7,9 @@ import { NavbarService } from '../../shared/components/navbar/navbar.service';
|
||||||
import { NavigationEnd, Router } from '@angular/router';
|
import { NavigationEnd, Router } from '@angular/router';
|
||||||
import { DaemonInfo } from '../../../common/DaemonInfo';
|
import { DaemonInfo } from '../../../common/DaemonInfo';
|
||||||
|
|
||||||
|
import * as $ from 'jquery';
|
||||||
|
import * as bootstrapTable from 'bootstrap-table';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-detail',
|
selector: 'app-detail',
|
||||||
templateUrl: './detail.component.html',
|
templateUrl: './detail.component.html',
|
||||||
|
@ -72,12 +75,12 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
new NavbarLink('pills-profile-tab', '#pills-profile', 'pills-profile', false, 'Peers', true)
|
new NavbarLink('pills-profile-tab', '#pills-profile', 'pills-profile', false, 'Peers', true)
|
||||||
];
|
];
|
||||||
|
|
||||||
this.cards = [];
|
this.cards = this.createLoadingCards();
|
||||||
|
|
||||||
this.router.events.subscribe((event) => {
|
this.router.events.subscribe((event) => {
|
||||||
if (event instanceof NavigationEnd) {
|
if (event instanceof NavigationEnd) {
|
||||||
if (event.url != '/detail') return;
|
if (event.url != '/detail') return;
|
||||||
this.onNavigationEnd();
|
//this.onNavigationEnd();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -89,21 +92,24 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
console.log('DetailComponent AFTER VIEW INIT');
|
console.log('DetailComponent AFTER VIEW INIT');
|
||||||
this.navbarService.setNavbarLinks(this.navbarLinks);
|
this.navbarService.setNavbarLinks(this.navbarLinks);
|
||||||
|
|
||||||
|
this.load().then(() => {
|
||||||
|
this.cards = this.createCards();
|
||||||
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
this.loadInterval = setInterval(() => {
|
||||||
this.ngZone.run(() => {
|
/*
|
||||||
if (this.isLoading) {
|
const $table = $('#table');
|
||||||
return;
|
$table.bootstrapTable({});
|
||||||
}
|
$table.bootstrapTable('refreshOptions', {
|
||||||
const $table = $('#table');
|
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||||
$table.bootstrapTable({});
|
|
||||||
$table.bootstrapTable('refreshOptions', {
|
|
||||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
|
||||||
});
|
|
||||||
this.load();
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}, 500);
|
*/
|
||||||
|
|
||||||
|
this.load().then(() => {
|
||||||
|
this.cards = this.createCards();
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -121,27 +127,50 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
}
|
}
|
||||||
this.startingDaemon = true;
|
this.startingDaemon = true;
|
||||||
|
|
||||||
try {
|
setTimeout(async () => {
|
||||||
await this.daemonService.startDaemon();
|
try {
|
||||||
this.daemonRunning = await this.daemonService.isRunning();
|
await this.daemonService.startDaemon();
|
||||||
}
|
this.daemonRunning = await this.daemonService.isRunning();
|
||||||
catch(error) {
|
}
|
||||||
console.error(error);
|
catch(error) {
|
||||||
}
|
console.error(error);
|
||||||
|
this.daemonRunning = false;
|
||||||
this.startingDaemon = false;
|
}
|
||||||
|
|
||||||
|
this.startingDaemon = false;
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onNavigationEnd(): void {
|
private onNavigationEnd(): void {
|
||||||
this.load().then(() => {
|
this.load().then(() => {
|
||||||
this.cards = this.createCards();
|
//this.cards = this.createCards();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createLoadingCards(): Card[] {
|
||||||
|
return [
|
||||||
|
new Card('Connection Status', this.connectionStatus, true),
|
||||||
|
new Card('Network Type', this.networkType, true),
|
||||||
|
new Card('Node Type', this.nodeType, true),
|
||||||
|
new Card('Sync progress', this.syncProgress, true),
|
||||||
|
new Card('Scan Height', `${this.height} / ${this.targetHeight}`, true),
|
||||||
|
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('Transaction count', `${this.txCount}`, true),
|
||||||
|
new Card('Pool size', `${this.poolSize}`, true)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
private createCards(): Card[] {
|
private createCards(): Card[] {
|
||||||
if (!this.daemonRunning) {
|
if (!this.daemonRunning) {
|
||||||
return []
|
return [];
|
||||||
|
}
|
||||||
|
if (this.isLoading) {
|
||||||
|
return this.createLoadingCards();
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
new Card('Connection Status', this.connectionStatus),
|
new Card('Connection Status', this.connectionStatus),
|
||||||
|
@ -193,9 +222,9 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
this.blockCount = blockCount.count;
|
this.blockCount = blockCount.count;
|
||||||
|
|
||||||
const version = await this.daemonService.getVersion();
|
//const version = await this.daemonService.getVersion();
|
||||||
|
|
||||||
this.version = `${version.version}`;
|
//this.version = `${version.version}`;
|
||||||
|
|
||||||
this.daemonInfo = await this.daemonService.getInfo();
|
this.daemonInfo = await this.daemonService.getInfo();
|
||||||
|
|
||||||
|
@ -211,8 +240,8 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
this.version = this.daemonInfo.version;
|
this.version = this.daemonInfo.version;
|
||||||
this.syncProgress = `${(this.height*100/this.targetHeight).toFixed(2)} %`;
|
this.syncProgress = `${(this.height*100/this.targetHeight).toFixed(2)} %`;
|
||||||
|
|
||||||
//const blockchainPruned = await this.isBlockchainPruned();
|
const blockchainPruned = await this.isBlockchainPruned();
|
||||||
const blockchainPruned = false;
|
//const blockchainPruned = false;
|
||||||
this.nodeType = blockchainPruned ? 'pruned' : 'full';
|
this.nodeType = blockchainPruned ? 'pruned' : 'full';
|
||||||
$table.bootstrapTable('load', this.getPeers());
|
$table.bootstrapTable('load', this.getPeers());
|
||||||
}
|
}
|
||||||
|
@ -251,9 +280,11 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
class Card {
|
class Card {
|
||||||
public header: string;
|
public header: string;
|
||||||
public content: string;
|
public content: string;
|
||||||
|
public loading: boolean;
|
||||||
|
|
||||||
constructor(header: string, content: string) {
|
constructor(header: string, content: string, loading: boolean = false) {
|
||||||
this.header = header;
|
this.header = header;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
|
this.loading = loading;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="tab-content" id="pills-settings-tabContent">
|
<div *ngIf="!loading" class="tab-content" id="pills-settings-tabContent">
|
||||||
<div class="tab-pane fade show active" id="pills-rpc" role="tabpanel" aria-labelledby="pills-rpc-tab" tabindex="0">
|
<div class="tab-pane fade show active" id="pills-rpc" role="tabpanel" aria-labelledby="pills-rpc-tab" tabindex="0">
|
||||||
<div class="row g-5 m-2">
|
<div class="row g-5 m-2">
|
||||||
<div class="col-md-7 col-lg-10">
|
<div class="col-md-7 col-lg-10">
|
||||||
|
@ -7,42 +7,42 @@
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="offline" class="form-check-label">Offline</label>
|
<label for="offline" class="form-check-label">Offline</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="offline" (change)="OnOfflineChange()">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="offline" [checked]="currentSettings.offline" (change)="OnOfflineChange()">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Do not listen for peers, nor connect to any</small>
|
<small class="text-body-secondary">Do not listen for peers, nor connect to any</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="public-node" class="form-check-label">Public node</label>
|
<label for="public-node" class="form-check-label">Public node</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="public-node" (change)="OnPublicNodeChange()">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="public-node" [checked]="currentSettings.publicNode" (change)="OnPublicNodeChange()">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Allow other users to use the node as a remote (restricted RPC mode, view-only commands) and advertise it over P2P</small>
|
<small class="text-body-secondary">Allow other users to use the node as a remote (restricted RPC mode, view-only commands) and advertise it over P2P</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="restricted-rpc" class="form-check-label">Restricted RPC</label>
|
<label for="restricted-rpc" class="form-check-label">Restricted RPC</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="restricted-rpc" (change)="OnRestrictedRPCChange()">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="restricted-rpc" [checked]="currentSettings.restrictedRpc" (change)="OnRestrictedRPCChange()">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Restrict RPC to view-only commands and do not return privacy sensitive data in RPC calls</small>
|
<small class="text-body-secondary">Restrict RPC to view-only commands and do not return privacy sensitive data in RPC calls</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="confirm-external-bind" class="form-check-label">Confirm external bind</label>
|
<label for="confirm-external-bind" class="form-check-label">Confirm external bind</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="confirm-external-bind" (change)="OnConfirmExternalBindChange()">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="confirm-external-bind" [checked]="currentSettings.confirmExternalBind" (change)="OnConfirmExternalBindChange()">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Confirm Bind IP is not a loopback (local) IP</small>
|
<small class="text-body-secondary">Confirm Bind IP is not a loopback (local) IP</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="rpc-ignore-ipv4" class="form-check-label">Ignore IPv4</label>
|
<label for="rpc-ignore-ipv4" class="form-check-label">Ignore IPv4</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-ignore-ipv4" (change)="OnIgnoreIPv4Change()">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-ignore-ipv4" [checked]="currentSettings.rpcIgnoreIpv4" (change)="OnIgnoreIPv4Change()">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Ignore unsuccessful IPv4 bind for RPC</small>
|
<small class="text-body-secondary">Ignore unsuccessful IPv4 bind for RPC</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="disable-rpc-ban" class="form-check-label">Disable ban</label>
|
<label for="disable-rpc-ban" class="form-check-label">Disable ban</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="disable-rpc-ban" (change)="OnDisableRpcBanChange()">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="disable-rpc-ban" [checked]="currentSettings.disableRpcBan" (change)="OnDisableRpcBanChange()">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Do not ban hosts on RPC errors</small>
|
<small class="text-body-secondary">Do not ban hosts on RPC errors</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-12">
|
<div class="form-check form-switch col-md-12">
|
||||||
<label for="rpc-use-ipv6" class="form-check-label">Enabled</label>
|
<label for="rpc-use-ipv6" class="form-check-label">Enabled</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-use-ipv6" [(ngModel)]="currentSettings.rpcUseIpv6" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-use-ipv6" [checked]="currentSettings.rpcUseIpv6" [(ngModel)]="currentSettings.rpcUseIpv6" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Allow IPv6 for RPC</small>
|
<small class="text-body-secondary">Allow IPv6 for RPC</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -161,7 +161,7 @@
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="rpc-payment-allow-free-loopback" class="form-check-label">Allow free loopback</label>
|
<label for="rpc-payment-allow-free-loopback" class="form-check-label">Allow free loopback</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-payment-allow-free-loopback" [(ngModel)]="currentSettings.rpcPaymentAllowFreeLoopback" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-payment-allow-free-loopback" [checked]="currentSettings.allowLocalIp" [(ngModel)]="currentSettings.rpcPaymentAllowFreeLoopback" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Allow free access from the loopback address (ie, the local host)</small>
|
<small class="text-body-secondary">Allow free access from the loopback address (ie, the local host)</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -176,23 +176,23 @@
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="rpc-ssl" class="form-label">SSL Mode</label>
|
<label for="rpc-ssl" class="form-label">SSL Mode</label>
|
||||||
<select class="form-select" id="rpc-ssl" [(ngModel)]="currentSettings.rpcSsl" [ngModelOptions]="{standalone: true}">
|
<select class="form-select" id="rpc-ssl" [(ngModel)]="currentSettings.rpcSsl" [ngModelOptions]="{standalone: true}">
|
||||||
<option [ngValue]="'autodetect'">Autodetect</option>
|
<option [ngValue]="'autodetect'" [selected]="currentSettings.rpcSsl == 'autodetect'">Autodetect</option>
|
||||||
<option [ngValue]="'enabled'">Enabled</option>
|
<option [ngValue]="'enabled'" [selected]="currentSettings.rpcSsl == 'enabled'">Enabled</option>
|
||||||
<option [ngValue]="'disabled'">Disabled</option>
|
<option [ngValue]="'disabled'" [selected]="currentSettings.rpcSsl == 'disabled'">Disabled</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-4">
|
<div class="form-check form-switch col-md-4">
|
||||||
<label for="rpc-ssl-allow-chained" class="form-check-label">Allow chained</label>
|
<label for="rpc-ssl-allow-chained" class="form-check-label">Allow chained</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-ssl-allow-chained" [(ngModel)]="currentSettings.rpcSslAllowChained" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-ssl-allow-chained" [checked]="currentSettings.rpcSslAllowChained" [(ngModel)]="currentSettings.rpcSslAllowChained" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Allow user chain certificates</small>
|
<small class="text-body-secondary">Allow user chain certificates</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-4">
|
<div class="form-check form-switch col-md-4">
|
||||||
<label for="rpc-ssl-allow-any-cert" class="form-check-label">Allow any cert</label>
|
<label for="rpc-ssl-allow-any-cert" class="form-check-label">Allow any cert</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-ssl-allow-any-cert" [(ngModel)]="currentSettings.rpcSslAllowAnyCert" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-ssl-allow-any-cert" [checked]="currentSettings.rpcSslAllowAnyCert" [(ngModel)]="currentSettings.rpcSslAllowAnyCert" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Allow any peer certificate</small>
|
<small class="text-body-secondary">Allow any peer certificate</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -229,14 +229,14 @@
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="allow-local-ip" class="form-check-label">Allow local IP</label>
|
<label for="allow-local-ip" class="form-check-label">Allow local IP</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="allow-local-ip" [(ngModel)]="currentSettings.allowLocalIp" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="allow-local-ip" [checked]="currentSettings.allowLocalIp" [(ngModel)]="currentSettings.allowLocalIp" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Allow local ip add to peer list, mostly in debug process</small>
|
<small class="text-body-secondary">Allow local ip add to peer list, mostly in debug process</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="p2p-ignore-ipv4" class="form-check-label">Ignore IPv4</label>
|
<label for="p2p-ignore-ipv4" class="form-check-label">Ignore IPv4</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="p2p-ignore-ipv4" [(ngModel)]="currentSettings.p2pIgnoreIpv4">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="p2p-ignore-ipv4" [checked]="currentSettings.p2pIgnoreIpv4" [(ngModel)]="currentSettings.p2pIgnoreIpv4">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Ignore unsuccessful IPv4 bind for P2P</small>
|
<small class="text-body-secondary">Ignore unsuccessful IPv4 bind for P2P</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -332,21 +332,21 @@
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="prune-blockchain" class="form-check-label">Prune Blockchain</label>
|
<label for="prune-blockchain" class="form-check-label">Prune Blockchain</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="prune-blockchain" [(ngModel)]="currentSettings.pruneBlockchain" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="prune-blockchain" [checked]="currentSettings.pruneBlockchain" [(ngModel)]="currentSettings.pruneBlockchain" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Reduce blockchain disk usage</small>
|
<small class="text-body-secondary">Reduce blockchain disk usage</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="sync-pruned-blocks" class="form-check-label">Sync pruned blocks</label>
|
<label for="sync-pruned-blocks" class="form-check-label">Sync pruned blocks</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="sync-pruned-blocks" [(ngModel)]="currentSettings.syncPrunedBlocks" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="sync-pruned-blocks" [checked]="currentSettings.syncPrunedBlocks" [(ngModel)]="currentSettings.syncPrunedBlocks" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Allow syncing from nodes with only pruned blocks</small>
|
<small class="text-body-secondary">Allow syncing from nodes with only pruned blocks</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="fast-block-sync" class="form-check-label">Fast block sync</label>
|
<label for="fast-block-sync" class="form-check-label">Fast block sync</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="fast-block-sync" [(ngModel)]="currentSettings.fastBlockSync" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="fast-block-sync" [checked]="currentSettings.fastBlockSync" [(ngModel)]="currentSettings.fastBlockSync" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Sync up most of the way by using embedded, known block hashes</small>
|
<small class="text-body-secondary">Sync up most of the way by using embedded, known block hashes</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -360,7 +360,7 @@
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="keep-alt-blocks" class="form-check-label">Keep alternative blocks</label>
|
<label for="keep-alt-blocks" class="form-check-label">Keep alternative blocks</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="keep-alt-blocks" [(ngModel)]="currentSettings.keepAltBlocks" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="keep-alt-blocks" [checked]="currentSettings.keepAltBlocks" [(ngModel)]="currentSettings.keepAltBlocks" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Keep alternative blocks on restart</small>
|
<small class="text-body-secondary">Keep alternative blocks on restart</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -379,6 +379,8 @@
|
||||||
<label for="db-sync-mode" class="form-label">Database sync mode</label>
|
<label for="db-sync-mode" class="form-label">Database sync mode</label>
|
||||||
<input type="text" class="form-control" id="db-sync-mode" placeholder="fast:async:250000000bytes" [(ngModel)]="currentSettings.dbSyncMode" [ngModelOptions]="{standalone: true}">
|
<input type="text" class="form-control" id="db-sync-mode" placeholder="fast:async:250000000bytes" [(ngModel)]="currentSettings.dbSyncMode" [ngModelOptions]="{standalone: true}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<hr class="my-4">
|
<hr class="my-4">
|
||||||
|
|
||||||
|
@ -386,15 +388,15 @@
|
||||||
|
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input id="credit" name="paymentMethod" type="radio" class="form-check-input">
|
<input id="credit" name="paymentMethod" type="radio" class="form-check-input" [value]="'mainnet'" [(ngModel)]="networkType" [ngModelOptions]="{standalone: true}" (change)="OnNetworkTypeChange()">
|
||||||
<label class="form-check-label" for="credit">mainnet</label>
|
<label class="form-check-label" for="credit">mainnet</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input id="debit" name="paymentMethod" type="radio" class="form-check-input" [(ngModel)]="currentSettings.testnet" [ngModelOptions]="{standalone: true}">
|
<input id="debit" name="paymentMethod" type="radio" class="form-check-input" [value]="'testnet'" [(ngModel)]="networkType" [ngModelOptions]="{standalone: true}" (change)="OnNetworkTypeChange()">
|
||||||
<label class="form-check-label" for="debit">testnet</label>
|
<label class="form-check-label" for="debit">testnet</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input id="paypal" name="paymentMethod" type="radio" class="form-check-input" [(ngModel)]="currentSettings.stagenet" [ngModelOptions]="{standalone: true}">
|
<input id="paypal" name="paymentMethod" type="radio" class="form-check-input" [value]="'stagenet'" [(ngModel)]="networkType" [ngModelOptions]="{standalone: true}" (change)="OnNetworkTypeChange()">
|
||||||
<label class="form-check-label" for="paypal">stagenet</label>
|
<label class="form-check-label" for="paypal">stagenet</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -415,14 +417,14 @@
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="bg-mining-enable" class="form-check-label">Enabled</label>
|
<label for="bg-mining-enable" class="form-check-label">Enabled</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="bg-mining-enable" [(ngModel)]="currentSettings.bgMiningEnable" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="bg-mining-enable" [checked]="currentSettings.bgMiningEnable" [(ngModel)]="currentSettings.bgMiningEnable" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Enable background mining</small>
|
<small class="text-body-secondary">Enable background mining</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check form-switch col-md-6">
|
<div class="form-check form-switch col-md-6">
|
||||||
<label for="bg-mining-ignore-battery" class="form-check-label">Ignore battery</label>
|
<label for="bg-mining-ignore-battery" class="form-check-label">Ignore battery</label>
|
||||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="bg-mining-ignore-battery" [(ngModel)]="currentSettings.bgMiningIgnoreBattery" [ngModelOptions]="{standalone: true}">
|
<input class="form-control form-check-input" type="checkbox" role="switch" id="bg-mining-ignore-battery" [checked]="currentSettings.bgMiningIgnoreBattery" [(ngModel)]="currentSettings.bgMiningIgnoreBattery" [ngModelOptions]="{standalone: true}">
|
||||||
<br>
|
<br>
|
||||||
<small class="text-body-secondary">Reduce blockchain disk usage</small>
|
<small class="text-body-secondary">Reduce blockchain disk usage</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -491,6 +493,6 @@
|
||||||
|
|
||||||
<hr class="my-4">
|
<hr class="my-4">
|
||||||
|
|
||||||
<button class="w-50 btn btn-primary btn-lg" type="submit" [disabled]="!modified" (click)="OnSave()">Save</button>
|
<button class="w-100 btn btn-primary btn-lg" type="submit" [disabled]="!modified" (click)="OnSave()">Save</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,13 +4,12 @@ import { NavigationEnd, NavigationStart, Router } from '@angular/router';
|
||||||
import { NavbarLink } from '../../shared/components/navbar/navbar.model';
|
import { NavbarLink } from '../../shared/components/navbar/navbar.model';
|
||||||
import { DaemonSettings } from '../../../common/DaemonSettings';
|
import { DaemonSettings } from '../../../common/DaemonSettings';
|
||||||
import { FormsModule, NgModel } from '@angular/forms';
|
import { FormsModule, NgModel } from '@angular/forms';
|
||||||
|
import { DaemonService } from '../../core/services/daemon/daemon.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings',
|
selector: 'app-settings',
|
||||||
templateUrl: './settings.component.html',
|
templateUrl: './settings.component.html',
|
||||||
styleUrl: './settings.component.scss',
|
styleUrl: './settings.component.scss'
|
||||||
imports: [FormsModule],
|
|
||||||
standalone: true
|
|
||||||
})
|
})
|
||||||
export class SettingsComponent implements AfterViewInit {
|
export class SettingsComponent implements AfterViewInit {
|
||||||
|
|
||||||
|
@ -20,9 +19,12 @@ export class SettingsComponent implements AfterViewInit {
|
||||||
|
|
||||||
public rpcLoginUser: string;
|
public rpcLoginUser: string;
|
||||||
public rpcLoginPassword: string;
|
public rpcLoginPassword: string;
|
||||||
|
public loading: boolean;
|
||||||
|
|
||||||
constructor(private router: Router, private navbarService: NavbarService) {
|
public networkType: 'mainnet' | 'testnet' | 'stagenet' = 'mainnet';
|
||||||
|
|
||||||
|
constructor(private router: Router, private navbarService: NavbarService, private daemonService: DaemonService) {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
this.navbarLinks = [
|
this.navbarLinks = [
|
||||||
new NavbarLink('pills-rpc-tab', '#pills-rpc', 'pills-rpc', true, 'RPC'),
|
new NavbarLink('pills-rpc-tab', '#pills-rpc', 'pills-rpc', true, 'RPC'),
|
||||||
|
@ -50,6 +52,17 @@ export class SettingsComponent implements AfterViewInit {
|
||||||
this.onNavigationEnd();
|
this.onNavigationEnd();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async load(): Promise<void> {
|
||||||
|
console.log("getting settings");
|
||||||
|
this.originalSettings = await this.daemonService.getSettings();
|
||||||
|
this.currentSettings = this.originalSettings.clone();
|
||||||
|
this.loading = false;
|
||||||
|
|
||||||
|
this.networkType = this.currentSettings.mainnet ? 'mainnet' : this.currentSettings.testnet ? 'testnet' : this.currentSettings.stagenet ? 'stagenet' : 'mainnet';
|
||||||
}
|
}
|
||||||
|
|
||||||
public get modified(): boolean {
|
public get modified(): boolean {
|
||||||
|
@ -105,12 +118,36 @@ export class SettingsComponent implements AfterViewInit {
|
||||||
this.currentSettings.noFluffyBlocks = !this.currentSettings.noFluffyBlocks;
|
this.currentSettings.noFluffyBlocks = !this.currentSettings.noFluffyBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OnNetworkTypeChange(): void {
|
||||||
|
if (this.networkType == 'mainnet') {
|
||||||
|
this.currentSettings.mainnet = true;
|
||||||
|
this.currentSettings.testnet = false;
|
||||||
|
this.currentSettings.stagenet = false;
|
||||||
|
}
|
||||||
|
else if (this.networkType == 'testnet') {
|
||||||
|
this.currentSettings.mainnet = false;
|
||||||
|
this.currentSettings.testnet = true;
|
||||||
|
this.currentSettings.stagenet = false;
|
||||||
|
}
|
||||||
|
else if (this.networkType == 'stagenet') {
|
||||||
|
this.currentSettings.mainnet = false;
|
||||||
|
this.currentSettings.testnet = false;
|
||||||
|
this.currentSettings.stagenet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private onNavigationEnd(): void {
|
private onNavigationEnd(): void {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnSave(): void {
|
public async OnSave(): Promise<void> {
|
||||||
|
if (!this.modified) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.daemonService.saveSettings(this.currentSettings);
|
||||||
|
|
||||||
|
this.originalSettings = this.currentSettings.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,10 +4,11 @@ import { CommonModule } from '@angular/common';
|
||||||
import { SettingsRoutingModule } from './settings-routing.module';
|
import { SettingsRoutingModule } from './settings-routing.module';
|
||||||
import { SharedModule } from '../../shared/shared.module';
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { SettingsComponent } from './settings.component';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [],
|
declarations: [SettingsComponent],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<div class="d-flex flex-column flex-shrink-0 p-3 text-bg-dark" style="width: 200px;">
|
<div class="d-flex flex-column flex-shrink-0 p-3 text-bg-dark" style="width: 280px;">
|
||||||
|
|
||||||
<ul class="nav nav-pills flex-column mb-auto">
|
<ul class="nav nav-pills flex-column mb-auto">
|
||||||
@for (navLink of navLinks; track navLink.title) {
|
@for (navLink of navLinks; track navLink.title) {
|
||||||
<a routerLink="{{navLink.path}}" [ngClass]="isActive(navLink) ? 'nav-link active' : 'nav-link text-white'">
|
<a routerLink="{{navLink.path}}" [ngClass]="isActive(navLink) ? 'nav-link active' : 'nav-link text-white'">
|
||||||
<i [class]="navLink.icon"></i>
|
<i [class]="navLink.icon"></i>
|
||||||
{{navLink.title}}
|
<strong>{{navLink.title}}</strong>
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { CommonModule, NgClass, NgFor } from '@angular/common';
|
import { CommonModule, NgClass, NgFor } from '@angular/common';
|
||||||
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||||||
import { ChildActivationEnd, ChildActivationStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, RouteConfigLoadEnd, RouteConfigLoadStart, Router, RouterEvent, RouterModule, RoutesRecognized } from '@angular/router';
|
import { ChildActivationEnd, ChildActivationStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, RouteConfigLoadEnd, RouteConfigLoadStart, Router, RouterEvent, RouterModule, RoutesRecognized } from '@angular/router';
|
||||||
|
import { DaemonService } from '../../../core/services/daemon/daemon.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sidebar',
|
selector: 'app-sidebar',
|
||||||
|
@ -10,11 +11,37 @@ import { ChildActivationEnd, ChildActivationStart, NavigationCancel, NavigationE
|
||||||
export class SidebarComponent implements OnChanges {
|
export class SidebarComponent implements OnChanges {
|
||||||
@Input() public isDaemonRunning: boolean = false;
|
@Input() public isDaemonRunning: boolean = false;
|
||||||
|
|
||||||
public navLinks: NavLink[];
|
public navLinks: NavLink[] = [];
|
||||||
public isLoading: boolean;
|
public isLoading: boolean;
|
||||||
public errorMessage: string;
|
public errorMessage: string;
|
||||||
|
|
||||||
constructor(private router: Router) {
|
constructor(private router: Router, private daemonService: DaemonService) {
|
||||||
|
this.updateLinks();
|
||||||
|
this.isLoading = false;
|
||||||
|
this.errorMessage = '';
|
||||||
|
this.daemonService.onDaemonStart.subscribe((started: boolean) => {
|
||||||
|
if (!started) {
|
||||||
|
this.navLinks = [
|
||||||
|
new NavLink('Dashboard', '/detail', 'bi bi-speedometer2'),
|
||||||
|
new NavLink('Settings', '/settings', 'bi bi-gear')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.navLinks = [
|
||||||
|
new NavLink('Dashboard', '/detail', 'bi bi-speedometer2'),
|
||||||
|
new NavLink('Blockchain', '/blockchain', 'bi bi-bounding-box'),
|
||||||
|
new NavLink('Transactions', '/transactions', 'bi bi-credit-card-2-front'),
|
||||||
|
new NavLink('Outputs', '/outputs', 'bi bi-circle-fill'),
|
||||||
|
new NavLink('Mining', '/mining', 'bi bi-minecart-loaded'),
|
||||||
|
new NavLink('Hard Fork Info', '/hardforkinfo', 'bi bi-signpost-split'),
|
||||||
|
new NavLink('Bans', '/bans', 'bi bi-ban'),
|
||||||
|
new NavLink('Settings', '/settings', 'bi bi-gear')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateLinks(): void {
|
||||||
if (!this.isDaemonRunning) {
|
if (!this.isDaemonRunning) {
|
||||||
this.navLinks = [
|
this.navLinks = [
|
||||||
new NavLink('Dashboard', '/detail', 'bi bi-speedometer2'),
|
new NavLink('Dashboard', '/detail', 'bi bi-speedometer2'),
|
||||||
|
@ -33,8 +60,6 @@ export class SidebarComponent implements OnChanges {
|
||||||
new NavLink('Settings', '/settings', 'bi bi-gear')
|
new NavLink('Settings', '/settings', 'bi bi-gear')
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
this.isLoading = false;
|
|
||||||
this.errorMessage = '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public isActive(navLink: NavLink): boolean {
|
public isActive(navLink: NavLink): boolean {
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class DaemonSettings {
|
||||||
public testDbgLockSleep: number = 0;
|
public testDbgLockSleep: number = 0;
|
||||||
|
|
||||||
public testnet: boolean = false;
|
public testnet: boolean = false;
|
||||||
public mainnet: boolean = false;
|
public mainnet: boolean = true;
|
||||||
public stagenet: boolean = false;
|
public stagenet: boolean = false;
|
||||||
|
|
||||||
public regtest: boolean = false;
|
public regtest: boolean = false;
|
||||||
|
|
Loading…
Reference in a new issue