From 09edc1f2b78a5c95f28ed0293d2d096f09117201 Mon Sep 17 00:00:00 2001 From: Gianmarco Date: Mon, 2 Feb 2026 09:07:38 +0100 Subject: [PATCH] Edit utenti --- .../TecniStampDbContextModelSnapshot.cs | 22 +-- .../Interfaces/IManagerService.cs | 1 + .../Interfaces/IRuoloService.cs | 9 ++ .../TecniStamp.Service/ManagerService.cs | 4 +- TecniStamp/TecniStamp.Service/RuoloService.cs | 13 ++ .../{Operatori.razor => Operatore.razor} | 34 ++-- .../Pages/Anagrafiche/Operatore_Edit.razor | 152 ++++++++++++++++++ .../Anagrafiche/{Ruoli.razor => Ruolo.razor} | 0 TecniStamp/TecniStamp/Model/BaseViewModel.cs | 8 + TecniStamp/TecniStamp/Model/RuoloViewModel.cs | 20 +++ TecniStamp/TecniStamp/Model/UserViewModel.cs | 48 ++++++ 11 files changed, 286 insertions(+), 25 deletions(-) create mode 100644 TecniStamp/TecniStamp.Service/Interfaces/IRuoloService.cs create mode 100644 TecniStamp/TecniStamp.Service/RuoloService.cs rename TecniStamp/TecniStamp/Components/Pages/Anagrafiche/{Operatori.razor => Operatore.razor} (70%) create mode 100644 TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatore_Edit.razor rename TecniStamp/TecniStamp/Components/Pages/Anagrafiche/{Ruoli.razor => Ruolo.razor} (100%) create mode 100644 TecniStamp/TecniStamp/Model/BaseViewModel.cs create mode 100644 TecniStamp/TecniStamp/Model/RuoloViewModel.cs create mode 100644 TecniStamp/TecniStamp/Model/UserViewModel.cs diff --git a/TecniStamp/TecniStamp.Infrastructure/Migrations/TecniStampDbContextModelSnapshot.cs b/TecniStamp/TecniStamp.Infrastructure/Migrations/TecniStampDbContextModelSnapshot.cs index af35120..7922a6c 100644 --- a/TecniStamp/TecniStamp.Infrastructure/Migrations/TecniStampDbContextModelSnapshot.cs +++ b/TecniStamp/TecniStamp.Infrastructure/Migrations/TecniStampDbContextModelSnapshot.cs @@ -102,7 +102,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("IdUtenteModifica"); - b.ToTable("Cliente"); + b.ToTable("Cliente", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.Commessa", b => @@ -167,7 +167,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("IdUtenteModifica"); - b.ToTable("Commessa"); + b.ToTable("Commessa", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.ComuneIstat", b => @@ -226,7 +226,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("ProvinciaIstatId"); - b.ToTable("ComuneIstat"); + b.ToTable("ComuneIstat", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.Feature", b => @@ -275,7 +275,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("SezioneId"); - b.ToTable("Feature"); + b.ToTable("Feature", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.Lavorazione", b => @@ -327,7 +327,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("IdUtenteModifica"); - b.ToTable("Lavorazione"); + b.ToTable("Lavorazione", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.Macchinario", b => @@ -376,7 +376,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("IdUtenteModifica"); - b.ToTable("Macchinario"); + b.ToTable("Macchinario", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.Permission", b => @@ -416,7 +416,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("RuoloId"); - b.ToTable("Permission"); + b.ToTable("Permission", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.ProvinciaIstat", b => @@ -454,7 +454,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("IdUtenteModifica"); - b.ToTable("ProvinciaIstat"); + b.ToTable("ProvinciaIstat", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.Ruolo", b => @@ -488,7 +488,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("IdUtenteModifica"); - b.ToTable("Ruolo"); + b.ToTable("Ruolo", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.Sezione", b => @@ -540,7 +540,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("ParentId"); - b.ToTable("Sezione"); + b.ToTable("Sezione", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.Utente", b => @@ -598,7 +598,7 @@ namespace TecniStamp.Infrastructure.Migrations b.HasIndex("RuoloId"); - b.ToTable("Utente"); + b.ToTable("Utente", (string)null); }); modelBuilder.Entity("TecniStamp.Domain.Cliente", b => diff --git a/TecniStamp/TecniStamp.Service/Interfaces/IManagerService.cs b/TecniStamp/TecniStamp.Service/Interfaces/IManagerService.cs index 1c85580..d82b9d9 100644 --- a/TecniStamp/TecniStamp.Service/Interfaces/IManagerService.cs +++ b/TecniStamp/TecniStamp.Service/Interfaces/IManagerService.cs @@ -3,6 +3,7 @@ public interface IManagerService { IPermissionService PermissionService { get; set; } + IRuoloService RuoloService{ get; set; } ISezioneService SezioneService { get; set; } IUserService UtenteService { get; set; } } \ No newline at end of file diff --git a/TecniStamp/TecniStamp.Service/Interfaces/IRuoloService.cs b/TecniStamp/TecniStamp.Service/Interfaces/IRuoloService.cs new file mode 100644 index 0000000..0caf075 --- /dev/null +++ b/TecniStamp/TecniStamp.Service/Interfaces/IRuoloService.cs @@ -0,0 +1,9 @@ +using OAService.Service.Repository; +using OAService.Service.Servizi.Interfacce; +using TecniStamp.Domain; + +namespace TecniStamp.Service.Interfaces; + +public interface IRuoloService : ITService +{ +} \ No newline at end of file diff --git a/TecniStamp/TecniStamp.Service/ManagerService.cs b/TecniStamp/TecniStamp.Service/ManagerService.cs index c247d03..d9a81bc 100644 --- a/TecniStamp/TecniStamp.Service/ManagerService.cs +++ b/TecniStamp/TecniStamp.Service/ManagerService.cs @@ -4,14 +4,16 @@ namespace TecniStamp.Service; public class ManagerService : IManagerService { - public ManagerService(IUserService userService, ISezioneService sezioneService, IPermissionService permissionService) + public ManagerService(IUserService userService, ISezioneService sezioneService, IPermissionService permissionService, IRuoloService ruoloService) { UtenteService = userService; SezioneService = sezioneService; PermissionService = permissionService; + RuoloService = ruoloService; } public IPermissionService PermissionService { get; set; } + public IRuoloService RuoloService { get; set; } public ISezioneService SezioneService { get; set; } public IUserService UtenteService { get; set; } } \ No newline at end of file diff --git a/TecniStamp/TecniStamp.Service/RuoloService.cs b/TecniStamp/TecniStamp.Service/RuoloService.cs new file mode 100644 index 0000000..3e89a85 --- /dev/null +++ b/TecniStamp/TecniStamp.Service/RuoloService.cs @@ -0,0 +1,13 @@ +using OAService.Service.Servizi.Implementazioni; +using TecniStamp.Domain; +using TecniStamp.Service.Interfaces; +using TecniStamp.Service.Repository; + +namespace TecniStamp.Service; + +public class RuoloService : TService, IRuoloService +{ + public RuoloService(ITecniStampUnitOfWork unitOfWork) : base(unitOfWork) + { + } +} \ No newline at end of file diff --git a/TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatori.razor b/TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatore.razor similarity index 70% rename from TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatori.razor rename to TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatore.razor index 15f5357..3a6de7e 100644 --- a/TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatori.razor +++ b/TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatore.razor @@ -1,6 +1,9 @@ @page "/Anagrafiche/Operatori" @using Microsoft.EntityFrameworkCore @using TecniStamp.Domain +@using TecniStamp.Model + +@rendermode InteractiveServer Operatori @@ -15,7 +18,7 @@
@@ -27,17 +30,14 @@ AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true" Data="@utenti" ColumnWidth="300px" LogicalFilterOperator="LogicalFilterOperator.Or" SelectionMode="DataGridSelectionMode.Single"> - - - - - @* *@ + + + + @@ -52,8 +52,8 @@
@code { - IQueryable utenti; - RadzenDataGrid userGrid; + List utenti; + RadzenDataGrid userGrid; /// /// Carica la lista degli utenti non eliminati, ordinandoli per cognome e nome. @@ -62,10 +62,18 @@ { await base.OnInitializedAsync(); - utenti = await _managerService.UtenteService.RicercaQueryable( + utenti = (await _managerService.UtenteService.RicercaQueryable( x => x.Eliminato == false, includi: x => x.Include(y => y.Ruolo), - ordinamento: x => x.OrderBy(y => y.Cognome).ThenBy(z => z.Nome)); + ordinamento: x => x.OrderBy(y => y.Cognome).ThenBy(z => z.Nome))) + .Select(x => (UserViewModel)x).ToList(); } + /// + /// Apre la pagina di modifica per il cliente selezionato. + /// + private async Task EditRow(UserViewModel cliente) + { + _navManager.NavigateTo($"/Anagrafiche/Operatori/Modifica/{cliente.Id}"); + } } diff --git a/TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatore_Edit.razor b/TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatore_Edit.razor new file mode 100644 index 0000000..e0149af --- /dev/null +++ b/TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Operatore_Edit.razor @@ -0,0 +1,152 @@ +@page "/Anagrafiche/Operatori/Modifica" +@page "/Anagrafiche/Operatori/Modifica/{UserId:guid}" +@using Microsoft.AspNetCore.Identity +@using Microsoft.EntityFrameworkCore +@using TecniStamp.Domain +@using TecniStamp.Model + +@rendermode InteractiveServer + +@pageTitle + +
+ + + + +
+
+
+
+
+
+
+ + + +
+
+
+ Nome + + +
+ +
+ Cognome + + +
+ +
+ Email + + +
+ +
+ Ruolo + +
+
+ +
+
+ Password + +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + +@code { + [Parameter] public Guid? UserId { get; set; } + + public UserViewModel Model { get; set; } = new(); + + private string pageTitle => Model?.Id == Guid.Empty ? "Nuovo operatore" : $"Modifica operatore {Model}"; + private List ruoli { get; set; } = new(); + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + + Model = UserId.GetValueOrDefault() == Guid.Empty + ? new UserViewModel() + : await _managerService.UtenteService.RicercaPer(x => x.Id == UserId, + includi:x => x.Include(y => y.Ruolo)); + + ruoli = (await _managerService.RuoloService.RicercaQueryable(x => x.Eliminato == false)) + .Select(x => (RuoloViewModel)x).ToList(); + } + + /// + /// Salva l’utente: recupera o crea il modello, applica le modifiche dalla UI, + /// gestisce l’hash della password se inserita e registra tutto a database + /// usando l’ID dell’utente autenticato. + /// + private async Task onUtenteSave() + { + var state = await _auth.GetAuthenticationStateAsync(); + var idClaim = state.User.FindFirst("UserId")?.Value; + if (string.IsNullOrEmpty(idClaim)) + { + // gestisci errore (utente non autenticato o claim mancante) + return; + } + + var model = await _managerService.UtenteService.RicercaPer(x => x.Id == Model.Id, solaLettura: false) + ?? new Utente(); + + model = Model.Map(model); + + if (!string.IsNullOrWhiteSpace(Model.Password)) + { + var hasher = new PasswordHasher(); + model.Password = hasher.HashPassword(model, Model.Password); + } + + model.RuoloId = Model.RuoloId; + + await _managerService.UtenteService.Salva(model, Guid.Parse(idClaim)); + _navManager.NavigateTo($"/Anagrafiche/Operatori/Modifica/{Model.Id}"); + } + + /// + /// Torna all’elenco utenti senza applicare altre azioni. + /// + private void backToHome() + { + _navManager.NavigateTo("/Anagrafiche/Operatori"); + } +} \ No newline at end of file diff --git a/TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Ruoli.razor b/TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Ruolo.razor similarity index 100% rename from TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Ruoli.razor rename to TecniStamp/TecniStamp/Components/Pages/Anagrafiche/Ruolo.razor diff --git a/TecniStamp/TecniStamp/Model/BaseViewModel.cs b/TecniStamp/TecniStamp/Model/BaseViewModel.cs new file mode 100644 index 0000000..65c216d --- /dev/null +++ b/TecniStamp/TecniStamp/Model/BaseViewModel.cs @@ -0,0 +1,8 @@ +namespace TecniStamp.Model; + +public abstract class BaseViewModel +{ + public Guid Id { get; set; } + + public abstract void Validate(); +} \ No newline at end of file diff --git a/TecniStamp/TecniStamp/Model/RuoloViewModel.cs b/TecniStamp/TecniStamp/Model/RuoloViewModel.cs new file mode 100644 index 0000000..28dd201 --- /dev/null +++ b/TecniStamp/TecniStamp/Model/RuoloViewModel.cs @@ -0,0 +1,20 @@ +using TecniStamp.Domain; + +namespace TecniStamp.Model; + +public class RuoloViewModel +{ + public Guid Id { get; set; } + public string Nome { get; set; } + + public static implicit operator RuoloViewModel(Ruolo model) + { + return model == null + ? null + : new RuoloViewModel() + { + Nome = model.Nome, + Id = model.Id + }; + } +} \ No newline at end of file diff --git a/TecniStamp/TecniStamp/Model/UserViewModel.cs b/TecniStamp/TecniStamp/Model/UserViewModel.cs new file mode 100644 index 0000000..b2e38df --- /dev/null +++ b/TecniStamp/TecniStamp/Model/UserViewModel.cs @@ -0,0 +1,48 @@ +using TecniStamp.Domain; + +namespace TecniStamp.Model; + +public class UserViewModel : BaseViewModel +{ + public string Username { get; set; } + public string Email { get; set; } + public string Password { get; set; } + public string Nome { get; set; } + public string Cognome { get; set; } + public Guid RuoloId { get; set; } + public string Ruolo { get; set; } + + public override void Validate() + { + } + + public override string ToString() + { + return $"{Nome} {Cognome}"; + } + + public static implicit operator UserViewModel(Utente model) + { + return model == null + ? null + : new UserViewModel() + { + Id = model.Id, + Username = model.Username, + Email = model.Email, + Cognome = model.Cognome, + Nome = model.Nome, + Ruolo = model.Ruolo?.Nome ?? string.Empty, + RuoloId = model.RuoloId.GetValueOrDefault() + }; + } + + public Utente Map(Utente model) + { + model.Nome = Nome; + model.Cognome = Cognome; + model.Email = Email; + + return model; + } +} \ No newline at end of file