d042863a56
- Aggiunto supporto schedulazione con intervalli flessibili (secondi/minuti/ore/giorni/settimane/mesi) - Esteso modello ProfileSchedule con campi IntervalValue e IntervalUnit - Ottimizzato ScheduledJobService per controlli ogni 30s con esecuzione parallela - Implementata interfaccia UI completa con anteprima real-time in italiano - Aggiunta migrazione database AddIntervalSchedulingFields - Implementati metodi calcolo NextExecutionTime per intervalli - Aggiunta gestione tracking anti-duplicati e cleanup automatico - Creata documentazione completa (6 file, 2500+ righe) Modifiche tecniche: - ProfileSchedule.cs: Nuovi campi e metodi CalculateNextInterval/GetScheduleDescription - ScheduledJobService.cs: Ridotto check interval a 30s, aggiunto parallel processing - ProfileScheduleService.cs: Supporto calcolo intervalli in UpdateNextExecutionTimeAsync - Scheduling.razor: Aggiunta sezione UI per configurazione intervalli - Scheduling.razor.cs: Implementato GetIntervalPreview() e gestione stato campi
229 lines
7.9 KiB
Plaintext
229 lines
7.9 KiB
Plaintext
@page "/settings"
|
|
@using Data_Coupler.Services
|
|
@using Data_Coupler.Models
|
|
@inject IJSRuntime JSRuntime
|
|
@inject ILogger<SettingsPage> Logger
|
|
|
|
<PageTitle>Impostazioni - Data Coupler</PageTitle>
|
|
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h1>
|
|
<i class="fas fa-cog text-primary"></i>
|
|
Impostazioni Sistema
|
|
</h1>
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="/">Home</a></li>
|
|
<li class="breadcrumb-item active" aria-current="page">Impostazioni</li>
|
|
</ol>
|
|
</nav>
|
|
</div>
|
|
|
|
@if (!string.IsNullOrEmpty(toastMessage))
|
|
{
|
|
<div class="alert alert-@(toastType == "success" ? "success" : toastType == "error" ? "danger" : "info") alert-dismissible fade show" role="alert">
|
|
<i class="fas fa-@(toastType == "success" ? "check-circle" : toastType == "error" ? "exclamation-circle" : "info-circle")"></i>
|
|
@toastMessage
|
|
<button type="button" class="btn-close" @onclick="ClearToast" aria-label="Close"></button>
|
|
</div>
|
|
}
|
|
|
|
<!-- Tab Navigation -->
|
|
<ul class="nav nav-tabs mb-4" id="settingsTabs" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link @(activeTab == "backup" ? "active" : "")"
|
|
id="backup-tab"
|
|
@onclick='() => SetActiveTab("backup")'
|
|
type="button"
|
|
role="tab"
|
|
aria-controls="backup"
|
|
aria-selected="@(activeTab == "backup")">
|
|
<i class="fas fa-download me-2"></i>
|
|
Backup e Ripristino
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link @(activeTab == "system" ? "active" : "")"
|
|
id="system-tab"
|
|
@onclick='() => SetActiveTab("system")'
|
|
type="button"
|
|
role="tab"
|
|
aria-controls="system"
|
|
aria-selected="@(activeTab == "system")">
|
|
<i class="fas fa-server me-2"></i>
|
|
Sistema
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link @(activeTab == "security" ? "active" : "")"
|
|
id="security-tab"
|
|
@onclick='() => SetActiveTab("security")'
|
|
type="button"
|
|
role="tab"
|
|
aria-controls="security"
|
|
aria-selected="@(activeTab == "security")">
|
|
<i class="fas fa-shield-alt me-2"></i>
|
|
Sicurezza
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link @(activeTab == "maintenance" ? "active" : "")"
|
|
id="maintenance-tab"
|
|
@onclick='() => SetActiveTab("maintenance")'
|
|
type="button"
|
|
role="tab"
|
|
aria-controls="maintenance"
|
|
aria-selected="@(activeTab == "maintenance")">
|
|
<i class="fas fa-tools me-2"></i>
|
|
Manutenzione
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- Tab Content -->
|
|
<div class="tab-content" id="settingsTabContent">
|
|
<!-- Backup Tab -->
|
|
<div class="tab-pane fade @(activeTab == "backup" ? "show active" : "")"
|
|
id="backup"
|
|
role="tabpanel"
|
|
aria-labelledby="backup-tab">
|
|
<BackupTab OnShowToast="ShowToastTuple" />
|
|
</div>
|
|
|
|
<!-- System Tab -->
|
|
<div class="tab-pane fade @(activeTab == "system" ? "show active" : "")"
|
|
id="system"
|
|
role="tabpanel"
|
|
aria-labelledby="system-tab">
|
|
<SystemTab OnShowToast="ShowToastTuple" />
|
|
</div>
|
|
|
|
<!-- Security Tab -->
|
|
<div class="tab-pane fade @(activeTab == "security" ? "show active" : "")"
|
|
id="security"
|
|
role="tabpanel"
|
|
aria-labelledby="security-tab">
|
|
<SecurityTab OnShowToast="ShowToastTuple" />
|
|
</div>
|
|
|
|
<!-- Maintenance Tab -->
|
|
<div class="tab-pane fade @(activeTab == "maintenance" ? "show active" : "")"
|
|
id="maintenance"
|
|
role="tabpanel"
|
|
aria-labelledby="maintenance-tab">
|
|
<MaintenanceTab OnShowToast="ShowToastTuple" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Include CSS per migliorare l'aspetto -->
|
|
<style>
|
|
.nav-tabs .nav-link {
|
|
border: 1px solid transparent;
|
|
border-radius: 0.375rem 0.375rem 0 0;
|
|
color: #6c757d;
|
|
background-color: #f8f9fa;
|
|
margin-right: 2px;
|
|
transition: all 0.15s ease-in-out;
|
|
}
|
|
|
|
.nav-tabs .nav-link:hover {
|
|
border-color: #e9ecef #e9ecef #dee2e6;
|
|
color: #495057;
|
|
background-color: #e9ecef;
|
|
}
|
|
|
|
.nav-tabs .nav-link.active {
|
|
color: #495057;
|
|
background-color: #fff;
|
|
border-color: #dee2e6 #dee2e6 #fff;
|
|
border-bottom: 1px solid #fff;
|
|
margin-bottom: -1px;
|
|
}
|
|
|
|
.tab-content {
|
|
border: 1px solid #dee2e6;
|
|
border-top: none;
|
|
border-radius: 0 0 0.375rem 0.375rem;
|
|
padding: 1.5rem;
|
|
background-color: #fff;
|
|
min-height: 500px;
|
|
}
|
|
|
|
.settings-section {
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.settings-section h4 {
|
|
border-bottom: 2px solid #e9ecef;
|
|
padding-bottom: 0.5rem;
|
|
margin-bottom: 1rem;
|
|
color: #495057;
|
|
}
|
|
|
|
.alert {
|
|
border-radius: 0.375rem;
|
|
border: none;
|
|
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
}
|
|
|
|
.card {
|
|
border: none;
|
|
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
border-radius: 0.5rem;
|
|
}
|
|
|
|
.card-header {
|
|
background-color: #f8f9fa;
|
|
border-bottom: 1px solid #dee2e6;
|
|
border-radius: 0.5rem 0.5rem 0 0 !important;
|
|
}
|
|
</style>
|
|
|
|
@code {
|
|
private string activeTab = "backup";
|
|
private string toastMessage = "";
|
|
private string toastType = "info";
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
// Inizializzazione se necessaria
|
|
await base.OnInitializedAsync();
|
|
}
|
|
|
|
private void SetActiveTab(string tabName)
|
|
{
|
|
activeTab = tabName;
|
|
StateHasChanged();
|
|
}
|
|
|
|
private void ShowToast(string message, string type = "info")
|
|
{
|
|
toastMessage = message;
|
|
toastType = type;
|
|
StateHasChanged();
|
|
|
|
// Auto-hide dopo 5 secondi per messaggi di successo
|
|
if (type == "success")
|
|
{
|
|
_ = Task.Delay(5000).ContinueWith(_ => ClearToast());
|
|
}
|
|
}
|
|
|
|
private void ShowToastTuple((string message, string type) toast)
|
|
{
|
|
ShowToast(toast.message, toast.type);
|
|
}
|
|
|
|
private void ClearToast()
|
|
{
|
|
toastMessage = "";
|
|
toastType = "info";
|
|
InvokeAsync(StateHasChanged);
|
|
}
|
|
} |