diff --git a/chat/static/tfjm/chat_eteam.webmanifest b/chat/static/tfjm/chat_eteam.webmanifest new file mode 100644 index 0000000..3b84c64 --- /dev/null +++ b/chat/static/tfjm/chat_eteam.webmanifest @@ -0,0 +1,17 @@ +{ + "background_color": "white", + "description": "Chat for ETEAM", + "display": "standalone", + "icons": [ + { + "src": "/static/tfjm/img/eteam.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "name": "ETEAM Chat", + "short_name": "ETEAM Chat", + "start_url": "/chat/fullscreen", + "theme_color": "black" +} diff --git a/chat/static/tfjm/chat.webmanifest b/chat/static/tfjm/chat_tfjm.webmanifest similarity index 100% rename from chat/static/tfjm/chat.webmanifest rename to chat/static/tfjm/chat_tfjm.webmanifest diff --git a/chat/templates/chat/chat.html b/chat/templates/chat/chat.html index 5588aab..e556ce0 100644 --- a/chat/templates/chat/chat.html +++ b/chat/templates/chat/chat.html @@ -6,7 +6,11 @@ {% block extracss %} {# Webmanifest PWA permettant l'installation de l'application sur un écran d'accueil, pour navigateurs supportés #} - + {% if TFJM.APP == "TFJM" %} + + {% elif TFJM.APP == "ETEAM" %} + + {% endif %} {% endblock %} {% block content-title %}{% endblock %} diff --git a/chat/templates/chat/fullscreen.html b/chat/templates/chat/fullscreen.html index e82a4e8..3a5cf0c 100644 --- a/chat/templates/chat/fullscreen.html +++ b/chat/templates/chat/fullscreen.html @@ -6,10 +6,13 @@ - - {% trans "TFJM² Chat" %} - - + {% if TFJM.APP == "TFJM" %} + {% trans "TFJM² Chat" %} + + {% elif TFJM.APP == "ETEAM" %} + {% trans "ETEAM Chat" %} + + {% endif %} {# Favicon #} @@ -27,7 +30,11 @@ {# Webmanifest PWA permettant l'installation de l'application sur un écran d'accueil, pour navigateurs supportés #} - + {% if TFJM.APP == "TFJM" %} + + {% elif TFJM.APP == "ETEAM" %} + + {% endif %} {% include "chat/content.html" with fullscreen=True %} diff --git a/chat/templates/chat/login.html b/chat/templates/chat/login.html index 377fee7..688be94 100644 --- a/chat/templates/chat/login.html +++ b/chat/templates/chat/login.html @@ -7,9 +7,9 @@ - {% trans "TFJM² Chat" %} - {% trans "Log in" %} + {% trans "Chat" %} - {% trans "Log in" %} - + {# Favicon #} @@ -25,7 +25,11 @@ {# Webmanifest PWA permettant l'installation de l'application sur un écran d'accueil, pour navigateurs supportés #} - + {% if TFJM.APP == "TFJM" %} + + {% elif TFJM.APP == "ETEAM" %} + + {% endif %}
diff --git a/draw/consumers.py b/draw/consumers.py index 9e7a398..828fd36 100644 --- a/draw/consumers.py +++ b/draw/consumers.py @@ -417,7 +417,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer): return error - async def process_dice_select_poules(self): + async def process_dice_select_poules(self): # noqa: C901 """ Called when all teams launched their dice. Place teams into pools and order their passage. diff --git a/participation/forms.py b/participation/forms.py index b14e1e1..dd4edee 100644 --- a/participation/forms.py +++ b/participation/forms.py @@ -111,7 +111,7 @@ class RequestValidationForm(forms.Form): ) engagement = forms.BooleanField( - label=_("I engage myself to participate to the whole TFJM²."), + label=_("I engage myself to participate to the whole tournament."), required=True, ) diff --git a/participation/models.py b/participation/models.py index 64d77d8..66022de 100644 --- a/participation/models.py +++ b/participation/models.py @@ -1,7 +1,8 @@ # Copyright (C) 2020 by Animath # SPDX-License-Identifier: GPL-3.0-or-later -import math + from datetime import date, timedelta +import math import os from django.conf import settings @@ -27,7 +28,7 @@ def get_motivation_letter_filename(instance, filename): class Team(models.Model): """ - The Team model represents a real team that participates to the TFJM². + The Team model represents a real team that participates to the tournament. This only includes the registration detail. """ name = models.CharField( diff --git a/participation/templates/participation/mails/team_validated.html b/participation/templates/participation/mails/team_validated.html index d929270..025c64e 100644 --- a/participation/templates/participation/mails/team_validated.html +++ b/participation/templates/participation/mails/team_validated.html @@ -15,10 +15,10 @@ {% if payment %}

- You must now pay your participation fee of € {{ team.participation.amount }}. + You must now pay your participation fee of € {{ payment.amount }}. You can pay by credit card or bank transfer. You'll find information on the payment page which you can find on - . + your account. If you have a scholarship, registration is free, but you must submit a justification on the same page.

{% elif registration.is_coach and team.participation.tournament.price %} diff --git a/participation/templates/participation/mails/team_validated.txt b/participation/templates/participation/mails/team_validated.txt index 46991d0..98b1814 100644 --- a/participation/templates/participation/mails/team_validated.txt +++ b/participation/templates/participation/mails/team_validated.txt @@ -2,8 +2,8 @@ Hello {{registration }}, Congratulations! Your team "{{ team.name }}" ({{ team.trigram }}) is now validated! You are now ready to to work on your problems. You can then upload your solutions to the platform. -{% if team.participation.amount %} -You must now pay your participation fee of € {{ team.participation.amount }}. +{% if payment %} +You must now pay your participation fee of € {{ payment.amount }}. You can pay by credit card or bank transfer. You'll find information on the payment page which you can find on your account: https://{{ domain }}{% url 'registration:my_account_detail' %} diff --git a/participation/views.py b/participation/views.py index 8834e2d..21d9079 100644 --- a/participation/views.py +++ b/participation/views.py @@ -231,7 +231,7 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView) mail_context = dict(team=self.object, domain=Site.objects.first().domain) mail_plain = render_to_string("participation/mails/request_validation.txt", mail_context) mail_html = render_to_string("participation/mails/request_validation.html", mail_context) - send_mail("[TFJM²] Validation d'équipe", mail_plain, settings.DEFAULT_FROM_EMAIL, + send_mail(f"[{settings.APP_NAME}] {_('Team validation')}", mail_plain, settings.DEFAULT_FROM_EMAIL, [self.object.participation.tournament.organizers_email], html_message=mail_html) return super().form_valid(form) @@ -255,7 +255,8 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView) domain = Site.objects.first().domain for registration in self.object.participants.all(): - if registration.is_student and self.object.participation.tournament.price: + if settings.PAYMENT_MANAGEMENT and \ + registration.is_student and self.object.participation.tournament.price: payment = Payment.objects.get(registrations=registration, final=False) else: payment = None @@ -265,7 +266,8 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView) message=form.cleaned_data["message"].replace('\n', '
')) mail_plain = render_to_string("participation/mails/team_validated.txt", mail_context_plain) mail_html = render_to_string("participation/mails/team_validated.html", mail_context_html) - registration.user.email_user("[TFJM²] Équipe validée", mail_plain, html_message=mail_html) + registration.user.email_user(f"[{settings.APP_NAME}] {_('Team validated')}", mail_plain, + html_message=mail_html) elif "invalidate" in self.request.POST: self.object.participation.valid = None self.object.participation.save() @@ -273,8 +275,8 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView) mail_context_html = dict(team=self.object, message=form.cleaned_data["message"].replace('\n', '
')) mail_plain = render_to_string("participation/mails/team_not_validated.txt", mail_context_plain) mail_html = render_to_string("participation/mails/team_not_validated.html", mail_context_html) - send_mail("[TFJM²] Équipe non validée", mail_plain, None, [self.object.email], - html_message=mail_html) + send_mail(f"[{settings.APP_NAME}] {_('Team not validated')}", mail_plain, + None, [self.object.email], html_message=mail_html) else: form.add_error(None, _("You must specify if you validate the registration or not.")) return self.form_invalid(form) @@ -1135,7 +1137,7 @@ class PoolJuryView(VolunteerMixin, FormView, DetailView): user.save() # Send welcome mail - subject = "[TFJM²] " + str(_("New TFJM² jury account")) + subject = f"[{settings.APP_NAME}] " + str(_("New jury account")) site = Site.objects.first() message = render_to_string('registration/mails/add_organizer.txt', dict(user=user, inviter=self.request.user, diff --git a/registration/models.py b/registration/models.py index b57f9e3..d16e197 100644 --- a/registration/models.py +++ b/registration/models.py @@ -50,7 +50,7 @@ class Registration(PolymorphicModel): The account got created or the email got changed. Send an email that contains a link to validate the address. """ - subject = "[TFJM²] " + str(_("Activate your TFJM² account")) + subject = f"[{settings.APP_NAME}] " + str(_("Activate your account")) token = email_validation_token.make_token(self.user) uid = urlsafe_base64_encode(force_bytes(self.user.pk)) site = Site.objects.first() @@ -309,7 +309,7 @@ class ParticipantRegistration(Registration): The team is selected for final. """ translation.activate(settings.PREFERRED_LANGUAGE_CODE) - subject = "[TFJM²] " + str(_("Team selected for the final tournament")) + subject = f"[{settings.APP_NAME}] " + str(_("Team selected for the final tournament")) site = Site.objects.first() from participation.models import Tournament tournament = Tournament.final_tournament() @@ -803,7 +803,7 @@ class Payment(models.Model): def send_remind_mail(self): translation.activate(settings.PREFERRED_LANGUAGE_CODE) - subject = "[TFJM²] " + str(_("Reminder for your payment")) + subject = f"[{settings.APP_NAME}] " + str(_("Reminder for your payment")) site = Site.objects.first() for registration in self.registrations.all(): message = loader.render_to_string('registration/mails/payment_reminder.txt', @@ -814,7 +814,7 @@ class Payment(models.Model): def send_helloasso_payment_confirmation_mail(self): translation.activate(settings.PREFERRED_LANGUAGE_CODE) - subject = "[TFJM²] " + str(_("Payment confirmation")) + subject = f"[{settings.APP_NAME}] " + str(_("Payment confirmation")) site = Site.objects.first() for registration in self.registrations.all(): message = loader.render_to_string('registration/mails/payment_confirmation.txt', diff --git a/registration/templates/registration/mails/final_selection.html b/registration/templates/registration/mails/final_selection.html new file mode 100644 index 0000000..a71bd4f --- /dev/null +++ b/registration/templates/registration/mails/final_selection.html @@ -0,0 +1,75 @@ + + + + + + + +

+ Bonjour {{ user.registration }}, +

+ +

+ Félicitations ! Votre équipe {{ user.registration.team.name }} ({{ user.registration.team.trigram }}) + est sélectionnée pour le tournoi final du TFJM² ! +

+ +

+ La finale aura lieu du {{ tournament.date_start|date:"d/m/Y" }} au {{ tournament.date_end|date:"d/m/Y" }} + à : {{ tournament.place }}. + Les organisateurices de la finale vous recontacteront pour plus de détails. +

+ +

+ D'ores-et-déjà, vous pouvez soumettre votre autorisation de droit à l'image spécifique à la finale sur votre espace personnel : + + https://{{ domain }}{% url 'registration:user_detail' pk=user.pk %} + . + {% if user.registration.is_student and user.registration.under_18_final %} + Vous pouvez également transmettre puisque vous êtes mineur⋅e votre autorisation parentale spécifique pour la finale sur la même page. + {% endif %} +

+ +

+ {% if tournament.price > 0 %} + {% if user.registration.is_student %} + {% if payment.type == "scholarship" %} + Votre statut de boursièr⋅e déjà enregistré vous exempte à nouveau des frais de participation de la finale. + {% else %} + Vous devez régler les frais de participation à la finale de {{ tournament.price }} €. + Rendez-vous pour cela sur la page du paiement : + + https://{{ domain }}{% url 'registration:update_payment' pk=payment.pk %} + . + {% endif %} + {% else %} + En tant qu'encadrant⋅e, vous n'avez toujours rien à payer, mais veillez bien à ce que les membres de votre équipe + règlent les frais de participation à la finale de {{ tournament.price }} €. + {% endif %} + {% endif %} +

+ +

+ Conformément au règlement du TFJM², vous pouvez soumettre de nouvelles versions de vos solutions, + pour améliorer vos explications, corriger des erreurs mineures ou la mise en page, ou supprimer + des éléments faux, mais il vous est en revanche interdit d'ajouter des résultats ou des preuves + ou de corriger des erreurs majeures. +

+ +

+ Pour mettre à jour vos solutions, rendez-vous sur la page de votre équipe : + + https://{{ domain }}{% url 'participation:participation_detail' pk=user.registration.team.participation.pk %} + . +

+ +

+ Cordialement, +

+ +-- +

+ L'équipe du TFJM² +

+ + diff --git a/registration/templates/registration/mails/final_selection.txt b/registration/templates/registration/mails/final_selection.txt new file mode 100644 index 0000000..364c736 --- /dev/null +++ b/registration/templates/registration/mails/final_selection.txt @@ -0,0 +1,38 @@ +Bonjour {{ user.registration }}, + +Félicitations ! Votre équipe {{ user.registration.team.name }} ({{ user.registration.team.trigram }}) est sélectionnée pour le tournoi final du TFJM² ! + +La finale aura lieu du {{ tournament.date_start|date:"d/m/Y" }} au {{ tournament.date_end|date:"d/m/Y" }} à : {{ tournament.place }}. +Les organisateurices de la finale vous recontacteront pour plus de détails. + +D'ores-et-déjà, vous pouvez soumettre votre autorisation de droit à l'image spécifique à la finale sur votre espace personnel : +https://{{ domain }}{% url 'registration:user_detail' pk=user.pk %} +{% if user.registration.is_student and user.registration.under_18_final %} +Vous pouvez également transmettre puisque vous êtes mineur⋅e votre autorisation parentale spécifique pour la finale sur la même page. +{% endif %} +{% if tournament.price > 0 %} +{% if user.registration.is_student %} +{% if payment.type == "scholarship" %} +Votre statut de boursièr⋅e déjà enregistré vous exempte à nouveau des frais de participation de la finale. +{% else %} +Vous devez régler les frais de participation à la finale de {{ tournament.price }} €. +Rendez-vous pour cela sur la page du paiement : +https://{{ domain }}{% url 'registration:update_payment' pk=payment.pk %} +{% endif %} +{% else %} +En tant qu'encadrant⋅e, vous n'avez toujours rien à payer, mais veillez bien à ce que les membres de votre équipe +règlent les frais de participation à la finale de {{ tournament.price }} €. +{% endif %} +{% endif %} +Conformément au règlement du TFJM², vous pouvez soumettre de nouvelles versions de vos solutions, +pour améliorer vos explications, corriger des erreurs mineures ou la mise en page, ou supprimer +des éléments faux, mais il vous est en revanche interdit d'ajouter des résultats ou des preuves +ou de corriger des erreurs majeures. + +Pour mettre à jour vos solutions, rendez-vous sur la page de votre équipe : +https://{{ domain }}{% url 'participation:participation_detail' pk=user.registration.team.participation.pk %} + +Cordialement, + +-- +L'équipe du TFJM² diff --git a/registration/views.py b/registration/views.py index 9d1a7d7..843809d 100644 --- a/registration/views.py +++ b/registration/views.py @@ -18,7 +18,7 @@ from django.http import FileResponse, Http404 from django.shortcuts import redirect, resolve_url from django.template.loader import render_to_string from django.urls import reverse_lazy -from django.utils import timezone, translation +from django.utils import translation from django.utils.crypto import get_random_string from django.utils.http import urlsafe_base64_decode from django.utils.text import format_lazy @@ -121,7 +121,7 @@ class AddOrganizerView(VolunteerMixin, CreateView): form.instance.set_password(password) form.instance.save() - subject = "[TFJM²] " + str(_("New TFJM² organizer account")) + subject = f"[{settings.APP_NAME}] " + str(_("New organizer account")) site = Site.objects.first() message = render_to_string('registration/mails/add_organizer.txt', dict(user=registration.user, inviter=self.request.user, diff --git a/tfjm/context_processors.py b/tfjm/context_processors.py index 29a0ae7..2bb128e 100644 --- a/tfjm/context_processors.py +++ b/tfjm/context_processors.py @@ -1,5 +1,7 @@ -from django.conf import settings +# Copyright (C) 2024 by Animath +# SPDX-License-Identifier: GPL-3.0-or-later +from django.conf import settings from participation.models import Tournament @@ -7,6 +9,7 @@ def tfjm_context(request): return { 'TFJM': { 'APP': settings.TFJM_APP, + 'APP_NAME': settings.APP_NAME, 'ML_MANAGEMENT': settings.ML_MANAGEMENT, 'PAYMENT_MANAGEMENT': settings.PAYMENT_MANAGEMENT, 'SINGLE_TOURNAMENT': diff --git a/tfjm/settings.py b/tfjm/settings.py index ca50624..af28623 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -347,6 +347,7 @@ except ImportError: if TFJM_APP == "TFJM": PREFERRED_LANGUAGE_CODE = 'fr' + APP_NAME = "TFJM²" TEAM_CODE_LENGTH = 3 RECOMMENDED_SOLUTIONS_COUNT = 5 NB_ROUNDS = 2 @@ -369,6 +370,7 @@ if TFJM_APP == "TFJM": ] elif TFJM_APP == "ETEAM": PREFERRED_LANGUAGE_CODE = 'en' + APP_NAME = "TFJM²" TEAM_CODE_LENGTH = 4 RECOMMENDED_SOLUTIONS_COUNT = 6 NB_ROUNDS = 3 diff --git a/tfjm/templates/base.html b/tfjm/templates/base.html index cb90406..4096641 100644 --- a/tfjm/templates/base.html +++ b/tfjm/templates/base.html @@ -9,11 +9,13 @@ - {# TODO ETEAM Plus d'uniformité #} - {% block title %}{{ title }}{% endblock title %} - {% trans "ETEAM Platform" %} + {% block title %}{{ title }}{% endblock title %} - {{ TFJM.APP_NAME }} - {# TODO ETEAM Plus d'uniformité #} - + {% if TFJM.APP == "TFJM" %} + + {% elif TFJM.APP == "ETEAM" %} + + {% endif %} {# Favicon #} diff --git a/tox.ini b/tox.ini index d511867..521eccb 100644 --- a/tox.ini +++ b/tox.ini @@ -26,7 +26,7 @@ deps = pep8-naming pyflakes commands = - flake8 api/ chat/ss draw/ logs/ participation/ registration/ tfjm/ + flake8 api/ chat/ draw/ logs/ participation/ registration/ tfjm/ [flake8] exclude =