Tweaks on templates and foundation for uploading a file
This commit is contained in:
parent
e7db47116e
commit
5c7e2238d8
9 changed files with 140 additions and 18 deletions
|
@ -24,6 +24,10 @@ class ElectionForm(forms.ModelForm):
|
|||
fields = ["name", "description", "restricted", "start_date", "end_date"]
|
||||
|
||||
|
||||
class UploadVotersForm(forms.Form):
|
||||
csv_file = forms.FileField(label=_("Sélectionnez un fichier .csv"))
|
||||
|
||||
|
||||
class QuestionForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Question
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
</div>
|
||||
|
||||
<div class="level-right">
|
||||
{% if election.start_date > current_time %}
|
||||
|
||||
{# Lien pour la modification #}
|
||||
{# Lien pour la modification et l'upload des votant·e·s #}
|
||||
{% if election.start_date > current_time %}
|
||||
<div class="level-item">
|
||||
<a class="button is-light is-outlined is-primary" href="{% url 'election.update' election.pk %}">
|
||||
<span class="icon">
|
||||
|
@ -33,10 +33,22 @@
|
|||
<span>{% trans "Modifier" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if election.restricted %}
|
||||
<div class="level-item">
|
||||
<a class="button is-light is-outlined is-primary" href="{% url 'election.upload-voters' election.pk %}">
|
||||
<span class="icon">
|
||||
<i class="fas fa-file-import"></i>
|
||||
</span>
|
||||
<span>{% trans "Importer une liste de votant·e·s" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% elif election.end_date < current_time %}
|
||||
{% if not election.tallied %}
|
||||
|
||||
{# Lien pour le dépouillement #}
|
||||
{% if not election.tallied %}
|
||||
<div class="level-item">
|
||||
<a class="button is-light is-outlined is-primary" href="{% url 'election.tally' election.pk %}">
|
||||
<span class="icon">
|
||||
|
@ -45,9 +57,9 @@
|
|||
<span>{% trans "Dépouiller" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
{# Lien pour la publication des résultats #}
|
||||
{% else %}
|
||||
<div class="level-item">
|
||||
<a class="button is-outlined is-primary" href="{% url 'election.publish' election.pk %}">
|
||||
<span class="icon">
|
||||
|
|
60
elections/templates/elections/upload_voters.html
Normal file
60
elections/templates/elections/upload_voters.html
Normal file
|
@ -0,0 +1,60 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
|
||||
{% block extra_head %}
|
||||
<script>
|
||||
$(document).ready(function($) {
|
||||
const fileInput = document.querySelector('#import-voters input[type=file]');
|
||||
fileInput.onchange = () => {
|
||||
if (fileInput.files.length > 0) {
|
||||
const fileName = document.querySelector('#import-voters .file-name');
|
||||
fileName.textContent = fileInput.files[0].name;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1 class="title">{% trans "Importer une liste de votant·e·s" %}</h1>
|
||||
<hr>
|
||||
|
||||
<div class="message is-warning">
|
||||
<div class="message-body">
|
||||
{% trans "Importez un fichier au format CSV, avec sur la première colonne les prénoms, sur la deuxième le nom et la troisième l'adresse email. Soit :<br><br><pre>Prénom_1,Nom_1,mail_1@machin.test<br>Prénom_2,Nom_2,mail_2@bidule.test<br>...</pre>" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="columns is-centered">
|
||||
<div class="column is-two-thirds">
|
||||
<form action="" method="post" id="import-voters">
|
||||
{% csrf_token %}
|
||||
|
||||
{% include "forms/form.html" with errors=False %}
|
||||
|
||||
<div class="field is-grouped is-centered">
|
||||
<div class="control is-expanded">
|
||||
<button class="button is-fullwidth is-outlined is-primary is-light">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-check"></i>
|
||||
</span>
|
||||
<span>{% trans "Enregistrer" %}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-primary" href="{% url 'election.admin' election.pk %}">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-undo-alt"></i>
|
||||
</span>
|
||||
<span>{% trans "Retour" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -7,6 +7,11 @@ urlpatterns = [
|
|||
path("create/", views.ElectionCreateView.as_view(), name="election.create"),
|
||||
path("created/", views.ElectionListView.as_view(), name="election.created"),
|
||||
path("admin/<int:pk>", views.ElectionAdminView.as_view(), name="election.admin"),
|
||||
path(
|
||||
"upload-voters/<int:pk>",
|
||||
views.ElectionUploadVotersView.as_view(),
|
||||
name="election.upload-voters",
|
||||
),
|
||||
path("update/<int:pk>", views.ElectionUpdateView.as_view(), name="election.update"),
|
||||
path("tally/<int:pk>", views.ElectionTallyView.as_view(), name="election.tally"),
|
||||
path(
|
||||
|
|
|
@ -10,12 +10,19 @@ from django.utils.translation import gettext_lazy as _
|
|||
from django.views.generic import (
|
||||
CreateView,
|
||||
DetailView,
|
||||
FormView,
|
||||
ListView,
|
||||
RedirectView,
|
||||
UpdateView,
|
||||
)
|
||||
|
||||
from .forms import ElectionForm, OptionForm, OptionFormSet, QuestionForm
|
||||
from .forms import (
|
||||
ElectionForm,
|
||||
OptionForm,
|
||||
OptionFormSet,
|
||||
QuestionForm,
|
||||
UploadVotersForm,
|
||||
)
|
||||
from .mixins import CreatorOnlyEditMixin, CreatorOnlyMixin, OpenElectionOnlyMixin
|
||||
from .models import Election, Option, Question
|
||||
|
||||
|
@ -63,11 +70,13 @@ class ElectionCreateView(SuccessMessageMixin, CreateView):
|
|||
return super().form_valid(form)
|
||||
|
||||
|
||||
# TODO : only the creator can edit the election and view the admin panel
|
||||
class ElectionAdminView(CreatorOnlyMixin, DetailView):
|
||||
model = Election
|
||||
template_name = "elections/election_admin.html"
|
||||
|
||||
def get_next_url(self):
|
||||
return reverse("election.view", args=[self.object.pk])
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs.update({"current_time": timezone.now()})
|
||||
return super().get_context_data(**kwargs)
|
||||
|
@ -76,6 +85,19 @@ class ElectionAdminView(CreatorOnlyMixin, DetailView):
|
|||
return super().get_queryset().prefetch_related("questions__options")
|
||||
|
||||
|
||||
class ElectionUploadVotersView(CreatorOnlyEditMixin, FormView):
|
||||
model = Election
|
||||
form_class = UploadVotersForm
|
||||
template_name = "elections/upload_voters.html"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
pass
|
||||
|
||||
|
||||
class ElectionListView(CreatorOnlyMixin, ListView):
|
||||
model = Election
|
||||
template_name = "elections/election_list.html"
|
||||
|
@ -290,7 +312,7 @@ class VoteView(OpenElectionOnlyMixin, DetailView):
|
|||
model = Question
|
||||
template_name = "elections/vote.html"
|
||||
|
||||
def get_newt_url(self):
|
||||
def get_next_url(self):
|
||||
return reverse("election.view", args=[self.object.election.pk])
|
||||
|
||||
def get_success_url(self):
|
||||
|
|
|
@ -94,6 +94,8 @@ class LogoutView(auth_views.LogoutView):
|
|||
logged in via CAS.
|
||||
"""
|
||||
|
||||
template_name = "auth/logout.html"
|
||||
|
||||
def setup(self, request):
|
||||
super().setup(request)
|
||||
if "CASCONNECTED" in request.session:
|
||||
|
|
12
shared/templates/auth/logout.html
Normal file
12
shared/templates/auth/logout.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
|
||||
{% block auth %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1 class="title">{% trans "Vous avez bien été déconnecté." %}</h1>
|
||||
<hr>
|
||||
|
||||
{% endblock %}
|
|
@ -55,7 +55,7 @@
|
|||
</div>
|
||||
|
||||
<div class="level-item ml-3">
|
||||
<a class="icon is-size-1 has-text-white" href="{% url 'auth.logout' %}?next=/{{ view.get_next_url }}">
|
||||
<a class="icon is-size-1 has-text-white" href="{% url 'auth.logout' %}?next={% if view.get_next_url %}{{ view.get_next_url }}{% else %}/{% endif %}">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
{% load bulma_utils i18n %}
|
||||
|
||||
<label class="label {% if field.field.required %}{{ form.required_css_class }}{% endif %}">
|
||||
{{ field.label }}
|
||||
{{ field.label_tag }}
|
||||
</label>
|
||||
|
||||
<div class="control">
|
||||
|
||||
<label class="file-label">
|
||||
{{ field|bulmafy:'file-input' }}
|
||||
<span class="file-cta">
|
||||
<span class="file-icon">
|
||||
<i class="fas fa-upload"></i>
|
||||
<div class="file has-name">
|
||||
<label class="file-label">
|
||||
{{ field|bulmafy:'file-input' }}
|
||||
<span class="file-cta">
|
||||
<span class="file-icon">
|
||||
<i class="fas fa-upload"></i>
|
||||
</span>
|
||||
<span class="file-label">
|
||||
{% trans "Choisissez un fichier..." %}
|
||||
</span>
|
||||
</span>
|
||||
<span class="file-label">
|
||||
{% trans "Choisissez un fichier..." %}
|
||||
<span class="file-name">
|
||||
{% trans "Aucun fichier sélectionné" %}
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{% for error in field.errors %}
|
||||
<span class="help is-danger {{ form.error_css_class }}">{{ error }}</span>
|
||||
|
|
Loading…
Reference in a new issue