Connexion + Tab dans des pages

WORK-KMO
Antoine PINAGOT 1 year ago
parent a098e11154
commit 2449c27f4e

@ -1,4 +1,4 @@
<Router AppAssembly="@typeof(App).Assembly"> @* <Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData"> <Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" /> <FocusOnNavigate RouteData="@routeData" Selector="h1" />
@ -9,5 +9,17 @@
<p role="alert">Sorry, there's nothing at this address.</p> <p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView> </LayoutView>
</NotFound> </NotFound>
</Router> </Router> *@
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
</Router>

@ -7,10 +7,16 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Blazored.LocalStorage" Version="4.4.0" />
<PackageReference Include="Blazorise.Bootstrap" Version="1.4.0" /> <PackageReference Include="Blazorise.Bootstrap" Version="1.4.0" />
<PackageReference Include="Blazorise.DataGrid" Version="1.4.0" /> <PackageReference Include="Blazorise.DataGrid" Version="1.4.0" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.4.0" /> <PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Components\" />
</ItemGroup>
</Project> </Project>

@ -0,0 +1,9 @@
namespace HeartTrack.Models
{
public class AppUser
{
public string Password { get; set; }
public List<string> Roles { get; set; }
public string UserName { get; set; }
}
}

@ -0,0 +1,9 @@
namespace HeartTrack.Models
{
public class CurrentUser
{
public Dictionary<string, string> Claims { get; set; }
public bool IsAuthenticated { get; set; }
public string UserName { get; set; }
}
}

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace HeartTrack.Models
{
public class LoginRequest
{
[Required]
public string Password { get; set; }
[Required]
public string UserName { get; set; }
}
}

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
namespace HeartTrack.Models
{
public class RegisterRequest
{
[Required]
public string Password { get; set; }
[Required]
[Compare(nameof(Password), ErrorMessage = "Passwords do not match!")]
public string PasswordConfirm { get; set; }
[Required]
public string UserName { get; set; }
}
}

@ -0,0 +1,13 @@
namespace HeartTrack.Models
{
public class Ticket
{
public int Id { get; set; }
public string Username { get; set; }
public string Nom { get; set; }
public string Prenom { get; set; }
public string Contexte { get; set; }
public string Description { get; set; }
public string Urgence { get; set; }
}
}

@ -0,0 +1,33 @@
using Blazorise;
using System.ComponentModel.DataAnnotations;
namespace HeartTrack.Models
{
public class TicketModel
{
[Required]
[Range(0, 121425711425541)]
public int Id { get; set; }
[Required]
[StringLength(50, ErrorMessage = "The username must not exceed 50 characters.")]
public string Username { get; set; }
[Required]
[StringLength(50, ErrorMessage = "The name must not exceed 50 characters.")]
public string Nom { get; set; }
[Required]
[StringLength(25, ErrorMessage = "The last name must not exceed 25 characters.")]
public string Prenom { get; set; }
[Required]
[StringLength(25, ErrorMessage = "The subject must not exceed 25 characters.")]
public string Contexte { get; set; }
[Required]
[StringLength(500, ErrorMessage = "Description must not exceed 500 characters.")]
public string Description { get; set; }
public Boolean Urgence { get; set; }
public Image Image { get; set; }
}
}

@ -12,5 +12,6 @@
public float Taille { get; set; } public float Taille { get; set; }
public float Poids { get; set; } public float Poids { get; set; }
public DateTime BirthDate { get; set; } public DateTime BirthDate { get; set; }
public Boolean isBan { get; set; }
} }
} }

@ -0,0 +1,39 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace HeartTrack.Models
{
public class UserModel
{
[Required]
[Range(0,121425711425541)]
public int Id { get; set; }
[Required]
[StringLength(50, ErrorMessage = "The username must not exceed 50 characters.")]
public string Username { get; set; }
[Required]
[StringLength(50, ErrorMessage = "The name must not exceed 50 characters.")]
[RegularExpression(@"^[A-Za-z]$", ErrorMessage = "Numbers are not accepted.")]
public string FirstName { get; set; }
[Required]
[StringLength(25, ErrorMessage = "The last name must not exceed 25 characters.")]
[RegularExpression(@"^[A-Za-z]*$", ErrorMessage = "Numbers are not accepted.")]
public string LastName { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string Sexe { get; set; }
[Required]
public float Taille { get; set; }
[Required]
public float Poids { get; set; }
[Required]
public DateTime BirthDate { get; set; }
public Boolean isBan { get; set; }
}
}

@ -0,0 +1,16 @@
@page "/tickets/add"
<h3>Add Ticket</h3>
@*<EditForm Model="@TicketModel" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<p>
<label>
<InputCheckbox @bind-Value="ticketModel.Urgence" Value="boolean"/>
</label>
</p>
<button type="submit">Submit</button>
</EditForm>*@

@ -0,0 +1,107 @@
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components;
using HeartTrack.Models;
namespace HeartTrack.Pages
{
public partial class AddTicket
{
[Inject]
public ILocalStorageService LocalStorage { get; set; }
[Inject]
public IWebHostEnvironment WebHostEnvironment { get; set; }
/// <summary>
/// The current item model
/// </summary>
private TicketModel ticketModel = new(){};
/*private async void HandleValidSubmit()
{
// Get the current data
var currentData = await LocalStorage.GetItemAsync<List<Ticket>>("data");
// Simulate the Id
ticketModel.Id = currentData.Max(s => s.Id) + 1;
// Add the item to the current data
currentData.Add(new Ticket
{
Id = ticketModel.Id,
Username = ticketModel.Username,
Nom = ticketModel.Nom,
Prenom = ticketModel.Prenom,
Contexte = ticketModel.Contexte,
Description = ticketModel.Description,
Urgence = ticketModel.Urgence
});
// Save the image
var imagePathInfo = new DirectoryInfo($"{WebHostEnvironment.WebRootPath}/images");
// Check if the folder "images" exist
if (!imagePathInfo.Exists)
{
imagePathInfo.Create();
}
// Determine the image name
var fileName = new FileInfo($"{imagePathInfo}/{itemModel.Name}.png");
// Write the file content
await File.WriteAllBytesAsync(fileName.FullName, itemModel.ImageContent);
// Save the data
await LocalStorage.SetItemAsync("data", currentData);
}
private async Task LoadImage(InputFileChangeEventArgs e)
{
// Set the content of the image to the model
using (var memoryStream = new MemoryStream())
{
await e.File.OpenReadStream().CopyToAsync(memoryStream);
itemModel.ImageContent = memoryStream.ToArray();
}
}
private void OnEnchantCategoriesChange(string item, object checkedValue)
{
if ((bool)checkedValue)
{
if (!itemModel.EnchantCategories.Contains(item))
{
itemModel.EnchantCategories.Add(item);
}
return;
}
if (itemModel.EnchantCategories.Contains(item))
{
itemModel.EnchantCategories.Remove(item);
}
}
private void OnRepairWithChange(string item, object checkedValue)
{
if ((bool)checkedValue)
{
if (!itemModel.RepairWith.Contains(item))
{
itemModel.RepairWith.Add(item);
}
return;
}
if (itemModel.RepairWith.Contains(item))
{
itemModel.RepairWith.Remove(item);
}
}*/
}
}

@ -0,0 +1,3 @@
@page "/admin"
<h3>Admin Page</h3>

@ -1,11 +1,29 @@
@page "/banned-users" @page "/banned-users"
@using HeartTrack.Models
<PageTitle>Banned Users</PageTitle> <PageTitle>Banned Users</PageTitle>
<h1>Banned Users</h1> <h1>Banned Users</h1>
This is banned users list of this website. This is banned users list of this website.
<div>
<NavLink class="btn btn-primary" href="banned-users/add" Match="NavLinkMatch.All">
<i class="fa fa-plus"></i> Ajouter
</NavLink>
</div>
<SurveyPrompt Title="How is Blazor working for you?" /> <SurveyPrompt Title="How is Blazor working for you?" />
<DataGrid TItem="User"
Data="@users"
ReadData="@OnReadData"
TotalItems="@totalUser"
PageSize="10"
ShowPager
Responsive>
<DataGridColumn TItem="User" Field="@nameof(User.Id)" Caption="Id" />
<DataGridColumn TItem="User" Field="@nameof(User.Username)" Caption="@Localizer["Username"]" />
<DataGridColumn TItem="User" Field="@nameof(User.Nom)" Caption="@Localizer["FirstN"]" />
<DataGridColumn TItem="User" Field="@nameof(User.Prenom)" Caption="@Localizer["LastN"]" />
<DataGridColumn Caption="" />
</DataGrid>

@ -0,0 +1,66 @@
using Blazored.LocalStorage;
using Blazorise;
using Blazorise.DataGrid;
using HeartTrack.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
namespace HeartTrack.Pages
{
public partial class BannedUsers
{
private List<User> users;
private int totalUser;
[Inject]
public HttpClient Http { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
[Inject]
public ILocalStorageService LocalStorage { get; set; }
[Inject]
public IStringLocalizer<Tokens> Localizer { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Do not treat this action if is not the first render
if (!firstRender)
{
return;
}
var currentData = await LocalStorage.GetItemAsync<User[]>("data");
// Check if data exist in the local storage
if (currentData == null)
{
// this code add in the local storage the fake data (we load the data sync for initialize the data before load the OnReadData method)
var originalData = Http.GetFromJsonAsync<User[]>($"{NavigationManager.BaseUri}fake-data.json").Result;
await LocalStorage.SetItemAsync("data", originalData);
}
}
private async Task OnReadData(DataGridReadDataEventArgs<User> e)
{
if (e.CancellationToken.IsCancellationRequested)
{
return;
}
// When you use a real API, we use this follow code
//var response = await Http.GetJsonAsync<Data[]>( $"http://my-api/api/data?page={e.Page}&pageSize={e.PageSize}" );
var response = (await LocalStorage.GetItemAsync<User[]>("data")).Skip((e.Page - 1) * e.PageSize).Take(e.PageSize).ToList();
if (!e.CancellationToken.IsCancellationRequested)
{
totalUser = (await LocalStorage.GetItemAsync<List<User>>("data")).Count;
users = new List<User>(response); // an actual data for the current page
}
}
}
}

@ -1,49 +0,0 @@
@page "/fetchdata"
<PageTitle>Weather forecast</PageTitle>
@using HeartTrack.Data
@inject WeatherForecastService ForecastService
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from a service.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}

@ -1,7 +1,7 @@
@page "/" @page "/"
@using System.Globalization @using System.Globalization
<PageTitle>Global View</PageTitle> @* <PageTitle>Global View</PageTitle>
<h1>Global View</h1> <h1>Global View</h1>
@ -12,5 +12,28 @@ Actual language:
<b>CurrentCulture</b>: @CultureInfo.CurrentCulture <b>CurrentCulture</b>: @CultureInfo.CurrentCulture
</p> </p>
<SurveyPrompt Title="How is Blazor working for you?" /> <SurveyPrompt Title="How is Blazor working for you?" /> *@
<AuthorizeView>
<Authorized>
<h1>Hello @context.User.Identity.Name !!</h1>
<p>Welcome to Blazor Learner.</p>
<ul>
@foreach (var claim in context.User.Claims)
{
<li>@claim.Type: @claim.Value</li>
}
</ul>
</Authorized>
<Authorizing>
<h1>Loading ...</h1>
</Authorizing>
<NotAuthorized>
<h1>Authentication Failure!</h1>
<p>You're not signed in.</p>
</NotAuthorized>
</AuthorizeView>

@ -0,0 +1,26 @@
@page "/login"
@layout AuthLayout
<h1 class="h2 font-weight-normal login-title">
Login
</h1>
<EditForm class="form-signin" OnValidSubmit="OnSubmit" Model="loginRequest">
<DataAnnotationsValidator />
<label for="inputUsername" class="sr-only">User Name</label>
<InputText id="inputUsername" class="form-control" @bind-Value="loginRequest.UserName" autofocus placeholder="Username" />
<ValidationMessage For="@(() => loginRequest.UserName)" />
<label for="inputPassword" class="sr-only">Password</label>
<InputText type="password" id="inputPassword" class="form-control" placeholder="Password" @bind-Value="loginRequest.Password" />
<ValidationMessage For="@(() => loginRequest.Password)" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<label class="text-danger">@error</label>
<NavLink href="register">
<h6 class="font-weight-normal text-center">Create account</h6>
</NavLink>
</EditForm>

@ -0,0 +1,32 @@
using HeartTrack.Models;
using HeartTrack.Services;
using Microsoft.AspNetCore.Components;
namespace HeartTrack.Pages
{
public partial class Login
{
[Inject]
public CustomStateProvider AuthStateProvider { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
private string error { get; set; }
private LoginRequest loginRequest { get; set; } = new LoginRequest();
private async Task OnSubmit()
{
error = null;
try
{
await AuthStateProvider.Login(loginRequest);
NavigationManager.NavigateTo("");
}
catch (Exception ex)
{
error = ex.Message;
}
}
}
}

@ -0,0 +1,29 @@
@page "/register"
@layout AuthLayout
<h1 class="h2 font-weight-normal login-title">
Register
</h1>
<EditForm class="form-signin" OnValidSubmit="OnSubmit" Model="registerRequest">
<DataAnnotationsValidator />
<label for="inputUsername" class="sr-only">User Name</label>
<InputText id="inputUsername" class="form-control" placeholder="Username" autofocus @bind-Value="@registerRequest.UserName" />
<ValidationMessage For="@(() => registerRequest.UserName)" />
<label for="inputPassword" class="sr-only">Password</label>
<InputText type="password" id="inputPassword" class="form-control" placeholder="Password" @bind-Value="@registerRequest.Password" />
<ValidationMessage For="@(() => registerRequest.Password)" />
<label for="inputPasswordConfirm" class="sr-only">Password Confirmation</label>
<InputText type="password" id="inputPasswordConfirm" class="form-control" placeholder="Password Confirmation" @bind-Value="@registerRequest.PasswordConfirm" />
<ValidationMessage For="@(() => registerRequest.PasswordConfirm)" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Create account</button>
<label class="text-danger">@error</label>
<NavLink href="login">
<h6 class="font-weight-normal text-center">Already have an account? Click here to login</h6>
</NavLink>
</EditForm>

@ -0,0 +1,32 @@
using HeartTrack.Models;
using HeartTrack.Services;
using Microsoft.AspNetCore.Components;
namespace HeartTrack.Pages
{
public partial class Register
{
[Inject]
public CustomStateProvider AuthStateProvider { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
private string error { get; set; }
private RegisterRequest registerRequest { get; set; } = new RegisterRequest();
private async Task OnSubmit()
{
error = null;
try
{
await AuthStateProvider.Register(registerRequest);
NavigationManager.NavigateTo("");
}
catch (Exception ex)
{
error = ex.Message;
}
}
}
}

@ -0,0 +1,20 @@
@page "/test"
<div class="text-center bg-blue-100">
<input class="border-4 w-1/3 rounded m-6 p-6 h-8
border-blue-300" @bind-value="SearchText"
@bind-value:event="oninput" placeholder="Search by title" />
</div>
@if (!Users.Any())
{
<p>Loading some images...</p>
}
else
{
<div class="p-2 grid grid-cols-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3">
@foreach (var user in FilteredUsers)
{
<p>feur</p>
}
</div>
}

@ -0,0 +1,28 @@
using Blazorise;
using HeartTrack.Models;
using HeartTrack.Services;
using Microsoft.AspNetCore.Components;
namespace HeartTrack.Pages
{
partial class Test : ComponentBase
{
public IEnumerable<User> Users { get; set; } = new List<User>();
public string SearchText = "";
[Inject]
public IDataService DataService { get; set; }
[Inject]
public IWebHostEnvironment WebHostEnvironment { get; set; }
protected override async Task OnInitializedAsync()
{
Users = await DataService.List(1, 50); ;
}
List<User> FilteredUsers => Users.Where(
user => user.Username.ToLower().Contains(SearchText.ToLower())).ToList();
}
}

@ -7,6 +7,9 @@ using Blazorise.Icons.FontAwesome;
using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Localization;
using System.Globalization; using System.Globalization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Blazored.LocalStorage;
using HeartTrack.Services;
using Microsoft.AspNetCore.Components.Authorization;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -15,8 +18,17 @@ builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor(); builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>(); builder.Services.AddSingleton<WeatherForecastService>();
// Authentification
builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<CustomStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(s => s.GetRequiredService<CustomStateProvider>());
builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();
builder.Services.AddScoped<IDataService, DataLocalService>();
builder.Services.AddBlazorise() builder.Services.AddBlazorise()
.AddBootstrapProviders() .AddBootstrapProviders()
.AddFontAwesomeIcons(); .AddFontAwesomeIcons();
@ -38,6 +50,8 @@ builder.Services.Configure<RequestLocalizationOptions>(options =>
options.SupportedUICultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("fr-FR") }; options.SupportedUICultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("fr-FR") };
}); });
builder.Services.AddBlazoredLocalStorage();
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.

@ -0,0 +1,57 @@
using HeartTrack.Models;
using System.Security.Claims;
namespace HeartTrack.Services
{
public class AuthService : IAuthService
{
private static readonly List<AppUser> CurrentUser;
static AuthService()
{
CurrentUser = new List<AppUser>
{
new AppUser { UserName = "Jesus", Password = "123456", Roles = new List<string> { "admin" } },
new AppUser { UserName = "Antoine", Password = "123456", Roles = new List<string> { "admin" } },
new AppUser { UserName = "Paul", Password = "123456", Roles = new List<string> { "admin" } },
new AppUser { UserName = "Kevin", Password = "123456", Roles = new List<string> { "admin" } },
new AppUser { UserName = "David", Password = "123456", Roles = new List<string> { "admin" } }
};
}
public CurrentUser GetUser(string userName)
{
var user = CurrentUser.FirstOrDefault(w => w.UserName == userName);
if (user == null)
{
throw new Exception("User name or password invalid !");
}
var claims = new List<Claim>();
claims.AddRange(user.Roles.Select(s => new Claim(ClaimTypes.Role, s)));
return new CurrentUser
{
IsAuthenticated = true,
UserName = user.UserName,
Claims = claims.ToDictionary(c => c.Type, c => c.Value)
};
}
public void Login(LoginRequest loginRequest)
{
var user = CurrentUser.FirstOrDefault(w => w.UserName == loginRequest.UserName && w.Password == loginRequest.Password);
if (user == null)
{
throw new Exception("User name or password invalid !");
}
}
public void Register(RegisterRequest registerRequest)
{
CurrentUser.Add(new AppUser { UserName = registerRequest.UserName, Password = registerRequest.Password, Roles = new List<string> { "guest" } });
}
}
}

@ -0,0 +1,75 @@
using HeartTrack.Models;
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
namespace HeartTrack.Services
{
public class CustomStateProvider : AuthenticationStateProvider
{
private readonly IAuthService _authService;
private CurrentUser _currentUser;
public CustomStateProvider(IAuthService authService)
{
this._authService = authService;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var identity = new ClaimsIdentity();
try
{
var userInfo = GetCurrentUser();
if (userInfo.IsAuthenticated)
{
var claims = new[] { new Claim(ClaimTypes.Name, _currentUser.UserName) }.Concat(_currentUser.Claims.Select(c => new Claim(c.Key, c.Value)));
identity = new ClaimsIdentity(claims, "Server authentication");
}
}
catch (HttpRequestException ex)
{
Console.WriteLine("Request failed:" + ex);
}
return new AuthenticationState(new ClaimsPrincipal(identity));
}
public async Task Login(LoginRequest loginParameters)
{
_authService.Login(loginParameters);
// No error - Login the user
var user = _authService.GetUser(loginParameters.UserName);
_currentUser = user;
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
public async Task Logout()
{
_currentUser = null;
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
public async Task Register(RegisterRequest registerParameters)
{
_authService.Register(registerParameters);
// No error - Login the user
var user = _authService.GetUser(registerParameters.UserName);
_currentUser = user;
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
private CurrentUser GetCurrentUser()
{
if (_currentUser != null && _currentUser.IsAuthenticated)
{
return _currentUser;
}
return new CurrentUser();
}
}
}

@ -0,0 +1,85 @@
using Blazored.LocalStorage;
using HeartTrack.Models;
using Microsoft.AspNetCore.Components;
namespace HeartTrack.Services
{
public class DataLocalService : IDataService
{
private readonly HttpClient _http;
private readonly ILocalStorageService _localStorage;
private readonly NavigationManager _navigationManager;
private readonly IWebHostEnvironment _webHostEnvironment;
public DataLocalService(
ILocalStorageService localStorage,
HttpClient http,
IWebHostEnvironment webHostEnvironment,
NavigationManager navigationManager)
{
_localStorage = localStorage;
_http = http;
_webHostEnvironment = webHostEnvironment;
_navigationManager = navigationManager;
}
public async Task Add(UserModel model)
{
// Get the current data
var currentData = await _localStorage.GetItemAsync<List<User>>("data");
// Simulate the Id
model.Id = currentData.Max(s => s.Id) + 1;
// Add the item to the current data
currentData.Add(new User
{
Id = model.Id,
Username = model.Username,
Nom = model.FirstName,
Prenom = model.LastName,
Email = model.Email,
Password = model.Password,
Sexe = model.Sexe,
Taille = model.Taille,
Poids = model.Poids,
BirthDate = model.BirthDate
});
// Save the data
await _localStorage.SetItemAsync("data", currentData);
}
public async Task<int> Count()
{
// Load data from the local storage
var currentData = await _localStorage.GetItemAsync<User[]>("data");
// Check if data exist in the local storage
if (currentData == null)
{
// this code add in the local storage the fake data
var originalData = await _http.GetFromJsonAsync<User[]>($"{_navigationManager.BaseUri}fake-data.json");
await _localStorage.SetItemAsync("data", originalData);
}
return (await _localStorage.GetItemAsync<User[]>("data")).Length;
}
public async Task<List<User>> List(int currentPage, int pageSize)
{
// Load data from the local storage
var currentData = await _localStorage.GetItemAsync<User[]>("data");
// Check if data exist in the local storage
if (currentData == null)
{
// this code add in the local storage the fake data
var originalData = await _http.GetFromJsonAsync<User[]>($"{_navigationManager.BaseUri}fake-data.json");
await _localStorage.SetItemAsync("data", originalData);
}
return (await _localStorage.GetItemAsync<User[]>("data")).Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
}
}
}

@ -0,0 +1,13 @@
using HeartTrack.Models;
namespace HeartTrack.Services
{
public interface IAuthService
{
CurrentUser GetUser(string userName);
void Login(LoginRequest loginRequest);
void Register(RegisterRequest registerRequest);
}
}

@ -0,0 +1,13 @@
using HeartTrack.Models;
namespace HeartTrack.Services
{
public interface IDataService
{
Task Add(UserModel model);
Task<int> Count();
Task<List<User>> List(int currentPage, int pageSize);
}
}

@ -0,0 +1,6 @@
@inherits LayoutComponentBase
<div class="main">
<div class="content px-4">
@Body
</div>
</div>

@ -15,8 +15,9 @@
</button> </button>
</div> </div>
@* Messages, notifs et pp compte à mettre *@ @* Messages, notifs et pp compte à mettre *@
<div class="px-4"> <div class="top-row px-4">
<CultureSelector /> <CultureSelector />
<button type="button" class="btn btn-link ml-md-auto" @onclick="@LogoutClick">Logout</button>
</div> </div>
</div> </div>

@ -0,0 +1,32 @@
using HeartTrack.Services;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components;
namespace HeartTrack.Shared
{
public partial class MainLayout
{
[Inject]
public CustomStateProvider AuthStateProvider { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
[CascadingParameter]
private Task<AuthenticationState> AuthenticationState { get; set; }
protected override async Task OnParametersSetAsync()
{
if (!(await AuthenticationState).User.Identity.IsAuthenticated)
{
NavigationManager.NavigateTo("/login");
}
}
private async Task LogoutClick()
{
await AuthStateProvider.Logout();
NavigationManager.NavigateTo("/login");
}
}
}

@ -11,6 +11,13 @@
<span class="oi oi-home" aria-hidden="true"></span> @Localizer["Global"] <span class="oi oi-home" aria-hidden="true"></span> @Localizer["Global"]
</NavLink> </NavLink>
</div> </div>
<AuthorizeView Roles="admin">
<li class="nav-item px-3">
<NavLink class="nav-link" href="admin" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Admin page
</NavLink>
</li>
</AuthorizeView>
<div class="nav-item px-3"> <div class="nav-item px-3">
<NavLink class="nav-link" href="tickets"> <NavLink class="nav-link" href="tickets">
<span class="oi oi-plus" aria-hidden="true"></span> @Localizer["Ticket"] <span class="oi oi-plus" aria-hidden="true"></span> @Localizer["Ticket"]

@ -8,4 +8,4 @@
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using HeartTrack @using HeartTrack
@using HeartTrack.Shared @using HeartTrack.Shared
@using Blazorise.DataGrid @using Blazorise.DataGrid

@ -8,9 +8,11 @@
".NETCoreApp,Version=v6.0": { ".NETCoreApp,Version=v6.0": {
"HeartTrack/1.0.0": { "HeartTrack/1.0.0": {
"dependencies": { "dependencies": {
"Blazored.LocalStorage": "4.4.0",
"Blazorise.Bootstrap": "1.4.0", "Blazorise.Bootstrap": "1.4.0",
"Blazorise.DataGrid": "1.4.0", "Blazorise.DataGrid": "1.4.0",
"Blazorise.Icons.FontAwesome": "1.4.0", "Blazorise.Icons.FontAwesome": "1.4.0",
"Microsoft.AspNetCore.Components.Authorization": "6.0.1",
"Microsoft.Extensions.Localization": "8.0.1" "Microsoft.Extensions.Localization": "8.0.1"
}, },
"runtime": { "runtime": {
@ -22,6 +24,17 @@
} }
} }
}, },
"Blazored.LocalStorage/4.4.0": {
"dependencies": {
"Microsoft.AspNetCore.Components.Web": "6.0.25"
},
"runtime": {
"lib/net6.0/Blazored.LocalStorage.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"Blazorise/1.4.0": { "Blazorise/1.4.0": {
"dependencies": { "dependencies": {
"Blazorise.Licensing": "1.2.0", "Blazorise.Licensing": "1.2.0",
@ -124,6 +137,18 @@
} }
}, },
"Microsoft.AspNetCore.Components.Analyzers/6.0.25": {}, "Microsoft.AspNetCore.Components.Analyzers/6.0.25": {},
"Microsoft.AspNetCore.Components.Authorization/6.0.1": {
"dependencies": {
"Microsoft.AspNetCore.Authorization": "6.0.25",
"Microsoft.AspNetCore.Components": "6.0.25"
},
"runtime": {
"lib/net6.0/Microsoft.AspNetCore.Components.Authorization.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.121.56714"
}
}
},
"Microsoft.AspNetCore.Components.Forms/6.0.25": { "Microsoft.AspNetCore.Components.Forms/6.0.25": {
"dependencies": { "dependencies": {
"Microsoft.AspNetCore.Components": "6.0.25" "Microsoft.AspNetCore.Components": "6.0.25"
@ -925,6 +950,13 @@
"serviceable": false, "serviceable": false,
"sha512": "" "sha512": ""
}, },
"Blazored.LocalStorage/4.4.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-zuXZB4/WW3Pr1761peemffdkjt09lbOP1wAkSDTKl7BTbA9V5e8LxS6MNfmyHW+BJzXrNDq90E2Y+AfIfnIbWQ==",
"path": "blazored.localstorage/4.4.0",
"hashPath": "blazored.localstorage.4.4.0.nupkg.sha512"
},
"Blazorise/1.4.0": { "Blazorise/1.4.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
@ -988,6 +1020,13 @@
"path": "microsoft.aspnetcore.components.analyzers/6.0.25", "path": "microsoft.aspnetcore.components.analyzers/6.0.25",
"hashPath": "microsoft.aspnetcore.components.analyzers.6.0.25.nupkg.sha512" "hashPath": "microsoft.aspnetcore.components.analyzers.6.0.25.nupkg.sha512"
}, },
"Microsoft.AspNetCore.Components.Authorization/6.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-cVE/z0bqqm1myMBK1pa/an9Z31V4eGb0E9c7gmiiViIq2bTz4TYFwkc9QlXwLwx1EKjNapi/+pTGITHI1ZIzKw==",
"path": "microsoft.aspnetcore.components.authorization/6.0.1",
"hashPath": "microsoft.aspnetcore.components.authorization.6.0.1.nupkg.sha512"
},
"Microsoft.AspNetCore.Components.Forms/6.0.25": { "Microsoft.AspNetCore.Components.Forms/6.0.25": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,

File diff suppressed because one or more lines are too long

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("HeartTrack")] [assembly: System.Reflection.AssemblyCompanyAttribute("HeartTrack")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+e6eca871930a2077a38dceded406de68248059ea")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a098e111547c18c55a8705cc7175fee1245ed200")]
[assembly: System.Reflection.AssemblyProductAttribute("HeartTrack")] [assembly: System.Reflection.AssemblyProductAttribute("HeartTrack")]
[assembly: System.Reflection.AssemblyTitleAttribute("HeartTrack")] [assembly: System.Reflection.AssemblyTitleAttribute("HeartTrack")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

@ -1 +1 @@
d30ed4a3a42cee40f2ca209ab170f57dc5eeac4fd8080332dd4fcbae3a663d09 5a687aac22c0782076c5bfe0a6928ecd6e1ff431e08fce9b31ef12d9f3e7872b

@ -26,22 +26,38 @@ build_metadata.AdditionalFiles.CssScope =
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcQWN0aXZpdGllcy5yYXpvcg== build_metadata.AdditionalFiles.TargetPath = UGFnZXNcQWN0aXZpdGllcy5yYXpvcg==
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/BannedUsers.razor] [C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/AddTicket.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcQmFubmVkVXNlcnMucmF6b3I= build_metadata.AdditionalFiles.TargetPath = UGFnZXNcQWRkVGlja2V0LnJhem9y
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/FetchData.razor] [C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Admin.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcRmV0Y2hEYXRhLnJhem9y build_metadata.AdditionalFiles.TargetPath = UGFnZXNcQWRtaW4ucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/BannedUsers.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcQmFubmVkVXNlcnMucmF6b3I=
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Index.razor] [C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Index.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcSW5kZXgucmF6b3I= build_metadata.AdditionalFiles.TargetPath = UGFnZXNcSW5kZXgucmF6b3I=
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Login.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcTG9naW4ucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Register.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcUmVnaXN0ZXIucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Reports.razor] [C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Reports.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcUmVwb3J0cy5yYXpvcg== build_metadata.AdditionalFiles.TargetPath = UGFnZXNcUmVwb3J0cy5yYXpvcg==
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Test.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcVGVzdC5yYXpvcg==
build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Tickets.razor] [C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Pages/Tickets.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcVGlja2V0cy5yYXpvcg== build_metadata.AdditionalFiles.TargetPath = UGFnZXNcVGlja2V0cy5yYXpvcg==
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
@ -50,6 +66,10 @@ build_metadata.AdditionalFiles.CssScope =
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcVG9rZW5zLnJhem9y build_metadata.AdditionalFiles.TargetPath = UGFnZXNcVG9rZW5zLnJhem9y
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Shared/AuthLayout.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXEF1dGhMYXlvdXQucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Shared/CultureSelector.razor] [C:/Users/antoi/Documents/Cours/2A/SAE/Admin/Admin/Sources/HeartTrack/Shared/CultureSelector.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXEN1bHR1cmVTZWxlY3Rvci5yYXpvcg== build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXEN1bHR1cmVTZWxlY3Rvci5yYXpvcg==
build_metadata.AdditionalFiles.CssScope = build_metadata.AdditionalFiles.CssScope =

@ -1 +1 @@
c63d2a571d8336634ecbf160550214c50149e1f4299792f26181df7f54f2a67c 745ea91892ff6a7a3b964f04dfaa384d73fe1ef6a90b3230451e2306bbffd4b3

@ -56,5 +56,7 @@ C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\n
C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\HeartTrack.Resources.Pages.Tokens.fr-FR.resources C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\HeartTrack.Resources.Pages.Tokens.fr-FR.resources
C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\HeartTrack.csproj.GenerateResource.cache C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\HeartTrack.csproj.GenerateResource.cache
C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\fr-FR\HeartTrack.resources.dll C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\fr-FR\HeartTrack.resources.dll
C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\bin\Debug\net6.0\Blazored.LocalStorage.dll
C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\bin\Debug\net6.0\Microsoft.AspNetCore.Components.Authorization.dll
C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\HeartTrack.Resources.Shared.NavMenu.resources C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\HeartTrack.Resources.Shared.NavMenu.resources
C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\HeartTrack.Resources.Shared.NavMenu.fr-FR.resources C:\Users\antoi\Documents\Cours\2A\SAE\Admin\Admin\Sources\HeartTrack\obj\Debug\net6.0\HeartTrack.Resources.Shared.NavMenu.fr-FR.resources

@ -1,6 +1,6 @@
{ {
"Version": 1, "Version": 1,
"Hash": "ec240AzVU2glV6r287clUEl7SpsFF2eQwJm6kl4/w3I=", "Hash": "hKkCCyCopeCL2bDCiMqO2ehUbpqNSgrUCESq8+TknS8=",
"Source": "HeartTrack", "Source": "HeartTrack",
"BasePath": "_content/HeartTrack", "BasePath": "_content/HeartTrack",
"Mode": "Default", "Mode": "Default",
@ -1080,6 +1080,25 @@
"CopyToPublishDirectory": "PreserveNewest", "CopyToPublishDirectory": "PreserveNewest",
"OriginalItemSpec": "wwwroot\\fake-data.json" "OriginalItemSpec": "wwwroot\\fake-data.json"
}, },
{
"Identity": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\wwwroot\\fake-tickets.json",
"SourceId": "HeartTrack",
"SourceType": "Discovered",
"ContentRoot": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\wwwroot\\",
"BasePath": "_content/HeartTrack",
"RelativePath": "fake-tickets.json",
"AssetKind": "All",
"AssetMode": "All",
"AssetRole": "Primary",
"AssetMergeBehavior": "PreferTarget",
"AssetMergeSource": "",
"RelatedAsset": "",
"AssetTraitName": "",
"AssetTraitValue": "",
"CopyToOutputDirectory": "Never",
"CopyToPublishDirectory": "PreserveNewest",
"OriginalItemSpec": "wwwroot\\fake-tickets.json"
},
{ {
"Identity": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\wwwroot\\favicon.ico", "Identity": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\wwwroot\\favicon.ico",
"SourceId": "HeartTrack", "SourceId": "HeartTrack",

File diff suppressed because one or more lines are too long

@ -56,6 +56,10 @@
"Id": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\wwwroot\\fake-data.json", "Id": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\wwwroot\\fake-data.json",
"PackagePath": "staticwebassets\\fake-data.json" "PackagePath": "staticwebassets\\fake-data.json"
}, },
{
"Id": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\wwwroot\\fake-tickets.json",
"PackagePath": "staticwebassets\\fake-tickets.json"
},
{ {
"Id": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\wwwroot\\favicon.ico", "Id": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\wwwroot\\favicon.ico",
"PackagePath": "staticwebassets\\favicon.ico" "PackagePath": "staticwebassets\\favicon.ico"

@ -208,6 +208,22 @@
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<OriginalItemSpec>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\staticwebassets\fake-data.json))</OriginalItemSpec> <OriginalItemSpec>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\staticwebassets\fake-data.json))</OriginalItemSpec>
</StaticWebAsset> </StaticWebAsset>
<StaticWebAsset Include="$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\staticwebassets\fake-tickets.json))">
<SourceType>Package</SourceType>
<SourceId>HeartTrack</SourceId>
<ContentRoot>$(MSBuildThisFileDirectory)..\staticwebassets\</ContentRoot>
<BasePath>_content/HeartTrack</BasePath>
<RelativePath>fake-tickets.json</RelativePath>
<AssetKind>All</AssetKind>
<AssetMode>All</AssetMode>
<AssetRole>Primary</AssetRole>
<RelatedAsset></RelatedAsset>
<AssetTraitName></AssetTraitName>
<AssetTraitValue></AssetTraitValue>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<OriginalItemSpec>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\staticwebassets\fake-tickets.json))</OriginalItemSpec>
</StaticWebAsset>
<StaticWebAsset Include="$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\staticwebassets\favicon.ico))"> <StaticWebAsset Include="$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\staticwebassets\favicon.ico))">
<SourceType>Package</SourceType> <SourceType>Package</SourceType>
<SourceId>HeartTrack</SourceId> <SourceId>HeartTrack</SourceId>

@ -45,6 +45,10 @@
"net6.0": { "net6.0": {
"targetAlias": "net6.0", "targetAlias": "net6.0",
"dependencies": { "dependencies": {
"Blazored.LocalStorage": {
"target": "Package",
"version": "[4.4.0, )"
},
"Blazorise.Bootstrap": { "Blazorise.Bootstrap": {
"target": "Package", "target": "Package",
"version": "[1.4.0, )" "version": "[1.4.0, )"
@ -57,6 +61,10 @@
"target": "Package", "target": "Package",
"version": "[1.4.0, )" "version": "[1.4.0, )"
}, },
"Microsoft.AspNetCore.Components.Authorization": {
"target": "Package",
"version": "[6.0.1, )"
},
"Microsoft.Extensions.Localization": { "Microsoft.Extensions.Localization": {
"target": "Package", "target": "Package",
"version": "[8.0.1, )" "version": "[8.0.1, )"

@ -2,6 +2,18 @@
"version": 3, "version": 3,
"targets": { "targets": {
"net6.0": { "net6.0": {
"Blazored.LocalStorage/4.4.0": {
"type": "package",
"dependencies": {
"Microsoft.AspNetCore.Components.Web": "6.0.0"
},
"compile": {
"lib/net6.0/Blazored.LocalStorage.dll": {}
},
"runtime": {
"lib/net6.0/Blazored.LocalStorage.dll": {}
}
},
"Blazorise/1.4.0": { "Blazorise/1.4.0": {
"type": "package", "type": "package",
"dependencies": { "dependencies": {
@ -155,6 +167,23 @@
"buildTransitive/netstandard2.0/Microsoft.AspNetCore.Components.Analyzers.targets": {} "buildTransitive/netstandard2.0/Microsoft.AspNetCore.Components.Analyzers.targets": {}
} }
}, },
"Microsoft.AspNetCore.Components.Authorization/6.0.1": {
"type": "package",
"dependencies": {
"Microsoft.AspNetCore.Authorization": "6.0.1",
"Microsoft.AspNetCore.Components": "6.0.1"
},
"compile": {
"lib/net6.0/Microsoft.AspNetCore.Components.Authorization.dll": {
"related": ".xml"
}
},
"runtime": {
"lib/net6.0/Microsoft.AspNetCore.Components.Authorization.dll": {
"related": ".xml"
}
}
},
"Microsoft.AspNetCore.Components.Forms/6.0.25": { "Microsoft.AspNetCore.Components.Forms/6.0.25": {
"type": "package", "type": "package",
"dependencies": { "dependencies": {
@ -1660,6 +1689,20 @@
} }
}, },
"libraries": { "libraries": {
"Blazored.LocalStorage/4.4.0": {
"sha512": "zuXZB4/WW3Pr1761peemffdkjt09lbOP1wAkSDTKl7BTbA9V5e8LxS6MNfmyHW+BJzXrNDq90E2Y+AfIfnIbWQ==",
"type": "package",
"path": "blazored.localstorage/4.4.0",
"files": [
".nupkg.metadata",
".signature.p7s",
"blazored.localstorage.4.4.0.nupkg.sha512",
"blazored.localstorage.nuspec",
"icon.png",
"lib/net6.0/Blazored.LocalStorage.dll",
"lib/net7.0/Blazored.LocalStorage.dll"
]
},
"Blazorise/1.4.0": { "Blazorise/1.4.0": {
"sha512": "RgewqcqsYJN7r5qkX0lYzWq1xpNRBpwdJKN1/wH2Q9hPcLcgyBUIYYTiah0hvlHIhtpWfX+zV85CPlJ5X1Yk4A==", "sha512": "RgewqcqsYJN7r5qkX0lYzWq1xpNRBpwdJKN1/wH2Q9hPcLcgyBUIYYTiah0hvlHIhtpWfX+zV85CPlJ5X1Yk4A==",
"type": "package", "type": "package",
@ -1865,6 +1908,21 @@
"microsoft.aspnetcore.components.analyzers.nuspec" "microsoft.aspnetcore.components.analyzers.nuspec"
] ]
}, },
"Microsoft.AspNetCore.Components.Authorization/6.0.1": {
"sha512": "cVE/z0bqqm1myMBK1pa/an9Z31V4eGb0E9c7gmiiViIq2bTz4TYFwkc9QlXwLwx1EKjNapi/+pTGITHI1ZIzKw==",
"type": "package",
"path": "microsoft.aspnetcore.components.authorization/6.0.1",
"files": [
".nupkg.metadata",
".signature.p7s",
"Icon.png",
"THIRD-PARTY-NOTICES.txt",
"lib/net6.0/Microsoft.AspNetCore.Components.Authorization.dll",
"lib/net6.0/Microsoft.AspNetCore.Components.Authorization.xml",
"microsoft.aspnetcore.components.authorization.6.0.1.nupkg.sha512",
"microsoft.aspnetcore.components.authorization.nuspec"
]
},
"Microsoft.AspNetCore.Components.Forms/6.0.25": { "Microsoft.AspNetCore.Components.Forms/6.0.25": {
"sha512": "YdO7ajZVU4HOieTQ0THKiqLSHXpE4S10o3sUXXxtSK9FSaiok75sdmbKBFXhl+hEYv0O+BFZRNCR1RRzxFuHUg==", "sha512": "YdO7ajZVU4HOieTQ0THKiqLSHXpE4S10o3sUXXxtSK9FSaiok75sdmbKBFXhl+hEYv0O+BFZRNCR1RRzxFuHUg==",
"type": "package", "type": "package",
@ -5496,9 +5554,11 @@
}, },
"projectFileDependencyGroups": { "projectFileDependencyGroups": {
"net6.0": [ "net6.0": [
"Blazored.LocalStorage >= 4.4.0",
"Blazorise.Bootstrap >= 1.4.0", "Blazorise.Bootstrap >= 1.4.0",
"Blazorise.DataGrid >= 1.4.0", "Blazorise.DataGrid >= 1.4.0",
"Blazorise.Icons.FontAwesome >= 1.4.0", "Blazorise.Icons.FontAwesome >= 1.4.0",
"Microsoft.AspNetCore.Components.Authorization >= 6.0.1",
"Microsoft.Extensions.Localization >= 8.0.1" "Microsoft.Extensions.Localization >= 8.0.1"
] ]
}, },
@ -5547,6 +5607,10 @@
"net6.0": { "net6.0": {
"targetAlias": "net6.0", "targetAlias": "net6.0",
"dependencies": { "dependencies": {
"Blazored.LocalStorage": {
"target": "Package",
"version": "[4.4.0, )"
},
"Blazorise.Bootstrap": { "Blazorise.Bootstrap": {
"target": "Package", "target": "Package",
"version": "[1.4.0, )" "version": "[1.4.0, )"
@ -5559,6 +5623,10 @@
"target": "Package", "target": "Package",
"version": "[1.4.0, )" "version": "[1.4.0, )"
}, },
"Microsoft.AspNetCore.Components.Authorization": {
"target": "Package",
"version": "[6.0.1, )"
},
"Microsoft.Extensions.Localization": { "Microsoft.Extensions.Localization": {
"target": "Package", "target": "Package",
"version": "[8.0.1, )" "version": "[8.0.1, )"

@ -1,9 +1,10 @@
{ {
"version": 2, "version": 2,
"dgSpecHash": "HEByZOGJLG5xIgquSuc7Cqn4OOXS6WtP6DO/ZE4KXgoop+AIZBUfEQWkE1+Cifem5wqyRAEVauiRZVyl63BcBQ==", "dgSpecHash": "S+L/SrPGNv2PU30yTN+p0XLbDm3AuD0IDhYxFTeiwOoF1cku92QTWij93b5S2Vs/UOJnhJFk5ZQYNHis9iNW2Q==",
"success": true, "success": true,
"projectFilePath": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\HeartTrack.csproj", "projectFilePath": "C:\\Users\\antoi\\Documents\\Cours\\2A\\SAE\\Admin\\Admin\\Sources\\HeartTrack\\HeartTrack.csproj",
"expectedPackageFiles": [ "expectedPackageFiles": [
"C:\\Users\\antoi\\.nuget\\packages\\blazored.localstorage\\4.4.0\\blazored.localstorage.4.4.0.nupkg.sha512",
"C:\\Users\\antoi\\.nuget\\packages\\blazorise\\1.4.0\\blazorise.1.4.0.nupkg.sha512", "C:\\Users\\antoi\\.nuget\\packages\\blazorise\\1.4.0\\blazorise.1.4.0.nupkg.sha512",
"C:\\Users\\antoi\\.nuget\\packages\\blazorise.bootstrap\\1.4.0\\blazorise.bootstrap.1.4.0.nupkg.sha512", "C:\\Users\\antoi\\.nuget\\packages\\blazorise.bootstrap\\1.4.0\\blazorise.bootstrap.1.4.0.nupkg.sha512",
"C:\\Users\\antoi\\.nuget\\packages\\blazorise.datagrid\\1.4.0\\blazorise.datagrid.1.4.0.nupkg.sha512", "C:\\Users\\antoi\\.nuget\\packages\\blazorise.datagrid\\1.4.0\\blazorise.datagrid.1.4.0.nupkg.sha512",
@ -13,6 +14,7 @@
"C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.authorization\\6.0.25\\microsoft.aspnetcore.authorization.6.0.25.nupkg.sha512", "C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.authorization\\6.0.25\\microsoft.aspnetcore.authorization.6.0.25.nupkg.sha512",
"C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.components\\6.0.25\\microsoft.aspnetcore.components.6.0.25.nupkg.sha512", "C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.components\\6.0.25\\microsoft.aspnetcore.components.6.0.25.nupkg.sha512",
"C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.components.analyzers\\6.0.25\\microsoft.aspnetcore.components.analyzers.6.0.25.nupkg.sha512", "C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.components.analyzers\\6.0.25\\microsoft.aspnetcore.components.analyzers.6.0.25.nupkg.sha512",
"C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.components.authorization\\6.0.1\\microsoft.aspnetcore.components.authorization.6.0.1.nupkg.sha512",
"C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.components.forms\\6.0.25\\microsoft.aspnetcore.components.forms.6.0.25.nupkg.sha512", "C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.components.forms\\6.0.25\\microsoft.aspnetcore.components.forms.6.0.25.nupkg.sha512",
"C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.components.web\\6.0.25\\microsoft.aspnetcore.components.web.6.0.25.nupkg.sha512", "C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.components.web\\6.0.25\\microsoft.aspnetcore.components.web.6.0.25.nupkg.sha512",
"C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.metadata\\6.0.25\\microsoft.aspnetcore.metadata.6.0.25.nupkg.sha512", "C:\\Users\\antoi\\.nuget\\packages\\microsoft.aspnetcore.metadata\\6.0.25\\microsoft.aspnetcore.metadata.6.0.25.nupkg.sha512",

@ -9,7 +9,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2019-10-20" "birthdate": "2018-12-27",
"isban": true
}, },
{ {
"id": 2, "id": 2,
@ -21,7 +22,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2022-01-06" "birthdate": "2021-06-29",
"isban": true
}, },
{ {
"id": 3, "id": 3,
@ -33,7 +35,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2015-02-05" "birthdate": "2021-04-09",
"isban": true
}, },
{ {
"id": 4, "id": 4,
@ -45,7 +48,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2015-04-20" "birthdate": "2022-11-20",
"isban": true
}, },
{ {
"id": 5, "id": 5,
@ -57,7 +61,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2020-02-22" "birthdate": "2021-02-20",
"isban": true
}, },
{ {
"id": 6, "id": 6,
@ -69,7 +74,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2018-03-11" "birthdate": "2014-02-17",
"isban": true
}, },
{ {
"id": 7, "id": 7,
@ -81,7 +87,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2019-04-21" "birthdate": "2020-07-14",
"isban": true
}, },
{ {
"id": 8, "id": 8,
@ -93,7 +100,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2023-05-17" "birthdate": "2018-02-21",
"isban": false
}, },
{ {
"id": 9, "id": 9,
@ -105,7 +113,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2021-06-16" "birthdate": "2014-07-31",
"isban": true
}, },
{ {
"id": 10, "id": 10,
@ -117,7 +126,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2014-09-24" "birthdate": "2019-10-02",
"isban": true
}, },
{ {
"id": 11, "id": 11,
@ -129,7 +139,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2015-02-28" "birthdate": "2015-07-26",
"isban": false
}, },
{ {
"id": 12, "id": 12,
@ -141,7 +152,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2022-09-26" "birthdate": "2020-10-23",
"isban": false
}, },
{ {
"id": 13, "id": 13,
@ -153,7 +165,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2019-06-19" "birthdate": "2014-11-03",
"isban": true
}, },
{ {
"id": 14, "id": 14,
@ -165,7 +178,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2022-09-25" "birthdate": "2014-01-31",
"isban": false
}, },
{ {
"id": 15, "id": 15,
@ -177,7 +191,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2017-10-21" "birthdate": "2022-04-12",
"isban": false
}, },
{ {
"id": 16, "id": 16,
@ -189,7 +204,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2021-02-05" "birthdate": "2018-07-22",
"isban": false
}, },
{ {
"id": 17, "id": 17,
@ -201,7 +217,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2018-06-14" "birthdate": "2017-04-04",
"isban": true
}, },
{ {
"id": 18, "id": 18,
@ -213,7 +230,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2017-02-09" "birthdate": "2015-08-15",
"isban": true
}, },
{ {
"id": 19, "id": 19,
@ -225,7 +243,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2020-09-16" "birthdate": "2022-04-10",
"isban": false
}, },
{ {
"id": 20, "id": 20,
@ -237,7 +256,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2020-01-31" "birthdate": "2020-02-09",
"isban": false
}, },
{ {
"id": 21, "id": 21,
@ -249,7 +269,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2020-04-11" "birthdate": "2017-02-18",
"isban": false
}, },
{ {
"id": 22, "id": 22,
@ -261,7 +282,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2016-10-30" "birthdate": "2023-06-25",
"isban": false
}, },
{ {
"id": 23, "id": 23,
@ -273,7 +295,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2014-09-20" "birthdate": "2017-09-27",
"isban": true
}, },
{ {
"id": 24, "id": 24,
@ -285,7 +308,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2019-01-21" "birthdate": "2015-02-01",
"isban": true
}, },
{ {
"id": 25, "id": 25,
@ -297,7 +321,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2017-10-28" "birthdate": "2017-05-28",
"isban": true
}, },
{ {
"id": 26, "id": 26,
@ -309,7 +334,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2021-11-05" "birthdate": "2022-06-11",
"isban": true
}, },
{ {
"id": 27, "id": 27,
@ -321,7 +347,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2014-08-06" "birthdate": "2019-08-08",
"isban": true
}, },
{ {
"id": 28, "id": 28,
@ -333,7 +360,8 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2020-06-03" "birthdate": "2015-01-29",
"isban": false
}, },
{ {
"id": 29, "id": 29,
@ -345,18 +373,7 @@
"sexe": "male", "sexe": "male",
"taille": 1.76, "taille": 1.76,
"poids": 56.3, "poids": 56.3,
"birthdate": "2018-07-01" "birthdate": "2020-08-21",
}, "isban": false
{
"id": 30,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"email": "john.doe@example.com",
"password": "password123",
"sexe": "male",
"taille": 1.76,
"poids": 56.3,
"birthdate": "2021-01-22"
} }
] ]

@ -0,0 +1,209 @@
[
{
"id": 1,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 2,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 3,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": false
},
{
"id": 4,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": false
},
{
"id": 5,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 6,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": false
},
{
"id": 7,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 8,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 9,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": false
},
{
"id": 10,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 11,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": false
},
{
"id": 12,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 13,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 14,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 15,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": false
},
{
"id": 16,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 17,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": false
},
{
"id": 18,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 19,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 20,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 21,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
},
{
"id": 22,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": false
},
{
"id": 23,
"username": "johndoe",
"nom": "Doe",
"prenom": "John",
"contexte": "Jvais dire wallah",
"description": "Wallah c`est la description",
"urgence": true
}
]
Loading…
Cancel
Save