mirror of
				https://gitlab.com/animath/si/plateforme.git
				synced 2025-10-31 12:09:51 +01:00 
			
		
		
		
	Add autocomplete feature for jury form
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
		| @@ -7,7 +7,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: TFJM\n" | "Project-Id-Version: TFJM\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2024-03-23 11:22+0100\n" | "POT-Creation-Date: 2024-03-23 23:02+0100\n" | ||||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||||
| "Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n" | "Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n" | ||||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | "Language-Team: LANGUAGE <LL@li.org>\n" | ||||||
| @@ -490,7 +490,7 @@ msgstr "Ce trigramme est déjà utilisé." | |||||||
| msgid "No team was found with this access code." | msgid "No team was found with this access code." | ||||||
| msgstr "Aucune équipe n'a été trouvée avec ce code d'accès." | msgstr "Aucune équipe n'a été trouvée avec ce code d'accès." | ||||||
|  |  | ||||||
| #: participation/forms.py:85 participation/forms.py:352 | #: participation/forms.py:85 participation/forms.py:355 | ||||||
| #: registration/forms.py:122 registration/forms.py:144 | #: registration/forms.py:122 registration/forms.py:144 | ||||||
| #: registration/forms.py:166 registration/forms.py:188 | #: registration/forms.py:166 registration/forms.py:188 | ||||||
| #: registration/forms.py:237 registration/forms.py:270 | #: registration/forms.py:237 registration/forms.py:270 | ||||||
| @@ -516,7 +516,7 @@ msgstr "Message à adresser à l'équipe :" | |||||||
| msgid "The uploaded file size must be under 5 Mo." | msgid "The uploaded file size must be under 5 Mo." | ||||||
| msgstr "Le fichier envoyé doit peser moins de 5 Mo." | msgstr "Le fichier envoyé doit peser moins de 5 Mo." | ||||||
|  |  | ||||||
| #: participation/forms.py:157 participation/forms.py:354 | #: participation/forms.py:157 participation/forms.py:357 | ||||||
| msgid "The uploaded file must be a PDF file." | msgid "The uploaded file must be a PDF file." | ||||||
| msgstr "Le fichier envoyé doit être au format PDF." | msgstr "Le fichier envoyé doit être au format PDF." | ||||||
|  |  | ||||||
| @@ -530,11 +530,15 @@ msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages." | |||||||
| msgid "Add" | msgid "Add" | ||||||
| msgstr "Ajouter" | msgstr "Ajouter" | ||||||
|  |  | ||||||
| #: participation/forms.py:251 | #: participation/forms.py:243 | ||||||
|  | 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:254 | ||||||
| msgid "CSV file:" | msgid "CSV file:" | ||||||
| msgstr "Tableur au format CSV :" | msgstr "Tableur au format CSV :" | ||||||
|  |  | ||||||
| #: participation/forms.py:275 | #: participation/forms.py:278 | ||||||
| msgid "" | msgid "" | ||||||
| "This file contains non-UTF-8 and non-ISO-8859-1 content. Please send your " | "This file contains non-UTF-8 and non-ISO-8859-1 content. Please send your " | ||||||
| "sheet as a CSV file." | "sheet as a CSV file." | ||||||
| @@ -542,30 +546,30 @@ msgstr "" | |||||||
| "Ce fichier contient des éléments non-UTF-8 et non-ISO-8859-1. Merci " | "Ce fichier contient des éléments non-UTF-8 et non-ISO-8859-1. Merci " | ||||||
| "d'envoyer votre tableur au format CSV." | "d'envoyer votre tableur au format CSV." | ||||||
|  |  | ||||||
| #: participation/forms.py:290 | #: participation/forms.py:293 | ||||||
| msgid "Can't determine the pool size. Are you sure your file is correct?" | msgid "Can't determine the pool size. Are you sure your file is correct?" | ||||||
| msgstr "" | msgstr "" | ||||||
| "Impossible de déterminer la taille de la poule. Êtes-vous sûr⋅e que le " | "Impossible de déterminer la taille de la poule. Êtes-vous sûr⋅e que le " | ||||||
| "fichier est correct ?" | "fichier est correct ?" | ||||||
|  |  | ||||||
| #: participation/forms.py:310 | #: participation/forms.py:313 | ||||||
| msgid "The following note is higher of the maximum expected value:" | msgid "The following note is higher of the maximum expected value:" | ||||||
| msgstr "La note suivante est supérieure au maximum attendu :" | msgstr "La note suivante est supérieure au maximum attendu :" | ||||||
|  |  | ||||||
| #: participation/forms.py:318 | #: participation/forms.py:321 | ||||||
| msgid "The following user was not found:" | msgid "The following user was not found:" | ||||||
| msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :" | msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :" | ||||||
|  |  | ||||||
| #: participation/forms.py:335 | #: participation/forms.py:338 | ||||||
| msgid "The defender, the opponent and the reporter must be different." | msgid "The defender, the opponent and the reporter must be different." | ||||||
| msgstr "" | msgstr "" | ||||||
| "Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es." | "Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es." | ||||||
|  |  | ||||||
| #: participation/forms.py:339 | #: participation/forms.py:342 | ||||||
| msgid "This defender did not work on this problem." | msgid "This defender did not work on this problem." | ||||||
| msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème." | msgstr "Ce⋅tte défenseur⋅se ne travaille pas sur ce problème." | ||||||
|  |  | ||||||
| #: participation/forms.py:358 | #: participation/forms.py:361 | ||||||
| msgid "The PDF file must not have more than 2 pages." | msgid "The PDF file must not have more than 2 pages." | ||||||
| msgstr "Le fichier PDF ne doit pas avoir plus de 2 pages." | msgstr "Le fichier PDF ne doit pas avoir plus de 2 pages." | ||||||
|  |  | ||||||
| @@ -1344,7 +1348,7 @@ msgstr "Modifier la poule" | |||||||
| msgid "Upload notes" | msgid "Upload notes" | ||||||
| msgstr "Envoyer les notes" | msgstr "Envoyer les notes" | ||||||
|  |  | ||||||
| #: participation/templates/participation/pool_jury.html:35 | #: participation/templates/participation/pool_jury.html:44 | ||||||
| msgid "Back to pool detail" | msgid "Back to pool detail" | ||||||
| msgstr "Retour aux détails de la poule" | msgstr "Retour aux détails de la poule" | ||||||
|  |  | ||||||
| @@ -1762,32 +1766,33 @@ msgid "Jury of pool {pool} for {tournament} with teams {teams}" | |||||||
| msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}" | msgstr "Jury de la poule {pool} pour {tournament} avec les équipes {teams}" | ||||||
|  |  | ||||||
| #: participation/views.py:814 | #: participation/views.py:814 | ||||||
| msgid "This user already exists, but is a participant." | #, python-brace-format | ||||||
| msgstr "Cet⋅te utilisateur⋅rice existe déjà, mais en tant que participant⋅e." | msgid "The jury {name} is already in the pool!" | ||||||
|  | msgstr "{name} est déjà dans la poule !" | ||||||
|  |  | ||||||
| #: participation/views.py:833 | #: participation/views.py:834 | ||||||
| msgid "New TFJM² jury account" | msgid "New TFJM² jury account" | ||||||
| msgstr "Nouveau compte de juré⋅e pour le TFJM²" | msgstr "Nouveau compte de juré⋅e pour le TFJM²" | ||||||
|  |  | ||||||
| #: participation/views.py:850 | #: participation/views.py:851 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "The jury {name} has been successfully added!" | msgid "The jury {name} has been successfully added!" | ||||||
| msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !" | msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !" | ||||||
|  |  | ||||||
| #: participation/views.py:882 | #: participation/views.py:883 | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "The jury {name} has been successfully removed!" | msgid "The jury {name} has been successfully removed!" | ||||||
| msgstr "{name} a été retiré⋅e avec succès du jury !" | msgstr "{name} a été retiré⋅e avec succès du jury !" | ||||||
|  |  | ||||||
| #: participation/views.py:910 | #: participation/views.py:911 | ||||||
| msgid "The following user is not registered as a jury:" | 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 :" | msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :" | ||||||
|  |  | ||||||
| #: participation/views.py:924 | #: participation/views.py:925 | ||||||
| msgid "Notes were successfully uploaded." | msgid "Notes were successfully uploaded." | ||||||
| msgstr "Les notes ont bien été envoyées." | msgstr "Les notes ont bien été envoyées." | ||||||
|  |  | ||||||
| #: participation/views.py:1588 | #: participation/views.py:1589 | ||||||
| msgid "You can't upload a synthesis after the deadline." | 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." | msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite." | ||||||
|  |  | ||||||
|   | |||||||
| @@ -213,17 +213,17 @@ class AddJuryForm(forms.ModelForm): | |||||||
|         self.helper.layout = Div( |         self.helper.layout = Div( | ||||||
|             Div( |             Div( | ||||||
|                 Div( |                 Div( | ||||||
|                     Field('first_name', autofocus="autofocus"), |                     Field('email', autofocus="autofocus", list="juries-email"), | ||||||
|                     css_class='col-md-3', |  | ||||||
|                 ), |  | ||||||
|                 Div( |  | ||||||
|                     Field('last_name'), |  | ||||||
|                     css_class='col-md-3', |  | ||||||
|                 ), |  | ||||||
|                 Div( |  | ||||||
|                     Field('email'), |  | ||||||
|                     css_class='col-md-5', |                     css_class='col-md-5', | ||||||
|                 ), |                 ), | ||||||
|  |                 Div( | ||||||
|  |                     Field('first_name', list="juries-first-name"), | ||||||
|  |                     css_class='col-md-3', | ||||||
|  |                 ), | ||||||
|  |                 Div( | ||||||
|  |                     Field('last_name', list="juries-last-name"), | ||||||
|  |                     css_class='col-md-3', | ||||||
|  |                 ), | ||||||
|                 Div( |                 Div( | ||||||
|                     Submit('submit', _("Add")), |                     Submit('submit', _("Add")), | ||||||
|                     css_class='col-md-1 py-md-4', |                     css_class='col-md-1 py-md-4', | ||||||
| @@ -239,6 +239,9 @@ class AddJuryForm(forms.ModelForm): | |||||||
|         email = self.data["email"] |         email = self.data["email"] | ||||||
|         if User.objects.filter(email=email).exists(): |         if User.objects.filter(email=email).exists(): | ||||||
|             self.instance = User.objects.get(email=email) |             self.instance = User.objects.get(email=email) | ||||||
|  |             if self.instance.registration.participates: | ||||||
|  |                 self.add_error(None, _("This user already exists, but is a participant.")) | ||||||
|  |                 return | ||||||
|         return email |         return email | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|   | |||||||
| @@ -8,15 +8,15 @@ | |||||||
|  |  | ||||||
|     {% for jury in pool.juries.all %} |     {% for jury in pool.juries.all %} | ||||||
|         <div class="row my-3"> |         <div class="row my-3"> | ||||||
|  |             <div class="col-md-5"> | ||||||
|  |                 <input type="email" class="form-control" value="{{ jury.user.email }}" disabled> | ||||||
|  |             </div> | ||||||
|             <div class="col-md-3"> |             <div class="col-md-3"> | ||||||
|                 <input type="text" class="form-control" value="{{ jury.user.first_name }}" disabled> |                 <input type="text" class="form-control" value="{{ jury.user.first_name }}" disabled> | ||||||
|             </div> |             </div> | ||||||
|             <div class="col-md-3"> |             <div class="col-md-3"> | ||||||
|                 <input type="text" class="form-control" value="{{ jury.user.last_name }}" disabled> |                 <input type="text" class="form-control" value="{{ jury.user.last_name }}" disabled> | ||||||
|             </div> |             </div> | ||||||
|             <div class="col-md-5"> |  | ||||||
|                 <input type="email" class="form-control" value="{{ jury.user.email }}" disabled> |  | ||||||
|             </div> |  | ||||||
|             <div class="col-md-1"> |             <div class="col-md-1"> | ||||||
|                 <a href="{% url 'participation:pool_remove_jury' pk=pool.pk  jury_id=jury.id %}" class="btn btn-danger"> |                 <a href="{% url 'participation:pool_remove_jury' pk=pool.pk  jury_id=jury.id %}" class="btn btn-danger"> | ||||||
|                     Retirer |                     Retirer | ||||||
| @@ -28,6 +28,15 @@ | |||||||
|     {{ form|as_crispy_errors }} |     {{ form|as_crispy_errors }} | ||||||
|     {% crispy form %} |     {% crispy form %} | ||||||
|  |  | ||||||
|  |     <datalist id="juries-email"> | ||||||
|  |     </datalist> | ||||||
|  |  | ||||||
|  |     <datalist id="juries-first-name"> | ||||||
|  |     </datalist> | ||||||
|  |  | ||||||
|  |     <datalist id="juries-last-name"> | ||||||
|  |     </datalist> | ||||||
|  |  | ||||||
|     <hr> |     <hr> | ||||||
|  |  | ||||||
|     <div class="row text-center"> |     <div class="row text-center"> | ||||||
| @@ -39,8 +48,60 @@ | |||||||
|  |  | ||||||
| {% block extrajavascript %} | {% block extrajavascript %} | ||||||
|     <script> |     <script> | ||||||
|         document.addEventListener('DOMContentLoaded', () => { |         const emailField = document.getElementById('id_email') | ||||||
|             initModal("updatePool", "{% url "participation:pool_update" pk=pool.pk %}") |         const firstNameField = document.getElementById('id_first_name') | ||||||
|  |         const lastNameField = document.getElementById('id_last_name') | ||||||
|  |  | ||||||
|  |         const juriesEmailList = document.getElementById('juries-email') | ||||||
|  |         const juriesFirstNameList = document.getElementById('juries-first-name') | ||||||
|  |         const juriesLastNameList = document.getElementById('juries-last-name') | ||||||
|  |  | ||||||
|  |         function updateJuries(filter) { | ||||||
|  |             fetch(`/api/registration/volunteers/?search=${filter}`) | ||||||
|  |                 .then(response => response.json()) | ||||||
|  |                 .then(response => response.results) | ||||||
|  |                 .then(data => { | ||||||
|  |                     juriesEmailList.innerHTML = '' | ||||||
|  |                     juriesFirstNameList.innerHTML = '' | ||||||
|  |                     juriesLastNameList.innerHTML = '' | ||||||
|  |  | ||||||
|  |                     data.forEach(jury => { | ||||||
|  |                         const optionEmail = document.createElement('option') | ||||||
|  |                         optionEmail.value = jury.email | ||||||
|  |                         optionEmail.setAttribute('data-id', jury.id) | ||||||
|  |                         juriesEmailList.appendChild(optionEmail) | ||||||
|  |  | ||||||
|  |                         const optionFirstName = document.createElement('option') | ||||||
|  |                         optionFirstName.value = jury.first_name | ||||||
|  |                         optionFirstName.setAttribute('data-id', jury.id) | ||||||
|  |                         juriesFirstNameList.appendChild(optionFirstName) | ||||||
|  |  | ||||||
|  |                         const optionLastName = document.createElement('option') | ||||||
|  |                         optionLastName.value = jury.last_name | ||||||
|  |                         optionLastName.setAttribute('data-id', jury.id) | ||||||
|  |                         juriesLastNameList.appendChild(optionLastName) | ||||||
|  |                     }) | ||||||
|  |                 }) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         emailField.addEventListener('input', event => { | ||||||
|  |             let emailOption = document.querySelector(`datalist[id="juries-email"] > option[value="${event.target.value}"]`) | ||||||
|  |             if (emailOption) { | ||||||
|  |                 let id = emailOption.getAttribute('data-id') | ||||||
|  |                 let firstNameOption = document.querySelector(`datalist[id="juries-first-name"] > option[data-id="${id}"]`) | ||||||
|  |                 let lastNameOption = document.querySelector(`datalist[id="juries-last-name"] > option[data-id="${id}"]`) | ||||||
|  |                 if (firstNameOption && lastNameOption) { | ||||||
|  |                     firstNameField.value = firstNameOption.value | ||||||
|  |                     lastNameField.value = lastNameOption.value | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             updateJuries(event.target.value) | ||||||
|  |         }) | ||||||
|  |         firstNameField.addEventListener('input', event => { | ||||||
|  |             updateJuries(event.target.value) | ||||||
|  |         }) | ||||||
|  |         lastNameField.addEventListener('input', event => { | ||||||
|  |             updateJuries(event.target.value) | ||||||
|         }) |         }) | ||||||
|     </script> |     </script> | ||||||
| {% endblock %} | {% endblock %} | ||||||
|   | |||||||
| @@ -810,8 +810,9 @@ class PoolJuryView(VolunteerMixin, FormView, DetailView): | |||||||
|             # The user already exists, so we don't recreate it |             # The user already exists, so we don't recreate it | ||||||
|             user.refresh_from_db() |             user.refresh_from_db() | ||||||
|             reg = user.registration |             reg = user.registration | ||||||
|             if reg.participates: |             if reg in self.object.juries.all(): | ||||||
|                 form.add_error(None, _("This user already exists, but is a participant.")) |                 messages.warning(self.request, _("The jury {name} is already in the pool!") | ||||||
|  |                                  .format(name=f"{user.first_name} {user.last_name}")) | ||||||
|                 return self.form_invalid(form) |                 return self.form_invalid(form) | ||||||
|         else: |         else: | ||||||
|             # Save the user object first |             # Save the user object first | ||||||
|   | |||||||
| @@ -50,4 +50,4 @@ class PaymentSerializer(serializers.ModelSerializer): | |||||||
| class BasicUserSerializer(serializers.ModelSerializer): | class BasicUserSerializer(serializers.ModelSerializer): | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = User |         model = User | ||||||
|         fields = ['first_name', 'last_name', 'email', ] |         fields = ['id', 'first_name', 'last_name', 'email', ] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user