2020-09-23 21:20:44 +00:00
|
|
|
import re
|
|
|
|
|
2020-10-20 11:14:02 +00:00
|
|
|
from bootstrap_datepicker_plus import DateTimePickerInput
|
2020-09-22 18:41:42 +00:00
|
|
|
from django import forms
|
2020-11-03 16:58:05 +00:00
|
|
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
2020-10-31 11:51:49 +00:00
|
|
|
from django.db.models import Q
|
2020-09-23 21:20:44 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2020-09-22 18:41:42 +00:00
|
|
|
|
2020-10-31 17:11:37 +00:00
|
|
|
from .models import Participation, Phase, Question, Team, Video
|
2020-09-22 18:41:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TeamForm(forms.ModelForm):
|
2020-10-30 18:46:46 +00:00
|
|
|
"""
|
|
|
|
Form to create a team, with the name and the trigram,
|
|
|
|
and if the team accepts that Animath diffuse the videos.
|
|
|
|
"""
|
2020-09-23 21:20:44 +00:00
|
|
|
def clean_trigram(self):
|
|
|
|
trigram = self.cleaned_data["trigram"].upper()
|
|
|
|
if not re.match("[A-Z]{3}", trigram):
|
|
|
|
raise ValidationError(_("The trigram must be composed of three uppercase letters."))
|
|
|
|
return trigram
|
|
|
|
|
2020-09-22 18:41:42 +00:00
|
|
|
class Meta:
|
|
|
|
model = Team
|
|
|
|
fields = ('name', 'trigram', 'grant_animath_access_videos',)
|
|
|
|
|
|
|
|
|
|
|
|
class JoinTeamForm(forms.ModelForm):
|
2020-10-30 18:46:46 +00:00
|
|
|
"""
|
|
|
|
Form to join a team by the access code.
|
|
|
|
"""
|
2020-09-22 18:41:42 +00:00
|
|
|
def clean_access_code(self):
|
|
|
|
access_code = self.cleaned_data["access_code"]
|
|
|
|
if not Team.objects.filter(access_code=access_code).exists():
|
2020-09-23 21:20:44 +00:00
|
|
|
raise ValidationError(_("No team was found with this access code."))
|
2020-09-22 18:41:42 +00:00
|
|
|
return access_code
|
|
|
|
|
|
|
|
def clean(self):
|
|
|
|
cleaned_data = super().clean()
|
|
|
|
if "access_code" in cleaned_data:
|
2020-09-23 21:20:44 +00:00
|
|
|
team = Team.objects.get(access_code=cleaned_data["access_code"])
|
|
|
|
self.instance = team
|
2020-09-22 18:41:42 +00:00
|
|
|
return cleaned_data
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Team
|
|
|
|
fields = ('access_code',)
|
2020-09-24 09:15:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
class ParticipationForm(forms.ModelForm):
|
2020-10-30 18:46:46 +00:00
|
|
|
"""
|
|
|
|
Form to update the problem of a team participation.
|
|
|
|
"""
|
2020-09-24 09:15:54 +00:00
|
|
|
class Meta:
|
|
|
|
model = Participation
|
|
|
|
fields = ('problem',)
|
2020-09-27 12:32:05 +00:00
|
|
|
|
|
|
|
|
2020-10-11 16:44:42 +00:00
|
|
|
class RequestValidationForm(forms.Form):
|
2020-10-30 18:46:46 +00:00
|
|
|
"""
|
|
|
|
Form to ask about validation.
|
|
|
|
"""
|
2020-10-11 16:44:42 +00:00
|
|
|
_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):
|
2020-10-30 18:46:46 +00:00
|
|
|
"""
|
|
|
|
Form to let administrators to accept or refuse a team.
|
|
|
|
"""
|
2020-10-11 16:44:42 +00:00
|
|
|
_form_type = forms.CharField(
|
|
|
|
initial="ValidateParticipationForm",
|
|
|
|
widget=forms.HiddenInput(),
|
|
|
|
)
|
|
|
|
|
|
|
|
message = forms.CharField(
|
|
|
|
label=_("Message to address to the team:"),
|
|
|
|
widget=forms.Textarea(),
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2020-09-27 12:32:05 +00:00
|
|
|
class UploadVideoForm(forms.ModelForm):
|
2020-10-30 18:46:46 +00:00
|
|
|
"""
|
|
|
|
Form to upload a video, for a solution or a synthesis.
|
|
|
|
"""
|
2020-09-27 12:32:05 +00:00
|
|
|
class Meta:
|
|
|
|
model = Video
|
|
|
|
fields = ('link',)
|
2020-10-20 11:14:02 +00:00
|
|
|
|
2020-10-20 12:51:09 +00:00
|
|
|
def clean(self):
|
2020-11-03 13:31:11 +00:00
|
|
|
if Phase.current_phase().phase_number != 1 and Phase.current_phase().phase_number != 4 and self.instance.link:
|
2020-10-20 12:51:09 +00:00
|
|
|
self.add_error("link", _("You can't upload your video after the deadline."))
|
|
|
|
return super().clean()
|
|
|
|
|
2020-10-20 11:14:02 +00:00
|
|
|
|
2020-10-31 11:51:49 +00:00
|
|
|
class ReceiveParticipationForm(forms.ModelForm):
|
|
|
|
"""
|
|
|
|
Update the received participation of a participation.
|
|
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.fields["received_participation"].queryset = Participation.objects.filter(
|
|
|
|
~Q(pk=self.instance.pk) & Q(problem=self.instance.problem, valid=True)
|
|
|
|
)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Participation
|
|
|
|
fields = ('received_participation',)
|
2020-10-31 12:35:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
class SendParticipationForm(forms.ModelForm):
|
|
|
|
"""
|
|
|
|
Update the sent participation of a participation.
|
|
|
|
"""
|
|
|
|
sent_participation = forms.ModelChoiceField(
|
|
|
|
queryset=Participation.objects,
|
|
|
|
label=lambda: _("Send to team"),
|
|
|
|
)
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super().__init__(*args, **kwargs)
|
2020-11-03 16:21:50 +00:00
|
|
|
try:
|
|
|
|
self.fields["sent_participation"].initial = self.instance.sent_participation
|
2020-11-03 16:58:05 +00:00
|
|
|
except ObjectDoesNotExist: # No sent participation
|
2020-11-03 16:21:50 +00:00
|
|
|
pass
|
2020-10-31 12:35:00 +00:00
|
|
|
self.fields["sent_participation"].queryset = Participation.objects.filter(
|
|
|
|
~Q(pk=self.instance.pk) & Q(problem=self.instance.problem, valid=True)
|
|
|
|
)
|
|
|
|
|
|
|
|
def clean(self, commit=True):
|
|
|
|
cleaned_data = super().clean()
|
2020-11-03 16:21:50 +00:00
|
|
|
if "sent_participation" in cleaned_data:
|
|
|
|
participation = cleaned_data["sent_participation"]
|
|
|
|
participation.received_participation = self.instance
|
|
|
|
self.instance = participation
|
2020-10-31 12:35:00 +00:00
|
|
|
return cleaned_data
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Participation
|
|
|
|
fields = ('sent_participation',)
|
2020-10-31 17:11:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
class QuestionForm(forms.ModelForm):
|
|
|
|
"""
|
|
|
|
Create or update a question.
|
|
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.fields["question"].widget.attrs.update({"placeholder": _("How did you get the idea to ...?")})
|
|
|
|
|
2020-11-03 16:58:05 +00:00
|
|
|
def clean(self):
|
|
|
|
if Phase.current_phase().phase_number != 2:
|
|
|
|
self.add_error(None, _("You can only create or update a question during the second phase."))
|
|
|
|
return super().clean()
|
|
|
|
|
2020-10-31 17:11:37 +00:00
|
|
|
class Meta:
|
|
|
|
model = Question
|
|
|
|
fields = ('question',)
|
2020-10-31 11:51:49 +00:00
|
|
|
|
|
|
|
|
2020-10-20 11:14:02 +00:00
|
|
|
class PhaseForm(forms.ModelForm):
|
2020-10-30 18:46:46 +00:00
|
|
|
"""
|
|
|
|
Form to update the calendar of a phase.
|
|
|
|
"""
|
2020-10-20 11:14:02 +00:00
|
|
|
class Meta:
|
|
|
|
model = Phase
|
|
|
|
fields = ('start', 'end',)
|
|
|
|
widgets = {
|
2020-10-20 12:21:16 +00:00
|
|
|
'start': DateTimePickerInput(format='%d/%m/%Y %H:%M'),
|
|
|
|
'end': DateTimePickerInput(format='%d/%m/%Y %H:%M'),
|
2020-10-20 11:14:02 +00:00
|
|
|
}
|
2020-10-20 12:21:16 +00:00
|
|
|
|
|
|
|
def clean(self):
|
|
|
|
# Ensure that dates are in a right order
|
|
|
|
cleaned_data = super().clean()
|
2020-11-03 15:26:43 +00:00
|
|
|
start = cleaned_data["start"]
|
|
|
|
end = cleaned_data["end"]
|
|
|
|
if end <= start:
|
2020-10-20 12:21:16 +00:00
|
|
|
self.add_error("end", _("Start date must be before the end date."))
|
2020-11-03 15:26:43 +00:00
|
|
|
if Phase.objects.filter(phase_number__lt=self.instance.phase_number, end__gt=start).exists():
|
2020-10-20 12:21:16 +00:00
|
|
|
self.add_error("start", _("This phase must start after the previous phases."))
|
2020-11-03 15:26:43 +00:00
|
|
|
if Phase.objects.filter(phase_number__gt=self.instance.phase_number, start__lt=end).exists():
|
2020-10-20 12:21:16 +00:00
|
|
|
self.add_error("end", _("This phase must end after the next phases."))
|
|
|
|
return cleaned_data
|