Add button to update notes

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello 2024-03-24 11:28:41 +01:00
parent 64b7644e5e
commit 6fa3a08a72
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
7 changed files with 73 additions and 53 deletions

View File

@ -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-24 10:29+0100\n" "POT-Creation-Date: 2024-03-24 11:26+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"
@ -23,7 +23,7 @@ msgstr "API"
#: draw/admin.py:39 draw/admin.py:57 draw/admin.py:75 #: draw/admin.py:39 draw/admin.py:57 draw/admin.py:75
#: participation/admin.py:109 participation/models.py:250 #: participation/admin.py:109 participation/models.py:250
#: participation/tables.py:87 #: participation/tables.py:88
msgid "teams" msgid "teams"
msgstr "équipes" msgstr "équipes"
@ -215,7 +215,7 @@ msgstr "Poule {letter}{number}"
#: draw/models.py:408 draw/models.py:435 participation/admin.py:136 #: draw/models.py:408 draw/models.py:435 participation/admin.py:136
#: participation/admin.py:155 participation/models.py:583 #: participation/admin.py:155 participation/models.py:583
#: participation/models.py:592 participation/tables.py:83 #: participation/models.py:592 participation/tables.py:84
msgid "pool" msgid "pool"
msgstr "poule" msgstr "poule"
@ -447,7 +447,7 @@ msgstr "changelogs"
msgid "Changelog of type \"{action}\" for model {model} at {timestamp}" msgid "Changelog of type \"{action}\" for model {model} at {timestamp}"
msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}" msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}"
#: participation/admin.py:83 participation/tables.py:43 #: participation/admin.py:83 participation/tables.py:44
msgid "valid" msgid "valid"
msgstr "valide" msgstr "valide"
@ -456,7 +456,7 @@ msgid "selected for final"
msgstr "sélectionnée pour la finale" msgstr "sélectionnée pour la finale"
#: participation/admin.py:124 participation/admin.py:183 #: participation/admin.py:124 participation/admin.py:183
#: participation/models.py:613 participation/tables.py:111 #: participation/models.py:613 participation/tables.py:112
msgid "defender" msgid "defender"
msgstr "défenseur⋅se" msgstr "défenseur⋅se"
@ -578,11 +578,11 @@ 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."
#: participation/models.py:32 participation/models.py:260 #: participation/models.py:32 participation/models.py:260
#: participation/tables.py:17 participation/tables.py:33 #: participation/tables.py:18 participation/tables.py:34
msgid "name" msgid "name"
msgstr "nom" msgstr "nom"
#: participation/models.py:38 participation/tables.py:38 #: participation/models.py:38 participation/tables.py:39
msgid "trigram" msgid "trigram"
msgstr "trigramme" msgstr "trigramme"
@ -1022,49 +1022,68 @@ msgstr "note d'oral du rapportage"
msgid "observer note" msgid "observer note"
msgstr "note de l'observation" msgstr "note de l'observation"
#: participation/models.py:940 #: participation/models.py:944
#, python-brace-format #, python-brace-format
msgid "Notes of {jury} for {passage}" msgid "Notes of {jury} for {passage}"
msgstr "Notes de {jury} pour le {passage}" msgstr "Notes de {jury} pour le {passage}"
#: participation/models.py:947 #: participation/models.py:951
msgid "note" msgid "note"
msgstr "note" msgstr "note"
#: participation/models.py:948 #: participation/models.py:952
msgid "notes" msgid "notes"
msgstr "notes" msgstr "notes"
#: participation/tables.py:49 #: participation/tables.py:50
msgid "Validated" msgid "Validated"
msgstr "Validée" msgstr "Validée"
#: participation/tables.py:49 #: participation/tables.py:50
msgid "Validation pending" msgid "Validation pending"
msgstr "Validation en attente" msgstr "Validation en attente"
#: participation/tables.py:49 #: participation/tables.py:50
msgid "Not validated" msgid "Not validated"
msgstr "Non validée" msgstr "Non validée"
#: participation/tables.py:63 #: participation/tables.py:64
msgid "date" msgid "date"
msgstr "date" msgstr "date"
#: participation/tables.py:66 #: participation/tables.py:67
#, python-brace-format #, python-brace-format
msgid "From {start} to {end}" msgid "From {start} to {end}"
msgstr "Du {start} au {end}" msgstr "Du {start} au {end}"
#: participation/tables.py:93 #: participation/tables.py:94
#, python-brace-format #, python-brace-format
msgid "Pool {letter}{round}" msgid "Pool {letter}{round}"
msgstr "Poule {letter}{round}" msgstr "Poule {letter}{round}"
#: participation/tables.py:97 #: participation/tables.py:98
msgid "No defined team" msgid "No defined team"
msgstr "Pas d'équipe définie" msgstr "Pas d'équipe définie"
#: participation/tables.py:142
#: participation/templates/participation/note_form.html:13
#: participation/templates/participation/passage_detail.html:54
#: participation/templates/participation/passage_detail.html:120
#: participation/templates/participation/passage_detail.html:126
#: participation/templates/participation/pool_detail.html:110
#: participation/templates/participation/pool_detail.html:128
#: participation/templates/participation/pool_detail.html:133
#: participation/templates/participation/team_detail.html:151
#: participation/templates/participation/team_detail.html:215
#: participation/templates/participation/tournament_form.html:12
#: participation/templates/participation/update_team.html:12
#: registration/tables.py:46
#: registration/templates/registration/payment_form.html:210
#: registration/templates/registration/update_user.html:16
#: registration/templates/registration/user_detail.html:186
msgid "Update"
msgstr "Modifier"
#: participation/templates/participation/chat.html:7 #: participation/templates/participation/chat.html:7
msgid "" msgid ""
"The chat feature is now out of usage. If you feel that having a chat feature " "The chat feature is now out of usage. If you feel that having a chat feature "
@ -1086,23 +1105,9 @@ msgstr "Créer"
msgid "Join" msgid "Join"
msgstr "Rejoindre" msgstr "Rejoindre"
#: participation/templates/participation/note_form.html:11 #: participation/templates/participation/note_form.html:8
#: participation/templates/participation/passage_detail.html:54 msgid "Notes of"
#: participation/templates/participation/passage_detail.html:120 msgstr "Notes de"
#: participation/templates/participation/passage_detail.html:126
#: participation/templates/participation/pool_detail.html:110
#: participation/templates/participation/pool_detail.html:128
#: participation/templates/participation/pool_detail.html:133
#: participation/templates/participation/team_detail.html:151
#: participation/templates/participation/team_detail.html:215
#: participation/templates/participation/tournament_form.html:12
#: participation/templates/participation/update_team.html:12
#: registration/tables.py:46
#: registration/templates/registration/payment_form.html:210
#: registration/templates/registration/update_user.html:16
#: registration/templates/registration/user_detail.html:186
msgid "Update"
msgstr "Modifier"
#: participation/templates/participation/participation_detail.html:6 #: participation/templates/participation/participation_detail.html:6
#: participation/templates/participation/participation_detail.html:21 #: participation/templates/participation/participation_detail.html:21
@ -1240,7 +1245,7 @@ msgstr "Moyenne de l'oral de l'équipe défenseuse :"
#: participation/templates/participation/passage_detail.html:79 #: participation/templates/participation/passage_detail.html:79
msgid "Average points for the opponent writing:" msgid "Average points for the opponent writing:"
msgstr "Moyenne de l'écrit de l'équipe opposante ':" msgstr "Moyenne de l'écrit de l'équipe opposante :"
#: participation/templates/participation/passage_detail.html:82 #: participation/templates/participation/passage_detail.html:82
msgid "Average points for the opponent oral:" msgid "Average points for the opponent oral:"

View File

@ -936,13 +936,13 @@ class Note(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy("participation:passage_detail", args=(self.passage.pk,)) return reverse_lazy("participation:passage_detail", args=(self.passage.pk,))
@property
def modal_name(self):
return f"updateNotes{self.pk}"
def __str__(self): def __str__(self):
return _("Notes of {jury} for {passage}").format(jury=self.jury, passage=self.passage) return _("Notes of {jury} for {passage}").format(jury=self.jury, passage=self.passage)
def __bool__(self):
return any((self.defender_writing, self.defender_oral, self.opponent_writing, self.opponent_oral,
self.reporter_writing, self.reporter_oral, self.observer_oral))
class Meta: class Meta:
verbose_name = _("note") verbose_name = _("note")
verbose_name_plural = _("notes") verbose_name_plural = _("notes")

View File

@ -1,7 +1,8 @@
# Copyright (C) 2020 by Animath # Copyright (C) 2020 by Animath
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.urls import reverse_lazy
from django.utils import formats from django.utils import formats
from django.utils.safestring import mark_safe
from django.utils.text import format_lazy from django.utils.text import format_lazy
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import django_tables2 as tables import django_tables2 as tables
@ -137,10 +138,21 @@ class NoteTable(tables.Table):
} }
) )
update = tables.Column(
verbose_name=_("Update"),
accessor="id",
empty_values=(),
)
def render_update(self, record):
return mark_safe(f'<button class="btn btn-info" data-bs-toggle="modal" '
f'data-bs-target="#{record.modal_name}Modal">'
f'{_("Update")}</button>')
class Meta: class Meta:
attrs = { attrs = {
'class': 'table table-condensed table-striped text-center', 'class': 'table table-condensed table-striped text-center',
} }
model = Note model = Note
fields = ('jury', 'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral', fields = ('jury', 'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral',
'reporter_writing', 'reporter_oral', 'observer_oral',) 'reporter_writing', 'reporter_oral', 'observer_oral', 'update',)

View File

@ -5,6 +5,8 @@
{% block content %} {% block content %}
<form method="post"> <form method="post">
<div id="form-content"> <div id="form-content">
<h4>{% trans "Notes of" %} {{ note.jury }}</h4>
<hr>
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
</div> </div>

View File

@ -49,7 +49,7 @@
{% if notes is not None %} {% if notes is not None %}
<div class="card-footer text-center"> <div class="card-footer text-center">
{% if my_note is not None %} {% if my_note is not None %}
<button class="btn btn-info" data-bs-toggle="modal" data-bs-target="#updateNotesModal">{% trans "Update notes" %}</button> <button class="btn btn-info" data-bs-toggle="modal" data-bs-target="#{{ my_note.modal_name }}Modal">{% trans "Update notes" %}</button>
{% endif %} {% endif %}
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#updatePassageModal">{% trans "Update" %}</button> <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#updatePassageModal">{% trans "Update" %}</button>
</div> </div>
@ -121,12 +121,12 @@
{% url "participation:passage_update" pk=passage.pk as modal_action %} {% url "participation:passage_update" pk=passage.pk as modal_action %}
{% include "base_modal.html" with modal_id="updatePassage" %} {% include "base_modal.html" with modal_id="updatePassage" %}
{% if my_note is not None %} {% for note in notes.data %}
{% trans "Update notes" as modal_title %} {% trans "Update notes" as modal_title %}
{% trans "Update" as modal_button %} {% trans "Update" as modal_button %}
{% url "participation:update_notes" pk=my_note.pk as modal_action %} {% url "participation:update_notes" pk=note.pk as modal_action %}
{% include "base_modal.html" with modal_id="updateNotes" %} {% include "base_modal.html" with modal_id=note.modal_name %}
{% endif %} {% endfor %}
{% elif user.registration.participates %} {% elif user.registration.participates %}
{% trans "Upload synthesis" as modal_title %} {% trans "Upload synthesis" as modal_title %}
{% trans "Upload" as modal_button %} {% trans "Upload" as modal_button %}
@ -141,9 +141,9 @@
{% if notes is not None %} {% if notes is not None %}
initModal("updatePassage", "{% url "participation:passage_update" pk=passage.pk %}") initModal("updatePassage", "{% url "participation:passage_update" pk=passage.pk %}")
{% if my_note is not None %} {% for note in notes.data %}
initModal("updateNotes", "{% url "participation:update_notes" pk=my_note.pk %}") initModal("{{ note.modal_name }}", "{% url "participation:update_notes" pk=note.pk %}")
{% endif %} {% endfor %}
{% elif user.registration.participates %} {% elif user.registration.participates %}
initModal("uploadSynthesis", "{% url "participation:upload_synthesis" pk=passage.pk %}") initModal("uploadSynthesis", "{% url "participation:upload_synthesis" pk=passage.pk %}")
{% endif %} {% endif %}

View File

@ -1527,9 +1527,9 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
if self.request.user.registration in self.object.pool.juries.all(): if self.request.user.registration in self.object.pool.juries.all():
context["my_note"] = Note.objects.get_or_create(passage=self.object, jury=self.request.user.registration)[0] context["my_note"] = Note.objects.get_or_create(passage=self.object, jury=self.request.user.registration)[0]
context["notes"] = NoteTable([note for note in self.object.notes.all() if note]) context["notes"] = NoteTable(self.object.notes.all())
elif self.request.user.registration.is_admin: elif self.request.user.registration.is_admin:
context["notes"] = NoteTable([note for note in self.object.notes.all() if note]) context["notes"] = NoteTable(self.object.notes.all())
if 'notes' in context and not self.object.observer: if 'notes' in context and not self.object.observer:
# Only display the observer column for 4-teams pools # Only display the observer column for 4-teams pools
context['notes']._sequence.pop() context['notes']._sequence.pop()

View File

@ -1,5 +1,6 @@
function initModal(target, url, content_id = 'form-content') { function initModal(target, url, content_id = 'form-content') {
document.querySelector('[data-bs-target="#' + target + 'Modal"]').addEventListener('click', () => { document.querySelectorAll('[data-bs-target="#' + target + 'Modal"]')
.forEach(elem => elem.addEventListener('click', () => {
let modalBody = document.querySelector("#" + target + "Modal div.modal-body") let modalBody = document.querySelector("#" + target + "Modal div.modal-body")
if (!modalBody.innerHTML.trim()) { if (!modalBody.innerHTML.trim()) {
@ -11,5 +12,5 @@ function initModal(target, url, content_id = 'form-content') {
.then(res => modalBody.innerHTML = res.getElementById(content_id).outerHTML) .then(res => modalBody.innerHTML = res.getElementById(content_id).outerHTML)
.then(() => $('.selectpicker').selectpicker()) // TODO Update that when the library will be JQuery-free .then(() => $('.selectpicker').selectpicker()) // TODO Update that when the library will be JQuery-free
} }
}) }))
} }