Files
Data-Coupler/Data_Coupler/Pages/ProfilesManagement.razor.cs
Alessio fb3b3142a7 feat: Implementa pagina di gestione profili avanzata
- Aggiunge nuova pagina ProfilesManagement (/profiles) con dashboard completo
- Implementa statistiche profili (totali, attivi, recenti, non utilizzati)
- Aggiunge filtri avanzati per ricerca e ordinamento profili
- Implementa visualizzazione dettagli profili con mappature campi
- Aggiunge funzionalità di eliminazione profili con conferma
- Implementa esportazione profili in formato JSON
- Aggiunge sistema di notifiche toast per feedback utente
- Integra navigazione nel menu principale
- Risolve errori di compilazione e duplicazione file
- Migliora UX con design responsive e interfaccia moderna
2025-07-02 01:15:23 +02:00

278 lines
7.9 KiB
C#

using Microsoft.AspNetCore.Components;
using CredentialManager.Models;
using CredentialManager.Services;
using Microsoft.JSInterop;
using System.Text.Json;
namespace Data_Coupler.Pages;
public partial class ProfilesManagement : ComponentBase
{
[Inject] private IDataCouplerProfileService ProfileService { get; set; } = null!;
[Inject] private IJSRuntime JSRuntime { get; set; } = null!;
[Inject] private ILogger<ProfilesManagement> Logger { get; set; } = null!;
// State delle liste
private List<DataCouplerProfile> allProfiles = new();
// State dei filtri
private string searchTerm = "";
private string selectedSourceType = "";
private string selectedUsageFilter = "";
private string sortOrder = "name";
// State delle modali
private bool showDetailsModal = false;
private bool showDeleteModal = false;
private DataCouplerProfile? selectedProfile = null;
private DataCouplerProfile? profileToDelete = null;
// State operazioni
private bool isLoading = true;
private bool isDeleting = false;
// Toast notifications
private string toastMessage = "";
private string toastType = "info";
// Statistiche
private int totalProfiles => allProfiles.Count;
private int activeProfiles => allProfiles.Count(p => p.LastUsedAt.HasValue && p.LastUsedAt.Value > DateTime.Now.AddDays(-30));
private int profilesThisWeek => allProfiles.Count(p => p.CreatedAt > DateTime.Now.AddDays(-7));
private int unusedProfiles => allProfiles.Count(p => !p.LastUsedAt.HasValue);
protected override async Task OnInitializedAsync()
{
await LoadProfiles();
}
private async Task LoadProfiles()
{
try
{
isLoading = true;
var profiles = await ProfileService.GetAllProfilesAsync();
allProfiles = profiles.ToList();
}
catch (Exception ex)
{
Logger.LogError(ex, "Errore nel caricamento dei profili");
ShowToast("Errore nel caricamento dei profili: " + ex.Message, "error");
}
finally
{
isLoading = false;
StateHasChanged();
}
}
private async Task RefreshProfiles()
{
await LoadProfiles();
}
// Filtri e ricerca
private IEnumerable<DataCouplerProfile> GetFilteredProfiles()
{
var filtered = allProfiles.AsEnumerable();
// Filtro per testo
if (!string.IsNullOrEmpty(searchTerm))
{
filtered = filtered.Where(p =>
p.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ||
(p.Description?.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ?? false));
}
// Filtro per tipo sorgente
if (!string.IsNullOrEmpty(selectedSourceType))
{
filtered = filtered.Where(p => p.SourceType.Equals(selectedSourceType, StringComparison.OrdinalIgnoreCase));
}
// Filtro per utilizzo
if (!string.IsNullOrEmpty(selectedUsageFilter))
{
filtered = selectedUsageFilter switch
{
"used" => filtered.Where(p => p.LastUsedAt.HasValue),
"unused" => filtered.Where(p => !p.LastUsedAt.HasValue),
"recent" => filtered.Where(p => p.LastUsedAt.HasValue && p.LastUsedAt.Value > DateTime.Now.AddDays(-7)),
_ => filtered
};
}
// Ordinamento
filtered = sortOrder switch
{
"created" => filtered.OrderByDescending(p => p.CreatedAt),
"lastused" => filtered.OrderByDescending(p => p.LastUsedAt ?? DateTime.MinValue),
_ => filtered.OrderBy(p => p.Name)
};
return filtered;
}
private void FilterProfiles()
{
StateHasChanged();
}
private void ClearSearch()
{
searchTerm = "";
FilterProfiles();
}
// Operazioni sui profili
private void ShowDetails(DataCouplerProfile profile)
{
selectedProfile = profile;
showDetailsModal = true;
StateHasChanged();
}
private void CloseDetailsModal()
{
showDetailsModal = false;
selectedProfile = null;
StateHasChanged();
}
private void ConfirmDelete(DataCouplerProfile profile)
{
profileToDelete = profile;
showDeleteModal = true;
StateHasChanged();
}
private void CancelDelete()
{
showDeleteModal = false;
profileToDelete = null;
StateHasChanged();
}
private async Task DeleteProfile()
{
if (profileToDelete == null) return;
try
{
isDeleting = true;
StateHasChanged();
await ProfileService.DeleteProfileAsync(profileToDelete.Id);
allProfiles.Remove(profileToDelete);
ShowToast("Profilo eliminato con successo", "success");
CancelDelete();
}
catch (Exception ex)
{
Logger.LogError(ex, "Errore nell'eliminazione del profilo {ProfileId}", profileToDelete.Id);
ShowToast("Errore nell'eliminazione: " + ex.Message, "error");
}
finally
{
isDeleting = false;
StateHasChanged();
}
}
private async Task ExportProfiles()
{
try
{
var profilesToExport = GetFilteredProfiles().ToList();
var json = JsonSerializer.Serialize(profilesToExport, new JsonSerializerOptions { WriteIndented = true });
var fileName = $"profiles_export_{DateTime.Now:yyyyMMdd_HHmmss}.json";
var bytes = System.Text.Encoding.UTF8.GetBytes(json);
var stream = new MemoryStream(bytes);
using var streamRef = new DotNetStreamReference(stream);
await JSRuntime.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
ShowToast("Esportazione completata", "success");
}
catch (Exception ex)
{
Logger.LogError(ex, "Errore nell'esportazione dei profili");
ShowToast("Errore nell'esportazione: " + ex.Message, "error");
}
}
// Helper methods per la UI
private string GetSourceTypeBadgeClass(string sourceType)
{
return sourceType?.ToLower() switch
{
"database" => "primary",
"file" => "success",
"rest" => "info",
_ => "secondary"
};
}
private string GetSourceTypeDisplayName(string sourceType)
{
return sourceType?.ToLower() switch
{
"database" => "Database",
"file" => "File",
"rest" => "REST API",
_ => "Sconosciuto"
};
}
private int GetMappingCount(DataCouplerProfile profile)
{
if (string.IsNullOrEmpty(profile.FieldMappingJson))
return 0;
try
{
var mappings = JsonSerializer.Deserialize<List<FieldMappingDto>>(profile.FieldMappingJson);
return mappings?.Count ?? 0;
}
catch
{
return 0;
}
}
private List<FieldMappingDto> GetProfileMappings(DataCouplerProfile profile)
{
if (string.IsNullOrEmpty(profile.FieldMappingJson))
return new List<FieldMappingDto>();
try
{
return JsonSerializer.Deserialize<List<FieldMappingDto>>(profile.FieldMappingJson) ?? new List<FieldMappingDto>();
}
catch
{
return new List<FieldMappingDto>();
}
}
// Toast notifications
private void ShowToast(string message, string type = "info")
{
toastMessage = message;
toastType = type;
StateHasChanged();
// Auto-hide dopo 5 secondi
_ = Task.Delay(5000).ContinueWith(_ => ClearToast());
}
private void ClearToast()
{
toastMessage = "";
toastType = "info";
InvokeAsync(StateHasChanged);
}
}