[Fedora Elections] #16: Cannot edit ballot after entering bad data
by fedora-badges
#16: Cannot edit ballot after entering bad data
---------------------+------------------------------------------------------
Reporter: jhrozek | Owner: nigelj
Type: defect | Status: new
Priority: major | Milestone: Release 0.1.0
Component: General | Version:
Keywords: |
---------------------+------------------------------------------------------
To reproduce:
* Enter the Real Presidential Nominee ballot
* vote, but input bad data
* I did input -1 5 4 3 2
* you are correctly reminded that "One or more votes had incorrect data,
please verify your ballot carefully!" but you can't change the numbers
entered afterwards
* I did reproduce this with both FF (latest F8 version) and Konqueror
* going back helps but it would be nice to be able to modify the data
on the same page. And mabe even highlight those that are bad.
--
Ticket URL: <https://fedorahosted.org/elections/ticket/16>
Fedora Elections <https://fedorahosted.org/elections/>
Fedora Elections
15 years, 10 months
[Fedora Elections] #17: UI should give a hint on the range
by fedora-badges
#17: UI should give a hint on the range
---------------------+------------------------------------------------------
Reporter: jhrozek | Owner: ricky
Type: defect | Status: new
Priority: major | Milestone: Release 0.1.0
Component: UI | Version:
Keywords: |
---------------------+------------------------------------------------------
Currently, the UI makes no hint on the range for the voting (which is the
# of applicants), it would be neat if there was a short sentence above the
list of people that said something like "Vote by entering a number in
range of 0 to XX".
With the current UI, one has to count the people, which is not user-
friendly.
--
Ticket URL: <https://fedorahosted.org/elections/ticket/17>
Fedora Elections <https://fedorahosted.org/elections/>
Fedora Elections
15 years, 11 months
r42 - branches/0.1.0-STABLE/elections trunk/elections
by Nigel Jones
Author: nigelj
Date: 2008-05-31 06:37:33 +0000 (Sat, 31 May 2008)
New Revision: 42
Modified:
branches/0.1.0-STABLE/elections/controllers.py
trunk/elections/controllers.py
Log:
Oppsie
Modified: branches/0.1.0-STABLE/elections/controllers.py
===================================================================
--- branches/0.1.0-STABLE/elections/controllers.py 2008-05-31 06:16:24 UTC (rev 41)
+++ branches/0.1.0-STABLE/elections/controllers.py 2008-05-31 06:37:33 UTC (rev 42)
@@ -215,7 +215,7 @@
response.status=403
return dict(message=msg, previous_url=previous_url, logging_in=True,
original_parameters=request.params,
- forward_url=forward_url, title=self.appTitle + ' -- Fedora Account System Login')
+ forward_url=forward_url, appTitle=self.appTitle + ' -- Fedora Account System Login')
@expose()
def logout(self):
Modified: trunk/elections/controllers.py
===================================================================
--- trunk/elections/controllers.py 2008-05-31 06:16:24 UTC (rev 41)
+++ trunk/elections/controllers.py 2008-05-31 06:37:33 UTC (rev 42)
@@ -215,7 +215,7 @@
response.status=403
return dict(message=msg, previous_url=previous_url, logging_in=True,
original_parameters=request.params,
- forward_url=forward_url, title=self.appTitle + ' -- Fedora Account System Login')
+ forward_url=forward_url, appTitle=self.appTitle + ' -- Fedora Account System Login')
@expose()
def logout(self):
15 years, 11 months
r41 - in branches/0.1.0-STABLE: . elections elections/templates
by Nigel Jones
Author: nigelj
Date: 2008-05-31 06:16:24 +0000 (Sat, 31 May 2008)
New Revision: 41
Added:
branches/0.1.0-STABLE/elections/templates/index.html
branches/0.1.0-STABLE/elections/templates/vote.html
Removed:
branches/0.1.0-STABLE/elections/templates/ballot.html
branches/0.1.0-STABLE/elections/templates/confirm.html
branches/0.1.0-STABLE/elections/templates/list.html
Modified:
branches/0.1.0-STABLE/elections.sql
branches/0.1.0-STABLE/elections/controllers.py
branches/0.1.0-STABLE/elections/model.py
branches/0.1.0-STABLE/elections/templates/about.html
branches/0.1.0-STABLE/elections/templates/login.html
Log:
Merge bugfixes (r39 & r40) from trunk
Modified: branches/0.1.0-STABLE/elections/controllers.py
===================================================================
--- branches/0.1.0-STABLE/elections/controllers.py 2008-05-31 06:01:16 UTC (rev 40)
+++ branches/0.1.0-STABLE/elections/controllers.py 2008-05-31 06:16:24 UTC (rev 41)
@@ -41,10 +41,10 @@
appTitle = 'Fedora Elections'
admin = Admin(appTitle)
- @expose(template="elections.templates.list")
+ @expose(template="elections.templates.index")
def index(self):
electlist = Elections.query.order_by(ElectionsTable.c.start_date).filter('id>0').all()
- return dict(elections=electlist, curtime=datetime.utcnow())
+ return dict(elections=electlist, curtime=datetime.utcnow(), appTitle=self.appTitle)
@expose(template="elections.templates.about")
def about(self,eid=None):
@@ -54,23 +54,36 @@
except ValueError:
election = Elections.query.filter_by(shortname=eid).all()[0]
eid = election.id
+ except TypeError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
+ except IndexError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
votergroups = LegalVoters.query.filter_by(election_id=eid).all()
candidates = Candidates.query.filter_by(election_id=eid).order_by(Candidates.name).all()
+ votergroups = LegalVoters.query.filter_by(election_id=eid).all()
curtime = datetime.utcnow()
- return dict(eid=eid, candidates=candidates, election=election, curtime=curtime)
+ return dict(eid=eid, candidates=candidates, election=election, curtime=curtime, votergroups=votergroups, appTitle=self.appTitle)
@identity.require(identity.not_anonymous())
- @expose(template="elections.templates.ballot")
- def ballot(self,eid=None):
+ @expose(template="elections.templates.vote")
+ def vote(self,eid=None, **kw):
try:
eid = int(eid)
election = Elections.query.filter_by(id=eid).all()[0]
except ValueError:
election = Elections.query.filter_by(shortname=eid).all()[0]
eid = election.id
+ except TypeError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
+ except IndexError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
votergroups = LegalVoters.query.filter_by(election_id=eid).all()
@@ -81,54 +94,25 @@
if match == 0:
turbogears.flash("You are not in a FAS group that can vote in this election, more information can be found here.")
raise turbogears.redirect("/about/" + str(eid))
-
- curtime = datetime.utcnow()
- if election.end_date < curtime:
- turbogears.flash("You cannot vote in this election because the end date has passed. You have been redirected to the election results")
- raise turbogears.redirect("/results/" + str(eid))
- elif election.start_date > curtime:
- election_started=False
- else:
- election_started=True
- candidates = Candidates.query.filter_by(election_id=eid).order_by(Candidates.name).all()
- return dict(eid=eid, candidates=candidates, election=election, election_started=election_started)
-
- @identity.require(identity.not_anonymous())
- @expose(template="elections.templates.confirm")
- def vote(self, eid, **kw):
- try:
- election = Elections.query.filter_by(id=eid).all()[0]
- except IndexError:
- turbogears.flash("Sorry, that election does not exist")
- raise turbogears.redirect("/")
-
- votergroups = LegalVoters.query.filter_by(election_id=eid).all()
- match = 0
- for group in votergroups:
- if identity.in_group(group.group_name):
- match = 1
- if match == 0:
- turbogears.flash("You are not in a FAS group that can vote in this election, more information can be found here.")
- raise turbogears.redirect("/about/" + str(election.name))
-
candidates = Candidates.query.filter_by(election_id=eid).order_by(Candidates.name).all()
uservote = UserVoteCount.query.filter_by(election_id=eid, voter=turbogears.identity.current.user_name).all()
+ uvotes = {}
+ next_action = ""
- #Before we do *ANYTHING* check if voting hasn't begun/has ended
curtime = datetime.utcnow()
if election.start_date > curtime:
- turbogears.flash("Voting has not yet begun.")
+ turbogears.flash("Voting as not yet started, sorry.")
raise turbogears.redirect("/")
elif election.end_date < curtime:
- turbogears.flash("We are sorry, voting has now ended.")
- raise turbogears.redirect("/")
+ turbogears.flash("You cannot vote in this election because the end date has passed. You have been redirected to the election results")
+ raise turbogears.redirect("/results/" + election.shortname)
elif len(uservote) != 0:
- turbogears.flash("You've voted too many times!")
+ turbogears.flash("You have already voted in this election!")
raise turbogears.redirect("/")
-
+
+ # Lets do this in reverse order
if "confirm" in kw:
- uvotes = {}
for c in candidates:
if str(c.id) in kw:
try:
@@ -143,32 +127,40 @@
raise turbogears.redirect("/")
for uvote in uvotes:
Votes(voter=turbogears.identity.current.user_name, candidate_id=uvote, weight=uvotes[uvote], election_id=eid)
- turbogears.flash("Saved!")
- raise turbogears.redirect("/")
- else:
+ turbogears.flash("You vote has been recorded, thank you!")
+ raise turbogears.redirect("/")
+ elif "vote" in kw:
turbogears.flash("Please confirm your vote!")
- uvotes = {}
for c in candidates:
if str(c.id) in kw:
try:
range = int(kw[str(c.id)])
if range > len(candidates):
- turbogears.flash("One or more votes had incorrect data, please verify your ballot carefully!")
- uvotes[c.id] = len(candidates)
+ turbogears.flash("Invalid data was detected for one or more candidates and was changed to zeros! Please correct and resubmit your ballot.")
+ uvotes[c.id] = 0
+ next_action = "vote"
elif range >= 0:
uvotes[c.id] = range
else:
- turbogears.flash("One or more votes had incorrect data, please verify your ballot carefully!")
+ turbogears.flash("Invalid data was detected for one or more candidates and was changed to zeros! Please correct and resubmit your ballot.")
uvotes[c.id] = 0
+ next_action = "vote"
except ValueError:
- turbogears.flash("Invalid data was detected and changed to zeros!")
+ turbogears.flash("Invalid data was detected for one or more candidates and was changed to zeros! Please correct and resubmit your ballot.")
uvotes[c.id] = 0
+ next_action = "vote"
else:
turbogears.flash("Invalid Ballot!")
raise turbogears.redirect("/")
-
- return dict(voteinfo=uvotes, candidates=candidates, election=election)
+ if next_action != "vote":
+ next_action = "confirm"
+ else:
+ for c in candidates:
+ uvotes[c.id] = ""
+ next_action = "vote"
+ return dict(eid=eid, candidates=candidates, election=election, nextaction=next_action, voteinfo=uvotes, appTitle=self.appTitle)
+
@expose(template="elections.templates.results")
def results(self,eid=None):
try:
@@ -177,6 +169,13 @@
except ValueError:
election = Elections.query.filter_by(shortname=eid).all()[0]
eid = election.id
+ except TypeError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
+ except IndexError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
+
curtime = datetime.utcnow()
if election.public_results == 0 and election.end_date > curtime:
turbogears.flash("We are sorry, the results for this election cannot be viewed at this time because the election is still in progress.")
@@ -185,7 +184,7 @@
turbogears.flash("We are sorry, the results for this election cannot be viewed at this time because the election has not started.")
raise turbogears.redirect("/")
votecount = VoteTally.query.filter_by(election_id=eid).order_by(VoteTally.novotes.desc()).all()
- return dict(votecount=votecount, election=election)
+ return dict(votecount=votecount, election=election, appTitle=self.appTitle)
@expose(template="elections.templates.login", allow_json=True)
def login(self, forward_url=None, previous_url=None, *args, **kw):
@@ -216,7 +215,7 @@
response.status=403
return dict(message=msg, previous_url=previous_url, logging_in=True,
original_parameters=request.params,
- forward_url=forward_url, title='Fedora Account System Login')
+ forward_url=forward_url, title=self.appTitle + ' -- Fedora Account System Login')
@expose()
def logout(self):
Modified: branches/0.1.0-STABLE/elections/model.py
===================================================================
--- branches/0.1.0-STABLE/elections/model.py 2008-05-31 06:01:16 UTC (rev 40)
+++ branches/0.1.0-STABLE/elections/model.py 2008-05-31 06:16:24 UTC (rev 41)
@@ -27,7 +27,11 @@
ElectionsTable = Table('elections', metadata, autoload=True)
VotesTable = Table('votes', metadata, autoload=True)
CandidatesTable = Table('candidates', metadata, autoload=True)
-LegalVotersTable = Table('legalvoters', metadata, autoload=True)
+LegalVotersTable = Table('legalvoters', metadata,
+ Column('election_id', Integer,
+ ForeignKey('elections.id'), primary_key=True),
+ Column('group_name', String, nullable=False)
+)
# View in the DB. Needs to have the column keys defined
VoteTallyTable = Table('votecount', metadata,
Modified: branches/0.1.0-STABLE/elections/templates/about.html
===================================================================
--- branches/0.1.0-STABLE/elections/templates/about.html 2008-05-31 06:01:16 UTC (rev 40)
+++ branches/0.1.0-STABLE/elections/templates/about.html 2008-05-31 06:16:24 UTC (rev 41)
@@ -4,10 +4,9 @@
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="master.html" />
<head>
- <title>Welcome to TurboGears</title>
+ <title>${appTitle} -- Election Information</title>
</head>
- <body>
-<!-- Also need to list eligable voting groups... -->
+ <body>
<h1>${election.name}</h1>
<p>${election.info}</p>
<p py:if="election.url"><a href="${election.url}">[More Information]</a></p>
@@ -15,10 +14,14 @@
<tr py:for="candidate in candidates">
<td>${candidate.name} <small py:if="candidate.url"><a href="${candidate.url}">[info]</a></small></td>
</tr>
-<!-- This link is okay, but one should appear if the election has public results -->
+<!-- !This link is okay, but one should appear if the election has public results -->
<tr>
- <td><a href="${tg.url('/ballot/' + election.shortname)}">Vote Now!</a></td>
+ <td><a href="${tg.url('/vote/' + election.shortname)}">Vote Now!</a></td>
</tr>
- </table>
+ </table>
+ <p>To vote in this election you must be a member of any one of the following groups:</p>
+ <ul>
+ <li py:for="g in votergroups">${g.group_name}</li>
+ </ul>
</body>
</html>
Deleted: branches/0.1.0-STABLE/elections/templates/ballot.html
===================================================================
--- branches/0.1.0-STABLE/elections/templates/ballot.html 2008-05-31 06:01:16 UTC (rev 40)
+++ branches/0.1.0-STABLE/elections/templates/ballot.html 2008-05-31 06:16:24 UTC (rev 41)
@@ -1,26 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="master.html" />
- <head>
- <title>Welcome to TurboGears</title>
- </head>
- <body>
- <h1>${election.name}</h1>
- <p>${election.info}</p>
- <p py:if="election.url"><a href="${election.url}">[More Information]</a></p>
- <form action="${tg.url('/vote/' + str(election.id))}" method="post">
- <table border="1" cellpadding="1">
- <tr py:for="candidate in candidates">
- <td>${candidate.name} <small py:if="candidate.url"><a href="${candidate.url}">[info]</a></small></td>
- <td><input type="text" name="${candidate.id}" value="" /></td>
- </tr>
- <tr>
- <td></td>
- <td><input type="submit" value="Submit" /></td>
- </tr>
- </table>
- </form>
- </body>
-</html>
Deleted: branches/0.1.0-STABLE/elections/templates/confirm.html
===================================================================
--- branches/0.1.0-STABLE/elections/templates/confirm.html 2008-05-31 06:01:16 UTC (rev 40)
+++ branches/0.1.0-STABLE/elections/templates/confirm.html 2008-05-31 06:16:24 UTC (rev 41)
@@ -1,26 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="master.html" />
- <head>
- <title>Welcome to TurboGears</title>
- </head>
- <body>
- <h1>Confirm Vote in ${election.name}</h1>
- <p>${election.info}</p>
- <p py:if="election.url"><a href="${election.url}">[More Information]</a></p>
- <form action="${tg.url('/vote/' + str(election.id))}" method="post">
- <table border="1" cellpadding="1">
- <tr py:for="candidate in candidates">
- <td>${candidate.name} <small py:if="candidate.url"><a href="${candidate.url}">[info]</a></small></td>
- <td><input type="text" name="${candidate.id}" value="${voteinfo[candidate.id]}" readonly="readonly" /></td>
- </tr>
- <tr>
- <td></td>
- <td><input type="submit" name="confirm" value="Confirm Vote!" /></td>
- </tr>
- </table>
- </form>
- </body>
-</html>
Copied: branches/0.1.0-STABLE/elections/templates/index.html (from rev 40, trunk/elections/templates/index.html)
===================================================================
--- branches/0.1.0-STABLE/elections/templates/index.html (rev 0)
+++ branches/0.1.0-STABLE/elections/templates/index.html 2008-05-31 06:16:24 UTC (rev 41)
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:py="http://genshi.edgewall.org/"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="master.html" />
+ <head>
+ <title>${appTitle}</title>
+ </head>
+ <body>
+ <ul>
+<!-- !Maybe change this link depending if they are logged in or not -->
+ <li py:for="election in elections"><a href="${tg.url('/about/' + election.shortname)}">${election.name}</a></li>
+<!-- !Would be nice features also include voting dates -->
+ </ul>
+ </body>
+</html>
Deleted: branches/0.1.0-STABLE/elections/templates/list.html
===================================================================
--- branches/0.1.0-STABLE/elections/templates/list.html 2008-05-31 06:01:16 UTC (rev 40)
+++ branches/0.1.0-STABLE/elections/templates/list.html 2008-05-31 06:16:24 UTC (rev 41)
@@ -1,16 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="master.html" />
- <head>
- <title>Welcome to TurboGears</title>
- </head>
- <body>
- <ul>
-<!-- Maybe change this link depending if they are logged in or not -->
- <li py:for="election in elections"><a href="${tg.url('/about/' + election.shortname)}">${election.name}</a></li>
-<!-- Would be nice features also include voting dates -->
- </ul>
- </body>
-</html>
Modified: branches/0.1.0-STABLE/elections/templates/login.html
===================================================================
--- branches/0.1.0-STABLE/elections/templates/login.html 2008-05-31 06:01:16 UTC (rev 40)
+++ branches/0.1.0-STABLE/elections/templates/login.html 2008-05-31 06:16:24 UTC (rev 41)
@@ -4,7 +4,7 @@
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="master.html" />
<head>
- <title>Login</title>
+ <title>${appTitle}</title>
</head>
<body>
<div id="loginBox">
Copied: branches/0.1.0-STABLE/elections/templates/vote.html (from rev 40, trunk/elections/templates/vote.html)
===================================================================
--- branches/0.1.0-STABLE/elections/templates/vote.html (rev 0)
+++ branches/0.1.0-STABLE/elections/templates/vote.html 2008-05-31 06:16:24 UTC (rev 41)
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:py="http://genshi.edgewall.org/"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="master.html" />
+ <head>
+ <title>${appTitle} -- Cast Your Vote</title>
+ </head>
+ <body>
+ <h1>${election.name}</h1>
+ <p>${election.info}</p>
+ <p py:if="election.url"><a href="${election.url}">[More Information]</a></p>
+ <form action="${tg.url('/vote/' + str(election.id))}" method="post">
+ <table border="1" cellpadding="1">
+ <tr py:for="candidate in candidates">
+ <td>${candidate.name} <small py:if="candidate.url"><a href="${candidate.url}">[info]</a></small></td>
+ <py:if test="nextaction=='vote'">
+ <td><select name="${candidate.id}">
+ <option py:for="option in range(0,len(candidates)+1)" value="$option">$option</option>
+ </select></td>
+ </py:if>
+ <py:if test="nextaction=='confirm'">
+ <td><input type="hidden" name="${candidate.id}" value="${voteinfo[candidate.id]}" />${voteinfo[candidate.id]}</td>
+ </py:if>
+ </tr>
+ <tr>
+ <td><input py:if="nextaction=='confirm'" type="button" value="Go Back" onClick="javascript.history.back(1)" /></td>
+ <td><input type="submit" name="${nextaction}" value="Submit" /></td>
+ </tr>
+ </table>
+ </form>
+ </body>
+</html>
Modified: branches/0.1.0-STABLE/elections.sql
===================================================================
--- branches/0.1.0-STABLE/elections.sql 2008-05-31 06:01:16 UTC (rev 40)
+++ branches/0.1.0-STABLE/elections.sql 2008-05-31 06:16:24 UTC (rev 41)
@@ -23,8 +23,8 @@
create table legalVoters (
election_id integer not null,
group_name text not null,
-foreign key (election_id) references elections (id),
-primary key (election_id)
+foreign key (election_id) references elections (id)
+-- primary key (election_id)
);
create table candidates (
15 years, 11 months
r40 - in trunk/elections: . templates
by Nigel Jones
Author: nigelj
Date: 2008-05-31 06:01:16 +0000 (Sat, 31 May 2008)
New Revision: 40
Added:
trunk/elections/templates/index.html
trunk/elections/templates/vote.html
Removed:
trunk/elections/templates/ballot.html
trunk/elections/templates/confirm.html
trunk/elections/templates/list.html
Modified:
trunk/elections/controllers.py
Log:
Small template name changes
Modified: trunk/elections/controllers.py
===================================================================
--- trunk/elections/controllers.py 2008-05-31 05:56:31 UTC (rev 39)
+++ trunk/elections/controllers.py 2008-05-31 06:01:16 UTC (rev 40)
@@ -41,7 +41,7 @@
appTitle = 'Fedora Elections'
admin = Admin(appTitle)
- @expose(template="elections.templates.list")
+ @expose(template="elections.templates.index")
def index(self):
electlist = Elections.query.order_by(ElectionsTable.c.start_date).filter('id>0').all()
return dict(elections=electlist, curtime=datetime.utcnow(), appTitle=self.appTitle)
@@ -70,7 +70,7 @@
return dict(eid=eid, candidates=candidates, election=election, curtime=curtime, votergroups=votergroups, appTitle=self.appTitle)
@identity.require(identity.not_anonymous())
- @expose(template="elections.templates.ballot")
+ @expose(template="elections.templates.vote")
def vote(self,eid=None, **kw):
try:
eid = int(eid)
Deleted: trunk/elections/templates/ballot.html
===================================================================
--- trunk/elections/templates/ballot.html 2008-05-31 05:56:31 UTC (rev 39)
+++ trunk/elections/templates/ballot.html 2008-05-31 06:01:16 UTC (rev 40)
@@ -1,33 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="master.html" />
- <head>
- <title>${appTitle} -- Cast Your Vote</title>
- </head>
- <body>
- <h1>${election.name}</h1>
- <p>${election.info}</p>
- <p py:if="election.url"><a href="${election.url}">[More Information]</a></p>
- <form action="${tg.url('/vote/' + str(election.id))}" method="post">
- <table border="1" cellpadding="1">
- <tr py:for="candidate in candidates">
- <td>${candidate.name} <small py:if="candidate.url"><a href="${candidate.url}">[info]</a></small></td>
- <py:if test="nextaction=='vote'">
- <td><select name="${candidate.id}">
- <option py:for="option in range(0,len(candidates)+1)" value="$option">$option</option>
- </select></td>
- </py:if>
- <py:if test="nextaction=='confirm'">
- <td><input type="hidden" name="${candidate.id}" value="${voteinfo[candidate.id]}" />${voteinfo[candidate.id]}</td>
- </py:if>
- </tr>
- <tr>
- <td><input py:if="nextaction=='confirm'" type="button" value="Go Back" onClick="javascript.history.back(1)" /></td>
- <td><input type="submit" name="${nextaction}" value="Submit" /></td>
- </tr>
- </table>
- </form>
- </body>
-</html>
Deleted: trunk/elections/templates/confirm.html
===================================================================
--- trunk/elections/templates/confirm.html 2008-05-31 05:56:31 UTC (rev 39)
+++ trunk/elections/templates/confirm.html 2008-05-31 06:01:16 UTC (rev 40)
@@ -1,26 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="master.html" />
- <head>
- <title>Welcome to TurboGears</title>
- </head>
- <body>
- <h1>Confirm Vote in ${election.name}</h1>
- <p>${election.info}</p>
- <p py:if="election.url"><a href="${election.url}">[More Information]</a></p>
- <form action="${tg.url('/vote/' + str(election.id))}" method="post">
- <table border="1" cellpadding="1">
- <tr py:for="candidate in candidates">
- <td>${candidate.name} <small py:if="candidate.url"><a href="${candidate.url}">[info]</a></small></td>
- <td><input type="text" name="${candidate.id}" value="${voteinfo[candidate.id]}" readonly="readonly" /></td>
- </tr>
- <tr>
- <td></td>
- <td><input type="submit" name="confirm" value="Confirm Vote!" /></td>
- </tr>
- </table>
- </form>
- </body>
-</html>
Copied: trunk/elections/templates/index.html (from rev 39, trunk/elections/templates/list.html)
===================================================================
--- trunk/elections/templates/index.html (rev 0)
+++ trunk/elections/templates/index.html 2008-05-31 06:01:16 UTC (rev 40)
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:py="http://genshi.edgewall.org/"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="master.html" />
+ <head>
+ <title>${appTitle}</title>
+ </head>
+ <body>
+ <ul>
+<!-- !Maybe change this link depending if they are logged in or not -->
+ <li py:for="election in elections"><a href="${tg.url('/about/' + election.shortname)}">${election.name}</a></li>
+<!-- !Would be nice features also include voting dates -->
+ </ul>
+ </body>
+</html>
Deleted: trunk/elections/templates/list.html
===================================================================
--- trunk/elections/templates/list.html 2008-05-31 05:56:31 UTC (rev 39)
+++ trunk/elections/templates/list.html 2008-05-31 06:01:16 UTC (rev 40)
@@ -1,16 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="master.html" />
- <head>
- <title>${appTitle}</title>
- </head>
- <body>
- <ul>
-<!-- !Maybe change this link depending if they are logged in or not -->
- <li py:for="election in elections"><a href="${tg.url('/about/' + election.shortname)}">${election.name}</a></li>
-<!-- !Would be nice features also include voting dates -->
- </ul>
- </body>
-</html>
Copied: trunk/elections/templates/vote.html (from rev 39, trunk/elections/templates/ballot.html)
===================================================================
--- trunk/elections/templates/vote.html (rev 0)
+++ trunk/elections/templates/vote.html 2008-05-31 06:01:16 UTC (rev 40)
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:py="http://genshi.edgewall.org/"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="master.html" />
+ <head>
+ <title>${appTitle} -- Cast Your Vote</title>
+ </head>
+ <body>
+ <h1>${election.name}</h1>
+ <p>${election.info}</p>
+ <p py:if="election.url"><a href="${election.url}">[More Information]</a></p>
+ <form action="${tg.url('/vote/' + str(election.id))}" method="post">
+ <table border="1" cellpadding="1">
+ <tr py:for="candidate in candidates">
+ <td>${candidate.name} <small py:if="candidate.url"><a href="${candidate.url}">[info]</a></small></td>
+ <py:if test="nextaction=='vote'">
+ <td><select name="${candidate.id}">
+ <option py:for="option in range(0,len(candidates)+1)" value="$option">$option</option>
+ </select></td>
+ </py:if>
+ <py:if test="nextaction=='confirm'">
+ <td><input type="hidden" name="${candidate.id}" value="${voteinfo[candidate.id]}" />${voteinfo[candidate.id]}</td>
+ </py:if>
+ </tr>
+ <tr>
+ <td><input py:if="nextaction=='confirm'" type="button" value="Go Back" onClick="javascript.history.back(1)" /></td>
+ <td><input type="submit" name="${nextaction}" value="Submit" /></td>
+ </tr>
+ </table>
+ </form>
+ </body>
+</html>
15 years, 11 months
r39 - in trunk: . elections elections/templates
by Nigel Jones
Author: nigelj
Date: 2008-05-31 05:56:31 +0000 (Sat, 31 May 2008)
New Revision: 39
Modified:
trunk/elections.sql
trunk/elections/controllers.py
trunk/elections/model.py
trunk/elections/templates/about.html
trunk/elections/templates/ballot.html
trunk/elections/templates/list.html
trunk/elections/templates/login.html
Log:
* elections.sql
- Delete primary key on legalvoters (opps)
* elections/model.py
- Manually specify a 'fake' primary key
* elections/controllers.py
- Rework vote processing
* elections/templates/*.html
- Include page title, closes Ticket #14
* elections/templates/ballot.html
- Prevent invalid input, closes Ticket #16
- Drop down menu instead of text box to demonstrate the ranges, closes Ticket #17
Modified: trunk/elections/controllers.py
===================================================================
--- trunk/elections/controllers.py 2008-05-29 11:44:50 UTC (rev 38)
+++ trunk/elections/controllers.py 2008-05-31 05:56:31 UTC (rev 39)
@@ -44,7 +44,7 @@
@expose(template="elections.templates.list")
def index(self):
electlist = Elections.query.order_by(ElectionsTable.c.start_date).filter('id>0').all()
- return dict(elections=electlist, curtime=datetime.utcnow())
+ return dict(elections=electlist, curtime=datetime.utcnow(), appTitle=self.appTitle)
@expose(template="elections.templates.about")
def about(self,eid=None):
@@ -54,23 +54,36 @@
except ValueError:
election = Elections.query.filter_by(shortname=eid).all()[0]
eid = election.id
+ except TypeError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
+ except IndexError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
votergroups = LegalVoters.query.filter_by(election_id=eid).all()
candidates = Candidates.query.filter_by(election_id=eid).order_by(Candidates.name).all()
+ votergroups = LegalVoters.query.filter_by(election_id=eid).all()
curtime = datetime.utcnow()
- return dict(eid=eid, candidates=candidates, election=election, curtime=curtime)
+ return dict(eid=eid, candidates=candidates, election=election, curtime=curtime, votergroups=votergroups, appTitle=self.appTitle)
@identity.require(identity.not_anonymous())
@expose(template="elections.templates.ballot")
- def ballot(self,eid=None):
+ def vote(self,eid=None, **kw):
try:
eid = int(eid)
election = Elections.query.filter_by(id=eid).all()[0]
except ValueError:
election = Elections.query.filter_by(shortname=eid).all()[0]
eid = election.id
+ except TypeError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
+ except IndexError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
votergroups = LegalVoters.query.filter_by(election_id=eid).all()
@@ -81,54 +94,25 @@
if match == 0:
turbogears.flash("You are not in a FAS group that can vote in this election, more information can be found here.")
raise turbogears.redirect("/about/" + str(eid))
-
- curtime = datetime.utcnow()
- if election.end_date < curtime:
- turbogears.flash("You cannot vote in this election because the end date has passed. You have been redirected to the election results")
- raise turbogears.redirect("/results/" + str(eid))
- elif election.start_date > curtime:
- election_started=False
- else:
- election_started=True
- candidates = Candidates.query.filter_by(election_id=eid).order_by(Candidates.name).all()
- return dict(eid=eid, candidates=candidates, election=election, election_started=election_started)
-
- @identity.require(identity.not_anonymous())
- @expose(template="elections.templates.confirm")
- def vote(self, eid, **kw):
- try:
- election = Elections.query.filter_by(id=eid).all()[0]
- except IndexError:
- turbogears.flash("Sorry, that election does not exist")
- raise turbogears.redirect("/")
-
- votergroups = LegalVoters.query.filter_by(election_id=eid).all()
- match = 0
- for group in votergroups:
- if identity.in_group(group.group_name):
- match = 1
- if match == 0:
- turbogears.flash("You are not in a FAS group that can vote in this election, more information can be found here.")
- raise turbogears.redirect("/about/" + str(election.name))
-
candidates = Candidates.query.filter_by(election_id=eid).order_by(Candidates.name).all()
uservote = UserVoteCount.query.filter_by(election_id=eid, voter=turbogears.identity.current.user_name).all()
+ uvotes = {}
+ next_action = ""
- #Before we do *ANYTHING* check if voting hasn't begun/has ended
curtime = datetime.utcnow()
if election.start_date > curtime:
- turbogears.flash("Voting has not yet begun.")
+ turbogears.flash("Voting as not yet started, sorry.")
raise turbogears.redirect("/")
elif election.end_date < curtime:
- turbogears.flash("We are sorry, voting has now ended.")
- raise turbogears.redirect("/")
+ turbogears.flash("You cannot vote in this election because the end date has passed. You have been redirected to the election results")
+ raise turbogears.redirect("/results/" + election.shortname)
elif len(uservote) != 0:
- turbogears.flash("You've voted too many times!")
+ turbogears.flash("You have already voted in this election!")
raise turbogears.redirect("/")
-
+
+ # Lets do this in reverse order
if "confirm" in kw:
- uvotes = {}
for c in candidates:
if str(c.id) in kw:
try:
@@ -143,32 +127,40 @@
raise turbogears.redirect("/")
for uvote in uvotes:
Votes(voter=turbogears.identity.current.user_name, candidate_id=uvote, weight=uvotes[uvote], election_id=eid)
- turbogears.flash("Saved!")
- raise turbogears.redirect("/")
- else:
+ turbogears.flash("You vote has been recorded, thank you!")
+ raise turbogears.redirect("/")
+ elif "vote" in kw:
turbogears.flash("Please confirm your vote!")
- uvotes = {}
for c in candidates:
if str(c.id) in kw:
try:
range = int(kw[str(c.id)])
if range > len(candidates):
- turbogears.flash("One or more votes had incorrect data, please verify your ballot carefully!")
- uvotes[c.id] = len(candidates)
+ turbogears.flash("Invalid data was detected for one or more candidates and was changed to zeros! Please correct and resubmit your ballot.")
+ uvotes[c.id] = 0
+ next_action = "vote"
elif range >= 0:
uvotes[c.id] = range
else:
- turbogears.flash("One or more votes had incorrect data, please verify your ballot carefully!")
+ turbogears.flash("Invalid data was detected for one or more candidates and was changed to zeros! Please correct and resubmit your ballot.")
uvotes[c.id] = 0
+ next_action = "vote"
except ValueError:
- turbogears.flash("Invalid data was detected and changed to zeros!")
+ turbogears.flash("Invalid data was detected for one or more candidates and was changed to zeros! Please correct and resubmit your ballot.")
uvotes[c.id] = 0
+ next_action = "vote"
else:
turbogears.flash("Invalid Ballot!")
raise turbogears.redirect("/")
-
- return dict(voteinfo=uvotes, candidates=candidates, election=election)
+ if next_action != "vote":
+ next_action = "confirm"
+ else:
+ for c in candidates:
+ uvotes[c.id] = ""
+ next_action = "vote"
+ return dict(eid=eid, candidates=candidates, election=election, nextaction=next_action, voteinfo=uvotes, appTitle=self.appTitle)
+
@expose(template="elections.templates.results")
def results(self,eid=None):
try:
@@ -177,6 +169,13 @@
except ValueError:
election = Elections.query.filter_by(shortname=eid).all()[0]
eid = election.id
+ except TypeError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
+ except IndexError:
+ turbogears.flash("This election does not exist, check if you have used the correct URL.")
+ raise turbogears.redirect("/")
+
curtime = datetime.utcnow()
if election.public_results == 0 and election.end_date > curtime:
turbogears.flash("We are sorry, the results for this election cannot be viewed at this time because the election is still in progress.")
@@ -185,7 +184,7 @@
turbogears.flash("We are sorry, the results for this election cannot be viewed at this time because the election has not started.")
raise turbogears.redirect("/")
votecount = VoteTally.query.filter_by(election_id=eid).order_by(VoteTally.novotes.desc()).all()
- return dict(votecount=votecount, election=election)
+ return dict(votecount=votecount, election=election, appTitle=self.appTitle)
@expose(template="elections.templates.login", allow_json=True)
def login(self, forward_url=None, previous_url=None, *args, **kw):
@@ -216,7 +215,7 @@
response.status=403
return dict(message=msg, previous_url=previous_url, logging_in=True,
original_parameters=request.params,
- forward_url=forward_url, title='Fedora Account System Login')
+ forward_url=forward_url, title=self.appTitle + ' -- Fedora Account System Login')
@expose()
def logout(self):
Modified: trunk/elections/model.py
===================================================================
--- trunk/elections/model.py 2008-05-29 11:44:50 UTC (rev 38)
+++ trunk/elections/model.py 2008-05-31 05:56:31 UTC (rev 39)
@@ -27,7 +27,11 @@
ElectionsTable = Table('elections', metadata, autoload=True)
VotesTable = Table('votes', metadata, autoload=True)
CandidatesTable = Table('candidates', metadata, autoload=True)
-LegalVotersTable = Table('legalvoters', metadata, autoload=True)
+LegalVotersTable = Table('legalvoters', metadata,
+ Column('election_id', Integer,
+ ForeignKey('elections.id'), primary_key=True),
+ Column('group_name', String, nullable=False)
+)
# View in the DB. Needs to have the column keys defined
VoteTallyTable = Table('votecount', metadata,
Modified: trunk/elections/templates/about.html
===================================================================
--- trunk/elections/templates/about.html 2008-05-29 11:44:50 UTC (rev 38)
+++ trunk/elections/templates/about.html 2008-05-31 05:56:31 UTC (rev 39)
@@ -4,10 +4,9 @@
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="master.html" />
<head>
- <title>Welcome to TurboGears</title>
+ <title>${appTitle} -- Election Information</title>
</head>
- <body>
-<!-- Also need to list eligable voting groups... -->
+ <body>
<h1>${election.name}</h1>
<p>${election.info}</p>
<p py:if="election.url"><a href="${election.url}">[More Information]</a></p>
@@ -15,10 +14,14 @@
<tr py:for="candidate in candidates">
<td>${candidate.name} <small py:if="candidate.url"><a href="${candidate.url}">[info]</a></small></td>
</tr>
-<!-- This link is okay, but one should appear if the election has public results -->
+<!-- !This link is okay, but one should appear if the election has public results -->
<tr>
- <td><a href="${tg.url('/ballot/' + election.shortname)}">Vote Now!</a></td>
+ <td><a href="${tg.url('/vote/' + election.shortname)}">Vote Now!</a></td>
</tr>
- </table>
+ </table>
+ <p>To vote in this election you must be a member of any one of the following groups:</p>
+ <ul>
+ <li py:for="g in votergroups">${g.group_name}</li>
+ </ul>
</body>
</html>
Modified: trunk/elections/templates/ballot.html
===================================================================
--- trunk/elections/templates/ballot.html 2008-05-29 11:44:50 UTC (rev 38)
+++ trunk/elections/templates/ballot.html 2008-05-31 05:56:31 UTC (rev 39)
@@ -4,7 +4,7 @@
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="master.html" />
<head>
- <title>Welcome to TurboGears</title>
+ <title>${appTitle} -- Cast Your Vote</title>
</head>
<body>
<h1>${election.name}</h1>
@@ -14,11 +14,18 @@
<table border="1" cellpadding="1">
<tr py:for="candidate in candidates">
<td>${candidate.name} <small py:if="candidate.url"><a href="${candidate.url}">[info]</a></small></td>
- <td><input type="text" name="${candidate.id}" value="" /></td>
+ <py:if test="nextaction=='vote'">
+ <td><select name="${candidate.id}">
+ <option py:for="option in range(0,len(candidates)+1)" value="$option">$option</option>
+ </select></td>
+ </py:if>
+ <py:if test="nextaction=='confirm'">
+ <td><input type="hidden" name="${candidate.id}" value="${voteinfo[candidate.id]}" />${voteinfo[candidate.id]}</td>
+ </py:if>
</tr>
<tr>
- <td></td>
- <td><input type="submit" value="Submit" /></td>
+ <td><input py:if="nextaction=='confirm'" type="button" value="Go Back" onClick="javascript.history.back(1)" /></td>
+ <td><input type="submit" name="${nextaction}" value="Submit" /></td>
</tr>
</table>
</form>
Modified: trunk/elections/templates/list.html
===================================================================
--- trunk/elections/templates/list.html 2008-05-29 11:44:50 UTC (rev 38)
+++ trunk/elections/templates/list.html 2008-05-31 05:56:31 UTC (rev 39)
@@ -4,13 +4,13 @@
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="master.html" />
<head>
- <title>Welcome to TurboGears</title>
+ <title>${appTitle}</title>
</head>
<body>
<ul>
-<!-- Maybe change this link depending if they are logged in or not -->
+<!-- !Maybe change this link depending if they are logged in or not -->
<li py:for="election in elections"><a href="${tg.url('/about/' + election.shortname)}">${election.name}</a></li>
-<!-- Would be nice features also include voting dates -->
+<!-- !Would be nice features also include voting dates -->
</ul>
</body>
</html>
Modified: trunk/elections/templates/login.html
===================================================================
--- trunk/elections/templates/login.html 2008-05-29 11:44:50 UTC (rev 38)
+++ trunk/elections/templates/login.html 2008-05-31 05:56:31 UTC (rev 39)
@@ -4,7 +4,7 @@
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="master.html" />
<head>
- <title>Login</title>
+ <title>${appTitle}</title>
</head>
<body>
<div id="loginBox">
Modified: trunk/elections.sql
===================================================================
--- trunk/elections.sql 2008-05-29 11:44:50 UTC (rev 38)
+++ trunk/elections.sql 2008-05-31 05:56:31 UTC (rev 39)
@@ -23,8 +23,8 @@
create table legalVoters (
election_id integer not null,
group_name text not null,
-foreign key (election_id) references elections (id),
-primary key (election_id)
+foreign key (election_id) references elections (id)
+-- primary key (election_id)
);
create table candidates (
15 years, 11 months
Call For Testers - Elections Application
by Nigel Jones
Hi everyone,
With Fedora 9 out the door we hit a very busy time for elections, the previous system was, well lets just say, not optimal.
So I accepted the goal of creating an application by our post-release election season that would integrate well with FAS and would allow a different method of voting, Range Voting.
If your not familiar with Range Voting check out http://en.wikipedia.org/wiki/Range_voting the essentials however is that you rank candidates from 0<-># of candidates, if you don't like them, just rank them 0.
In the future, the application will not only allow the Board and Steering Committees to hold elections, it will (hopefully) become available to SIGs and Steering Committees for any time of poll/call to vote.
This is where you all come in, it's impossible for a small group of people to find every possible mistake or bug in ANY item of software, so the more people we can get in to test it and report bugs/issues/thoughts the better!
All I ask is 10-20 minutes of your time, whenever your free over the couple of days to test and provide feedback.
Instructions:
1) You'll need an account on the test instance of FAS at http://publictest10.fedoraproject.org/accounts/ (PLEASE) do not use your normal password and you don't need to do CLA etc (I've removed that requirement in the elections app for now).
2) Please direct your browser to https://publictest10.fedoraproject.org/elections/ and test away!
3) Try voting etc, make sure that you *can* view the results at https://publictest10.fedoraproject.org/elections/results/fedora but can't view the results at https://publictest10.fedoraproject.org/elections/results/president
Notes:
* I'm aware the UI is absolutely awful, there is already a ticket open for this (https://fedorahosted.org/elections/ticket/4) please feel free to add items there.
* Any errors you encounter that are 'unexpected' to you, please file a ticket at https://fedorahosted.org/elections/newticket setting Milestone to 'Release 0.1.0' with full reproduction steps, and the time it occurred (TZ=UTC date)
* Any other feedback can be directed to the elections-devel list (elections-devel(a)lists.fedorahosted.org)
After 5am UTC on the 1st June both elections will end and the 'results' should be public and hopefully we'll have a decent election app!
Thanks a lot & Happy Testing,
Nigel Jones
p.s. Sorry to those that fall asleep during my e-mail - I nearly did too!
p.s.s. Thanks must be given to Toshio, Ricky, Luca and Mike who have all assisted in this release
15 years, 11 months