From: Date: Thu, 31 Jan 2008 02:06:07 +0000 (-0500) Subject: merged changed in from devel to activate voting in full elections X-Git-Url: https://projects.mako.cc/source/selectricity-live/commitdiff_plain/c35eb01007440d21ded1ec10e56406108fe44294?hp=d857bfeff0568003715939fab8aa2925261272a6 merged changed in from devel to activate voting in full elections also, fixed some typos in the merged code --- diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..65303de --- /dev/null +++ b/COPYING @@ -0,0 +1,301 @@ + 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. diff --git a/README b/README index 22f3eb7..9980f41 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ =============================================== 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) @@ -21,6 +21,9 @@ Also, you will need install the other applications installed first: 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 ====== diff --git a/app/controllers/election_controller.rb b/app/controllers/election_controller.rb index 89a2c22..acf47cc 100644 --- a/app/controllers/election_controller.rb +++ b/app/controllers/election_controller.rb @@ -43,6 +43,9 @@ class ElectionController < ApplicationController end def show + @sidebar_content = render_to_string :partial => 'progress', + :locals => { :page => 'review' } + @election = Election.find(params[:id]) end @@ -94,34 +97,6 @@ class ElectionController < ApplicationController 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, @@ -134,10 +109,13 @@ class ElectionController < ApplicationController ## 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] ) @@ -150,14 +128,6 @@ class ElectionController < ApplicationController 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 diff --git a/app/controllers/voter_controller.rb b/app/controllers/voter_controller.rb index fb1bec7..461be29 100644 --- a/app/controllers/voter_controller.rb +++ b/app/controllers/voter_controller.rb @@ -5,12 +5,30 @@ class VoterController < ApplicationController 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 @@ -33,6 +51,18 @@ class VoterController < ApplicationController 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] diff --git a/app/models/election.rb b/app/models/election.rb index cd809ab..99d64f9 100644 --- a/app/models/election.rb +++ b/app/models/election.rb @@ -91,14 +91,14 @@ class Election < ActiveRecord::Base #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) diff --git a/app/views/election/_candidate_form.rhtml b/app/views/election/_candidate_form.rhtml index ed14dff..fcbf072 100644 --- a/app/views/election/_candidate_form.rhtml +++ b/app/views/election/_candidate_form.rhtml @@ -1,11 +1,11 @@ -<% %> - -

New candidate name:
+


<%= text_field :candidate, :name, :size => 60 %>

-

Candidate description/platform (optional):
+

(optional)
<%= text_area :candidate, :description, :cols => 60, :rows => 5 %>

-

Candidate picture (optional and < 100x100 pixels):
+ +

(optional and < 100x100 pixels)
<%= file_field :candidate, :picture %>

+
diff --git a/app/views/election/_candidate_line.rhtml b/app/views/election/_candidate_line.rhtml index e5bcf07..6b5b553 100644 --- a/app/views/election/_candidate_line.rhtml +++ b/app/views/election/_candidate_line.rhtml @@ -1,19 +1,17 @@
  • <%=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 } %>) -
    -
    - <%=h (@current_candidate.description) %> -
    - <% else %> - (<%= link_to_remote "Show Details", - :update => "cand#{@current_candidate.id}", - :url => { :action => :moreinfo_candidate, - :id => @current_candidate.id } %>) - <% end %> + + (<%= link_to "Show Details", "#", + :onclick => "show_candidate_info(#{@current_candidate.id}); return false;" %>) + +
  • diff --git a/app/views/election/_candidate_line_edit.rhtml b/app/views/election/_candidate_line_edit.rhtml index 61a9f63..0fd5b67 100644 --- a/app/views/election/_candidate_line_edit.rhtml +++ b/app/views/election/_candidate_line_edit.rhtml @@ -1,29 +1,28 @@ -<% -%> -
    -

    <%=h @current_candidate.name %> - (<%= link_to_remote "Delete", +

    +
    <%=h @current_candidate.name %>
    +
    + <%= 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 %>)
    -
    - - <% if @current_candidate.description.length > 0 %> - - <% else %> - - <% end %> -
    - <% if @current_candidate.picture? %> - - <% end %> - - Description:
    - <%= h(@current_candidate.description) %> -
    -
    + :id => @current_candidate.id } %> +
    +
    + +
    +
    + <% if @current_candidate.picture? %> + + <% end %> +
    +
    + <% if @current_candidate.description.length > 0 %> + <%= h(@current_candidate.description) %> + <% else %> + + <% end %> +
    +
    +

    diff --git a/app/views/election/_candidate_list.rhtml b/app/views/election/_candidate_list.rhtml index 881c0a5..2691f5b 100644 --- a/app/views/election/_candidate_list.rhtml +++ b/app/views/election/_candidate_list.rhtml @@ -1,7 +1,20 @@ -<% %> + + diff --git a/app/views/election/_overview_form.rhtml b/app/views/election/_overview_form.rhtml index 7d575e9..8efa1b3 100644 --- a/app/views/election/_overview_form.rhtml +++ b/app/views/election/_overview_form.rhtml @@ -15,9 +15,13 @@ <%= datetime_select :election, :startdate %>

    --> -

    Election End Date
    +


    All elections end at 23:59.
    <%= date_select :election, :enddate %>

    +


    +<% type_hash = {}; ELECTION_TYPES.each {|k,v| type_hash[v] = k} %> +<%= select_tag 'election[election_method]', options_for_select(type_hash, @election.election_method) %>

    + diff --git a/app/views/election/_voters_form.rhtml b/app/views/election/_voters_form.rhtml index 87df4ce..8130ade 100644 --- a/app/views/election/_voters_form.rhtml +++ b/app/views/election/_voters_form.rhtml @@ -11,4 +11,5 @@ address per line).

    --> <%= hidden_field :raw_voter_list, :email, :value => 2 %>

    -<%= submit_tag "Add Voters" %> + +

    <%= submit_tag "Add Voters" %>

    diff --git a/app/views/election/edit_candidate.rhtml b/app/views/election/edit_candidate.rhtml deleted file mode 100644 index 7e1dd65..0000000 --- a/app/views/election/edit_candidate.rhtml +++ /dev/null @@ -1,9 +0,0 @@ -

    Editing <%=h @candidate.name %>

    - -<%= error_messages_for :candidate %> -<% form_tag( { :action => :update_candidate, :id => @candidate.id }, - :multipart => true ) do %> -<%= render :partial => 'candidate_form' %> -<%= submit_tag "Save" %> -<% end %> - diff --git a/app/views/election/edit_candidates.rhtml b/app/views/election/edit_candidates.rhtml index dcd601a..7e1f315 100644 --- a/app/views/election/edit_candidates.rhtml +++ b/app/views/election/edit_candidates.rhtml @@ -1,10 +1,31 @@ -

    Edit/Add Candidates

    +
    + Edit Candidates + +
    + +
    + +
    + Enter New Candidate + +
    <%= error_messages_for :candidate %> -<% unless @election.candidates.empty? %> -

    The following are valid options or candidates in this election:

    +<% form_tag( { :action => :add_candidate, :id => @election.id }, + :multipart => true ) do %> +<%= render :partial => 'candidate_form' %> +

    <%= submit_tag "Add Candidate" %>

    +<% end %> + +
    + Current Candidates + +
    + + +<% unless @election.candidates.empty? %> <% @election.candidates.each do |candidate| %> <% @current_candidate = candidate %> <%= render :partial => 'candidate_line_edit' %> @@ -14,12 +35,12 @@

    There are no candidates registered for this election.

    <% end %> -

    Please enter new candidates below.

    +
    + Continue + +
    -<% form_tag( { :action => :add_candidate, :id => @election.id }, - :multipart => true ) do %> -<%= render :partial => 'candidate_form' %> -<%= submit_tag "Add Candidate" %> -<% end %> +

    When you are done entering candidates, please click the button below +to proceed to the next step.

    -<%= button_to "Done!", :action => 'new_voters', :id => @election %> +<%= button_to "Proceed to Next Step", :action => 'new_voters', :id => @election %> diff --git a/app/views/election/edit_voters.rhtml b/app/views/election/edit_voters.rhtml index 1e98fba..8819b95 100644 --- a/app/views/election/edit_voters.rhtml +++ b/app/views/election/edit_voters.rhtml @@ -1,5 +1,7 @@ -<% @edit = true %> -

    Edit Voter List

    +
    + Edit Voter List + +
    <%= render :partial => 'voter_list' %> @@ -7,4 +9,12 @@ <%= render :partial => 'voters_form' %> <% end %> -<%= button_to 'Done!', :action => 'show', :id => @election.id %> +
    + Continue + +
    + +

    When you are done entering voters, please click the button below +to proceed to the next step.

    + +<%= button_to 'Proceed to Next Step!', :action => 'show', :id => @election.id %> diff --git a/app/views/election/general_information.rhtml b/app/views/election/general_information.rhtml index be09953..dd1271c 100644 --- a/app/views/election/general_information.rhtml +++ b/app/views/election/general_information.rhtml @@ -1,4 +1,7 @@ -

    Vote Overview

    +
    + Election Overview + +
    <% form_tag (:action => 'create_election') do %> <%= render :partial => 'overview_form' %> diff --git a/app/views/election/list.rhtml b/app/views/election/list.rhtml deleted file mode 100644 index 321bf46..0000000 --- a/app/views/election/list.rhtml +++ /dev/null @@ -1,35 +0,0 @@ -<% %> -

    Listing elections

    - - - -<% for election in @elections %> - - - - - -<% end %> -

    <%=h link_to election.name, :action => 'show', :id => election %>

    -

    Description:

    -
    <%=h election.description %>
    - -

    Election Information:

    -
      -
    • <%= election.voters.length %> registered voters
    • -
    • <%= "Not " unless election.anonymous == 1 %>Anonymous
    • -
    • Starts <%= election.startdate %>
    • -
    • Ends <%= election.enddate %>
    • -
    -
    -

    Candidates:

    - <% @election = election %><%= render :partial => 'candidate_list', :id => election.id %> -
    - <%= link_to 'Destroy', { :action => 'destroy', :id => election }, :confirm => 'Are you sure?' %>
    - -<%= 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 %> - -
    - -<%= link_to 'New election', :action => 'new' %> diff --git a/app/views/election/remind_voter.rhtml b/app/views/election/remind_voter.rhtml deleted file mode 100644 index 40d7a20..0000000 --- a/app/views/election/remind_voter.rhtml +++ /dev/null @@ -1 +0,0 @@ -The message has been sent, please check your inbox soon. \ No newline at end of file diff --git a/app/views/election/show.rhtml b/app/views/election/show.rhtml index 2a23168..3e63628 100644 --- a/app/views/election/show.rhtml +++ b/app/views/election/show.rhtml @@ -1,4 +1,7 @@ -

    Vote Information

    +
    + Election Overview + +
    <% if @election.active? %>
    Vote is in currently in progress. Return to @@ -8,8 +11,6 @@ :action => 'results', :id => @election.id %>.
    <% end %> -

    Overview

    -

    Summary

    @@ -32,8 +33,11 @@

    <%= link_to "Edit overview.", :action => 'edit', :id => @election.id %>

    <% end %> -

    Candidates

    -<% %> +
    + Candidates + +
    + <% unless @election.candidates.empty? %> <%= render :partial => 'candidate_list' %> <% unless @election.active %> @@ -44,7 +48,10 @@ <% end %> -

    Voters

    +
    + Voters + +
    <% unless @election.voters.empty? %> <%= render :partial => 'voter_list' %> @@ -54,7 +61,11 @@ <% end %> <% unless @election.active? %> -

    Start Election

    + +
    + Start Election + +
    <% if @election.start_blockers.length > 0 %>

    Your vote cannot be started for the following reasons:

    diff --git a/app/views/front/_basic_login.rhtml b/app/views/front/_basic_login.rhtml index 16ddc8d..bd03a9d 100644 --- a/app/views/front/_basic_login.rhtml +++ b/app/views/front/_basic_login.rhtml @@ -8,5 +8,5 @@

    <%= submit_tag 'Log in' %>

    <% end %> -

    <%= link_to 'Lost or forgot your password?', :controller => 'account', :action => 'forgot_password' %>

    + diff --git a/app/views/front/_user_summary.rhtml b/app/views/front/_user_summary.rhtml index 3b541c8..ce65bba 100644 --- a/app/views/front/_user_summary.rhtml +++ b/app/views/front/_user_summary.rhtml @@ -9,3 +9,5 @@ <% end %> +

    <%= link_to "Create a new election", :controller => 'election', :action => 'new' %>.

    + diff --git a/app/views/front/index.rhtml b/app/views/front/index.rhtml index 54e4688..afdf35d 100644 --- a/app/views/front/index.rhtml +++ b/app/views/front/index.rhtml @@ -5,12 +5,12 @@

    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.

    - <% form_tag(:controller => 'voter', :action => 'index') do %> + <% form_tag(:controller => 'voter', :action => 'login') do %>

    <%= text_field :vote, :password %>

    <%= submit_tag "Log In" %>

    <% end %> -

    <%= link_to 'Lost or forgot your token?', :controller => 'voter', :action => 'forgot_password' %>

    +

    <%= link_to 'Lost or forgot your token?', :controller => 'voter', :action => 'reminder' %>

    SMS Interface

    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' %>.

    @@ -29,9 +29,14 @@ existing vote. You can log in below.

    <%= render :partial => 'basic_login' %> + +

    Full elections creation is not yet public. Contact us for access.

    + + <% end %> -

    Full elections creation is not yet public. <%= link_to("Contact us", - "mailto:team@selectricity.org") %> for access.

    +
    diff --git a/app/views/quickvote/create.rhtml b/app/views/quickvote/create.rhtml index c05424e..eecb4fb 100644 --- a/app/views/quickvote/create.rhtml +++ b/app/views/quickvote/create.rhtml @@ -35,6 +35,10 @@

    +

    <%= quickform.select('election_method', %w(ssd condorcet plurality approval borda) ) %>

    diff --git a/app/views/quickvote/index.rhtml b/app/views/quickvote/index.rhtml index d1018cf..ccc7ec6 100644 --- a/app/views/quickvote/index.rhtml +++ b/app/views/quickvote/index.rhtml @@ -1,6 +1,6 @@
    - Quickvote - <%=h @voter.election.description.capitalize %> + Quickvote + <%=h @voter.election.description.capitalize %>
    diff --git a/app/views/voter/_sortable_vote.rhtml b/app/views/voter/_sortable_vote.rhtml index 512a4ee..2452476 100644 --- a/app/views/voter/_sortable_vote.rhtml +++ b/app/views/voter/_sortable_vote.rhtml @@ -1,3 +1,8 @@ +

    Your Vote

    + +

    Please vote by dragging items in the list below into your preferred +order.

    +
      <% for ranking in @voter.vote.rankings %> @@ -12,3 +17,7 @@ <%= sortable_element 'rankings-list', :url => { :action => "sort_candidates", :id => @voter.vote.id }, :complete => visual_effect(:highlight, 'rankings-list') %> + +
      +<%= button_to "Confirm Vote", :action => 'review', :id => @voter.password %> +
      diff --git a/app/views/voter/forgot_password.rhtml b/app/views/voter/forgot_password.rhtml deleted file mode 100644 index 43d1d03..0000000 --- a/app/views/voter/forgot_password.rhtml +++ /dev/null @@ -1,12 +0,0 @@ -

      Deleted your email? Lost your password?

      -

      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!

      - -<% form_tag :controller => 'election', :action => 'remind_voter' do %> - -

      Email - <%= text_field_tag :email %>

      - - <%= submit_tag "Submit" %> -<% end -%> diff --git a/app/views/voter/full_vote.rhtml b/app/views/voter/full_vote.rhtml index cfc20e3..9d4f1d0 100644 --- a/app/views/voter/full_vote.rhtml +++ b/app/views/voter/full_vote.rhtml @@ -1,10 +1,41 @@ -<% %> +
      + Vote + <%= @voter.election.name %> +
      -

      Election: <%= @voter.election.name %>

      -

      Voter: <%= @voter.email %>

      Description:

      -
      <%= @voter.election.description %>
      +

      <%= @voter.election.description %>

      -<%= render :partial => 'sortable_vote' %> +
      + Current Voter + +
      -<%= button_to "Submit Vote", :action => 'review', :id => @voter.password %> +

      <%= @voter.email %>

      + +
      + Instructions + +
      + +

      Drag and drop the items on list in the left column +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.

      + +
      + Candidate List + +
      + +<% @voter.election.candidates.each do |candidate| %> + <% @current_candidate = candidate %> + +
      +

      <%=h @current_candidate.name -%>

      +
      + <%=h (@current_candidate.description) %> +
      +
      + <% end %> + diff --git a/app/views/voter/index.rhtml b/app/views/voter/index.rhtml index 5c2ea27..e92081d 100644 --- a/app/views/voter/index.rhtml +++ b/app/views/voter/index.rhtml @@ -1,8 +1,11 @@ -<% %> +
      + Voter Login + +

      Please enter your password/token to log in and vote:

      -<% form_tag(:action => 'index') do %> +<% form_tag(:action => 'login') do %> <%= text_field :vote, :password %> <%= submit_tag "Log In" %> <% end %> diff --git a/app/views/voter/reminder.rhtml b/app/views/voter/reminder.rhtml new file mode 100644 index 0000000..ad757e4 --- /dev/null +++ b/app/views/voter/reminder.rhtml @@ -0,0 +1,16 @@ +
      + Password Reminder + +
      + +

      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.

      + +<% form_tag :action => 'reminder' do %> + +

      Email + <%= text_field_tag :email %>

      + + <%= submit_tag "Submit" %> +<% end -%> diff --git a/app/views/voter/reminder_sent.rhtml b/app/views/voter/reminder_sent.rhtml new file mode 100644 index 0000000..4bb88e8 --- /dev/null +++ b/app/views/voter/reminder_sent.rhtml @@ -0,0 +1,6 @@ +
      + Reminder Sent + +
      + +

      The message has been sent, please check your inbox.

      diff --git a/app/views/voter/review.rhtml b/app/views/voter/review.rhtml index b8b9089..d9ecf19 100644 --- a/app/views/voter/review.rhtml +++ b/app/views/voter/review.rhtml @@ -1,7 +1,11 @@ -<% %> +
      + Review + <%= @voter.election.name %> +
      -<% %> -

      Please review your vote carefully before confirming it.

      +

      Your vote will not be recorded until you confirm it on this +page. Please review your vote carefully before clicking +confirm.

      You have ranked the candidates in the following order (from most preferred to least preferred:

      @@ -12,21 +16,23 @@ preferred to least preferred:

      <% end %>
    - - - - - +
    + Confirm/Discard + +
    - - - - +

    Please select from one of the following pages.

    - - - - +
    +

    <%= button_to 'Confirm This Vote', :action => 'confirm', :id => @voter.password %>

    + +

    If you choose, you will be able to go back
    and change it up until + the end of hte voting period.

    -
    <%= button_to 'Confirm', :action => 'confirm', :id => @voter.password %>Confirm this vote now. You will be able to go back and - change it.
    <%= button_to 'Change', :action => 'index', :id => @voter.password %>Go back to the voting page and vote again.
    <%= button_to 'Discard', :action => 'discard' %>Discard this tentative vote and log out.
    +

    <%= button_to 'Discard This Vote', votepassword_url( + :action => 'index', :urlpassword => @voter.password) %>

    + +

    You will be returned to the voting page to vote
    again, if you choose.

    + + +
    diff --git a/app/views/voter/thanks.rhtml b/app/views/voter/thanks.rhtml index ab8992c..883b4fa 100644 --- a/app/views/voter/thanks.rhtml +++ b/app/views/voter/thanks.rhtml @@ -1,9 +1,15 @@ -<% %> +
    + Vote Recorded + +
    -

    Your vote has been recorded.

    +

    Your vote has been recorded for the <%= @voter.election.name +%>.

    Your unique token for this vote is: <%= @voter.vote.token %>

    -

    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.

    +

    Please record this token for your records and keep it secret. This is +not 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.

    diff --git a/app/views/voter_notify/reminder.rhtml b/app/views/voter_notify/reminder.rhtml index 1373bc2..0a90746 100644 --- a/app/views/voter_notify/reminder.rhtml +++ b/app/views/voter_notify/reminder.rhtml @@ -1,16 +1,18 @@ 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! diff --git a/app/views/voter_notify/votestart.rhtml b/app/views/voter_notify/votestart.rhtml index f9dbfc6..e2c480f 100644 --- a/app/views/voter_notify/votestart.rhtml +++ b/app/views/voter_notify/votestart.rhtml @@ -11,7 +11,7 @@ need to use the following token to log in to Selectricity: <%= @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: @@ -21,7 +21,7 @@ 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! diff --git a/config/environment.rb b/config/environment.rb index 3e5f1c6..32d313b 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -59,7 +59,7 @@ end # Include your application configuration below -MAIL_CONFIG = { :from => 'Selectricity '} +MAIL_CONFIG = { :from => 'Selectricity '} require 'uniq_token' require 'randarray' diff --git a/config/routes.rb b/config/routes.rb index f763da9..e2f458d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -15,6 +15,13 @@ ActionController::Routing::Routes.draw do |map| 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', diff --git a/public/stylesheets/main.css b/public/stylesheets/main.css index 50863c1..97c6848 100644 --- a/public/stylesheets/main.css +++ b/public/stylesheets/main.css @@ -246,20 +246,6 @@ blockquote { 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; @@ -464,3 +450,34 @@ div.photo img { 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; +} diff --git a/public/stylesheets/quickvote.css b/public/stylesheets/quickvote.css index b18da44..5b7c8b4 100644 --- a/public/stylesheets/quickvote.css +++ b/public/stylesheets/quickvote.css @@ -9,3 +9,18 @@ a { #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; +} + diff --git a/public/stylesheets/voter.css b/public/stylesheets/voter.css index 98b94dc..5a38cae 100644 --- a/public/stylesheets/voter.css +++ b/public/stylesheets/voter.css @@ -10,3 +10,17 @@ a { 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; +} +