Add teams administration panel #3
Merged
maxime.batista
merged 4 commits from teams
into master
1 year ago
@ -0,0 +1,6 @@
|
||||
namespace AdminPanel.Models;
|
||||
|
||||
public record Team(uint Id, string Name, string Picture, string MainColor, string SecondColor)
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
using System.Text;
|
||||
using AdminPanel.Services;
|
||||
using MudBlazor;
|
||||
|
||||
namespace AdminPanel.Pages;
|
||||
|
||||
public class DisplayUtils
|
||||
{
|
||||
public static void ShowErrors(ServiceException e, ISnackbar snackbar)
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,106 @@
|
||||
@page "/teams"
|
||||
@using AdminPanel.Models
|
||||
@using DataGridEditMode = MudBlazor.DataGridEditMode
|
||||
|
||||
|
||||
<PageTitle>Teams Panel</PageTitle>
|
||||
|
||||
<h3>TeamListPanel</h3>
|
||||
<h1>Team Panel</h1>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
||||
<MudPopover Open="@_isOpenAdd" Fixed="true" Class="px-4 pt-4">
|
||||
<div class="d-flex flex-column">
|
||||
<MudForm @bind-IsValid="@_success" @bind-Errors="@_errors">
|
||||
<MudTextField
|
||||
T="string"
|
||||
Label="Name"
|
||||
Required="true"
|
||||
@bind-Value="FormName"
|
||||
RequiredError="Team's name is required!" />
|
||||
<MudTextField
|
||||
T="string"
|
||||
Label="Picture"
|
||||
Required="true"
|
||||
@bind-Value="FormPicture"
|
||||
RequiredError="Picture is required!"/>
|
||||
<MudTextField
|
||||
T="string"
|
||||
Label="MainColor"
|
||||
Required="true"
|
||||
@bind-Value="FormMainColor"
|
||||
RequiredError="Main color is required!"/>
|
||||
<MudTextField
|
||||
T="string"
|
||||
Label="SecondaryColor"
|
||||
Required="true"
|
||||
@bind-Value="FormSecondaryColor"
|
||||
RequiredError="Secondary color is required!"/>
|
||||
<div class="d-flex justify-center">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@AddTeamConfirmed" Class="ml-auto">Apply</MudButton>
|
||||
</div>
|
||||
</MudForm>
|
||||
<MudButton OnClick="@ToggleOpen" Class="ml-auto mr-n3 mb-1" Color="Color.Error">Close</MudButton>
|
||||
</div>
|
||||
</MudPopover>
|
||||
|
||||
<MudCard>
|
||||
<ToolBarContent style="display: flex; justify-content: space-evenly;">
|
||||
<!--<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@ToggleOpen">Ajouter</MudButton>-->
|
||||
<div style="display: flex; align-items: center">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Add" OnClick="@ToggleOpen" Color="@Color.Success"/>
|
||||
<MudText>Add Team</MudText>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Remove" OnClick="@ToggleOpenConfirmation" Color="@Color.Error"/>
|
||||
<MudText>Remove selection</MudText>
|
||||
</div>
|
||||
<!--<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@ToggleOpenConfirmation">Supprimer</MudButton>-->
|
||||
<MudSpacer/>
|
||||
<MudText>Teams</MudText>
|
||||
<MudSpacer/>
|
||||
</ToolBarContent>
|
||||
</MudCard>
|
||||
|
||||
|
||||
<MudPopover Open="@_isOpenConf" Fixed="true" Class="px-4 pt-4">
|
||||
<div class="d-flex flex-column">
|
||||
<Content>
|
||||
<p>Are you sure you want to delete this team(s)?</p>
|
||||
</Content>
|
||||
<Footer>
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Default" OnClick="@DeleteSelectedTeams">Confirm</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Default" OnClick="@CloseToggleConf">Close</MudButton>
|
||||
</Footer>
|
||||
</div>
|
||||
</MudPopover>
|
||||
|
||||
<MudDataGrid
|
||||
T="Team"
|
||||
RowsPerPage="4"
|
||||
ServerData="GetTeamsFromServer"
|
||||
@ref="Grid"
|
||||
MultiSelection="true"
|
||||
@bind-SelectedItems="SelectedTeams"
|
||||
ReadOnly="false"
|
||||
EditMode="DataGridEditMode.Form"
|
||||
CommittedItemChanges="OnTeamUpdated">
|
||||
<Columns>
|
||||
<SelectColumn T="Team"/>
|
||||
<PropertyColumn
|
||||
Property="x => x.Name"/>
|
||||
<PropertyColumn
|
||||
Property="x => x.MainColor"/>
|
||||
<PropertyColumn
|
||||
Property="x => x.SecondColor"/>
|
||||
<PropertyColumn
|
||||
Property="x => x.Picture"/>
|
||||
<TemplateColumn>
|
||||
<CellTemplate>
|
||||
<MudIconButton Size="Size.Small" Icon="@Icons.Material.Outlined.Edit" OnClick="@context.Actions.StartEditingItemAsync"/>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
<PagerContent>
|
||||
<MudDataGridPager T="Team" PageSizeOptions="new[] { 1, 2, 4, 10, 25, 50, 100 }"/>
|
||||
</PagerContent>
|
||||
</MudDataGrid>
|
||||
|
@ -0,0 +1,109 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text;
|
||||
using AdminPanel.Models;
|
||||
using AdminPanel.Services;
|
||||
using Blazorise.Extensions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using MudBlazor;
|
||||
|
||||
namespace AdminPanel.Pages;
|
||||
|
||||
public partial class TeamListPanel
|
||||
{
|
||||
[Inject] private ISnackbar Snackbar { get; init; }
|
||||
[Inject] private ITeamService TeamService { get; init; }
|
||||
private bool _isOpenAdd;
|
||||
private bool _isOpenConf;
|
||||
private bool _success;
|
||||
private string[] _errors = { };
|
||||
|
||||
[StringLength(1,ErrorMessage = "Nombre de caractères minimal : 1 ")]
|
||||
private string? FormName { get; set; }
|
||||
|
||||
[RegularExpression(@"(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})?", ErrorMessage = "L'image doit être le lien d'une image sur le web")]
|
||||
private string? FormPicture { get; set; }
|
||||
|
||||
[RegularExpression(@"(/#[0-9a-f]{6})",ErrorMessage = "La couleur principale doit être un code hexadécimal")]
|
||||
private string? FormMainColor { get; set; }
|
||||
|
||||
[RegularExpression(@"(/#[0-9a-f]{6})",ErrorMessage = "La couleur secondaire doit être un code hexadécimal")]
|
||||
private string? FormSecondaryColor { get; set; }
|
||||
private MudDataGrid<Team>? Grid { get; set; }
|
||||
private HashSet<Team> SelectedTeams { get; set; } = new();
|
||||
|
||||
private void UnBindForm()
|
||||
{
|
||||
FormName = null;
|
||||
FormPicture = null;
|
||||
FormMainColor = null;
|
||||
FormSecondaryColor = null;
|
||||
}
|
||||
|
||||
private async Task<GridData<Team>> GetTeamsFromServer(GridState<Team> state)
|
||||
{
|
||||
var (count, teams) = await TeamService.ListTeam((uint)(state.Page * state.PageSize), (uint)state.PageSize);
|
||||
return new GridData<Team>
|
||||
{
|
||||
TotalItems = (int)count,
|
||||
Items = teams
|
||||
};
|
||||
}
|
||||
|
||||
private void ToggleOpen()
|
||||
{
|
||||
_isOpenAdd = !(_isOpenAdd);
|
||||
}
|
||||
|
||||
private void ToggleOpenConfirmation()
|
||||
{
|
||||
_isOpenConf = !(_isOpenConf);
|
||||
}
|
||||
|
||||
private async Task AddTeam()
|
||||
{
|
||||
try
|
||||
{
|
||||
await TeamService.AddTeam(FormName!, FormPicture!, FormMainColor!, FormSecondaryColor!);
|
||||
}
|
||||
catch (ServiceException err)
|
||||
{
|
||||
DisplayUtils.ShowErrors(err,Snackbar);
|
||||
}
|
||||
}
|
||||
|
||||
private async void AddTeamConfirmed()
|
||||
{
|
||||
await AddTeam();
|
||||
ToggleOpen();
|
||||
await Grid!.ReloadServerData();
|
||||
UnBindForm();
|
||||
}
|
||||
|
||||
private async void DeleteSelectedTeams()
|
||||
{
|
||||
if (!SelectedTeams.IsNullOrEmpty())
|
||||
{
|
||||
var ids = SelectedTeams.ToList().ConvertAll(team => team.Id);
|
||||
await TeamService.DeleteTeams(ids);
|
||||
await Grid!.ReloadServerData();
|
||||
}
|
||||
CloseToggleConf();
|
||||
}
|
||||
|
||||
private void CloseToggleConf()
|
||||
{
|
||||
_isOpenConf = false;
|
||||
}
|
||||
|
||||
private async void OnTeamUpdated(Team t)
|
||||
{
|
||||
try
|
||||
{
|
||||
await TeamService.UpdateTeam(t);
|
||||
}
|
||||
catch (ServiceException err)
|
||||
{
|
||||
DisplayUtils.ShowErrors(err,Snackbar);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace AdminPanel.Services;
|
||||
|
||||
public class ErrorsUtils
|
||||
{
|
||||
private record ServerErrorMessageDto(string? Field, string? Error, string Message);
|
||||
|
||||
public static 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);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
using System.Net.Http.Json;
|
||||
using AdminPanel.Models;
|
||||
|
||||
namespace AdminPanel.Services;
|
||||
|
||||
public class HttpTeamService : ITeamService
|
||||
{
|
||||
|
||||
private readonly HttpClient _client;
|
||||
|
||||
public HttpTeamService(HttpClient client)
|
||||
{
|
||||
this._client = client;
|
||||
}
|
||||
|
||||
private record ListTeamResponse(uint TotalCount, List<Team> Teams);
|
||||
|
||||
public async Task<(uint, List<Team>)> ListTeam(uint from, uint count)
|
||||
{
|
||||
var httpResponse = await _client.GetAsync($"/api/admin/list-team?start={from}&n={count}");
|
||||
httpResponse.EnsureSuccessStatusCode();
|
||||
var response = await httpResponse.Content.ReadFromJsonAsync<ListTeamResponse>()!;
|
||||
|
||||
return (response.TotalCount, response.Teams);
|
||||
}
|
||||
|
||||
private record AddTeamDTORequest(string Name, string Picture, string MainColor, string SecondaryColor);
|
||||
|
||||
public async Task AddTeam(string name, string picture, string mainColor, string secondaryColor)
|
||||
{
|
||||
var httpResponse = await _client.PostAsJsonAsync($"/api/admin/add-team", new AddTeamDTORequest(name,picture,mainColor,secondaryColor));
|
||||
await ErrorsUtils.EnsureResponseIsOk(httpResponse);
|
||||
}
|
||||
|
||||
private record DeleteTeamsDTORequest(List<uint> Teams);
|
||||
public async Task DeleteTeams(List<uint> teams)
|
||||
{
|
||||
var httpResponse = await _client.PostAsJsonAsync($"/api/admin/delete-teams", new DeleteTeamsDTORequest(teams));
|
||||
await ErrorsUtils.EnsureResponseIsOk(httpResponse);
|
||||
|
||||
}
|
||||
|
||||
private record UpdateTeamDTORequest(uint Id, string Name, string Picture, string MainColor, string SecondaryColor);
|
||||
public async Task UpdateTeam(Team team)
|
||||
{
|
||||
var httpResponse = await _client.PostAsJsonAsync($"/api/admin/team/{team.Id}/update",
|
||||
new UpdateTeamDTORequest(team.Id, team.Name, team.Picture, team.MainColor, team.SecondColor) );
|
||||
await ErrorsUtils.EnsureResponseIsOk(httpResponse);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
using AdminPanel.Models;
|
||||
|
||||
namespace AdminPanel.Services;
|
||||
|
||||
public interface ITeamService
|
||||
{
|
||||
public Task<(uint, List<Team>)> ListTeam(uint from, uint count);
|
||||
public Task AddTeam(string name, string picture, string mainColor, string secondaryColor);
|
||||
public Task DeleteTeams(List<uint> teams);
|
||||
public Task UpdateTeam(Team team);
|
||||
|
||||
}
|
Loading…
Reference in new issue