- 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
289 lines
11 KiB
Plaintext
289 lines
11 KiB
Plaintext
@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;
|
||
}
|
||
}
|