Admin page to view an election
This commit is contained in:
parent
786ac214a8
commit
d418fd9e3d
8 changed files with 163 additions and 14 deletions
23
elections/migrations/0002_auto_20201218_1452.py
Normal file
23
elections/migrations/0002_auto_20201218_1452.py
Normal 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",
|
||||||
|
),
|
||||||
|
]
|
23
elections/migrations/0003_auto_20201218_1954.py
Normal file
23
elections/migrations/0003_auto_20201218_1954.py
Normal 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
0
elections/mixins.py
Normal 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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
{% 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 }}
|
||||||
<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>
|
||||||
{{ o.text }}
|
{{ o.text }}
|
||||||
</div>
|
</div>
|
||||||
|
|
51
elections/templates/elections/election_update.html
Normal file
51
elections/templates/elections/election_update.html
Normal 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 %}
|
|
@ -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"),
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Loading…
Reference in a new issue