Add update note menu

This commit is contained in:
Yohann D'ANELLO 2021-01-14 18:21:22 +01:00
parent be8904079d
commit ef785a5eb8
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
8 changed files with 69 additions and 8 deletions

View File

@ -12,6 +12,8 @@ class ParticipationConfig(AppConfig):
name = 'participation' name = 'participation'
def ready(self): def ready(self):
from participation.signals import create_team_participation, update_mailing_list from participation.signals import create_notes, create_team_participation, update_mailing_list
pre_save.connect(update_mailing_list, "participation.Team") pre_save.connect(update_mailing_list, "participation.Team")
post_save.connect(create_team_participation, "participation.Team") post_save.connect(create_team_participation, "participation.Team")
post_save.connect(create_notes, "participation.Passage")
post_save.connect(create_notes, "participation.Pool")

View File

@ -9,7 +9,7 @@ from django.core.exceptions import ValidationError
from django.utils import formats from django.utils import formats
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from .models import Participation, Passage, Pool, Team, Tournament, Solution, Synthesis from .models import Note, Participation, Passage, Pool, Team, Tournament, Solution, Synthesis
class TeamForm(forms.ModelForm): class TeamForm(forms.ModelForm):
@ -173,3 +173,10 @@ class SynthesisForm(forms.ModelForm):
class Meta: class Meta:
model = Synthesis model = Synthesis
fields = ('type', 'file',) fields = ('type', 'file',)
class NoteForm(forms.ModelForm):
class Meta:
model = Note
fields = ('defender_writing', 'defender_oral', 'opponent_writing',
'opponent_oral', 'reporter_writing', 'reporter_oral', )

View File

@ -379,7 +379,8 @@ class Passage(models.Model):
final_solution=self.pool.tournament.final) final_solution=self.pool.tournament.final)
def avg(self, iterator) -> int: def avg(self, iterator) -> int:
return sum(iterator) / len(list(iterator)) items = [i for i in iterator if i]
return sum(items) / len(items) if items else 0
@property @property
def average_defender_writing(self): def average_defender_writing(self):
@ -581,6 +582,9 @@ class Note(models.Model):
default=0, default=0,
) )
def get_absolute_url(self):
return reverse_lazy("participation:passage_detail", args=(self.passage.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)

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 typing import Union
from participation.models import Participation, Team from participation.models import Note, Participation, Passage, Pool, Team
from tfjm.lists import get_sympa_client from tfjm.lists import get_sympa_client
@ -33,3 +34,13 @@ def update_mailing_list(instance: Team, **_):
for coach in instance.coachs.all(): for coach in instance.coachs.all():
get_sympa_client().subscribe(coach.user.email, f"equipe-{instance.trigram.lower()}", False, get_sympa_client().subscribe(coach.user.email, f"equipe-{instance.trigram.lower()}", False,
f"{coach.user.first_name} {coach.user.last_name}") f"{coach.user.first_name} {coach.user.last_name}")
def create_notes(instance: Union[Passage, Pool], **_):
if isinstance(instance, Pool):
for passage in instance.passages.all():
create_notes(passage)
return
for jury in instance.pool.juries.all():
Note.objects.get_or_create(jury=jury, passage=instance)

View File

@ -0,0 +1,13 @@
{% extends "base.html" %}
{% load crispy_forms_filters i18n %}
{% block content %}
<form method="post">
<div id="form-content">
{% csrf_token %}
{{ form|crispy }}
</div>
<button class="btn btn-primary" type="submit">{% trans "Update" %}</button>
</form>
{% endblock content %}

View File

@ -40,6 +40,7 @@
</div> </div>
{% if user.registration.is_admin %} {% if user.registration.is_admin %}
<div class="card-footer text-center"> <div class="card-footer text-center">
<button class="btn btn-info" data-toggle="modal" data-target="#updateNotesModal">{% trans "Update notes" %}</button>
<button class="btn btn-primary" data-toggle="modal" data-target="#updatePassageModal">{% trans "Update" %}</button> <button class="btn btn-primary" data-toggle="modal" data-target="#updatePassageModal">{% trans "Update" %}</button>
</div> </div>
{% elif user.registration.participates %} {% elif user.registration.participates %}
@ -54,6 +55,11 @@
{% trans "Update" as modal_button %} {% trans "Update" as modal_button %}
{% 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" %}
{% trans "Update notes" as modal_title %}
{% trans "Update" as modal_button %}
{% url "participation:update_notes" pk=my_note.pk as modal_action %}
{% include "base_modal.html" with modal_id="updateNotes" %}
{% 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 %}
@ -71,6 +77,12 @@
if (!modalBody.html().trim()) if (!modalBody.html().trim())
modalBody.load("{% url "participation:passage_update" pk=passage.pk %} #form-content") modalBody.load("{% url "participation:passage_update" pk=passage.pk %} #form-content")
}); });
$('button[data-target="#updateNotesModal"]').click(function() {
let modalBody = $("#updateNotesModal div.modal-body");
if (!modalBody.html().trim())
modalBody.load("{% url "participation:update_notes" pk=my_note.pk %} #form-content")
});
{% elif user.registration.participates %} {% elif user.registration.participates %}
$('button[data-target="#uploadSynthesisModal"]').click(function() { $('button[data-target="#uploadSynthesisModal"]').click(function() {
let modalBody = $("#uploadSynthesisModal div.modal-body"); let modalBody = $("#uploadSynthesisModal div.modal-body");

View File

@ -5,7 +5,7 @@ from django.urls import path
from django.views.generic import TemplateView from django.views.generic import TemplateView
from .views import CreateTeamView, JoinTeamView, \ from .views import CreateTeamView, JoinTeamView, \
MyParticipationDetailView, MyTeamDetailView, ParticipationDetailView, \ MyParticipationDetailView, MyTeamDetailView, NoteUpdateView, ParticipationDetailView, \
PassageCreateView, PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, \ PassageCreateView, PassageDetailView, PassageUpdateView, PoolCreateView, PoolDetailView, \
PoolUpdateView, PoolUpdateTeamsView, TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, \ PoolUpdateView, PoolUpdateTeamsView, TeamAuthorizationsView, TeamDetailView, TeamLeaveView, TeamListView, \
TeamUpdateView, TournamentCreateView, TournamentDetailView, TournamentListView, TournamentUpdateView, \ TeamUpdateView, TournamentCreateView, TournamentDetailView, TournamentListView, TournamentUpdateView, \
@ -38,5 +38,6 @@ urlpatterns = [
path("pools/passages/<int:pk>/", PassageDetailView.as_view(), name="passage_detail"), path("pools/passages/<int:pk>/", PassageDetailView.as_view(), name="passage_detail"),
path("pools/passages/<int:pk>/update/", PassageUpdateView.as_view(), name="passage_update"), path("pools/passages/<int:pk>/update/", PassageUpdateView.as_view(), name="passage_update"),
path("pools/passages/<int:pk>/solution/", SynthesisUploadView.as_view(), name="upload_synthesis"), path("pools/passages/<int:pk>/solution/", SynthesisUploadView.as_view(), name="upload_synthesis"),
path("pools/passages/notes/<int:pk>/", NoteUpdateView.as_view(), name="update_notes"),
path("chat/", TemplateView.as_view(template_name="participation/chat.html"), name="chat") path("chat/", TemplateView.as_view(template_name="participation/chat.html"), name="chat")
] ]

View File

@ -23,9 +23,9 @@ from tfjm.lists import get_sympa_client
from tfjm.matrix import Matrix from tfjm.matrix import Matrix
from tfjm.views import AdminMixin from tfjm.views import AdminMixin
from .forms import JoinTeamForm, ParticipationForm, PassageForm, PoolForm, PoolTeamsForm, RequestValidationForm, \ from .forms import JoinTeamForm, NoteForm, ParticipationForm, PassageForm, PoolForm, PoolTeamsForm, \
TeamForm, TournamentForm, ValidateParticipationForm, SolutionForm, SynthesisForm RequestValidationForm, TeamForm, TournamentForm, ValidateParticipationForm, SolutionForm, SynthesisForm
from .models import Participation, Passage, Pool, Team, Tournament, Solution, Synthesis from .models import Note, Participation, Passage, Pool, Team, Tournament, Solution, Synthesis
from .tables import TeamTable, TournamentTable, ParticipationTable, PoolTable from .tables import TeamTable, TournamentTable, ParticipationTable, PoolTable
@ -513,6 +513,12 @@ class PassageCreateView(AdminMixin, CreateView):
class PassageDetailView(LoginRequiredMixin, DetailView): class PassageDetailView(LoginRequiredMixin, DetailView):
model = Passage model = Passage
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.request.user.registration in self.object.pool.juries.all():
context["my_note"] = Note.objects.get(passage=self.object, jury=self.request.user.registration)
return context
class PassageUpdateView(AdminMixin, UpdateView): class PassageUpdateView(AdminMixin, UpdateView):
model = Passage model = Passage
@ -551,3 +557,8 @@ class SynthesisUploadView(LoginRequiredMixin, FormView):
def get_success_url(self): def get_success_url(self):
return reverse_lazy("participation:passage_detail", args=(self.passage.pk,)) return reverse_lazy("participation:passage_detail", args=(self.passage.pk,))
class NoteUpdateView(LoginRequiredMixin, UpdateView):
model = Note
form_class = NoteForm