On sérialise les modèles pour transmettre en JSON, on améliore le formulaire modal
This commit is contained in:
parent
8a91648bac
commit
a621bb8197
8 changed files with 87 additions and 38 deletions
|
@ -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())
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
10
shared/json/__init__.py
Normal 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
21
shared/json/mixins.py
Normal 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)
|
|
@ -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>
|
||||
</header>
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">{{ modal_title }}</p>
|
||||
<button class="delete" aria-label="close" data-closes="modal-{{ modal_id }}"></button>
|
||||
</header>
|
||||
|
||||
<section class="modal-card-body">
|
||||
<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" %}
|
||||
</section>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<footer class="modal-card-foot">
|
||||
<button class="button is-fullwidth is-outlined is-primary is-light" type="submit">
|
||||
<span class="icon">
|
||||
<i class="fas fa-check"></i>
|
||||
</span>
|
||||
<span>{% trans "Enregistrer" %}</span>
|
||||
</button>
|
||||
<footer class="modal-card-foot">
|
||||
<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 }}">
|
||||
<span class="icon">
|
||||
<i class="fas fa-times"></i>
|
||||
</span>
|
||||
<span>{% trans "Annuler" %}</span>
|
||||
</a>
|
||||
</footer>
|
||||
</form>
|
||||
<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>
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue