Logs #31

Merged
kentin.brongniart merged 5 commits from Logs into master 3 months ago

@ -0,0 +1,41 @@
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.Logging;
using Microsoft.VisualBasic;
using System;
using System.Diagnostics;
using System.Security.Claims;
using WF_WebAdmin.Pages;
using WF_WebAdmin.Service;
namespace WF_WebAdmin.Model
{
public static partial class LoggerSaveStub
{
public static void Log(ILogger logs,LogLevel logLevel,string message)
{
ILogsService logsService = new LogsServiceStub();
logsService.addLogs( new Logs( logLevel , message ) );
logs.Log(logLevel, message );
}
}
}
/*
[Inject]
public ILogger< Class > Logger { get; set; }
LoggerSaveStub.Log(Logger,LogLevel. level , message );
LogLevel:
Trace = 0,
Debug = 1,
Information = 2,
Warning = 3,
Error = 4,
Critical = 5,
None = 6,
*/

@ -0,0 +1,14 @@
namespace WF_WebAdmin.Model
{
public class Logs
{
public LogLevel LogLevel { get; set; }
public string Message { get; set; }
public Logs(LogLevel logLevel , string message) {
this.LogLevel=logLevel;
this.Message=message;
}
}
}

@ -28,5 +28,5 @@ else
}
<h4>@Localizer["AccueilManualChange"]</h4>
<button>@Localizer["AccueilAddRandomQuote"]</button>
<button @onclick="() => RandomDailyquote()">@Localizer["AccueilAddRandomQuote"]</button>

@ -1,6 +1,7 @@
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using System.Security.Claims;
using WF_WebAdmin.Model;
@ -9,6 +10,8 @@ namespace WF_WebAdmin.Pages
public partial class Accueil
{
private Quote[] Dailyquote;
[Inject]
public ILogger<Accueil> Logger { get; set; }
[Inject]
public HttpClient Http { get; set; }
@ -29,5 +32,11 @@ namespace WF_WebAdmin.Pages
Dailyquote = await Http.GetFromJsonAsync<Quote[]>($"{NavigationManager.BaseUri}fake-dataDailyQuote.json");
}
private void RandomDailyquote()
{
//fonction a compléter
LoggerSaveStub.Log(Logger, LogLevel.Information, "Changement aléatoire de la quote du jour");
}
}
}

@ -4,12 +4,16 @@ using WF_WebAdmin.Model;
using Microsoft.AspNetCore.Mvc;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using System.Security.Claims;
namespace WF_WebAdmin.Pages
{
public partial class AddQuiz
{
[Inject]
public ILogger<AddQuiz> Logger { get; set; }
[Inject]
public IStringLocalizer<AddQuiz> Localizer { get; set; }
@ -41,6 +45,7 @@ namespace WF_WebAdmin.Pages
id++;
// Create a new quiz and add it using the quiz service.
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Création de la question {QuizModel.Question}");
await quizService.addQuiz(new Quiz(
id, // New quiz ID
validateInformation(QuizModel.Question), // Validated question

@ -1,6 +1,7 @@
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Localization;
using System.Collections.Generic;
using WF_WebAdmin.Model;
@ -10,10 +11,13 @@ namespace WF_WebAdmin.Pages
{
public partial class DeleteUser
{
[Inject]
public ILogger<DeleteUser> Logger { get; set; }
private List<User> users;
private bool showDeletePopup = false;
private bool showModifyPopup = false;
private List<User> users;
private User userToDelete = null;
private User selectedUser;
private bool showPopupDelete = false;
@ -34,22 +38,22 @@ namespace WF_WebAdmin.Pages
private IUserService userService { get; set; }
[Inject]
public IStringLocalizer<DeleteUser> Localizer { get; set; }
public IStringLocalizer<DeleteUser> Localizer { get; set; }
/// <summary>
/// This method is called when the component is initialized.
/// It is an asynchronous method that retrieves a list of users from the user service.
/// The method fetches a subset of users with a specified maximum value and page number (1 in this case).
/// </summary>
protected override async Task OnInitializedAsync()
{
protected override async Task OnInitializedAsync()
{
// Retrieve a list of users using the user service. The number of users and page number are specified.
// MaxValue determines how many users to retrieve, and '1' refers to the first page of results.
users = await userService.getSomeUser(MaxValue, 1);
}
users = await userService.getSomeUser(MaxValue, 1);
}
/// <summary>
@ -59,27 +63,27 @@ namespace WF_WebAdmin.Pages
/// and updates the list of users and total item count if the operation is not cancelled.
/// </summary>
/// <param name="e">The event arguments containing pagination details (page size and page number) and a cancellation token.</param>
private async Task OnReadData(DataGridReadDataEventArgs<User> e)
{
private async Task OnReadData(DataGridReadDataEventArgs<User> e)
{
// If the cancellation token is requested, exit the method without processing the request.
if (e.CancellationToken.IsCancellationRequested)
{
return;
}
if (e.CancellationToken.IsCancellationRequested)
{
return;
}
// Fetch a page of users from the user service using the page size and page number provided by the event arguments.
var response = await userService.getSomeUser(e.PageSize, e.Page);
var response = await userService.getSomeUser(e.PageSize, e.Page);
// If the operation is not cancelled, update the total number of users and the list of users.
if (!e.CancellationToken.IsCancellationRequested)
{
if (!e.CancellationToken.IsCancellationRequested)
{
totalItem = await userService.getNbUser(); // Get the total number of users
users = new List<User>(response.ToArray()); // Store the retrieved users in the users list
page = e.Page; // Update the current page number
}
}
// ------- Popup remove user -------
}
}
// ------- Popup remove user -------
/// <summary>
/// Displays a confirmation popup to confirm the deletion of a user.
@ -87,13 +91,13 @@ namespace WF_WebAdmin.Pages
/// and it sets the user to be deleted and shows the confirmation popup.
/// </summary>
/// <param name="user">The user to be deleted, which is passed to the method for confirmation.</param>
private void ShowConfirmation(User user)
{
private void ShowConfirmation(User user)
{
// Set the user to be deleted and show the confirmation popup.
userToDelete = user; // Store the user to be deleted in a variable
showPopupDelete = true; // Display the confirmation popup
}
}
/// <summary>
/// Displays a confirmation popup for modifying a user's information.
@ -101,13 +105,13 @@ namespace WF_WebAdmin.Pages
/// and it sets the selected user and shows the modification confirmation popup.
/// </summary>
/// <param name="user">The user whose information is to be modified, passed to the method for confirmation.</param>
private void ShowModifyConfirmation(User user)
{
private void ShowModifyConfirmation(User user)
{
// Set the selected user and show the modification confirmation popup.
selectedUser = user; // Store the user to be modified
showModifyPopup = true; // Display the confirmation popup for modification
}
}
/// <summary>
/// Removes the specified user from the system.
@ -115,95 +119,99 @@ namespace WF_WebAdmin.Pages
/// It calls the user service to remove the user, closes the confirmation popup,
/// and then refreshes the list of users by fetching the updated data.
/// </summary>
private async Task RemoveUser()
{
private async Task RemoveUser()
{
// Check if there is a user to delete
if (userToDelete != null)
{
if (userToDelete != null)
{
// Remove the selected user from the system using the user service
await userService.removeUser(userToDelete);
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Supretion de l utilisateur : {userToDelete.Name}");
await userService.removeUser(userToDelete);
// Close the confirmation popup after the deletion
ClosePopup();
ClosePopup();
// Refresh the list of users by fetching the updated data from the user service
var response = await userService.getSomeUser(MaxValue, page);
var response = await userService.getSomeUser(MaxValue, page);
// Update the users list with the latest data
users = new List<User>(response.ToArray());
}
}
users = new List<User>(response.ToArray());
}
}
/// <summary>
/// Modifies the selected user's information.
/// This method is triggered when the user confirms the modification of a user's details.
/// It calls the user service to update the user's information and then closes the modification popup.
/// </summary>
private async Task ModifyUser()
{
private async Task ModifyUser()
{
// Update the selected user's information using the user service
await userService.updateUser(selectedUser);
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Modification de l utilisateur : {selectedUser.Name}");
await userService.updateUser(selectedUser);
// Close the modification popup after the update is complete
ClosePopup();
}
ClosePopup();
}
/// <summary>
/// Closes all open popups in the UI by setting their visibility flags to false.
/// This method is typically called after an action (like deleting or modifying a user)
/// to hide any active popups and reset the UI state.
/// </summary>
private void ClosePopup()
{
private void ClosePopup()
{
// Set all popup visibility flags to false to hide the popups
showDeletePopup = false; // Close the delete confirmation popup
showModifyPopup = false; // Close the modify confirmation popup
showPopupDelete = false; // Close any additional delete popups
showPopupAdmin = false; // Close the admin-related popup (if any)
}
// ------- Popup admin -------
}
// ------- Popup admin -------
/// <summary>
/// Displays a confirmation popup to confirm the promotion of a user to admin status.
/// This method is triggered when the user intends to promote a specific user to admin.
/// It sets the selected user to be promoted and shows the confirmation popup for admin promotion.
/// </summary>
/// <param name="user">The user to be promoted to admin, passed to the method for confirmation.</param>
private void ShowConfirmationAdmin(User user)
{
private void ShowConfirmationAdmin(User user)
{
// Set the user to be promoted to admin and show the confirmation popup.
userToAdmin = user; // Store the user to be promoted
showPopupAdmin = true; // Display the confirmation popup for admin promotion
}
}
/// <summary>
/// Toggles the admin status of the selected user.
/// This method checks the current admin status of the user, and if the user is not an admin,
/// it promotes them to admin. If the user is already an admin, it demotes them.
/// After the change, the user's information is updated, and the confirmation popup is closed.
/// </summary>
private async Task setAdmin()
{
private async Task setAdmin()
{
// Check if the user is not already an admin
if (!userToAdmin.IsAdmin)
{
if (!userToAdmin.IsAdmin)
{
// Promote the user to admin
userToAdmin.IsAdmin = true;
LoggerSaveStub.Log(Logger, LogLevel.Information, $"L utilisateur {userToAdmin.Name} a ete mis en administrateur");
userToAdmin.IsAdmin = true;
await userService.updateUser(userToAdmin); // Update the user status in the service
ClosePopup(); // Close the confirmation popup
}
else
{
}
else
{
// Demote the user from admin to normal user
userToAdmin.IsAdmin = false;
LoggerSaveStub.Log(Logger, LogLevel.Information, $"L utilisateur {userToAdmin.Name} n'est plus administrateur");
userToAdmin.IsAdmin = false;
await userService.updateUser(userToAdmin); // Update the user status in the service
ClosePopup(); // Close the confirmation popup
}
}
}
}

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using System.Security.Claims;
using WF_WebAdmin.Model;
using WF_WebAdmin.Service;
@ -9,6 +10,9 @@ namespace WF_WebAdmin.Pages
[Parameter]
public int Id { get; set; }
[Inject]
public ILogger<Edit> Logger { get; set; }
[Inject]
private IQuoteService quoteService { get; set; }
@ -61,6 +65,7 @@ namespace WF_WebAdmin.Pages
protected async void HandleValidSubmit()
{
// Update the properties of the selected quote (`q`) with the data from `quoteModel`.
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Modification de la quote {q.Content}");
q.Content = quoteModel.Content;
q.Langue = quoteModel.Langue;
q.TitleSrc = quoteModel.TitleSrc;

@ -15,7 +15,7 @@ namespace WF_WebAdmin.Pages
private UserLogin userLogin = new UserLogin();
[Inject]
public UserLogin uLogin { get; set; }
public UserLogin uLogin { get; set; }
private string ErrorConnexion;

@ -0,0 +1,34 @@
@page "/logs"
<h3>Logs</h3>
@if (logs is null)
{
<p>Aucun Logs</p>
}
@* else if (quotes.Count == 0)
{
<p>Aucune citation en attente de validation.</p>
} *@
else
{
<p>Citations en attente de validation :</p>
<table>
<thead>
<tr>
<th>LogLevel :</th>
<th>Message :</th>
</tr>
</thead>
<tbody>
@foreach (var log in logs)
{
<tr>
<td>@log.LogLevel</td>
<td>@log.Message</td>
</tr>
}
</tbody>
</table>
}

@ -0,0 +1,21 @@
using Microsoft.AspNetCore.Components;
using WF_WebAdmin.Model;
namespace WF_WebAdmin.Pages
{
public partial class LogsPage
{
private Logs[] logs;
[Inject]
public HttpClient Http { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
protected override async Task OnInitializedAsync()
{
logs = await Http.GetFromJsonAsync<Logs[]>($"{NavigationManager.BaseUri}fake_data_logs.json");
}
}
}

@ -1,6 +1,7 @@
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using System.Security.Claims;
using WF_WebAdmin.Model;
using WF_WebAdmin.Service;
@ -22,6 +23,9 @@ namespace WF_WebAdmin.Pages
private int page = 1;
[Inject]
public ILogger<ModifQuiz> Logger { get; set; }
[Inject]
public IStringLocalizer<ModifQuiz> Localizer { get; set; }
@ -103,6 +107,7 @@ namespace WF_WebAdmin.Pages
private async Task EditQuiz()
{
// Update the quiz in the service
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Modification de la question {selectedQuiz.Question}");
await QuizService.updateQuiz(selectedQuiz);
// Clear the selected quiz after successful update
@ -139,6 +144,7 @@ namespace WF_WebAdmin.Pages
if (selectedQuiz != null)
{
// Remove the selected quiz from the service by its ID
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Supretion de la question {selectedQuiz.Question}");
await QuizService.removeQuiz(selectedQuiz.Id);
// Clear the selected quiz after successful removal

@ -1,6 +1,8 @@
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using System.Security.Claims;
using WF_WebAdmin.Model;
using WF_WebAdmin.Service;
@ -22,6 +24,9 @@ namespace WF_WebAdmin.Pages
private int page = 1;
[Inject]
public ILogger<ModifQuote> Logger { get; set; }
[Inject]
public IStringLocalizer<ModifQuote> Localizer { get; set; }
@ -112,6 +117,7 @@ namespace WF_WebAdmin.Pages
if (selectedQuote != null)
{
// Remove the selected quote using the QuoteService
LoggerSaveStub.Log(Logger, LogLevel.Information, $"La quote {selectedQuote.Content} a ete suprimer");
await QuoteService.removeQuote(selectedQuote);
// Clear the selected quote after removal

@ -1,6 +1,8 @@
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using System.Security.Claims;
using WF_WebAdmin.Model;
using WF_WebAdmin.Service;
@ -9,6 +11,8 @@ namespace WF_WebAdmin.Pages
public partial class ValidQuiz
{
private List<Quiz> quizzes;
[Inject]
public ILogger<ValidQuiz> Logger { get; set; }
[Inject]
public IStringLocalizer<ValidQuiz> Localizer { get; set; }
@ -20,29 +24,29 @@ namespace WF_WebAdmin.Pages
public NavigationManager NavigationManager { get; set; }
[Inject]
public IQuizService QuizService { get; set; }
public IQuizService QuizService { get; set; }
/// <summary>
/// Initializes the component asynchronously by fetching the quizzes that need validation.
/// This method retrieves a list of quizzes from the `QuizService` that are pending validation when the component is initialized.
/// </summary>
protected override async Task OnInitializedAsync()
{
protected override async Task OnInitializedAsync()
{
// Fetch quizzes that need validation
quizzes = await QuizService.getQuizzesToValidate();
}
quizzes = await QuizService.getQuizzesToValidate();
}
/// <summary>
/// Handles the event when the "Validate" button is clicked for a quiz.
/// This method calls the `ValidateQuiz` method, passing the specified quiz for validation.
/// </summary>
/// <param name="quiz">The quiz that is being validated.</param>
private void OnValidButton(Quiz quiz)
{
private void OnValidButton(Quiz quiz)
{
// Call the ValidateQuiz method to validate the quiz
ValidateQuiz(quiz);
}
ValidateQuiz(quiz);
}
/// <summary>
/// Validates the specified quiz by setting its `IsValid` property to true and updating its state in the service.
@ -50,43 +54,47 @@ namespace WF_WebAdmin.Pages
/// It then calls the `QuizService.updateQuiz` method to persist the changes.
/// </summary>
/// <param name="quiz">The quiz that is being validated.</param>
private void ValidateQuiz(Quiz quiz)
{
private void ValidateQuiz(Quiz quiz)
{
// Log the validation action to the console
Console.WriteLine($"Quiz {quiz.Id} validated!");
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Quiz {quiz.Id} validated!");
Console.WriteLine($"Quiz {quiz.Id} validated!");
// Create a new quiz instance (or modify the existing one)
Quiz newQuiz = quiz;
newQuiz.IsValid = true;
Quiz newQuiz = quiz;
newQuiz.IsValid = true;
// Update the quiz state in the QuizService
QuizService.updateQuiz(quiz);
}
QuizService.updateQuiz(quiz);
}
/// <summary>
/// Handles the event when the "Reject" button is clicked for a quiz.
/// This method calls the `RejectQuiz` method, passing the specified quiz to be rejected.
/// </summary>
/// <param name="quiz">The quiz that is being rejected.</param>
private void OnRejectButton(Quiz quiz)
{
private void OnRejectButton(Quiz quiz)
{
// Call the RejectQuiz method to reject the quiz
RejectQuiz(quiz);
}
RejectQuiz(quiz);
}
/// <summary>
/// Rejects the specified quiz by logging a rejection message and removing it from the QuizService.
/// This method logs a message to the console indicating the quiz has been rejected, and then calls the `QuizService.removeQuiz`
/// method to remove the quiz from the system.
/// </summary>
/// <param name="quiz">The quiz that is being rejected.</param>
private void RejectQuiz(Quiz quiz)
{
private void RejectQuiz(Quiz quiz)
{
// Log the rejection action to the console
Console.WriteLine($"Quiz {quiz.Id} rejected!");
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Quiz {quiz.Id} rejected!");
Console.WriteLine($"Quiz {quiz.Id} rejected!");
// Remove the rejected quiz from the QuizService
QuizService.removeQuiz(quiz.Id);
QuizService.removeQuiz(quiz.Id);
}
}
}

@ -12,6 +12,7 @@ using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using Blazored.Modal;
using WF_WebAdmin.Service;
using Microsoft.Extensions.Logging;
[assembly: RootNamespace("WF_WebAdmin")]
@ -27,6 +28,8 @@ builder.Services.AddHttpClient();
builder.Services.AddScoped<UserLogin>();
//builder.WebHost.UseUrls("http://0.0.0.0:5000");
builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging"));
builder.Services
.AddBlazorise()
.AddBootstrapProviders()

@ -0,0 +1,17 @@
using WF_WebAdmin.Model;
namespace WF_WebAdmin.Service
{
public interface ILogsService
{
public Task removeLogs(Logs logs);
public Task<List<Logs>> getAllLogs();
public Task<List<Logs>> getSomeLogs(int nb, int page);
public Task addLogs(Logs logs);
public Task<int> getNbLogs();
}
}

@ -0,0 +1,67 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Text.Json;
using WF_WebAdmin.Model;
namespace WF_WebAdmin.Service
{
public class LogsServiceStub : ILogsService
{
private readonly string _jsonFilePath = Path.Combine(Environment.CurrentDirectory, "wwwroot", "fake_data_logs.json");
public async Task saveLogsJson(List<Logs> logs)
{
var json = JsonSerializer.Serialize(logs, new JsonSerializerOptions { WriteIndented = true });
await File.WriteAllTextAsync(_jsonFilePath, json);
}
public async Task addLogs(Logs logs)
{
var data = await getAllLogs();
data.Add(logs);
await saveLogsJson(data);
}
public async Task<List<Logs>> getAllLogs()
{
if (!File.Exists(_jsonFilePath))
{
Console.Out.WriteLine($"{_jsonFilePath} not found");
return new List<Logs>();
}
var json = await File.ReadAllTextAsync(_jsonFilePath);
return JsonSerializer.Deserialize<List<Logs>>(json) ?? new List<Logs>();
}
public async Task<int> getNbLogs()
{
throw new NotImplementedException();
}
public async Task<List<Logs>> getSomeLogs(int nb, int page)
{
var logs = await getAllLogs();
if ((page - 1) * nb + nb > logs.Count())
{
return logs.GetRange(logs.Count() - nb, nb);
}
return logs.GetRange((page - 1) * nb, nb);
}
public async Task removeLogs(Logs logs)
{
var data = await getAllLogs();
var l = data.FirstOrDefault(p => p.Message ==logs.Message && p.LogLevel==logs.LogLevel);
if (l != null)
{
data.Remove(l);
await saveLogsJson(data);
}
}
}
}

@ -11,7 +11,7 @@
<div class="sidebar">
<NavMenu/>
</div>
@* } *@
@*}*@
<main>
<div class="top-row px-4">

@ -49,6 +49,12 @@
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="logs">
<span class="oi oi-list-rich" aria-hidden="true"></span> Logs
</NavLink>
</div>
</nav>
</div>

@ -1,7 +1,7 @@
[
{
"Id": 1,
"Content": "Que la force soit avec toi.",
"Content": "Que la force soit avec toi",
"Like": 150,
"Langue": "en",
"Charac": "Drago Malefoy",

@ -0,0 +1,66 @@
[
{
"LogLevel": 1,
"Message": "Logs de test"
},
{
"LogLevel": 2,
"Message": "Demande de supretion de l utilisateur : admin"
},
{
"LogLevel": 2,
"Message": "Demande de supretion de l utilisateur : testeur"
},
{
"LogLevel": 2,
"Message": "Demande de supretion de l utilisateur : dev"
},
{
"LogLevel": 2,
"Message": "Changement al\u00E9atoire de la quote du jour"
},
{
"LogLevel": 2,
"Message": "Quiz 11 validated!"
},
{
"LogLevel": 2,
"Message": "Quiz 12 rejected!"
},
{
"LogLevel": 2,
"Message": "Modification de l utilisateur : testeur1"
},
{
"LogLevel": 2,
"Message": "L utilisateur testeur1 n\u0027est plus administrateur"
},
{
"LogLevel": 2,
"Message": "L utilisateur testeur1 a ete mis en administrateur"
},
{
"LogLevel": 2,
"Message": "Supretion de l utilisateur : dev"
},
{
"LogLevel": 2,
"Message": "Modification de la quote Que la force soit avec toi."
},
{
"LogLevel": 2,
"Message": "La quote Que la force soit avec toi a ete suprimer"
},
{
"LogLevel": 2,
"Message": "Cr\u00E9ation de la question coucou"
},
{
"LogLevel": 2,
"Message": "Modification de la question coucou."
},
{
"LogLevel": 2,
"Message": "Supretion de la question coucou."
}
]

@ -12,14 +12,14 @@
},
{
"Id": 12,
"Question": "Irure occaecat sit laborum nul ea dolore et aliqua sunt Lorem enim esse.",
"AnswerA": "excepteur occaecat",
"AnswerB": "pariatur in",
"AnswerC": "reprehenderit excepteur",
"AnswerD": "laborum adipisicing",
"CAnswer": "D",
"Question": "question",
"AnswerA": "repA",
"AnswerB": "non",
"AnswerC": "do",
"AnswerD": "ut",
"CAnswer": "A",
"IsValid": false,
"UserProposition": "Shields Roth"
"UserProposition": "Brooks Martinez"
},
{
"Id": 13,

@ -2,7 +2,7 @@
{
"Id": 3,
"Image": "https://tse4.mm.bing.net/th/id/OIP.XNQPKwc1OUfvnSO9MsxDYgHaE7?w=202\u0026h=180\u0026c=7\u0026r=0\u0026o=5\u0026pid=1.7",
"Name": "testeur",
"Name": "testeur1",
"Email": "testeur@gmail.com",
"DateCreation": "2024-08-02T00:00:00",
"IsAdmin": true,

Loading…
Cancel
Save