Edit utenti

This commit is contained in:
2025-12-02 12:06:07 +01:00
parent 7b5973330f
commit f9081e6fe7
9 changed files with 242 additions and 24 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -11,10 +11,7 @@
@using System.Security.Claims
@using StandManager.Service.Interfaces
@inject StandManagerDbContext dbContext
@inject NavigationManager navi
@inject IHttpContextAccessor HttpContextAccessor
@inject IManagerService _managerService
<div class="page page-center">
<div class="container container-tight py-4">
@ -79,12 +76,13 @@
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Email),
new Claim(ClaimTypes.Role, "Admin")
new Claim(ClaimTypes.Role, "Admin"),
new Claim("UserId", user.Id.ToString())
};
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await httpContext.SignInAsync(principal);
navi.NavigateTo("/management/dashboard");
_navManager.NavigateTo("/management/dashboard");
}
}

View File

@ -1,24 +1,61 @@
@page "/management/Utenti"
@using Microsoft.AspNetCore.Authorization
@using StandManager.Domain.Entita
@using StandManager.Service.Interfaces
@inject IManagerService _managerService
@attribute [Authorize]
<h3>Utenti</h3>
@attribute [Authorize]
@page "/management/Utenti"
@rendermode InteractiveServer
<PageTitle>Utenti</PageTitle>
<RadzenDataGrid AllowFiltering="true" AllowColumnResize="true" AllowAlternatingRows="false" FilterMode="FilterMode.CheckBoxList" AllowSorting="true" PageSize="5" AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true"
Data="@utenti" ColumnWidth="300px" LogicalFilterOperator="LogicalFilterOperator.Or" SelectionMode="DataGridSelectionMode.Single">
<Columns>
<RadzenDataGridColumn Property="@nameof(Utente.Id)" Filterable="false" Title="ID" Width="80px" TextAlign="TextAlign.Center" />
<RadzenDataGridColumn Property="@nameof(Utente.Nome)" Title="First Name" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Utente.Cognome)" Title="Last Name" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Utente.Email)" Title="Mail" Width="200px" />
</Columns>
</RadzenDataGrid>
<div class="page-wrapper">
<!-- BEGIN PAGE HEADER -->
<div class="page-header d-print-none" aria-label="Page header">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
<h2 class="page-title">Utenti</h2>
</div>
</div>
</div>
</div>
<!-- END PAGE HEADER -->
<!-- BEGIN PAGE BODY -->
<div class="page-body">
<div class="container-xl">
<div class="row row-cards">
<div class="col-lg-12">
<div class="card">
<div class="table-responsive">
<RadzenDataGrid @ref="userGrid" AllowFiltering="true" AllowColumnResize="true" AllowAlternatingRows="false" FilterMode="FilterMode.CheckBoxList" AllowSorting="true" PageSize="5"
AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true"
Data="@utenti" ColumnWidth="300px" LogicalFilterOperator="LogicalFilterOperator.Or" SelectionMode="DataGridSelectionMode.Single">
<Columns>
<RadzenDataGridColumn Property="@nameof(Utente.Id)" Filterable="false" Title="ID" Width="80px" TextAlign="TextAlign.Center" />
<RadzenDataGridColumn Property="@nameof(Utente.Nome)" Title="First Name" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Utente.Cognome)" Title="Last Name" Width="160px" />
<RadzenDataGridColumn Property="@nameof(Utente.Email)" Title="Mail" Width="200px" />
<RadzenDataGridColumn Context="order" Filterable="false" Sortable="false" TextAlign="TextAlign.Right">
<Template Context="user">
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="rz-my-1 rz-ms-1" Click="@(args => EditRow(user))" @onclick:stopPropagation="true" />
<RadzenButton Icon="delete" ButtonStyle="ButtonStyle.Danger" Variant="Variant.Flat" Size="ButtonSize.Medium" Shade="Shade.Lighter" class="rz-my-1 rz-ms-1" Click="@(args => DeleteRow(user))" @onclick:stopPropagation="true" />
</Template>
<EditTemplate Context="user">
<RadzenButton Icon="check" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Size="ButtonSize.Medium" Click="@((args) => SaveRow(user))" aria-label="Save" />
<RadzenButton Icon="close" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" Size="ButtonSize.Medium" class="rz-my-1 rz-ms-1" Click="@((args) => CancelEdit(user))" aria-label="Cancel" />
<RadzenButton Icon="delete" ButtonStyle="ButtonStyle.Danger" Variant="Variant.Flat" Size="ButtonSize.Medium" Shade="Shade.Lighter" class="rz-my-1 rz-ms-1" Click="@(args => DeleteRow(user))" aria-label="Delete" />
</EditTemplate>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@code {
IQueryable<Utente> utenti;
RadzenDataGrid<Utente> userGrid;
protected override async Task OnInitializedAsync()
{
@ -26,4 +63,24 @@
utenti = await _managerService.UtenteService.RicercaQueryable(x => x.Eliminato == false);
}
private async Task EditRow(Utente user)
{
_navManager.NavigateTo($"/management/Utenti/Modifica/{user.Id}");
}
private async Task DeleteRow(Utente user)
{
}
private async Task SaveRow(Utente user)
{
}
private async Task CancelEdit(Utente user)
{
}
}

View File

@ -0,0 +1,117 @@
@attribute [Authorize]
@rendermode InteractiveServer
@page "/management/Utenti/Modifica"
@page "/management/Utenti/Modifica/{UserId:guid}"
@using Microsoft.AspNetCore.Identity
@using StandManager.Model
@inject AuthenticationStateProvider auth
<PageTitle>@pageTitle</PageTitle>
<div class="page-wrapper">
<!-- BEGIN PAGE HEADER -->
<div class="page-header d-print-none" aria-label="Page header">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
<h2 class="page-title">@pageTitle</h2>
</div>
</div>
</div>
</div>
<!-- END PAGE HEADER -->
<!-- BEGIN PAGE BODY -->
<div class="page-body">
<div class="container-xl">
<div class="row row-cards">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<div class="row g-5">
<EditForm Model="utente" OnValidSubmit="onUtenteSave" FormName="editUserForm">
<DataAnnotationsValidator />
<div class="col-12">
<div class="row">
<div class="col-4 mb-3">
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Nome</RadzenText>
<RadzenTextBox Style="width: 100%" aria-label="Nome" @bind-Value="@utente.Nome" />
</div>
<div class="col-4 mb-3">
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Cognome</RadzenText>
<RadzenTextBox Style="width: 100%" aria-label="Cognome" @bind-Value="@utente.Cognome" />
</div>
<div class="col-4 mb-3">
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Email</RadzenText>
<RadzenTextBox Style="width: 100%" aria-label="Email" @bind-Value="@utente.Email" />
</div>
</div>
<div class="row">
<div class="col-4 mb-3">
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Password</RadzenText>
<RadzenPassword Style="width: 100%" aria-label="Password" @bind-Value="@utente.Password" />
</div>
</div>
<div class="row">
<div class="col-4 mb-3">
<button type="submit" class="btn btn-primary w-100">
Salva
</button>
</div>
</div>
</div>
</EditForm>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@code {
[Parameter]
public Guid? UserId { get; set; }
[SupplyParameterFromForm]
private UtenteViewModel? utente { get; set; }
private string pageTitle => utente?.Id == Guid.Empty ? "Nuovo utente" : "Modifica utente";
protected override async Task OnInitializedAsync()
{
utente ??= await _managerService.UtenteService.RicercaPer(x => x.Id == UserId);
}
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 == utente.Id, solaLettura: false)
?? new Utente();
model = utente.Map(model);
if (!string.IsNullOrWhiteSpace(utente.Password))
{
var hasher = new PasswordHasher<Utente>();
model.Password = hasher.HashPassword(model, utente.Password);
}
await _managerService.UtenteService.Salva(model, Guid.Parse(idClaim));
_navManager.NavigateTo("/management/Utenti");
}
}

View File

@ -9,6 +9,12 @@
@using Microsoft.JSInterop
@using StandManager
@using StandManager.Components
@using Microsoft.AspNetCore.Authorization
@using StandManager.Domain.Entita
@using StandManager.Service.Interfaces
@using Radzen
@using Radzen.Blazor
@inject IManagerService _managerService
@inject NavigationManager _navManager

View File

@ -0,0 +1,40 @@
using StandManager.Domain.Entita;
using System.ComponentModel.DataAnnotations;
namespace StandManager.Model
{
public class UtenteViewModel
{
public Guid Id { get; set; }
public string Username { get; set; }
//[Required]
//[EmailAddress(ErrorMessage = "Email non valida")]
public string Email { get; set; }
public string Password { get; set; }
//[Required(ErrorMessage ="Il nome è obbligatorio")]
public string Nome { get; set; }
//[Required(ErrorMessage = "Il cognome è obbligatorio")]
public string Cognome { get; set; }
public static implicit operator UtenteViewModel(Utente? model)
{
return model == null ? null : new UtenteViewModel
{
Id = model.Id,
Username = model.Username,
Email = model.Email,
Nome = model.Nome,
Cognome = model.Cognome
};
}
public Utente Map(Utente model)
{
model.Nome = Nome;
model.Cognome = Cognome;
model.Email = Email;
return model;
}
}
}

View File

@ -84,11 +84,11 @@ else
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAntiforgery();
app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();