From 3fc334836c61eae091a0ff03e1a5f5cd1cd45adb Mon Sep 17 00:00:00 2001 From: Olivier Bado-Faustin Date: Thu, 6 Jun 2024 10:32:45 +0200 Subject: [PATCH] [DONE] Some corrections on Video QUIZ (#1146) * Some corrections on Video QUIZ : * Replace some b tags by strong * Correct collapsed state of video completion accordion * JS : replace "checkValidity" by "reportValidity" to use browser validation process and UI * Comment some unused JS funcs in playlists * Display question number on some help texts * Code formatting * Split update_questions in 2 functions for Flake8 compliance (less complexity) --- pod/ai_enhancement/utils.py | 2 +- pod/ai_enhancement/views.py | 4 +- .../templates/video_completion.html | 48 ++- pod/completion/urls.py | 1 + pod/locale/fr/LC_MESSAGES/django.mo | Bin 220028 -> 220213 bytes pod/locale/fr/LC_MESSAGES/django.po | 299 +++++++++--------- pod/locale/fr/LC_MESSAGES/djangojs.mo | Bin 21460 -> 21857 bytes pod/locale/fr/LC_MESSAGES/djangojs.po | 54 +++- pod/locale/nl/LC_MESSAGES/django.mo | Bin 2059 -> 2059 bytes pod/locale/nl/LC_MESSAGES/django.po | 138 ++++---- pod/locale/nl/LC_MESSAGES/djangojs.mo | Bin 413 -> 413 bytes pod/locale/nl/LC_MESSAGES/djangojs.po | 44 ++- pod/main/static/css/pod.css | 12 +- pod/main/static/js/main.js | 3 +- pod/meeting/views.py | 4 +- .../static/playlist/js/playlist-reorganize.js | 10 +- pod/quiz/forms.py | 42 +-- pod/quiz/models.py | 86 +++-- pod/quiz/static/quiz/js/create-quiz.js | 191 ++++++----- pod/quiz/static/quiz/js/video-quiz-submit.js | 44 ++- pod/quiz/templates/quiz/create_edit_quiz.html | 52 ++- pod/quiz/templates/quiz/delete_quiz.html | 4 +- pod/quiz/templates/quiz/manage_quiz.html | 21 ++ pod/quiz/templates/quiz/question_form.html | 30 +- pod/quiz/templates/quiz/video_quiz.html | 53 ++-- pod/quiz/templates/quiz/video_quiz_aside.html | 25 +- pod/quiz/tests/test_models.py | 85 ++--- pod/quiz/tests/test_templatetags.py | 7 +- pod/quiz/tests/test_views.py | 52 +-- pod/quiz/views.py | 141 +++++---- 30 files changed, 864 insertions(+), 588 deletions(-) create mode 100644 pod/quiz/templates/quiz/manage_quiz.html diff --git a/pod/ai_enhancement/utils.py b/pod/ai_enhancement/utils.py index eebd915504..ecab02890e 100644 --- a/pod/ai_enhancement/utils.py +++ b/pod/ai_enhancement/utils.py @@ -308,7 +308,7 @@ def send_email_enhancement(video): + ", and is now available on %(site_title)s." ) % { - "content_title": "%s" % video.title, + "content_title": "%s" % video.title, "site_title": __TITLE_SITE__, }, _("You will find it here:"), diff --git a/pod/ai_enhancement/views.py b/pod/ai_enhancement/views.py index 49fbf369ab..26da7b90d2 100644 --- a/pod/ai_enhancement/views.py +++ b/pod/ai_enhancement/views.py @@ -116,7 +116,7 @@ def send_enhancement_creation_request( messages.add_message( request, messages.ERROR, - _("Something wrong... Status error: ") + _("Something wrong… Status error: ") + creation_response["status"], ) else: @@ -202,7 +202,7 @@ def delete_enhancement_request( messages.add_message( request, messages.ERROR, - _("Something wrong... Status error: ") + _("Something wrong… Status error: ") + deletion_response["status"], ) else: diff --git a/pod/completion/templates/video_completion.html b/pod/completion/templates/video_completion.html index ede4f45a73..f02ad092cd 100644 --- a/pod/completion/templates/video_completion.html +++ b/pod/completion/templates/video_completion.html @@ -27,7 +27,7 @@

-

@@ -51,7 +51,7 @@

{% if request.user.is_staff %}

-

@@ -80,7 +80,7 @@

-

@@ -104,7 +104,7 @@

-

@@ -114,7 +114,7 @@

{% if form_overlay %} - {% include 'overlay/form_overlay.html' with form_overlay=form_overlay %} + {% include 'overlay/form_overlay.html' with form_overlay=form_overlay %} {% endif %}
@@ -129,28 +129,20 @@

{% if USE_QUIZ %}

-

-

- {% is_quiz_exists video as is_quiz_exists %} - {% if is_quiz_exists %} - {% trans 'Edit your quiz' %} - {% trans 'To edit your quiz for this video.' %} - {% else %} - {% trans 'Create a quiz' %} - {% trans 'To create a quiz for this video.' %} - {% endif %} -

- {% if is_quiz_exists %} -

- {% trans 'Delete your quiz' %} - {% trans 'To delete your quiz for this video.' %} -

+ {% is_quiz_accessible video as is_quiz_accessible %} + {% if is_quiz_accessible %} + + + {% trans 'Answer the quiz' %} + {% endif %} + {% include 'quiz/manage_quiz.html' %}
@@ -197,13 +189,17 @@

{% trans "Help"%}

    {% for vid in video.get_video_mp4 %}
  • - +
  • {% endfor %} {% if video.is_video == False and video.get_video_mp3 %}
  • - +
  • {% endif %} @@ -232,10 +228,10 @@

    {% trans "Help"%}

    {% if USE_QUIZ %}
    -

    {% trans 'Quizzes allow you to test the memorization and comprehension of your video.' %}

    +

    {% trans 'A Quiz allow you to test the memorization and comprehension of your video.' %}

    {% endif %} diff --git a/pod/completion/urls.py b/pod/completion/urls.py index bfa309807d..b6dfd14b0a 100644 --- a/pod/completion/urls.py +++ b/pod/completion/urls.py @@ -1,3 +1,4 @@ +"""Esup-Pod Video completion urls.""" from django.conf.urls import url from .views import video_completion from .views import video_caption_maker diff --git a/pod/locale/fr/LC_MESSAGES/django.mo b/pod/locale/fr/LC_MESSAGES/django.mo index 69ec26e12ef4d7abd82930184779fe7a58681a76..d1bd46c9eb9e06a1b20e35fca45f004be00348bd 100644 GIT binary patch delta 49491 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 Q!6fDI!Unfij&mOVUn^M~b^rhX delta 49063 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 diff --git a/pod/locale/fr/LC_MESSAGES/django.po b/pod/locale/fr/LC_MESSAGES/django.po index 847e4c8fee..6f9a77dfee 100644 --- a/pod/locale/fr/LC_MESSAGES/django.po +++ b/pod/locale/fr/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ msgid "" msgstr "" "Project-Id-Version: Pod\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-06-04 13:24+0000\n" +"POT-Creation-Date: 2024-06-06 07:49+0000\n" "PO-Revision-Date: \n" -"Last-Translator: SebastienCozeDev \n" +"Last-Translator: obado \n" "Language-Team: Pod Team cotech-esup-pod@esup-portail.org\n" "Language: fr\n" "MIME-Version: 1.0\n" @@ -18,7 +18,7 @@ msgstr "" #: pod/ai_enhancement/apps.py msgid "Artificial Intelligence Enhancement" -msgstr "Amélioration par l'intelligence artificielle" +msgstr "Amélioration par l’intelligence artificielle" #: pod/ai_enhancement/forms.py msgid "Choose the title." @@ -208,7 +208,7 @@ msgstr "Créé le" #: pod/ai_enhancement/models.py msgid "The date and time when the enhancement was created" -msgstr "La date et l'heure à laquelle l'enrichissement a été créé" +msgstr "La date et l’heure à laquelle l’enrichissement a été créé" #: pod/ai_enhancement/models.py msgid "Updated at" @@ -216,7 +216,7 @@ msgstr "Mis à jour le" #: pod/ai_enhancement/models.py msgid "The date and time when the enhancement was updated" -msgstr "La date et l'heure à laquelle l'enrichissement a été mis à jour" +msgstr "La date et l’heure à laquelle l’enrichissement a été mis à jour" #: pod/ai_enhancement/models.py msgid "Is ready" @@ -232,7 +232,7 @@ msgstr "ID d’enrichissement AI dans Aristote" #: pod/ai_enhancement/models.py msgid "Enter the ID of the enhancement in Aristote" -msgstr "Entrez l'identifiant de l'enrichissement dans Aristote" +msgstr "Entrez l’identifiant de l’enrichissement dans Aristote" #: pod/ai_enhancement/templates/choose_video_element.html #: pod/dressing/models.py pod/video/apps.py pod/video/models.py @@ -244,7 +244,7 @@ msgstr "Vidéos" #: pod/ai_enhancement/templates/choose_video_element.html #, python-format msgid "Video name: %(video.title)s" -msgstr "Nom de la vidéo : %(video.title)s" +msgstr "Nom de la vidéo : %(video.title)s" #: pod/ai_enhancement/templates/choose_video_element.html msgid "Import subtitle" @@ -368,7 +368,7 @@ msgid "" "To enhance the video with Aristote AI, please check the box and click " "confirm." msgstr "" -"Pour améliorer la vidéo avec l'IA Aristote, veuillez cocher la case et " +"Pour améliorer la vidéo avec l’IA Aristote, veuillez cocher la case et " "cliquer sur confirmer." #: pod/ai_enhancement/templates/create_enhancement.html @@ -400,7 +400,7 @@ msgid "" "video data will also be deleted from Aristote AI." msgstr "" "Pour supprimer cette amélioration, veuillez cocher la case et cliquer sur " -"confirmer. Les données de la vidéo seront également supprimées sur l'IA " +"confirmer. Les données de la vidéo seront également supprimées sur l’IA " "Aristote." #: pod/ai_enhancement/utils.py pod/live/templates/live/direct.html @@ -428,13 +428,13 @@ msgid "" "“%(content_title)s” was processed by the AI. Suggestions for improvement are " "available on %(site_title)s." msgstr "" -"« %(content_title)s » a été traité par l'IA. Des suggestions d'amélioration " +"« %(content_title)s » a été traité par l’IA. Des suggestions d’amélioration " "sont disponibles sur %(site_title)s." #: pod/ai_enhancement/utils.py #, python-format msgid "IA improvement #%(content_id)s completed" -msgstr "Amélioration de l'IA #%(content_id)s est terminée" +msgstr "Amélioration de l’IA #%(content_id)s est terminée" #: pod/ai_enhancement/utils.py pod/live/utils.py pod/meeting/utils.py #: pod/video_encode_transcript/utils.py @@ -447,7 +447,7 @@ msgid "" "IA improvement “%(content_title)s” has been completed, and is now available " "on %(site_title)s." msgstr "" -"Amélioration de l'AI « %(content_title)s » a été achevée, et est maintenant " +"Amélioration de l’AI « %(content_title)s » a été achevée, et est maintenant " "disponible sur %(site_title)s." #: pod/ai_enhancement/utils.py pod/meeting/utils.py @@ -482,12 +482,12 @@ msgid "-- All languages --" msgstr "-- Toutes les langues --" #: pod/ai_enhancement/views.py -msgid "Something wrong... Status error: " -msgstr "Quelque chose ne va pas... Erreur de statut : " +msgid "Something wrong… Status error: " +msgstr "Quelque chose ne va pas… Erreur de statut : " #: pod/ai_enhancement/views.py msgid "Error: no response from Aristote AI." -msgstr "Erreur : pas de réponse de l'IA Aristote." +msgstr "Erreur : pas de réponse de l’IA Aristote." #: pod/ai_enhancement/views.py msgid "Enhance the video with Aristote AI" @@ -499,11 +499,11 @@ msgstr "Vous ne pouvez pas supprimer cette amélioration." #: pod/ai_enhancement/views.py msgid "The video has not been improved." -msgstr "La vidéo n'a pas été améliorée." +msgstr "La vidéo n’a pas été améliorée." #: pod/ai_enhancement/views.py msgid "Enhancement successfully deleted." -msgstr "L'amélioration a été supprimée avec succès." +msgstr "L’amélioration a été supprimée avec succès." #: pod/ai_enhancement/views.py msgid "No enhancement found." @@ -511,16 +511,16 @@ msgstr "Aucune amélioration trouvée." #: pod/ai_enhancement/views.py msgid "Delete the video enhancement" -msgstr "Supprimer l'amélioration de la vidéo" +msgstr "Supprimer l’amélioration de la vidéo" #: pod/ai_enhancement/views.py msgid "You cannot use AI to improve this video." -msgstr "Vous ne pouvez pas utiliser l'IA pour améliorer cette vidéo." +msgstr "Vous ne pouvez pas utiliser l’IA pour améliorer cette vidéo." #: pod/ai_enhancement/views.py msgid "Video Caption Maker - Aristote AI Version" msgstr "" -"Outil de création de fichier de sous-titres/légende - Version de l'IA " +"Outil de création de fichier de sous-titres/légende - Version de l’IA " "Aristote" #: pod/ai_enhancement/views.py @@ -1978,7 +1978,7 @@ msgstr "menu" #: pod/completion/templates/video_caption_maker.html msgid "Enrichment is ready. You can now edit the subtitles." msgstr "" -"L'enrichissement est prêt. Vous pouvez maintenant éditer les sous-titres." +"L’enrichissement est prêt. Vous pouvez maintenant éditer les sous-titres." #: pod/completion/templates/video_caption_maker.html #: pod/video/templates/videos/add_video.html @@ -2109,7 +2109,7 @@ msgstr "Remplacer" #: pod/completion/templates/video_completion.html msgid "Contributor(s)" -msgstr "Contributeurs" +msgstr "Contributeur(s)" #: pod/completion/templates/video_completion.html msgid "Add a new contributor" @@ -2117,7 +2117,7 @@ msgstr "Ajouter un nouveau contributeur" #: pod/completion/templates/video_completion.html msgid "Subtitle(s) and Caption(s)" -msgstr "Sous-titres et légendes" +msgstr "Sous-titre(s) et légende(s)" #: pod/completion/templates/video_completion.html pod/completion/views.py msgid "Video caption maker" @@ -2133,7 +2133,7 @@ msgstr "Ajouter un nouveau fichier de sous-titres ou de légende" #: pod/completion/templates/video_completion.html msgid "Additional resource(s)" -msgstr "Documents complémentaires" +msgstr "Document(s) complémentaire(s)" #: pod/completion/templates/video_completion.html msgid "Add a new additional resource" @@ -2141,42 +2141,23 @@ msgstr "Ajouter un document complémentaire" #: pod/completion/templates/video_completion.html msgid "Overlay(s)" -msgstr "Superpositions" +msgstr "Superposition(s)" #: pod/completion/templates/video_completion.html msgid "Add a new overlay" msgstr "Ajouter une nouvelle superposition" -#: pod/completion/templates/video_completion.html pod/quiz/models.py -msgid "Quizzes" -msgstr "Quiz" - -#: pod/completion/templates/video_completion.html -#: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Edit your quiz" -msgstr "Éditez votre quiz" - -#: pod/completion/templates/video_completion.html -msgid "To edit your quiz for this video." -msgstr "Pour éditer votre quiz pour cette vidéo." - -#: pod/completion/templates/video_completion.html +#: pod/completion/templates/video_completion.html pod/quiz/apps.py +#: pod/quiz/models.py pod/quiz/templates/quiz/create_edit_quiz.html #: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Create a quiz" -msgstr "Créer un quiz" - -#: pod/completion/templates/video_completion.html -msgid "To create a quiz for this video." -msgstr "Pour créer un quiz pour cette vidéo." +msgid "Quiz" +msgstr "Quiz" #: pod/completion/templates/video_completion.html +#: pod/quiz/templates/quiz/create_edit_quiz.html #: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Delete your quiz" -msgstr "Supprimez votre quiz" - -#: pod/completion/templates/video_completion.html -msgid "To delete your quiz for this video." -msgstr "Pour supprimer votre quiz pour cette vidéo." +msgid "Answer the quiz" +msgstr "Répondre au quiz" #: pod/completion/templates/video_completion.html msgid "List of people related to this video." @@ -2193,7 +2174,7 @@ msgstr "" #: pod/completion/templates/video_completion.html msgid "Subtitle(s) and/or captions(s) related to this video." -msgstr "Sous-titres et/ou légendes relatifs à cette vidéo." +msgstr "Sous-titre(s) et/ou légende(s) relatifs à cette vidéo." #: pod/completion/templates/video_completion.html msgid "" @@ -2242,15 +2223,16 @@ msgstr "" "malencontreuses." #: pod/completion/templates/video_completion.html -msgid ":" -msgstr " : " +#, python-format +msgid "%(name)s:" +msgstr "%(name)s :" #: pod/completion/templates/video_completion.html msgid "" "Document(s) related to this video. These documents will be downloadable by " "users." msgstr "" -"Documents relatifs à cette vidéo. Ces documents seront téléchargeables par " +"Document(s) relatifs à cette vidéo. Ces documents seront téléchargeables par " "les utilisateurs." #: pod/completion/templates/video_completion.html @@ -2279,10 +2261,10 @@ msgstr "" #: pod/completion/templates/video_completion.html msgid "" -"Quizzes allow you to test the memorization and comprehension of your video." +"A Quiz allow you to test the memorization and comprehension of your video." msgstr "" -"Les quiz vous permettent de tester la mémorisation et la compréhension de " -"votre vidéo." +"Un quiz vous permet de tester la mémorisation et la compréhension de votre " +"vidéo." #: pod/completion/tests/test_views.py msgid "editor" @@ -3076,8 +3058,8 @@ msgid "" "a>." msgstr "" "L’accès à l’ajout d’enregistrements externes a été limité. Si vous souhaitez " -"ajouter des enregistrements externes sur la plateforme, veuillez nous contacter." +"ajouter des enregistrements externes sur la plateforme, veuillez nous contacter." #: pod/import_video/templates/import_video/add_or_edit.html msgid "" @@ -3443,8 +3425,8 @@ msgid "" "This video was uploaded to Pod; its origin is %(type)s: %(url)s" msgstr "" -"Cette vidéo a été téléversée sur Pod ; son origine est %(type)s : %(url)s" +"Cette vidéo a été téléversée sur Pod ; son origine est %(type)s : %(url)s" #: pod/import_video/views.py msgid "" @@ -3458,8 +3440,8 @@ msgstr "" #: pod/import_video/views.py #, python-format msgid "" -"This video “%(name)s” was uploaded to Pod; its origin is %(type)s: %(url)s

    %(desc)s" +"This video “%(name)s” was uploaded to Pod; its origin is %(type)s: %(url)s

    %(desc)s" msgstr "" "Cette vidéo « %(name)s » a été téléversée sur Pod ; son origine est " "%(type)s : %(url)s

    %(desc)s" @@ -3467,8 +3449,8 @@ msgstr "" #: pod/import_video/views.py #, python-format msgid "" -"This video “%(name)s” was uploaded to Pod; its origin is Youtube: %(url)s" +"This video “%(name)s” was uploaded to Pod; its origin is Youtube: %(url)s" msgstr "" "Cette vidéo « %(name)s » a été téléversée sur Pod ; son origine est " "Youtube : %(url)s" @@ -4470,9 +4452,9 @@ msgid "" "the other sharing options in the dedicated tab." msgstr "" "Vous venez de programmer un nouvel évènement direct intitulé " -"“%(content_title)s” du %(start_date)s au %(end_date)s sur le serveur vidéo : " -"%(url_event)s). Vous pouvez retrouver les autres options de partage dans " -"l’onglet dédié." +"« %(content_title)s » du %(start_date)s au %(end_date)s sur le serveur " +"vidéo : %(url_event)s). Vous pouvez retrouver les autres options de partage " +"dans l’onglet dédié." #: pod/live/utils.py msgid "You cannot view this page." @@ -6043,7 +6025,7 @@ msgstr "Jour(s) de la semaine pour la réunion" #: pod/meeting/models.py msgid "Recurring meeting each day(s) specified" -msgstr "Réunion récurrente chaque jour spécifié" +msgstr "Réunion récurrente chaque jour(s) spécifié(s)" #: pod/meeting/models.py msgid "" @@ -6885,16 +6867,16 @@ msgid "" msgstr "" "\n" "

    Bonjour,\n" -"

    %(owner)s vous invite à une réunion récurrente " -"%(meeting_title)s.

    \n" +"

    %(owner)s vous invite à une réunion récurrente " +"%(meeting_title)s.

    \n" "

    Date de début : %(start_date_time)s

    \n" "

    Récurrent jusqu’à la date : %(end_date)s

    \n" "

    La réunion se tiendra tou(te)s les %(frequency)s %(recurrence)s \n" "

    Voici le lien pour rejoindre la réunion :\n" " %(join_link)s

    \n" -"

    Vous avez besoin de ce mot de passe pour entrer : " -"%(password)s

    \n" +"

    Vous avez besoin de ce mot de passe pour entrer : " +"%(password)s

    \n" "

    Cordialement

    \n" " " @@ -6903,8 +6885,8 @@ msgstr "" msgid "" "\n" "

    Hello,

    \n" -"

    %(owner)s invites you to the meeting " -"%(meeting_title)s.

    \n" +"

    %(owner)s invites you to the meeting " +"%(meeting_title)s.

    \n" "

    here the link to join the meeting:\n" " %(join_link)s

    \n" "

    You need this password to enter: %(password)s.

    \n" "

    Voici le lien pour rejoindre la réunion :\n" " %(join_link)s

    \n" -"

    Vous avez besoin de ce mot de passe pour entrer : " -"%(password)s

    \n" +"

    Vous avez besoin de ce mot de passe pour entrer : " +"%(password)s

    \n" "

    Cordialement

    \n" " " @@ -6928,8 +6910,8 @@ msgstr "" msgid "" "\n" "

    Hello,

    \n" -"

    %(owner)s invites you to the meeting " -"%(meeting_title)s.

    \n" +"

    %(owner)s invites you to the meeting " +"%(meeting_title)s.

    \n" "

    Start date: %(start_date_time)s

    \n" "

    End date: %(end_date)s

    \n" "

    here the link to join the meeting:\n" @@ -6947,8 +6929,8 @@ msgstr "" "

    Date de fin : %(end_date)s

    \n" "

    Voici le lien pour rejoindre la réunion :\n" " %(join_link)s

    \n" -"

    Vous avez besoin de ce mot de passe pour entrer : " -"%(password)s

    \n" +"

    Vous avez besoin de ce mot de passe pour entrer : " +"%(password)s

    \n" "

    Cordialement

    \n" " " @@ -7804,11 +7786,6 @@ msgstr "" msgid "Allow" msgstr "Autoriser" -#: pod/quiz/apps.py pod/quiz/models.py -#: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Quiz" -msgstr "Quiz" - #: pod/quiz/forms.py msgid "Redaction" msgstr "Rédaction" @@ -7842,31 +7819,31 @@ msgid "Explanation" msgstr "Explication" #: pod/quiz/forms.py -msgid "Explanation of the question" -msgstr "Explication de la question" +msgid "Explanation of the answer." +msgstr "Explication de la réponse." -#: pod/quiz/forms.py pod/quiz/models.py -msgid "Please choose an explanation." -msgstr "Veuillez choisir une explication." +#: pod/quiz/forms.py +msgid "" +"An explanation that will be displayed once the user has responded (feedback)." +msgstr "" +"Une explication qui sera affichée une fois que l’utilisateur aura répondu " +"(feedback)." #: pod/quiz/forms.py pod/quiz/models.py msgid "Start timestamp" msgstr "Horodatage de départ" #: pod/quiz/forms.py pod/quiz/models.py -msgid "" -"Please choose the beginning time of the answer in the video (in seconds)." -msgstr "" -"Veuillez choisir l’heure de début de la réponse dans la vidéo (en secondes)." +msgid "The start time of the answer in the video (in seconds)." +msgstr "L’heure de début de la réponse dans la vidéo (en secondes)." #: pod/quiz/forms.py pod/quiz/models.py msgid "End timestamp" msgstr "Horodatage de fin" #: pod/quiz/forms.py pod/quiz/models.py -msgid "Please choose the end time of the answer in the video (in seconds)." -msgstr "" -"Veuillez choisir l’heure de fin de la réponse dans la vidéo (en secondes)." +msgid "The end time of the answer in the video (in seconds)." +msgstr "L’heure de fin de la réponse dans la vidéo (en secondes)." #: pod/quiz/forms.py msgid "Question type" @@ -7890,7 +7867,7 @@ msgstr "Afficher les réponses correctes" #: pod/quiz/forms.py msgid "The correction page can be reach." -msgstr "La page de correction est accessible" +msgstr "La page de correction est accessible." #: pod/quiz/forms.py msgid "Delete video quiz cannot be undone" @@ -7929,26 +7906,34 @@ msgid "Write a long answer." msgstr "Écrivez une réponse longue." #: pod/quiz/models.py -msgid "Please choose a video associated with the quiz." +msgid "Choose a video associated with the quiz." msgstr "Veuillez choisir une vidéo associée au quiz." #: pod/quiz/models.py -msgid "Please choose if this quiz is only for connected users or not." +msgid "Choose if this quiz is only for connected users or not." msgstr "" "Veuillez choisir si ce quiz est réservé aux utilisateurs connectés ou non." #: pod/quiz/models.py -msgid "Please choose if the correct answers will be displayed or not." +msgid "Choose if the correct answers will be displayed or not." msgstr "Veuillez choisir si les réponses correctes seront affichées ou non." +#: pod/quiz/models.py +msgid "Quizzes" +msgstr "Quiz" + #: pod/quiz/models.py msgid "Quiz of video" msgstr "Quiz de la vidéo" #: pod/quiz/models.py -msgid "Please choose a quiz associated with the question." +msgid "Choose a quiz associated with the question." msgstr "Veuillez choisir un quiz associé à la question." +#: pod/quiz/models.py +msgid "Please choose an explanation." +msgstr "Veuillez choisir une explication." + #: pod/quiz/models.py msgid "Question" msgstr "Question" @@ -7965,6 +7950,11 @@ msgstr "L’horodatage de début doit être inférieur à l’heure de fin." msgid "End timestamp cannot be defined without a start timestamp." msgstr "L’horodatage de fin ne peut être défini sans l’heure de début." +#: pod/quiz/models.py +#, python-format +msgid "Question “%s”" +msgstr "Question « %s »" + #: pod/quiz/models.py msgid "Choices" msgstr "Choix" @@ -7974,8 +7964,8 @@ msgid "" "Choices must be like this: {'choice 1': true, 'choice 2': false, ...} | true " "for the right choice, false for the wrong choices." msgstr "" -"Les choix doivent ressembler à ceci : {'choix 1': true, 'choix 2': " -"false, ...} | true pour le bon choix, false pour les mauvais choix." +"Les choix doivent ressembler à ceci : {'choix 1': true, 'choix 2': false, …} " +"| true pour le bon choix, false pour les mauvais choix." #: pod/quiz/models.py msgid "Single choice questions" @@ -7987,7 +7977,7 @@ msgstr "Il doit y avoir au moins 2 choix." #: pod/quiz/models.py msgid "There must be only one correct answer." -msgstr "Il ne doit y avoir qu'une seule réponse correcte." +msgstr "Il ne doit y avoir qu’une seule réponse correcte." #: pod/quiz/models.py msgid "Invalid JSON format for choices." @@ -7998,9 +7988,8 @@ msgid "" "Choices must be like this: {'choice 1': true, 'choice 2': true, 'choice 3': " "false, ...} | true for the right choice, false for the wrong choices." msgstr "" -"Les choix doivent ressembler à ceci : {'choix 1': true, 'choix 2': true, " -"'choix 3': false, ...} | true pour le bon choix, false pour les mauvais " -"choix." +"Les choix doivent ressembler à ceci : {'choix 1': true, 'choix 2': true, " +"'choix 3': false, …} | true pour le bon choix, false pour les mauvais choix." #: pod/quiz/models.py msgid "Multiple choice questions" @@ -8051,13 +8040,27 @@ msgstr "Ajouter une question" msgid "Back to video" msgstr "Retour à la vidéo" +#: pod/quiz/templates/quiz/create_edit_quiz.html +#: pod/quiz/templates/quiz/manage_quiz.html +msgid "Delete your quiz" +msgstr "Supprimez votre quiz" + #: pod/quiz/templates/quiz/delete_quiz.html msgid "To delete the quiz, please check the box and click “Delete”." msgstr "" "Pour supprimer la vidéo, veuillez cocher la case et cliquer sur " "« Supprimer »." +#: pod/quiz/templates/quiz/manage_quiz.html +msgid "Edit your quiz" +msgstr "Éditez votre quiz" + +#: pod/quiz/templates/quiz/manage_quiz.html +msgid "Create a quiz" +msgstr "Créer un quiz" + #: pod/quiz/templates/quiz/question_form.html +#: pod/quiz/templates/quiz/video_quiz.html msgid "Question #" msgstr "Question n°" @@ -8071,19 +8074,19 @@ msgstr "Une ou plusieurs erreurs ont été trouvées dans la question." #: pod/quiz/templates/quiz/video_quiz.html msgid "Your score is:" -msgstr "Votre score est de :" +msgstr "Votre score est de :" #: pod/quiz/templates/quiz/video_quiz.html -msgid "That's great! Bravo!" -msgstr "C'est super ! Bravo !" +msgid "That’s great! Bravo!" +msgstr "C’est super ! Bravo !" #: pod/quiz/templates/quiz/video_quiz.html msgid "Can do better." msgstr "Peut mieux faire." #: pod/quiz/templates/quiz/video_quiz.html -msgid "It's not terrible, but there's room for improvement!" -msgstr "Ce n'est pas terrible, mais de l’amélioration est possible !" +msgid "It’s not terrible, but there’s room for improvement!" +msgstr "Ce n’est pas terrible, mais de l’amélioration est possible !" #: pod/quiz/templates/quiz/video_quiz.html msgid "Error found in form" @@ -8091,16 +8094,16 @@ msgstr "Erreur constatée dans le formulaire" #: pod/quiz/templates/quiz/video_quiz.html #, python-format -msgid "For the question \"%(title)s\", %(error)s." -msgstr "Pour la question \"%(title)s\", %(error)s." +msgid "For the question “%(title)s”, %(error)s." +msgstr "Pour la question « %(title)s », %(error)s." #: pod/quiz/templates/quiz/video_quiz.html -msgid "Right answer:" -msgstr "Bonne réponse :" +msgid "Correct answer:" +msgstr "Réponse correcte :" #: pod/quiz/templates/quiz/video_quiz.html msgid "Explanation:" -msgstr "Explication :" +msgstr "Explication :" #: pod/quiz/templates/quiz/video_quiz.html msgid "Show answer in the video" @@ -8114,9 +8117,9 @@ msgstr "Refaire le quiz" msgid "Validate" msgstr "Valider" -#: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Answer the quiz" -msgstr "Répondre au quiz" +#: pod/quiz/templates/quiz/video_quiz.html +msgid "Manage quiz" +msgstr "Gérer le quiz" #: pod/quiz/tests/test_views.py pod/quiz/views.py msgid "You cannot create a quiz for this video." @@ -8135,22 +8138,30 @@ msgstr "Le quiz a été supprimé." msgid "Quiz creation for the video “%s”" msgstr "Création du quiz de la vidéo « %s »" +#: pod/quiz/views.py +#, python-format +msgid "No answer defined for question %s." +msgstr "Aucune réponse n’a été définie pour la question %s." + #: pod/quiz/views.py msgid "Quiz successfully created." msgstr "Quiz créé avec succès." +#: pod/quiz/views.py +msgid "Error during quiz creation." +msgstr "Erreur pendant la création du quiz." + #: pod/quiz/views.py msgid "Quiz successfully updated." msgstr "Quiz mis à jour avec succès." #: pod/quiz/views.py -msgid "The data sent to create the quiz are invalid." -msgstr "Les données envoyées pour créer le quiz ne sont pas valides." +msgid "Error during quiz update." +msgstr "Erreur pendant la mise à jour du quiz." #: pod/quiz/views.py -#, python-brace-format -msgid "Quiz edition for the video: {video.title}" -msgstr "Édition du quiz pour la vidéo : {video.title}" +msgid "The data sent to create the quiz are invalid." +msgstr "Les données envoyées pour créer le quiz ne sont pas valides." #: pod/quiz/views.py msgid "You have to choose at least one answer" @@ -8483,8 +8494,8 @@ msgstr "Prévisualisation d’enregistrement" #: pod/video/templates/videos/video-element.html msgid "" "To view this video please enable JavaScript, and consider upgrading to a web " -"browser that supports HTML5 video" +"browser that supports HTML5 video" msgstr "" "Pour visionner cette vidéo, veuillez activer JavaScript et envisager de " "passer à un navigateur Web qui Bonjour,
    un nouvel enregistrement a été ajouté sur la plateforme " "%(title_site)s à partir de l’enregistreur « %(recorder)s ».
    Pour " -"l’ajouter, cliquez sur le lien ci-dessous.

    " -"%(link_url)s
    Si le lien n’est pas actif, il faut le copier-coller " -"dans la barre d’adresse de votre navigateur.

    Cordialement.

    " +"l’ajouter, cliquez sur le lien ci-dessous.

    %(link_url)s
    Si le lien n’est pas actif, il " +"faut le copier-coller dans la barre d’adresse de votre navigateur.

    Cordialement.

    " #: pod/recorder/views.py msgid "New recording added." @@ -8913,8 +8925,8 @@ msgid "" "%(url)s

    \n" msgstr "" "vous pouvez changer la date de suppression en éditant votre vidéo :

    \n" -"

    " -"%(scheme)s:%(url)s

    \n" +"

    %(scheme)s:%(url)s

    \n" "\n" #: pod/video/management/commands/check_obsolete_videos.py @@ -8931,7 +8943,7 @@ msgid "" "please contact the manager(s) in charge of your establishment at this " "address(es): %(email_address)s

    \n" msgstr "" -"veuillez contacter les gestionnaires en charge de votre établissement à " +"veuillez contacter le(s) gestionnaire(s) en charge de votre établissement à " "l’adresse suivante : %(email_address)s

    \n" #: pod/video/management/commands/check_obsolete_videos.py @@ -8946,7 +8958,7 @@ msgstr "Votre vidéo sera obsolète" #: pod/video/management/commands/check_obsolete_videos.py #, python-format msgid "Hello manager(s) of %(estab)s on %(site_title)s," -msgstr "Bonjour les gestionnaire(s) de %(estab)s sur %(site_title)s," +msgstr "Bonjour le(s) gestionnaire(s) de %(estab)s sur %(site_title)s," #: pod/video/management/commands/check_obsolete_videos.py #, python-format @@ -9041,8 +9053,8 @@ msgid "" "And below is the list of ignored videos that were not packaged because they " "have been recently viewed." msgstr "" -"Vous trouverez ci-dessous la liste des vidéos ignorées qui n'ont pas été " -"regroupées parce qu'elles ont été visionnées récemment." +"Vous trouverez ci-dessous la liste des vidéos ignorées qui n’ont pas été " +"regroupées parce qu’elles ont été visionnées récemment." #: pod/video/management/commands/create_archive_package.py #, python-format @@ -9826,8 +9838,8 @@ msgid "" "This video is chaptered. Click the chapter button on the video player to view them." msgstr "" -"Cette vidéo est chapitrée. Cliquez sur le bouton de chapitre sur le lecteur vidéo pour les voir." +"Cette vidéo est chapitrée. Cliquez sur le bouton de chapitre sur le lecteur vidéo pour les voir." #: pod/video/templates/videos/video-all-info.html msgid "Other versions" @@ -10327,7 +10339,7 @@ msgstr "Description du thème" #: pod/video/templates/videos/video_page_content.html msgid "The video is currently waiting for Aristote AI treatment." -msgstr "La vidéo est actuellement en attente du traitement par l'IA Aristote." +msgstr "La vidéo est actuellement en attente du traitement par l’IA Aristote." #: pod/video/templates/videos/video_page_content.html msgid "" @@ -10873,3 +10885,6 @@ msgstr "Résultats de la recherche" #: pod/xapi/apps.py msgid "Esup-Pod xAPI" msgstr "xAPI Esup-Pod" + +#~ msgid "Quiz(zes)" +#~ msgstr "Quiz" diff --git a/pod/locale/fr/LC_MESSAGES/djangojs.mo b/pod/locale/fr/LC_MESSAGES/djangojs.mo index 21444518f7023cf8f9b75503fefdf1e888b4545b..74cf27b6fb78f8ef72b6f2c7107dccc9ecb7a7be 100644 GIT binary patch delta 5400 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 z\n" +"Last-Translator: obado \n" "Language-Team: \n" "Language: fr\n" "MIME-Version: 1.0\n" @@ -26,7 +26,7 @@ msgstr "Aucune description" #: pod/ai_enhancement/static/ai_enhancement/js/enrich-form.js msgid "An error has occurred. Please try later." -msgstr "Une erreur est survenue. Merci d'essayer plus tard." +msgstr "Une erreur est survenue. Merci d’essayer plus tard." #: pod/chapter/static/js/chapters.js pod/enrichment/static/js/enrichment.js #: pod/quiz/static/quiz/js/create-quiz.js @@ -458,7 +458,7 @@ msgstr "Action réalisée avec succès." msgid "Text copied" msgstr "Texte copié" -#: pod/main/static/js/main.js +#: pod/main/static/js/main.js pod/quiz/static/quiz/js/create-quiz.js msgid "There are errors in the form, please correct them." msgstr "Des erreurs sont présentes dans le formulaire, veuillez les corriger." @@ -661,21 +661,51 @@ msgid "Long answer" msgstr "Réponse longue" #: pod/quiz/static/quiz/js/create-quiz.js -msgid "Remove choice" -msgstr "Supprimer le choix" +#, javascript-format +msgid "Select the choice #%s as correct answer." +msgstr "Selectionnez le choix n°%s comme réponse correcte." #: pod/quiz/static/quiz/js/create-quiz.js -msgid "Choice" -msgstr "Choix" +#, javascript-format +msgid "Remove choice %s" +msgstr "Supprimer le choix n°%s" #: pod/quiz/static/quiz/js/create-quiz.js -msgid "Your choices" -msgstr "Vos choix" +#, javascript-format +msgid "Choice #%s" +msgstr "Choix n°%s" + +#: pod/quiz/static/quiz/js/create-quiz.js +#, javascript-format +msgid "Choices for question #%s" +msgstr "Choix de la question n°%s" #: pod/quiz/static/quiz/js/create-quiz.js msgid "Add a choice" msgstr "Ajouter un choix" +#: pod/quiz/static/quiz/js/create-quiz.js +#, javascript-format +msgid "Remove choice #%s" +msgstr "Supprimer le choix n°%s" + +#: pod/quiz/static/quiz/js/create-quiz.js +#, javascript-format +msgid "choice #%s" +msgstr "choix n°%s" + +#: pod/quiz/static/quiz/js/create-quiz.js +msgid "Choice" +msgstr "Choix" + +#: pod/quiz/static/quiz/js/video-quiz-submit.js +msgid "Correct answer given" +msgstr "Réponse correcte envoyée" + +#: pod/quiz/static/quiz/js/video-quiz-submit.js +msgid "Incorrect answer given" +msgstr "Réponse incorrecte envoyée" + #: pod/video/static/js/ajax-display-channels.js msgid "%(count)s channel" msgid_plural "%(count)s channels" @@ -782,8 +812,8 @@ msgstr[1] "%s commentaires" #: pod/video/static/js/dashboard.js msgid "Please confirm the editing of the following video:" msgid_plural "Please confirm the editing of the following videos:" -msgstr[0] "Veuillez confirmer l'édition de la vidéo suivante :" -msgstr[1] "Veuillez confirmer l'édition des vidéos suivantes :" +msgstr[0] "Veuillez confirmer l’édition de la vidéo suivante :" +msgstr[1] "Veuillez confirmer l’édition des vidéos suivantes :" #: pod/video/static/js/dashboard.js msgid "Please confirm the deletion of the following video:" diff --git a/pod/locale/nl/LC_MESSAGES/django.mo b/pod/locale/nl/LC_MESSAGES/django.mo index 804868c257651276bb228a385b5eea4df3d87d7e..6aa3517b50a608665fb781ed94449d20e52e6026 100644 GIT binary patch delta 23 ecmeAc=oZ+pkA=%j*T6)<(9FunVDkwUXJ!CV9R^|m delta 23 ecmeAc=oZ+pkA=%r*U(hKz|zXVaPtWkXJ!CVFa~4* diff --git a/pod/locale/nl/LC_MESSAGES/django.po b/pod/locale/nl/LC_MESSAGES/django.po index fcc74c8391..f9457ba693 100644 --- a/pod/locale/nl/LC_MESSAGES/django.po +++ b/pod/locale/nl/LC_MESSAGES/django.po @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: Pod\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-06-04 13:24+0000\n" -"PO-Revision-Date: 2024-05-15 09:01+0200\n" +"POT-Creation-Date: 2024-06-06 07:49+0000\n" +"PO-Revision-Date: 2024-06-04 16:20+0200\n" "Last-Translator: obado \n" "Language-Team: \n" "Language: nl_NL\n" @@ -472,7 +472,7 @@ msgid "-- All languages --" msgstr "" #: pod/ai_enhancement/views.py -msgid "Something wrong... Status error: " +msgid "Something wrong… Status error: " msgstr "" #: pod/ai_enhancement/views.py @@ -2067,35 +2067,16 @@ msgstr "" msgid "Add a new overlay" msgstr "" -#: pod/completion/templates/video_completion.html pod/quiz/models.py -msgid "Quizzes" -msgstr "" - -#: pod/completion/templates/video_completion.html -#: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Edit your quiz" -msgstr "" - -#: pod/completion/templates/video_completion.html -msgid "To edit your quiz for this video." -msgstr "" - -#: pod/completion/templates/video_completion.html +#: pod/completion/templates/video_completion.html pod/quiz/apps.py +#: pod/quiz/models.py pod/quiz/templates/quiz/create_edit_quiz.html #: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Create a quiz" -msgstr "" - -#: pod/completion/templates/video_completion.html -msgid "To create a quiz for this video." +msgid "Quiz" msgstr "" #: pod/completion/templates/video_completion.html +#: pod/quiz/templates/quiz/create_edit_quiz.html #: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Delete your quiz" -msgstr "" - -#: pod/completion/templates/video_completion.html -msgid "To delete your quiz for this video." +msgid "Answer the quiz" msgstr "" #: pod/completion/templates/video_completion.html @@ -2149,7 +2130,8 @@ msgid "" msgstr "" #: pod/completion/templates/video_completion.html -msgid ":" +#, python-format +msgid "%(name)s:" msgstr "" #: pod/completion/templates/video_completion.html @@ -2178,7 +2160,7 @@ msgstr "" #: pod/completion/templates/video_completion.html msgid "" -"Quizzes allow you to test the memorization and comprehension of your video." +"A Quiz allow you to test the memorization and comprehension of your video." msgstr "" #: pod/completion/tests/test_views.py @@ -3254,15 +3236,15 @@ msgstr "" #: pod/import_video/views.py #, python-format msgid "" -"This video “%(name)s” was uploaded to Pod; its origin is %(type)s: %(url)s

    %(desc)s" +"This video “%(name)s” was uploaded to Pod; its origin is %(type)s: %(url)s

    %(desc)s" msgstr "" #: pod/import_video/views.py #, python-format msgid "" -"This video “%(name)s” was uploaded to Pod; its origin is Youtube: %(url)s" +"This video “%(name)s” was uploaded to Pod; its origin is Youtube: %(url)s" msgstr "" #: pod/import_video/views.py @@ -6497,8 +6479,8 @@ msgstr "" msgid "" "\n" "

    Hello,

    \n" -"

    %(owner)s invites you to the meeting " -"%(meeting_title)s.

    \n" +"

    %(owner)s invites you to the meeting " +"%(meeting_title)s.

    \n" "

    here the link to join the meeting:\n" " %(join_link)s

    \n" "

    You need this password to enter: %(password)sHello,

    \n" -"

    %(owner)s invites you to the meeting " -"%(meeting_title)s.

    \n" +"

    %(owner)s invites you to the meeting " +"%(meeting_title)s.

    \n" "

    Start date: %(start_date_time)s

    \n" "

    End date: %(end_date)s

    \n" "

    here the link to join the meeting:\n" @@ -7315,11 +7297,6 @@ msgstr "" msgid "Allow" msgstr "" -#: pod/quiz/apps.py pod/quiz/models.py -#: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Quiz" -msgstr "" - #: pod/quiz/forms.py msgid "Redaction" msgstr "" @@ -7353,11 +7330,12 @@ msgid "Explanation" msgstr "" #: pod/quiz/forms.py -msgid "Explanation of the question" +msgid "Explanation of the answer." msgstr "" -#: pod/quiz/forms.py pod/quiz/models.py -msgid "Please choose an explanation." +#: pod/quiz/forms.py +msgid "" +"An explanation that will be displayed once the user has responded (feedback)." msgstr "" #: pod/quiz/forms.py pod/quiz/models.py @@ -7365,8 +7343,7 @@ msgid "Start timestamp" msgstr "" #: pod/quiz/forms.py pod/quiz/models.py -msgid "" -"Please choose the beginning time of the answer in the video (in seconds)." +msgid "The start time of the answer in the video (in seconds)." msgstr "" #: pod/quiz/forms.py pod/quiz/models.py @@ -7374,7 +7351,7 @@ msgid "End timestamp" msgstr "" #: pod/quiz/forms.py pod/quiz/models.py -msgid "Please choose the end time of the answer in the video (in seconds)." +msgid "The end time of the answer in the video (in seconds)." msgstr "" #: pod/quiz/forms.py @@ -7444,15 +7421,19 @@ msgid "Write a long answer." msgstr "" #: pod/quiz/models.py -msgid "Please choose a video associated with the quiz." +msgid "Choose a video associated with the quiz." msgstr "" #: pod/quiz/models.py -msgid "Please choose if this quiz is only for connected users or not." +msgid "Choose if this quiz is only for connected users or not." msgstr "" #: pod/quiz/models.py -msgid "Please choose if the correct answers will be displayed or not." +msgid "Choose if the correct answers will be displayed or not." +msgstr "" + +#: pod/quiz/models.py +msgid "Quizzes" msgstr "" #: pod/quiz/models.py @@ -7460,7 +7441,11 @@ msgid "Quiz of video" msgstr "" #: pod/quiz/models.py -msgid "Please choose a quiz associated with the question." +msgid "Choose a quiz associated with the question." +msgstr "" + +#: pod/quiz/models.py +msgid "Please choose an explanation." msgstr "" #: pod/quiz/models.py @@ -7479,6 +7464,11 @@ msgstr "" msgid "End timestamp cannot be defined without a start timestamp." msgstr "" +#: pod/quiz/models.py +#, python-format +msgid "Question “%s”" +msgstr "" + #: pod/quiz/models.py msgid "Choices" msgstr "" @@ -7560,11 +7550,25 @@ msgstr "" msgid "Back to video" msgstr "" +#: pod/quiz/templates/quiz/create_edit_quiz.html +#: pod/quiz/templates/quiz/manage_quiz.html +msgid "Delete your quiz" +msgstr "" + #: pod/quiz/templates/quiz/delete_quiz.html msgid "To delete the quiz, please check the box and click “Delete”." msgstr "" +#: pod/quiz/templates/quiz/manage_quiz.html +msgid "Edit your quiz" +msgstr "" + +#: pod/quiz/templates/quiz/manage_quiz.html +msgid "Create a quiz" +msgstr "" + #: pod/quiz/templates/quiz/question_form.html +#: pod/quiz/templates/quiz/video_quiz.html msgid "Question #" msgstr "" @@ -7583,7 +7587,7 @@ msgid "Your score is:" msgstr "" #: pod/quiz/templates/quiz/video_quiz.html -msgid "That's great! Bravo!" +msgid "That’s great! Bravo!" msgstr "" #: pod/quiz/templates/quiz/video_quiz.html @@ -7591,7 +7595,7 @@ msgid "Can do better." msgstr "" #: pod/quiz/templates/quiz/video_quiz.html -msgid "It's not terrible, but there's room for improvement!" +msgid "It’s not terrible, but there’s room for improvement!" msgstr "" #: pod/quiz/templates/quiz/video_quiz.html @@ -7600,11 +7604,11 @@ msgstr "" #: pod/quiz/templates/quiz/video_quiz.html #, python-format -msgid "For the question \"%(title)s\", %(error)s." +msgid "For the question “%(title)s”, %(error)s." msgstr "" #: pod/quiz/templates/quiz/video_quiz.html -msgid "Right answer:" +msgid "Correct answer:" msgstr "" #: pod/quiz/templates/quiz/video_quiz.html @@ -7623,8 +7627,8 @@ msgstr "" msgid "Validate" msgstr "" -#: pod/quiz/templates/quiz/video_quiz_aside.html -msgid "Answer the quiz" +#: pod/quiz/templates/quiz/video_quiz.html +msgid "Manage quiz" msgstr "" #: pod/quiz/tests/test_views.py pod/quiz/views.py @@ -7644,21 +7648,29 @@ msgstr "" msgid "Quiz creation for the video “%s”" msgstr "" +#: pod/quiz/views.py +#, python-format +msgid "No answer defined for question %s." +msgstr "" + #: pod/quiz/views.py msgid "Quiz successfully created." msgstr "" +#: pod/quiz/views.py +msgid "Error during quiz creation." +msgstr "" + #: pod/quiz/views.py msgid "Quiz successfully updated." msgstr "" #: pod/quiz/views.py -msgid "The data sent to create the quiz are invalid." +msgid "Error during quiz update." msgstr "" #: pod/quiz/views.py -#, python-brace-format -msgid "Quiz edition for the video: {video.title}" +msgid "The data sent to create the quiz are invalid." msgstr "" #: pod/quiz/views.py @@ -7971,8 +7983,8 @@ msgstr "" #: pod/video/templates/videos/video-element.html msgid "" "To view this video please enable JavaScript, and consider upgrading to a web " -"browser that supports HTML5 video" +"browser that supports HTML5 video" msgstr "" #: pod/recorder/templates/recorder/link_record.html diff --git a/pod/locale/nl/LC_MESSAGES/djangojs.mo b/pod/locale/nl/LC_MESSAGES/djangojs.mo index 85f9b292831085e2f54967cfd61cce72737fd765..c1e6f65f880c6fbb3957ca7030492a6297fcadc6 100644 GIT binary patch delta 30 mcmbQsJePUGVlFdX0}};9Gb\n" "Language-Team: \n" "Language: nl\n" @@ -14,7 +14,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.4.2\n" +"X-Generator: Poedit 3.4.4\n" #: pod/ai_enhancement/static/ai_enhancement/js/enrich-form.js msgid "No discipline" @@ -436,7 +436,7 @@ msgstr "" msgid "Text copied" msgstr "" -#: pod/main/static/js/main.js +#: pod/main/static/js/main.js pod/quiz/static/quiz/js/create-quiz.js msgid "There are errors in the form, please correct them." msgstr "" @@ -629,21 +629,51 @@ msgid "Long answer" msgstr "" #: pod/quiz/static/quiz/js/create-quiz.js -msgid "Remove choice" +#, javascript-format +msgid "Select the choice #%s as correct answer." msgstr "" #: pod/quiz/static/quiz/js/create-quiz.js -msgid "Choice" +#, javascript-format +msgid "Remove choice %s" msgstr "" #: pod/quiz/static/quiz/js/create-quiz.js -msgid "Your choices" +#, javascript-format +msgid "Choice #%s" +msgstr "" + +#: pod/quiz/static/quiz/js/create-quiz.js +#, javascript-format +msgid "Choices for question #%s" msgstr "" #: pod/quiz/static/quiz/js/create-quiz.js msgid "Add a choice" msgstr "" +#: pod/quiz/static/quiz/js/create-quiz.js +#, javascript-format +msgid "Remove choice #%s" +msgstr "" + +#: pod/quiz/static/quiz/js/create-quiz.js +#, javascript-format +msgid "choice #%s" +msgstr "" + +#: pod/quiz/static/quiz/js/create-quiz.js +msgid "Choice" +msgstr "" + +#: pod/quiz/static/quiz/js/video-quiz-submit.js +msgid "Correct answer given" +msgstr "" + +#: pod/quiz/static/quiz/js/video-quiz-submit.js +msgid "Incorrect answer given" +msgstr "" + #: pod/video/static/js/ajax-display-channels.js msgid "%(count)s channel" msgid_plural "%(count)s channels" diff --git a/pod/main/static/css/pod.css b/pod/main/static/css/pod.css index e4a8ce8eff..4be7c6aea1 100755 --- a/pod/main/static/css/pod.css +++ b/pod/main/static/css/pod.css @@ -847,7 +847,11 @@ span[data-bs-placement] { .required_star, .form-help-inline { color: var(--bs-danger); - font-size: 1.3rem; + +} + +.form-check-label>.required_star { + font-size: 1em; } /* prevent a large link from extending beyond it's container @@ -1837,3 +1841,9 @@ body[data-admin-utc-offset] font-size: 13px; text-align: left; } + +/** QUIZ **/ + +.question-container li.bi::before { + margin-right: .5em; +} diff --git a/pod/main/static/js/main.js b/pod/main/static/js/main.js index 4b5df6a626..5b14a05f82 100644 --- a/pod/main/static/js/main.js +++ b/pod/main/static/js/main.js @@ -1244,8 +1244,7 @@ restricted_access(); form.addEventListener( "submit", function (event) { - if (form.checkValidity() === false) { - form.scrollIntoView(); + if (form.reportValidity() === false) { showalert( gettext("There are errors in the form, please correct them."), "alert-danger", diff --git a/pod/meeting/views.py b/pod/meeting/views.py index fd7f3bc31c..0f8c9b09ed 100644 --- a/pod/meeting/views.py +++ b/pod/meeting/views.py @@ -1061,7 +1061,7 @@ def get_html_content(request: WSGIRequest, meeting: Meeting) -> str:

    %(owner)s invites you to the meeting %(meeting_title)s.

    here the link to join the meeting: %(join_link)s

    -

    You need this password to enter: %(password)s

    +

    You need this password to enter: %(password)s

    Regards

    """ ) @@ -1086,7 +1086,7 @@ def get_html_content(request: WSGIRequest, meeting: Meeting) -> str:

    End date: %(end_date)s

    here the link to join the meeting: %(join_link)s

    -

    You need this password to enter: %(password)s

    +

    You need this password to enter: %(password)s

    Regards

    """ ) diff --git a/pod/playlist/static/playlist/js/playlist-reorganize.js b/pod/playlist/static/playlist/js/playlist-reorganize.js index c46145cfff..6a18db02d7 100644 --- a/pod/playlist/static/playlist/js/playlist-reorganize.js +++ b/pod/playlist/static/playlist/js/playlist-reorganize.js @@ -1,8 +1,12 @@ +/** + * Esup-Pod Playlist reorganize scripts. + */ + const exchangedValues = []; var infinite; -const reorganizeButtonsSpanElement = document.getElementById('reorganize-buttons'); -const collapseAsideElement = document.getElementById('collapseAside'); +// const reorganizeButtonsSpanElement = document.getElementById('reorganize-buttons'); +// const collapseAsideElement = document.getElementById('collapseAside'); const reorganizeButton = document.getElementById('reorganize-button'); addEventForReorganizedButton(); @@ -112,7 +116,7 @@ function onDrop(event) { */ function activateDragAndDrop(parent) { const draggableElements = document.querySelectorAll(".draggable-container"); - const cardFooterElements = document.querySelectorAll(".card-footer"); + // const cardFooterElements = document.querySelectorAll(".card-footer"); draggableElements.forEach((draggableElement) => { draggableElement.setAttribute('draggable', true); draggableElement.addEventListener('dragstart', onDragStart); diff --git a/pod/quiz/forms.py b/pod/quiz/forms.py index 121a4a1b76..ca2aa6e9c6 100644 --- a/pod/quiz/forms.py +++ b/pod/quiz/forms.py @@ -44,11 +44,11 @@ class QuestionForm(forms.Form): label=_("Explanation"), widget=forms.Textarea( attrs={ - "placeholder": _("Explanation of the question"), + "placeholder": _("Explanation of the answer."), } ), required=False, - help_text=_("Please choose an explanation."), + help_text=_("An explanation that will be displayed once the user has responded (feedback)."), ) start_timestamp = forms.IntegerField( label=_("Start timestamp"), @@ -56,7 +56,7 @@ class QuestionForm(forms.Form): min_value=0, widget=forms.NumberInput(attrs={"class": "start-timestamp-field"}), help_text=_( - "Please choose the beginning time of the answer in the video (in seconds)." + "The start time of the answer in the video (in seconds)." ), ) end_timestamp = forms.IntegerField( @@ -65,7 +65,7 @@ class QuestionForm(forms.Form): min_value=0, widget=forms.NumberInput(attrs={"class": "end-timestamp-field"}), help_text=_( - "Please choose the end time of the answer in the video (in seconds)." + "The end time of the answer in the video (in seconds)." ), ) type = forms.ChoiceField( @@ -123,7 +123,7 @@ def __init__(self, *args, **kwargs) -> None: super(QuestionForm, self).__init__(*args, **kwargs) self.fields = add_placeholder_and_asterisk(self.fields) - def _clean_single_choice(self): + def _clean_single_choice(self) -> None: """Call SingleChoiceQuestion's clean method.""" choices_str = self.cleaned_data.get("single_choice") single_choice_question = SingleChoiceQuestion(choices=choices_str) @@ -133,7 +133,7 @@ def _clean_single_choice(self): for error in e.error_list: self.add_error("single_choice", error) - def _clean_multiple_choice(self): + def _clean_multiple_choice(self) -> None: """Call MultipleChoiceQuestion's clean method.""" choices_str = self.cleaned_data.get("multiple_choice") multiple_choice_question = MultipleChoiceQuestion(choices=choices_str) @@ -172,11 +172,12 @@ class QuizDeleteForm(forms.Form): agree = forms.BooleanField( label=_("I agree"), + required=True, help_text=_("Delete video quiz cannot be undone"), widget=forms.CheckboxInput(), ) - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: """Init deletion quiz form.""" super(QuizDeleteForm, self).__init__(*args, **kwargs) self.fields = add_placeholder_and_asterisk(self.fields) @@ -186,7 +187,7 @@ def __init__(self, *args, **kwargs): class SingleChoiceQuestionForm(forms.ModelForm): - """Form to add or edit a single choice question form.""" + """Form to show a single choice question form.""" selected_choice = forms.CharField( label=_("Single choice question"), @@ -196,10 +197,12 @@ class SingleChoiceQuestionForm(forms.ModelForm): ) class Meta: + """SingleChoiceQuestionForm Metadata.""" + model = SingleChoiceQuestion fields = ["selected_choice"] - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: """Init single choice question form.""" super(SingleChoiceQuestionForm, self).__init__(*args, **kwargs) @@ -211,7 +214,8 @@ def __init__(self, *args, **kwargs): choices_list = [(choice, choice) for choice in choices_dict.keys()] self.fields["selected_choice"].widget.choices = choices_list - self.fields["selected_choice"].widget.attrs["class"] = "list-unstyled ps-2" + self.fields["selected_choice"].widget.wrap_label = False + self.fields["selected_choice"].widget.attrs["class"] = "list-unstyled ps-2 mb-0" def clean_selected_choice(self): data = self.cleaned_data["selected_choice"] @@ -219,7 +223,7 @@ def clean_selected_choice(self): class MultipleChoiceQuestionForm(forms.ModelForm): - """Form to add or edit a multiple choice question form.""" + """Form to show a multiple choice question form.""" selected_choice = forms.CharField( label=_("Multiple choice question"), @@ -232,7 +236,7 @@ class Meta: model = MultipleChoiceQuestion fields = ["selected_choice"] - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: """Init multiple choice question form.""" super(MultipleChoiceQuestionForm, self).__init__(*args, **kwargs) @@ -245,7 +249,7 @@ def __init__(self, *args, **kwargs): choices_list = [(choice, choice) for choice in choices_dict.keys()] self.fields["selected_choice"].widget.choices = choices_list - self.fields["selected_choice"].widget.attrs["class"] = "list-unstyled ps-2" + self.fields["selected_choice"].widget.attrs["class"] = "list-unstyled ps-2 mb-0" def clean_selected_choice(self): data = self.cleaned_data["selected_choice"] @@ -253,12 +257,12 @@ def clean_selected_choice(self): class ShortAnswerQuestionForm(forms.ModelForm): - """Form to add or edit a short answer question form.""" + """Form to show a short answer question form.""" user_answer = forms.CharField( label=_("Short answer question"), widget=forms.TextInput(), - required=False, + required=True, help_text=_("Write a short answer."), ) @@ -273,20 +277,22 @@ def __init__(self, *args, **kwargs) -> None: class LongAnswerQuestionForm(forms.ModelForm): - """Form to add or edit a long answer question form.""" + """Form to show a long answer question form.""" user_answer = forms.CharField( label=_("Long answer question"), widget=forms.Textarea(), - required=False, + required=True, help_text=_("Write a long answer."), ) class Meta: + """LongAnswerQuestionForm Metadata.""" + model = LongAnswerQuestion fields = ["user_answer"] def __init__(self, *args, **kwargs) -> None: - """Init short answer question form.""" + """Init long answer question form.""" super(LongAnswerQuestionForm, self).__init__(*args, **kwargs) self.fields = add_placeholder_and_asterisk(self.fields) diff --git a/pod/quiz/models.py b/pod/quiz/models.py index e6af7e94ce..7c68a51717 100644 --- a/pod/quiz/models.py +++ b/pod/quiz/models.py @@ -22,20 +22,22 @@ class Quiz(models.Model): Video, verbose_name=_("Video"), on_delete=models.CASCADE, - help_text=_("Please choose a video associated with the quiz."), + help_text=_("Choose a video associated with the quiz."), ) connected_user_only = models.BooleanField( verbose_name=_("Connected user only"), default=False, - help_text=_("Please choose if this quiz is only for connected users or not."), + help_text=_("Choose if this quiz is only for connected users or not."), ) show_correct_answers = models.BooleanField( verbose_name=_("Show correct answers"), default=True, - help_text=_("Please choose if the correct answers will be displayed or not."), + help_text=_("Choose if the correct answers will be displayed or not."), ) class Meta: + """Quiz Metadata.""" + ordering = ["id"] verbose_name = _("Quiz") verbose_name_plural = _("Quizzes") @@ -47,11 +49,11 @@ class Meta: ), ] - def __str__(self): - """String representation of the quiz.""" + def __str__(self) -> str: + """Represent the quiz as string.""" return _("Quiz of video") + " " + str(self.video) - def get_questions(self): + def get_questions(self) -> list: """ Retrieve questions associated with the quiz. @@ -79,7 +81,7 @@ class Question(models.Model): Quiz, verbose_name=_("Quiz"), on_delete=models.CASCADE, - help_text=_("Please choose a quiz associated with the question."), + help_text=_("Choose a quiz associated with the question."), ) title = models.CharField( verbose_name=_("Title"), @@ -96,18 +98,20 @@ class Question(models.Model): verbose_name=_("Start timestamp"), null=True, help_text=_( - "Please choose the beginning time of the answer in the video (in seconds)." + "The start time of the answer in the video (in seconds)." ), ) end_timestamp = models.PositiveIntegerField( verbose_name=_("End timestamp"), null=True, help_text=_( - "Please choose the end time of the answer in the video (in seconds)." + "The end time of the answer in the video (in seconds)." ), ) class Meta: + """Question Metadata.""" + ordering = ["id"] abstract = True verbose_name = _("Question") @@ -120,7 +124,7 @@ class Meta: ), ] - def clean(self): + def clean(self) -> None: """Clean method for Question model.""" super().clean() @@ -138,9 +142,9 @@ def clean(self): _("End timestamp cannot be defined without a start timestamp.") ) - def __str__(self): - """String representation of the question.""" - return _("Question") + " " + self.title + def __str__(self) -> str: + """Represent the question as string.""" + return _("Question “%s”") % self.title def get_question_form(self, data=None): """ @@ -154,7 +158,7 @@ def get_question_form(self, data=None): """ return "This method must be redefined in child class." - def get_answer(self): + def get_answer(self) -> None: """ Get the answer for the question. @@ -163,7 +167,7 @@ def get_answer(self): """ return None - def get_type(self): + def get_type(self) -> None: """ Get the type of the question. @@ -190,10 +194,12 @@ class SingleChoiceQuestion(Question): ) class Meta: + """SingleChoiceQuestion Metadata.""" + verbose_name = _("Single choice question") verbose_name_plural = _("Single choice questions") - def clean(self): + def clean(self) -> None: """Clean method for SingleChoiceQuestion model.""" super().clean() @@ -211,9 +217,9 @@ def clean(self): if sum([1 for choice in self.choices.values() if choice]) != 1: raise ValidationError(_("There must be only one correct answer.")) - def __str__(self): - """String representation of the SingleChoiceQuestion.""" - return super().__str__() + def __str__(self) -> str: + """Represent the SingleChoiceQuestion as string.""" + return "%s choices: %s" % (super().__str__(), self.choices) def get_answer(self): if isinstance(self.choices, str): @@ -226,6 +232,13 @@ def get_answer(self): ) return correct_answer + def get_choices(self): + """Return choices for this question.""" + if self.choices: + return self.choices + else: + return "{}" + def get_type(self): return "single_choice" @@ -261,10 +274,12 @@ class MultipleChoiceQuestion(Question): ) class Meta: + """MultipleChoiceQuestion Metadata.""" + verbose_name = _("Multiple choice question") verbose_name_plural = _("Multiple choice questions") - def clean(self): + def clean(self) -> None: """Clean method for MultipleChoiceQuestion model.""" super().clean() @@ -282,9 +297,9 @@ def clean(self): if not any(choices.values()): raise ValidationError(_("There must be at least one correct answer.")) - def __str__(self): - """String representation of the MultipleChoiceQuestion.""" - return super().__str__() + def __str__(self) -> str: + """Represent the MultipleChoiceQuestion as string.""" + return "%s choices: %s" % (super().__str__(), self.choices) def get_type(self): return "multiple_choice" @@ -300,6 +315,13 @@ def get_answer(self): ] return correct_answer + def get_choices(self): + """Return choices for this question.""" + if self.choices: + return self.choices + else: + return "{}" + def get_question_form(self, data=None): """ Get the form for the question. @@ -337,8 +359,8 @@ class Meta: verbose_name = _("True/false question") verbose_name_plural = _("True/false questions") - def __str__(self): - """String representation of the TrueFalseQuestion.""" + def __str__(self) -> str: + """Represent the TrueFalseQuestion as string.""" return super().__str__() def get_type(self): @@ -364,11 +386,11 @@ class Meta: verbose_name = _("Short answer question") verbose_name_plural = _("Short answer questions") - def __str__(self): - """String representation of the ShortAnswerQuestion.""" + def __str__(self) -> str: + """Represent the ShortAnswerQuestion as string.""" return super().__str__() - def get_answer(self): + def get_answer(self) -> str: return self.answer def get_type(self): @@ -377,6 +399,7 @@ def get_type(self): def get_question_form(self, data=None): """ Get the form for the question. + Args: data (dict): Form data. Returns: @@ -407,11 +430,11 @@ class Meta: verbose_name = _("Long answer question") verbose_name_plural = _("Long answer questions") - def __str__(self): - """String representation of the LongAnswerQuestion.""" + def __str__(self) -> str: + """Representation the LongAnswerQuestion as string.""" return super().__str__() - def get_answer(self): + def get_answer(self) -> str: return self.answer def get_type(self): @@ -420,6 +443,7 @@ def get_type(self): def get_question_form(self, data=None): """ Get the form for the question. + Args: data (dict): Form data. Returns: diff --git a/pod/quiz/static/quiz/js/create-quiz.js b/pod/quiz/static/quiz/js/create-quiz.js index a5d4b27e7d..19aca27417 100644 --- a/pod/quiz/static/quiz/js/create-quiz.js +++ b/pod/quiz/static/quiz/js/create-quiz.js @@ -1,8 +1,18 @@ /** * @file Esup-Pod functions for the quiz creation or edit form. - * @since 3.6.0 + * @since 3.7.0 */ +// Read-only globals defined in video-script.html +/* +global player +*/ + +// Read-only globals defined in create_edit_quiz.html +/* +global initialData +*/ + document.addEventListener("DOMContentLoaded", function () { let addQuestionButton = document.getElementById("add-question"); const totalNewForms = document.getElementById("id_questions-TOTAL_FORMS"); @@ -17,7 +27,7 @@ document.addEventListener("DOMContentLoaded", function () { let questionsTypeElements = document.querySelectorAll( ".question-select-type", ); - for (questionTypeEl of questionsTypeElements) { + for (let questionTypeEl of questionsTypeElements) { addEventListenerQuestionType(questionTypeEl); } @@ -34,9 +44,8 @@ document.addEventListener("DOMContentLoaded", function () { if (!initialData) { return null; } - const questionIndex = questionForm.getAttribute("data-question-index"); - const questionData = initialData.existing_questions[questionIndex]; - return questionData; + const questionIndex = Number(questionForm.getAttribute("data-question-index")); + return initialData.existing_questions[questionIndex]; } /** @@ -44,7 +53,7 @@ document.addEventListener("DOMContentLoaded", function () { * @param {HTMLElement} questionTypeElement - The HTML element representing the question type. */ function addEventListenerQuestionType(questionTypeElement) { - questionTypeElement.addEventListener("change", function (event) { + questionTypeElement.addEventListener("change", function () { let questionForm = questionTypeElement.closest(".question-form"); handleQuestionType(questionForm); }); @@ -54,7 +63,7 @@ document.addEventListener("DOMContentLoaded", function () { let removeQuestionButtons = document.querySelectorAll( ".delete-question-button", ); - for (removeQuestionButton of removeQuestionButtons) { + for (let removeQuestionButton of removeQuestionButtons) { removeQuestionButton.addEventListener("click", removeQuestionForm); } @@ -148,7 +157,8 @@ document.addEventListener("DOMContentLoaded", function () { const questionFormToDelete = event.target.closest(".question-form"); if (questionFormToDelete) { - + + // If the question already exist in Pod, we only hide in dom and send a "delete" input. const deleteInput = document.getElementById(`id_questions-${questionFormToDelete.getAttribute("data-question-index")}-DELETE`); if (deleteInput) { deleteInput.checked = true; @@ -158,7 +168,7 @@ document.addEventListener("DOMContentLoaded", function () { const currentQuestionForms = document.querySelectorAll(".question-form"); totalNewForms.setAttribute("value", currentQuestionForms.length - 1); } - + } } @@ -176,15 +186,16 @@ document.addEventListener("DOMContentLoaded", function () { input.type = "text"; input.id = inputId; input.name = inputId; + input.required = true; input.placeholder = gettext("The short answer"); input.classList.add("short-answer-field", "form-control"); label.setAttribute("for", inputId); label.textContent = gettext("Short answer"); - let initialData = getQuestionData(questionForm); - if (initialData && initialData["short_answer"] != null) { - input.value = initialData["short_answer"]; + let qData = getQuestionData(questionForm); + if (qData && qData["short_answer"] != null) { + input.value = qData["short_answer"]; } const questionChoicesForm = questionForm.querySelector(".question-choices-form"); @@ -203,15 +214,16 @@ document.addEventListener("DOMContentLoaded", function () { textarea.id = textareaId; textarea.name = textareaId; + textarea.required = true; textarea.placeholder = gettext("The long answer"); textarea.classList.add("long-answer-field", "form-control"); label.setAttribute("for", textareaId); label.textContent = gettext("Long answer"); - let initialData = getQuestionData(questionForm); - if (initialData && initialData["long_answer"] != null) { - textarea.value = initialData["long_answer"]; + let qData = getQuestionData(questionForm); + if (qData && qData["long_answer"] != null) { + textarea.value = qData["long_answer"]; } const questionChoicesForm = questionForm.querySelector(".question-choices-form"); @@ -225,6 +237,7 @@ document.addEventListener("DOMContentLoaded", function () { */ function handleSingleChoiceQuestion(questionForm) { const choicesForm = questionForm.querySelector(".question-choices-form"); + const questionIndex = Number(questionForm.getAttribute("data-question-index")); const createChoiceElement = (index, choice) => { const choiceDiv = document.createElement("div"); @@ -232,29 +245,40 @@ document.addEventListener("DOMContentLoaded", function () { const input = document.createElement("input"); input.type = "radio"; + input.required = true; input.classList.add("form-check-input"); + message = gettext("Select the choice #%s as correct answer."); + input.title = interpolate(message, [index]); input.name = `choice-${questionForm.getAttribute("data-question-index")}`; input.id = `choice-${questionForm.getAttribute("data-question-index")}-${index}`; const deleteButton = document.createElement("a"); - deleteButton.setAttribute('title', gettext("Remove choice") + ` ${index}`) - deleteButton.setAttribute('role', 'button') - deleteButton.classList.add( + const deleteIcon = document.createElement("i"); + deleteIcon.classList.add( "bi", - "bi-trash", + "bi-trash" + ); + deleteButton.appendChild(deleteIcon); + message = gettext("Remove choice %s"); + deleteButton.setAttribute('title', interpolate(message, [index])); + deleteButton.setAttribute('role', 'button'); + deleteButton.classList.add( "btn", "btn-link", "pod-btn-social", ); + deleteButton.addEventListener("click", function () { choiceDiv.remove(); }); const textInput = document.createElement("input"); - textInput.id = `choice-text-${questionForm.getAttribute("data-question-index")}-${index}`; - textInput.name = `choice-text-${questionForm.getAttribute("data-question-index")}`; + textInput.id = `choice-text-${questionIndex}-${index}`; + textInput.name = `choice-text-${questionIndex}`; textInput.type = "text"; - textInput.placeholder = gettext("Choice") + ` ${index}`; + textInput.required = true; + message = gettext("Choice #%s"); + textInput.placeholder = interpolate(message, [index]); textInput.classList.add("form-control", "ms-2"); if (choice) { textInput.value = choice[0]; @@ -266,12 +290,12 @@ document.addEventListener("DOMContentLoaded", function () { const inputLabel = document.createElement("label"); inputLabel.setAttribute("for", input.id); inputLabel.textContent = textInput.placeholder; - inputLabel.classList.add("d-none") + inputLabel.classList.add("d-none"); const textInputLabel = document.createElement("label"); textInputLabel.setAttribute("for", textInput.id); textInputLabel.textContent = textInput.placeholder; - textInputLabel.classList.add("d-none") + textInputLabel.classList.add("d-none"); choiceDiv.appendChild(inputLabel); choiceDiv.appendChild(input); @@ -285,12 +309,13 @@ document.addEventListener("DOMContentLoaded", function () { const fieldset = document.createElement("fieldset"); const legend = document.createElement("legend"); legend.classList.add("col-form-label"); - legend.textContent = gettext("Your choices"); + let message = gettext("Choices for question #%s"); + legend.textContent = interpolate(message, [questionIndex+1]); fieldset.appendChild(legend); - let initialData = getQuestionData(questionForm); - if (initialData && initialData["choices"] != null) { - const initialChoices = Object.entries(initialData["choices"]); + let qData = getQuestionData(questionForm); + if (qData && qData["choices"] != null) { + const initialChoices = Object.entries(qData["choices"]); for (let i = 0; i < initialChoices.length; i++) { fieldset.appendChild(createChoiceElement(i + 1, initialChoices[i])); } @@ -303,7 +328,7 @@ document.addEventListener("DOMContentLoaded", function () { const addButton = document.createElement("button"); addButton.textContent = gettext("Add a choice"); addButton.type = "button"; - addButton.classList.add("btn", "btn-outline-secondary", "btn-sm", "mt-2"); + addButton.classList.add("btn", "btn-primary", "btn-sm", "mt-2"); addButton.addEventListener("click", function () { fieldset.appendChild( createChoiceElement( @@ -322,6 +347,7 @@ document.addEventListener("DOMContentLoaded", function () { */ function handleMultipleChoiceQuestion(questionForm) { const choicesForm = questionForm.querySelector(".question-choices-form"); + const questionIndex = Number(questionForm.getAttribute("data-question-index")); const createChoiceElement = (index, choice) => { const choiceDiv = document.createElement("div"); @@ -330,20 +356,26 @@ document.addEventListener("DOMContentLoaded", function () { const input = document.createElement("input"); input.type = "checkbox"; + let message = gettext("Select the choice #%s as correct answer."); + input.title = interpolate(message, [index]); input.classList.add("form-check-input"); - input.name = `choice-${questionForm.getAttribute("data-question-index")}`; - input.id = `choice-${questionForm.getAttribute("data-question-index")}-${index}`; + input.name = `choice-${questionIndex}`; + input.id = `choice-${questionIndex}-${index}`; const deleteButton = document.createElement("a"); - deleteButton.setAttribute('title', gettext("Remove choice") + ` ${index}`) - deleteButton.setAttribute('role', 'button') - deleteButton.classList.add( + message = gettext("Remove choice #%s"); + const deleteIcon = document.createElement("i"); + deleteIcon.classList.add( "bi", - "bi-trash", + "bi-trash" + ); + deleteButton.appendChild(deleteIcon); + deleteButton.setAttribute('title', interpolate(message, [index])); + deleteButton.setAttribute('role', 'button'); + deleteButton.classList.add( "btn", "btn-link", "pod-btn-social", - "py-0", ); deleteButton.addEventListener("click", function () { choiceDiv.remove(); @@ -351,9 +383,11 @@ document.addEventListener("DOMContentLoaded", function () { const textInput = document.createElement("input"); textInput.type = "text"; + textInput.required = true; textInput.id = `choice-text-${questionForm.getAttribute("data-question-index")}-${index}`; textInput.name = `choice-text-${questionForm.getAttribute("data-question-index")}`; - textInput.placeholder = gettext("Choice") + ` ${index}`; + message = gettext("choice #%s"); + textInput.placeholder = interpolate(message, [index]); textInput.classList.add("form-control", "ms-2"); if (choice) { textInput.value = choice[0]; @@ -384,12 +418,13 @@ document.addEventListener("DOMContentLoaded", function () { const fieldset = document.createElement("fieldset"); const legend = document.createElement("legend"); legend.classList.add("col-form-label"); - legend.textContent = gettext("Your choices"); + let message = gettext("Choices for question #%s"); + legend.textContent = interpolate(message, [questionIndex+1]); fieldset.appendChild(legend); - let initialData = getQuestionData(questionForm); - if (initialData && initialData["choices"] != null) { - const initialChoices = Object.entries(initialData["choices"]); + let qData = getQuestionData(questionForm); + if (qData && qData["choices"] != null) { + const initialChoices = Object.entries(qData["choices"]); for (let i = 0; i < initialChoices.length; i++) { fieldset.appendChild(createChoiceElement(i + 1, initialChoices[i])); } @@ -402,7 +437,7 @@ document.addEventListener("DOMContentLoaded", function () { const addButton = document.createElement("button"); addButton.textContent = gettext("Add a choice"); addButton.type = "button"; - addButton.classList.add("btn", "btn-outline-secondary", "btn-sm", "mt-2"); + addButton.classList.add("btn", "btn-primary", "btn-sm", "mt-2"); addButton.addEventListener("click", function () { fieldset.appendChild( createChoiceElement( @@ -477,14 +512,13 @@ document.addEventListener("DOMContentLoaded", function () { buttonElement.classList.add( "get-timestamp-from-video", "btn", - "btn-outline-secondary", + "btn-secondary", "btn-sm", - "ms-2", - "mb-2", + "m-1" ); buttonElement.textContent = gettext("Get time from the player"); - buttonElement.addEventListener("click", (event) => { + buttonElement.addEventListener("click", () => { if (!(typeof player === "undefined")) { htmlElement.value = Math.floor(player.currentTime()); } @@ -506,36 +540,47 @@ document.addEventListener("DOMContentLoaded", function () { let submissionButton = document.getElementById("quiz-submission-button"); submissionButton.addEventListener("click", (event) => { - if (event) { - event.preventDefault(); - } + let form = document.getElementById("quiz-form"); - let questionFormsList = document.querySelectorAll(".question-form"); - for (questionForm of questionFormsList) { - const questionType = questionForm.querySelector( - ".question-select-type", - ).value; - switch (questionType) { - case "short_answer": - handleShortAnswerSubmission(questionForm); - break; - case "long_answer": - handleLongAnswerSubmission(questionForm); - break; - case "single_choice": - handleSingleChoiceSubmission(questionForm); - break; - case "multiple_choice": - handleMultipleChoiceSubmission(questionForm); - break; - // Add other cases for other type of question - default: - break; + if (form.reportValidity() === false) { + showalert( + gettext("There are errors in the form, please correct them."), + "alert-danger", + ); + event.preventDefault(); + event.stopPropagation(); + form.classList.add("was-validated"); + } else { + form.classList.add("was-validated"); + if (form.dataset.morecheck) { + window[form.dataset.morecheck](form, event); + } + let questionFormsList = document.querySelectorAll(".question-form"); + for (let questionForm of questionFormsList) { + console.log(questionForm); + const questionType = questionForm.querySelector( + ".question-select-type", + ).value; + switch (questionType) { + case "short_answer": + handleShortAnswerSubmission(questionForm); + break; + case "long_answer": + handleLongAnswerSubmission(questionForm); + break; + case "single_choice": + handleSingleChoiceSubmission(questionForm); + break; + case "multiple_choice": + handleMultipleChoiceSubmission(questionForm); + break; + // Add other cases for other type of question + default: + break; + } } + form.submit(); } - let form = document.getElementById("quiz-form"); - console.log(form); - form.submit(); }); } diff --git a/pod/quiz/static/quiz/js/video-quiz-submit.js b/pod/quiz/static/quiz/js/video-quiz-submit.js index 39630edd6f..d8487f7a08 100644 --- a/pod/quiz/static/quiz/js/video-quiz-submit.js +++ b/pod/quiz/static/quiz/js/video-quiz-submit.js @@ -1,6 +1,20 @@ +/** + * @file Esup-Pod video QUiz submission script. + * @since 3.7.0 + */ + +// Read-only globals defined in video-script.html +/* +global player +*/ +// Read-only globals defined in video_quiz.html +/* +global questions_answers +*/ + const questionList = document.querySelectorAll(".question-container"); -for (questionElement of questionList) { +for (let questionElement of questionList) { let showResponseButton = questionElement.querySelector( ".show-response-button", ); @@ -8,28 +22,40 @@ for (questionElement of questionList) { showResponseButton.addEventListener("click", function (event) { event.preventDefault(); if(player.paused()) { - player.play() + player.play(); } player.currentTime(this.attributes.start.value); }); } - - // get all answer and parse it - // if answer in good answer, put it in green else if user answer put it in red + let questionid = questionElement.dataset.questionid; + + // Get short or long answer input + let textInput = document.getElementById(`id_${questionid}-user_answer`); + if (textInput) { + textInput.disabled = true; + } + + // get all checkbox & radio answers and parse them. + // if answer in good answer, put it in green else if user answer put it in red let allanswers = questionElement.querySelectorAll(`ul#id_${questionid}-selected_choice li input`); - for (answer of allanswers) { + for (let answer of allanswers) { + answer.disabled=true; if (questions_answers[`${questionid}`]) { let user_answer = questions_answers[`${questionid}`][0]; let correct_answer = questions_answers[`${questionid}`][1]; if( (Array.isArray(correct_answer) && correct_answer.includes(answer.value)) || correct_answer === answer.value ){ - answer.closest('li').classList.add('alert', 'alert-success'); + answer.closest('li').classList.add('bi', 'bi-clipboard-check', 'text-success'); + answer.closest('li').title=gettext("Correct answer given"); } else if ((Array.isArray(user_answer) && user_answer.includes(answer.value)) || user_answer === answer.value ){ - answer.closest('li').classList.add('alert', 'alert-danger'); + answer.closest('li').classList.add('bi', 'bi-clipboard-x', 'text-danger'); + answer.closest('li').title=gettext("Incorrect answer given"); + } else { + answer.closest('li').classList.add('bi', 'bi-clipboard'); } if ((Array.isArray(user_answer) && user_answer.includes(answer.value)) || user_answer === answer.value ){ answer.checked = true; } } - } + } } diff --git a/pod/quiz/templates/quiz/create_edit_quiz.html b/pod/quiz/templates/quiz/create_edit_quiz.html index 0cfe3b299a..d93b8818af 100644 --- a/pod/quiz/templates/quiz/create_edit_quiz.html +++ b/pod/quiz/templates/quiz/create_edit_quiz.html @@ -1,6 +1,7 @@ {% extends 'base.html' %} {% load i18n %} {% load static %} +{% load video_quiz %} {% block page_extra_head %} {% include 'videos/video-header.html' %} @@ -58,31 +59,58 @@ {% endwith %} {% endfor %}

-
- {% include "quiz/question_form.html" with form=question_formset.empty_form form_index="__prefix__" %} -
- +
- + {% trans "Back to video" %}
+ +
+ {% include "quiz/question_form.html" with form=question_formset.empty_form form_index="__prefix__" %} +
{% endblock page_content %} {% block page_aside %} - {% if video.owner == request.user or request.user.is_superuser or perms.chapter.add_chapter or request.user in video.additional_owners.all %} -
-

 {% trans "Manage video"%}

-
- {% include "videos/link_video.html" with hide_favorite_link=True %} + {% if video.owner == request.user or request.user.is_superuser or request.user in video.additional_owners.all %} +
+

+  {% trans "Manage video"%} +

+
+ {% include "videos/link_video.html" with hide_favorite_link=True %} +
+
+
+

+  {% trans "Quiz"%} +

+
+ {% is_quiz_accessible video as is_quiz_accessible %} + {% if is_quiz_accessible %} + + + {% trans 'Answer the quiz' %} + + {% endif %} + + + {% trans 'Delete your quiz' %} + +
-
{% endif %}
-

 {% trans "Video"%}

+

+  {% trans "Video"%} +

{% include 'videos/video-element.html' %}
diff --git a/pod/quiz/templates/quiz/delete_quiz.html b/pod/quiz/templates/quiz/delete_quiz.html index e78c497fb8..e0f906146b 100644 --- a/pod/quiz/templates/quiz/delete_quiz.html +++ b/pod/quiz/templates/quiz/delete_quiz.html @@ -55,7 +55,9 @@ {% endfor %} diff --git a/pod/quiz/templates/quiz/manage_quiz.html b/pod/quiz/templates/quiz/manage_quiz.html new file mode 100644 index 0000000000..ddd1fea5d2 --- /dev/null +++ b/pod/quiz/templates/quiz/manage_quiz.html @@ -0,0 +1,21 @@ +{% load i18n %} +{% load video_quiz %} + +{% is_quiz_exists video as is_quiz_exists %} +{% if video.owner == request.user or request.user in video.additional_owners.all %} + {% if is_quiz_exists %} + + + {% trans 'Edit your quiz' %} + + + + {% trans 'Delete your quiz' %} + + {% else %} + + + {% trans 'Create a quiz' %} + + {% endif %} +{% endif %} diff --git a/pod/quiz/templates/quiz/question_form.html b/pod/quiz/templates/quiz/question_form.html index 58e178ea93..b71a632253 100644 --- a/pod/quiz/templates/quiz/question_form.html +++ b/pod/quiz/templates/quiz/question_form.html @@ -22,22 +22,20 @@ {% for field in form.visible_fields %} {% spaceless %} -
-
- {{ field.errors }} - {% if "form-check-input" in field.field.widget.attrs.class %} -
- {{ field }} -
- {% else %} - - {{ field }} - {% endif %} - {% if field.help_text %} - {{ field.help_text|safe }} - {% endif %} - {% if field.field.required %}
{% trans "Please provide a valid value for this field." %}
{% endif %} -
+
+ {{ field.errors }} + {% if "form-check-input" in field.field.widget.attrs.class %} +
+ {{ field }} +
+ {% else %} + + {{ field }} + {% endif %} + {% if field.help_text %} + {{ field.help_text|safe }} + {% endif %} + {% if field.field.required %}
{% trans "Please provide a valid value for this field." %}
{% endif %}
{% endspaceless %} {% endfor %} diff --git a/pod/quiz/templates/quiz/video_quiz.html b/pod/quiz/templates/quiz/video_quiz.html index 8036542044..94d9fdef3b 100644 --- a/pod/quiz/templates/quiz/video_quiz.html +++ b/pod/quiz/templates/quiz/video_quiz.html @@ -26,7 +26,7 @@ {% if percentage_score >= 75 %} {% elif percentage_score >= 45 %}