Admin page to view an election

This commit is contained in:
Tom Hubrecht 2020-12-19 15:04:04 +01:00
parent 786ac214a8
commit d418fd9e3d
8 changed files with 163 additions and 14 deletions

View file

@ -0,0 +1,23 @@
# Generated by Django 2.2.17 on 2020-12-18 14:52
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("elections", "0001_initial"),
]
operations = [
migrations.RenameField(
model_name="election",
old_name="end_time",
new_name="end",
),
migrations.RenameField(
model_name="election",
old_name="start_time",
new_name="start",
),
]

View file

@ -0,0 +1,23 @@
# Generated by Django 2.2.17 on 2020-12-18 19:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("elections", "0002_auto_20201218_1452"),
]
operations = [
migrations.RenameField(
model_name="election",
old_name="end",
new_name="end_date",
),
migrations.RenameField(
model_name="election",
old_name="start",
new_name="start_date",
),
]

0
elections/mixins.py Normal file
View file

View file

@ -1,6 +1,6 @@
from django.contrib.auth import get_user_model
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.contrib.auth import get_user_model
User = get_user_model() User = get_user_model()
@ -10,8 +10,8 @@ class Election(models.Model):
short_name = models.SlugField(_("nom bref"), unique=True) short_name = models.SlugField(_("nom bref"), unique=True)
description = models.TextField(_("description"), blank=True) description = models.TextField(_("description"), blank=True)
start_time = models.DateTimeField(_("date et heure de début")) start_date = models.DateTimeField(_("date et heure de début"))
end_time = models.DateTimeField(_("date et heure de fin")) end_date = models.DateTimeField(_("date et heure de fin"))
created_by = models.ForeignKey( created_by = models.ForeignKey(
User, on_delete=models.SET_NULL, blank=True, null=True User, on_delete=models.SET_NULL, blank=True, null=True

View file

@ -4,11 +4,35 @@
{% block content %} {% block content %}
<h1 class="title">{{ election.name }}</h1> <div class="level">
<div class="level-left">
<div class="level-item">
<h1 class="title">{{ election.name }}</h1>
</div>
<div class="level-item">
<span class="tag is-medium is-primary">{{ election.start_date|date:"d/m/Y H:i" }}</span>
<span class="icon">
<i class="fas fa-long-arrow-alt-right"></i>
</span>
<span class="tag is-medium is-primary">{{ election.end_date|date:"d/m/Y H:i" }}</span>
</div>
</div>
<div class="level-right">
<div class="level-item">
<a class="button is-light is-outlined is-primary" href="{% url 'election.update' election.pk %}">
<span class="icon">
<i class="fas fa-edit"></i>
</span>
&nbsp;
{% trans "Modifier" %}
</a>
</div>
</div>
</div>
<hr> <hr>
<div class="message is-info"> <div class="message is-primary">
<p class="message-body">{{ election.description }}</p> <div class="message-body">{{ election.description|linebreaksbr }}</div>
</div> </div>
<div class="container"> <div class="container">
@ -16,15 +40,33 @@
{% for q in election.questions.all %} {% for q in election.questions.all %}
<div class="panel"> <div class="panel">
<div class="panel-heading is-size-6"> <div class="panel-heading is-size-6">
<a class="tag is-small is-outlined is-light is-danger">{% trans "Supprimer" %}</a> {{ q.text }}&nbsp;
<a class="tag is-small is-outlined is-light is-info">{% trans "Modifier" %}</a> <a class="tag is-small is-outlined is-light is-danger">
{{ q.text }} <span class="icon">
<i class="fas fa-times"></i>
</span>
{% trans "Supprimer" %}
</a>
<a class="tag is-small is-outlined is-light is-info">
<span class="icon">
<i class="fas fa-edit"></i>
</span>
{% trans "Modifier" %}
</a>
</div> </div>
{% for o in q.options.all %} {% for o in q.options.all %}
<div class="panel-block"> <div class="panel-block">
<div class="tags has-addons"> <div class="tags has-addons">
<a class="tag is-danger">{% trans "Supprimer" %}</a> <a class="tag is-danger" title="{% trans "Supprimer" %}">
<a class="tag is-info">{% trans "Modifier" %}</a> <span class="icon">
<i class="fas fa-times"></i>
</span>
</a>
<a class="tag is-info" title="{% trans "Modifier" %}">
<span class="icon">
<i class="fas fa-edit"></i>
</span>
</a>
</div> </div>
&nbsp;&nbsp;{{ o.text }} &nbsp;&nbsp;{{ o.text }}
</div> </div>

View file

@ -0,0 +1,51 @@
{% extends "elections/base.html" %}
{% load i18n static %}
{% block extra_head %}
{# DateTimePicker #}
<script src={% static 'vendor/datepicker/datetimepicker.js' %}></script>
<link rel="stylesheet" href="{% static 'vendor/datepicker/datetimepicker.css' %}">
<script>
$(document).ready(function($) {
$('#id_start_date').datetimepicker({
format: 'Y-m-d H:i'
});
$('#id_end_date').datetimepicker({
format: 'Y-m-d H:i'
});
});
</script>
{% endblock %}
{% block content %}
{% for error in form.non_field_errors %}
<div class="notification is-danger">
{{ error }}
</div>
{% endfor %}
<h1 class="title">{% trans "Modification d'une élection" %}</h1>
<hr>
<div class="container">
<form action="" method="post">
{% csrf_token %}
{% include "elections/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">{% trans "Enregistrer" %}</button>
</div>
<div class="control">
<a class="button is-primary" href="{% url 'election.admin' election.pk %}">{% trans "Retour" %}</a>
</div>
</div>
</form>
</div>
{% endblock %}

View file

@ -4,6 +4,7 @@ from . import views
urlpatterns = [ urlpatterns = [
path("create/", views.ElectionCreateView.as_view(), name="election.create"), path("create/", views.ElectionCreateView.as_view(), name="election.create"),
path("admin/<int:pk>", views.ElectionAdminView.as_view(), name="election.admin"),
path("update/<int:pk>", views.ElectionUpdateView.as_view(), name="election.update"), path("update/<int:pk>", views.ElectionUpdateView.as_view(), name="election.update"),
path("view/<int:pk>", views.ElectionView.as_view(), name="election.view"), path("view/<int:pk>", views.ElectionView.as_view(), name="election.view"),
path("vote/<int:pk>", views.VoteView.as_view(), name="election.vote"), path("vote/<int:pk>", views.VoteView.as_view(), name="election.vote"),

View file

@ -6,7 +6,7 @@ from django.urls import reverse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DetailView, UpdateView from django.views.generic import CreateView, DetailView, UpdateView
from .forms import ElectionCreateForm, OptionFormSet from .forms import OptionFormSet
from .models import Election, Option, Question from .models import Election, Option, Question
# TODO: access control *everywhere* # TODO: access control *everywhere*
@ -14,14 +14,23 @@ from .models import Election, Option, Question
class ElectionCreateView(SuccessMessageMixin, CreateView): class ElectionCreateView(SuccessMessageMixin, CreateView):
model = Election model = Election
form_class = ElectionCreateForm fields = ["name", "description", "start_date", "end_date"]
template_name = "elections/election_create.html" template_name = "elections/election_create.html"
success_message = _("Élection crée avec succès !") success_message = _("Élection crée avec succès !")
# TODO : only the creator can edit the election and view the admin panel
class ElectionAdminView(DetailView):
model = Election
template_name = "elections/election_admin.html"
def get_queryset(self):
return super().get_queryset().prefetch_related("questions__options")
class ElectionUpdateView(SuccessMessageMixin, UpdateView): class ElectionUpdateView(SuccessMessageMixin, UpdateView):
model = Election model = Election
fields = ["name", "description", "start_time", "end_time"] fields = ["name", "description", "start_date", "end_date"]
success_message = _("Élection modifiée avec succès !") success_message = _("Élection modifiée avec succès !")
def get_queryset(self): def get_queryset(self):