| @@ -4,3 +4,4 @@ | |||||
| .bundle/config | .bundle/config | ||||
| /.ruby-gemset | /.ruby-gemset | ||||
| /tmp/ | /tmp/ | ||||
| _* | |||||
| @@ -0,0 +1,292 @@ | |||||
| #!/usr/bin/env ruby | |||||
| # Generate a static site | |||||
| require 'logger' | |||||
| require 'haml' | |||||
| require_relative '../models' | |||||
| OUTPUT_DIR = '_site' | |||||
| VIEWS_DIR = File.join('..', 'views') | |||||
| LAYOUT_FN = File.join(VIEWS_DIR, 'layout.haml') | |||||
| @log = Logger.new($stdout) | |||||
| @log.level = Logger::INFO | |||||
| @log.info "Build starts." | |||||
| @log.info "Output directory is: #{OUTPUT_DIR}" | |||||
| class String | |||||
| def pluralize(num) | |||||
| if num == 1 | |||||
| return self | |||||
| end | |||||
| case self[-1] | |||||
| when 'y' | |||||
| self[0..-2] + 'ies' | |||||
| when 's' | |||||
| self + "es" | |||||
| else | |||||
| self + "s" | |||||
| end | |||||
| end | |||||
| end | |||||
| def commify(num) | |||||
| num.to_s.reverse.gsub(/(\d\d\d)(?=\d)(?!\d*\.)/,'\1,').reverse | |||||
| end | |||||
| # From http://snippets.dzone.com/posts/show/593 | |||||
| def to_ordinal(num) | |||||
| num = num.to_i | |||||
| if (10...20) === num | |||||
| "#{num}th" | |||||
| else | |||||
| g = %w{ th st nd rd th th th th th th } | |||||
| a = num.to_s | |||||
| c = a[-1..-1].to_i | |||||
| a + g[c] | |||||
| end | |||||
| end | |||||
| def format_percent(num) | |||||
| sprintf("%.0f%%", num) | |||||
| end | |||||
| def short_date(d) | |||||
| d.strftime("%e %b %Y") | |||||
| end | |||||
| def long_date(d) | |||||
| d.strftime("%e %B %Y") | |||||
| end | |||||
| # Exception for Labour/Co-operative candidacies | |||||
| def party_name(labcoop, party_name) | |||||
| labcoop ? "Labour and Co-operative Party" : party_name | |||||
| end | |||||
| def write_page(path_items, template, locals = {}) | |||||
| dir = File.join(path_items) | |||||
| FileUtils.mkdir_p(dir) | |||||
| @log.debug dir | |||||
| fn = File.join(dir, 'index.html') | |||||
| # https://stackoverflow.com/questions/6125265/using-layouts-in-haml-files-independently-of-rails | |||||
| html = Haml::Engine.new(File.read(LAYOUT_FN)).render do | |||||
| Haml::Engine.new(File.read(File.join(VIEWS_DIR, "#{template}.haml"))).render(Object.new, locals) | |||||
| end | |||||
| File.write(fn, html) | |||||
| @log.info fn | |||||
| # TODO - add page to sitemap.xml or sitemap.txt | |||||
| # https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190 | |||||
| end | |||||
| test_dir = File.join(Dir.pwd, OUTPUT_DIR) | |||||
| # FIXME - clear output directory at the start of every run | |||||
| # FileUtils.rm_rf(test_dir) | |||||
| Dir.mkdir(test_dir) unless File.directory?(test_dir) | |||||
| Dir.chdir(test_dir) | |||||
| # Copy `public` dir to output dir | |||||
| FileUtils.copy_entry(File.join('..', 'public'), '.') | |||||
| # Home page | |||||
| locals = { | |||||
| future_elections: Election.future, | |||||
| past_elections: Election.past | |||||
| } | |||||
| write_page('.', 'index', locals) | |||||
| # Election pages | |||||
| Election.each do |e| | |||||
| locals = { | |||||
| body: Body.first(:slug => e.body.slug), | |||||
| election: Election.first(:body => e.body, :d => e.d), | |||||
| elections_for_this_body: Election.all(:body => e.body, :order => [:d]), | |||||
| total_seats: Candidacy.sum(:seats, :election => e), | |||||
| total_votes: Candidacy.sum(:votes, :election => e) | |||||
| } | |||||
| # There's got to be a better way to do this, either with SQL or Datamapper | |||||
| locals['total_districts'] = repository(:default).adapter.select(" | |||||
| SELECT district_id | |||||
| FROM candidacies | |||||
| WHERE election_id = ? | |||||
| GROUP BY district_id | |||||
| ORDER BY district_id | |||||
| ", e.id).count | |||||
| locals['results_by_party'] = repository(:default).adapter.select(" | |||||
| SELECT | |||||
| p.colour, | |||||
| p.name, | |||||
| SUM(c.votes) AS votez, | |||||
| SUM(c.seats) AS seatz, | |||||
| COUNT(*) AS cands | |||||
| FROM candidacies c | |||||
| LEFT JOIN parties p ON p.id = c.party_id | |||||
| WHERE c.election_id = ? | |||||
| GROUP BY c.party_id, p.colour, p.name | |||||
| ORDER BY seatz DESC, votez DESC | |||||
| ", e.id) | |||||
| write_page(['bodies', e.body.slug, 'elections', e.d.to_s], 'electionsummary', locals) | |||||
| # District results for this election (resultsdistrict) | |||||
| # Loop through all districts in this election | |||||
| e.candidacies.districts.each do |d| | |||||
| total_seats = Candidacy.sum(:seats, :district => d, :election => e) | |||||
| total_votes = Candidacy.sum(:votes, :district => d, :election => e) | |||||
| poll = Poll.get(d.id, e.id) | |||||
| locals = { | |||||
| district: d, | |||||
| body: d.body, | |||||
| election: e, | |||||
| candidacies: Candidacy.all(:district => d, :election => e, :order => [:position]), | |||||
| total_votes: total_votes, | |||||
| total_candidates: Candidacy.count(:district => d, :election => e), | |||||
| total_seats: total_seats, | |||||
| districts_in_this_election: e.candidacies.districts, | |||||
| poll: poll | |||||
| } | |||||
| locals['share_message'] = nil | |||||
| if total_seats == 1 | |||||
| locals['share_denominator'] = total_votes | |||||
| elsif poll && poll.valid_ballot_papers | |||||
| locals['share_denominator'] = poll.valid_ballot_papers | |||||
| else | |||||
| locals['share_denominator'] = total_votes / total_seats | |||||
| locals['share_message'] = "The vote share percentages have been estimated as we don't have data for the number of valid ballot papers in this poll." | |||||
| end | |||||
| # Postgres: All the columns selected when using GROUP BY must either be aggregate functions or appear in the GROUP BY clause | |||||
| locals['results_by_party'] = repository(:default).adapter.select(" | |||||
| SELECT | |||||
| p.name AS party_name, | |||||
| p.colour AS party_colour, | |||||
| COUNT(c.id) AS num_candidates, | |||||
| SUM(c.seats) AS num_seats, | |||||
| SUM(c.votes) AS total_votes | |||||
| FROM candidacies c | |||||
| LEFT JOIN parties p | |||||
| ON c.party_id = p.id | |||||
| WHERE c.district_id = ? | |||||
| AND c.election_id = ? | |||||
| GROUP BY p.name, p.colour | |||||
| ORDER BY total_votes DESC | |||||
| ", d.id, e.id) | |||||
| write_page(['bodies', e.body.slug, 'elections', e.d.to_s, e.body.districts_name, d.slug], 'resultsdistrict', locals) | |||||
| end | |||||
| end | |||||
| # Candidate index | |||||
| locals = { candidates: Candidate.all(:order => [ :surname, :forenames ]) } | |||||
| write_page('candidates', 'candidates', locals) | |||||
| # Candidate pages | |||||
| # FIXME: What do we do about deleted candidates/redirects? | |||||
| Candidate.each do |c| | |||||
| locals = { | |||||
| candidate: c | |||||
| } | |||||
| locals['candidacies'] = repository(:default).adapter.select(" | |||||
| SELECT | |||||
| e.d, | |||||
| c.*, | |||||
| p.name AS party_name, | |||||
| p.colour AS party_colour, | |||||
| b.name AS body_name, | |||||
| b.slug AS body_slug, | |||||
| b.districts_name AS districts_name, | |||||
| d.name AS district_name, | |||||
| d.slug AS district_slug | |||||
| FROM candidacies c | |||||
| INNER JOIN elections e | |||||
| ON c.election_id = e.id | |||||
| INNER JOIN parties p | |||||
| ON c.party_id = p.id | |||||
| INNER JOIN bodies b | |||||
| ON e.body_id = b.id | |||||
| INNER JOIN districts d | |||||
| ON c.district_id = d.id | |||||
| WHERE c.candidate_id = ? | |||||
| ORDER BY d | |||||
| ", c.id) | |||||
| write_page(['candidates', c.id.to_s], 'candidate', locals) | |||||
| end | |||||
| # Bodies index | |||||
| dir = 'bodies' | |||||
| FileUtils.mkdir_p(dir) | |||||
| @log.debug dir | |||||
| fn = File.join(dir, 'index.html') | |||||
| FileUtils.touch(fn) # empty file | |||||
| @log.info fn | |||||
| # Body detail pages | |||||
| Body.each do |b| | |||||
| locals = { | |||||
| body: b, | |||||
| districts: District.all(:body => b, :order => [:name]) | |||||
| } | |||||
| locals['elections'] = repository(:default).adapter.select(" | |||||
| SELECT | |||||
| e.id, | |||||
| e.kind, | |||||
| e.d, | |||||
| SUM(p.ballot_papers_issued)::float / SUM(p.electorate) * 100 AS turnout_percent | |||||
| FROM elections e | |||||
| LEFT JOIN polls p | |||||
| ON e.id = p.election_id | |||||
| WHERE e.body_id = ? | |||||
| GROUP BY p.election_id, e.id | |||||
| ORDER BY e.d DESC | |||||
| ", b.id) | |||||
| write_page(['bodies', b.slug], 'body', locals) | |||||
| # Districts for this body | |||||
| b.districts.each do |d| | |||||
| locals = { | |||||
| district: d, | |||||
| body: b | |||||
| } | |||||
| write_page(['bodies', b.slug, b.districts_name, d.slug], 'district', locals) | |||||
| end | |||||
| end | |||||
| write_page('about', 'about') | |||||
| write_page('guides', 'guides') | |||||
| write_page(%w(guides how-the-parliament-election-works), 'parliament') | |||||
| write_page(%w(guides how-the-council-election-works), 'election') | |||||
| @log.info "Build complete." | |||||
| @@ -1,4 +1,4 @@ | |||||
| %h1= @page_title = @body.name | |||||
| %h1= page_title = body.name | |||||
| %h2 Elections | %h2 Elections | ||||
| @@ -8,10 +8,10 @@ | |||||
| %th | %th | ||||
| %th | %th | ||||
| %th turnout | %th turnout | ||||
| - @elections.each do |election| | |||||
| - elections.each do |election| | |||||
| %tr | %tr | ||||
| %td | %td | ||||
| %a{ :href => "/bodies/#{@body.slug}/elections/#{election.d}" }< | |||||
| %a{ :href => "/bodies/#{body.slug}/elections/#{election.d}" }< | |||||
| = short_date(election.d) | = short_date(election.d) | ||||
| %td | %td | ||||
| = election.kind | = election.kind | ||||
| @@ -20,9 +20,9 @@ | |||||
| = format_percent(election.turnout_percent) | = format_percent(election.turnout_percent) | ||||
| %h2 | %h2 | ||||
| = @body.districts_name.capitalize | |||||
| = body.districts_name.capitalize | |||||
| - @districts.each do |district| | |||||
| - districts.each do |district| | |||||
| %p | %p | ||||
| %a{ :href => "/bodies/#{@body.slug}/#{@body.districts_name}/#{district.slug}" } | |||||
| %a{ :href => "/bodies/#{body.slug}/#{body.districts_name}/#{district.slug}" } | |||||
| = district.name | = district.name | ||||
| @@ -2,7 +2,7 @@ | |||||
| %a{ :href => "/candidates" } | %a{ :href => "/candidates" } | ||||
| « All candidates | « All candidates | ||||
| %h1= @page_title = @candidate.name | |||||
| %h1= page_title = candidate.name | |||||
| %h2 Elections contested | %h2 Elections contested | ||||
| @@ -17,7 +17,7 @@ | |||||
| %th position | %th position | ||||
| %th | %th | ||||
| - @candidacies.each do |ccy| | |||||
| - candidacies.each do |ccy| | |||||
| %tr | %tr | ||||
| %td{ :style => "background-color: #{ccy['party_colour']}" } | %td{ :style => "background-color: #{ccy['party_colour']}" } | ||||
| %td | %td | ||||
| @@ -46,6 +46,6 @@ | |||||
| %p | %p | ||||
| Some candidates have more than one profile page due to them using slightly different names in different elections. See the full | Some candidates have more than one profile page due to them using slightly different names in different elections. See the full | ||||
| %a{ :href => "/candidates/##{@candidate.surname[0]}" }< | |||||
| %a{ :href => "/candidates/##{candidate.surname[0]}" }< | |||||
| candidates list | candidates list | ||||
| for details. | for details. | ||||
| @@ -1,21 +1,21 @@ | |||||
| %h1= @page_title = "Candidates" | |||||
| %h1= page_title = "Candidates" | |||||
| %nav.letter_index | %nav.letter_index | ||||
| - ("A".."Z").each do |letter| | - ("A".."Z").each do |letter| | ||||
| %a{ :href => "##{letter}" }< | %a{ :href => "##{letter}" }< | ||||
| = letter | = letter | ||||
| - @first_letter = '' | |||||
| - first_letter = '' | |||||
| %table | %table | ||||
| - @candidates.each do |c| | |||||
| - if c.surname[0] != @first_letter | |||||
| - @first_letter = c.surname[0] | |||||
| - candidates.each do |c| | |||||
| - if c.surname[0] != first_letter | |||||
| - first_letter = c.surname[0] | |||||
| %tr.noborder | %tr.noborder | ||||
| %td | %td | ||||
| %td | %td | ||||
| %tr.noborder{ :name => @first_letter, :id => @first_letter } | |||||
| %td.strong{ :style => "font-size: 300%;" }= @first_letter.upcase | |||||
| %tr.noborder{ :name => first_letter, :id => first_letter } | |||||
| %td.strong{ :style => "font-size: 300%;" }= first_letter.upcase | |||||
| %td | %td | ||||
| %tr | %tr | ||||
| %td | %td | ||||
| @@ -1,26 +1,26 @@ | |||||
| - @page_title = "#{@district.name} #{@district.body.district_name}, #{@district.body.name}" | |||||
| - page_title = "#{district.name} #{district.body.district_name}, #{district.body.name}" | |||||
| %nav | %nav | ||||
| %a{ :href => "/bodies/#{@district.body.slug}" } | |||||
| %a{ :href => "/bodies/#{district.body.slug}" } | |||||
| « | « | ||||
| = @district.body.name | |||||
| = district.body.name | |||||
| %h1= "#{@district.name} #{@district.body.district_name}" | |||||
| %h1= "#{district.name} #{district.body.district_name}" | |||||
| -# | -# | ||||
| - @election = Election.get(9) # FIXME magic number | |||||
| - election = Election.get(9) # FIXME magic number | |||||
| %h2 | %h2 | ||||
| = @district.name | |||||
| = district.name | |||||
| ward candidates for the | ward candidates for the | ||||
| %a{ :href => "/bodies/#{@election.body.slug}/elections/#{@election.d}"} | |||||
| = @election.body.name | |||||
| %a{ :href => "/bodies/#{election.body.slug}/elections/#{election.d}"} | |||||
| = election.body.name | |||||
| election on | election on | ||||
| = long_date(@election.d) | |||||
| = long_date(election.d) | |||||
| %table | %table | ||||
| - Candidacy.all(:election => @election, :district => @district, :order => [:party_id]).each do |c| | |||||
| - campaign = Campaign.first(:party => c.party, :election => @election) | |||||
| - Candidacy.all(:election => election, :district => district, :order => [:party_id]).each do |c| | |||||
| - campaign = Campaign.first(:party => c.party, :election => election) | |||||
| %tr.vcard | %tr.vcard | ||||
| %td{ :style => "background-color: #{c.party.colour}" } | %td{ :style => "background-color: #{c.party.colour}" } | ||||
| %td.candidate_name.fn | %td.candidate_name.fn | ||||
| @@ -42,12 +42,12 @@ | |||||
| %h2 Candidates elected | %h2 Candidates elected | ||||
| - Election.all(:body => @district.body, :order => [:d.desc]).each do |election| | |||||
| - ccys = Candidacy.all(:election_id => election.id, :district_id => @district.id, :seats => 1, :order => [:votes.desc]) | |||||
| - Election.all(:body => district.body, :order => [:d.desc]).each do |election| | |||||
| - ccys = Candidacy.all(:election_id => election.id, :district_id => district.id, :seats => 1, :order => [:votes.desc]) | |||||
| - unless ccys == [] | - unless ccys == [] | ||||
| %h3 | %h3 | ||||
| %a{ :href => "/bodies/#{@district.body.slug}/elections/#{election.d}/#{election.body.districts_name}/#{@district.slug}"} | |||||
| %a{ :href => "/bodies/#{district.body.slug}/elections/#{election.d}/#{election.body.districts_name}/#{district.slug}"} | |||||
| = long_date election.d | = long_date election.d | ||||
| = election.kind | = election.kind | ||||
| @@ -19,5 +19,3 @@ | |||||
| %p If a political party gets 28 or more councillors they get to run Sutton Council and decide its policies and services. | %p If a political party gets 28 or more councillors they get to run Sutton Council and decide its policies and services. | ||||
| %p If no party gets 28 councillors the parties have to agree among themselves who will run the council. This is called “no overall control”. | %p If no party gets 28 councillors the parties have to agree among themselves who will run the council. This is called “no overall control”. | ||||
| = haml :register, :layout => false | |||||
| @@ -1,66 +1,66 @@ | |||||
| - @page_title = "#{@election.body.name} #{@election.kind} #{long_date(@election.d)}" | |||||
| - page_title = "#{election.body.name} #{election.kind} #{long_date(election.d)}" | |||||
| %nav | %nav | ||||
| %a{ :href => "/bodies/#{@election.body.slug}" } | |||||
| %a{ :href => "/bodies/#{election.body.slug}" } | |||||
| « | « | ||||
| = @election.body.name | |||||
| = election.body.name | |||||
| - if @elections_for_this_body.size > 1 | |||||
| - if elections_for_this_body.size > 1 | |||||
| %p | %p | ||||
| - @election_index = @elections_for_this_body.index(@election) | |||||
| - election_index = elections_for_this_body.index(election) | |||||
| - unless @election_index == 0 | |||||
| - @previous_election = @elections_for_this_body[@election_index - 1] | |||||
| %a{ :href => "/bodies/#{@election.body.slug}/elections/#{@previous_election.d}", :title => "#{@previous_election.kind} #{short_date(@previous_election.d)}" } | |||||
| - unless election_index == 0 | |||||
| - previous_election = elections_for_this_body[election_index - 1] | |||||
| %a{ :href => "/bodies/#{election.body.slug}/elections/#{previous_election.d}", :title => "#{previous_election.kind} #{short_date(previous_election.d)}" } | |||||
| « | « | ||||
| Previous | Previous | ||||
| = @election.body.name | |||||
| = election.body.name | |||||
| election | election | ||||
| | | ||||
| - unless @election_index == @elections_for_this_body.size - 1 | |||||
| - @next_election = @elections_for_this_body[@election_index + 1] | |||||
| %a{ :href => "/bodies/#{@election.body.slug}/elections/#{@next_election.d}", :title => "#{@next_election.kind} #{short_date(@next_election.d)}" } | |||||
| - unless election_index == elections_for_this_body.size - 1 | |||||
| - next_election = elections_for_this_body[election_index + 1] | |||||
| %a{ :href => "/bodies/#{election.body.slug}/elections/#{next_election.d}", :title => "#{next_election.kind} #{short_date(next_election.d)}" } | |||||
| Next | Next | ||||
| = @election.body.name | |||||
| = election.body.name | |||||
| election | election | ||||
| » | » | ||||
| %h1 | %h1 | ||||
| = @election.body.name | |||||
| = @election.kind | |||||
| = election.body.name | |||||
| = election.kind | |||||
| %br | %br | ||||
| = long_date(@election.d) | |||||
| = long_date(election.d) | |||||
| -# Does this election have any recorded votes, i.e. has it been held? | -# Does this election have any recorded votes, i.e. has it been held? | ||||
| - @election_held = Candidacy.sum(:votes, :election => @election) | |||||
| - election_held = Candidacy.sum(:votes, :election => election) | |||||
| - unless @election_held | |||||
| - unless election_held | |||||
| .warning | .warning | ||||
| We don't have the results for this election yet. | We don't have the results for this election yet. | ||||
| %p= @polling_station | |||||
| -# %p= polling_station | |||||
| %p= @election.reason | |||||
| %p= election.reason | |||||
| %p | %p | ||||
| = @election.candidacies.count | |||||
| = "candidate".pluralize(@election.candidacies.count) | |||||
| - if @election_held | |||||
| = election.candidacies.count | |||||
| = "candidate".pluralize(election.candidacies.count) | |||||
| - if election_held | |||||
| contested | contested | ||||
| - else | - else | ||||
| will be contesting | will be contesting | ||||
| -# We can't calculate the number of seats being contested if the election hasn't been held | -# We can't calculate the number of seats being contested if the election hasn't been held | ||||
| - if @election_held | |||||
| = @total_seats | |||||
| = "seat".pluralize(@total_seats) | |||||
| - if election_held | |||||
| = total_seats | |||||
| = "seat".pluralize(total_seats) | |||||
| in | in | ||||
| = @total_districts | |||||
| = @election.body.district_name.pluralize(@total_districts) | |||||
| = total_districts | |||||
| = election.body.district_name.pluralize(total_districts) | |||||
| in Sutton. | in Sutton. | ||||
| - if @election_held | |||||
| - if election_held | |||||
| %table | %table | ||||
| %tr.header | %tr.header | ||||
| @@ -69,69 +69,69 @@ | |||||
| %th.highlight seats won | %th.highlight seats won | ||||
| %th votes | %th votes | ||||
| %th % votes | %th % votes | ||||
| - if @total_seats > 1 | |||||
| - if total_seats > 1 | |||||
| %th % seats | %th % seats | ||||
| %th votes per seat | %th votes per seat | ||||
| %th candidates | %th candidates | ||||
| %th votes per candidate | %th votes per candidate | ||||
| -# | -# | ||||
| %th relative popularity | %th relative popularity | ||||
| - @max_votes_per_candidate = @results_by_party.first.votez.to_f / @results_by_party.first.cands.to_f # We really need to scan the array for the max value | |||||
| - @results_by_party.each do |row| | |||||
| - max_votes_per_candidate = results_by_party.first.votez.to_f / results_by_party.first.cands.to_f # We really need to scan the array for the max value | |||||
| - results_by_party.each do |row| | |||||
| %tr | %tr | ||||
| %td{ :style => "background-color: #{row.colour}" } | %td{ :style => "background-color: #{row.colour}" } | ||||
| %td.data_party= row.name | %td.data_party= row.name | ||||
| %td.data_seats.right.highlight= row.seatz | %td.data_seats.right.highlight= row.seatz | ||||
| %td.data_votes.right= commify(row.votez) | %td.data_votes.right= commify(row.votez) | ||||
| - if @election_held | |||||
| %td.right= format_percent(row.votez.to_f / @total_votes * 100) | |||||
| - if @total_seats > 1 | |||||
| %td.right= format_percent(row.seatz.to_f / @total_seats * 100) | |||||
| - if election_held | |||||
| %td.right= format_percent(row.votez.to_f / total_votes * 100) | |||||
| - if total_seats > 1 | |||||
| %td.right= format_percent(row.seatz.to_f / total_seats * 100) | |||||
| %td.data_votes_per_seat.right | %td.data_votes_per_seat.right | ||||
| - if row.seatz > 0 | - if row.seatz > 0 | ||||
| = commify(row.votez / row.seatz) | = commify(row.votez / row.seatz) | ||||
| - else | - else | ||||
| — | — | ||||
| %td.data_candidates.right= row.cands | %td.data_candidates.right= row.cands | ||||
| - if @election_held && @total_seats > 1 | |||||
| - if election_held && total_seats > 1 | |||||
| %td.right= commify(row.votez / row.cands) | %td.right= commify(row.votez / row.cands) | ||||
| -# | -# | ||||
| %td.right= format_percent( ( row.votez.to_f / row.cands.to_f ) / @max_votes_per_candidate * 100) | |||||
| %td.right= format_percent( ( row.votez.to_f / row.cands.to_f ) / max_votes_per_candidate * 100) | |||||
| %tr.footer | %tr.footer | ||||
| %td | %td | ||||
| %td | %td | ||||
| %td.right.highlight= @total_seats | |||||
| %td.right= commify(@total_votes) | |||||
| %td.right.highlight= total_seats | |||||
| %td.right= commify(total_votes) | |||||
| %td | %td | ||||
| - if @total_seats > 1 | |||||
| - if total_seats > 1 | |||||
| %td | %td | ||||
| %td | %td | ||||
| %td.right= commify(@election.candidacies.count) | |||||
| %td.right= commify(election.candidacies.count) | |||||
| %td | %td | ||||
| - if @election.ballot_papers_issued | |||||
| - if election.ballot_papers_issued | |||||
| %table | %table | ||||
| %tr | %tr | ||||
| %td Electorate | %td Electorate | ||||
| %td.right= commify(@election.electorate) | |||||
| %td.right= commify(election.electorate) | |||||
| %tr | %tr | ||||
| %td Ballot papers issued | %td Ballot papers issued | ||||
| %td.right= commify(@election.ballot_papers_issued) | |||||
| %td.right= commify(election.ballot_papers_issued) | |||||
| %tr | %tr | ||||
| %td Turnout | %td Turnout | ||||
| %td.right= sprintf("%.0f%%", @election.ballot_papers_issued / @election.electorate.to_f * 100) | |||||
| %td.right= sprintf("%.0f%%", election.ballot_papers_issued / election.electorate.to_f * 100) | |||||
| %h2 | %h2 | ||||
| = "Candidate".pluralize(@total_seats) | |||||
| = "Candidate".pluralize(total_seats) | |||||
| elected | elected | ||||
| %table | %table | ||||
| - @election.polls.each do |p| | |||||
| - election.polls.each do |p| | |||||
| %tr | %tr | ||||
| %td | %td | ||||
| %a{ :href => "/bodies/#{@election.body.slug}/elections/#{@election.d}/#{@election.body.districts_name}/#{p.district.slug}"} | |||||
| %a{ :href => "/bodies/#{election.body.slug}/elections/#{election.d}/#{election.body.districts_name}/#{p.district.slug}"} | |||||
| = p.district.name | = p.district.name | ||||
| - p.successful_candidacies.each do |sc| | - p.successful_candidacies.each do |sc| | ||||
| %td{ :style => "background-color: #{sc.party.colour};" } | %td{ :style => "background-color: #{sc.party.colour};" } | ||||
| @@ -1,16 +1,17 @@ | |||||
| #lookup | |||||
| %h2= @election_title | |||||
| %form{ :method => 'get', :action => '/' } | |||||
| %label{ :for => "postcode" } My postcode is | |||||
| %input{ :type => 'text', :name => 'postcode', :value => @default_pc, :size => 8, :maxlength => 8 } | |||||
| %input{ :type => 'submit', :value => "Find my results" } | |||||
| -# | |||||
| #lookup | |||||
| %h2= @election_title | |||||
| %form{ :method => 'get', :action => '/' } | |||||
| %label{ :for => "postcode" } My postcode is | |||||
| %input{ :type => 'text', :name => 'postcode', :value => @default_pc, :size => 8, :maxlength => 8 } | |||||
| %input{ :type => 'submit', :value => "Find my results" } | |||||
| - if @future_elections.size > 0 | |||||
| - if future_elections.size > 0 | |||||
| %h2 Upcoming elections | %h2 Upcoming elections | ||||
| %table | %table | ||||
| - @future_elections.each do |election| | |||||
| - future_elections.each do |election| | |||||
| %tr | %tr | ||||
| %td | %td | ||||
| %a{ :href => "/bodies/#{election.body.slug}/elections/#{election.d}" } | %a{ :href => "/bodies/#{election.body.slug}/elections/#{election.d}" } | ||||
| @@ -20,12 +21,12 @@ | |||||
| %td | %td | ||||
| = election.kind | = election.kind | ||||
| - if @past_elections.size > 0 | |||||
| - if past_elections.size > 0 | |||||
| %h2 Past elections | %h2 Past elections | ||||
| %table | %table | ||||
| - @past_elections.each do |election| | |||||
| - past_elections.each do |election| | |||||
| %tr | %tr | ||||
| %td | %td | ||||
| %a{ :href => "/bodies/#{election.body.slug}/elections/#{election.d}" } | %a{ :href => "/bodies/#{election.body.slug}/elections/#{election.d}" } | ||||
| @@ -2,7 +2,7 @@ | |||||
| %html | %html | ||||
| %head | %head | ||||
| %title= @page_title ? @page_title + " - Sutton Elections" : "Sutton Elections - Your guide to voting and election results in the London Borough of Sutton" | %title= @page_title ? @page_title + " - Sutton Elections" : "Sutton Elections - Your guide to voting and election results in the London Borough of Sutton" | ||||
| %link{ :rel => 'stylesheet', :type => 'text/css', :href => 'http://yui.yahooapis.com/pure/0.6.0/pure-min.css' } | |||||
| <link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous"> | |||||
| %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/style.css' } | %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/style.css' } | ||||
| %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/print.css', :media => 'print' } | %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/print.css', :media => 'print' } | ||||
| %meta{ :name => 'referrer', :content => 'no-referrer' } | %meta{ :name => 'referrer', :content => 'no-referrer' } | ||||
| @@ -28,10 +28,11 @@ | |||||
| %a{ :href => '/about' } About | %a{ :href => '/about' } About | ||||
| #main | #main | ||||
| - if flash[:notice] | |||||
| #notice | |||||
| %p= flash[:notice] | |||||
| - if flash[:error] | |||||
| #error | |||||
| %p= flash[:error] | |||||
| -# - if flash[:notice] | |||||
| -# #notice | |||||
| -# %p= flash[:notice] | |||||
| -# - if flash[:error] | |||||
| -# #error | |||||
| -# %p= flash[:error] | |||||
| = yield | = yield | ||||
| @@ -23,5 +23,3 @@ | |||||
| %p If no party gets 326 MPs the parties have to agree among themselves who will run the country. This is called a “hung parliament”. | %p If no party gets 326 MPs the parties have to agree among themselves who will run the country. This is called a “hung parliament”. | ||||
| %p Elections for parliament must be held at least once every five years. The prime minister can choose to have an election earlier if they wish. | %p Elections for parliament must be held at least once every five years. The prime minister can choose to have an election earlier if they wish. | ||||
| = haml :register, :layout => false | |||||
| @@ -1,35 +1,35 @@ | |||||
| - @page_title = "#{@district.name} #{@district.body.district_name} results, #{@body.name} election #{short_date(@election.d)}" | |||||
| - page_title = "#{district.name} #{district.body.district_name} results, #{body.name} election #{short_date(election.d)}" | |||||
| %nav | %nav | ||||
| - if @districts_in_this_election.size > 1 | |||||
| - @district_index = @districts_in_this_election.index(@district) | |||||
| - if districts_in_this_election.size > 1 | |||||
| - district_index = districts_in_this_election.index(district) | |||||
| - unless @district_index == 0 # Don't show the previous link if this is the first district for this election | |||||
| - @previous_district = @districts_in_this_election[@district_index - 1] | |||||
| %a{ :href => "/bodies/#{@election.body.slug}/elections/#{@election.d}/#{@election.body.districts_name}/#{@previous_district.slug}" } | |||||
| - unless district_index == 0 # Don't show the previous link if this is the first district for this election | |||||
| - previous_district = districts_in_this_election[district_index - 1] | |||||
| %a{ :href => "/bodies/#{election.body.slug}/elections/#{election.d}/#{election.body.districts_name}/#{previous_district.slug}" } | |||||
| « | « | ||||
| = @previous_district.name | |||||
| = previous_district.name | |||||
| | | ||||
| - unless @district_index == @districts_in_this_election.size - 1 # Don't show the next link if this is the last district for this election | |||||
| - @next_district = @districts_in_this_election[@district_index + 1] | |||||
| %a{ :href => "/bodies/#{@election.body.slug}/elections/#{@election.d}/#{@election.body.districts_name}/#{@next_district.slug}" } | |||||
| = @next_district.name | |||||
| - unless district_index == districts_in_this_election.size - 1 # Don't show the next link if this is the last district for this election | |||||
| - next_district = districts_in_this_election[district_index + 1] | |||||
| %a{ :href => "/bodies/#{election.body.slug}/elections/#{election.d}/#{election.body.districts_name}/#{next_district.slug}" } | |||||
| = next_district.name | |||||
| » | » | ||||
| %p | %p | ||||
| %a{ :href => "/bodies/#{@district.body.slug}/elections/#{@election.d}" } | |||||
| = @body.name | |||||
| = @election.kind | |||||
| = long_date(@election.d) | |||||
| %a{ :href => "/bodies/#{district.body.slug}/elections/#{election.d}" } | |||||
| = body.name | |||||
| = election.kind | |||||
| = long_date(election.d) | |||||
| %h1 | %h1 | ||||
| %a{ :href => "/bodies/#{@district.body.slug}/#{@district.body.district_name.pluralize(2)}/#{@district.slug}" } | |||||
| = @district.name + " " + @district.body.district_name | |||||
| %a{ :href => "/bodies/#{district.body.slug}/#{district.body.district_name.pluralize(2)}/#{district.slug}" } | |||||
| = district.name + " " + district.body.district_name | |||||
| - @election_held = Candidacy.sum(:votes, :election => @election, :district => @district) | |||||
| - election_held = Candidacy.sum(:votes, :election => election, :district => district) | |||||
| - unless @election_held | |||||
| - unless election_held | |||||
| .warning | .warning | ||||
| We don't have the results for this election yet. | We don't have the results for this election yet. | ||||
| @@ -44,7 +44,7 @@ | |||||
| %th | %th | ||||
| - count = 0 | - count = 0 | ||||
| - @candidacies.each do |candidacy| | |||||
| - candidacies.each do |candidacy| | |||||
| - count += 1 | - count += 1 | ||||
| %tr.vcard | %tr.vcard | ||||
| %td= count | %td= count | ||||
| @@ -54,9 +54,9 @@ | |||||
| = candidacy.candidate.short_name | = candidacy.candidate.short_name | ||||
| %td.org | %td.org | ||||
| = party_name(candidacy.labcoop, candidacy.party.name) | = party_name(candidacy.labcoop, candidacy.party.name) | ||||
| - if @election_held | |||||
| - if election_held | |||||
| %td.right= commify(candidacy.votes) | %td.right= commify(candidacy.votes) | ||||
| %td.right= format_percent(candidacy.votes.to_f / @share_denominator * 100) | |||||
| %td.right= format_percent(candidacy.votes.to_f / share_denominator * 100) | |||||
| - if candidacy.seats == 1 | - if candidacy.seats == 1 | ||||
| %td.elected.elected_text="Elected" | %td.elected.elected_text="Elected" | ||||
| @@ -72,15 +72,15 @@ | |||||
| %td | %td | ||||
| %td | %td | ||||
| %td | %td | ||||
| %td.right= commify(@total_votes) | |||||
| %td.right= commify(total_votes) | |||||
| %td | %td | ||||
| %td | %td | ||||
| - if @share_message | |||||
| - if share_message | |||||
| .warning | .warning | ||||
| = @share_message | |||||
| = share_message | |||||
| - if @total_seats > 1 | |||||
| - if total_seats > 1 | |||||
| %h2 Votes by party | %h2 Votes by party | ||||
| %table | %table | ||||
| @@ -96,20 +96,20 @@ | |||||
| - count = 0 | - count = 0 | ||||
| - @results_by_party.each do |row| | |||||
| - results_by_party.each do |row| | |||||
| - count += 1 | - count += 1 | ||||
| %tr | %tr | ||||
| %td.right= count | %td.right= count | ||||
| %td{ :style => "background-color: #{row['party_colour'] }" } | %td{ :style => "background-color: #{row['party_colour'] }" } | ||||
| %td= row['party_name'] | %td= row['party_name'] | ||||
| - if @election_held | |||||
| - if election_held | |||||
| %td.right.highlight= row['num_seats'] | %td.right.highlight= row['num_seats'] | ||||
| - else | - else | ||||
| %td.right.highlight — | %td.right.highlight — | ||||
| %td.right= row['num_candidates'] | %td.right= row['num_candidates'] | ||||
| - if @election_held | |||||
| - if election_held | |||||
| %td.right= commify(row['total_votes']) | %td.right= commify(row['total_votes']) | ||||
| %td.right= format_percent(row['total_votes'].to_f / @total_votes * 100) | |||||
| %td.right= format_percent(row['total_votes'].to_f / total_votes * 100) | |||||
| %td.right= commify(row['total_votes'] / row['num_candidates']) | %td.right= commify(row['total_votes'] / row['num_candidates']) | ||||
| - else | - else | ||||
| %td.right — | %td.right — | ||||
| @@ -120,48 +120,48 @@ | |||||
| %td | %td | ||||
| %td | %td | ||||
| %td | %td | ||||
| - if @election_held | |||||
| %td.right.highlight= @total_seats | |||||
| - if election_held | |||||
| %td.right.highlight= total_seats | |||||
| - else | - else | ||||
| %td.right.highlight | %td.right.highlight | ||||
| %td.right= @total_candidates | |||||
| %td.right= commify(@total_votes) | |||||
| %td.right= total_candidates | |||||
| %td.right= commify(total_votes) | |||||
| %td | %td | ||||
| %td | %td | ||||
| - if @poll | |||||
| - if poll | |||||
| %p | %p | ||||
| %table | %table | ||||
| - if @poll.ballot_papers_issued | |||||
| - if poll.ballot_papers_issued | |||||
| %tr | %tr | ||||
| %td Ballot papers issued | %td Ballot papers issued | ||||
| %td.right= commify(@poll.ballot_papers_issued) | |||||
| - if @poll.electorate | |||||
| %td.right= commify(poll.ballot_papers_issued) | |||||
| - if poll.electorate | |||||
| %tr | %tr | ||||
| %td Electorate | %td Electorate | ||||
| %td.right= commify(@poll.electorate) | |||||
| - if @poll.turnout_percent > 0 | |||||
| %td.right= commify(poll.electorate) | |||||
| - if poll.turnout_percent > 0 | |||||
| %tr | %tr | ||||
| %td Turnout | %td Turnout | ||||
| %td.right= sprintf("%.0f%%", @poll.turnout_percent) | |||||
| %td.right= sprintf("%.0f%%", poll.turnout_percent) | |||||
| -# Show this table conditionally as sometimes we have electorate data but no | -# Show this table conditionally as sometimes we have electorate data but no | ||||
| -# breakdown of rejected ballot papers | -# breakdown of rejected ballot papers | ||||
| - if @poll.rejected_no_official_mark | |||||
| - if poll.rejected_no_official_mark | |||||
| %h2 Rejected ballot papers | %h2 Rejected ballot papers | ||||
| %table | %table | ||||
| %tr | %tr | ||||
| %td No official mark on the ballot paper | %td No official mark on the ballot paper | ||||
| %td.right= commify(@poll.rejected_no_official_mark) | |||||
| %td.right= commify(poll.rejected_no_official_mark) | |||||
| %tr | %tr | ||||
| %td Voting for too many candidates | %td Voting for too many candidates | ||||
| %td.right= commify(@poll.rejected_too_many_candidates) | |||||
| %td.right= commify(poll.rejected_too_many_candidates) | |||||
| %tr | %tr | ||||
| %td Voter could be identified by writing or a mark on the ballot paper | %td Voter could be identified by writing or a mark on the ballot paper | ||||
| %td.right= commify(@poll.rejected_identifiable_voter) | |||||
| %td.right= commify(poll.rejected_identifiable_voter) | |||||
| %tr | %tr | ||||
| %td Ballot paper unmarked or voter's intention uncertain | %td Ballot paper unmarked or voter's intention uncertain | ||||
| %td.right= commify(@poll.rejected_blank_or_uncertain) | |||||
| %td.right= commify(poll.rejected_blank_or_uncertain) | |||||
| %tr.footer | %tr.footer | ||||
| %td | %td | ||||
| %td.right= commify(@poll.total_rejected_ballots) | |||||
| %td.right= commify(poll.total_rejected_ballots) | |||||