mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-06-25 00:20:31 +02:00
Compare commits
9 Commits
60f5236dee
...
dev
Author | SHA1 | Date | |
---|---|---|---|
8aec72d712
|
|||
6a521b6121
|
|||
62abfa94d6
|
|||
952315ea4d
|
|||
2e613799c9
|
|||
08805a6360
|
|||
6841659e41
|
|||
a84ffcf0a3
|
|||
203fc3cd54
|
@ -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
@ -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():
|
||||||
|
@ -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 "
|
||||||
|
@ -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',)
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
|
@ -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 \
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
{{ object.user.last_name }}
|
|
||||||
{{ object.user.first_name }}
|
|
||||||
{{ object.user.email }}
|
|
@ -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': (
|
||||||
|
@ -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">
|
||||||
|
Reference in New Issue
Block a user