Files
Encelado/TradingBot/Components/Pages/Settings.razor
Alberto Balbo 92c8e57a8c Persistenza dati e logging avanzato con UI e Unraid
- Aggiunto TradeHistoryService per persistenza trade/posizioni attive su disco (JSON, auto-save/restore)
- Logging centralizzato (LoggingService) con livelli, categorie, simbolo e buffer circolare (500 log)
- Nuova pagina Logs: monitoraggio real-time, filtri avanzati, cancellazione log, colorazione livelli
- Sezione "Dati Persistenti" in Settings: conteggio trade, dimensione dati, reset con conferma modale
- Background service per salvataggio sicuro su shutdown/stop container
- Aggiornata sidebar, stili modali/bottoni danger, .gitignore e documentazione (README, CHANGELOG, UNRAID_INSTALL, checklist)
- Versione 1.3.0
2025-12-22 11:24:17 +01:00

289 lines
11 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@page "/settings"
@using TradingBot.Services
@using TradingBot.Models
@inject SettingsService SettingsService
@inject TradingBotService TradingBotService
@inject TradeHistoryService HistoryService
@implements IDisposable
@rendermode InteractiveServer
<PageTitle>Impostazioni - TradingBot</PageTitle>
<div class="settings-page">
<div class="page-header">
<h1>Impostazioni</h1>
<p class="subtitle">Configura le impostazioni globali del trading bot</p>
</div>
<div class="settings-section">
<h2>Generale</h2>
<div class="settings-group">
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Modalità Simulazione</div>
<div class="setting-description">Utilizza dati simulati invece di dati reali di mercato</div>
</div>
<label class="toggle-switch">
<input type="checkbox" checked="@settings.SimulationMode" @onchange="(e) => UpdateSetting(nameof(AppSettings.SimulationMode), (bool)e.Value!)" disabled />
<span class="toggle-slider"></span>
</label>
</div>
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Notifiche Desktop</div>
<div class="setting-description">Ricevi notifiche per operazioni importanti</div>
</div>
<label class="toggle-switch">
<input type="checkbox" checked="@settings.DesktopNotifications" @onchange="(e) => UpdateSetting(nameof(AppSettings.DesktopNotifications), (bool)e.Value!)" />
<span class="toggle-slider"></span>
</label>
</div>
</div>
</div>
<div class="settings-section">
<h2>Trading</h2>
<div class="settings-group">
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Auto-Start Bot</div>
<div class="setting-description">Avvia automaticamente il bot all'apertura dell'applicazione</div>
</div>
<label class="toggle-switch">
<input type="checkbox" checked="@settings.AutoStartBot" @onchange="(e) => UpdateSetting(nameof(AppSettings.AutoStartBot), (bool)e.Value!)" />
<span class="toggle-slider"></span>
</label>
</div>
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Conferma Operazioni Manuali</div>
<div class="setting-description">Richiedi conferma prima di eseguire operazioni manuali</div>
</div>
<label class="toggle-switch">
<input type="checkbox" checked="@settings.ConfirmManualTrades" @onchange="(e) => UpdateSetting(nameof(AppSettings.ConfirmManualTrades), (bool)e.Value!)" />
<span class="toggle-slider"></span>
</label>
</div>
</div>
</div>
<div class="settings-section">
<h2>Dati Persistenti</h2>
<div class="settings-group">
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Trade Salvati</div>
<div class="setting-description">@TradingBotService.Trades.Count trade nella cronologia</div>
</div>
<div class="setting-value">
@FormatBytes(dataSize)
</div>
</div>
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Posizioni Attive</div>
<div class="setting-description">@TradingBotService.ActivePositions.Count posizioni aperte</div>
</div>
</div>
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Cancella Tutti i Dati</div>
<div class="setting-description text-danger">Elimina cronologia trade e resetta i saldi</div>
</div>
<button class="btn-danger" @onclick="ShowClearDataConfirmation" disabled="@TradingBotService.Status.IsRunning">
<span class="bi bi-trash"></span>
Cancella Dati
</button>
</div>
</div>
</div>
<div class="settings-section">
<h2>Avanzate</h2>
<div class="settings-group">
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Intervallo Aggiornamento</div>
<div class="setting-description">Frequenza di aggiornamento dei dati di mercato</div>
</div>
<select class="setting-select" value="@settings.UpdateIntervalSeconds" @onchange="(e) => UpdateSetting(nameof(AppSettings.UpdateIntervalSeconds), int.Parse(e.Value!.ToString()!))">
<option value="2">2 secondi</option>
<option value="3">3 secondi</option>
<option value="5">5 secondi</option>
<option value="10">10 secondi</option>
</select>
</div>
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Log Level</div>
<div class="setting-description">Livello di dettaglio dei log di sistema</div>
</div>
<select class="setting-select" value="@settings.LogLevel" @onchange="(e) => UpdateSetting(nameof(AppSettings.LogLevel), e.Value!.ToString()!)">
<option value="Error">Error</option>
<option value="Warning">Warning</option>
<option value="Info">Info</option>
<option value="Debug">Debug</option>
</select>
</div>
</div>
</div>
<div class="settings-actions">
<button class="btn-secondary" @onclick="ResetToDefaults">
<span class="bi bi-arrow-counterclockwise"></span>
Reset Predefiniti
</button>
<button class="btn-primary" @onclick="SaveSettings">
<span class="bi bi-check-lg"></span>
Salva Modifiche
</button>
</div>
@if (showNotification)
{
<div class="notification success">
<span class="bi bi-check-circle-fill"></span>
Impostazioni salvate con successo!
</div>
}
@if (showClearConfirmation)
{
<div class="modal-overlay" @onclick="HideClearDataConfirmation">
<div class="modal-dialog" @onclick:stopPropagation="true">
<div class="modal-header">
<h3>Conferma Cancellazione</h3>
<button class="btn-close" @onclick="HideClearDataConfirmation">×</button>
</div>
<div class="modal-body">
<p class="text-danger">
<strong>Attenzione!</strong> Questa azione eliminerà:
</p>
<ul>
<li>Tutta la cronologia dei trade (@TradingBotService.Trades.Count trade)</li>
<li>Tutte le posizioni attive (@TradingBotService.ActivePositions.Count posizioni)</li>
<li>I saldi verranno resettati ai valori iniziali</li>
</ul>
<p class="text-danger">
<strong>Questa operazione è irreversibile!</strong>
</p>
</div>
<div class="modal-footer">
<button class="btn-secondary" @onclick="HideClearDataConfirmation">Annulla</button>
<button class="btn-danger" @onclick="ConfirmClearData">
<span class="bi bi-trash"></span>
Conferma Cancellazione
</button>
</div>
</div>
</div>
}
</div>
@code {
private AppSettings settings = new();
private bool showNotification = false;
private bool showClearConfirmation = false;
private long dataSize = 0;
protected override void OnInitialized()
{
settings = SettingsService.GetSettings();
SettingsService.OnSettingsChanged += HandleSettingsChanged;
TradingBotService.OnStatusChanged += HandleStatusChanged;
UpdateDataSize();
}
private void UpdateDataSize()
{
dataSize = HistoryService.GetDataSize();
}
private void UpdateSetting<T>(string propertyName, T value)
{
SettingsService.UpdateSetting(propertyName, value);
settings = SettingsService.GetSettings();
ShowNotification();
}
private void SaveSettings()
{
SettingsService.UpdateSettings(settings);
ShowNotification();
}
private void ResetToDefaults()
{
SettingsService.ResetToDefaults();
settings = SettingsService.GetSettings();
ShowNotification();
}
private void ShowClearDataConfirmation()
{
showClearConfirmation = true;
}
private void HideClearDataConfirmation()
{
showClearConfirmation = false;
}
private async Task ConfirmClearData()
{
await TradingBotService.ClearAllDataAsync();
UpdateDataSize();
showClearConfirmation = false;
showNotification = true;
StateHasChanged();
await Task.Delay(3000);
showNotification = false;
StateHasChanged();
}
private async void ShowNotification()
{
showNotification = true;
StateHasChanged();
await Task.Delay(3000);
showNotification = false;
StateHasChanged();
}
private string FormatBytes(long bytes)
{
string[] sizes = { "B", "KB", "MB", "GB" };
double len = bytes;
int order = 0;
while (len >= 1024 && order < sizes.Length - 1)
{
order++;
len = len / 1024;
}
return $"{len:0.##} {sizes[order]}";
}
private void HandleSettingsChanged()
{
settings = SettingsService.GetSettings();
InvokeAsync(StateHasChanged);
}
private void HandleStatusChanged()
{
UpdateDataSize();
InvokeAsync(StateHasChanged);
}
public void Dispose()
{
SettingsService.OnSettingsChanged -= HandleSettingsChanged;
TradingBotService.OnStatusChanged -= HandleStatusChanged;
}
}