On sérialise les modèles pour transmettre en JSON, on améliore le formulaire modal

This commit is contained in:
Tom Hubrecht 2021-09-16 16:43:27 +02:00
parent 8a91648bac
commit a621bb8197
8 changed files with 87 additions and 38 deletions

View file

@ -7,6 +7,7 @@ from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _
from shared.auth import CONNECTION_METHODS
from shared.json import Serializer
from shared.utils import choices_length
from .staticdefs import (
@ -86,7 +87,7 @@ class Election(models.Model):
ordering = ["-start_date", "-end_date"]
class Question(models.Model):
class Question(Serializer, models.Model):
election = models.ForeignKey(
Election, related_name="questions", on_delete=models.CASCADE
)
@ -110,6 +111,8 @@ class Question(models.Model):
blank=True,
)
serializable_fields = ["text_en", "text_fr", "type"]
def is_form_valid(self, vote_form):
validate_function = getattr(ValidateFunctions, VALIDATE_FUNCTIONS[self.type])
return vote_form.is_valid() and validate_function(vote_form)
@ -154,7 +157,7 @@ class Question(models.Model):
ordering = ["id"]
class Option(models.Model):
class Option(Serializer, models.Model):
question = models.ForeignKey(
Question, related_name="options", on_delete=models.CASCADE
)
@ -171,6 +174,8 @@ class Option(models.Model):
# For now, we store the amount of votes received after the election is tallied
nb_votes = models.PositiveSmallIntegerField(_("nombre de votes reçus"), default=0)
serializable_fields = ["text_fr", "text_en", "abbreviation"]
def save(self, *args, **kwargs):
# On enlève les espaces et on passe tout en majuscules
self.abbreviation = "".join(self.abbreviation.upper().split())

View file

@ -9,7 +9,7 @@
</span>
</a>
<a class="tag is-info is-light is-outlined has-tooltip-primary mb-0 modal-button" data-tooltip="{% trans "Modifier" %}" data-post_url="{% url 'election.mod-option' o.pk %}" data-target="modal-option" data-o_en="{{ o.text_en }}" data-o_fr="{{ o.text_fr }}" data-abbr="{{ o.abbreviation }}" data-title="{% trans "Modifier l'option" %}" data-type="option" data-parent="o_{{ o.pk }}">
<a class="tag is-info is-light is-outlined has-tooltip-primary mb-0 modal-button" data-tooltip="{% trans "Modifier" %}" data-post_url="{% url 'election.mod-option' o.pk %}" data-target="modal-option" data-json='{{ o.to_json }}' data-title="{% trans "Modifier l'option" %}" data-type="option" data-parent="o_{{ o.pk }}">
<span class="icon">
<i class="fas fa-edit"></i>
</span>

View file

@ -21,7 +21,7 @@
</span>
</a>
<a class="tag is-outlined is-light is-info ml-1 modal-button" data-post_url="{% url 'election.mod-question' q.pk %}" data-target="modal-question" data-q_type="{{ q.type }}" data-q_en="{{ q.text_en }}" data-q_fr="{{ q.text_fr }}" data-title="{% trans "Modifier la question" %}" data-type="question" data-parent="q_{{ q.pk }}">
<a class="tag is-outlined is-light is-info ml-1 modal-button" data-post_url="{% url 'election.mod-question' q.pk %}" data-target="modal-question" data-json='{{ q.to_json }}' data-title="{% trans "Modifier la question" %}" data-parent="q_{{ q.pk }}">
<span class="icon-text">
<span class="icon">
<i class="fas fa-edit"></i>
@ -56,7 +56,7 @@
{# Rajout d'une option #}
{% if q.election.start_date > current_time %}
<div class="panel-block">
<button class="button modal-button is-primary is-outlined is-fullwidth option" data-post_url="{% url 'election.add-option' q.pk %}" data-target="modal-option" data-title="{% trans "Rajouter une option" %}" data-type="option" data-next="options_{{ q.pk }}">
<button class="button modal-button is-primary is-outlined is-fullwidth option" data-post_url="{% url 'election.add-option' q.pk %}" data-target="modal-option" data-title="{% trans "Rajouter une option" %}" data-json='{"text_fr": "", "text_en": "", "abbreviation": ""}' data-next="options_{{ q.pk }}">
<span class="icon">
<i class="fas fa-plus"></i>
</span>

View file

@ -10,14 +10,10 @@
f.dataset.next = b.dataset.next;
f.dataset.origin = b.dataset.parent
if (b.dataset.type == 'question') {
_$('[name="text_fr"]', f, false).value = b.dataset.q_fr || '';
_$('[name="text_en"]', f, false).value = b.dataset.q_en || '';
_$('[name="type"]', f, false).value = b.dataset.q_type || 'assentiment';
} else if (b.dataset.type == 'option') {
_$('[name="text_fr"]', f, false).value = b.dataset.o_fr || '';
_$('[name="text_en"]', f, false).value = b.dataset.o_en || '';
_$('[name="abbreviation"]', f, false).value = b.dataset.abbr || '';
const d = JSON.parse(b.dataset.json);
for (const [k, v] of Object.entries(d)) {
_$(`[name='${k}']`, f, false).value = v;
}
});
}
@ -279,7 +275,7 @@
<div class="columns is-centered" id="q_add">
<div class="column is-two-thirds">
<button class="button modal-button is-primary is-outlined is-fullwidth question" data-post_url="{% url 'election.add-question' election.pk %}" data-target="modal-question" data-title="{% trans "Rajouter une question" %}" data-next="questions" data-type="question">
<button class="button modal-button is-primary is-outlined is-fullwidth question" data-post_url="{% url 'election.add-question' election.pk %}" data-target="modal-question" data-title="{% trans "Rajouter une question" %}" data-next="questions" data-json='{"text_fr": "", "text_en": "", "type": "assentiment"}'>
<span class="icon">
<i class="fas fa-question"></i>
</span>

View file

@ -19,7 +19,7 @@ from django.views.generic import (
View,
)
from shared.json.views import JsonCreateView, JsonDeleteView, JsonUpdateView
from shared.json import JsonCreateView, JsonDeleteView, JsonUpdateView
from shared.views import BackgroundUpdateView, TimeMixin
from .forms import (
@ -71,6 +71,23 @@ class ElectionCreateView(AdminOnlyMixin, SuccessMessageMixin, CreateView):
return super().form_valid(form)
class ElectionDeleteView(CreatorOnlyMixin, BackgroundUpdateView):
model = Election
pattern_name = "election.list"
def get_object(self, queryset=None):
obj = self.get_object()
# On ne peut supprimer que les élections n'ayant pas eu de vote et dont
# le mail d'annonce n'a pas été fait
if obj.voters.exists() or obj.send_election_mail:
raise Http404
return obj
def get(self, request, *args, **kwargs):
self.get_object().delete()
return super().get(request, *args, **kwargs)
class ElectionAdminView(CreatorOnlyMixin, TimeMixin, DetailView):
model = Election
template_name = "elections/election_admin.html"

10
shared/json/__init__.py Normal file
View file

@ -0,0 +1,10 @@
from .mixins import Serializer # noqa
from .views import JsonCreateView, JsonDeleteView, JsonDetailView, JsonUpdateView
__all__ = [
"Serializer",
"JsonCreateView",
"JsonDeleteView",
"JsonDetailView",
"JsonUpdateView",
]

21
shared/json/mixins.py Normal file
View file

@ -0,0 +1,21 @@
import json
class Serializer:
serializable_fields = []
def get_serializable_fields(self):
return self.serializable_fields
def to_json(self):
data = {}
for field in self.get_serializable_fields():
if hasattr(self, field):
data.update({field: getattr(self, field)})
else:
raise AttributeError(
"This object does not have a field named '{}'".format(field)
)
return json.dumps(data)

View file

@ -3,33 +3,33 @@
<div class="modal" id="modal-{{ modal_id }}">
<div class="modal-background" data-closes="modal-{{ modal_id }}"></div>
<div class="modal-card">
<form method="post" action="{{ post_url }}" data-modal="modal-{{ modal_id }}">
{% csrf_token %}
<header class="modal-card-head">
<p class="modal-card-title">{{ modal_title }}</p>
<a class="delete" aria-label="close" data-closes="modal-{{ modal_id }}"></a>
<button class="delete" aria-label="close" data-closes="modal-{{ modal_id }}"></button>
</header>
<section class="modal-card-body">
<form method="post" action="{{ post_url }}" id="form-{{ modal_id }}" data-modal="modal-{{ modal_id }}">
{% csrf_token %}
{% include "forms/form.html" %}
</form>
</section>
<footer class="modal-card-foot">
<button class="button is-fullwidth is-outlined is-primary is-light" type="submit">
<button class="button is-fullwidth is-outlined is-primary is-light" form="form-{{ modal_id }}" type="submit">
<span class="icon">
<i class="fas fa-check"></i>
</span>
<span>{% trans "Enregistrer" %}</span>
</button>
<a class="button is-primary button-close" data-closes="modal-{{ modal_id }}">
<button class="button is-primary button-close" data-closes="modal-{{ modal_id }}">
<span class="icon">
<i class="fas fa-times"></i>
</span>
<span>{% trans "Annuler" %}</span>
</a>
</button>
</footer>
</form>
</div>
</div>