mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-05-18 04:52:45 +00:00
Compare commits
3 Commits
6fa3a08a72
...
4f129280c3
Author | SHA1 | Date | |
---|---|---|---|
|
4f129280c3 | ||
|
d2c1a826a8 | ||
|
0b9079b431 |
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TFJM\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-03-24 11:26+0100\n"
|
||||
"POT-Creation-Date: 2024-03-24 18:13+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -214,17 +214,17 @@ msgid "Pool {letter}{number}"
|
||||
msgstr "Poule {letter}{number}"
|
||||
|
||||
#: draw/models.py:408 draw/models.py:435 participation/admin.py:136
|
||||
#: participation/admin.py:155 participation/models.py:583
|
||||
#: participation/models.py:592 participation/tables.py:84
|
||||
#: participation/admin.py:155 participation/models.py:597
|
||||
#: participation/models.py:606 participation/tables.py:84
|
||||
msgid "pool"
|
||||
msgstr "poule"
|
||||
|
||||
#: draw/models.py:409 participation/models.py:584
|
||||
#: draw/models.py:409 participation/models.py:598
|
||||
msgid "pools"
|
||||
msgstr "poules"
|
||||
|
||||
#: draw/models.py:421 participation/models.py:503 participation/models.py:753
|
||||
#: participation/models.py:783 participation/models.py:821
|
||||
#: draw/models.py:421 participation/models.py:503 participation/models.py:767
|
||||
#: participation/models.py:797 participation/models.py:839
|
||||
msgid "participation"
|
||||
msgstr "participation"
|
||||
|
||||
@ -248,8 +248,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"L'ordre de choix dans la poule, entre 0 et la taille de la poule moins 1."
|
||||
|
||||
#: draw/models.py:458 draw/models.py:481 participation/models.py:606
|
||||
#: participation/models.py:790
|
||||
#: draw/models.py:458 draw/models.py:481 participation/models.py:620
|
||||
#: participation/models.py:804
|
||||
#, python-brace-format
|
||||
msgid "Problem #{problem}"
|
||||
msgstr "Problème n°{problem}"
|
||||
@ -377,8 +377,8 @@ msgstr "Êtes-vous sûr·e de vouloir annuler le tirage au sort ?"
|
||||
msgid "Close"
|
||||
msgstr "Fermer"
|
||||
|
||||
#: draw/views.py:31 participation/views.py:155 participation/views.py:441
|
||||
#: participation/views.py:472
|
||||
#: draw/views.py:31 participation/views.py:156 participation/views.py:442
|
||||
#: participation/views.py:473
|
||||
msgid "You are not in a team."
|
||||
msgstr "Vous n'êtes pas dans une équipe."
|
||||
|
||||
@ -456,21 +456,21 @@ msgid "selected for final"
|
||||
msgstr "sélectionnée pour la finale"
|
||||
|
||||
#: participation/admin.py:124 participation/admin.py:183
|
||||
#: participation/models.py:613 participation/tables.py:112
|
||||
#: participation/models.py:627 participation/tables.py:112
|
||||
msgid "defender"
|
||||
msgstr "défenseur⋅se"
|
||||
|
||||
#: participation/admin.py:128 participation/models.py:620
|
||||
#: participation/models.py:833
|
||||
#: participation/admin.py:128 participation/models.py:634
|
||||
#: participation/models.py:851
|
||||
msgid "opponent"
|
||||
msgstr "opposant⋅e"
|
||||
|
||||
#: participation/admin.py:132 participation/models.py:627
|
||||
#: participation/models.py:834
|
||||
#: participation/admin.py:132 participation/models.py:641
|
||||
#: participation/models.py:852
|
||||
msgid "reporter"
|
||||
msgstr "rapporteur⋅e"
|
||||
|
||||
#: participation/admin.py:187 participation/models.py:788
|
||||
#: participation/admin.py:187 participation/models.py:802
|
||||
msgid "problem"
|
||||
msgstr "numéro de problème"
|
||||
|
||||
@ -490,11 +490,11 @@ msgstr "Ce trigramme est déjà utilisé."
|
||||
msgid "No team was found with this access code."
|
||||
msgstr "Aucune équipe n'a été trouvée avec ce code d'accès."
|
||||
|
||||
#: participation/forms.py:60 participation/views.py:443
|
||||
#: participation/forms.py:60 participation/views.py:444
|
||||
msgid "The team is already validated or the validation is pending."
|
||||
msgstr "La validation de l'équipe est déjà faite ou en cours."
|
||||
|
||||
#: participation/forms.py:89 participation/forms.py:359
|
||||
#: participation/forms.py:89 participation/forms.py:364
|
||||
#: registration/forms.py:122 registration/forms.py:144
|
||||
#: registration/forms.py:166 registration/forms.py:188
|
||||
#: registration/forms.py:237 registration/forms.py:270
|
||||
@ -520,7 +520,7 @@ msgstr "Message à adresser à l'équipe :"
|
||||
msgid "The uploaded file size must be under 5 Mo."
|
||||
msgstr "Le fichier envoyé doit peser moins de 5 Mo."
|
||||
|
||||
#: participation/forms.py:161 participation/forms.py:361
|
||||
#: participation/forms.py:161 participation/forms.py:366
|
||||
msgid "The uploaded file must be a PDF file."
|
||||
msgstr "Le fichier envoyé doit être au format PDF."
|
||||
|
||||
@ -528,21 +528,21 @@ msgstr "Le fichier envoyé doit être au format PDF."
|
||||
msgid "The PDF file must not have more than 30 pages."
|
||||
msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages."
|
||||
|
||||
#: participation/forms.py:232
|
||||
#: participation/forms.py:237
|
||||
#: participation/templates/participation/pool_detail.html:123
|
||||
#: participation/templates/participation/tournament_detail.html:119
|
||||
#: participation/templates/participation/tournament_detail.html:139
|
||||
msgid "Add"
|
||||
msgstr "Ajouter"
|
||||
|
||||
#: participation/forms.py:247
|
||||
#: participation/forms.py:252
|
||||
msgid "This user already exists, but is a participant."
|
||||
msgstr "Cet⋅te utilisateur⋅rice existe déjà, mais en tant que participant⋅e."
|
||||
|
||||
#: participation/forms.py:258
|
||||
#: participation/forms.py:263
|
||||
msgid "CSV file:"
|
||||
msgstr "Tableur au format CSV :"
|
||||
|
||||
#: participation/forms.py:282
|
||||
#: participation/forms.py:287
|
||||
msgid ""
|
||||
"This file contains non-UTF-8 and non-ISO-8859-1 content. Please send your "
|
||||
"sheet as a CSV file."
|
||||
@ -550,30 +550,30 @@ msgstr ""
|
||||
"Ce fichier contient des éléments non-UTF-8 et non-ISO-8859-1. Merci "
|
||||
"d'envoyer votre tableur au format CSV."
|
||||
|
||||
#: participation/forms.py:297
|
||||
#: participation/forms.py:302
|
||||
msgid "Can't determine the pool size. Are you sure your file is correct?"
|
||||
msgstr ""
|
||||
"Impossible de déterminer la taille de la poule. Êtes-vous sûr⋅e que le "
|
||||
"fichier est correct ?"
|
||||
|
||||
#: participation/forms.py:317
|
||||
#: participation/forms.py:322
|
||||
msgid "The following note is higher of the maximum expected value:"
|
||||
msgstr "La note suivante est supérieure au maximum attendu :"
|
||||
|
||||
#: participation/forms.py:325
|
||||
#: participation/forms.py:330
|
||||
msgid "The following user was not found:"
|
||||
msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :"
|
||||
|
||||
#: participation/forms.py:342
|
||||
#: participation/forms.py:347
|
||||
msgid "The defender, the opponent and the reporter must be different."
|
||||
msgstr ""
|
||||
"Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es."
|
||||
|
||||
#: participation/forms.py:346
|
||||
#: participation/forms.py:351
|
||||
msgid "This defender did not work on this problem."
|
||||
msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème."
|
||||
|
||||
#: participation/forms.py:365
|
||||
#: participation/forms.py:370
|
||||
msgid "The PDF file must not have more than 2 pages."
|
||||
msgstr "Le fichier PDF ne doit pas avoir plus de 2 pages."
|
||||
|
||||
@ -864,19 +864,23 @@ msgstr "Tour {round}"
|
||||
msgid "juries"
|
||||
msgstr "jurys"
|
||||
|
||||
#: participation/models.py:550
|
||||
#: participation/models.py:552
|
||||
msgid "president of the jury"
|
||||
msgstr "président⋅e du jury"
|
||||
|
||||
#: participation/models.py:559
|
||||
msgid "BigBlueButton URL"
|
||||
msgstr "Lien BigBlueButton"
|
||||
|
||||
#: participation/models.py:551
|
||||
#: participation/models.py:560
|
||||
msgid "The link of the BBB visio for this pool."
|
||||
msgstr "Le lien du salon BBB pour cette poule."
|
||||
|
||||
#: participation/models.py:556
|
||||
#: participation/models.py:565
|
||||
msgid "results available"
|
||||
msgstr "résultats disponibles"
|
||||
|
||||
#: participation/models.py:557
|
||||
#: participation/models.py:566
|
||||
msgid ""
|
||||
"Check this case when results become accessible to teams. They stay "
|
||||
"accessible to you. Only averages are given."
|
||||
@ -885,28 +889,32 @@ msgstr ""
|
||||
"Ils restent toujours accessibles pour vous. Seules les moyennes sont "
|
||||
"communiquées."
|
||||
|
||||
#: participation/models.py:577
|
||||
#: participation/models.py:587
|
||||
msgid "The president of the jury must be part of the jury."
|
||||
msgstr "Læ président⋅e du jury doit faire partie du jury."
|
||||
|
||||
#: participation/models.py:591
|
||||
#, python-brace-format
|
||||
msgid "Pool of day {round} for tournament {tournament} with teams {teams}"
|
||||
msgstr "Poule du jour {round} du tournoi {tournament} avec les équipes {teams}"
|
||||
|
||||
#: participation/models.py:597
|
||||
#: participation/models.py:611
|
||||
msgid "position"
|
||||
msgstr "position"
|
||||
|
||||
#: participation/models.py:604
|
||||
#: participation/models.py:618
|
||||
msgid "defended solution"
|
||||
msgstr "solution défendue"
|
||||
|
||||
#: participation/models.py:637
|
||||
#: participation/models.py:651
|
||||
msgid "observer"
|
||||
msgstr "observateur⋅rice"
|
||||
|
||||
#: participation/models.py:642
|
||||
#: participation/models.py:656
|
||||
msgid "penalties"
|
||||
msgstr "pénalités"
|
||||
|
||||
#: participation/models.py:644
|
||||
#: participation/models.py:658
|
||||
msgid ""
|
||||
"Number of penalties for the defender. The defender will loose a 0.5 "
|
||||
"coefficient per penalty."
|
||||
@ -914,124 +922,124 @@ msgstr ""
|
||||
"Nombre de pénalités pour l'équipe défenseuse. Elle perd un coefficient 0.5 "
|
||||
"sur sa présentation orale par pénalité."
|
||||
|
||||
#: participation/models.py:720 participation/models.py:723
|
||||
#: participation/models.py:726 participation/models.py:729
|
||||
#: participation/models.py:734 participation/models.py:737
|
||||
#: participation/models.py:740 participation/models.py:743
|
||||
#, python-brace-format
|
||||
msgid "Team {trigram} is not registered in the pool."
|
||||
msgstr "L'équipe {trigram} n'est pas inscrite dans la poule."
|
||||
|
||||
#: participation/models.py:734
|
||||
#: participation/models.py:748
|
||||
#, python-brace-format
|
||||
msgid "Passage of {defender} for problem {problem}"
|
||||
msgstr "Passage de {defender} pour le problème {problem}"
|
||||
|
||||
#: participation/models.py:738 participation/models.py:747
|
||||
#: participation/models.py:828 participation/models.py:870
|
||||
#: participation/models.py:752 participation/models.py:761
|
||||
#: participation/models.py:846 participation/models.py:888
|
||||
msgid "passage"
|
||||
msgstr "passage"
|
||||
|
||||
#: participation/models.py:739
|
||||
#: participation/models.py:753
|
||||
msgid "passages"
|
||||
msgstr "passages"
|
||||
|
||||
#: participation/models.py:758
|
||||
#: participation/models.py:772
|
||||
msgid "difference"
|
||||
msgstr "différence"
|
||||
|
||||
#: participation/models.py:759
|
||||
#: participation/models.py:773
|
||||
msgid "Score to add/remove on the final score"
|
||||
msgstr "Score à ajouter/retrancher au score final"
|
||||
|
||||
#: participation/models.py:766
|
||||
#: participation/models.py:780
|
||||
msgid "tweak"
|
||||
msgstr "harmonisation"
|
||||
|
||||
#: participation/models.py:767
|
||||
#: participation/models.py:781
|
||||
msgid "tweaks"
|
||||
msgstr "harmonisations"
|
||||
|
||||
#: participation/models.py:795
|
||||
#: participation/models.py:809
|
||||
msgid "solution for the final tournament"
|
||||
msgstr "solution pour la finale"
|
||||
|
||||
#: participation/models.py:800 participation/models.py:839
|
||||
#: participation/models.py:814 participation/models.py:857
|
||||
msgid "file"
|
||||
msgstr "fichier"
|
||||
|
||||
#: participation/models.py:806
|
||||
#: participation/models.py:824
|
||||
#, python-brace-format
|
||||
msgid "Solution of team {team} for problem {problem}"
|
||||
msgstr "Solution de l'équipe {team} pour le problème {problem}"
|
||||
|
||||
#: participation/models.py:808
|
||||
#: participation/models.py:826
|
||||
msgid "for final"
|
||||
msgstr "pour la finale"
|
||||
|
||||
#: participation/models.py:811
|
||||
#: participation/models.py:829
|
||||
msgid "solution"
|
||||
msgstr "solution"
|
||||
|
||||
#: participation/models.py:812
|
||||
#: participation/models.py:830
|
||||
msgid "solutions"
|
||||
msgstr "solutions"
|
||||
|
||||
#: participation/models.py:845
|
||||
#: participation/models.py:863
|
||||
#, python-brace-format
|
||||
msgid "Synthesis of {team} as {type} for problem {problem} of {defender}"
|
||||
msgstr ""
|
||||
"Note de synthèse de l'équipe {team} en tant que {type} pour le problème "
|
||||
"{problem} de {defender}"
|
||||
|
||||
#: participation/models.py:853
|
||||
#: participation/models.py:871
|
||||
msgid "synthesis"
|
||||
msgstr "note de synthèse"
|
||||
|
||||
#: participation/models.py:854
|
||||
#: participation/models.py:872
|
||||
msgid "syntheses"
|
||||
msgstr "notes de synthèse"
|
||||
|
||||
#: participation/models.py:863
|
||||
#: participation/models.py:881
|
||||
msgid "jury"
|
||||
msgstr "jury"
|
||||
|
||||
#: participation/models.py:875
|
||||
#: participation/models.py:893
|
||||
msgid "defender writing note"
|
||||
msgstr "note d'écrit de la défense"
|
||||
|
||||
#: participation/models.py:881
|
||||
#: participation/models.py:899
|
||||
msgid "defender oral note"
|
||||
msgstr "note d'oral de la défense"
|
||||
|
||||
#: participation/models.py:887
|
||||
#: participation/models.py:905
|
||||
msgid "opponent writing note"
|
||||
msgstr "note d'écrit de l'opposition"
|
||||
|
||||
#: participation/models.py:893
|
||||
#: participation/models.py:911
|
||||
msgid "opponent oral note"
|
||||
msgstr "note d'oral de l'opposition"
|
||||
|
||||
#: participation/models.py:899
|
||||
#: participation/models.py:917
|
||||
msgid "reporter writing note"
|
||||
msgstr "note d'écrit du rapportage"
|
||||
|
||||
#: participation/models.py:905
|
||||
#: participation/models.py:923
|
||||
msgid "reporter oral note"
|
||||
msgstr "note d'oral du rapportage"
|
||||
|
||||
#: participation/models.py:911
|
||||
#: participation/models.py:929
|
||||
msgid "observer note"
|
||||
msgstr "note de l'observation"
|
||||
|
||||
#: participation/models.py:944
|
||||
#: participation/models.py:965
|
||||
#, python-brace-format
|
||||
msgid "Notes of {jury} for {passage}"
|
||||
msgstr "Notes de {jury} pour le {passage}"
|
||||
|
||||
#: participation/models.py:951
|
||||
#: participation/models.py:968
|
||||
msgid "note"
|
||||
msgstr "note"
|
||||
|
||||
#: participation/models.py:952
|
||||
#: participation/models.py:969
|
||||
msgid "notes"
|
||||
msgstr "notes"
|
||||
|
||||
@ -1357,7 +1365,41 @@ msgstr "Modifier la poule"
|
||||
msgid "Upload notes"
|
||||
msgstr "Envoyer les notes"
|
||||
|
||||
#: participation/templates/participation/pool_jury.html:44
|
||||
#: participation/templates/participation/pool_jury.html:9
|
||||
msgid ""
|
||||
"On this page, you can manage the juries of the pool. You can add a new jury "
|
||||
"by entering the email address of the jury. If the jury is not registered, "
|
||||
"the account will be created automatically. If the jury already exists, its "
|
||||
"account will be autocompleted and directly linked to the pool."
|
||||
msgstr ""
|
||||
"Sur cette page, vous pouvez gérer les juré⋅es de la poule. Vous pouvez "
|
||||
"ajouter un⋅e juré⋅e en entrant son adresse e-mail. Si læ juré⋅e n'est pas "
|
||||
"inscrit⋅e, le compte sera créé automatiquement. Si læ juré⋅e existe déjà, "
|
||||
"son compte sera autocomplété et directement lié à la poule."
|
||||
|
||||
#: participation/templates/participation/pool_jury.html:17
|
||||
msgid ""
|
||||
"On this page, you can also define the president of the jury, who will have "
|
||||
"the right to see all solutions and if necessary define the notes of other "
|
||||
"jury members."
|
||||
msgstr ""
|
||||
"Sur cette page, vous pouvez aussi définir læ président⋅e du jury, qui aura "
|
||||
"le droit de voir toutes les solutions et si nécessaire définir les notes des "
|
||||
"autres membres du jury."
|
||||
|
||||
#: participation/templates/participation/pool_jury.html:41
|
||||
msgid "PoJ"
|
||||
msgstr "PDJ"
|
||||
|
||||
#: participation/templates/participation/pool_jury.html:46
|
||||
msgid "Preside"
|
||||
msgstr "Présider"
|
||||
|
||||
#: participation/templates/participation/pool_jury.html:51
|
||||
msgid "Remove"
|
||||
msgstr "Retirer"
|
||||
|
||||
#: participation/templates/participation/pool_jury.html:74
|
||||
msgid "Back to pool detail"
|
||||
msgstr "Retour aux détails de la poule"
|
||||
|
||||
@ -1508,7 +1550,7 @@ msgid "Invalidate"
|
||||
msgstr "Invalider"
|
||||
|
||||
#: participation/templates/participation/team_detail.html:209
|
||||
#: participation/views.py:326
|
||||
#: participation/views.py:327
|
||||
msgid "Upload motivation letter"
|
||||
msgstr "Envoyer la lettre de motivation"
|
||||
|
||||
@ -1517,7 +1559,7 @@ msgid "Update team"
|
||||
msgstr "Modifier l'équipe"
|
||||
|
||||
#: participation/templates/participation/team_detail.html:219
|
||||
#: participation/views.py:435
|
||||
#: participation/views.py:436
|
||||
msgid "Leave team"
|
||||
msgstr "Quitter l'équipe"
|
||||
|
||||
@ -1611,7 +1653,15 @@ msgstr "Poules"
|
||||
msgid "Add new pool"
|
||||
msgstr "Ajouter une nouvelle poule"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:118
|
||||
#: participation/templates/participation/tournament_detail.html:121
|
||||
msgid "Publish notes for first round"
|
||||
msgstr "Publier les notes pour le premier tour"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:127
|
||||
msgid "Publish notes for second round"
|
||||
msgstr "Publier les notes pour le second tour"
|
||||
|
||||
#: participation/templates/participation/tournament_detail.html:138
|
||||
msgid "Add pool"
|
||||
msgstr "Ajouter une poule"
|
||||
|
||||
@ -1644,44 +1694,44 @@ msgstr "Modèles :"
|
||||
msgid "Warning: non-free format"
|
||||
msgstr "Attention : format non libre"
|
||||
|
||||
#: participation/views.py:55 tfjm/templates/base.html:79
|
||||
#: participation/views.py:56 tfjm/templates/base.html:79
|
||||
#: tfjm/templates/navbar.html:35
|
||||
msgid "Create team"
|
||||
msgstr "Créer une équipe"
|
||||
|
||||
#: participation/views.py:64 participation/views.py:105
|
||||
#: participation/views.py:65 participation/views.py:106
|
||||
msgid "You don't participate, so you can't create a team."
|
||||
msgstr "Vous ne participez pas, vous ne pouvez pas créer d'équipe."
|
||||
|
||||
#: participation/views.py:66 participation/views.py:107
|
||||
#: participation/views.py:67 participation/views.py:108
|
||||
msgid "You are already in a team."
|
||||
msgstr "Vous êtes déjà dans une équipe."
|
||||
|
||||
#: participation/views.py:96 tfjm/templates/base.html:74
|
||||
#: participation/views.py:97 tfjm/templates/base.html:74
|
||||
#: tfjm/templates/navbar.html:40
|
||||
msgid "Join team"
|
||||
msgstr "Rejoindre une équipe"
|
||||
|
||||
#: participation/views.py:156 participation/views.py:473
|
||||
#: participation/views.py:157 participation/views.py:474
|
||||
msgid "You don't participate, so you don't have any team."
|
||||
msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe."
|
||||
|
||||
#: participation/views.py:182
|
||||
#: participation/views.py:183
|
||||
#, python-brace-format
|
||||
msgid "Detail of team {trigram}"
|
||||
msgstr "Détails de l'équipe {trigram}"
|
||||
|
||||
#: participation/views.py:211
|
||||
#: participation/views.py:212
|
||||
msgid "You don't participate, so you can't request the validation of the team."
|
||||
msgstr ""
|
||||
"Vous ne participez pas, vous ne pouvez pas demander la validation de "
|
||||
"l'équipe."
|
||||
|
||||
#: participation/views.py:214
|
||||
#: participation/views.py:215
|
||||
msgid "The validation of the team is already done or pending."
|
||||
msgstr "La validation de l'équipe est déjà faite ou en cours."
|
||||
|
||||
#: participation/views.py:217
|
||||
#: participation/views.py:218
|
||||
msgid ""
|
||||
"The team can't be validated: missing email address confirmations, "
|
||||
"authorizations, people, motivation letter or the tournament is not set."
|
||||
@ -1690,114 +1740,123 @@ msgstr ""
|
||||
"d'adresse e-mail, soit une autorisation, soit des personnes, soit la lettre "
|
||||
"de motivation, soit le tournoi n'a pas été choisi."
|
||||
|
||||
#: participation/views.py:239
|
||||
#: participation/views.py:240
|
||||
msgid "You are not an organizer of the tournament."
|
||||
msgstr "Vous n'êtes pas un⋅e organisateur⋅rice du tournoi."
|
||||
|
||||
#: participation/views.py:242
|
||||
#: participation/views.py:243
|
||||
msgid "This team has no pending validation."
|
||||
msgstr "L'équipe n'a pas de validation en attente."
|
||||
|
||||
#: participation/views.py:269
|
||||
#: participation/views.py:270
|
||||
msgid "You must specify if you validate the registration or not."
|
||||
msgstr "Vous devez spécifier si vous validez l'inscription ou non."
|
||||
|
||||
#: participation/views.py:304
|
||||
#: participation/views.py:305
|
||||
#, python-brace-format
|
||||
msgid "Update team {trigram}"
|
||||
msgstr "Mise à jour de l'équipe {trigram}"
|
||||
|
||||
#: participation/views.py:365 participation/views.py:421
|
||||
#: participation/views.py:366 participation/views.py:422
|
||||
#, python-brace-format
|
||||
msgid "Motivation letter of {team}.{ext}"
|
||||
msgstr "Lettre de motivation de {team}.{ext}"
|
||||
|
||||
#: participation/views.py:396
|
||||
#: participation/views.py:397
|
||||
#, python-brace-format
|
||||
msgid "Photo authorization of {participant}.{ext}"
|
||||
msgstr "Autorisation de droit à l'image de {participant}.{ext}"
|
||||
|
||||
#: participation/views.py:402
|
||||
#: participation/views.py:403
|
||||
#, python-brace-format
|
||||
msgid "Parental authorization of {participant}.{ext}"
|
||||
msgstr "Autorisation parentale de {participant}.{ext}"
|
||||
|
||||
#: participation/views.py:409
|
||||
#: participation/views.py:410
|
||||
#, python-brace-format
|
||||
msgid "Health sheet of {participant}.{ext}"
|
||||
msgstr "Fiche sanitaire de {participant}.{ext}"
|
||||
|
||||
#: participation/views.py:415
|
||||
#: participation/views.py:416
|
||||
#, python-brace-format
|
||||
msgid "Vaccine sheet of {participant}.{ext}"
|
||||
msgstr "Carnet de vaccination de {participant}.{ext}"
|
||||
|
||||
#: participation/views.py:425
|
||||
#: participation/views.py:426
|
||||
#, python-brace-format
|
||||
msgid "Photo authorizations of team {trigram}.zip"
|
||||
msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip"
|
||||
|
||||
#: participation/views.py:487
|
||||
#: participation/views.py:488
|
||||
msgid "The team is not validated yet."
|
||||
msgstr "L'équipe n'est pas encore validée."
|
||||
|
||||
#: participation/views.py:501
|
||||
#: participation/views.py:502
|
||||
#, python-brace-format
|
||||
msgid "Participation of team {trigram}"
|
||||
msgstr "Participation de l'équipe {trigram}"
|
||||
|
||||
#: participation/views.py:582
|
||||
#: participation/views.py:584
|
||||
#, python-brace-format
|
||||
msgid "Payments of {tournament}"
|
||||
msgstr "Paiements de {tournament}"
|
||||
|
||||
#: participation/views.py:663
|
||||
#: participation/views.py:657
|
||||
msgid "Notes published!"
|
||||
msgstr "Notes publiées !"
|
||||
|
||||
#: participation/views.py:693
|
||||
msgid "You can't upload a solution after the deadline."
|
||||
msgstr "Vous ne pouvez pas envoyer de solution après la date limite."
|
||||
|
||||
#: participation/views.py:771
|
||||
#: participation/views.py:802
|
||||
#, python-brace-format
|
||||
msgid "Solutions for pool {pool} of tournament {tournament}.zip"
|
||||
msgstr "Solutions pour la poule {pool} du tournoi {tournament}.zip"
|
||||
|
||||
#: participation/views.py:772
|
||||
#: participation/views.py:803
|
||||
#, python-brace-format
|
||||
msgid "Syntheses for pool {pool} of tournament {tournament}.zip"
|
||||
msgstr "Notes de synthèses pour la poule {pool} du tournoi {tournament}.zip"
|
||||
|
||||
#: participation/views.py:798
|
||||
#: participation/views.py:833
|
||||
#, python-brace-format
|
||||
msgid "Jury of pool {pool} for {tournament} with teams {teams}"
|
||||
msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}"
|
||||
|
||||
#: participation/views.py:814
|
||||
#: participation/views.py:849
|
||||
#, python-brace-format
|
||||
msgid "The jury {name} is already in the pool!"
|
||||
msgstr "{name} est déjà dans la poule !"
|
||||
|
||||
#: participation/views.py:834
|
||||
#: participation/views.py:869
|
||||
msgid "New TFJM² jury account"
|
||||
msgstr "Nouveau compte de juré⋅e pour le TFJM²"
|
||||
|
||||
#: participation/views.py:851
|
||||
#: participation/views.py:886
|
||||
#, python-brace-format
|
||||
msgid "The jury {name} has been successfully added!"
|
||||
msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !"
|
||||
|
||||
#: participation/views.py:883
|
||||
#: participation/views.py:921
|
||||
#, python-brace-format
|
||||
msgid "The jury {name} has been successfully removed!"
|
||||
msgstr "{name} a été retiré⋅e avec succès du jury !"
|
||||
|
||||
#: participation/views.py:911
|
||||
#: participation/views.py:947
|
||||
#, python-brace-format
|
||||
msgid "The jury {name} has been successfully promoted president!"
|
||||
msgstr "{name} a été nommé⋅e président⋅e du jury !"
|
||||
|
||||
#: participation/views.py:975
|
||||
msgid "The following user is not registered as a jury:"
|
||||
msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :"
|
||||
|
||||
#: participation/views.py:925
|
||||
#: participation/views.py:989
|
||||
msgid "Notes were successfully uploaded."
|
||||
msgstr "Les notes ont bien été envoyées."
|
||||
|
||||
#: participation/views.py:1589
|
||||
#: participation/views.py:1672
|
||||
msgid "You can't upload a synthesis after the deadline."
|
||||
msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."
|
||||
|
||||
|
@ -43,7 +43,7 @@ class SynthesisInline(admin.TabularInline):
|
||||
class PoolInline(admin.TabularInline):
|
||||
model = Pool
|
||||
extra = 0
|
||||
autocomplete_fields = ('tournament', 'participations', 'juries',)
|
||||
autocomplete_fields = ('tournament', 'participations', 'jury_president', 'juries',)
|
||||
show_change_link = True
|
||||
|
||||
|
||||
@ -100,10 +100,10 @@ class ParticipationAdmin(admin.ModelAdmin):
|
||||
|
||||
@admin.register(Pool)
|
||||
class PoolAdmin(admin.ModelAdmin):
|
||||
list_display = ('__str__', 'tournament', 'round', 'letter', 'teams',)
|
||||
list_display = ('__str__', 'tournament', 'round', 'letter', 'teams', 'jury_president',)
|
||||
list_filter = ('tournament', 'round', 'letter',)
|
||||
search_fields = ('participations__team__name', 'participations__team__trigram',)
|
||||
autocomplete_fields = ('tournament', 'participations', 'juries',)
|
||||
autocomplete_fields = ('tournament', 'participations', 'jury_president', 'juries',)
|
||||
inlines = (PassageInline, TweakInline,)
|
||||
|
||||
@admin.display(description=_("teams"))
|
||||
|
@ -178,8 +178,13 @@ class SolutionForm(forms.ModelForm):
|
||||
class PoolForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Pool
|
||||
fields = ('tournament', 'round', 'letter', 'bbb_url', 'results_available', 'juries',)
|
||||
fields = ('tournament', 'round', 'letter', 'bbb_url', 'results_available', 'jury_president', 'juries',)
|
||||
widgets = {
|
||||
"jury_president": forms.Select(attrs={
|
||||
'class': 'selectpicker',
|
||||
'data-live-search': 'true',
|
||||
'data-live-search-normalize': 'true',
|
||||
}),
|
||||
"juries": forms.SelectMultiple(attrs={
|
||||
'class': 'selectpicker',
|
||||
'data-live-search': 'true',
|
||||
@ -218,19 +223,19 @@ class AddJuryForm(forms.ModelForm):
|
||||
Div(
|
||||
Div(
|
||||
Field('email', autofocus="autofocus", list="juries-email"),
|
||||
css_class='col-md-5',
|
||||
css_class='col-md-5 px-1',
|
||||
),
|
||||
Div(
|
||||
Field('first_name', list="juries-first-name"),
|
||||
css_class='col-md-3',
|
||||
css_class='col-md-3 px-1',
|
||||
),
|
||||
Div(
|
||||
Field('last_name', list="juries-last-name"),
|
||||
css_class='col-md-3',
|
||||
css_class='col-md-3 px-1',
|
||||
),
|
||||
Div(
|
||||
Submit('submit', _("Add")),
|
||||
css_class='col-md-1 py-md-4',
|
||||
css_class='col-md-1 py-md-4 px-1',
|
||||
),
|
||||
css_class='row',
|
||||
)
|
||||
|
27
participation/migrations/0009_pool_jury_president.py
Normal file
27
participation/migrations/0009_pool_jury_president.py
Normal file
@ -0,0 +1,27 @@
|
||||
# Generated by Django 5.0.2 on 2024-03-24 14:31
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("participation", "0008_alter_participation_options"),
|
||||
("registration", "0012_payment_token_alter_payment_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="pool",
|
||||
name="jury_president",
|
||||
field=models.ForeignKey(
|
||||
default=None,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="pools_presided",
|
||||
to="registration.volunteerregistration",
|
||||
verbose_name="president of the jury",
|
||||
),
|
||||
),
|
||||
]
|
@ -8,7 +8,7 @@ from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
|
||||
from django.db import models
|
||||
from django.db.models import Index
|
||||
from django.db.models import F, Index, Q
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.utils.crypto import get_random_string
|
||||
@ -543,6 +543,15 @@ class Pool(models.Model):
|
||||
verbose_name=_("juries"),
|
||||
)
|
||||
|
||||
jury_president = models.ForeignKey(
|
||||
VolunteerRegistration,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
default=None,
|
||||
related_name="pools_presided",
|
||||
verbose_name=_("president of the jury"),
|
||||
)
|
||||
|
||||
bbb_url = models.CharField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
@ -573,6 +582,11 @@ class Pool(models.Model):
|
||||
def get_absolute_url(self):
|
||||
return reverse_lazy("participation:pool_detail", args=(self.pk,))
|
||||
|
||||
def validate_constraints(self, exclude=None):
|
||||
if self.jury_president not in self.juries.all():
|
||||
raise ValidationError({'jury_president': _("The president of the jury must be part of the jury.")})
|
||||
return super().validate_constraints()
|
||||
|
||||
def __str__(self):
|
||||
return _("Pool of day {round} for tournament {tournament} with teams {teams}")\
|
||||
.format(round=self.round,
|
||||
@ -802,6 +816,10 @@ class Solution(models.Model):
|
||||
unique=True,
|
||||
)
|
||||
|
||||
@property
|
||||
def tournament(self):
|
||||
return Tournament.final_tournament() if self.final_solution else self.participation.tournament
|
||||
|
||||
def __str__(self):
|
||||
return _("Solution of team {team} for problem {problem}")\
|
||||
.format(team=self.participation.team.name, problem=self.problem)\
|
||||
@ -940,6 +958,9 @@ class Note(models.Model):
|
||||
def modal_name(self):
|
||||
return f"updateNotes{self.pk}"
|
||||
|
||||
def has_any_note(self):
|
||||
return any(self.get_all())
|
||||
|
||||
def __str__(self):
|
||||
return _("Notes of {jury} for {passage}").format(jury=self.jury, passage=self.passage)
|
||||
|
||||
|
@ -4,23 +4,53 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="alert alert-info">
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
On this page, you can manage the juries of the pool. You can add a new jury by entering the email address
|
||||
of the jury. If the jury is not registered, the account will be created automatically. If the jury already
|
||||
exists, its account will be autocompleted and directly linked to the pool.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
On this page, you can also define the president of the jury, who will have the right to see all solutions
|
||||
and if necessary define the notes of other jury members.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
{% for jury in pool.juries.all %}
|
||||
<div class="row my-3">
|
||||
<div class="col-md-5">
|
||||
<div class="row my-3 px-0">
|
||||
<div class="col-md-5 px-1">
|
||||
<input type="email" class="form-control" value="{{ jury.user.email }}" disabled>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3 px-1">
|
||||
<input type="text" class="form-control" value="{{ jury.user.first_name }}" disabled>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3 px-1">
|
||||
<input type="text" class="form-control" value="{{ jury.user.last_name }}" disabled>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<a href="{% url 'participation:pool_remove_jury' pk=pool.pk jury_id=jury.id %}" class="btn btn-danger">
|
||||
Retirer
|
||||
<div class="col-md-1 px-1">
|
||||
<div class="btn-group-vertical btn-group-sm">
|
||||
{% if jury == pool.jury_president %}
|
||||
<button class="btn btn-success">
|
||||
<i class="fas fa-crown"></i> {% trans "PoJ" %}
|
||||
</button>
|
||||
{% else %}
|
||||
<a href="{% url 'participation:pool_preside' pk=pool.pk jury_id=jury.id %}"
|
||||
class="btn btn-warning">
|
||||
<i class="fas fa-crown"></i> {% trans "Preside" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'participation:pool_remove_jury' pk=pool.pk jury_id=jury.id %}"
|
||||
class="btn btn-danger">
|
||||
<i class="fas fa-trash"></i> {% trans "Remove" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
@ -111,6 +111,26 @@
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% if not available_notes_1 or not available_notes_2 %}
|
||||
{% if user.registration.is_admin or user.registration in tournament.organizers.all %}
|
||||
<div class="card-footer text-center">
|
||||
<div class="btn-group">
|
||||
{% if not available_notes_1 %}
|
||||
<a href="{% url 'participation:tournament_publish_notes' pk=tournament.pk round=1 %}" class="btn btn-info">
|
||||
<i class="fas fa-upload"></i>
|
||||
{% trans "Publish notes for first round" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if not available_notes_2 %}
|
||||
<a href="{% url 'participation:tournament_publish_notes' pk=tournament.pk round=2 %}" class="btn btn-info">
|
||||
<i class="fas fa-upload"></i>
|
||||
{% trans "Publish notes for second round" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
@ -7,10 +7,11 @@ from django.views.generic import TemplateView
|
||||
from .views import CreateTeamView, FinalNotationSheetTemplateView, JoinTeamView, MyParticipationDetailView, \
|
||||
MyTeamDetailView, NoteUpdateView, ParticipationDetailView, PassageCreateView, PassageDetailView, \
|
||||
PassageUpdateView, PoolCreateView, PoolDetailView, PoolDownloadView, PoolJuryView, PoolNotesTemplateView, \
|
||||
PoolRemoveJuryView, PoolUpdateTeamsView, PoolUpdateView, PoolUploadNotesView, ScaleNotationSheetTemplateView, \
|
||||
SolutionUploadView, SynthesisUploadView, TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, \
|
||||
TeamUpdateView, TeamUploadMotivationLetterView, TournamentCreateView, TournamentDetailView, \
|
||||
TournamentExportCSVView, TournamentListView, TournamentPaymentsView, TournamentUpdateView
|
||||
PoolPresideJuryView, PoolRemoveJuryView, PoolUpdateTeamsView, PoolUpdateView, PoolUploadNotesView, \
|
||||
ScaleNotationSheetTemplateView, SolutionUploadView, SynthesisUploadView, TeamAuthorizationsView, TeamDetailView, \
|
||||
TeamLeaveView, TeamListView, TeamUpdateView, TeamUploadMotivationLetterView, TournamentCreateView, \
|
||||
TournamentDetailView, TournamentExportCSVView, TournamentListView, TournamentPaymentsView, \
|
||||
TournamentPublishNotesView, TournamentUpdateView
|
||||
|
||||
|
||||
app_name = "participation"
|
||||
@ -35,6 +36,8 @@ urlpatterns = [
|
||||
path("tournament/<int:pk>/update/", TournamentUpdateView.as_view(), name="tournament_update"),
|
||||
path("tournament/<int:pk>/payments/", TournamentPaymentsView.as_view(), name="tournament_payments"),
|
||||
path("tournament/<int:pk>/csv/", TournamentExportCSVView.as_view(), name="tournament_csv"),
|
||||
path("tournament/<int:pk>/publish-notes/<int:round>/", TournamentPublishNotesView.as_view(),
|
||||
name="tournament_publish_notes"),
|
||||
path("pools/create/", PoolCreateView.as_view(), name="pool_create"),
|
||||
path("pools/<int:pk>/", PoolDetailView.as_view(), name="pool_detail"),
|
||||
path("pools/<int:pk>/update/", PoolUpdateView.as_view(), name="pool_update"),
|
||||
@ -45,6 +48,7 @@ urlpatterns = [
|
||||
path("pools/<int:pk>/update-teams/", PoolUpdateTeamsView.as_view(), name="pool_update_teams"),
|
||||
path("pools/<int:pk>/jury/", PoolJuryView.as_view(), name="pool_jury"),
|
||||
path("pools/<int:pk>/jury/remove/<int:jury_id>/", PoolRemoveJuryView.as_view(), name="pool_remove_jury"),
|
||||
path("pools/<int:pk>/jury/preside/<int:jury_id>/", PoolPresideJuryView.as_view(), name="pool_preside"),
|
||||
path("pools/<int:pk>/upload-notes/", PoolUploadNotesView.as_view(), name="pool_upload_notes"),
|
||||
path("pools/<int:pk>/upload-notes/template/", PoolNotesTemplateView.as_view(), name="pool_notes_template"),
|
||||
path("pools/passages/add/<int:pk>/", PassageCreateView.as_view(), name="passage_create"),
|
||||
|
@ -26,6 +26,7 @@ from django.utils import timezone
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, DetailView, FormView, RedirectView, TemplateView, UpdateView, View
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from django.views.generic.edit import FormMixin, ProcessFormView
|
||||
from django_tables2 import MultiTableMixin, SingleTableMixin, SingleTableView
|
||||
from magic import Magic
|
||||
@ -543,13 +544,6 @@ class TournamentDetailView(MultiTableMixin, DetailView):
|
||||
"""
|
||||
model = Tournament
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.tables = [
|
||||
ParticipationTable(self.get_object().participations.all()),
|
||||
PoolTable(self.get_object().pools.order_by('id').all()),
|
||||
]
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
tables = context['tables']
|
||||
@ -565,9 +559,17 @@ class TournamentDetailView(MultiTableMixin, DetailView):
|
||||
if note:
|
||||
notes[participation] = note
|
||||
context["notes"] = sorted(notes.items(), key=lambda x: x[1], reverse=True)
|
||||
context["available_notes_1"] = all(pool.results_available for pool in self.object.pools.filter(round=1).all())
|
||||
context["available_notes_2"] = all(pool.results_available for pool in self.object.pools.filter(round=2).all())
|
||||
|
||||
return context
|
||||
|
||||
def get_tables(self):
|
||||
return [
|
||||
ParticipationTable(self.object.participations.all()),
|
||||
PoolTable(self.object.pools.order_by('id').all()),
|
||||
]
|
||||
|
||||
|
||||
class TournamentPaymentsView(VolunteerMixin, SingleTableMixin, DetailView):
|
||||
"""
|
||||
@ -631,6 +633,34 @@ class TournamentExportCSVView(VolunteerMixin, DetailView):
|
||||
return resp
|
||||
|
||||
|
||||
class TournamentPublishNotesView(VolunteerMixin, SingleObjectMixin, RedirectView):
|
||||
"""
|
||||
Publish notes of a tournament for a given round.
|
||||
"""
|
||||
model = Tournament
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
tournament = self.get_object()
|
||||
reg = request.user.registration
|
||||
if not reg.is_admin and (not reg.is_volunteer or tournament not in reg.organized_tournaments.all()):
|
||||
return self.handle_no_permission()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if int(kwargs["round"]) not in (1, 2):
|
||||
raise Http404
|
||||
|
||||
tournament = Tournament.objects.get(pk=kwargs["pk"])
|
||||
tournament.pools.filter(round=kwargs["round"]).update(results_available=True)
|
||||
messages.success(request, _("Notes published!"))
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_redirect_url(self, *args, **kwargs):
|
||||
return reverse_lazy("participation:tournament_detail", args=(kwargs['pk'],))
|
||||
|
||||
|
||||
class SolutionUploadView(LoginRequiredMixin, FormView):
|
||||
template_name = "participation/upload_solution.html"
|
||||
form_class = SolutionForm
|
||||
@ -721,8 +751,7 @@ class PoolUpdateView(VolunteerMixin, UpdateView):
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
if request.user.registration.is_admin or request.user.registration.is_volunteer \
|
||||
and (self.get_object().tournament in request.user.registration.organized_tournaments.all()
|
||||
or request.user.registration in self.get_object().juries.all()):
|
||||
and self.get_object().tournament in request.user.registration.organized_tournaments.all():
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
return self.handle_no_permission()
|
||||
|
||||
@ -750,9 +779,11 @@ class PoolDownloadView(VolunteerMixin, DetailView):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
if request.user.registration.is_admin or request.user.registration.is_volunteer \
|
||||
and (self.get_object().tournament in request.user.registration.organized_tournaments.all()
|
||||
or request.user.registration in self.get_object().juries.all()):
|
||||
reg = request.user.registration
|
||||
if reg.is_admin or reg.is_volunteer \
|
||||
and (self.get_object().tournament in reg.organized_tournaments.all()
|
||||
or reg in self.get_object().juries.all()
|
||||
or reg.pools_presided.filter(tournament=self.get_object().tournament).exists()):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
return self.handle_no_permission()
|
||||
|
||||
@ -785,12 +816,16 @@ class PoolJuryView(VolunteerMixin, FormView, DetailView):
|
||||
form_class = AddJuryForm
|
||||
template_name = 'participation/pool_jury.html'
|
||||
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
if request.user.registration.is_admin or request.user.registration.is_volunteer \
|
||||
and self.get_object().tournament in request.user.registration.organized_tournaments.all():
|
||||
self.object = self.get_object()
|
||||
|
||||
if request.user.is_authenticated and \
|
||||
(request.user.registration.is_admin or request.user.registration.is_volunteer
|
||||
and (self.object.tournament in request.user.registration.organized_tournaments.all()
|
||||
or request.user.registration == self.object.jury_president)):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
return self.handle_no_permission()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@ -866,11 +901,14 @@ class PoolRemoveJuryView(VolunteerMixin, DetailView):
|
||||
model = Pool
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
if request.user.registration.is_admin or request.user.registration.is_volunteer \
|
||||
and self.get_object().tournament in request.user.registration.organized_tournaments.all():
|
||||
self.object = self.get_object()
|
||||
|
||||
if request.user.is_authenticated and \
|
||||
(request.user.registration.is_admin or request.user.registration.is_volunteer
|
||||
and (self.object.tournament in request.user.registration.organized_tournaments.all()
|
||||
or request.user.registration == self.object.jury_president)):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
return self.handle_no_permission()
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
@ -885,6 +923,32 @@ class PoolRemoveJuryView(VolunteerMixin, DetailView):
|
||||
return redirect(reverse_lazy('participation:pool_jury', args=(pool.pk,)))
|
||||
|
||||
|
||||
class PoolPresideJuryView(VolunteerMixin, DetailView):
|
||||
model = Pool
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
|
||||
if request.user.is_authenticated and \
|
||||
(request.user.registration.is_admin or request.user.registration.is_volunteer
|
||||
and (self.object.tournament in request.user.registration.organized_tournaments.all()
|
||||
or request.user.registration == self.object.jury_president)):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
return self.handle_no_permission()
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
pool = self.get_object()
|
||||
if not pool.juries.filter(pk=kwargs['jury_id']).exists():
|
||||
raise Http404
|
||||
jury = pool.juries.get(pk=kwargs['jury_id'])
|
||||
pool.jury_president = jury
|
||||
pool.save()
|
||||
messages.success(request, _("The jury {name} has been successfully promoted president!")
|
||||
.format(name=f"{jury.user.first_name} {jury.user.last_name}"))
|
||||
return redirect(reverse_lazy('participation:pool_jury', args=(pool.pk,)))
|
||||
|
||||
|
||||
class PoolUploadNotesView(VolunteerMixin, FormView, DetailView):
|
||||
model = Pool
|
||||
form_class = UploadNotesForm
|
||||
@ -896,7 +960,7 @@ class PoolUploadNotesView(VolunteerMixin, FormView, DetailView):
|
||||
if request.user.is_authenticated and \
|
||||
(request.user.registration.is_admin or request.user.registration.is_volunteer
|
||||
and (self.object.tournament in request.user.registration.organized_tournaments.all()
|
||||
or request.user.registration in self.object.juries.all())):
|
||||
or request.user.registration == self.object.jury_president)):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
return self.handle_no_permission()
|
||||
@ -935,6 +999,17 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
||||
"""
|
||||
model = Pool
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
|
||||
if request.user.is_authenticated and \
|
||||
(request.user.registration.is_admin or request.user.registration.is_volunteer
|
||||
and (self.object.tournament in request.user.registration.organized_tournaments.all()
|
||||
or request.user.registration == self.object.jury_president)):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
return self.handle_no_permission()
|
||||
|
||||
def render_to_response(self, context, **response_kwargs): # noqa: C901
|
||||
pool_size = self.object.passages.count()
|
||||
passage_width = 7 if pool_size == 4 else 6
|
||||
@ -1513,26 +1588,34 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
if request.user.registration.is_admin or request.user.registration.is_volunteer \
|
||||
and (self.get_object().pool.tournament in request.user.registration.organized_tournaments.all()
|
||||
or request.user.registration in self.get_object().pool.juries.all()) \
|
||||
or request.user.registration.participates and request.user.registration.team \
|
||||
and request.user.registration.team.participation in [self.get_object().defender,
|
||||
self.get_object().opponent,
|
||||
self.get_object().reporter]:
|
||||
reg = request.user.registration
|
||||
passage = self.get_object()
|
||||
if reg.is_admin or reg.is_volunteer \
|
||||
and (self.get_object().pool.tournament in reg.organized_tournaments.all()
|
||||
or reg in passage.pool.juries.all()
|
||||
or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \
|
||||
or reg.participates and reg.team \
|
||||
and reg.team.participation in [passage.defender, passage.opponent, passage.reporter, passage.observer]:
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
return self.handle_no_permission()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
if self.request.user.registration in self.object.pool.juries.all():
|
||||
reg = self.request.user.registration
|
||||
if reg in self.object.pool.juries.all():
|
||||
context["my_note"] = Note.objects.get_or_create(passage=self.object, jury=self.request.user.registration)[0]
|
||||
context["notes"] = NoteTable(self.object.notes.all())
|
||||
elif self.request.user.registration.is_admin:
|
||||
context["notes"] = NoteTable(self.object.notes.all())
|
||||
if 'notes' in context and not self.object.observer:
|
||||
if reg.is_volunteer:
|
||||
notes = self.object.notes.all()
|
||||
if not reg.is_admin \
|
||||
or (reg != self.object.pool.jury_president
|
||||
and reg not in self.object.pool.tournament.organizers.all()):
|
||||
notes = [note for note in notes if note.has_any_note()]
|
||||
context["notes"] = NoteTable(notes)
|
||||
|
||||
# Only display the observer column for 4-teams pools
|
||||
context['notes']._sequence.pop()
|
||||
context['notes']._sequence.remove('observer_oral')
|
||||
if 'notes' in context and not self.request.user.registration.is_admin:
|
||||
context['notes']._sequence.remove('update')
|
||||
return context
|
||||
|
||||
|
||||
@ -1611,8 +1694,9 @@ class NoteUpdateView(VolunteerMixin, UpdateView):
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
|
||||
if request.user.registration.is_admin or request.user.registration.is_volunteer \
|
||||
and self.get_object().jury == request.user.registration:
|
||||
reg = request.user.registration
|
||||
note = self.get_object()
|
||||
if reg.is_admin or reg.is_volunteer and (note.jury == reg or note.passage.pool.jury_president == reg):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
return self.handle_no_permission()
|
||||
|
@ -797,9 +797,10 @@ class SolutionView(LoginRequiredMixin, View):
|
||||
else:
|
||||
passage_participant_qs = Passage.objects.none()
|
||||
if not (user.registration.is_admin
|
||||
or user.registration.is_volunteer and user.registration
|
||||
in (solution.participation.tournament
|
||||
if not solution.final_solution else Tournament.final_tournament()).organizers.all()
|
||||
or (user.registration.is_volunteer
|
||||
and user.registration in solution.tournament.organizers.all())
|
||||
or (user.registration.is_volunteer
|
||||
and user.registration.presided_pools.filter(tournament=solution.tournament).exists())
|
||||
or user.registration.is_volunteer
|
||||
and Passage.objects.filter(Q(pool__juries=user.registration)
|
||||
| Q(pool__tournament__in=user.registration.organized_tournaments.all()),
|
||||
@ -834,7 +835,8 @@ class SynthesisView(LoginRequiredMixin, View):
|
||||
user = request.user
|
||||
if not (user.registration.is_admin or user.registration.is_volunteer
|
||||
and (user.registration in synthesis.passage.pool.juries.all()
|
||||
or user.registration in synthesis.passage.pool.tournament.organizers.all())
|
||||
or user.registration in synthesis.passage.pool.tournament.organizers.all()
|
||||
or user.registration.presided_pools.filter(tournament=synthesis.passage.pool.tournament).exists())
|
||||
or user.registration.participates and user.registration.team == synthesis.participation.team):
|
||||
raise PermissionDenied
|
||||
# Guess mime type of the file
|
||||
|
Loading…
x
Reference in New Issue
Block a user