maxime.batista 1 year ago
parent 182911eac1
commit 59999e5148

@ -1,7 +1,9 @@
using AdminPanel.Models; using System.Text;
using AdminPanel.Models;
using AdminPanel.Services; using AdminPanel.Services;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.Primitives;
using MudBlazor; using MudBlazor;
namespace AdminPanel.Pages namespace AdminPanel.Pages
@ -31,7 +33,8 @@ namespace AdminPanel.Pages
private async Task<GridData<User>> LoadUsersFromServer(GridState<User> state) private async Task<GridData<User>> LoadUsersFromServer(GridState<User> state)
{ {
Logger.LogDebug($"Loading users from server, state = {state} searchString = {SearchString}"); Logger.LogDebug($"Loading users from server, state = {state} searchString = {SearchString}");
var (count, users) = await Service.ListUsers((uint)(state.Page * state.PageSize), (uint)state.PageSize, SearchString); var (count, users) =
await Service.ListUsers((uint)(state.Page * state.PageSize), (uint)state.PageSize, SearchString);
return new GridData<User> return new GridData<User>
{ {
TotalItems = (int)count, TotalItems = (int)count,
@ -47,10 +50,9 @@ namespace AdminPanel.Pages
{ {
await Service.UpdateUser(user); await Service.UpdateUser(user);
} }
catch (Exception) catch (ServiceException err)
{ {
Snackbar.Add( ShowErrors(err);
"Server responded with errors, your given input may be incorrect.\nIf you entered a new email, verify that the email is not used by another member.");
} }
} }
@ -66,9 +68,25 @@ namespace AdminPanel.Pages
Logger.LogDebug($"Added user : {user}"); Logger.LogDebug($"Added user : {user}");
await Grid.ReloadServerData(); await Grid.ReloadServerData();
} }
catch (Exception) catch (ServiceException err)
{ {
Snackbar.Add("Server responded with errors, your given input may be incorrect."); ShowErrors(err);
}
}
private void ShowErrors(ServiceException e)
{
foreach (var erronedArgument in e.ArgumentMessages)
{
var sb = new StringBuilder(erronedArgument.Key);
sb.Append(" :");
foreach (var message in erronedArgument.Value)
{
sb.Append("\n\t-");
sb.Append(message);
}
Snackbar.Add(sb.ToString());
} }
} }
@ -81,24 +99,23 @@ namespace AdminPanel.Pages
await Service.RemoveUsers(users); await Service.RemoveUsers(users);
await Grid.ReloadServerData(); await Grid.ReloadServerData();
} }
catch (Exception) catch (ServiceException err)
{ {
Snackbar.Add("Server responded with errors"); ShowErrors(err);
} }
} }
private Func<string, string?> VerifyLength(uint min, uint max) private Func<string, string?> VerifyLength(uint min, uint max)
{ {
return s => s.Length >= min && s.Length <= max ? null : $"length is incorrect (must be between {min} and {max})"; return s => s.Length >= min && s.Length <= max
? null
: $"length is incorrect (must be between {min} and {max})";
} }
private void ValidateSearch(KeyboardEventArgs e) private void ValidateSearch(KeyboardEventArgs e)
{
if (e.Key == "Enter")
{ {
Grid.ReloadServerData(); Grid.ReloadServerData();
Logger.LogDebug($"Searching for {SearchString}"); Logger.LogDebug($"Searching for {SearchString}");
} }
} }
}
} }

@ -12,7 +12,7 @@ builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services builder.Services
.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); .AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Logging.SetMinimumLevel(LogLevel.Debug); // builder.Logging.SetMinimumLevel(LogLevel.Debug);
var client = new HttpClient var client = new HttpClient
{ {

@ -1,3 +1,5 @@
using System.Diagnostics;
using System.Net;
using System.Net.Http.Json; using System.Net.Http.Json;
using AdminPanel.Models; using AdminPanel.Models;
@ -12,29 +14,53 @@ public class HttpUsersService : IUsersService
this.Client = client; this.Client = client;
} }
private record ListUsersResponse(List<User> Users, uint TotalCount); private record ServerErrorMessageDto(string? Field, string? Error, string Message);
private async Task EnsureResponseIsOk(HttpResponseMessage response)
{
if (response.StatusCode == HttpStatusCode.OK)
{
return;
}
var content = await response.Content.ReadFromJsonAsync<ServerErrorMessageDto[]>();
var messages = content!
.GroupBy(e => e.Field ?? e.Error!)
.ToDictionary(
g => g.Key,
g => g.ToList().ConvertAll(e => e.Message)
);
throw new ServiceException("Server refused request", messages);
}
private record ListUsersResponseDto(List<User> Users, uint TotalCount);
public async Task<(uint, List<User>)> ListUsers(uint from, uint len, string? searchString = null) public async Task<(uint, List<User>)> ListUsers(uint from, uint len, string? searchString = null)
{ {
var httpResponse = await Client.GetAsync($"/api/admin/list-users?start={from}&n={len}&search={searchString ?? ""}"); var httpResponse =
httpResponse.EnsureSuccessStatusCode(); await Client.GetAsync($"/api/admin/list-users?start={from}&n={len}&search={searchString ?? ""}");
await EnsureResponseIsOk(httpResponse);
var response = await httpResponse.Content.ReadFromJsonAsync<ListUsersResponse>() var response = await httpResponse.Content.ReadFromJsonAsync<ListUsersResponseDto>()
?? throw new Exception("Received non-parseable json from server"); ?? throw new Exception("Received non-parseable json from server");
return (response.TotalCount, response.Users); return (response.TotalCount, response.Users);
} }
private record AddUserRequest(string Username, string Email, string Password, bool IsAdmin); private record AddUserRequestDto(string Username, string Email, string Password, bool IsAdmin);
private record AddUserResponse(uint Id); private record AddUserResponseDto(uint Id);
public async Task<User> AddUser(string username, string email, string password, bool isAdmin) public async Task<User> AddUser(string username, string email, string password, bool isAdmin)
{ {
var httpResponse = await Client.PostAsJsonAsync("/api/admin/user/add", new AddUserRequest(username, email, password, isAdmin)); var httpResponse = await Client.PostAsJsonAsync("/api/admin/user/add",
httpResponse.EnsureSuccessStatusCode(); new AddUserRequestDto(username, email, password, isAdmin));
var response = await httpResponse.Content.ReadFromJsonAsync<AddUserResponse>() await EnsureResponseIsOk(httpResponse);
var response = await httpResponse.Content.ReadFromJsonAsync<AddUserResponseDto>()
?? throw new Exception("Received non-parseable json from server"); ?? throw new Exception("Received non-parseable json from server");
return new User return new User
@ -46,19 +72,22 @@ public class HttpUsersService : IUsersService
}; };
} }
private record RemoveUsersRequest(uint[] Identifiers); private record RemoveUsersRequestDto(uint[] Identifiers);
public async Task RemoveUsers(IEnumerable<uint> userIds) public async Task RemoveUsers(IEnumerable<uint> userIds)
{ {
var httpResponse = await Client.PostAsJsonAsync("/api/admin/user/remove-all", new RemoveUsersRequest(userIds.ToArray())); var httpResponse =
httpResponse.EnsureSuccessStatusCode(); await Client.PostAsJsonAsync("/api/admin/user/remove-all", new RemoveUsersRequestDto(userIds.ToArray()));
await EnsureResponseIsOk(httpResponse);
} }
private record UpdateUserRequest(string Email, string Username, bool IsAdmin); private record UpdateUserRequestDto(string Email, string Username, bool IsAdmin);
public async Task UpdateUser(User user) public async Task UpdateUser(User user)
{ {
var httpResponse = await Client.PostAsJsonAsync($"/api/admin/user/{user.Id}/update", new UpdateUserRequest(user.Email, user.Name, user.IsAdmin)); var httpResponse = await Client.PostAsJsonAsync($"/api/admin/user/{user.Id}/update",
httpResponse.EnsureSuccessStatusCode(); new UpdateUserRequestDto(user.Email, user.Name, user.IsAdmin));
await EnsureResponseIsOk(httpResponse);
} }
} }

@ -0,0 +1,18 @@
namespace AdminPanel.Services;
class ServiceException : Exception
{
public Dictionary<string, List<string>> ArgumentMessages { get; init; }
public ServiceException(string? message, Dictionary<string, List<string>> arguments) : base(message)
{
ArgumentMessages = arguments;
}
public ServiceException(string? message, Dictionary<string, List<string>> arguments, Exception? innerException) : base(message, innerException)
{
ArgumentMessages = arguments;
}
}
Loading…
Cancel
Save