From 3d5befba8e84fa7f80f0cc1b573bc2fd45fba4a2 Mon Sep 17 00:00:00 2001 From: Leo Fahrbach <leo.fahrbach@tum.de> Date: Fri, 6 Aug 2021 13:23:53 +0200 Subject: [PATCH] Renamed Election Fields: - result_unpublished -> result_published - disable_abstention -> enable_abstention --- management/forms.py | 8 ++--- .../templates/management/add_election.html | 6 ++-- management/templates/management/election.html | 2 +- management/views.py | 2 +- requirements_dev.txt | 1 + vote/forms.py | 8 ++--- ...name_unpublished_and_disable_abstention.py | 30 +++++++++++++++++++ vote/models.py | 4 +-- vote/selectors.py | 4 +-- vote/templates/vote/index_election_item.html | 2 +- .../vote/spectator_election_item.html | 2 +- vote/templates/vote/vote.html | 2 +- vote/tests.py | 20 +++++++------ 13 files changed, 62 insertions(+), 29 deletions(-) create mode 100644 vote/migrations/0029_rename_unpublished_and_disable_abstention.py diff --git a/management/forms.py b/management/forms.py index 8fd739f..6f22792 100644 --- a/management/forms.py +++ b/management/forms.py @@ -208,7 +208,7 @@ class AddElectionForm(forms.ModelForm, TemplateStringForm): model = Election fields = ( 'title', 'start_date', 'end_date', 'session', 'max_votes_yes', 'voters_self_apply', 'send_emails_on_start', - 'remind_text', 'disable_abstention', 'result_unpublished') + 'remind_text', 'enable_abstention', 'result_published') labels = { 'title': 'Election Name', @@ -217,10 +217,10 @@ class AddElectionForm(forms.ModelForm, TemplateStringForm): 'voters_self_apply': 'Voters can apply for the election', 'send_emails_on_start': 'Voters receive an e-mail when the election starts<br>' '(useful for elections that last several days)', - 'disable_abstention': 'Disable the option to abstain in this election<br>' - '(only YES and NO votes will be allowed)', + 'enable_abstention': 'Enable the option to abstain in this election<br>' + '(YES, NO and ABSTENTION votes will be allowed)', 'remind_text': '', - 'result_unpublished': 'Disable auto publish of the election results', + 'result_published': 'Automatically publish the election results', } def clean_remind_text(self): diff --git a/management/templates/management/add_election.html b/management/templates/management/add_election.html index 17873c0..47df2a6 100644 --- a/management/templates/management/add_election.html +++ b/management/templates/management/add_election.html @@ -17,7 +17,7 @@ {{ form|as_crispy_errors }} {% for field in form %} - {% if field.html_name != "remind_text" and field.html_name != "send_emails_on_start" and field.html_name != "voters_self_apply" and field.html_name != "email" and field.html_name != 'disable_abstention' and field.html_name != 'result_unpublished' %} + {% if field.html_name != "remind_text" and field.html_name != "send_emails_on_start" and field.html_name != "voters_self_apply" and field.html_name != "email" and field.html_name != 'enable_abstention' and field.html_name != 'result_published' %} {{ field|as_crispy_field }} {% endif %} {% endfor %} @@ -32,8 +32,8 @@ </span> </div> <div id="collapseOne" class="card-body collapse{% if form.remind_text.value %} show{% endif %}"> - {{ form.result_unpublished|as_crispy_field }} - {{ form.disable_abstention|as_crispy_field }} + {{ form.result_published|as_crispy_field }} + {{ form.enable_abstention|as_crispy_field }} {{ form.voters_self_apply|as_crispy_field }} {{ form.send_emails_on_start|as_crispy_field }} <h5>Remind email template text</h5> diff --git a/management/templates/management/election.html b/management/templates/management/election.html index aba5e8c..471f5c7 100644 --- a/management/templates/management/election.html +++ b/management/templates/management/election.html @@ -120,7 +120,7 @@ <h4>Result</h4> {% include 'management/results.html' %} - {% if election.result_unpublished %} + {% if not election.result_published %} <hr> <form action="{% url 'management:election' election.pk %}" method="post"> {% csrf_token %} diff --git a/management/views.py b/management/views.py index cf0f040..475dede 100644 --- a/management/views.py +++ b/management/views.py @@ -243,7 +243,7 @@ def election_detail(request, pk): context['start_election_form'] = form if request.POST and request.POST.get('action') == 'publish': - election.result_unpublished = False + election.result_published = True election.save() return render(request, template_name='management/election.html', context=context) diff --git a/requirements_dev.txt b/requirements_dev.txt index 7d536fb..34bfbce 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -3,3 +3,4 @@ pylint~=2.8 pylint-django~=2.4 django-stubs build +freezegun \ No newline at end of file diff --git a/vote/forms.py b/vote/forms.py index 7e0b986..0ec5006 100644 --- a/vote/forms.py +++ b/vote/forms.py @@ -61,12 +61,12 @@ class VoteBoundField(forms.BoundField): class VoteField(forms.ChoiceField): - def __init__(self, *, application, disable_abstention=False, **kwargs): + def __init__(self, *, application, enable_abstention=True, **kwargs): super().__init__( label=application.get_display_name(), - choices=VOTE_CHOICES_NO_ABSTENTION if disable_abstention else VOTE_CHOICES, + choices=VOTE_CHOICES if enable_abstention else VOTE_CHOICES_NO_ABSTENTION, widget=forms.RadioSelect(), - initial=None if disable_abstention else VOTE_ABSTENTION, + initial=VOTE_ABSTENTION if enable_abstention else None, **kwargs ) self.application = application @@ -89,7 +89,7 @@ class VoteForm(forms.Form): # dynamically construct form fields for application in self.election.applications.all(): self.fields[f'{application.pk}'] = VoteField(application=application, - disable_abstention=self.election.disable_abstention) + enable_abstention=self.election.enable_abstention) self.num_applications = self.election.applications.all().count() diff --git a/vote/migrations/0029_rename_unpublished_and_disable_abstention.py b/vote/migrations/0029_rename_unpublished_and_disable_abstention.py new file mode 100644 index 0000000..dffbda6 --- /dev/null +++ b/vote/migrations/0029_rename_unpublished_and_disable_abstention.py @@ -0,0 +1,30 @@ +# Generated by Django 3.1.13 on 2021-08-06 08:40 + +from django.db import migrations +from django.db.models import Q + + +def update_values(apps, schema_editor): + election = apps.get_model('vote', 'election') + election.objects.update(result_published=Q(result_published=False)) + election.objects.update(enable_abstention=Q(enable_abstention=False)) + + +class Migration(migrations.Migration): + dependencies = [ + ('vote', '0028_auto_20210804_2335'), + ] + + operations = [ + migrations.RenameField( + model_name='election', + old_name='result_unpublished', + new_name='result_published', + ), + migrations.RenameField( + model_name='election', + old_name='disable_abstention', + new_name='enable_abstention', + ), + migrations.RunPython(update_values, reverse_code=update_values), + ] diff --git a/vote/models.py b/vote/models.py index db30e08..e1e0092 100644 --- a/vote/models.py +++ b/vote/models.py @@ -97,8 +97,8 @@ class Election(models.Model): end_date = models.DateTimeField(blank=True, null=True) max_votes_yes = models.IntegerField(blank=True, null=True) session = models.ForeignKey(Session, related_name='elections', on_delete=CASCADE) - result_unpublished = models.BooleanField(null=False, default=True) - disable_abstention = models.BooleanField(default=False) + result_published = models.BooleanField(null=False, default=False) + enable_abstention = models.BooleanField(default=True) voters_self_apply = models.BooleanField(default=False) send_emails_on_start = models.BooleanField(default=False) remind_text = models.TextField(max_length=8000, blank=True, null=True) diff --git a/vote/selectors.py b/vote/selectors.py index e40ccc9..f08a823 100644 --- a/vote/selectors.py +++ b/vote/selectors.py @@ -24,8 +24,8 @@ def _closed_elections(session: Session): def published_elections(session: Session): - return _closed_elections(session).filter(result_unpublished=False) + return _closed_elections(session).filter(result_published=True) def closed_elections(session: Session): - return _closed_elections(session).filter(result_unpublished=True) + return _closed_elections(session).filter(result_published=False) diff --git a/vote/templates/vote/index_election_item.html b/vote/templates/vote/index_election_item.html index 7a82c6d..34ad03b 100644 --- a/vote/templates/vote/index_election_item.html +++ b/vote/templates/vote/index_election_item.html @@ -24,7 +24,7 @@ <div class="list-group mt-3"> {% if can_vote %} <a class="btn btn-primary" role="button" href="{% url 'vote:vote' election.pk %}">Vote Now!</a> - {% elif election.closed and not election.result_unpublished %} + {% elif election.closed and election.result_published %} <div class="alert alert-info" role="alert"> <h4 class="alert-heading">Voting Ended:</h4> <hr> diff --git a/vote/templates/vote/spectator_election_item.html b/vote/templates/vote/spectator_election_item.html index ce68ec1..e2130ff 100644 --- a/vote/templates/vote/spectator_election_item.html +++ b/vote/templates/vote/spectator_election_item.html @@ -10,7 +10,7 @@ {% endif %} <hr> <div class="list-group mt-3"> - {% if election.closed and not election.result_unpublished %} + {% if election.closed and election.result_published %} <div class="alert alert-info" role="alert"> <h4 class="alert-heading">Election result:</h4> <hr> diff --git a/vote/templates/vote/vote.html b/vote/templates/vote/vote.html index f055095..4d8ac08 100644 --- a/vote/templates/vote/vote.html +++ b/vote/templates/vote/vote.html @@ -49,7 +49,7 @@ <thead class="thead-light"> <tr> <th>{% if election.voters_self_apply %}Applicant{% else %}Option{% endif %}</th> - {% if not election.disable_abstention %} + {% if election.enable_abstention %} <th class="choice text-center">Abstention</th> {% endif %} <th class="choice text-center text-success">YES</th> diff --git a/vote/tests.py b/vote/tests.py index 272439f..48d990e 100644 --- a/vote/tests.py +++ b/vote/tests.py @@ -1,7 +1,8 @@ -from datetime import timedelta +from datetime import timedelta, datetime from django.test import TestCase from django.utils import timezone +from freezegun import freeze_time from vote.models import Election, Enc32, Voter, Session from vote.selectors import closed_elections, open_elections, published_elections, upcoming_elections @@ -27,10 +28,11 @@ class VoterTestCase(TestCase): class ElectionSelectorsTest(TestCase): def test_election_selectors(self) -> None: - now = timezone.now() # but why does freezegun not work in the query sets - before = now - timedelta(minutes=50) - bbefore = now - timedelta(minutes=100) - after = now + timedelta(minutes=50) + now = datetime(year=2021, month=4, day=1, tzinfo=timezone.get_fixed_timezone(5)) + before = now - timedelta(seconds=5) + bbefore = now - timedelta(seconds=10) + after = now + timedelta(seconds=5) + freeze_time(now).start() session = Session.objects.create(title="TEST") # upcoming elections @@ -44,9 +46,9 @@ class ElectionSelectorsTest(TestCase): # published elections all_published = set() all_published.add(Election.objects.create(session=session, start_date=bbefore, end_date=before, - result_unpublished=False)) + result_published=True)) all_published.add(Election.objects.create(session=session, start_date=before, end_date=now, - result_unpublished=False)) + result_published=True)) # closed (not published) elections all_closed = set() all_closed.add(Election.objects.create(session=session, start_date=bbefore, end_date=before)) @@ -68,13 +70,13 @@ class ElectionSelectorsTest(TestCase): published = published_elections(session) self.assertEqual(all_published, set(published)) for e in published: - self.assertTrue(e.started and e.closed and not e.is_open and not e.result_unpublished) + self.assertTrue(e.started and e.closed and not e.is_open and e.result_published) # test closed closed = closed_elections(session) self.assertEqual(all_closed, set(closed)) for e in closed: - self.assertTrue(e.started and e.closed and not e.is_open and e.result_unpublished) + self.assertTrue(e.started and e.closed and not e.is_open and not e.result_published) def gen_data(): -- GitLab