diff --git a/apps/participation/forms.py b/apps/participation/forms.py
index b2ac9d3..66d7965 100644
--- a/apps/participation/forms.py
+++ b/apps/participation/forms.py
@@ -4,7 +4,7 @@ from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
-from .models import Participation, Team
+from .models import Participation, Team, Video
class TeamForm(forms.ModelForm):
@@ -42,3 +42,9 @@ class ParticipationForm(forms.ModelForm):
class Meta:
model = Participation
fields = ('problem',)
+
+
+class UploadVideoForm(forms.ModelForm):
+ class Meta:
+ model = Video
+ fields = ('link',)
diff --git a/apps/participation/models.py b/apps/participation/models.py
index 029f6f9..6867bb2 100644
--- a/apps/participation/models.py
+++ b/apps/participation/models.py
@@ -1,3 +1,6 @@
+import re
+
+from django.core.exceptions import ObjectDoesNotExist
from django.core.validators import RegexValidator
from django.db import models
from django.db.models import Index
@@ -63,10 +66,10 @@ class Participation(models.Model):
verbose_name=_("problem number"),
)
- solution = models.ForeignKey(
+ solution = models.OneToOneField(
"participation.Video",
on_delete=models.SET_NULL,
- related_name="+",
+ related_name="participation_solution",
null=True,
default=None,
verbose_name=_("solution video"),
@@ -81,10 +84,10 @@ class Participation(models.Model):
verbose_name=_("received participation"),
)
- synthesis = models.ForeignKey(
+ synthesis = models.OneToOneField(
"participation.Video",
on_delete=models.SET_NULL,
- related_name="+",
+ related_name="participation_synthesis",
null=True,
default=None,
verbose_name=_("synthesis video"),
@@ -99,12 +102,6 @@ class Participation(models.Model):
class Video(models.Model):
- participation = models.ForeignKey(
- "participation.Participation",
- on_delete=models.CASCADE,
- verbose_name=_("participation"),
- )
-
link = models.URLField(
verbose_name=_("link"),
help_text=_("The full video link."),
@@ -117,6 +114,24 @@ class Video(models.Model):
help_text=_("The video got the validation of the administrators."),
)
+ @property
+ def participation(self):
+ try:
+ return self.participation_solution
+ except ObjectDoesNotExist:
+ return self.participation_synthesis
+
+ @property
+ def platform(self):
+ if "youtube.com" in self.link or "youtu.be" in self.link:
+ return "youtube"
+ return "unknown"
+
+ @property
+ def youtube_code(self):
+ return re.compile("(https?://|)(www\\.|)(youtube\\.com/watch\\?v=|youtu\\.be/)([a-zA-Z0-9-_]*)?.*?")\
+ .match("https://www.youtube.com/watch?v=73nsrixx7eI").group(4)
+
def __str__(self):
return _("Video of team {name} ({trigram})")\
.format(name=self.participation.team.name, trigram=self.participation.team.trigram)
diff --git a/apps/participation/signals.py b/apps/participation/signals.py
index 16a52af..2f8f222 100644
--- a/apps/participation/signals.py
+++ b/apps/participation/signals.py
@@ -1,5 +1,10 @@
-from participation.models import Participation
+from participation.models import Participation, Video
def create_team_participation(instance, **_):
- Participation.objects.get_or_create(team=instance)
+ participation = Participation.objects.get_or_create(team=instance)[0]
+ if not participation.solution:
+ participation.solution = Video.objects.create()
+ if not participation.synthesis:
+ participation.synthesis = Video.objects.create()
+ participation.save()
diff --git a/apps/participation/templates/participation/participation_detail.html b/apps/participation/templates/participation/participation_detail.html
new file mode 100644
index 0000000..65ac9b9
--- /dev/null
+++ b/apps/participation/templates/participation/participation_detail.html
@@ -0,0 +1,61 @@
+{% extends "base.html" %}
+
+{% load i18n %}
+
+{% block content %}
+{% trans "any" as any %}
+
+
+
+
+
{% trans "Participation of team" %} {{ participation.team.name }} ({{ participation.team.trigram }})
+
+
+
+
{% trans "Chosen problem:" %}
+
{{ participation.get_problem_display }}
+
+
+
+
+
+
+
+
+
+
{% trans "Participation of team" %} {{ participation.team.name }} ({{ participation.team.trigram }})
+
+
+ {% trans "No video sent" as novideo %}
+ {% trans "Video link:" %} {{ participation.solution.link|default:novideo }}
+
+ {% if participation.solution.platform == "youtube" %}
+ {% include "participation/youtube_iframe.html" with youtube_code=participation.solution.youtube_code %}
+ {% else %}
+
+ {% trans "This video platform is not supported yet." %}
+
+ {% endif %}
+
+
+
+
+
+{% trans "Upload video" as modal_title %}
+{% trans "Upload" as modal_button %}
+{% url "participation:upload_video" pk=participation.solution_id as modal_action %}
+{% include "base_modal.html" with modal_id="uploadVideo" %}
+{% endblock %}
+
+{% block extrajavascript %}
+
+{% endblock %}
diff --git a/apps/participation/templates/participation/upload_video.html b/apps/participation/templates/participation/upload_video.html
new file mode 100644
index 0000000..5271644
--- /dev/null
+++ b/apps/participation/templates/participation/upload_video.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% load crispy_forms_filters i18n %}
+
+{% block content %}
+
+{% endblock content %}
+
diff --git a/apps/participation/templates/participation/youtube_iframe.html b/apps/participation/templates/participation/youtube_iframe.html
new file mode 100644
index 0000000..4c577d2
--- /dev/null
+++ b/apps/participation/templates/participation/youtube_iframe.html
@@ -0,0 +1,8 @@
+
+
+
diff --git a/apps/participation/urls.py b/apps/participation/urls.py
index 7334b0f..b5a8c36 100644
--- a/apps/participation/urls.py
+++ b/apps/participation/urls.py
@@ -1,6 +1,7 @@
from django.urls import path
-from .views import CreateTeamView, JoinTeamView, MyTeamDetailView, TeamDetailView, TeamUpdateView
+from .views import CreateTeamView, JoinTeamView, MyParticipationDetailView, MyTeamDetailView, ParticipationDetailView,\
+ TeamDetailView, TeamUpdateView, UploadVideoView
app_name = "participation"
@@ -11,4 +12,7 @@ urlpatterns = [
path("team/", MyTeamDetailView.as_view(), name="my_team_detail"),
path("team//", TeamDetailView.as_view(), name="team_detail"),
path("team//update/", TeamUpdateView.as_view(), name="update_team"),
+ path("detail/", MyParticipationDetailView.as_view(), name="my_participation_detail"),
+ path("detail//", ParticipationDetailView.as_view(), name="participation_detail"),
+ path("detail/upload-video//", UploadVideoView.as_view(), name="upload_video"),
]
diff --git a/apps/participation/views.py b/apps/participation/views.py
index bebfa9c..a79c8f1 100644
--- a/apps/participation/views.py
+++ b/apps/participation/views.py
@@ -5,8 +5,8 @@ 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 .forms import JoinTeamForm, ParticipationForm, TeamForm
-from .models import Team
+from .forms import JoinTeamForm, ParticipationForm, TeamForm, UploadVideoForm
+from .models import Participation, Team, Video
class CreateTeamView(LoginRequiredMixin, CreateView):
@@ -99,3 +99,27 @@ class TeamUpdateView(LoginRequiredMixin, UpdateView):
def get_success_url(self):
return reverse_lazy("participation:team_detail", args=(self.object.pk,))
+
+
+class MyParticipationDetailView(LoginRequiredMixin, RedirectView):
+ def get_redirect_url(self, *args, **kwargs):
+ user = self.request.user
+ registration = user.registration
+ if registration.participates:
+ if registration.team:
+ return reverse_lazy("participation:participation_detail", args=(registration.team.participation.id,))
+ raise PermissionDenied(_("You are not in a team."))
+ raise PermissionDenied(_("You don't participate, so you don't have any team."))
+
+
+class ParticipationDetailView(LoginRequiredMixin, DetailView):
+ model = Participation
+
+
+class UploadVideoView(LoginRequiredMixin, UpdateView):
+ model = Video
+ form_class = UploadVideoForm
+ template_name = "participation/upload_video.html"
+
+ def get_success_url(self):
+ return reverse_lazy("participation:participation_detail", args=(self.object.participation.pk,))
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 959680f..39c561a 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-09-27 12:35+0200\n"
+"POT-Creation-Date: 2020-09-27 14:31+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Yohann D'ANELLO \n"
"Language-Team: LANGUAGE \n"
@@ -38,7 +38,7 @@ msgstr "Fermer"
msgid "Logs"
msgstr "Logs"
-#: apps/logs/models.py:22 apps/registration/models.py:18
+#: apps/logs/models.py:22 apps/registration/models.py:16
msgid "user"
msgstr "utilisateur"
@@ -99,7 +99,7 @@ msgstr "changelogs"
msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}"
-#: apps/participation/forms.py:14 apps/participation/models.py:19
+#: apps/participation/forms.py:14 apps/participation/models.py:22
msgid "The trigram must be composed of three uppercase letters."
msgstr "Le trigramme doit être composé de trois lettres majuscules."
@@ -107,27 +107,27 @@ 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/models.py:12
+#: apps/participation/models.py:15
msgid "name"
msgstr "nom"
-#: apps/participation/models.py:18
+#: apps/participation/models.py:21
msgid "trigram"
msgstr "trigramme"
-#: apps/participation/models.py:26
+#: apps/participation/models.py:29
msgid "access code"
msgstr "code d'accès"
-#: apps/participation/models.py:27
+#: apps/participation/models.py:30
msgid "The access code let other people to join the team."
msgstr "Le code d'accès permet aux autres participants de rejoindre l'équipe."
-#: apps/participation/models.py:31
+#: apps/participation/models.py:34
msgid "Grant Animath to publish my video"
msgstr "Autoriser Animath à publier ma vidéo"
-#: apps/participation/models.py:32
+#: apps/participation/models.py:35
msgid ""
"Give the authorisation to publish the video on the main website to promote "
"the action."
@@ -135,98 +135,135 @@ msgstr ""
"Donner l'autorisation de publier la vidéo sur le site principal pour "
"promouvoir les Correspondances."
-#: apps/participation/models.py:42
+#: apps/participation/models.py:45
#, python-brace-format
msgid "Team {name} ({trigram})"
msgstr "Équipe {name} ({trigram})"
-#: apps/participation/models.py:45 apps/participation/models.py:56
-#: apps/registration/models.py:83 apps/registration/models.py:129
+#: apps/participation/models.py:48 apps/participation/models.py:59
+#: apps/registration/models.py:81 apps/registration/models.py:127
msgid "team"
msgstr "équipe"
-#: apps/participation/models.py:46
+#: apps/participation/models.py:49
msgid "teams"
msgstr "équipes"
-#: apps/participation/models.py:60
+#: apps/participation/models.py:63
#, python-brace-format
msgid "Problem #{problem:d}"
msgstr "Problème n°{problem:d}"
-#: apps/participation/models.py:63
+#: apps/participation/models.py:66
msgid "problem number"
msgstr "numéro de problème"
-#: apps/participation/models.py:72
+#: apps/participation/models.py:75
msgid "solution video"
msgstr "vidéo de solution"
-#: apps/participation/models.py:81
+#: apps/participation/models.py:84
msgid "received participation"
msgstr "participation reçue"
-#: apps/participation/models.py:90
+#: apps/participation/models.py:93
msgid "synthesis video"
msgstr "vidéo de synthèse"
-#: apps/participation/models.py:94
+#: apps/participation/models.py:97
#, python-brace-format
msgid "Participation of the team {name} ({trigram})"
msgstr "Participation de l'équipe {name} ({trigram})"
-#: apps/participation/models.py:97 apps/participation/models.py:105
+#: apps/participation/models.py:100
msgid "participation"
msgstr "participation"
-#: apps/participation/models.py:98
+#: apps/participation/models.py:101
msgid "participations"
msgstr "participations"
-#: apps/participation/models.py:109
+#: apps/participation/models.py:106
msgid "link"
msgstr "lien"
-#: apps/participation/models.py:110
+#: apps/participation/models.py:107
msgid "The full video link."
msgstr "Le lien complet de la vidéo."
-#: apps/participation/models.py:116
+#: apps/participation/models.py:113
msgid "valid"
msgstr "valide"
-#: apps/participation/models.py:117
+#: apps/participation/models.py:114
msgid "The video got the validation of the administrators."
msgstr "La vidéo a été validée par les administrateurs."
-#: apps/participation/models.py:121
+#: apps/participation/models.py:136
#, python-brace-format
msgid "Video of team {name} ({trigram})"
msgstr "Vidéo de l'équipe {name} ({trigram})"
-#: apps/participation/models.py:125
+#: apps/participation/models.py:140
msgid "video"
msgstr "vidéo"
-#: apps/participation/models.py:126
+#: apps/participation/models.py:141
msgid "videos"
msgstr "vidéos"
#: apps/participation/templates/participation/create_team.html:11
-#: templates/base.html:202
+#: templates/base.html:207
msgid "Create"
msgstr "Créer"
#: apps/participation/templates/participation/join_team.html:11
-#: templates/base.html:198
+#: templates/base.html:203
msgid "Join"
msgstr "Rejoindre"
+#: apps/participation/templates/participation/participation_detail.html:6
#: apps/participation/templates/participation/team_detail.html:6
#: apps/registration/templates/registration/user_detail.html:6
msgid "any"
msgstr "aucun"
+#: apps/participation/templates/participation/participation_detail.html:11
+#: apps/participation/templates/participation/participation_detail.html:27
+#, fuzzy
+#| msgid "participation"
+msgid "Participation of team"
+msgstr "participation"
+
+#: apps/participation/templates/participation/participation_detail.html:15
+#: apps/participation/templates/participation/team_detail.html:29
+msgid "Chosen problem:"
+msgstr "Problème choisi :"
+
+#: apps/participation/templates/participation/participation_detail.html:30
+msgid "No video sent"
+msgstr "Pas de vidéo envoyée"
+
+#: apps/participation/templates/participation/participation_detail.html:31
+msgid "Video link:"
+msgstr "Lien de la vidéo :"
+
+#: apps/participation/templates/participation/participation_detail.html:32
+#: apps/participation/templates/participation/participation_detail.html:46
+#: apps/participation/templates/participation/upload_video.html:11
+#: apps/registration/templates/registration/upload_photo_authorization.html:18
+#: apps/registration/templates/registration/user_detail.html:60
+msgid "Upload"
+msgstr "Téléverser"
+
+#: apps/participation/templates/participation/participation_detail.html:37
+msgid "This video platform is not supported yet."
+msgstr "La plateforme de cette vidéo n'est pas encore supportée."
+
+#: apps/participation/templates/participation/participation_detail.html:45
+msgid "Upload video"
+msgstr "Envoyer la vidéo"
+
#: apps/participation/templates/participation/team_detail.html:14
msgid "Name:"
msgstr "Nom :"
@@ -247,10 +284,6 @@ msgstr "Encadrants :"
msgid "Participants:"
msgstr "Participants :"
-#: apps/participation/templates/participation/team_detail.html:29
-msgid "Chosen problem:"
-msgstr "Problème choisi :"
-
#: apps/participation/templates/participation/team_detail.html:32
msgid "Grant Animath to publish our video:"
msgstr "Autoriser Animath à publier notre vidéo :"
@@ -277,7 +310,7 @@ msgid "Update team"
msgstr "Modifier l'équipe"
#: apps/participation/views.py:15 templates/base.html:70
-#: templates/base.html:201
+#: templates/base.html:206
msgid "Create team"
msgstr "Créer une équipe"
@@ -290,15 +323,15 @@ msgid "You are already in a team."
msgstr "Vous êtes déjà dans une équipe."
#: apps/participation/views.py:41 templates/base.html:75
-#: templates/base.html:197
+#: templates/base.html:202
msgid "Join team"
msgstr "Rejoindre une équipe"
-#: apps/participation/views.py:72
+#: apps/participation/views.py:72 apps/participation/views.py:111
msgid "You are not in a team."
msgstr "Vous n'êtes pas dans une équipe."
-#: apps/participation/views.py:73
+#: apps/participation/views.py:73 apps/participation/views.py:112
msgid "You don't participate, so you don't have any team."
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
@@ -310,7 +343,7 @@ msgstr "rôle"
msgid "participant"
msgstr "participant"
-#: apps/registration/forms.py:16 apps/registration/models.py:138
+#: apps/registration/forms.py:16 apps/registration/models.py:136
msgid "coach"
msgstr "encadrant"
@@ -318,88 +351,88 @@ msgstr "encadrant"
msgid "The uploaded file must be a PDF, PNG of JPEG file."
msgstr "Le fichier envoyé doit être au format PDF, PNG ou JPEG."
-#: apps/registration/models.py:23
+#: apps/registration/models.py:21
msgid "Grant Animath to contact me in the future about other actions"
msgstr ""
"Autoriser Animath à me recontacter à l'avenir à propos d'autres actions"
-#: apps/registration/models.py:28
+#: apps/registration/models.py:26
msgid "email confirmed"
msgstr "email confirmé"
-#: apps/registration/models.py:32
+#: apps/registration/models.py:30
msgid "Activate your Correspondances account"
msgstr "Activez votre compte des Correspondances"
-#: apps/registration/models.py:68
+#: apps/registration/models.py:66
msgid "registration"
msgstr "inscription"
-#: apps/registration/models.py:69
+#: apps/registration/models.py:67
msgid "registrations"
msgstr "inscriptions"
-#: apps/registration/models.py:88
+#: apps/registration/models.py:86
msgid "12th grade"
msgstr "Terminale"
-#: apps/registration/models.py:89
+#: apps/registration/models.py:87
msgid "11th grade"
msgstr "Première"
-#: apps/registration/models.py:90
+#: apps/registration/models.py:88
msgid "10th grade or lower"
msgstr "Seconde ou inférieur"
-#: apps/registration/models.py:92
+#: apps/registration/models.py:90
msgid "student class"
msgstr "classe"
-#: apps/registration/models.py:97
+#: apps/registration/models.py:95
msgid "school"
msgstr "école"
-#: apps/registration/models.py:102
+#: apps/registration/models.py:100
msgid "photo authorization"
msgstr "autorisation de droit à l'image"
-#: apps/registration/models.py:110
+#: apps/registration/models.py:108
msgid "student"
msgstr "étudiant"
-#: apps/registration/models.py:118
+#: apps/registration/models.py:116
msgid "student registration"
msgstr "inscription d'élève"
-#: apps/registration/models.py:119
+#: apps/registration/models.py:117
msgid "student registrations"
msgstr "inscriptions d'élève"
-#: apps/registration/models.py:133
+#: apps/registration/models.py:131
msgid "professional activity"
msgstr "activité professionnelle"
-#: apps/registration/models.py:146
+#: apps/registration/models.py:144
msgid "coach registration"
msgstr "inscription d'encadrant"
-#: apps/registration/models.py:147
+#: apps/registration/models.py:145
msgid "coach registrations"
msgstr "inscriptions d'encadrants"
-#: apps/registration/models.py:152
+#: apps/registration/models.py:150
msgid "role of the administrator"
msgstr "rôle de l'administrateur"
-#: apps/registration/models.py:157
+#: apps/registration/models.py:155
msgid "admin"
msgstr "admin"
-#: apps/registration/models.py:165
+#: apps/registration/models.py:163
msgid "admin registration"
msgstr "inscription d'administrateur"
-#: apps/registration/models.py:166
+#: apps/registration/models.py:164
msgid "admin registrations"
msgstr "inscriptions d'administrateur"
@@ -495,7 +528,7 @@ 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."
#: apps/registration/templates/registration/password_reset_complete.html:10
-#: templates/base.html:108 templates/base.html:192 templates/base.html:193
+#: templates/base.html:113 templates/base.html:197 templates/base.html:198
#: templates/registration/login.html:7 templates/registration/login.html:8
#: templates/registration/login.html:25
msgid "Log in"
@@ -570,11 +603,6 @@ msgstr "Majeur"
msgid "Child"
msgstr "Mineur"
-#: apps/registration/templates/registration/upload_photo_authorization.html:18
-#: apps/registration/templates/registration/user_detail.html:60
-msgid "Upload"
-msgstr "Téléverser"
-
#: apps/registration/templates/registration/user_detail.html:14
msgid "Last name:"
msgstr "Nom de famille :"
@@ -635,27 +663,27 @@ msgstr "Modifier l'utilisateur"
msgid "Upload photo authorization"
msgstr "Téléverser l'autorisation de droit à l'image"
-#: apps/registration/views.py:63
+#: apps/registration/views.py:60
msgid "Email validation"
msgstr "Validation de l'adresse mail"
-#: apps/registration/views.py:65
+#: apps/registration/views.py:62
msgid "Validate email"
msgstr "Valider l'adresse mail"
-#: apps/registration/views.py:104
+#: apps/registration/views.py:101
msgid "Email validation unsuccessful"
msgstr "Échec de la validation de l'adresse mail"
-#: apps/registration/views.py:115
+#: apps/registration/views.py:112
msgid "Email validation email sent"
msgstr "Mail de confirmation de l'adresse mail envoyé"
-#: apps/registration/views.py:123
+#: apps/registration/views.py:120
msgid "Resend email validation link"
msgstr "Renvoyé le lien de validation de l'adresse mail"
-#: apps/registration/views.py:195
+#: apps/registration/views.py:192
#, python-brace-format
msgid "Photo authorization of {student}.{ext}"
msgstr "Autorisation de droit à l'image de {student}.{ext}"
@@ -729,31 +757,35 @@ msgstr "Accueil"
msgid "My team"
msgstr "Mon équipe"
-#: templates/base.html:88
+#: templates/base.html:86
+msgid "My participation"
+msgstr "Ma participation"
+
+#: templates/base.html:93
msgid "Make a gift"
msgstr "Faire un don"
-#: templates/base.html:92
+#: templates/base.html:97
msgid "Administration"
msgstr "Administration"
-#: templates/base.html:99
+#: templates/base.html:104
msgid "Return to admin view"
msgstr "Retourner à l'interface administrateur"
-#: templates/base.html:104
+#: templates/base.html:109
msgid "Register"
msgstr "S'inscrire"
-#: templates/base.html:120
+#: templates/base.html:125
msgid "My account"
msgstr "Mon compte"
-#: templates/base.html:123
+#: templates/base.html:128
msgid "Log out"
msgstr "Déconnexion"
-#: templates/base.html:139
+#: templates/base.html:144
#, python-format
msgid ""
"Your email address is not validated. Please click on the link you received "
@@ -764,7 +796,7 @@ msgstr ""
"avez reçu par mail. Vous pouvez renvoyer un mail en cliquant sur ce lien."
-#: templates/base.html:162
+#: templates/base.html:167
msgid "Contact us"
msgstr "Nous contacter"
diff --git a/templates/base.html b/templates/base.html
index a0d8e3b..b455b36 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -81,6 +81,11 @@
{% trans "My team" %}
+