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 69ec26e12e..d1bd46c9eb 100644 Binary files a/pod/locale/fr/LC_MESSAGES/django.mo and b/pod/locale/fr/LC_MESSAGES/django.mo differ 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 21444518f7..74cf27b6fb 100644 Binary files a/pod/locale/fr/LC_MESSAGES/djangojs.mo and b/pod/locale/fr/LC_MESSAGES/djangojs.mo differ diff --git a/pod/locale/fr/LC_MESSAGES/djangojs.po b/pod/locale/fr/LC_MESSAGES/djangojs.po index 2b56d85376..dad031dce7 100644 --- a/pod/locale/fr/LC_MESSAGES/djangojs.po +++ b/pod/locale/fr/LC_MESSAGES/djangojs.po @@ -5,9 +5,9 @@ msgid "" msgstr "" "Project-Id-Version: Esup-Pod\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-06-04 13:25+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: \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 804868c257..6aa3517b50 100644 Binary files a/pod/locale/nl/LC_MESSAGES/django.mo and b/pod/locale/nl/LC_MESSAGES/django.mo differ 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 85f9b29283..c1e6f65f88 100644 Binary files a/pod/locale/nl/LC_MESSAGES/djangojs.mo and b/pod/locale/nl/LC_MESSAGES/djangojs.mo differ diff --git a/pod/locale/nl/LC_MESSAGES/djangojs.po b/pod/locale/nl/LC_MESSAGES/djangojs.po index 208567eb18..d9f1a34f9a 100644 --- a/pod/locale/nl/LC_MESSAGES/djangojs.po +++ b/pod/locale/nl/LC_MESSAGES/djangojs.po @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: Esup-Pod\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-06-04 13:25+0000\n" -"PO-Revision-Date: 2024-04-15 14:27+0200\n" +"POT-Creation-Date: 2024-06-05 15:31+0000\n" +"PO-Revision-Date: 2024-06-04 16:20+0200\n" "Last-Translator: obado \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 %}