308 lines
12 KiB
C#
308 lines
12 KiB
C#
using Manager.DTOs;
|
||
using Manager.Helpers;
|
||
using ManagerService.Data;
|
||
using ManagerService.Data.SubSection;
|
||
using ManagerService.DTOs;
|
||
using ManagerService.Services;
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Configuration;
|
||
using Microsoft.Extensions.Logging;
|
||
using Mqtt.Client.AspNetCore.Services;
|
||
using Newtonsoft.Json;
|
||
using NSwag.Annotations;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Reflection.Emit;
|
||
using System.Security.Cryptography;
|
||
using System.Text.Json;
|
||
|
||
namespace ManagerService.Controllers
|
||
{
|
||
[Authorize(Policy = ManagerService.Service.Security.Policies.ContentEditor)]
|
||
[ApiController, Route("api/[controller]")]
|
||
[OpenApiTag("Section quiz", Description = "Section quiz management")]
|
||
public class SectionQuizController : ControllerBase
|
||
{
|
||
private readonly MyInfoMateDbContext _myInfoMateDbContext;
|
||
|
||
private readonly ILogger<SectionQuizController> _logger;
|
||
private readonly IConfiguration _configuration;
|
||
IHexIdGeneratorService idService = new HexIdGeneratorService();
|
||
|
||
public SectionQuizController(IConfiguration configuration, ILogger<SectionQuizController> logger, MyInfoMateDbContext myInfoMateDbContext)
|
||
{
|
||
_logger = logger;
|
||
_configuration = configuration;
|
||
_myInfoMateDbContext = myInfoMateDbContext;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Get all quiz questions from section
|
||
/// </summary>
|
||
/// <param name="sectionId">Section id</param>
|
||
[AllowAnonymous]
|
||
[ProducesResponseType(typeof(List<QuestionDTO>), 200)]
|
||
[ProducesResponseType(typeof(string), 404)]
|
||
[ProducesResponseType(typeof(string), 500)]
|
||
[HttpGet("{sectionId}/questions")]
|
||
public ObjectResult GetAllQuizQuestionFromSection(string sectionId)
|
||
{
|
||
try
|
||
{
|
||
SectionQuiz sectionQuiz = _myInfoMateDbContext.Sections.OfType<SectionQuiz>().Include(sq => sq.QuizQuestions).ThenInclude(qq => qq.Resource).FirstOrDefault(sq => sq.Id == sectionId);
|
||
|
||
List<QuestionDTO> questionDTOs = new List<QuestionDTO>();
|
||
foreach (var question in sectionQuiz.QuizQuestions)
|
||
{
|
||
questionDTOs.Add(new QuestionDTO()
|
||
{
|
||
id = question.Id,
|
||
label = question.Label,
|
||
responses = question.Responses,
|
||
imageBackgroundResourceId = question.ResourceId,
|
||
imageBackgroundResourceType = question.Resource?.Type,
|
||
imageBackgroundResourceUrl = question.Resource?.Url,
|
||
order = question.Order
|
||
});
|
||
}
|
||
|
||
return new OkObjectResult(questionDTOs);
|
||
}
|
||
catch (KeyNotFoundException ex)
|
||
{
|
||
return new NotFoundObjectResult(ex.Message) { };
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Create new question
|
||
/// </summary>
|
||
/// <param name="sectionId">Section Id</param>
|
||
/// <param name="questionDTO">question</param>
|
||
[ProducesResponseType(typeof(QuestionDTO), 200)]
|
||
[ProducesResponseType(typeof(string), 400)]
|
||
[ProducesResponseType(typeof(string), 409)]
|
||
[ProducesResponseType(typeof(string), 500)]
|
||
[HttpPost("{sectionId}/questions")]
|
||
public ObjectResult Create(string sectionId, [FromBody] QuestionDTO questionDTO)
|
||
{
|
||
try
|
||
{
|
||
if (sectionId == null)
|
||
throw new ArgumentNullException("Section param is null");
|
||
|
||
if (questionDTO == null)
|
||
throw new ArgumentNullException("Question is null");
|
||
|
||
var existingSection = _myInfoMateDbContext.Sections.OfType<SectionQuiz>().Include(sq => sq.QuizQuestions).ThenInclude(qq => qq.Resource).FirstOrDefault(sq => sq.Id == sectionId);
|
||
if (existingSection == null)
|
||
throw new KeyNotFoundException("Section quiz does not exist");
|
||
|
||
// TODO verification ?
|
||
QuizQuestion quizQuestion = new QuizQuestion();
|
||
quizQuestion.Label = questionDTO.label;
|
||
quizQuestion.Responses = questionDTO.responses;
|
||
quizQuestion.ResourceId = questionDTO.imageBackgroundResourceId;
|
||
quizQuestion.Order = existingSection.QuizQuestions.Count();
|
||
|
||
existingSection.QuizQuestions.Add(quizQuestion);
|
||
|
||
_myInfoMateDbContext.SaveChanges();
|
||
|
||
var questionDTOToSend = new QuestionDTO()
|
||
{
|
||
id = quizQuestion.Id,
|
||
label = quizQuestion.Label,
|
||
responses = quizQuestion.Responses,
|
||
imageBackgroundResourceId = quizQuestion.ResourceId,
|
||
imageBackgroundResourceType = quizQuestion.Resource?.Type,
|
||
imageBackgroundResourceUrl = quizQuestion.Resource?.Url,
|
||
order = quizQuestion.Order
|
||
};
|
||
|
||
return new OkObjectResult(questionDTOToSend);
|
||
}
|
||
catch (ArgumentNullException ex)
|
||
{
|
||
return new BadRequestObjectResult(ex.Message) { };
|
||
}
|
||
catch (InvalidOperationException ex)
|
||
{
|
||
return new ConflictObjectResult(ex.Message) { };
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update a quiz question
|
||
/// </summary>
|
||
/// <param name="updatedQuizQuestion">QuizQuestion to update</param>
|
||
[ProducesResponseType(typeof(QuestionDTO), 200)]
|
||
[ProducesResponseType(typeof(string), 400)]
|
||
[ProducesResponseType(typeof(string), 404)]
|
||
[ProducesResponseType(typeof(string), 500)]
|
||
[HttpPut]
|
||
public ObjectResult Update([FromBody] QuestionDTO questionDTO)
|
||
{
|
||
try
|
||
{
|
||
if (questionDTO == null)
|
||
throw new ArgumentNullException("Question param is null");
|
||
|
||
var existingQuestion = _myInfoMateDbContext.QuizQuestions.FirstOrDefault(qq => qq.Id == questionDTO.id);
|
||
if (existingQuestion == null)
|
||
throw new KeyNotFoundException("Question quiz does not exist");
|
||
|
||
if (questionDTO.order != existingQuestion.Order)
|
||
{
|
||
// Order update
|
||
var existingSection = _myInfoMateDbContext.Sections.OfType<SectionQuiz>().Include(sq => sq.QuizQuestions.OrderBy(q => q.Order)).FirstOrDefault(sq => sq.Id == existingQuestion.SectionQuizId);
|
||
|
||
if (existingSection == null)
|
||
throw new Exception("Section quiz not found");
|
||
|
||
var questions = existingSection.QuizQuestions.OrderBy(q => q.Order).ToList();
|
||
|
||
// Retirer la question d<>plac<61>e
|
||
questions.RemoveAll(q => q.Id == existingQuestion.Id);
|
||
|
||
// Ins<6E>rer <20> la nouvelle position (d<>j<EFBFBD> en 0-based)
|
||
int newIndex = questionDTO.order.Value;
|
||
newIndex = Math.Clamp(newIndex, 0, questions.Count);
|
||
questions.Insert(newIndex, existingQuestion);
|
||
|
||
// R<>assigner les ordres en 0-based
|
||
for (int i = 0; i < questions.Count; i++)
|
||
{
|
||
questions[i].Order = i;
|
||
}
|
||
|
||
}
|
||
else {
|
||
// Simple update
|
||
existingQuestion.Label = questionDTO.label;
|
||
existingQuestion.Responses = questionDTO.responses;
|
||
existingQuestion.Order = questionDTO.order.Value; // TO TEST
|
||
existingQuestion.ResourceId = questionDTO.imageBackgroundResourceId;
|
||
}
|
||
|
||
_myInfoMateDbContext.SaveChanges();
|
||
|
||
return new OkObjectResult(questionDTO);
|
||
}
|
||
catch (ArgumentNullException ex)
|
||
{
|
||
return new BadRequestObjectResult(ex.Message) { };
|
||
}
|
||
catch (KeyNotFoundException ex)
|
||
{
|
||
return new NotFoundObjectResult(ex.Message) { };
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update sections order
|
||
/// </summary>
|
||
/// <param name="updatedSectionsOrder">New sections order</param>
|
||
/*[ProducesResponseType(typeof(string), 200)]
|
||
[ProducesResponseType(typeof(string), 400)]
|
||
[ProducesResponseType(typeof(string), 404)]
|
||
[ProducesResponseType(typeof(string), 500)]
|
||
[HttpPut("order")]
|
||
public ObjectResult UpdateOrder([FromBody] List<SectionDTO> updatedSectionsOrder)
|
||
{
|
||
// TODO REWRITE LOGIC..
|
||
try
|
||
{
|
||
if (updatedSectionsOrder == null)
|
||
throw new ArgumentNullException("Sections param is null");
|
||
|
||
foreach (var section in updatedSectionsOrder)
|
||
{
|
||
var sectionDB = _myInfoMateDbContext.Sections.FirstOrDefault(s => s.Id == section.id);
|
||
if (sectionDB == null)
|
||
throw new KeyNotFoundException($"Section {section.label} with id {section.id} does not exist");
|
||
}
|
||
|
||
foreach (var updatedSection in updatedSectionsOrder)
|
||
{
|
||
var section = _myInfoMateDbContext.Sections.FirstOrDefault(s => s.Id == updatedSection.id);
|
||
//OldSection section = _sectionService.GetById(updatedSection.id);
|
||
section.Order = updatedSection.order.GetValueOrDefault();
|
||
_myInfoMateDbContext.SaveChanges();
|
||
|
||
//_sectionService.Update(section.Id, section);
|
||
}
|
||
|
||
if (updatedSectionsOrder.Count > 0) {
|
||
MqttClientService.PublishMessage($"config/{updatedSectionsOrder[0].configurationId}", JsonConvert.SerializeObject(new PlayerMessageDTO() { configChanged = true }));
|
||
}
|
||
|
||
return new ObjectResult("Sections order has been successfully modified") { StatusCode = 200 };
|
||
}
|
||
catch (ArgumentNullException ex)
|
||
{
|
||
return new BadRequestObjectResult(ex.Message) { };
|
||
}
|
||
catch (KeyNotFoundException ex)
|
||
{
|
||
return new NotFoundObjectResult(ex.Message) { };
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||
}
|
||
}*/
|
||
|
||
|
||
/// <summary>
|
||
/// Delete a quiz question
|
||
/// </summary>
|
||
/// <param name="quizQuestionId">Id of quizQuestion to delete</param>
|
||
[ProducesResponseType(typeof(string), 202)]
|
||
[ProducesResponseType(typeof(string), 404)]
|
||
[ProducesResponseType(typeof(string), 500)]
|
||
[HttpDelete("questions/delete/{quizQuestionId}")]
|
||
public ObjectResult Delete(int quizQuestionId)
|
||
{
|
||
try
|
||
{
|
||
var quizQuestion = _myInfoMateDbContext.QuizQuestions.FirstOrDefault(qq => qq.Id == quizQuestionId);
|
||
if (quizQuestion == null)
|
||
throw new KeyNotFoundException("QuizQuestion does not exist");
|
||
|
||
_myInfoMateDbContext.Remove(quizQuestion);
|
||
_myInfoMateDbContext.SaveChanges();
|
||
|
||
return new ObjectResult("The quiz question has been deleted") { StatusCode = 202 };
|
||
}
|
||
catch (ArgumentNullException ex)
|
||
{
|
||
return new BadRequestObjectResult(ex.Message) { };
|
||
}
|
||
catch (KeyNotFoundException ex)
|
||
{
|
||
return new NotFoundObjectResult(ex.Message) { };
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||
}
|
||
}
|
||
}
|
||
}
|