From d73a92c7f72fab2318b897cec6a3b63dc14479a9 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 20 Oct 2020 16:08:42 +0200 Subject: [PATCH] Add leave team button --- .../templates/participation/team_detail.html | 13 ++ .../templates/participation/team_leave.html | 13 ++ apps/participation/urls.py | 4 +- apps/participation/views.py | 26 +++ locale/fr/LC_MESSAGES/django.po | 166 ++++++++++-------- 5 files changed, 145 insertions(+), 77 deletions(-) create mode 100644 apps/participation/templates/participation/team_leave.html diff --git a/apps/participation/templates/participation/team_detail.html b/apps/participation/templates/participation/team_detail.html index 5ac6626..f6fcf21 100644 --- a/apps/participation/templates/participation/team_detail.html +++ b/apps/participation/templates/participation/team_detail.html @@ -62,6 +62,9 @@ @@ -120,6 +123,11 @@ {% trans "Update" as modal_button %} {% url "participation:update_team" pk=team.pk as modal_action %} {% include "base_modal.html" with modal_id="updateTeam" %} + + {% trans "Leave team" as modal_title %} + {% trans "Leave" as modal_button %} + {% url "participation:team_leave" as modal_action %} + {% include "base_modal.html" with modal_id="leaveTeam" modal_button_type="danger" %} {% endblock %} {% block extrajavascript %} @@ -130,6 +138,11 @@ if (!modalBody.html().trim()) modalBody.load("{% url "participation:update_team" pk=team.pk %} #form-content"); }); + $('button[data-target="#leaveTeamModal"]').click(function() { + let modalBody = $("#leaveTeamModal div.modal-body"); + if (!modalBody.html().trim()) + modalBody.load("{% url "participation:team_leave" %} #form-content"); + }); }); {% endblock %} diff --git a/apps/participation/templates/participation/team_leave.html b/apps/participation/templates/participation/team_leave.html new file mode 100644 index 0000000..72d3db9 --- /dev/null +++ b/apps/participation/templates/participation/team_leave.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} + +{% load i18n %} + +{% block content %} +
+
+ {% csrf_token %} + {% trans "Are you sure that you want to leave this team?" %} +
+ +
+{% endblock %} diff --git a/apps/participation/urls.py b/apps/participation/urls.py index 54efc74..10b7676 100644 --- a/apps/participation/urls.py +++ b/apps/participation/urls.py @@ -1,7 +1,8 @@ from django.urls import path from .views import CalendarView, CreateTeamView, JoinTeamView, MyParticipationDetailView, MyTeamDetailView, \ - ParticipationDetailView, PhaseUpdateView, TeamAuthorizationsView, TeamDetailView, TeamUpdateView, UploadVideoView + ParticipationDetailView, PhaseUpdateView, TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamUpdateView, \ + UploadVideoView app_name = "participation" @@ -13,6 +14,7 @@ urlpatterns = [ path("team//", TeamDetailView.as_view(), name="team_detail"), path("team//update/", TeamUpdateView.as_view(), name="update_team"), path("team//authorizations/", TeamAuthorizationsView.as_view(), name="team_authorizations"), + path("team/leave/", TeamLeaveView.as_view(), name="team_leave"), 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 0ca63e4..fa6d6bf 100644 --- a/apps/participation/views.py +++ b/apps/participation/views.py @@ -2,6 +2,9 @@ from io import BytesIO import os from zipfile import ZipFile +from django.shortcuts import redirect +from django.views.generic.base import View, TemplateView + from corres2math.lists import get_sympa_client from corres2math.views import AdminMixin from django.contrib.auth.mixins import LoginRequiredMixin @@ -236,6 +239,29 @@ class TeamAuthorizationsView(LoginRequiredMixin, DetailView): return response +class TeamLeaveView(LoginRequiredMixin, TemplateView): + template_name = "participation/team_leave.html" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated: + return self.handle_no_permission() + if not request.user.registration.team: + raise PermissionDenied(_("You are not in a team.")) + if request.user.registration.team.participation.valid is not None: + raise PermissionDenied(_("The team is already validated or the validation is pending.")) + return super().dispatch(request, *args, **kwargs) + + @transaction.atomic() + def post(self, request, *args, **kwargs): + team = request.user.registration.team + request.user.registration.team = None + request.user.registration.save() + get_sympa_client().unsubscribe(request.user.email, f"equipe-{team.trigram.lower()}", False) + if team.students.count() + team.coachs.count() == 0: + team.delete() + return redirect(reverse_lazy("index")) + + class MyParticipationDetailView(LoginRequiredMixin, RedirectView): def get_redirect_url(self, *args, **kwargs): user = self.request.user diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 1d24bce..76a01c1 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-20 15:21+0200\n" +"POT-Creation-Date: 2020-10-20 15:53+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: LANGUAGE \n" @@ -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:15 apps/participation/models.py:27 +#: apps/participation/forms.py:15 apps/participation/models.py:28 msgid "The trigram must be composed of three uppercase letters." msgstr "Le trigramme doit être composé de trois lettres majuscules." @@ -131,28 +131,28 @@ msgstr "Cette phase doit commencer après les phases précédentes." msgid "This phase must end after the next phases." msgstr "Cette phase doit finir avant les phases suivantes." -#: apps/participation/models.py:20 apps/participation/tables.py:30 +#: apps/participation/models.py:21 apps/participation/tables.py:30 #: apps/participation/tables.py:52 apps/participation/tables.py:78 msgid "name" msgstr "nom" -#: apps/participation/models.py:26 apps/participation/tables.py:57 +#: apps/participation/models.py:27 apps/participation/tables.py:57 msgid "trigram" msgstr "trigramme" -#: apps/participation/models.py:34 +#: apps/participation/models.py:35 msgid "access code" msgstr "code d'accès" -#: apps/participation/models.py:35 +#: apps/participation/models.py:36 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:39 +#: apps/participation/models.py:40 msgid "Grant Animath to publish my video" msgstr "Autoriser Animath à publier ma vidéo" -#: apps/participation/models.py:40 +#: apps/participation/models.py:41 msgid "" "Give the authorisation to publish the video on the main website to promote " "the action." @@ -160,101 +160,101 @@ msgstr "" "Donner l'autorisation de publier la vidéo sur le site principal pour " "promouvoir les Correspondances." -#: apps/participation/models.py:67 +#: apps/participation/models.py:72 #, python-brace-format msgid "Team {name} ({trigram})" msgstr "Équipe {name} ({trigram})" -#: apps/participation/models.py:70 apps/participation/models.py:81 +#: apps/participation/models.py:75 apps/participation/models.py:86 #: apps/registration/models.py:89 apps/registration/models.py:134 msgid "team" msgstr "équipe" -#: apps/participation/models.py:71 +#: apps/participation/models.py:76 msgid "teams" msgstr "équipes" -#: apps/participation/models.py:85 +#: apps/participation/models.py:90 #, python-brace-format msgid "Problem #{problem:d}" msgstr "Problème n°{problem:d}" -#: apps/participation/models.py:88 apps/participation/tables.py:35 +#: apps/participation/models.py:93 apps/participation/tables.py:35 #: apps/participation/tables.py:62 msgid "problem number" msgstr "numéro de problème" -#: apps/participation/models.py:94 apps/participation/models.py:145 +#: apps/participation/models.py:99 apps/participation/models.py:150 msgid "valid" msgstr "valide" -#: apps/participation/models.py:95 apps/participation/models.py:146 +#: apps/participation/models.py:100 apps/participation/models.py:151 msgid "The video got the validation of the administrators." msgstr "La vidéo a été validée par les administrateurs." -#: apps/participation/models.py:104 +#: apps/participation/models.py:109 msgid "solution video" msgstr "vidéo de solution" -#: apps/participation/models.py:113 +#: apps/participation/models.py:118 msgid "received participation" msgstr "participation reçue" -#: apps/participation/models.py:122 +#: apps/participation/models.py:127 msgid "synthesis video" msgstr "vidéo de synthèse" -#: apps/participation/models.py:129 +#: apps/participation/models.py:134 #, python-brace-format msgid "Participation of the team {name} ({trigram})" msgstr "Participation de l'équipe {name} ({trigram})" -#: apps/participation/models.py:132 +#: apps/participation/models.py:137 msgid "participation" msgstr "participation" -#: apps/participation/models.py:133 +#: apps/participation/models.py:138 msgid "participations" msgstr "participations" -#: apps/participation/models.py:138 +#: apps/participation/models.py:143 msgid "link" msgstr "lien" -#: apps/participation/models.py:139 +#: apps/participation/models.py:144 msgid "The full video link." msgstr "Le lien complet de la vidéo." -#: apps/participation/models.py:173 +#: apps/participation/models.py:178 #, python-brace-format msgid "Video of team {name} ({trigram})" msgstr "Vidéo de l'équipe {name} ({trigram})" -#: apps/participation/models.py:177 +#: apps/participation/models.py:182 msgid "video" msgstr "vidéo" -#: apps/participation/models.py:178 +#: apps/participation/models.py:183 msgid "videos" msgstr "vidéos" -#: apps/participation/models.py:185 +#: apps/participation/models.py:190 msgid "phase number" msgstr "phase" -#: apps/participation/models.py:190 +#: apps/participation/models.py:195 msgid "phase description" msgstr "description" -#: apps/participation/models.py:194 +#: apps/participation/models.py:199 msgid "start date of the given phase" msgstr "début de la phase" -#: apps/participation/models.py:199 +#: apps/participation/models.py:204 msgid "end date of the given phase" msgstr "fin de la phase" -#: apps/participation/models.py:214 +#: apps/participation/models.py:219 msgid "" "Phase {phase_number:d} starts on {start:%Y-%m-%d %H:%M} and ends on {end:%Y-" "%m-%d %H:%M}" @@ -262,11 +262,11 @@ msgstr "" "Phase {phase_number:d} démarrant le {start:%d/%m/%Y %H:%M} et finissant le " "{end:%d/%m/%Y %H:%M}" -#: apps/participation/models.py:218 +#: apps/participation/models.py:223 msgid "phase" msgstr "phase" -#: apps/participation/models.py:219 +#: apps/participation/models.py:224 msgid "phases" msgstr "phases" @@ -281,9 +281,9 @@ msgid "Join" msgstr "Rejoindre" #: apps/participation/templates/participation/participation_detail.html:6 -#: apps/participation/templates/participation/team_detail.html:28 -#: apps/participation/templates/participation/team_detail.html:37 -#: apps/participation/templates/participation/team_detail.html:42 +#: apps/participation/templates/participation/team_detail.html:31 +#: apps/participation/templates/participation/team_detail.html:40 +#: apps/participation/templates/participation/team_detail.html:45 #: apps/registration/templates/registration/user_detail.html:6 #: apps/registration/templates/registration/user_detail.html:26 msgid "any" @@ -299,7 +299,7 @@ msgid "Team:" msgstr "Équipe :" #: apps/participation/templates/participation/participation_detail.html:16 -#: apps/participation/templates/participation/team_detail.html:41 +#: apps/participation/templates/participation/team_detail.html:44 msgid "Chosen problem:" msgstr "Problème choisi :" @@ -337,8 +337,8 @@ msgstr "La plateforme de cette vidéo n'est pas encore supportée." #: apps/participation/templates/participation/phase_form.html:11 #: apps/participation/templates/participation/phase_list.html:18 -#: apps/participation/templates/participation/team_detail.html:61 -#: apps/participation/templates/participation/team_detail.html:117 +#: apps/participation/templates/participation/team_detail.html:64 +#: apps/participation/templates/participation/team_detail.html:123 #: apps/participation/templates/participation/update_team.html:12 #: apps/registration/templates/registration/update_user.html:12 #: apps/registration/templates/registration/user_detail.html:64 @@ -364,34 +364,45 @@ msgid "Trigram:" msgstr "Trigramme :" #: apps/participation/templates/participation/team_detail.html:20 +#: apps/registration/templates/registration/user_detail.html:20 +msgid "Email:" +msgstr "Adresse e-mail :" + +#: apps/participation/templates/participation/team_detail.html:23 msgid "Access code:" msgstr "Code d'accès :" -#: apps/participation/templates/participation/team_detail.html:23 +#: apps/participation/templates/participation/team_detail.html:26 msgid "Coachs:" msgstr "Encadrants :" -#: apps/participation/templates/participation/team_detail.html:32 +#: apps/participation/templates/participation/team_detail.html:35 msgid "Participants:" msgstr "Participants :" -#: apps/participation/templates/participation/team_detail.html:45 +#: apps/participation/templates/participation/team_detail.html:48 msgid "Grant Animath to publish our video:" msgstr "Autoriser Animath à publier notre vidéo :" -#: apps/participation/templates/participation/team_detail.html:48 +#: apps/participation/templates/participation/team_detail.html:51 msgid "Authorizations:" msgstr "Autorisations :" -#: apps/participation/templates/participation/team_detail.html:54 +#: apps/participation/templates/participation/team_detail.html:57 msgid "Not uploaded yet" msgstr "Pas encore envoyée" -#: apps/participation/templates/participation/team_detail.html:70 +#: apps/participation/templates/participation/team_detail.html:66 +#: apps/participation/templates/participation/team_detail.html:128 +#: apps/participation/templates/participation/team_leave.html:9 +msgid "Leave" +msgstr "Quitter" + +#: apps/participation/templates/participation/team_detail.html:76 msgid "Access to team participation" msgstr "Accéder à la participation de l'équipe" -#: apps/participation/templates/participation/team_detail.html:77 +#: apps/participation/templates/participation/team_detail.html:83 msgid "" "Your team has at least 3 members and all photo authorizations were given: " "the team can be validated." @@ -399,11 +410,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:82 +#: apps/participation/templates/participation/team_detail.html:88 msgid "Submit my team to validation" msgstr "Soumettre mon équipe à validation" -#: apps/participation/templates/participation/team_detail.html:88 +#: apps/participation/templates/participation/team_detail.html:94 msgid "" "Your team must be composed of 3 members and each member must upload its " "photo authorization and confirm its email address." @@ -411,15 +422,15 @@ 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:93 +#: apps/participation/templates/participation/team_detail.html:99 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:99 +#: apps/participation/templates/participation/team_detail.html:105 msgid "Your validation is pending." msgstr "Votre validation est en attente." -#: apps/participation/templates/participation/team_detail.html:103 +#: apps/participation/templates/participation/team_detail.html:109 msgid "" "The team requested to be validated. You may now control the authorizations " "and confirm that they can participate." @@ -427,85 +438,92 @@ 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 +#: apps/participation/templates/participation/team_detail.html:115 msgid "Validate" msgstr "Valider" -#: apps/participation/templates/participation/team_detail.html:110 +#: apps/participation/templates/participation/team_detail.html:116 msgid "Invalidate" msgstr "Invalider" -#: apps/participation/templates/participation/team_detail.html:116 +#: apps/participation/templates/participation/team_detail.html:122 msgid "Update team" msgstr "Modifier l'équipe" -#: apps/participation/views.py:30 templates/base.html:77 +#: apps/participation/templates/participation/team_detail.html:127 +msgid "Leave team" +msgstr "Quitter l'équipe" + +#: apps/participation/templates/participation/team_leave.html:7 +msgid "Are you sure that you want to leave this team?" +msgstr "Êtes-vous sûr·e de vouloir quitter cette équipe ?" + +#: apps/participation/views.py:32 templates/base.html:77 #: templates/base.html:228 msgid "Create team" msgstr "Créer une équipe" -#: apps/participation/views.py:37 apps/participation/views.py:67 +#: apps/participation/views.py:39 apps/participation/views.py:69 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:39 apps/participation/views.py:69 +#: apps/participation/views.py:41 apps/participation/views.py:71 msgid "You are already in a team." msgstr "Vous êtes déjà dans une équipe." -#: apps/participation/views.py:60 templates/base.html:82 +#: apps/participation/views.py:62 templates/base.html:82 #: templates/base.html:224 msgid "Join team" msgstr "Rejoindre une équipe" -#: apps/participation/views.py:95 apps/participation/views.py:249 +#: apps/participation/views.py:97 apps/participation/views.py:248 +#: apps/participation/views.py:259 msgid "You are not in a team." msgstr "Vous n'êtes pas dans une équipe." -#: apps/participation/views.py:96 apps/participation/views.py:250 +#: apps/participation/views.py:98 apps/participation/views.py:260 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:135 +#: apps/participation/views.py:137 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:138 +#: apps/participation/views.py:140 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:151 +#: apps/participation/views.py:153 msgid "You are not an administrator." msgstr "Vous n'êtes pas administrateur." -#: apps/participation/views.py:154 +#: apps/participation/views.py:156 msgid "This team has no pending validation." msgstr "L'équipe n'a pas de validation en attente." -#: apps/participation/views.py:176 +#: apps/participation/views.py:175 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:233 apps/registration/views.py:213 +#: apps/participation/views.py:232 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:237 +#: apps/participation/views.py:236 #, 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:259 +#: apps/participation/views.py:269 msgid "The team is not validated yet." msgstr "L'équipe n'est pas encore validée." -#: apps/participation/views.py:268 -#, fuzzy, python-brace-format -#| msgid "Participation of the team {name} ({trigram})" +#: apps/participation/views.py:278 msgid "Participation of team {trigram}" -msgstr "Participation de l'équipe {name} ({trigram})" +msgstr "Participation de l'équipe {trigram}" #: apps/registration/forms.py:13 msgid "role" @@ -779,10 +797,6 @@ msgstr "Nom de famille :" msgid "First name:" msgstr "Prénom :" -#: apps/registration/templates/registration/user_detail.html:20 -msgid "Email:" -msgstr "Adresse e-mail :" - #: apps/registration/templates/registration/user_detail.html:22 msgid "Not confirmed" msgstr "Non confirmée"