mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2024-12-25 20:22:22 +00:00
Profile list
This commit is contained in:
parent
f70f6f16f0
commit
03f47f996b
@ -127,10 +127,10 @@ class TFJMUser(AbstractUser):
|
|||||||
role = models.CharField(
|
role = models.CharField(
|
||||||
max_length=16,
|
max_length=16,
|
||||||
choices=[
|
choices=[
|
||||||
("0admin", _("admin")),
|
("0admin", _("Admin")),
|
||||||
("1volunteer", _("organizer")),
|
("1volunteer", _("Organizer")),
|
||||||
("2coach", _("coach")),
|
("2coach", _("Coach")),
|
||||||
("3participant", _("participant")),
|
("3participant", _("Participant")),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -6,4 +6,7 @@ from member.models import TFJMUser
|
|||||||
class UserTable(tables.Table):
|
class UserTable(tables.Table):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = TFJMUser
|
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'
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
|
|
||||||
from .views import CreateUserView, DocumentView
|
from .views import CreateUserView, ProfileListView, OrphanedProfileListView, OrganizersListView
|
||||||
|
|
||||||
app_name = "member"
|
app_name = "member"
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ urlpatterns = [
|
|||||||
path("join-team/", RedirectView.as_view(pattern_name="index"), name="join_team"),
|
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/", RedirectView.as_view(pattern_name="index"), name="my_team"),
|
||||||
path("my-team/update/", RedirectView.as_view(pattern_name="index"), name="update_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("profiles/", ProfileListView.as_view(), name="all_profiles"),
|
||||||
path("orphaned-profiles/", RedirectView.as_view(pattern_name="index"), name="orphaned_profiles"),
|
path("orphaned-profiles/", OrphanedProfileListView.as_view(), name="orphaned_profiles"),
|
||||||
path("organizers/", RedirectView.as_view(pattern_name="index"), name="organizers"),
|
path("organizers/", OrganizersListView.as_view(), name="organizers"),
|
||||||
]
|
]
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from django.db.models import Q
|
||||||
from django.http import FileResponse
|
from django.http import FileResponse
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from django.views.generic import CreateView
|
from django.views.generic import CreateView
|
||||||
|
from django_tables2 import SingleTableView
|
||||||
|
|
||||||
|
from tournament.views import AdminMixin
|
||||||
from .forms import SignUpForm
|
from .forms import SignUpForm
|
||||||
from .models import TFJMUser, Document
|
from .models import TFJMUser, Document
|
||||||
|
from .tables import UserTable
|
||||||
|
|
||||||
|
|
||||||
class CreateUserView(CreateView):
|
class CreateUserView(CreateView):
|
||||||
@ -22,3 +27,29 @@ class DocumentView(LoginRequiredMixin, View):
|
|||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
return FileResponse(doc.file, content_type="application/pdf")
|
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"))
|
||||||
|
@ -74,6 +74,32 @@ class TournamentDetailView(DetailView):
|
|||||||
class TeamDetailView(LoginRequiredMixin, DetailView):
|
class TeamDetailView(LoginRequiredMixin, DetailView):
|
||||||
model = Team
|
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):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TFJM2\n"
|
"Project-Id-Version: TFJM2\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: 2020-04-29 02:30+0000\n"
|
||||||
"Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n"
|
"Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n"
|
||||||
"Language-Team: fr <LL@li.org>\n"
|
"Language-Team: fr <LL@li.org>\n"
|
||||||
@ -30,7 +30,7 @@ msgstr "membre"
|
|||||||
msgid "Choose a role..."
|
msgid "Choose a role..."
|
||||||
msgstr "Choisir un rôle ..."
|
msgstr "Choisir un rôle ..."
|
||||||
|
|
||||||
#: apps/member/forms.py:15
|
#: apps/member/forms.py:15 apps/member/models.py:133
|
||||||
msgid "Participant"
|
msgid "Participant"
|
||||||
msgstr "Participant"
|
msgstr "Participant"
|
||||||
|
|
||||||
@ -122,20 +122,16 @@ msgid "description"
|
|||||||
msgstr "description"
|
msgstr "description"
|
||||||
|
|
||||||
#: apps/member/models.py:130
|
#: apps/member/models.py:130
|
||||||
msgid "admin"
|
msgid "Admin"
|
||||||
msgstr "administrateur"
|
msgstr "Administrateur"
|
||||||
|
|
||||||
#: apps/member/models.py:131
|
#: apps/member/models.py:131
|
||||||
msgid "organizer"
|
msgid "Organizer"
|
||||||
msgstr "oragnisateur"
|
msgstr "Organisateur"
|
||||||
|
|
||||||
#: apps/member/models.py:132
|
#: apps/member/models.py:132
|
||||||
msgid "coach"
|
msgid "Coach"
|
||||||
msgstr "encadrant"
|
msgstr "Encadrant"
|
||||||
|
|
||||||
#: apps/member/models.py:133
|
|
||||||
msgid "participant"
|
|
||||||
msgstr "participant"
|
|
||||||
|
|
||||||
#: apps/member/models.py:139 apps/tournament/models.py:63
|
#: apps/member/models.py:139 apps/tournament/models.py:63
|
||||||
#: apps/tournament/models.py:129
|
#: apps/tournament/models.py:129
|
||||||
@ -269,7 +265,8 @@ msgstr "synthèses"
|
|||||||
#: apps/member/models.py:286
|
#: apps/member/models.py:286
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Synthesis of team {trigram} that is {dest} for problem {problem}"
|
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
|
#: apps/member/models.py:294
|
||||||
msgid "key"
|
msgid "key"
|
||||||
@ -287,6 +284,18 @@ msgstr "configuration"
|
|||||||
msgid "configurations"
|
msgid "configurations"
|
||||||
msgstr "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/apps.py:7 apps/tournament/models.py:76
|
||||||
#: apps/tournament/models.py:98 templates/tournament/team_detail.html:18
|
#: apps/tournament/models.py:98 templates/tournament/team_detail.html:18
|
||||||
msgid "tournament"
|
msgid "tournament"
|
||||||
@ -432,29 +441,27 @@ msgid "Tournaments list"
|
|||||||
msgstr "Liste des tournois"
|
msgstr "Liste des tournois"
|
||||||
|
|
||||||
#: apps/tournament/views.py:56
|
#: apps/tournament/views.py:56
|
||||||
#, fuzzy, python-brace-format
|
|
||||||
#| msgid "Payment of {user}"
|
|
||||||
msgid "Tournament of {name}"
|
msgid "Tournament of {name}"
|
||||||
msgstr "Paiement de {user}"
|
msgstr "Tournoi de {user}"
|
||||||
|
|
||||||
#: apps/tournament/views.py:80
|
#: apps/tournament/views.py:97 apps/tournament/views.py:131
|
||||||
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
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Solutions for team {team}.zip"
|
msgid "Solutions for team {team}.zip"
|
||||||
msgstr "Solutions pour l'équipe {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"
|
msgid "All solutions"
|
||||||
msgstr "Toutes les solutions"
|
msgstr "Toutes les solutions"
|
||||||
|
|
||||||
#: apps/tournament/views.py:149
|
#: apps/tournament/views.py:175
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Solutions for tournament {tournament}.zip"
|
msgid "Solutions for tournament {tournament}.zip"
|
||||||
msgstr "Solutions pour le tournoi {tournament}.zip"
|
msgstr "Solutions pour le tournoi {tournament}.zip"
|
||||||
@ -471,18 +478,6 @@ msgstr "Accueil"
|
|||||||
msgid "Tournament list"
|
msgid "Tournament list"
|
||||||
msgstr "Liste des tournois"
|
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
|
#: templates/base.html:89
|
||||||
msgid "My account"
|
msgid "My account"
|
||||||
msgstr "Mon compte"
|
msgstr "Mon compte"
|
||||||
@ -671,7 +666,7 @@ msgid "Reset my password"
|
|||||||
msgstr "Réinitialiser mon mot de passe"
|
msgstr "Réinitialiser mon mot de passe"
|
||||||
|
|
||||||
#: templates/tournament/solutions_orga_list.html:14
|
#: templates/tournament/solutions_orga_list.html:14
|
||||||
#| msgid "tournaments"
|
#, python-format
|
||||||
msgid "%(tournament)s — ZIP"
|
msgid "%(tournament)s — ZIP"
|
||||||
msgstr "%(tournament)s — ZIP"
|
msgstr "%(tournament)s — ZIP"
|
||||||
|
|
||||||
@ -700,10 +695,13 @@ msgid "Documents"
|
|||||||
msgstr "Documents"
|
msgstr "Documents"
|
||||||
|
|
||||||
#: templates/tournament/team_detail.html:45
|
#: templates/tournament/team_detail.html:45
|
||||||
#, python-format
|
|
||||||
msgid "Motivation letter:"
|
msgid "Motivation letter:"
|
||||||
msgstr "Lettre de motivation :"
|
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
|
#: templates/tournament/tournament_detail.html:22
|
||||||
msgid "Free"
|
msgid "Free"
|
||||||
msgstr "Gratuit"
|
msgstr "Gratuit"
|
||||||
@ -722,7 +720,8 @@ msgstr "Envoyer un mail à toutes les personnes du tournoi"
|
|||||||
|
|
||||||
#: templates/tournament/tournament_detail.html:43
|
#: templates/tournament/tournament_detail.html:43
|
||||||
msgid "Send a mail to all people in this tournament that are in a valid team"
|
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
|
#: templates/tournament/tournament_detail.html:50
|
||||||
msgid "Edit tournament"
|
msgid "Edit tournament"
|
||||||
|
7
templates/member/profile_list.html
Normal file
7
templates/member/profile_list.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load django_tables2 %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% render_table table %}
|
||||||
|
{% endblock %}
|
@ -51,9 +51,15 @@
|
|||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
<ul>
|
<ul>
|
||||||
{% for solution in team.solutions.all %}
|
{% for solution in team.solutions.all %}
|
||||||
<li><strong>{{ solution }} :</strong> <a data-turbolinks="false" href="{% url "member:document" file=solution.file %}">{% trans "Download" %}</a></li>
|
<li><strong>{{ solution }} :</strong> <a data-turbolinks="false" href="{% url "document" file=solution.file %}">{% trans "Download" %}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-success" name="zip">{% trans "Download solutions as ZIP" %}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Loading…
Reference in New Issue
Block a user