1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-06-25 00:20:31 +02:00

Compare commits

...

9 Commits

11 changed files with 498 additions and 402 deletions

View File

@ -4,12 +4,10 @@ ENV PYTHONUNBUFFERED 1
ENV DJANGO_ALLOW_ASYNC_UNSAFE 1 ENV DJANGO_ALLOW_ASYNC_UNSAFE 1
RUN apk add --no-cache gettext nginx gcc git libc-dev libffi-dev libpq-dev libxml2-dev libxslt-dev \ RUN apk add --no-cache gettext nginx gcc git libc-dev libffi-dev libpq-dev libxml2-dev libxslt-dev \
npm libmagic texlive texmf-dist-fontsrecommended texmf-dist-lang texmf-dist-latexextra libmagic texlive texmf-dist-fontsrecommended texmf-dist-lang texmf-dist-latexextra uglify-js
RUN apk add --no-cache bash RUN apk add --no-cache bash
RUN npm install -g yuglify
RUN mkdir /code /code/docs RUN mkdir /code /code/docs
WORKDIR /code WORKDIR /code
COPY requirements.txt /code/requirements.txt COPY requirements.txt /code/requirements.txt

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,13 @@ from pathlib import Path
from django.conf import settings from django.conf import settings
from django.core.management import BaseCommand from django.core.management import BaseCommand
from django.utils.translation import activate
from participation.models import Solution, Tournament from participation.models import Solution, Tournament
class Command(BaseCommand): class Command(BaseCommand):
def handle(self, *args, **kwargs): def handle(self, *args, **kwargs):
activate(settings.PREFERRED_LANGUAGE_CODE)
base_dir = Path(__file__).parent.parent.parent.parent base_dir = Path(__file__).parent.parent.parent.parent
base_dir /= "output" base_dir /= "output"
if not base_dir.is_dir(): if not base_dir.is_dir():

View File

@ -440,6 +440,10 @@ class Tournament(models.Model):
return Participation.objects.filter(final=True) return Participation.objects.filter(final=True)
return self.participation_set return self.participation_set
@property
def organizers_and_presidents(self):
return VolunteerRegistration.objects.filter(Q(admin=True) | Q(organized_tournaments=self) | Q(pools_presided__tournament=self))
@property @property
def solutions(self): def solutions(self):
if self.final: if self.final:
@ -932,10 +936,10 @@ class Participation(models.Model):
'content': content, 'content': content,
}) })
elif timezone.now() <= tournament.reviews_first_phase_limit + timedelta(hours=2): elif timezone.now() <= tournament.reviews_first_phase_limit + timedelta(hours=2):
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reporter=self) reporter_passage = Passage.objects.get(pool__tournament=tournament, pool__round=1, reporter=self)
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, opponent=self) opponent_passage = Passage.objects.get(pool__tournament=tournament, pool__round=1, opponent=self)
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reviewer=self) reviewer_passage = Passage.objects.get(pool__tournament=tournament, pool__round=1, reviewer=self)
observer_passage = Passage.objects.filter(pool__tournament=self.tournament, pool__round=1, observer=self) observer_passage = Passage.objects.filter(pool__tournament=tournament, pool__round=1, observer=self)
observer_passage = observer_passage.get() if observer_passage.exists() else None observer_passage = observer_passage.get() if observer_passage.exists() else None
reporter_text = _("<p>The solutions draw is ended. You can check the result on " reporter_text = _("<p>The solutions draw is ended. You can check the result on "
@ -997,10 +1001,10 @@ class Participation(models.Model):
'content': content, 'content': content,
}) })
elif timezone.now() <= tournament.reviews_second_phase_limit + timedelta(hours=2): elif timezone.now() <= tournament.reviews_second_phase_limit + timedelta(hours=2):
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reporter=self) reporter_passage = Passage.objects.get(pool__tournament=tournament, pool__round=2, reporter=self)
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, opponent=self) opponent_passage = Passage.objects.get(pool__tournament=tournament, pool__round=2, opponent=self)
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reviewer=self) reviewer_passage = Passage.objects.get(pool__tournament=tournament, pool__round=2, reviewer=self)
observer_passage = Passage.objects.filter(pool__tournament=self.tournament, pool__round=2, observer=self) observer_passage = Passage.objects.filter(pool__tournament=tournament, pool__round=2, observer=self)
observer_passage = observer_passage.get() if observer_passage.exists() else None observer_passage = observer_passage.get() if observer_passage.exists() else None
reporter_text = _("<p>For the second round, you will present " reporter_text = _("<p>For the second round, you will present "
@ -1061,10 +1065,10 @@ class Participation(models.Model):
}) })
elif settings.NB_ROUNDS >= 3 \ elif settings.NB_ROUNDS >= 3 \
and timezone.now() <= tournament.reviews_third_phase_limit + timedelta(hours=2): and timezone.now() <= tournament.reviews_third_phase_limit + timedelta(hours=2):
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reporter=self) reporter_passage = Passage.objects.get(pool__tournament=tournament, pool__round=3, reporter=self)
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, opponent=self) opponent_passage = Passage.objects.get(pool__tournament=tournament, pool__round=3, opponent=self)
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reviewer=self) reviewer_passage = Passage.objects.get(pool__tournament=tournament, pool__round=3, reviewer=self)
observer_passage = Passage.objects.filter(pool__tournament=self.tournament, pool__round=3, observer=self) observer_passage = Passage.objects.filter(pool__tournament=tournament, pool__round=3, observer=self)
observer_passage = observer_passage.get() if observer_passage.exists() else None observer_passage = observer_passage.get() if observer_passage.exists() else None
reporter_text = _("<p>For the third round, you will present " reporter_text = _("<p>For the third round, you will present "

View File

@ -107,11 +107,6 @@ class PoolTable(tables.Table):
class PassageTable(tables.Table): class PassageTable(tables.Table):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not settings.HAS_OBSERVER:
del self.columns['observer']
reporter = tables.LinkColumn( reporter = tables.LinkColumn(
"participation:passage_detail", "participation:passage_detail",
args=[tables.A("id")], args=[tables.A("id")],
@ -135,16 +130,12 @@ class PassageTable(tables.Table):
'class': 'table table-condensed table-striped text-center', 'class': 'table table-condensed table-striped text-center',
} }
model = Passage model = Passage
fields = ('reporter', 'opponent', 'reviewer', 'observer', 'solution_number', ) fields = ('reporter', 'opponent', 'reviewer',) \
+ (('observer',) if settings.HAS_OBSERVER else ()) \
+ ('solution_number', )
class NoteTable(tables.Table): class NoteTable(tables.Table):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not settings.HAS_OBSERVER:
del self.columns['observer_writing']
del self.columns['observer_oral']
jury = tables.Column( jury = tables.Column(
attrs={ attrs={
"td": { "td": {
@ -170,4 +161,6 @@ class NoteTable(tables.Table):
} }
model = Note model = Note
fields = ('jury', 'reporter_writing', 'reporter_oral', 'opponent_writing', 'opponent_oral', fields = ('jury', 'reporter_writing', 'reporter_oral', 'opponent_writing', 'opponent_oral',
'reviewer_writing', 'reviewer_oral', 'observer_writing', 'observer_oral', 'update',) 'reviewer_writing', 'reviewer_oral',) + \
(('observer_writing', 'observer_oral') if settings.HAS_OBSERVER else ()) + \
('update',)

View File

@ -23,45 +23,81 @@
<dd class="col-sm-6">{% if tournament.price %}{{ tournament.price }} €{% else %}{% trans "Free" %}{% endif %}</dd> <dd class="col-sm-6">{% if tournament.price %}{{ tournament.price }} €{% else %}{% trans "Free" %}{% endif %}</dd>
{% endif %} {% endif %}
<dt class="col-sm-6 text-sm-end">{% trans 'remote'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "remote"|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.remote|yesno }}</dd> <dd class="col-sm-6">{{ tournament.remote|yesno }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans 'dates'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "dates"|capfirst %}</dt>
<dd class="col-sm-6">{% trans "From" %} {{ tournament.date_start }} {% trans "to" %} {{ tournament.date_end }}</dd> <dd class="col-sm-6">{% trans "From" %} {{ tournament.date_start }} {% trans "to" %} {{ tournament.date_end }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans 'date of registration closing'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "date of registration closing"|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.inscription_limit }}</dd> <dd class="col-sm-6">{{ tournament.inscription_limit }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal solution submission'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "date of maximal solution submission"|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.solution_limit }}</dd> <dd class="col-sm-6">{{ tournament.solution_limit }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans 'date of the random draw'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "date of the random draw"|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.solutions_draw }}</dd> <dd class="col-sm-6">{{ tournament.solutions_draw }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal written reviews submission for the first round'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "date of maximal written reviews submission for the first round"|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.reviews_first_phase_limit }}</dd> <dd class="col-sm-6">{{ tournament.reviews_first_phase_limit }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal written reviews submission for the second round'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "Solutions available for the second round" %}</dt>
<dd class="col-sm-6">
{{ tournament.solutions_available_second_phase|yesno }}
{% if user.is_authenticated and user.registration in tournament.organizers_and_presidents.all %}
{% now 'Y-m-d' as today %}
{% if not tournament.solutions_available_second_phase %}
{% if today >= tournament.date_first_phase|date:"Y-m-d" %}
<a href="{% url 'participation:tournament_publish_solutions' pk=tournament.pk round=2 %}" class="btn btn-sm btn-info"><i class="fas fa-eye"></i> {% trans "Publish" %}</a>
{% endif %}
{% else %}
{% if today <= tournament.date_second_phase|date:"Y-m-d" %}
<a href="{% url 'participation:tournament_publish_solutions' pk=tournament.pk round=2 %}?hide" class="btn btn-sm bg-danger"><i class="fas fa-eye-slash"></i> {% trans "Unpublish" %}</a>
{% endif %}
{% endif %}
{% endif %}
</dd>
<dt class="col-sm-6 text-sm-end">{% trans "date of maximal written reviews submission for the second round"|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.reviews_second_phase_limit }}</dd> <dd class="col-sm-6">{{ tournament.reviews_second_phase_limit }}</dd>
{% if TFJM.APP == "ETEAM" %} {% if TFJM.NB_ROUNDS == 3 %}
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal written reviews submission for the third round'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "Solutions available for the third round" %}</dt>
<dd class="col-sm-6">
{{ tournament.solutions_available_third_phase|yesno }}
{% if tournament.solutions_available_second_phase and user.is_authenticated and user.registration in tournament.organizers_and_presidents.all %}
{% now 'Y-m-d' as today %}
{% if not tournament.solutions_available_third_phase %}
{% if today >= tournament.date_second_phase|date:"Y-m-d" %}
<a href="{% url 'participation:tournament_publish_solutions' pk=tournament.pk round=3 %}" class="btn btn-sm btn-info"><i class="fas fa-eye"></i> {% trans "Publish" %}</a>
{% endif %}
{% else %}
{% if today <= tournament.date_third_phase|date:"Y-m-d" %}
<a href="{% url 'participation:tournament_publish_solutions' pk=tournament.pk round=3 %}?hide" class="btn btn-sm bg-danger"><i class="fas fa-eye-slash"></i> {% trans "Unpublish" %}</a>
{% endif %}
{% endif %}
{% endif %}
</dd>
<dt class="col-sm-6 text-sm-end">{% trans "date of maximal written reviews submission for the third round"|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.reviews_third_phase_limit }}</dd> <dd class="col-sm-6">{{ tournament.reviews_third_phase_limit }}</dd>
{% endif %} {% endif %}
<dt class="col-sm-6 text-sm-end">{% trans 'description'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "description"|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.description }}</dd> <dd class="col-sm-6">{{ tournament.description }}</dd>
{% if TFJM.ML_MANAGEMENT %} {% if TFJM.ML_MANAGEMENT %}
<dt class="col-sm-6 text-sm-end">{% trans 'To contact organizers' %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "To contact organizers" %}</dt>
<dd class="col-sm-6"><a href="mailto:{{ tournament.organizers_email }}">{{ tournament.organizers_email }}</a></dd> <dd class="col-sm-6"><a href="mailto:{{ tournament.organizers_email }}">{{ tournament.organizers_email }}</a></dd>
<dt class="col-sm-6 text-sm-end">{% trans 'To contact juries' %}</dt> {% if user.is_authenticated and user.registration.is_volunteer %}
<dt class="col-sm-6 text-sm-end">{% trans "To contact juries" %}</dt>
<dd class="col-sm-6"><a href="mailto:{{ tournament.jurys_email }}">{{ tournament.jurys_email }}</a></dd> <dd class="col-sm-6"><a href="mailto:{{ tournament.jurys_email }}">{{ tournament.jurys_email }}</a></dd>
<dt class="col-sm-6 text-sm-end">{% trans 'To contact valid teams' %}</dt> <dt class="col-sm-6 text-sm-end">{% trans "To contact valid teams" %}</dt>
<dd class="col-sm-6"><a href="mailto:{{ tournament.teams_email }}">{{ tournament.teams_email }}</a></dd> <dd class="col-sm-6"><a href="mailto:{{ tournament.teams_email }}">{{ tournament.teams_email }}</a></dd>
{% endif %} {% endif %}
{% endif %}
</dl> </dl>
</div> </div>

View File

@ -12,7 +12,7 @@ from .views import CreateTeamView, FinalNotationSheetTemplateView, GSheetNotific
TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \ TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, TeamUpdateView, \
TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \ TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, TournamentExportCSVView, \
TournamentHarmonizeNoteView, TournamentHarmonizeView, TournamentListView, TournamentPaymentsView, \ TournamentHarmonizeNoteView, TournamentHarmonizeView, TournamentListView, TournamentPaymentsView, \
TournamentPublishNotesView, TournamentUpdateView, WrittenReviewUploadView TournamentPublishNotesView, TournamentPublishSolutionsView, TournamentUpdateView, WrittenReviewUploadView
app_name = "participation" app_name = "participation"
@ -48,6 +48,8 @@ urlpatterns = [
name="tournament_notation_sheets"), name="tournament_notation_sheets"),
path("tournament/<int:pk>/notation/notifications/", GSheetNotificationsView.as_view(), path("tournament/<int:pk>/notation/notifications/", GSheetNotificationsView.as_view(),
name="tournament_gsheet_notifications"), name="tournament_gsheet_notifications"),
path("tournament/<int:pk>/publish-solutions/<int:round>/", TournamentPublishSolutionsView.as_view(),
name="tournament_publish_solutions"),
path("tournament/<int:pk>/publish-notes/<int:round>/", TournamentPublishNotesView.as_view(), path("tournament/<int:pk>/publish-notes/<int:round>/", TournamentPublishNotesView.as_view(),
name="tournament_publish_notes"), name="tournament_publish_notes"),
path("tournament/<int:pk>/harmonize/<int:round>/", TournamentHarmonizeView.as_view(), path("tournament/<int:pk>/harmonize/<int:round>/", TournamentHarmonizeView.as_view(),

View File

@ -672,7 +672,7 @@ class TournamentPaymentsView(VolunteerMixin, SingleTableMixin, DetailView):
if self.object.final: if self.object.final:
payments = Payment.objects.filter(final=True) payments = Payment.objects.filter(final=True)
else: else:
payments = Payment.objects.filter(registrations__team__participation__tournament=self.get_object()) payments = Payment.objects.filter(registrations__team__participation__tournament=self.get_object(), final=False)
return payments.annotate(team_id=F('registrations__team')).order_by('-valid', 'registrations__team__trigram') \ return payments.annotate(team_id=F('registrations__team')).order_by('-valid', 'registrations__team__trigram') \
.distinct().all() .distinct().all()
@ -747,12 +747,12 @@ class TournamentPublishNotesView(VolunteerMixin, SingleObjectMixin, RedirectView
return self.handle_no_permission() return self.handle_no_permission()
tournament = self.get_object() tournament = self.get_object()
reg = request.user.registration reg = request.user.registration
if not reg.is_admin and (not reg.is_volunteer or tournament not in reg.organized_tournaments.all()): if not reg.is_volunteer or reg not in tournament.organizers_and_presidents.all():
return self.handle_no_permission() return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if int(kwargs["round"]) not in (1, 2): if int(kwargs["round"]) not in range(1, settings.NB_ROUNDS + 1):
raise Http404 raise Http404
tournament = Tournament.objects.get(pk=kwargs["pk"]) tournament = Tournament.objects.get(pk=kwargs["pk"])
@ -767,6 +767,45 @@ class TournamentPublishNotesView(VolunteerMixin, SingleObjectMixin, RedirectView
return reverse_lazy("participation:tournament_detail", args=(kwargs['pk'],)) return reverse_lazy("participation:tournament_detail", args=(kwargs['pk'],))
class TournamentPublishSolutionsView(VolunteerMixin, SingleObjectMixin, RedirectView):
"""
On rend les solutions du tour suivant accessibles aux équipes.
"""
model = Tournament
def dispatch(self, request, *args, **kwargs):
"""
Les admins, orgas et PJ peuvent rendre les solutions accessibles.
"""
if not request.user.is_authenticated:
return self.handle_no_permission()
tournament = self.get_object()
reg = request.user.registration
if not reg.is_volunteer or reg not in tournament.organizers_and_presidents.all():
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
if int(kwargs["round"]) not in range(2, settings.NB_ROUNDS + 1):
raise Http404
tournament = Tournament.objects.get(pk=kwargs["pk"])
publish_solutions = 'hide' not in request.GET
if int(kwargs['round']) == 2:
tournament.solutions_available_second_phase = publish_solutions
elif int(kwargs['round']) == 3:
tournament.solutions_available_third_phase = publish_solutions
tournament.save()
if 'hide' not in request.GET:
messages.success(request, _("Solutions are now available to teams!"))
else:
messages.warning(request, _("Solutions are not available to teams anymore."))
return super().get(request, *args, **kwargs)
def get_redirect_url(self, *args, **kwargs):
return reverse_lazy("participation:tournament_detail", args=(kwargs['pk'],))
class TournamentHarmonizeView(VolunteerMixin, DetailView): class TournamentHarmonizeView(VolunteerMixin, DetailView):
""" """
Harmonize the notes of a tournament. Harmonize the notes of a tournament.
@ -779,7 +818,7 @@ class TournamentHarmonizeView(VolunteerMixin, DetailView):
return self.handle_no_permission() return self.handle_no_permission()
tournament = self.get_object() tournament = self.get_object()
reg = request.user.registration reg = request.user.registration
if not reg.is_admin and (not reg.is_volunteer or tournament not in reg.organized_tournaments.all()): if not reg.is_volunteer or reg not in tournament.organizers_and_presidents.all():
return self.handle_no_permission() return self.handle_no_permission()
if self.kwargs['round'] not in range(1, settings.NB_ROUNDS + 1): if self.kwargs['round'] not in range(1, settings.NB_ROUNDS + 1):
raise Http404 raise Http404
@ -812,7 +851,7 @@ class TournamentHarmonizeNoteView(VolunteerMixin, DetailView):
return self.handle_no_permission() return self.handle_no_permission()
tournament = self.get_object() tournament = self.get_object()
reg = request.user.registration reg = request.user.registration
if not reg.is_admin and (not reg.is_volunteer or tournament not in reg.organized_tournaments.all()): if not reg.is_volunteer or reg not in tournament.organizers_and_presidents.all():
return self.handle_no_permission() return self.handle_no_permission()
if self.kwargs['round'] not in range(1, settings.NB_ROUNDS + 1) \ if self.kwargs['round'] not in range(1, settings.NB_ROUNDS + 1) \
or self.kwargs['action'] not in ('add', 'remove') \ or self.kwargs['action'] not in ('add', 'remove') \
@ -852,7 +891,7 @@ class SelectTeamFinalView(VolunteerMixin, DetailView):
return self.handle_no_permission() return self.handle_no_permission()
tournament = self.get_object() tournament = self.get_object()
reg = request.user.registration reg = request.user.registration
if not reg.is_admin and (not reg.is_volunteer or tournament not in reg.organized_tournaments.all()): if not reg.is_volunteer or reg not in tournament.organizers_and_presidents.all():
return self.handle_no_permission() return self.handle_no_permission()
participation_qs = tournament.participations.filter(pk=self.kwargs["participation_id"]) participation_qs = tournament.participations.filter(pk=self.kwargs["participation_id"])
if not participation_qs.exists(): if not participation_qs.exists():
@ -1003,17 +1042,14 @@ class SolutionsDownloadView(VolunteerMixin, View):
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
elif 'tournament_id' in kwargs: elif 'tournament_id' in kwargs:
tournament = Tournament.objects.get(pk=kwargs["tournament_id"]) tournament = Tournament.objects.get(pk=kwargs["tournament_id"])
if reg.is_volunteer \ if reg.is_volunteer and reg in tournament.organizers_and_presidents.all():
and (tournament in reg.organized_tournaments.all()
or reg.pools_presided.filter(tournament=tournament).exists()):
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
else: else:
pool = Pool.objects.get(pk=kwargs["pool_id"]) pool = Pool.objects.get(pk=kwargs["pool_id"])
tournament = pool.tournament tournament = pool.tournament
if reg.is_volunteer \ if reg.is_volunteer \
and (reg in tournament.organizers.all() and (reg in tournament.organizers_and_presidents.all()
or reg in pool.juries.all() or reg in pool.juries.all()):
or reg.pools_presided.filter(tournament=tournament).exists()):
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
return self.handle_no_permission() return self.handle_no_permission()
@ -2001,7 +2037,7 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
reg = request.user.registration reg = request.user.registration
passage = self.get_object() passage = self.get_object()
if reg.is_admin or reg.is_volunteer \ if reg.is_admin or reg.is_volunteer \
and (self.get_object().pool.tournament in reg.organized_tournaments.all() and (reg in self.get_object().pool.tournament.organizers_and_presidents.all()
or reg in passage.pool.juries.all() or reg in passage.pool.juries.all()
or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \ or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \
or reg.participates and reg.team \ or reg.participates and reg.team \

View File

@ -1,3 +0,0 @@
{{ object.user.last_name }}
{{ object.user.first_name }}
{{ object.user.email }}

View File

@ -213,6 +213,7 @@ STATICFILES_FINDERS = (
PIPELINE = { PIPELINE = {
'DISABLE_WRAPPER': True, 'DISABLE_WRAPPER': True,
'JS_COMPRESSOR': 'pipeline.compressors.uglifyjs.UglifyJSCompressor',
'JAVASCRIPT': { 'JAVASCRIPT': {
'main': { 'main': {
'source_filenames': ( 'source_filenames': (

View File

@ -23,7 +23,7 @@
</div> </div>
<div id="sidebar-card" class="collapse d-lg-block"> <div id="sidebar-card" class="collapse d-lg-block">
<div class="card-body"> <div class="card-body px-2 py-1">
{% for information in user.registration.important_informations %} {% for information in user.registration.important_informations %}
<div class="card my-2"> <div class="card my-2">
<div class="card-header bg-dark-subtle"> <div class="card-header bg-dark-subtle">