--- /dev/null
+ AFFERO GENERAL PUBLIC LICENSE
+ Version 1, March 2002
+
+ Copyright © 2002 Affero Inc.
+ 510 Third Street - Suite 225, San Francisco, CA 94107, USA
+
+This license is a modified version of the GNU General Public License
+copyright (C) 1989, 1991 Free Software Foundation, Inc. made with their
+permission. Section 2(d) has been added to cover use of software over a
+computer network.
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+ Preamble
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the Affero General Public License is
+intended to guarantee your freedom to share and change free software--to
+make sure the software is free for all its users. This Public License
+applies to most of Affero's software and to any other program whose
+authors commit to using it. (Some other Affero software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price.
+This General Public License is designed to make sure that you have the
+freedom to distribute copies of free software (and charge for this
+service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone
+to deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis
+or for a fee, you must give the recipients all the rights that you have.
+You must make sure that they, too, receive or can get the source code.
+And you must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+Finally, any free program is threatened constantly by software patents.
+We wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program
+proprietary. To prevent this, we have made it clear that any patent must
+be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this Affero General Public License. The "Program",
+ below, refers to any such program or work, and a "work based on the
+ Program" means either the Program or any derivative work under
+ copyright law: that is to say, a work containing the Program or a
+ portion of it, either verbatim or with modifications and/or
+ translated into another language. (Hereinafter, translation is
+ included without limitation in the term "modification".) Each
+ licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of running
+the Program is not restricted, and the output from the Program is
+covered only if its contents constitute a work based on the Program
+(independent of having been made by running the Program). Whether that
+is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you
+ conspicuously and appropriately publish on each copy an appropriate
+ copyright notice and disclaimer of warranty; keep intact all the
+ notices that refer to this License and to the absence of any
+ warranty; and give any other recipients of the Program a copy of this
+ License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above,
+ provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive
+ use in the most ordinary way, to print or display an announcement
+ including an appropriate copyright notice and a notice that there
+ is no warranty (or else, saying that you provide a warranty) and
+ that users may redistribute the program under these conditions,
+ and telling the user how to view a copy of this License.
+ (Exception: if the Program itself is interactive but does not
+ normally print such an announcement, your work based on the
+ Program is not required to print an announcement.)
+
+ d) If the Program as you received it is intended to interact with
+ users through a computer network and if, in the version you
+ received, any user interacting with the Program was given the
+ opportunity to request transmission to that user of the Program's
+ complete source code, you must not remove that facility from your
+ modified version of the Program or work based on the Program, and
+ must offer an equivalent opportunity for all users interacting
+ with your Program through a computer network to request immediate
+ transmission by HTTP of the complete source code of your modified
+ version or other derivative work.
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program, and
+can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based on
+the Program, the distribution of the whole must be on the terms of this
+License, whose permissions for other licensees extend to the entire
+whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of a
+storage or distribution medium does not bring the other work under the
+scope of this License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+ Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the
+ following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for softpware interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed
+ only for noncommercial distribution and only if you received the
+ program in object code or executable form with such an offer, in
+ accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source code
+means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to control
+compilation and installation of the executable. However, as a special
+exception, the source code distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access
+to copy from a designated place, then offering equivalent access to copy
+the source code from the same place counts as distribution of the source
+code, even though third parties are not compelled to copy the source
+along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense or distribute the Program is
+ void, and will automatically terminate your rights under this
+ License. However, parties who have received copies, or rights, from
+ you under this License will not have their licenses terminated so
+ long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying
+ the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject
+ to these terms and conditions. You may not impose any further
+ restrictions on the recipients' exercise of the rights granted
+ herein. You are not responsible for enforcing compliance by third
+ parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do
+ not excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under
+ this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Program at all. For example,
+ if a patent license would not permit royalty-free redistribution of
+ the Program by all those who receive copies directly or indirectly
+ through you, then the only way you could satisfy both it and this
+ License would be to refrain entirely from distribution of the
+ Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is implemented
+by public license practices. Many people have made generous
+contributions to the wide range of software distributed through that
+system in reliance on consistent application of that system; it is up to
+the author/donor to decide if he or she is willing to distribute
+software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be
+a consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License
+ may add an explicit geographical distribution limitation excluding
+ those countries, so that distribution is permitted only in or among
+ countries not thus excluded. In such case, this License incorporates
+ the limitation as if written in the body of this License.
+
+9. Affero Inc. may publish revised and/or new versions of the Affero
+ General Public License from time to time. Such new versions will be
+ similar in spirit to the present version, but may differ in detail to
+ address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+Affero, Inc. If the Program does not specify a version number of this
+License, you may choose any version ever published by Affero, Inc.
+
+You may also choose to redistribute modified versions of this program
+under any version of the Free Software Foundation's GNU General Public
+License version 3 or higher, so long as that version of the GNU GPL
+includes terms and conditions substantially equivalent to those of this
+license.
+
+10. If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by
+ Affero, Inc., write to us; we sometimes make exceptions for this.
+ Our decision will be guided by the two goals of preserving the free
+ status of all derivatives of our free software and of promoting the
+ sharing and reuse of software generally.
+
+ NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
+ WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
+ PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND,
+ EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+ PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
+ THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGES.
===============================================
To use Selectricity, you'll need to install the following gems in
-addition to rails and its dependencies:
+addition to Ruby on Rails, MySQL, and its dependencies:
* rmagick
* gruff (http://nubyonrails.com/pages/gruff)
On Ubuntu, you can install install the dependencies with:
apt-get install imagemagick libmagick9-dev ruby1.8-dev libwmf-bin
+Our server configuration uses Mongrel (installed from gems) behind an
+Apache2 load balancing proxy using mod_proxy.
+
===============================================
=== Contributors to Selectricity Include ======
end
def show
+ @sidebar_content = render_to_string :partial => 'progress',
+ :locals => { :page => 'review' }
+
@election = Election.find(params[:id])
end
candidate.destroy
end
- def lessinfo_candidate
- @show_details = false
- @current_candidate = Candidate.find( params[:id] )
- render :partial => 'candidate_line'
- end
-
- def moreinfo_candidate
- @show_details = true
- @current_candidate = Candidate.find( params[:id] )
- render :partial => 'candidate_line'
- end
-
- def edit_candidate
- @candidate = Candidate.find( params[:id] )
- @election = @candidate.election
- end
-
- def update_candidate
- @candidate = Candidate.find(params[:id])
- @election = @candidate.election
-
- if @candidate.update_attributes(params[:candidate])
- redirect_to :action => 'edit_candidates', :id => @candidate.election.id
- else
- render :action => 'edit_candidate'
- end
- end
-
def candidate_picture
candidate = Candidate.find( params[:id] )
send_data( candidate.picture.data,
## for a particular election
####################################################################
def new_voters
- edit_voters
+ redirect_to :action => 'edit_voters', :id => params[:id]
end
def edit_voters
+ @sidebar_content = render_to_string :partial => 'progress',
+ :locals => { :page => 'voters' }
+
@election = Election.find( params[:id] )
if params.has_key?( :raw_voter_list )
process_incoming_voters( params[:raw_voter_list] )
voter.destroy
end
- def remind_voter
- voter_array= FullVoter.find(:all, :conditions => ["email = ?", params[:email]])
- voter_array.delete_if {|voter| voter.election.active == 0}
- unless voter_array.empty?
- VoterNotify.deliver_reminder(voter_array)
- end
- end
-
## methods for computing and printing results
####################################################################
def results
require_dependency "election"
def index
- password = params[:id]
- password = params[:vote][:password] if params[:vote]
- if @voter = FullVoter.find(:all, :conditions => [ "password = ?", password ] )[0]
+ if params[:urlpassword]
+ password = params[:urlpassword]
+ else
+ password = nil
+ end
+
+ if @voter = FullVoter.find(:all, :conditions =>
+ [ "password = ?", password ] )[0]
@voter.vote = Vote.new if @voter.vote.nil?
@voter.vote.set_defaults! if @voter.vote.rankings.empty?
+
+ @election = @voter.election
+ @sidebar_content = render_to_string(:partial => 'sortable_vote')
render :action => 'full_vote'
+ elsif params[:urlpassword]
+ redirect_to :action => 'index'
+ end
+ end
+
+ def login
+ if params[:vote] and params[:vote][:password]
+ redirect_to votepassword_url( :action => 'index', :urlpassword => params[:vote][:password])
+ else
+ redirect_to :action => 'index'
end
end
end
end
+ def reminder
+ if params[:email]
+ voter_array= FullVoter.find(:all, :conditions => ["email = ?", params[:email]])
+ voter_array.delete_if {|voter| voter.election.active == 0}
+ unless voter_array.empty?
+ VoterNotify.deliver_reminder(voter_array)
+ end
+ render :action => 'reminder_sent'
+ end
+ end
+
+
private
def authenticate
password = params[:id]
#Calculate results if not in memcache
def results
# Assignment is intentional
- if defined? Cache and c = Cache.get("election_results:#{id}:#{self.votes.length}")
+ if Cache and c = Cache.get("election_results:#{id}:#{self.votes.length}")
@plurality_result = c['plurality']
@approval_result = c['approval']
@condorcet_result = c['condorcet']
@ssd_result = c['ssd']
@borda_result = c['borda']
return c
- elsif defined? Cache
+ elsif Cache
# memcache is available, but missed.
results = self.results!
Cache.set("election_results:#{id}:#{self.votes.length}", results)
-<% %>
-
-<p>New candidate name:<br />
+<p><label for="candidate_name">Name</label><br />
<%= text_field :candidate, :name, :size => 60 %></p>
-<p>Candidate description/platform (optional):<br />
+<p><label for="candidate_description">Description/Platform</label> (optional)<br />
<%= text_area :candidate, :description, :cols => 60, :rows => 5 %></p>
-<p>Candidate picture (optional and < 100x100 pixels):<br />
+
+<p style="float: left;"><label for="candidate_picture">Picture</label> (optional and < 100x100 pixels)<br />
<%= file_field :candidate, :picture %></p>
+<div class="clear-div"></div>
<div id="cand<%= @current_candidate.id %>">
<li><%=h @current_candidate.name -%>
- <% if @show_details %>
- (<%= link_to_remote "Hide Details",
- :update => "cand#{@current_candidate.id}",
- :url => { :action => :lessinfo_candidate,
- :id => @current_candidate.id } %>)
- <br />
- <blockquote>
- <%=h (@current_candidate.description) %>
- </blockquote>
- <% else %>
- (<%= link_to_remote "Show Details",
- :update => "cand#{@current_candidate.id}",
- :url => { :action => :moreinfo_candidate,
- :id => @current_candidate.id } %>)
- <% end %>
+ <span id="show_candidate_link_<%= @current_candidate.id %>">
+ (<%= link_to "Show Details", "#",
+ :onclick => "show_candidate_info(#{@current_candidate.id}); return false;" %>)
+ </span>
+ <span style="display: none;" id="hide_candidate_link_<%= @current_candidate.id %>">
+ (<%= link_to "Hide Details", "#",
+ :onclick => "hide_candidate_info(#{@current_candidate.id}); return false;" %>)
+ <br />
+
+ <div style="display: none;" id="candidate_description_<%= @current_candidate.id %>">
+ <%=h (@current_candidate.description) %>
+ </>
+ </span>
</li>
</div>
-<% -%>
-<div id="cand<%= @current_candidate.id %>">
-<p><strong><%=h @current_candidate.name %></strong>
- (<%= link_to_remote "Delete",
+<div class="candidate_box" id="cand<%= @current_candidate.id %>">
+ <div class="candidate_box_name"><%=h @current_candidate.name %></div>
+ <div class="candidate_box_menu">
+ <%= link_to_remote "Delete",
:complete => "Element.remove('cand#{@current_candidate.id}')",
:url => { :action => :delete_candidate,
- :id => @current_candidate.id } %> |
- <%= link_to "Edit", :action => 'edit_candidate', :id =>
- @current_candidate.id %>)<br />
- <blockquote>
- <table><tr><td valign="top">
- <% if @current_candidate.picture? %>
- <img src="<%= url_for :action => 'candidate_picture',
- :id => @current_candidate.id %>"
- align="top" width="80px" />
- <% end %>
- </td>
- <% if @current_candidate.description.length > 0 %>
- <td valign="top">
- <em>Description:</em><br />
- <%= h(@current_candidate.description) %>
- </td>
- <% else %>
- <td></td>
- <% end %>
- </tr></table>
- </blockquote>
+ :id => @current_candidate.id } %>
+ </div>
+ <div class="clear-div"></div>
+
+ <div class="candidate_box_info">
+ <div class="candidate_box_picture">
+ <% if @current_candidate.picture? %>
+ <img src="<%= url_for :action => 'candidate_picture',
+ :id => @current_candidate.id %>" />
+ <% end %>
+ </div>
+ <div class="candidate_box_description">
+ <% if @current_candidate.description.length > 0 %>
+ <%= h(@current_candidate.description) %>
+ <% else %>
+ <!-- no description -->
+ <% end %>
+ </div>
+ <div class="clear-div"></div>
+ </div>
</p>
</div>
-<% %>
<ul id="candidate_list">
<% @election.candidates.each do |candidate| %>
<% @current_candidate = candidate %>
- <%= render(:partial => 'candidate_line')%>
+ <%= render(:partial => 'election/candidate_line')%>
<% end %>
</ul>
+
+<script>
+function show_candidate_info(id) {
+ Element.hide($("show_candidate_link_" + id));
+ Element.show($("candidate_description_" + id));
+ Element.show($("hide_candidate_link_" + id));
+}
+
+function hide_candidate_info(id) {
+ Element.hide($("hide_candidate_link_" + id));
+ Element.hide($("candidate_description_" + id));
+ Element.show($("show_candidate_link_" + id));
+}
+</script>
<%= datetime_select :election, :startdate %></p>
-->
-<p>Election End Date<br />
+<p><label for="election_enddate">Election End Date</label><br />
<font size="-1"><em>All elections end at 23:59.</em></font><br />
<%= date_select :election, :enddate %></p>
+<p><label for="election_election_method">Election Method</label><br />
+<% type_hash = {}; ELECTION_TYPES.each {|k,v| type_hash[v] = k} %>
+<%= select_tag 'election[election_method]', options_for_select(type_hash, @election.election_method) %></p>
+
<!--[eoform:election]-->
-->
<%= hidden_field :raw_voter_list, :email, :value => 2 %>
</p>
-<%= submit_tag "Add Voters" %>
+
+<p><%= submit_tag "Add Voters" %></p>
+++ /dev/null
-<h1>Editing <%=h @candidate.name %></h1>
-
-<%= error_messages_for :candidate %>
-<% form_tag( { :action => :update_candidate, :id => @candidate.id },
- :multipart => true ) do %>
-<%= render :partial => 'candidate_form' %>
-<%= submit_tag "Save" %>
-<% end %>
-
-<h2>Edit/Add Candidates</h2>
+<div id="title-header">
+ <span class="header">Edit Candidates</span>
+ <span class="subheader"></span>
+</div>
+
+<div class="clear-div"></div>
+
+<div class="normal-header">
+ <span class="header">Enter New Candidate</span>
+ <span class="subheader"></span>
+</div>
<%= error_messages_for :candidate %>
-<% unless @election.candidates.empty? %>
- <p>The following are valid options or candidates in this election:</p>
+<% form_tag( { :action => :add_candidate, :id => @election.id },
+ :multipart => true ) do %>
+<%= render :partial => 'candidate_form' %>
+<p><%= submit_tag "Add Candidate" %></p>
+<% end %>
+
+<div class="normal-header">
+ <span class="header">Current Candidates</span>
+ <span class="subheader"></span>
+</div>
+
+
+<% unless @election.candidates.empty? %>
<% @election.candidates.each do |candidate| %>
<% @current_candidate = candidate %>
<%= render :partial => 'candidate_line_edit' %>
<p>There are no candidates registered for this election.</p>
<% end %>
-<p>Please enter new candidates below.</p>
+<div class="normal-header">
+ <span class="header">Continue</span>
+ <span class="subheader"></span>
+</div>
-<% form_tag( { :action => :add_candidate, :id => @election.id },
- :multipart => true ) do %>
-<%= render :partial => 'candidate_form' %>
-<%= submit_tag "Add Candidate" %>
-<% end %>
+<p>When you are done entering candidates, please click the button below
+to proceed to the next step.</p>
-<%= button_to "Done!", :action => 'new_voters', :id => @election %>
+<%= button_to "Proceed to Next Step", :action => 'new_voters', :id => @election %>
-<% @edit = true %>
-<h1>Edit Voter List</h1>
+<div id="title-header">
+ <span class="header">Edit Voter List</span>
+ <span class="subheader"></span>
+</div>
<%= render :partial => 'voter_list' %>
<%= render :partial => 'voters_form' %>
<% end %>
-<%= button_to 'Done!', :action => 'show', :id => @election.id %>
+<div class="normal-header">
+ <span class="header">Continue</span>
+ <span class="subheader"></span>
+</div>
+
+<p>When you are done entering voters, please click the button below
+to proceed to the next step.</p>
+
+<%= button_to 'Proceed to Next Step!', :action => 'show', :id => @election.id %>
-<h2>Vote Overview</h2>
+<div id="title-header">
+ <span class="header">Election Overview</span>
+ <span class="subheader"></span>
+</div>
<% form_tag (:action => 'create_election') do %>
<%= render :partial => 'overview_form' %>
+++ /dev/null
-<% %>
-<h1>Listing elections</h1>
-
-<table cellpadding="10px">
-
-<% for election in @elections %>
- <tr>
- <td valign="top"><h2><%=h link_to election.name, :action => 'show', :id => election %></h2>
- <p><strong>Description:</strong></p>
- <blockquote><%=h election.description %></blockquote>
-
- <p><strong>Election Information:</strong></p>
- <ul>
- <li><%= election.voters.length %> registered voters</li>
- <li><%= "<strong>Not</strong> " unless election.anonymous == 1 %>Anonymous</li>
- <li>Starts <%= election.startdate %></li>
- <li>Ends <%= election.enddate %></li>
- </ul>
- </td>
- <td valign="top">
- <p><strong>Candidates:</strong></p>
- <% @election = election %><%= render :partial => 'candidate_list', :id => election.id %>
- </td>
- <td valign="top">
- <%= link_to 'Destroy', { :action => 'destroy', :id => election }, :confirm => 'Are you sure?' %></td>
- </tr>
-<% end %>
-</table>
-
-<%= link_to 'Previous page', { :page => @election_pages.current.previous } if @election_pages.current.previous %>
-<%= link_to 'Next page', { :page => @election_pages.current.next } if @election_pages.current.next %>
-
-<br />
-
-<%= link_to 'New election', :action => 'new' %>
+++ /dev/null
-The message has been sent, please check your inbox soon.
\ No newline at end of file
-<h1>Vote Information</h1>
+<div id="title-header">
+ <span class="header">Election Overview</span>
+ <span class="subheader"></span>
+</div>
<% if @election.active? %>
<div id="status">Vote is in currently in progress. Return to
:action => 'results', :id => @election.id %>.</div>
<% end %>
-<h2>Overview</h2>
-
<p><strong>Summary</strong></p>
<blockquote>
<p><%= link_to "Edit overview.", :action => 'edit', :id => @election.id %></p>
<% end %>
-<h2>Candidates</h2>
-<% %>
+<div class="normal-header">
+ <span class="header">Candidates</span>
+ <span class="subheader"></span>
+</div>
+
<% unless @election.candidates.empty? %>
<%= render :partial => 'candidate_list' %>
<% unless @election.active %>
<% end %>
-<h2>Voters</h2>
+<div class="normal-header">
+ <span class="header">Voters</span>
+ <span class="subheader"></span>
+</div>
<% unless @election.voters.empty? %>
<%= render :partial => 'voter_list' %>
<% end %>
<% unless @election.active? %>
- <h2>Start Election</h2>
+
+<div class="normal-header">
+ <span class="header">Start Election</span>
+ <span class="subheader"></span>
+</div>
<% if @election.start_blockers.length > 0 %>
<p>Your vote cannot be started for the following reasons:</p>
<p><%= submit_tag 'Log in' %></p>
<% end %>
-<p><%= link_to 'Lost or forgot your password?', :controller => 'account', :action => 'forgot_password' %></p>
+<!-- <p><%= link_to 'Lost or forgot your password?', :controller => 'account', :action => 'forgot_password' %></p> -->
</ul>
<% end %>
+<p><%= link_to "Create a new election", :controller => 'election', :action => 'new' %>.</p>
+
<p>If you have received an email with a token inviting you to vote in
an ongoing election, you can log in to vote using your token below.</p>
- <% form_tag(:controller => 'voter', :action => 'index') do %>
+ <% form_tag(:controller => 'voter', :action => 'login') do %>
<p><%= text_field :vote, :password %></p>
<p><%= submit_tag "Log In" %></p>
<% end %>
- <p><%= link_to 'Lost or forgot your token?', :controller => 'voter', :action => 'forgot_password' %></p>
+ <p><%= link_to 'Lost or forgot your token?', :controller => 'voter', :action => 'reminder' %></p>
<h3>SMS Interface</h3>
<p>For information on accessing Selectricity over email or via SMS/text messages from your mobile phone, email <%= link_to "vote\@selectricity.org", "mailto:vote@selectricity.org" %> with "help" in the body or read the <%= link_to "Selectricity Anywhere documentation", :controller => 'about', :action => 'anywhere' %>.</p>
existing vote. You can log in <!-- or create a new account -->below.</p>
<%= render :partial => 'basic_login' %>
+
+ <p>Full elections creation is not yet public. <a
+ href="mailto:team@selectricity.org">Contact us</a> for access.</p>
+
+ <!-- <p>If you do not yet have an account, you should <%= link_to "create
+ one", :controller => 'account', :action => 'signup' %>.</p> -->
<% end %>
- <p>Full elections creation is not yet public. <%= link_to("Contact us",
- "mailto:team@selectricity.org") %> for access.</p>
+
</div>
</div>
<p><label for="quickvote_election_method">Election Method</label></p>
+<!--
+<% type_hash = {}; ELECTION_TYPES.each {|k,v| type_hash[v] = k} %>
+<%= select_tag 'election_election_method', options_for_select(type_hash, @quickvote.election_method) %></p>
+-->
<p><%= quickform.select('election_method',
%w(ssd condorcet plurality approval borda) ) %></p>
<div id="title-header">
- <span class="header">Quickvote</span>
- <span class="subheader"><%=h @voter.election.description.capitalize %></span>
+ <span class="header">Quickvote</span>
+ <span class="subheader"><%=h @voter.election.description.capitalize %></span>
</div>
<div class="clear-div"></div>
+<h2>Your Vote</h2>
+
+<p>Please vote by dragging items in the list below into your preferred
+order.</p>
+
<div id="sortable_list">
<ol id="rankings-list">
<% for ranking in @voter.vote.rankings %>
<%= sortable_element 'rankings-list',
:url => { :action => "sort_candidates", :id => @voter.vote.id },
:complete => visual_effect(:highlight, 'rankings-list') %>
+
+<div style="margin-left: 30pt;">
+<%= button_to "Confirm Vote", :action => 'review', :id => @voter.password %>
+</div>
+++ /dev/null
-<h4>Deleted your email? Lost your password?</h4>
-<p>Not to worry, enter the email at which you were supposed to receive your
-password, and we'll hook you up with a set of magic numbers that shall grant
-access to the chambers within. Hoo-rah!</p>
-
-<% form_tag :controller => 'election', :action => 'remind_voter' do %>
-
- <p><span label for="email">Email</label></span>
- <%= text_field_tag :email %></p>
-
- <%= submit_tag "Submit" %>
-<% end -%>
-<% %>
+<div id="title-header">
+ <span class="header">Vote</span>
+ <span class="subheader"><%= @voter.election.name %></span>
+</div>
-<p><strong>Election:</strong> <%= @voter.election.name %></p>
-<p><strong>Voter:</strong> <%= @voter.email %></p>
<p><strong>Description:</strong></p>
-<blockquote><%= @voter.election.description %></blockquote>
+<p><%= @voter.election.description %></p>
-<%= render :partial => 'sortable_vote' %>
+<div class="normal-header">
+ <span class="header">Current Voter</span>
+ <span class="subheader"></span>
+</div>
-<%= button_to "Submit Vote", :action => 'review', :id => @voter.password %>
+<p><strong><%= @voter.email %></strong></p>
+
+<div class="normal-header">
+ <span class="header">Instructions</span>
+ <span class="subheader"></span>
+</div>
+
+<p>Drag and drop the items on <strong>list in the left column</strong>
+until they are in order from most preferred at the top to least
+preferred at the bottom. When you are done, press confirm to record your
+vote.</p>
+
+<div class="normal-header">
+ <span class="header">Candidate List</span>
+ <span class="subheader"></span>
+</div>
+
+<% @voter.election.candidates.each do |candidate| %>
+ <% @current_candidate = candidate %>
+
+ <div id="cand<%= @current_candidate.id %>">
+ <h3><%=h @current_candidate.name -%></h3>
+ <blockquote>
+ <%=h (@current_candidate.description) %>
+ </blockquote>
+ </div>
+ <% end %>
+</ul>
-<% %>
+<div id="title-header">
+ <span class="header">Voter Login</span>
+ <span class="subheader"></span>
+</div>
<p>Please enter your password/token to log in and vote:</p>
-<% form_tag(:action => 'index') do %>
+<% form_tag(:action => 'login') do %>
<%= text_field :vote, :password %>
<%= submit_tag "Log In" %>
<% end %>
--- /dev/null
+<div id="title-header">
+ <span class="header">Password Reminder</span>
+ <span class="subheader"></span>
+</div>
+
+<p>Enter the email at which you were supposed to receive your password,
+and we'll send you a new password over email for every election that you
+are currently registered.</p>
+
+<% form_tag :action => 'reminder' do %>
+
+ <p><span label for="email">Email</label></span>
+ <%= text_field_tag :email %></p>
+
+ <%= submit_tag "Submit" %>
+<% end -%>
--- /dev/null
+<div id="title-header">
+ <span class="header">Reminder Sent</span>
+ <span class="subheader"></span>
+</div>
+
+<p>The message has been sent, please check your inbox.</p>
-<% %>
+<div id="title-header">
+ <span class="header">Review</span>
+ <span class="subheader"><%= @voter.election.name %></span>
+</div>
-<% %>
-<h1>Please review your vote carefully before confirming it.</h1>
+<p><strong>Your vote will not be recorded until you confirm it on this
+page.</strong> Please review your vote carefully before clicking
+confirm.</p>
<p>You have ranked the candidates in the following order (from most
preferred to least preferred:</p>
<% end %>
</ol>
-<table>
-<tr>
- <td valign="top"><%= button_to 'Confirm', :action => 'confirm', :id => @voter.password %></td>
- <td valign="top">Confirm this vote now. You will be able to go back and
- change it.</td>
-</tr>
+<div class="normal-header">
+ <span class="header">Confirm/Discard</span>
+ <span class="subheader"></span>
+</div>
-<tr>
- <td valign="top"><%= button_to 'Change', :action => 'index', :id => @voter.password %></td>
- <td valign="top">Go back to the voting page and vote again.</td>
-</tr>
+<p>Please select from one of the following pages.</p>
-<tr>
- <td valign="top"><%= button_to 'Discard', :action => 'discard' %></td>
- <td valign="top">Discard this tentative vote and log out.</td>
-</tr>
+<div style="text-align: center;">
+ <p><%= button_to 'Confirm This Vote', :action => 'confirm', :id => @voter.password %></p>
+
+ <p>If you choose, you will be able to go back<br />and change it up until
+ the end of hte voting period.</p>
-</table>
+ <p><%= button_to 'Discard This Vote', votepassword_url(
+ :action => 'index', :urlpassword => @voter.password) %></p>
+
+ <p>You will be returned to the voting page to vote<br /> again, if you choose.</p>
+
+</tr>
+</div>
-<% %>
+<div id="title-header">
+ <span class="header">Vote Recorded</span>
+ <span class="subheader"></span>
+</div>
-<p>Your vote has been recorded.</p>
+<p>Your vote has been recorded for the <strong><%= @voter.election.name
+%></strong>.</p>
<p>Your unique token for this vote is: <strong><%= @voter.vote.token %></strong></p>
-<p>Please record this token for your records and keep it secret. You
-will be able to use this token to verify that your vote was used in the
-election and that your vote was recorded correctly.</p>
+<p>Please record this token for your records and keep it secret. This is
+<strong>not</strong> the same token that you recieved in email. At the
+end of the election, you will be able to use this token to verify that
+your vote was used in the election and that your vote was recorded
+correctly.</p>
Voter!
-Either you or an election administrator has requested you receive a reminder for an election you've been registered in.
+Either you or an election administrator has requested you receive a
+reminder for an election you've been registered in.
+
+Here are the election(s) for which you are currently registered and your
+tokens to enter each election:
-Here are the election(s) for which you are currently registered and your tokens to enter each election:
<% @voter_array.each do |voter| -%>
<%= voter.election.name %>: <%= voter.password %>
<% end -%>
-
If you feel there is a technical error, please contact:
- help@selectricity.org
+ team@selectricity.org
(Selectricity Tech Support)
Thanks and happy voting!
<%= @voter.password %>
Alternatively, you can just click this URL:
- http://selectricity.org<%= url_for :controller => 'voter' %>
+ <%= votepassword_url( :host => 'selectricity.org', :urlpassword => @voter.password) %>
If you have any questions or if you feel you have received this message
in error, you should contact:
Alternatively, if you feel there is a technical error, please contact:
- help@selectricity.org
+ team@selectricity.org
(Selectricity Tech Support)
Thanks and happy voting!
# Include your application configuration below
-MAIL_CONFIG = { :from => 'Selectricity <info@selectricity.org>'}
+MAIL_CONFIG = { :from => 'Selectricity <team@selectricity.org>'}
require 'uniq_token'
require 'randarray'
map.connect '/sitealizer/:action', :controller => 'sitealizer'
+ map.connect 'voter/:action',
+ :controller => 'voter',
+ :requirements => { :action => /(review|confirm|authenticate|index|login|reminder)/ }
+
+ map.votepassword 'voter/:urlpassword',
+ :controller => 'voter',
+ :action => 'index'
map.connect 'quickvote/:action/:id',
:controller => 'quickvote',
background-color: #f0f0f0;
}
-li.moveable {
- background-color: #E5FFCC;
- border:1px solid #4D801A;
- cursor: move;
- padding: 4px;
- margin: 4px;
-}
-
-#sortable_list {
- font-size: 24pt;
- display: float;
- float: left;
-}
-
.result_table {
text-align: center;
margin-bottom: 1em;
margin: 0;
padding: 0;
}
+
+/* main election candidate stylesheet information */
+
+.candidate_box {
+}
+.candidate_box_name {
+ float: left;
+ font-size: 1.3em;
+ font-weight: bold;
+}
+.candidate_box_menu {
+ text-align: right;
+ float: right;
+ font-size: 0.8em;
+ font-weight: bold;
+}
+.candidate_box_info {
+ margin: 0.5em 0 0.5em 3em;
+}
+/*.candidate_box_picture {
+ width: 100px;
+ float: left;
+ margin: 0 0.8em 0.5em 0;
+}*/
+.candidate_box_picture img {
+ width: 100px;
+ border: 1px solid black;
+}
+.candidate_box_description {
+ display: inline;
+}
#title-header .subheader {
color: #74ce00;
}
+
+#sortable_list {
+ font-size: 24pt;
+ display: float;
+ float: left;
+}
+
+li.moveable {
+ background-color: #E5FFCC;
+ border:1px solid #4D801A;
+ cursor: move;
+ padding: 4px;
+ margin: 4px;
+}
+
color: #005cd9;
background-color: #e5e5e5;
}
+
+#sortable_list {
+ display: float;
+ float: left;
+}
+
+li.moveable {
+ background-color: #c0d9fb;
+ border:1px solid #005cd9;
+ cursor: move;
+ padding: 4px;
+ margin: 4px;
+}
+