From c62f070e39a55f5559c7ea1923e6c6a0dccee479 Mon Sep 17 00:00:00 2001 From: Samy Avrillon Date: Tue, 10 Jun 2025 23:53:48 +0200 Subject: [PATCH] =?UTF-8?q?Ajout=20d'une=20page=20d'=C3=A9dition=20des=20q?= =?UTF-8?q?uizz?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../com/bernard/misael/model/Question.java | 9 +- .../bernard/misael/questions/DccQuestion.java | 32 +++ .../com/bernard/misael/questions/QTypes.java | 15 +- .../misael/repository/QuestionRepository.java | 3 + .../bernard/misael/service/QuizzManager.java | 11 + .../misael/service/QuizzManagerImpl.java | 232 ++++++++++++++++++ .../misael/web/QuestionsController.java | 126 ++++++++++ src/main/resources/application.yml | 4 + src/main/resources/static/css/quizz-edit.css | 41 ++++ src/main/resources/templates/quizz-edit.html | 204 +++++++++++++++ src/main/resources/templates/quizz.html | 2 +- .../misael/MisaelApplicationTests.java | 9 + versions.properties | 2 + 14 files changed, 684 insertions(+), 7 deletions(-) create mode 100644 src/main/resources/static/css/quizz-edit.css create mode 100644 src/main/resources/templates/quizz-edit.html diff --git a/build.gradle b/build.gradle index bad4fb6..26e6f64 100644 --- a/build.gradle +++ b/build.gradle @@ -41,6 +41,7 @@ dependencies { implementation Spring.session.jdbc implementation 'jakarta.validation:jakarta.validation-api:_' runtimeOnly 'org.webjars:jquery:_' + runtimeOnly 'org.webjars:lodash:_' developmentOnly Spring.boot.devTools runtimeOnly 'org.postgresql:postgresql:_' testImplementation Spring.boot.test diff --git a/src/main/java/com/bernard/misael/model/Question.java b/src/main/java/com/bernard/misael/model/Question.java index fe8d1fe..c0717d9 100644 --- a/src/main/java/com/bernard/misael/model/Question.java +++ b/src/main/java/com/bernard/misael/model/Question.java @@ -7,15 +7,12 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.persistence.*; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter -@Setter @NoArgsConstructor -@AllArgsConstructor @Entity @Table(name="questions") public class Question { @@ -26,15 +23,19 @@ public class Question { private long id; @Column(nullable=false) + @Setter QTypes type; @Column(nullable=false) + @Setter private int index; @ManyToOne @JoinColumn(name = "quizz",nullable = false) + @Setter private Quizz quizz; + @Setter private String value; transient QuestionType qtype = null; @@ -44,7 +45,7 @@ public class Question { JsonNode jsNode; try { jsNode = om.readTree(value); - qtype = type.getConstructor().apply(jsNode); + qtype = type.construct(jsNode); } catch (JsonProcessingException e) { throw new IllegalStateException(e); } diff --git a/src/main/java/com/bernard/misael/questions/DccQuestion.java b/src/main/java/com/bernard/misael/questions/DccQuestion.java index fbe0382..df0fb2e 100644 --- a/src/main/java/com/bernard/misael/questions/DccQuestion.java +++ b/src/main/java/com/bernard/misael/questions/DccQuestion.java @@ -4,12 +4,20 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.bernard.misael.service.exception.MalformedAnswerException; import com.bernard.misael.service.exception.MalformedClientAnswerException; import com.bernard.misael.service.exception.QuestionTypeException; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -82,4 +90,28 @@ public class DccQuestion implements QuestionType{ } } + public static Logger LOG = LoggerFactory.getLogger(DccQuestion.class); + + public static boolean validate(JsonNode data) { + LOG.info(data.toPrettyString()); + LOG.info(Stream.of(data.get("wrong")).map(p -> p.isTextual()+"->"+p).collect(Collectors.joining(";"))); + return data.isObject() && + data.has("text") && data.get("text").isTextual() && + data.has("good") && data.get("good").isTextual() && + data.has("wrong") && data.get("wrong").isArray() && + data.get("wrong").size() >= 3 && + StreamSupport.stream(Spliterators.spliterator(data.get("wrong").elements(),data.get("wrong").size(),Spliterator.SIZED),false).allMatch(p -> + p.isTextual() + ); + } + + public static final JsonNode getDefaultDccQuestion() { + ObjectNode q = JsonNodeFactory.instance.objectNode(); + q.set("text",JsonNodeFactory.instance.textNode("")); + q.set("good",JsonNodeFactory.instance.textNode("")); + ArrayNode wrong = JsonNodeFactory.instance.arrayNode(3); + for(int i=0;i<3;i++)wrong.add(JsonNodeFactory.instance.textNode("")); + q.set("wrong",wrong); + return q; + } } diff --git a/src/main/java/com/bernard/misael/questions/QTypes.java b/src/main/java/com/bernard/misael/questions/QTypes.java index a29b608..77024ab 100644 --- a/src/main/java/com/bernard/misael/questions/QTypes.java +++ b/src/main/java/com/bernard/misael/questions/QTypes.java @@ -7,15 +7,18 @@ import com.fasterxml.jackson.databind.JsonNode; import lombok.AllArgsConstructor; import lombok.Getter; -@Getter @AllArgsConstructor public enum QTypes { - DCC(1,DccQuestion.class,DccQuestion::new); + DCC(1,DccQuestion.class,DccQuestion::new,DccQuestion::validate,DccQuestion.getDefaultDccQuestion()); private int id; + @SuppressWarnings("unused") private Class type; private Function constructor; + private Function validator; + @Getter + private JsonNode defaultQuestion; public static QTypes findById(final int id) { for(QTypes value : QTypes.values()) @@ -24,4 +27,12 @@ public enum QTypes { return null; } + public QuestionType construct(JsonNode data){ + return this.constructor.apply(data); + } + + public boolean validate(JsonNode data){ + return this.validator.apply(data); + } + } diff --git a/src/main/java/com/bernard/misael/repository/QuestionRepository.java b/src/main/java/com/bernard/misael/repository/QuestionRepository.java index fa6041d..cdc7a2d 100644 --- a/src/main/java/com/bernard/misael/repository/QuestionRepository.java +++ b/src/main/java/com/bernard/misael/repository/QuestionRepository.java @@ -1,5 +1,7 @@ package com.bernard.misael.repository; +import java.util.Set; + import org.springframework.data.jpa.repository.JpaRepository; import com.bernard.misael.model.Question; @@ -9,5 +11,6 @@ import com.bernard.misael.model.Quizz; public interface QuestionRepository extends JpaRepository { public Question findByQuizzAndIndex(Quizz quizz, int index); + public Set findByQuizz(Quizz quizz); } \ No newline at end of file diff --git a/src/main/java/com/bernard/misael/service/QuizzManager.java b/src/main/java/com/bernard/misael/service/QuizzManager.java index 9cbc276..a9702bf 100644 --- a/src/main/java/com/bernard/misael/service/QuizzManager.java +++ b/src/main/java/com/bernard/misael/service/QuizzManager.java @@ -4,6 +4,7 @@ import java.util.List; import com.bernard.misael.model.Quizz; import com.bernard.misael.model.User; +import com.bernard.misael.questions.QTypes; import com.fasterxml.jackson.databind.JsonNode; public interface QuizzManager { @@ -13,5 +14,15 @@ public interface QuizzManager { public boolean canAccessQuizz(User user, long quizzId); public List accessibleQuizz(User user); + + public boolean canEditQuizz(User user, long quizzId); + + public JsonNode getQuizzInfo(User user, long quizzId); + public JsonNode setQuizzName(User user, long quizzId, String newName); + public JsonNode addQuestion(User user, long quizzId); + public JsonNode removeQuestion(User user, long quizzId, long questionId); + public JsonNode reorderQuestions(User user, long quizzId, List newOrder); + public JsonNode editQuestion(User user, long quizzId, long questionId, JsonNode value); + public JsonNode setQuestionType(User user, long quizzId, long questionId, QTypes type); } \ No newline at end of file diff --git a/src/main/java/com/bernard/misael/service/QuizzManagerImpl.java b/src/main/java/com/bernard/misael/service/QuizzManagerImpl.java index dd48f51..a3ab954 100644 --- a/src/main/java/com/bernard/misael/service/QuizzManagerImpl.java +++ b/src/main/java/com/bernard/misael/service/QuizzManagerImpl.java @@ -1,11 +1,15 @@ package com.bernard.misael.service; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -14,6 +18,7 @@ import com.bernard.misael.model.Question; import com.bernard.misael.model.Quizz; import com.bernard.misael.model.QuizzForm; import com.bernard.misael.model.User; +import com.bernard.misael.questions.QTypes; import com.bernard.misael.questions.QuestionType.AnswerResult; import com.bernard.misael.repository.AnswerRepository; import com.bernard.misael.repository.QuestionRepository; @@ -22,7 +27,11 @@ import com.bernard.misael.repository.QuizzRepository; import com.bernard.misael.service.exception.MalformedAnswerException; import com.bernard.misael.service.exception.MalformedClientAnswerException; import com.bernard.misael.service.exception.QuestionTypeException; +import com.bernard.misael.web.QuestionsController; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -198,4 +207,227 @@ public class QuizzManagerImpl implements QuizzManager { ).collect(Collectors.toList()); } + Logger logger = LoggerFactory.getLogger(QuestionsController.class); + @Override + public boolean canEditQuizz(User user, long quizzId) { + try { + Quizz quizz = qRepository.getReferenceById(quizzId); + logger.info("Quizz owner is "+quizz.getOwner().getName()); + return quizz.getOwner().equals(user); + } catch (EntityNotFoundException e) { + logger.info("Could not find quizz of id "+quizzId); + return false; + } + } + + private Optional checkEditQuizz(User user, long quizzId) { + if(user == null) + return Optional.of(errorNode("You need to be logged in to edit the quizz")); + if(!canEditQuizz(user, quizzId)) + return Optional.of(errorNode("User has no right to edit quizz")); + Optional oquizz = qRepository.findById(quizzId); + if(!oquizz.isPresent()) + return Optional.of(errorNode("Could not find quizz with id "+quizzId)); + return Optional.empty(); + } + + + @Override + public JsonNode getQuizzInfo(User user, long quizzId) { + Optional authCheck = checkEditQuizz(user, quizzId); + if(authCheck.isPresent()) return authCheck.get(); + + Quizz quizz = qRepository.findById(quizzId).get(); + + ArrayNode n = JsonNodeFactory.instance.arrayNode(quizz.getQuestionCount()); + for(int i = 0;i authCheck = checkEditQuizz(user, quizzId); + if(authCheck.isPresent()) return authCheck.get(); + + if(newName.isBlank() | newName.length()>255) + return errorNode("Le nom est invalide"); + + Quizz quizz = qRepository.findById(quizzId).get(); + + quizz.setName(newName); + ObjectNode out = JsonNodeFactory.instance.objectNode(); + out.set("success", JsonNodeFactory.instance.booleanNode(true)); + return out; + } + + public static final QTypes DEFAULT_QTYPE = QTypes.DCC; + + @Override + public JsonNode addQuestion(User user, long quizzId) { + Optional authCheck = checkEditQuizz(user, quizzId); + if(authCheck.isPresent()) return authCheck.get(); + + Quizz quizz = qRepository.findById(quizzId).get(); + + Question q = new Question(); + q.setType(DEFAULT_QTYPE); + JsonNode n = DEFAULT_QTYPE.getDefaultQuestion(); + q.setValue(n.toString()); + q.setQuizz(quizz); + q.setIndex(quizz.getQuestionCount()); + quizz.setQuestionCount(quizz.getQuestionCount()+1); + questionRepository.save(q); + + ObjectNode out = JsonNodeFactory.instance.objectNode(); + out.set("success", JsonNodeFactory.instance.booleanNode(true)); + out.set("type", JsonNodeFactory.instance.textNode(DEFAULT_QTYPE.name())); + out.set("value", n); + return out; + } + + @Override + public JsonNode removeQuestion(User user, long quizzId, long questionId) { + Optional authCheck = checkEditQuizz(user, quizzId); + if(authCheck.isPresent()) return authCheck.get(); + + Quizz quizz = qRepository.findById(quizzId).get(); + + final Question q; + try { + q = questionRepository.getReferenceById(questionId); + } catch (EntityNotFoundException e){ + return errorNode("Could not find question with id "+questionId); + } + + questionRepository.findByQuizz(quizz).forEach(qq -> { + if(qq.getIndex()>q.getIndex()) + qq.setIndex(qq.getIndex()-1); + }); + questionRepository.delete(q); + quizz.setQuestionCount(quizz.getQuestionCount()-1); + + ObjectNode out = JsonNodeFactory.instance.objectNode(); + out.set("success", JsonNodeFactory.instance.booleanNode(true)); + return out; + } + + @Override + public JsonNode reorderQuestions(User user, long quizzId, List newOrder) { + Optional authCheck = checkEditQuizz(user, quizzId); + if(authCheck.isPresent()) return authCheck.get(); + + Quizz quizz = qRepository.findById(quizzId).get(); + + // We need that the base set of neworder is the list of ids + // 1) The length is right + if(quizz.getQuestionCount() != newOrder.size()) + return errorNode("You must put every question in order"); + // 2) There is no duplicates + if(new HashSet(newOrder).size() != newOrder.size()) + return errorNode("You shouldn't put duplicates in the new order"); + // 3) All ids correspond to an actual question of the right quizz + List questions = new ArrayList<>(newOrder.size()); + for(int i = 0;i authCheck = checkEditQuizz(user, quizzId); + if(authCheck.isPresent()) return authCheck.get(); + + Quizz quizz = qRepository.findById(quizzId).get(); + + final Question q; + try { + q = questionRepository.getReferenceById(questionId); + } catch (EntityNotFoundException e){ + return errorNode("Could not find question with id "+questionId); + } + + if(!q.getQuizz().equals(quizz)) + return errorNode("Question is not associated with the right quizzId"); + + if(!q.getType().validate(value)) + return errorNode("Invalid question value"); + q.setValue(value.toString()); + + ObjectNode out = JsonNodeFactory.instance.objectNode(); + out.set("success", JsonNodeFactory.instance.booleanNode(true)); + return out; + } + + @Override + public JsonNode setQuestionType(User user, long quizzId, long questionId, QTypes type) { + Optional authCheck = checkEditQuizz(user, quizzId); + if(authCheck.isPresent()) return authCheck.get(); + + Quizz quizz = qRepository.findById(quizzId).get(); + + final Question q; + try { + q = questionRepository.getReferenceById(questionId); + } catch (EntityNotFoundException e){ + return errorNode("Could not find question with id "+questionId); + } + + if(!q.getQuizz().equals(quizz)) + return errorNode("Question is not associated with the right quizzId"); + + // If type is the same, we don't change (and dont reset the value) + JsonNode n; + if(!type.equals(q.getType())) { + // Then we need to change + q.setType(type); + n = type.getDefaultQuestion(); + q.setValue(n.toString()); + } else { + ObjectMapper om = new ObjectMapper(); + try { + n = om.readTree(q.getValue()); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Value stored for question "+questionId+" is illegal (non-json)",e); + } + } + + ObjectNode out = JsonNodeFactory.instance.objectNode(); + out.set("success", JsonNodeFactory.instance.booleanNode(true)); + out.set("new", n); + return out; + } + } diff --git a/src/main/java/com/bernard/misael/web/QuestionsController.java b/src/main/java/com/bernard/misael/web/QuestionsController.java index e3a4822..1de47cb 100644 --- a/src/main/java/com/bernard/misael/web/QuestionsController.java +++ b/src/main/java/com/bernard/misael/web/QuestionsController.java @@ -1,7 +1,13 @@ package com.bernard.misael.web; import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -11,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import com.bernard.misael.model.Quizz; import com.bernard.misael.model.User; +import com.bernard.misael.questions.QTypes; import com.bernard.misael.repository.QuizzRepository; import com.bernard.misael.repository.UserRepository; import com.bernard.misael.service.QuizzManager; @@ -24,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestBody; + @Controller @RequestMapping("/questions") public class QuestionsController { @@ -89,7 +97,125 @@ public class QuestionsController { JsonNode out = qm.answer(u, quizzId, data); return new ResponseEntity<>(out, HttpStatus.OK); } + + + Logger logger = LoggerFactory.getLogger(QuestionsController.class); + @GetMapping("/quizz-edit/{q}") + public Object quizzEdit(@PathVariable("q") long quizzId, Principal p, Model m) { + if (p==null) + return "redirect:/login?restricted"; + User u = ur.findByName(p.getName()); + logger.info("An INFO Message"); + if (u==null || !qm.canEditQuizz(u, quizzId)) + return new ResponseEntity<>(HttpStatus.FORBIDDEN); + m.addAttribute("quizzId", quizzId); + + return "quizz-edit"; + } + + @PostMapping("/quizz-edit/{q}/get") + public ResponseEntity quizzSetName(@PathVariable("q") long quizzId, Principal p) { + User u = null; + if (p!=null) + u = ur.findByName(p.getName()); + if(u==null) + return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED); + JsonNode out = qm.getQuizzInfo(u, quizzId); + return new ResponseEntity<>(out, HttpStatus.OK); + } + + @PostMapping("/quizz-edit/{q}/set-name") + public ResponseEntity quizzSetName(@PathVariable("q") long quizzId, @RequestBody String data, Principal p) { + User u = null; + if (p!=null) + u = ur.findByName(p.getName()); + if(u==null) + return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED); + JsonNode out = qm.setQuizzName(u, quizzId, data); + return new ResponseEntity<>(out, HttpStatus.OK); + } + + @PostMapping("/quizz-edit/{q}/add-question") + public ResponseEntity quizzAddQuestion(@PathVariable("q") long quizzId, Principal p) { + User u = null; + if (p!=null) + u = ur.findByName(p.getName()); + if(u==null) + return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED); + JsonNode out = qm.addQuestion(u, quizzId); + return new ResponseEntity<>(out, HttpStatus.OK); + } + + @PostMapping("/quizz-edit/{q}/remove-question/{qi}") + public ResponseEntity quizzSetName(@PathVariable("q") long quizzId, @PathVariable("qi") long questionId, Principal p) { + User u = null; + if (p!=null) + u = ur.findByName(p.getName()); + if(u==null) + return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED); + JsonNode out = qm.removeQuestion(u, quizzId, questionId); + return new ResponseEntity<>(out, HttpStatus.OK); + } + @PostMapping("/quizz-edit/{q}/reorder-questions") + public ResponseEntity quizzReorderQuestions(@PathVariable("q") long quizzId, @RequestBody JsonNode data, Principal p) { + User u = null; + if (p!=null) + u = ur.findByName(p.getName()); + if(u==null) + return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED); + if(!data.isArray()) + return new ResponseEntity<>( + JsonNodeFactory.instance.textNode("Data should be an array"), + HttpStatus.BAD_REQUEST); + List idz = new ArrayList<>(data.size()); + for(int i=0;i( + JsonNodeFactory.instance.textNode("Data should be an array of numbers"), + HttpStatus.BAD_REQUEST); + JsonNode out = qm.reorderQuestions(u, quizzId, idz); + return new ResponseEntity<>(out, HttpStatus.OK); + } + + @PostMapping("/quizz-edit/{q}/edit-question/{qi}") + public ResponseEntity quizzEditQuestion(@PathVariable("q") long quizzId, + @PathVariable("qi") long questionId, @RequestBody JsonNode data, Principal p) { + User u = null; + if (p!=null) + u = ur.findByName(p.getName()); + if(u==null) + return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED); + + JsonNode out = qm.editQuestion(u, quizzId, questionId, data); + return new ResponseEntity<>(out, HttpStatus.OK); + } + + @PostMapping("/quizz-edit/{q}/set-question-type/{qi}") + public ResponseEntity quizzSetQuestionType(@PathVariable("q") long quizzId, + @PathVariable("qi") long questionId, @RequestBody JsonNode data, Principal p) { + User u = null; + if (p!=null) + u = ur.findByName(p.getName()); + if(u==null) + return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED); + if(!data.isTextual()) + return new ResponseEntity<>( + JsonNodeFactory.instance.textNode("Data should be a string"), + HttpStatus.BAD_REQUEST); + Optional qtype = Arrays.stream(QTypes.values()) + .filter(q -> q.name().equals(data.textValue())) + .findAny(); + if(qtype.isEmpty()) + return new ResponseEntity<>( + JsonNodeFactory.instance.textNode("Unknown qtype"), + HttpStatus.BAD_REQUEST); + + JsonNode out = qm.setQuestionType(u, quizzId, questionId, qtype.get()); + return new ResponseEntity<>(out, HttpStatus.OK); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 63c7b6d..ccfa83e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -33,3 +33,7 @@ spring: hibernate: ddl-auto: none generate-ddl: true + +logging: + level: + root: INFO \ No newline at end of file diff --git a/src/main/resources/static/css/quizz-edit.css b/src/main/resources/static/css/quizz-edit.css new file mode 100644 index 0000000..820812c --- /dev/null +++ b/src/main/resources/static/css/quizz-edit.css @@ -0,0 +1,41 @@ +ol#questions-list { + display: table; + border-spacing: 2px; + width: 90%; +} +ol#questions-list li { + width: 90%; + background-color: lemonchiffon; + border: 2pt solid; + display: table-row; + flex-direction: row; + align-items: stretch; + margin: auto; +} + +ol#questions-list li div.button-box { + display:table-cell; + text-align: center; + vertical-align: middle; + width: 7em; +} + +ol#questions-list li div.button-box button{ + width: 7em; +} + +ol#questions-list li div.content-box { + display:table-cell; + background-color: gainsboro; + color: black; + font-size: 12pt; +} + + +/* DCC */ +div.dcc-box h5, div.dcc-box h5 input{ + font-size: 16pt; + font-weight: bold; + text-decoration: underline; + width: 100%; +} \ No newline at end of file diff --git a/src/main/resources/templates/quizz-edit.html b/src/main/resources/templates/quizz-edit.html new file mode 100644 index 0000000..9b07195 --- /dev/null +++ b/src/main/resources/templates/quizz-edit.html @@ -0,0 +1,204 @@ + + + +
+ + + + +
+ + +
+

Quizz

+
    +
+ + + +
+ + \ No newline at end of file diff --git a/src/main/resources/templates/quizz.html b/src/main/resources/templates/quizz.html index ad7071c..d9c89b9 100644 --- a/src/main/resources/templates/quizz.html +++ b/src/main/resources/templates/quizz.html @@ -8,7 +8,7 @@
    -
  • Premier item ?
  • +
  • Aucun quizz de disponible malheureusement :(
  • Quizz
diff --git a/src/test/java/com/bernard/misael/MisaelApplicationTests.java b/src/test/java/com/bernard/misael/MisaelApplicationTests.java index 141c486..d4e7097 100644 --- a/src/test/java/com/bernard/misael/MisaelApplicationTests.java +++ b/src/test/java/com/bernard/misael/MisaelApplicationTests.java @@ -3,6 +3,8 @@ package com.bernard.misael; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import com.bernard.misael.questions.QTypes; + @SpringBootTest class MisaelApplicationTests { @@ -10,4 +12,11 @@ class MisaelApplicationTests { void contextLoads() { } + @Test + void validateDefaultQuestions() { + for(QTypes qt : QTypes.values()){ + assert qt.validate(qt.getDefaultQuestion()); + } + } + } diff --git a/versions.properties b/versions.properties index 911e907..69c3388 100644 --- a/versions.properties +++ b/versions.properties @@ -96,3 +96,5 @@ plugin.org.flywaydb.flyway=11.3.2 ## # available=11.3.4 plugin.io.spring.dependency-management=1.1.7 + +version.org.webjars..lodash=4.17.21