diff --git a/apps/participation/forms.py b/apps/participation/forms.py
index 66d7965..45839d9 100644
--- a/apps/participation/forms.py
+++ b/apps/participation/forms.py
@@ -44,6 +44,30 @@ class ParticipationForm(forms.ModelForm):
fields = ('problem',)
+class RequestValidationForm(forms.Form):
+ _form_type = forms.CharField(
+ initial="RequestValidationForm",
+ widget=forms.HiddenInput(),
+ )
+
+ engagement = forms.BooleanField(
+ label=_("I engage myself to participate to the whole \"Correspondances\"."),
+ required=True,
+ )
+
+
+class ValidateParticipationForm(forms.Form):
+ _form_type = forms.CharField(
+ initial="ValidateParticipationForm",
+ widget=forms.HiddenInput(),
+ )
+
+ message = forms.CharField(
+ label=_("Message to address to the team:"),
+ widget=forms.Textarea(),
+ )
+
+
class UploadVideoForm(forms.ModelForm):
class Meta:
model = Video
diff --git a/apps/participation/templates/participation/team_detail.html b/apps/participation/templates/participation/team_detail.html
index 89471ab..6451db7 100644
--- a/apps/participation/templates/participation/team_detail.html
+++ b/apps/participation/templates/participation/team_detail.html
@@ -78,6 +78,7 @@
@@ -98,8 +99,17 @@
{% trans "Your validation is pending." %}
{% else %}
- Team asked for validation.
- {# TODO Add validation form: validate or invalidate, with a message #}
+
+ {% trans "The team requested to be validated. You may now control the authorizations and confirm that they can participate." %}
+
+
{% endif %}
{% endif %}
diff --git a/apps/participation/views.py b/apps/participation/views.py
index b708eff..381367a 100644
--- a/apps/participation/views.py
+++ b/apps/participation/views.py
@@ -6,15 +6,16 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.http import HttpResponse
-from django.shortcuts import redirect
from django.template.loader import render_to_string
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DetailView, FormView, RedirectView, UpdateView
+from django.views.generic.edit import FormMixin, ProcessFormView
from magic import Magic
from registration.models import AdminRegistration
-from .forms import JoinTeamForm, ParticipationForm, TeamForm, UploadVideoForm
+from .forms import JoinTeamForm, ParticipationForm, RequestValidationForm, TeamForm, UploadVideoForm,\
+ ValidateParticipationForm
from .models import Participation, Team, Video
@@ -90,32 +91,22 @@ class MyTeamDetailView(LoginRequiredMixin, RedirectView):
raise PermissionDenied(_("You don't participate, so you don't have any team."))
-class TeamDetailView(LoginRequiredMixin, DetailView):
+class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView):
model = Team
def get(self, request, *args, **kwargs):
user = request.user
+ self.object = self.get_object()
if user.registration.is_admin or user.registration.participates and user.registration.team.pk == kwargs["pk"]:
return super().get(request, *args, **kwargs)
raise PermissionDenied
- def post(self, request, *args, **kwargs):
- if request.user.registration.participates:
- if "request-validation" in request.POST:
- request.user.registration.team.participation.valid = False
- request.user.registration.team.participation.save()
-
- for admin in AdminRegistration.objects.all():
- mail_context = dict(user=admin.user, team=request.user.registration.team)
- mail_plain = render_to_string("participation/mails/request_validation.txt", mail_context)
- mail_html = render_to_string("participation/mails/request_validation.html", mail_context)
- admin.user.email_user("[Corres2math] Validation d'équipe", mail_plain, html_message=mail_html)
- return redirect(request.path)
-
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
- team = self.object
+ team = self.get_object()
+ context["request_validation_form"] = RequestValidationForm(self.request.POST or None)
+ context["validation_form"] = ValidateParticipationForm(self.request.POST or None)
context["can_validate"] = team.students.count() >= 3 and \
all(r.email_confirmed for r in team.students.all()) and \
all(r.photo_authorization for r in team.students.all()) and \
@@ -123,6 +114,56 @@ class TeamDetailView(LoginRequiredMixin, DetailView):
return context
+ def get_form_class(self):
+ if not self.request.POST:
+ return RequestValidationForm
+ elif self.request.POST["_form_type"] == "RequestValidationForm":
+ return RequestValidationForm
+ elif self.request.POST["_form_type"] == "ValidateParticipationForm":
+ return ValidateParticipationForm
+ return None
+
+ def form_valid(self, form):
+ self.object = self.get_object()
+ if isinstance(form, RequestValidationForm):
+ if not self.request.user.registration.participates:
+ form.add_error(None, _("You don't participate, so you can't request the validation of the team."))
+ return self.form_invalid(form)
+ if self.object.participation.valid is not None:
+ form.add_error(None, _("The validation of the team is already done or pending."))
+ return self.form_invalid(form)
+
+ self.object.participation.valid = False
+ self.object.participation.save()
+
+ for admin in AdminRegistration.objects.all():
+ mail_context = dict(user=admin.user, team=self.object)
+ mail_plain = render_to_string("participation/mails/request_validation.txt", mail_context)
+ mail_html = render_to_string("participation/mails/request_validation.html", mail_context)
+ admin.user.email_user("[Corres2math] Validation d'équipe", mail_plain, html_message=mail_html)
+ elif isinstance(form, ValidateParticipationForm):
+ if not self.request.user.registration.is_admin:
+ form.add_error(None, _("You are not an administrator."))
+ return self.form_invalid(form)
+ elif self.object.participation.valid is not False:
+ form.add_error(None, _("This team has no pending validation."))
+ return self.form_invalid(form)
+
+ if "validate" in self.request.POST:
+ self.object.participation.valid = True
+ self.object.participation.save()
+ elif "invalidate" in self.request.POST:
+ self.object.participation.valid = None
+ self.object.participation.save()
+ else:
+ form.add_error(None, _("You must specify if you validate the registration or not."))
+ return self.form_invalid(form)
+
+ return super().form_invalid(form)
+
+ def get_success_url(self):
+ return self.request.path
+
class TeamUpdateView(LoginRequiredMixin, UpdateView):
model = Team
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index ea110aa..9305d78 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Corres2math\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-10-11 16:48+0200\n"
+"POT-Creation-Date: 2020-10-11 18:43+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Yohann D'ANELLO \n"
"Language-Team: LANGUAGE \n"
@@ -107,6 +107,14 @@ msgstr "Le trigramme doit être composé de trois lettres majuscules."
msgid "No team was found with this access code."
msgstr "Aucune équipe n'a été trouvée avec ce code d'accès."
+#: apps/participation/forms.py:54
+msgid "I engage myself to participate to the whole \"Correspondances\"."
+msgstr "Je m'engage à participer à l'intégralité des Correspondances."
+
+#: apps/participation/forms.py:66
+msgid "Message to address to the team:"
+msgstr "Message à adresser à l'équipe :"
+
#: apps/participation/models.py:16
msgid "name"
msgstr "nom"
@@ -135,80 +143,80 @@ msgstr ""
"Donner l'autorisation de publier la vidéo sur le site principal pour "
"promouvoir les Correspondances."
-#: apps/participation/models.py:59
+#: apps/participation/models.py:60
#, python-brace-format
msgid "Team {name} ({trigram})"
msgstr "Équipe {name} ({trigram})"
-#: apps/participation/models.py:62 apps/participation/models.py:73
+#: apps/participation/models.py:63 apps/participation/models.py:74
#: apps/registration/models.py:85 apps/registration/models.py:130
msgid "team"
msgstr "équipe"
-#: apps/participation/models.py:63
+#: apps/participation/models.py:64
msgid "teams"
msgstr "équipes"
-#: apps/participation/models.py:77
+#: apps/participation/models.py:78
#, python-brace-format
msgid "Problem #{problem:d}"
msgstr "Problème n°{problem:d}"
-#: apps/participation/models.py:80
+#: apps/participation/models.py:81
msgid "problem number"
msgstr "numéro de problème"
-#: apps/participation/models.py:86 apps/participation/models.py:134
+#: apps/participation/models.py:87 apps/participation/models.py:135
msgid "valid"
msgstr "valide"
-#: apps/participation/models.py:87 apps/participation/models.py:135
+#: apps/participation/models.py:88 apps/participation/models.py:136
msgid "The video got the validation of the administrators."
msgstr "La vidéo a été validée par les administrateurs."
-#: apps/participation/models.py:96
+#: apps/participation/models.py:97
msgid "solution video"
msgstr "vidéo de solution"
-#: apps/participation/models.py:105
+#: apps/participation/models.py:106
msgid "received participation"
msgstr "participation reçue"
-#: apps/participation/models.py:114
+#: apps/participation/models.py:115
msgid "synthesis video"
msgstr "vidéo de synthèse"
-#: apps/participation/models.py:118
+#: apps/participation/models.py:119
#, python-brace-format
msgid "Participation of the team {name} ({trigram})"
msgstr "Participation de l'équipe {name} ({trigram})"
-#: apps/participation/models.py:121
+#: apps/participation/models.py:122
msgid "participation"
msgstr "participation"
-#: apps/participation/models.py:122
+#: apps/participation/models.py:123
msgid "participations"
msgstr "participations"
-#: apps/participation/models.py:127
+#: apps/participation/models.py:128
msgid "link"
msgstr "lien"
-#: apps/participation/models.py:128
+#: apps/participation/models.py:129
msgid "The full video link."
msgstr "Le lien complet de la vidéo."
-#: apps/participation/models.py:157
+#: apps/participation/models.py:158
#, python-brace-format
msgid "Video of team {name} ({trigram})"
msgstr "Vidéo de l'équipe {name} ({trigram})"
-#: apps/participation/models.py:161
+#: apps/participation/models.py:162
msgid "video"
msgstr "vidéo"
-#: apps/participation/models.py:162
+#: apps/participation/models.py:163
msgid "videos"
msgstr "vidéos"
@@ -302,7 +310,7 @@ msgid "Not uploaded yet"
msgstr "Pas encore envoyée"
#: apps/participation/templates/participation/team_detail.html:61
-#: apps/participation/templates/participation/team_detail.html:104
+#: apps/participation/templates/participation/team_detail.html:117
#: apps/participation/templates/participation/update_team.html:12
#: apps/registration/templates/registration/update_user.html:12
#: apps/registration/templates/registration/user_detail.html:64
@@ -322,11 +330,11 @@ msgstr ""
"Votre équipe contient au moins 3 personnes et toutes les autorisations de "
"droit à l'image ont été données : l'équipe peut être validée."
-#: apps/participation/templates/participation/team_detail.html:79
+#: apps/participation/templates/participation/team_detail.html:82
msgid "Submit my team to validation"
msgstr "Soumettre mon équipe à validation"
-#: apps/participation/templates/participation/team_detail.html:84
+#: apps/participation/templates/participation/team_detail.html:88
msgid ""
"Your team must be composed of 3 members and each member must upload its "
"photo authorization and confirm its email address."
@@ -334,55 +342,93 @@ msgstr ""
"Votre équipe doit être composée de 3 membres et chaque membre doit envoyer "
"son autorisation de droit à l'image et confirmé son adresse e-mail."
-#: apps/participation/templates/participation/team_detail.html:89
+#: apps/participation/templates/participation/team_detail.html:93
msgid "This team didn't ask for validation yet."
msgstr "L'équipe n'a pas encore demandé à être validée."
-#: apps/participation/templates/participation/team_detail.html:95
+#: apps/participation/templates/participation/team_detail.html:99
msgid "Your validation is pending."
msgstr "Votre validation est en attente."
#: apps/participation/templates/participation/team_detail.html:103
+msgid ""
+"The team requested to be validated. You may now control the authorizations "
+"and confirm that they can participate."
+msgstr ""
+"L'équipe a demandé à être validée. Vous pouvez désormais contrôler les "
+"différentes autorisations et confirmer qu'elle peut participer."
+
+#: apps/participation/templates/participation/team_detail.html:109
+msgid "Validate"
+msgstr "Valider"
+
+#: apps/participation/templates/participation/team_detail.html:110
+msgid "Invalidate"
+msgstr "Invalider"
+
+#: apps/participation/templates/participation/team_detail.html:116
msgid "Update team"
msgstr "Modifier l'équipe"
-#: apps/participation/views.py:21 templates/base.html:70
+#: apps/participation/views.py:25 templates/base.html:70
#: templates/base.html:206
msgid "Create team"
msgstr "Créer une équipe"
-#: apps/participation/views.py:28 apps/participation/views.py:58
+#: apps/participation/views.py:32 apps/participation/views.py:62
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."
-#: apps/participation/views.py:30 apps/participation/views.py:60
+#: apps/participation/views.py:34 apps/participation/views.py:64
msgid "You are already in a team."
msgstr "Vous êtes déjà dans une équipe."
-#: apps/participation/views.py:51 templates/base.html:75
+#: apps/participation/views.py:55 templates/base.html:75
#: templates/base.html:202
msgid "Join team"
msgstr "Rejoindre une équipe"
-#: apps/participation/views.py:86 apps/participation/views.py:175
+#: apps/participation/views.py:90 apps/participation/views.py:232
msgid "You are not in a team."
msgstr "Vous n'êtes pas dans une équipe."
-#: apps/participation/views.py:87 apps/participation/views.py:176
+#: apps/participation/views.py:91 apps/participation/views.py:233
msgid "You don't participate, so you don't have any team."
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
-#: apps/participation/views.py:159 apps/registration/views.py:213
+#: apps/participation/views.py:130
+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."
+
+#: apps/participation/views.py:133
+msgid "The validation of the team is already done or pending."
+msgstr "La validation de l'équipe est déjà faite ou en cours."
+
+#: apps/participation/views.py:146
+msgid "You are not an administrator."
+msgstr "Vous n'êtes pas administrateur."
+
+#: apps/participation/views.py:149
+msgid "This team has no pending validation."
+msgstr "L'équipe n'a pas de validation en attente."
+
+#: apps/participation/views.py:159
+msgid "You must specify if you validate the registration or not."
+msgstr "Vous devez spécifier si vous validez l'inscription ou non."
+
+#: apps/participation/views.py:216 apps/registration/views.py:213
#, python-brace-format
msgid "Photo authorization of {student}.{ext}"
msgstr "Autorisation de droit à l'image de {student}.{ext}"
-#: apps/participation/views.py:163
+#: apps/participation/views.py:220
#, python-brace-format
msgid "Photo authorizations of team {trigram}.zip"
msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip"
-#: apps/participation/views.py:185
+#: apps/participation/views.py:242
msgid "The team is not validated yet."
msgstr "L'équipe n'est pas encore validée."