diff --git a/apps/member/models.py b/apps/member/models.py index 7d96bdc..2559be9 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -127,10 +127,10 @@ class TFJMUser(AbstractUser): role = models.CharField( max_length=16, choices=[ - ("0admin", _("admin")), - ("1volunteer", _("organizer")), - ("2coach", _("coach")), - ("3participant", _("participant")), + ("0admin", _("Admin")), + ("1volunteer", _("Organizer")), + ("2coach", _("Coach")), + ("3participant", _("Participant")), ] ) diff --git a/apps/member/tables.py b/apps/member/tables.py index 451756d..e7890ba 100644 --- a/apps/member/tables.py +++ b/apps/member/tables.py @@ -6,4 +6,7 @@ from member.models import TFJMUser class UserTable(tables.Table): class Meta: model = TFJMUser - fields = ("last_name", "first_name", "role",) + fields = ("last_name", "first_name", "role", "date_joined", ) + attrs = { + 'class': 'table table-condensed table-striped table-hover' + } diff --git a/apps/member/urls.py b/apps/member/urls.py index 5fcadcd..c918085 100644 --- a/apps/member/urls.py +++ b/apps/member/urls.py @@ -1,7 +1,7 @@ from django.urls import path from django.views.generic import RedirectView -from .views import CreateUserView, DocumentView +from .views import CreateUserView, ProfileListView, OrphanedProfileListView, OrganizersListView app_name = "member" @@ -12,7 +12,7 @@ urlpatterns = [ path("join-team/", RedirectView.as_view(pattern_name="index"), name="join_team"), path("my-team/", RedirectView.as_view(pattern_name="index"), name="my_team"), path("my-team/update/", RedirectView.as_view(pattern_name="index"), name="update_my_team"), - path("profiles/", RedirectView.as_view(pattern_name="index"), name="all_profiles"), - path("orphaned-profiles/", RedirectView.as_view(pattern_name="index"), name="orphaned_profiles"), - path("organizers/", RedirectView.as_view(pattern_name="index"), name="organizers"), + path("profiles/", ProfileListView.as_view(), name="all_profiles"), + path("orphaned-profiles/", OrphanedProfileListView.as_view(), name="orphaned_profiles"), + path("organizers/", OrganizersListView.as_view(), name="organizers"), ] diff --git a/apps/member/views.py b/apps/member/views.py index 3398b6e..6802b75 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -1,11 +1,16 @@ from django.contrib.auth.mixins import LoginRequiredMixin from django.core.exceptions import PermissionDenied +from django.db.models import Q from django.http import FileResponse +from django.utils.translation import gettext_lazy as _ from django.views import View from django.views.generic import CreateView +from django_tables2 import SingleTableView +from tournament.views import AdminMixin from .forms import SignUpForm from .models import TFJMUser, Document +from .tables import UserTable class CreateUserView(CreateView): @@ -22,3 +27,29 @@ class DocumentView(LoginRequiredMixin, View): raise PermissionDenied return FileResponse(doc.file, content_type="application/pdf") + + +class ProfileListView(LoginRequiredMixin, AdminMixin, SingleTableView): + model = TFJMUser + queryset = TFJMUser.objects.order_by("role", "last_name", "first_name") + table_class = UserTable + template_name = "member/profile_list.html" + extra_context = dict(title=_("All profiles")) + + +class OrphanedProfileListView(LoginRequiredMixin, AdminMixin, SingleTableView): + model = TFJMUser + queryset = TFJMUser.objects.filter((Q(role="2coach") | Q(role="3participant")) & Q(team__isnull=True))\ + .order_by("role", "last_name", "first_name") + table_class = UserTable + template_name = "member/profile_list.html" + extra_context = dict(title=_("Orphaned profiles")) + + +class OrganizersListView(LoginRequiredMixin, AdminMixin, SingleTableView): + model = TFJMUser + queryset = TFJMUser.objects.filter(Q(role="0admin") | Q(role="1volunteer"))\ + .order_by("role", "last_name", "first_name") + table_class = UserTable + template_name = "member/profile_list.html" + extra_context = dict(title=_("Organizers")) diff --git a/apps/tournament/views.py b/apps/tournament/views.py index 7fbb047..041d29e 100644 --- a/apps/tournament/views.py +++ b/apps/tournament/views.py @@ -74,6 +74,32 @@ class TournamentDetailView(DetailView): class TeamDetailView(LoginRequiredMixin, DetailView): model = Team + def dispatch(self, request, *args, **kwargs): + if not request.user.admin and self.request.user not in self.get_object().tournament.organizers: + raise PermissionDenied + return super().dispatch(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + team = self.get_object() + if "zip" in request.POST: + solutions = team.solutions.all() + + out = BytesIO() + zf = zipfile.ZipFile(out, "w") + + for solution in solutions: + zf.write(solution.file.path, str(solution) + ".pdf") + + zf.close() + + resp = HttpResponse(out.getvalue(), content_type="application/x-zip-compressed") + resp['Content-Disposition'] = 'attachment; filename={}'\ + .format(_("Solutions for team {team}.zip") + .format(team=str(team)).replace(" ", "%20")) + return resp + + return self.get(request, *args, **kwargs) + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 937f702..014f63e 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: TFJM2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-30 18:11+0000\n" +"POT-Creation-Date: 2020-04-30 19:04+0000\n" "PO-Revision-Date: 2020-04-29 02:30+0000\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: fr \n" @@ -30,7 +30,7 @@ msgstr "membre" msgid "Choose a role..." msgstr "Choisir un rôle ..." -#: apps/member/forms.py:15 +#: apps/member/forms.py:15 apps/member/models.py:133 msgid "Participant" msgstr "Participant" @@ -122,20 +122,16 @@ msgid "description" msgstr "description" #: apps/member/models.py:130 -msgid "admin" -msgstr "administrateur" +msgid "Admin" +msgstr "Administrateur" #: apps/member/models.py:131 -msgid "organizer" -msgstr "oragnisateur" +msgid "Organizer" +msgstr "Organisateur" #: apps/member/models.py:132 -msgid "coach" -msgstr "encadrant" - -#: apps/member/models.py:133 -msgid "participant" -msgstr "participant" +msgid "Coach" +msgstr "Encadrant" #: apps/member/models.py:139 apps/tournament/models.py:63 #: apps/tournament/models.py:129 @@ -269,7 +265,8 @@ msgstr "synthèses" #: apps/member/models.py:286 #, python-brace-format msgid "Synthesis of team {trigram} that is {dest} for problem {problem}" -msgstr "Synthèse de l'équipe {trigram} qui est {dest} pour le problème {problem}" +msgstr "" +"Synthèse de l'équipe {trigram} qui est {dest} pour le problème {problem}" #: apps/member/models.py:294 msgid "key" @@ -287,6 +284,18 @@ msgstr "configuration" msgid "configurations" msgstr "configurations" +#: apps/member/views.py:37 templates/base.html:81 +msgid "All profiles" +msgstr "Tous les profils" + +#: apps/member/views.py:46 templates/base.html:80 +msgid "Orphaned profiles" +msgstr "Profils orphelins" + +#: apps/member/views.py:55 templates/base.html:83 +msgid "Organizers" +msgstr "Organisateurs" + #: apps/tournament/apps.py:7 apps/tournament/models.py:76 #: apps/tournament/models.py:98 templates/tournament/team_detail.html:18 msgid "tournament" @@ -432,29 +441,27 @@ msgid "Tournaments list" msgstr "Liste des tournois" #: apps/tournament/views.py:56 -#, fuzzy, python-brace-format -#| msgid "Payment of {user}" msgid "Tournament of {name}" -msgstr "Paiement de {user}" +msgstr "Tournoi de {user}" -#: apps/tournament/views.py:80 -msgid "Information about team" -msgstr "Informations sur l'équipe" - -#: apps/tournament/views.py:89 templates/base.html:108 templates/base.html:126 -msgid "Solutions" -msgstr "Solutions" - -#: apps/tournament/views.py:105 +#: apps/tournament/views.py:97 apps/tournament/views.py:131 #, python-brace-format msgid "Solutions for team {team}.zip" msgstr "Solutions pour l'équipe {team}.zip" -#: apps/tournament/views.py:130 +#: apps/tournament/views.py:106 +msgid "Information about team" +msgstr "Informations sur l'équipe" + +#: apps/tournament/views.py:115 templates/base.html:108 templates/base.html:126 +msgid "Solutions" +msgstr "Solutions" + +#: apps/tournament/views.py:156 msgid "All solutions" msgstr "Toutes les solutions" -#: apps/tournament/views.py:149 +#: apps/tournament/views.py:175 #, python-brace-format msgid "Solutions for tournament {tournament}.zip" msgstr "Solutions pour le tournoi {tournament}.zip" @@ -471,18 +478,6 @@ msgstr "Accueil" msgid "Tournament list" msgstr "Liste des tournois" -#: templates/base.html:80 -msgid "Orphaned profiles" -msgstr "Profils orphelins" - -#: templates/base.html:81 -msgid "All profiles" -msgstr "Tous les profils" - -#: templates/base.html:83 -msgid "Organizers" -msgstr "Organisateurs" - #: templates/base.html:89 msgid "My account" msgstr "Mon compte" @@ -671,7 +666,7 @@ msgid "Reset my password" msgstr "Réinitialiser mon mot de passe" #: templates/tournament/solutions_orga_list.html:14 -#| msgid "tournaments" +#, python-format msgid "%(tournament)s — ZIP" msgstr "%(tournament)s — ZIP" @@ -700,10 +695,13 @@ msgid "Documents" msgstr "Documents" #: templates/tournament/team_detail.html:45 -#, python-format msgid "Motivation letter:" msgstr "Lettre de motivation :" +#: templates/tournament/team_detail.html:61 +msgid "Download solutions as ZIP" +msgstr "Télécharger les solutions en archive ZIP" + #: templates/tournament/tournament_detail.html:22 msgid "Free" msgstr "Gratuit" @@ -722,7 +720,8 @@ msgstr "Envoyer un mail à toutes les personnes du tournoi" #: templates/tournament/tournament_detail.html:43 msgid "Send a mail to all people in this tournament that are in a valid team" -msgstr "Envoyer un mail à toutes les personnes du tournoi dans une équipe valide" +msgstr "" +"Envoyer un mail à toutes les personnes du tournoi dans une équipe valide" #: templates/tournament/tournament_detail.html:50 msgid "Edit tournament" diff --git a/templates/member/profile_list.html b/templates/member/profile_list.html new file mode 100644 index 0000000..1c0d551 --- /dev/null +++ b/templates/member/profile_list.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% load django_tables2 %} + +{% block content %} + {% render_table table %} +{% endblock %} diff --git a/templates/tournament/team_detail.html b/templates/tournament/team_detail.html index ed05c6c..3d1ae5b 100644 --- a/templates/tournament/team_detail.html +++ b/templates/tournament/team_detail.html @@ -51,9 +51,15 @@
+
+
+ {% csrf_token %} + +
+
{% endif %} {% endblock %}