From 2840a15fd5ec56af87229ba7701d904bd655f321 Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Wed, 5 Apr 2023 16:54:16 +0200 Subject: [PATCH] Add form to add juries in a pool Signed-off-by: Emmy D'Anello --- locale/fr/LC_MESSAGES/django.po | 222 +++++++++++------- participation/forms.py | 45 ++++ .../participation/pool_add_jurys.html | 47 ++++ .../templates/participation/pool_detail.html | 7 +- participation/urls.py | 5 +- participation/views.py | 62 ++++- .../registration/mails/add_organizer.html | 2 +- .../registration/mails/add_organizer.txt | 2 +- tfjm/settings.py | 1 + tfjm/templates/base.html | 11 +- 10 files changed, 308 insertions(+), 96 deletions(-) create mode 100644 participation/templates/participation/pool_add_jurys.html diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index a05b444..3616fe5 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: TFJM\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-04-05 10:43+0200\n" +"POT-Creation-Date: 2023-04-05 16:46+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Emmy D'Anello \n" "Language-Team: LANGUAGE \n" @@ -422,80 +422,94 @@ msgstr "rapporteur⋅e" msgid "problem" msgstr "numéro de problème" -#: participation/forms.py:27 +#: participation/forms.py:30 msgid "This name is already used." msgstr "Ce nom est déjà utilisé." -#: participation/forms.py:34 participation/models.py:40 +#: participation/forms.py:37 participation/models.py:40 msgid "The trigram must be composed of three uppercase letters." msgstr "Le trigramme doit être composé de trois lettres majuscules." -#: participation/forms.py:37 +#: participation/forms.py:40 msgid "This trigram is already used." msgstr "Ce trigramme est déjà utilisé." -#: participation/forms.py:52 +#: participation/forms.py:55 msgid "No team was found with this access code." msgstr "Aucune équipe n'a été trouvée avec ce code d'accès." -#: participation/forms.py:81 participation/forms.py:289 +#: participation/forms.py:84 participation/forms.py:334 #: registration/forms.py:113 registration/forms.py:135 #: registration/forms.py:157 registration/forms.py:179 #: registration/forms.py:224 msgid "The uploaded file size must be under 2 Mo." msgstr "Le fichier envoyé doit peser moins de 2 Mo." -#: participation/forms.py:83 registration/forms.py:115 +#: participation/forms.py:86 registration/forms.py:115 #: registration/forms.py:137 registration/forms.py:159 #: registration/forms.py:181 registration/forms.py:226 msgid "The uploaded file must be a PDF, PNG of JPEG file." msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG." -#: participation/forms.py:101 +#: participation/forms.py:104 msgid "I engage myself to participate to the whole TFJM²." msgstr "Je m'engage à participer à l'intégralité du TFJM²." -#: participation/forms.py:116 +#: participation/forms.py:119 msgid "Message to address to the team:" msgstr "Message à adresser à l'équipe :" -#: participation/forms.py:151 +#: participation/forms.py:154 msgid "The uploaded file size must be under 5 Mo." msgstr "Le fichier envoyé doit peser moins de 5 Mo." -#: participation/forms.py:153 participation/forms.py:291 +#: participation/forms.py:156 participation/forms.py:336 msgid "The uploaded file must be a PDF file." msgstr "Le fichier envoyé doit être au format PDF." -#: participation/forms.py:157 +#: participation/forms.py:160 msgid "The PDF file must not have more than 30 pages." msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages." -#: participation/forms.py:203 +#: participation/forms.py:209 +msgid "Add new jury" +msgstr "Ajouter un⋅e nouvelleau juré⋅e" + +#: participation/forms.py:224 +#: participation/templates/participation/pool_detail.html:77 +#: participation/templates/participation/tournament_detail.html:111 +msgid "Add" +msgstr "Ajouter" + +#: participation/forms.py:237 registration/forms.py:35 registration/forms.py:60 +msgid "This email address is already used." +msgstr "Cette adresse e-mail est déjà utilisée." + +#: participation/forms.py:248 msgid "CSV file:" msgstr "Tableur au format CSV :" -#: participation/forms.py:220 +#: participation/forms.py:265 msgid "" "This file contains non-UTF-8 content. Please send your sheet as a CSV file." msgstr "" "Ce fichier contient des éléments non-UTF-8. Merci d'envoyer votre tableur au " "format CSV." -#: participation/forms.py:247 +#: participation/forms.py:292 msgid "The following note is higher of the maximum expected value:" msgstr "La note suivante est supérieure au maximum attendu :" -#: participation/forms.py:255 +#: participation/forms.py:300 msgid "The following user was not found:" msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :" -#: participation/forms.py:272 +#: participation/forms.py:317 msgid "The defender, the opponent and the reporter must be different." msgstr "" "Læ défenseur⋅se, l'opposant⋅e et læ rapporteur⋅e doivent être différent⋅es." -#: participation/forms.py:276 +#: participation/forms.py:321 msgid "This defender did not work on this problem." msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème." @@ -853,12 +867,12 @@ msgstr "" #: participation/templates/participation/create_team.html:11 #: participation/templates/participation/tournament_form.html:14 -#: tfjm/templates/base.html:248 +#: tfjm/templates/base.html:255 msgid "Create" msgstr "Créer" #: participation/templates/participation/join_team.html:11 -#: tfjm/templates/base.html:243 +#: tfjm/templates/base.html:250 msgid "Join" msgstr "Rejoindre" @@ -866,9 +880,10 @@ msgstr "Rejoindre" #: participation/templates/participation/passage_detail.html:46 #: participation/templates/participation/passage_detail.html:102 #: participation/templates/participation/passage_detail.html:108 -#: participation/templates/participation/pool_detail.html:58 -#: participation/templates/participation/pool_detail.html:77 +#: participation/templates/participation/pool_add_jurys.html:35 +#: participation/templates/participation/pool_detail.html:63 #: participation/templates/participation/pool_detail.html:82 +#: participation/templates/participation/pool_detail.html:87 #: participation/templates/participation/team_detail.html:126 #: participation/templates/participation/team_detail.html:190 #: participation/templates/participation/tournament_form.html:12 @@ -932,7 +947,7 @@ msgstr "Envoyer une solution" #: participation/templates/participation/participation_detail.html:59 #: participation/templates/participation/passage_detail.html:114 -#: participation/templates/participation/pool_detail.html:87 +#: participation/templates/participation/pool_detail.html:92 #: participation/templates/participation/team_detail.html:185 #: participation/templates/participation/upload_motivation_letter.html:13 #: participation/templates/participation/upload_notes.html:24 @@ -1037,6 +1052,37 @@ msgstr "Points de læ rapporteur⋅e :" msgid "Update passage" msgstr "Modifier le passage" +#: participation/templates/participation/pool_add_jurys.html:9 +msgid "You can here register juries for the pool." +msgstr "Vous pouvez inscrire ici les juré⋅es de la poule." + +#: participation/templates/participation/pool_add_jurys.html:10 +msgid "" +"Be careful: this form register new users. To add existing users into the " +"jury, please use this form:" +msgstr "" +"Attention : ce formulaire inscrit des nouvelleaux utilisateur⋅rices. " +"Pour ajouter des utilisateur⋅rices au jury, utilisez ce formulaire :" + +#: participation/templates/participation/pool_add_jurys.html:11 +#: participation/templates/participation/pool_add_jurys.html:34 +#: participation/templates/participation/pool_detail.html:81 +#: participation/templates/participation/pool_form.html:11 +msgid "Update pool" +msgstr "Modifier la poule" + +#: participation/templates/participation/pool_add_jurys.html:14 +msgid "For now, the registered juries for the tournament are:" +msgstr "Pour l'instant, les juré⋅es inscrit⋅es au tournoi sont :" + +#: participation/templates/participation/pool_add_jurys.html:19 +msgid "There is no jury yet." +msgstr "Il n'y a pas de juré⋅e pour le moment." + +#: participation/templates/participation/pool_add_jurys.html:30 +msgid "Back to pool detail" +msgstr "Retour aux détails de la poule" + #: participation/templates/participation/pool_detail.html:15 msgid "Round:" msgstr "Tour :" @@ -1053,48 +1099,42 @@ msgstr "Équipes :" msgid "Juries:" msgstr "Juré⋅es :" -#: participation/templates/participation/pool_detail.html:31 +#: participation/templates/participation/pool_detail.html:32 +msgid "Add jurys" +msgstr "Ajouter des juré⋅es" + +#: participation/templates/participation/pool_detail.html:36 msgid "Defended solutions:" msgstr "Solutions défendues :" -#: participation/templates/participation/pool_detail.html:38 +#: participation/templates/participation/pool_detail.html:43 msgid "BigBlueButton link:" msgstr "Lien BigBlueButton :" -#: participation/templates/participation/pool_detail.html:44 +#: participation/templates/participation/pool_detail.html:49 #: participation/templates/participation/tournament_detail.html:97 msgid "Ranking" msgstr "Classement" -#: participation/templates/participation/pool_detail.html:57 -#: participation/templates/participation/pool_detail.html:71 +#: participation/templates/participation/pool_detail.html:62 +#: participation/templates/participation/pool_detail.html:76 msgid "Add passage" msgstr "Ajouter un passage" -#: participation/templates/participation/pool_detail.html:59 -#: participation/templates/participation/pool_detail.html:81 +#: participation/templates/participation/pool_detail.html:64 +#: participation/templates/participation/pool_detail.html:86 msgid "Update teams" msgstr "Modifier les équipes" -#: participation/templates/participation/pool_detail.html:60 +#: participation/templates/participation/pool_detail.html:65 msgid "Upload notes from a CSV file" msgstr "Soumettre les notes à partir d'un fichier CSV" -#: participation/templates/participation/pool_detail.html:67 +#: participation/templates/participation/pool_detail.html:72 msgid "Passages" msgstr "Passages" -#: participation/templates/participation/pool_detail.html:72 -#: participation/templates/participation/tournament_detail.html:111 -msgid "Add" -msgstr "Ajouter" - -#: participation/templates/participation/pool_detail.html:76 -#: participation/templates/participation/pool_form.html:11 -msgid "Update pool" -msgstr "Modifier la poule" - -#: participation/templates/participation/pool_detail.html:86 +#: participation/templates/participation/pool_detail.html:91 msgid "Upload notes" msgstr "Envoyer les notes" @@ -1228,7 +1268,7 @@ msgid "Invalidate" msgstr "Invalider" #: participation/templates/participation/team_detail.html:184 -#: participation/views.py:333 +#: participation/views.py:335 msgid "Upload motivation letter" msgstr "Envoyer la lettre de motivation" @@ -1237,7 +1277,7 @@ msgid "Update team" msgstr "Modifier l'équipe" #: participation/templates/participation/team_detail.html:194 -#: participation/views.py:442 +#: participation/views.py:444 msgid "Leave team" msgstr "Quitter l'équipe" @@ -1246,7 +1286,7 @@ msgid "Are you sure that you want to leave this team?" msgstr "Êtes-vous sûr·e de vouloir quitter cette équipe ?" #: participation/templates/participation/team_list.html:6 -#: tfjm/templates/base.html:236 +#: tfjm/templates/base.html:243 msgid "All teams" msgstr "Toutes les équipes" @@ -1329,7 +1369,7 @@ msgid "Add pool" msgstr "Ajouter une poule" #: participation/templates/participation/tournament_list.html:6 -#: tfjm/templates/base.html:232 +#: tfjm/templates/base.html:239 msgid "All tournaments" msgstr "Tous les tournois" @@ -1349,49 +1389,49 @@ msgstr "Télécharger la fiche de notation vierge" msgid "Templates:" msgstr "Modèles :" -#: participation/views.py:44 tfjm/templates/base.html:73 -#: tfjm/templates/base.html:247 +#: participation/views.py:46 tfjm/templates/base.html:73 +#: tfjm/templates/base.html:254 msgid "Create team" msgstr "Créer une équipe" -#: participation/views.py:53 participation/views.py:98 +#: participation/views.py:55 participation/views.py:100 msgid "You don't participate, so you can't create a team." msgstr "Vous ne participez pas, vous ne pouvez pas créer d'équipe." -#: participation/views.py:55 participation/views.py:100 +#: participation/views.py:57 participation/views.py:102 msgid "You are already in a team." msgstr "Vous êtes déjà dans une équipe." -#: participation/views.py:89 tfjm/templates/base.html:78 -#: tfjm/templates/base.html:242 +#: participation/views.py:91 tfjm/templates/base.html:78 +#: tfjm/templates/base.html:249 msgid "Join team" msgstr "Rejoindre une équipe" -#: participation/views.py:151 participation/views.py:448 -#: participation/views.py:482 +#: participation/views.py:153 participation/views.py:450 +#: participation/views.py:484 msgid "You are not in a team." msgstr "Vous n'êtes pas dans une équipe." -#: participation/views.py:152 participation/views.py:483 +#: participation/views.py:154 participation/views.py:485 msgid "You don't participate, so you don't have any team." msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe." -#: participation/views.py:178 +#: participation/views.py:180 #, python-brace-format msgid "Detail of team {trigram}" msgstr "Détails de l'équipe {trigram}" -#: participation/views.py:215 +#: participation/views.py:217 msgid "You don't participate, so you can't request the validation of the team." msgstr "" "Vous ne participez pas, vous ne pouvez pas demander la validation de " "l'équipe." -#: participation/views.py:218 +#: participation/views.py:220 msgid "The validation of the team is already done or pending." msgstr "La validation de l'équipe est déjà faite ou en cours." -#: participation/views.py:221 +#: participation/views.py:223 msgid "" "The team can't be validated: missing email address confirmations, " "authorizations, people, motivation letter or the tournament is not set." @@ -1400,79 +1440,93 @@ msgstr "" "d'adresse e-mail, soit une autorisation, soit des personnes, soit la lettre " "de motivation, soit le tournoi n'a pas été choisi." -#: participation/views.py:243 +#: participation/views.py:245 msgid "You are not an organizer of the tournament." msgstr "Vous n'êtes pas un⋅e organisateur⋅rice du tournoi." -#: participation/views.py:246 +#: participation/views.py:248 msgid "This team has no pending validation." msgstr "L'équipe n'a pas de validation en attente." -#: participation/views.py:276 +#: participation/views.py:278 msgid "You must specify if you validate the registration or not." msgstr "Vous devez spécifier si vous validez l'inscription ou non." -#: participation/views.py:311 +#: participation/views.py:313 #, python-brace-format msgid "Update team {trigram}" msgstr "Mise à jour de l'équipe {trigram}" -#: participation/views.py:372 participation/views.py:428 +#: participation/views.py:374 participation/views.py:430 #, python-brace-format msgid "Motivation letter of {team}.{ext}" msgstr "Lettre de motivation de {team}.{ext}" -#: participation/views.py:403 +#: participation/views.py:405 #, python-brace-format msgid "Photo authorization of {participant}.{ext}" msgstr "Autorisation de droit à l'image de {participant}.{ext}" -#: participation/views.py:409 +#: participation/views.py:411 #, python-brace-format msgid "Parental authorization of {participant}.{ext}" msgstr "Autorisation parentale de {participant}.{ext}" -#: participation/views.py:416 +#: participation/views.py:418 #, python-brace-format msgid "Health sheet of {participant}.{ext}" msgstr "Fiche sanitaire de {participant}.{ext}" -#: participation/views.py:422 +#: participation/views.py:424 #, python-brace-format msgid "Vaccine sheet of {participant}.{ext}" msgstr "Carnet de vaccination de {participant}.{ext}" -#: participation/views.py:432 +#: participation/views.py:434 #, python-brace-format msgid "Photo authorizations of team {trigram}.zip" msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip" -#: participation/views.py:450 +#: participation/views.py:452 msgid "The team is already validated or the validation is pending." msgstr "La validation de l'équipe est déjà faite ou en cours." -#: participation/views.py:497 +#: participation/views.py:499 msgid "The team is not validated yet." msgstr "L'équipe n'est pas encore validée." -#: participation/views.py:511 +#: participation/views.py:513 #, python-brace-format msgid "Participation of team {trigram}" msgstr "Participation de l'équipe {trigram}" -#: participation/views.py:637 +#: participation/views.py:639 msgid "You can't upload a solution after the deadline." msgstr "Vous ne pouvez pas envoyer de solution après la date limite." -#: participation/views.py:740 +#: participation/views.py:727 +#, python-brace-format +msgid "Jurys of {pool}" +msgstr "Juré⋅es de la {pool}" + +#: participation/views.py:749 +msgid "New TFJM² jury account" +msgstr "Nouveau compte de juré⋅e pour le TFJM²" + +#: participation/views.py:761 +#, python-brace-format +msgid "The jury {name} has been successfully added!" +msgstr "Læ juré⋅e {name} a été ajouté⋅e avec succès !" + +#: participation/views.py:796 msgid "The following user is not registered as a jury:" msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :" -#: participation/views.py:748 +#: participation/views.py:804 msgid "Notes were successfully uploaded." msgstr "Les notes ont bien été envoyées." -#: participation/views.py:860 +#: participation/views.py:916 msgid "You can't upload a synthesis after the deadline." msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite." @@ -1502,10 +1556,6 @@ msgstr "participant⋅e" msgid "coach" msgstr "encadrant⋅e" -#: registration/forms.py:35 registration/forms.py:60 -msgid "This email address is already used." -msgstr "Cette adresse e-mail est déjà utilisée." - #: registration/forms.py:218 msgid "Pending" msgstr "En attente" @@ -1850,8 +1900,8 @@ msgid "Your password has been set. You may go ahead and log in now." msgstr "Votre mot de passe a été changé. Vous pouvez désormais vous connecter." #: registration/templates/registration/password_reset_complete.html:10 -#: tfjm/templates/base.html:133 tfjm/templates/base.html:252 -#: tfjm/templates/base.html:253 tfjm/templates/registration/login.html:7 +#: tfjm/templates/base.html:133 tfjm/templates/base.html:259 +#: tfjm/templates/base.html:260 tfjm/templates/registration/login.html:7 #: tfjm/templates/registration/login.html:8 #: tfjm/templates/registration/login.html:25 msgid "Log in" @@ -2305,15 +2355,15 @@ msgstr "" "avez reçu par mail. Vous pouvez renvoyer un mail en cliquant sur ce lien." -#: tfjm/templates/base.html:190 +#: tfjm/templates/base.html:197 msgid "Contact us" msgstr "Nous contacter" -#: tfjm/templates/base.html:217 +#: tfjm/templates/base.html:224 msgid "About" msgstr "À propos" -#: tfjm/templates/base.html:239 +#: tfjm/templates/base.html:246 msgid "Search results" msgstr "Résultats de la recherche" diff --git a/participation/forms.py b/participation/forms.py index a4c0a55..639469e 100644 --- a/participation/forms.py +++ b/participation/forms.py @@ -6,6 +6,9 @@ from io import StringIO import re from typing import Iterable +from crispy_forms.bootstrap import InlineField +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Submit, Fieldset, Layout, Div from django import forms from django.contrib.auth.models import User from django.core.exceptions import ValidationError @@ -197,6 +200,48 @@ class PoolTeamsForm(forms.ModelForm): }), } +class AddJuryForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.helper = FormHelper() + self.helper.form_class = 'form-inline' + self.helper.layout = Fieldset( + _("Add new jury"), + Div( + Div( + InlineField('first_name', autofocus="autofocus"), + css_class='col-xl-3', + ), + Div( + InlineField('last_name'), + css_class='col-xl-3', + ), + Div( + InlineField('email'), + css_class='col-xl-5', + ), + Div( + Submit('submit', _("Add")), + css_class='col-xl-1', + ), + css_class='row', + ) + ) + + def clean_email(self): + """ + Ensure that the email address is unique. + """ + email = self.data["email"] + if User.objects.filter(email=email).exists(): + self.add_error("email", _("This email address is already used.")) + return email + + class Meta: + model = User + fields = ('first_name', 'last_name', 'email',) + + class UploadNotesForm(forms.Form): file = forms.FileField( diff --git a/participation/templates/participation/pool_add_jurys.html b/participation/templates/participation/pool_add_jurys.html new file mode 100644 index 0000000..9b1259c --- /dev/null +++ b/participation/templates/participation/pool_add_jurys.html @@ -0,0 +1,47 @@ +{% extends "base.html" %} + +{% load crispy_forms_tags %} +{% load i18n %} + +{% block content %} +
+

+ {% trans "You can here register juries for the pool." %} + {% trans "Be careful: this form register new users. To add existing users into the jury, please use this form:" %} + +

+

+ {% trans "For now, the registered juries for the tournament are:" %} +

    + {% for jury in pool.juries.all %} +
  • {{ jury.user.first_name }} {{ jury.user.last_name }} ({{ jury.user.email }})
  • + {% empty %} +
  • {% trans "There is no jury yet." %}
  • + {% endfor %} +
+

+
+ {% crispy form %} + +
+ + + + {% trans "Update pool" as modal_title %} + {% trans "Update" as modal_button %} + {% url "participation:pool_update" pk=pool.pk as modal_action %} + {% include "base_modal.html" with modal_id="updatePool" %} +{% endblock %} + +{% block extrajavascript %} + +{% endblock %} + diff --git a/participation/templates/participation/pool_detail.html b/participation/templates/participation/pool_detail.html index 1a59ed5..4d29b67 100644 --- a/participation/templates/participation/pool_detail.html +++ b/participation/templates/participation/pool_detail.html @@ -26,7 +26,12 @@
{% trans "Juries:" %}
-
{{ pool.juries.all|join:", " }}
+
+ {{ pool.juries.all|join:", " }} + + {% trans "Add jurys" %} + +
{% trans "Defended solutions:" %}
diff --git a/participation/urls.py b/participation/urls.py index d37abb3..2024b0f 100644 --- a/participation/urls.py +++ b/participation/urls.py @@ -5,8 +5,8 @@ from django.urls import path from django.views.generic import TemplateView from .views import CreateTeamView, JoinTeamView, MyParticipationDetailView, MyTeamDetailView, NoteUpdateView, \ - ParticipationDetailView, PassageCreateView, PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, \ - PoolUpdateTeamsView, PoolUpdateView, PoolUploadNotesView, SolutionUploadView, SynthesisUploadView,\ + ParticipationDetailView, PassageCreateView, PassageDetailView, PassageUpdateView, PoolAddJurysView, PoolCreateView,\ + PoolDetailView, PoolUpdateTeamsView, PoolUpdateView, PoolUploadNotesView, SolutionUploadView, SynthesisUploadView,\ TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \ TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \ TournamentListView, TournamentUpdateView @@ -37,6 +37,7 @@ urlpatterns = [ path("pools//", PoolDetailView.as_view(), name="pool_detail"), path("pools//update/", PoolUpdateView.as_view(), name="pool_update"), path("pools//update-teams/", PoolUpdateTeamsView.as_view(), name="pool_update_teams"), + path("pools//add-jurys/", PoolAddJurysView.as_view(), name="pool_add_jurys"), path("pools//upload-notes/", PoolUploadNotesView.as_view(), name="pool_upload_notes"), path("pools/passages/add//", PassageCreateView.as_view(), name="passage_create"), path("pools/passages//", PassageDetailView.as_view(), name="passage_detail"), diff --git a/participation/views.py b/participation/views.py index f4e900d..77ca609 100644 --- a/participation/views.py +++ b/participation/views.py @@ -1,5 +1,6 @@ # Copyright (C) 2020 by Animath # SPDX-License-Identifier: GPL-3.0-or-later + import csv from io import BytesIO import os @@ -17,18 +18,19 @@ from django.shortcuts import redirect from django.template.loader import render_to_string from django.urls import reverse_lazy from django.utils import timezone +from django.utils.crypto import get_random_string from django.utils.translation import gettext_lazy as _ from django.views.generic import CreateView, DetailView, FormView, RedirectView, TemplateView, UpdateView, View from django.views.generic.edit import FormMixin, ProcessFormView from django_tables2 import SingleTableView from magic import Magic -from registration.models import StudentRegistration +from registration.models import StudentRegistration, VolunteerRegistration from tfjm.lists import get_sympa_client from tfjm.matrix import Matrix from tfjm.views import AdminMixin, VolunteerMixin -from .forms import JoinTeamForm, MotivationLetterForm, NoteForm, ParticipationForm, PassageForm, PoolForm, \ - PoolTeamsForm, RequestValidationForm, SolutionForm, SynthesisForm, TeamForm, TournamentForm, \ +from .forms import AddJuryForm, JoinTeamForm, MotivationLetterForm, NoteForm, ParticipationForm, PassageForm, \ + PoolForm, PoolTeamsForm, RequestValidationForm, SolutionForm, SynthesisForm, TeamForm, TournamentForm, \ UploadNotesForm, ValidateParticipationForm from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament from .tables import NoteTable, ParticipationTable, PassageTable, PoolTable, TeamTable, TournamentTable @@ -715,6 +717,60 @@ class PoolUpdateTeamsView(VolunteerMixin, UpdateView): return self.handle_no_permission() +class PoolAddJurysView(VolunteerMixin, FormView, DetailView): + model = Pool + form_class = AddJuryForm + template_name = 'participation/pool_add_jurys.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['title'] = _("Jurys of {pool}").format(pool=self.object) + return context + + @transaction.atomic + def form_valid(self, form): + self.object = self.get_object() + + form.save() + user = form.instance + reg = VolunteerRegistration.objects.create( + user=user, + professional_activity="Juré⋅e du tournoi " + self.object.tournament.name, + ) + self.object.juries.add(reg) + self.object.save() + + reg.send_email_validation_link() + + password = get_random_string(16) + user.set_password(password) + user.save() + + subject = "[TFJM²] " + str(_("New TFJM² jury account")) + site = Site.objects.first() + message = render_to_string('registration/mails/add_organizer.txt', dict(user=user, + inviter=self.request.user, + password=password, + domain=site.domain)) + html = render_to_string('registration/mails/add_organizer.html', dict(user=user, + inviter=self.request.user, + password=password, + domain=site.domain)) + user.email_user(subject, message, html_message=html) + + messages.success(self.request, _("The jury {name} has been successfully added!")\ + .format(name=f"{user.first_name} {user.last_name}")) + + return super().form_valid(form) + + def form_invalid(self, form): + self.object = self.get_object() + return super().form_invalid(form) + + def get_success_url(self): + return reverse_lazy('participation:pool_add_jurys', args=(self.kwargs['pk'],)) + + class PoolUploadNotesView(VolunteerMixin, FormView, DetailView): model = Pool form_class = UploadNotesForm diff --git a/registration/templates/registration/mails/add_organizer.html b/registration/templates/registration/mails/add_organizer.html index e33e667..121560b 100644 --- a/registration/templates/registration/mails/add_organizer.html +++ b/registration/templates/registration/mails/add_organizer.html @@ -14,7 +14,7 @@

Vous avez été invités par {{ inviter.registration }} à rejoindre la plateforme du TFJM², accessible à l'adresse - https://{{ domain }}/. Vous disposez d'un compte d'organisateur. + https://{{ domain }}/. Vous disposez d'un compte de bénévole.

diff --git a/registration/templates/registration/mails/add_organizer.txt b/registration/templates/registration/mails/add_organizer.txt index 19f91ec..817545e 100644 --- a/registration/templates/registration/mails/add_organizer.txt +++ b/registration/templates/registration/mails/add_organizer.txt @@ -3,7 +3,7 @@ Bonjour {{ user.registration }}, Vous avez été invités par {{ inviter.registration }} à rejoindre la plateforme du TFJM², accessible à l'adresse -https://{{ domain }}/. Vous disposez d'un compte d'organisateur. +https://{{ domain }}/. Vous disposez d'un compte de bénévole. Un mot de passe aléatoire a été défini : {{ password }}. Par sécurité, merci de le changer dès votre connexion. diff --git a/tfjm/settings.py b/tfjm/settings.py index 4ddd44d..f17ea6f 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -194,6 +194,7 @@ MEDIA_ROOT = os.path.join(BASE_DIR, "media") DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' +CRISPY_ALLOWED_TEMPLATE_PACKS = 'bootstrap5' CRISPY_TEMPLATE_PACK = 'bootstrap5' DJANGO_TABLES2_TEMPLATE = 'django_tables2/bootstrap5.html' diff --git a/tfjm/templates/base.html b/tfjm/templates/base.html index aeffd9b..b260bf6 100644 --- a/tfjm/templates/base.html +++ b/tfjm/templates/base.html @@ -160,7 +160,7 @@

{% block fullcontent %}
- {% block contenttitle %}{% endblock %} + {% block contenttitle %}

{{ title }}

{% endblock %} {% if user.is_authenticated and not user.registration.email_confirmed %} {% endif %} -
+
+ {% for message in messages %} + + {% endfor %} +
{% block content %}

Default content...