From 794170d9907a3730d73542a9ef781c5c5b6b3e95 Mon Sep 17 00:00:00 2001
From: Ben Adida <ben@adida.net>
Date: Mon, 30 Aug 2010 19:19:45 -0700
Subject: [PATCH] started merging bboard and voter list, they are really the
 same feature, improving pagination, and added better warnings when trustees
 haven't uploaded public keys.

---
 helios/election_urls.py           |  1 -
 helios/models.py                  |  4 +++
 helios/templates/voters_list.html | 31 +++++++++--------------
 helios/views.py                   | 42 ++++++++++++-------------------
 4 files changed, 32 insertions(+), 46 deletions(-)

diff --git a/helios/election_urls.py b/helios/election_urls.py
index 2e2580e..c288ad8 100644
--- a/helios/election_urls.py
+++ b/helios/election_urls.py
@@ -65,7 +65,6 @@ urlpatterns = patterns('',
     (r'^/voters/$', voter_list),
     (r'^/voters/upload$', voters_upload),
     (r'^/voters/list$', voters_list_pretty),
-    (r'^/voters/search$', voters_search),
     (r'^/voters/email$', voters_email),
     (r'^/voters/(?P<voter_uuid>[^/]+)$', one_voter),
     (r'^/voters/(?P<voter_uuid>[^/]+)/delete$', voter_delete),
diff --git a/helios/models.py b/helios/models.py
index 4913f3c..2a1a407 100644
--- a/helios/models.py
+++ b/helios/models.py
@@ -196,6 +196,10 @@ class Election(models.Model, electionalgs.Election):
     if len(trustees) == 0:
       issues.append("no trustees")
 
+    for t in trustees:
+      if t.public_key == None:
+        issues.append("trustee %s hasn't generated a key yet" % t.name)
+
     return issues
     
 
diff --git a/helios/templates/voters_list.html b/helios/templates/voters_list.html
index 5077b71..e0dfc63 100644
--- a/helios/templates/voters_list.html
+++ b/helios/templates/voters_list.html
@@ -1,8 +1,8 @@
 {% extends TEMPLATE_BASE %}
 
-{% block title %}Voters for {{election.name}}{% endblock %}
+{% block title %}Voters &amp; Ballot Tracking Center for {{election.name}}{% endblock %}
 {% block content %}
-  <h2 class="title">{{election.name}} &mdash; Voters <span style="font-size:0.7em;">[<a href="{% url helios.views.one_election_view election.uuid %}">back to election</a>]</span></h2>
+  <h2 class="title">{{election.name}} &mdash; Voters and Ballot Tracking Center <span style="font-size:0.7em;">[<a href="{% url helios.views.one_election_view election.uuid %}">back to election</a>]</span></h2>
 
 <p>
 <u>Registration</u> is {% if not election.frozen_at %}currently{% endif %} <b>{{ election.registration_status_pretty }}</b>.
@@ -15,21 +15,15 @@
 {% endif %}
 </p>
 
-<!--
-<p>
-<u>Eligibility</u>: [more to come]
-</p>
--->
-
 {% if email_voters and election.frozen_at and admin_p %}
 <p><a href="{% url helios.views.voters_email election.uuid %}">email voters</a></p>
 {% endif %}
 
 
 <p>
-<form method="get" action="{% url helios.views.voters_search election.uuid %}"><b>search</b>: <input type="text" name="q" /> <input type="submit" value="search" /></form>
+<form method="get" action="{% url helios.views.voters_list_pretty election.uuid %}"><b>search</b>: <input type="text" name="q" /> <input type="submit" value="search" /></form>
 </p>
-
+<br />
 {% if admin_p and upload_p %}
 <p>
 {% if not election.frozen_at %}
@@ -60,18 +54,15 @@ Prior Bulk Uploads:
 {% endif %}
 
 {% if voters %}
-Voters {{offset_plus_one}} - {{offset_plus_limit}} &nbsp;&nbsp;
 
-{% if next_after %}
-<a href="./list?after={{next_after}}&offset={{offset_plus_limit}}">next {{limit}}</a> &nbsp;&nbsp;
+{% if voters_page.has_previous %}
+<a href="./list?page={{voters_page.previous_page_number}}&limit={{limit}}">previous {{limit}}</a> &nbsp;&nbsp;
 {% endif %}
 
-{% ifequal offset 0 %}
-{% else %}
-<a href="./list">back to start</a> &nbsp;&nbsp;
-{% endifequal %}
-{% if more_p %}
-<a href="./list?after={{next_after}}&offset={{next_offset}}">next {{limit}}</a>
+Voters {{voters_page.start_index}} - {{voters_page.end_index}} (of {{total_voters}})&nbsp;&nbsp;
+
+{% if voters_page.has_next %}
+<a href="./list?page={{voters_page.next_page_number}}&limit={{limit}}">next {{limit}}</a> &nbsp;&nbsp;
 {% endif %}
 
 <table class="pretty">
@@ -83,6 +74,7 @@ Voters {{offset_plus_one}} - {{offset_plus_limit}} &nbsp;&nbsp;
 {% if election.use_voter_aliases %}
 <th>Alias</th>
 {% endif %}
+<th>Smart Ballot Tracker</th>
 </tr>
 {% for voter in voters %}
 <tr>
@@ -101,6 +93,7 @@ Voters {{offset_plus_one}} - {{offset_plus_limit}} &nbsp;&nbsp;
 {% if election.use_voter_aliases %}
 <td>{{voter.alias}}</td>
 {% endif %}
+<td><tt style="font-size: 1.4em;;">{% if voter.vote_hash %}{{voter.vote_hash}} <span style="font-size:0.8em;">[<a href="{% url helios.views.voter_last_vote election_uuid=election.uuid,voter_uuid=voter.uuid %}">view</a>]</span>{% else %}&mdash;{% endif %}</tt></td>
 </tr>
 {% endfor %}
 </table>
diff --git a/helios/views.py b/helios/views.py
index 23920af..e15f560 100644
--- a/helios/views.py
+++ b/helios/views.py
@@ -7,7 +7,9 @@ Ben Adida (ben@adida.net)
 
 from django.core.urlresolvers import reverse
 from django.core.mail import send_mail
+from django.core.paginator import Paginator
 from django.http import *
+from django.db import transaction
 
 from mimetypes import guess_type
 
@@ -709,6 +711,7 @@ def one_election_save_questions(request, election):
   # always a machine API
   return SUCCESS
 
+@transaction.commit_on_success
 @election_admin(frozen=False)
 def one_election_freeze(request, election):
   # figure out the number of questions and trustees
@@ -829,9 +832,11 @@ def one_election_set_result_and_proof(request, election):
 def voters_list_pretty(request, election):
   """
   Show the list of voters
+  now using Django pagination
   """
-  after = request.GET.get('after', None)
-  offset= int(request.GET.get('offset', 0))
+
+  # for django pagination support
+  page = int(request.GET.get('page', 1))
   limit = int(request.GET.get('limit', 50))
   
   order_by = 'voter_id'
@@ -843,34 +848,19 @@ def voters_list_pretty(request, election):
   voter_files = election.voterfile_set.all()
 
   # load a bunch of voters
-  voters = Voter.get_by_election(election, after=after, limit=limit+1, order_by=order_by)
-    
-  more_p = len(voters) > limit
-  if more_p:
-    voters = voters[0:limit]
-    next_after = getattr(voters[limit-1], order_by)
-  else:
-    next_after = None
+  voters = Voter.get_by_election(election, order_by=order_by)
+  total_voters = voters.count()
+
+  voter_paginator = Paginator(voters, limit)
+  voters_page = voter_paginator.page(page)
     
-  return render_template(request, 'voters_list', {'election': election, 'voters': voters, 'admin_p': admin_p, 
-                                                  'next_after': next_after, 'email_voters': helios.VOTERS_EMAIL,
-                                                  'offset': offset, 'limit': limit, 'offset_plus_one': offset+1,
-                                                  'offset_plus_limit': offset+min(limit,len(voters)),
+  return render_template(request, 'voters_list', {'election': election, 'voters_page': voters_page,
+                                                  'voters': voters_page.object_list, 'admin_p': admin_p, 
+                                                  'email_voters': helios.VOTERS_EMAIL,
+                                                  'limit': limit, 'total_voters': total_voters,
                                                   'upload_p': helios.VOTERS_UPLOAD,
                                                   'voter_files': voter_files})
 
-@election_admin()
-def voters_search(request, election):
-  """
-  Search the voters by voter_id
-  """
-  search_term = request.GET.get('q', None)
-  if not search_term:
-    raise Exception("must provide a search term")
-  
-  voter = Voter.get_by_election_and_voter_id(election, voter_id=search_term)
-  return render_template(request, 'voters_search', {'election': election, 'voter': voter, 'search_term': search_term})
-
 @election_admin(frozen=False)
 def voters_upload(request, election):
   """
-- 
GitLab