From ecb4f16ec5a78eca5e89ce77c55bb64625471046 Mon Sep 17 00:00:00 2001 From: ricola Date: Tue, 3 Mar 2026 00:59:24 +0100 Subject: [PATCH 1/5] Update sqlite3 --- Gemfile.lock | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 955384c..9a65df9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -46,7 +46,7 @@ GEM net-pop net-smtp mini_mime (1.1.5) - mini_portile2 (2.8.8) + mini_portile2 (2.8.9) minitest (5.25.5) mustermann (3.0.3) ruby2_keywords (~> 0.0.1) @@ -91,11 +91,8 @@ GEM activerecord (>= 4.1) sinatra (>= 1.0) singleton (0.3.0) - sqlite3 (2.6.0) + sqlite3 (2.8.1) mini_portile2 (~> 2.8.0) - sqlite3 (2.6.0-arm64-darwin) - sqlite3 (2.6.0-x86_64-darwin) - sqlite3 (2.6.0-x86_64-linux-gnu) text (1.3.1) tilt (2.6.0) timeout (0.4.3) From d5f77d338bbc4a8c29c34faa1f44531ade6ff031 Mon Sep 17 00:00:00 2001 From: ricola Date: Mon, 23 Mar 2026 18:26:32 -0600 Subject: [PATCH 2/5] Send automatic email reminders Closes #4 --- Rakefile | 5 +++ config/environments/defaults.rb | 2 ++ config/schedule.rb | 1 + ...0260323215246_add_reminders_to_votes.rb.rb | 5 +++ db/schema.rb | 3 +- vedia.rb | 31 ++++++++++++++++++- views/votes_reminder_email.erb | 5 +++ 7 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20260323215246_add_reminders_to_votes.rb.rb create mode 100644 views/votes_reminder_email.erb diff --git a/Rakefile b/Rakefile index 62ef4c3..85d5e21 100644 --- a/Rakefile +++ b/Rakefile @@ -25,3 +25,8 @@ desc "Close votes that have expired" task :close_expired_votes do close_expired_votes end + +desc "Send email reminders" +task :send_reminders do + send_reminders +end diff --git a/config/environments/defaults.rb b/config/environments/defaults.rb index 108f981..0ba7f98 100644 --- a/config/environments/defaults.rb +++ b/config/environments/defaults.rb @@ -6,3 +6,5 @@ set :values, [ { :id => 1, :label => _("Awful"), :color => '#ff4500' }, { :id => 5, :label => _("Good"), :color => '#228b22' }, { :id => 6, :label => _("Very good"), :color => '#006400' } ] set :expire_after, 7 * 24 * 60 * 60 # 7 days +set :reminders, [ { :timeout => 48 * 60 * 60 }, + { :timeout => 24 * 60 * 60 } ] diff --git a/config/schedule.rb b/config/schedule.rb index c72feae..168cb97 100644 --- a/config/schedule.rb +++ b/config/schedule.rb @@ -6,4 +6,5 @@ set :environment_variable, 'RACK_ENV' every 5.minutes do rake "close_expired_votes" + rake "send_email_reminders" end diff --git a/db/migrate/20260323215246_add_reminders_to_votes.rb.rb b/db/migrate/20260323215246_add_reminders_to_votes.rb.rb new file mode 100644 index 0000000..952e4ee --- /dev/null +++ b/db/migrate/20260323215246_add_reminders_to_votes.rb.rb @@ -0,0 +1,5 @@ +class AddRemindersToVotes < ActiveRecord::Migration[7.2] + def change + add_column :votes, :reminders, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index bffb47b..5675bc4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2025_06_08_223006) do +ActiveRecord::Schema[7.2].define(version: 2026_03_23_215246) do create_table "candidates", force: :cascade do |t| t.integer "vote_id" t.string "name" @@ -56,6 +56,7 @@ ActiveRecord::Schema[7.2].define(version: 2025_06_08_223006) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "state" + t.integer "reminders" end add_foreign_key "ratings", "votes" diff --git a/vedia.rb b/vedia.rb index 4403543..7759d23 100644 --- a/vedia.rb +++ b/vedia.rb @@ -268,6 +268,7 @@ post '/admin/votes/:id' do if (@vote.state == 'open' or @vote.state == 'closed') and new_expiry > Time.now puts "change" @vote.expire_on = new_expiry + @vote.reminders = 0 @vote.state = 'open' @vote.save end @@ -589,7 +590,7 @@ def close_expired_votes mail = Mail.new mail.from = settings.admin_email mail.to = user.email - mail.subject = _("Results of the vote: %{t}") % { t: vote.title } + mail.subject = _("Results of the vote '%{t}'") % { t: vote.title } template = ERB.new(File.read("views/votes_close_email.erb")) mail.body = template.result(binding) mail.deliver @@ -597,6 +598,34 @@ def close_expired_votes end end +def send_reminders + Vote.where(state: 'open').each do |vote| + settings.reminders.slice(vote.reminders..settings.reminders.length-1).each do |reminder| + minutes_to_expiry = ( vote.expire_on - Time.now.utc ) / 60 + if minutes_to_expiry < reminder[:timeout] / 60 + User.all.each do |user| + if not vote.ratings.collect { |rating| rating.user }.include?(user) + puts "#{Time.now.utc} Sending reminder #{reminder[:template]} for '#{vote.title}' to #{user.email}..." + mail = Mail.new + mail.from = settings.admin_email + mail.to = user.email + if minutes_to_expiry < 60 + mail.subject = _("%{m} minutes left to vote on '%{t}'") % { m: minutes_to_expiry.round, t: vote.title } + else + mail.subject = _("%{h} hours left to vote on '%{t}'") % { h: (minutes_to_expiry / 60).round, t: vote.title } + end + template = ERB.new(File.read("views/votes_reminder_email.erb")) + mail.body = template.result(binding) + mail.deliver + end + end + vote.reminders = vote.reminders + 1 + vote.save + end + end + end +end + helpers do def current_user if session[:user_id] diff --git a/views/votes_reminder_email.erb b/views/votes_reminder_email.erb new file mode 100644 index 0000000..92cf2d6 --- /dev/null +++ b/views/votes_reminder_email.erb @@ -0,0 +1,5 @@ +<%= _("You haven't voted yet!") %> + +<%= _("Visit this link to vote:") %> + +<%= "#{settings.base_url}votes/#{vote.secure_id}" %> From 185e47c5ffcb93758c3186b950e787861c45d3c0 Mon Sep 17 00:00:00 2001 From: ricola Date: Mon, 23 Mar 2026 18:57:25 -0600 Subject: [PATCH 3/5] Factorize --- vedia.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vedia.rb b/vedia.rb index 7759d23..080d054 100644 --- a/vedia.rb +++ b/vedia.rb @@ -585,7 +585,7 @@ def close_expired_votes puts "#{Time.now.utc} Closing vote \"#{vote.title}\" because it expired on #{vote.expire_on}..." vote.state = 'closed' vote.save - User.all.each do |user| + all_users_sorted.each do |user| puts "#{Time.now.utc} Sending results by email to #{user.email}..." mail = Mail.new mail.from = settings.admin_email @@ -603,7 +603,7 @@ def send_reminders settings.reminders.slice(vote.reminders..settings.reminders.length-1).each do |reminder| minutes_to_expiry = ( vote.expire_on - Time.now.utc ) / 60 if minutes_to_expiry < reminder[:timeout] / 60 - User.all.each do |user| + all_users_sorted.each do |user| if not vote.ratings.collect { |rating| rating.user }.include?(user) puts "#{Time.now.utc} Sending reminder #{reminder[:template]} for '#{vote.title}' to #{user.email}..." mail = Mail.new @@ -660,6 +660,10 @@ helpers do @candidate = Candidate.find(params[:cid]) end + def all_users_sorted + User.all.each.sort_by { |user| user.email } + end + def require_candidate_in_vote redirect '/votes/' + @vote.secure_id unless @candidate.vote == @vote end From 125d2714b0d5272b2c8008e36154a3750deb1ccb Mon Sep 17 00:00:00 2001 From: ricola Date: Mon, 23 Mar 2026 18:58:30 -0600 Subject: [PATCH 4/5] List users who haven't voted Closes #3 --- views/votes_show_closed.erb | 6 +++++- views/votes_show_open.erb | 14 +++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/views/votes_show_closed.erb b/views/votes_show_closed.erb index caf22e6..b904577 100644 --- a/views/votes_show_closed.erb +++ b/views/votes_show_closed.erb @@ -175,7 +175,7 @@ <% end %> - <% @vote.ratings.collect { |rating| rating.user }.uniq.sort_by { |user| user.email }.each do |user| %> + <% all_users_sorted.each do |user| %> <%= user.email %> <% @vote.candidates.each do |candidate| %> @@ -183,6 +183,10 @@ <%= erb :rating_badge, :locals => { :value => settings.values.select { |e| e[:id] == rating.value }.first } %> + <% else %> + + <%= _("Not voted") %> + <% end %> <% end %> diff --git a/views/votes_show_open.erb b/views/votes_show_open.erb index 488780c..ea19fb5 100644 --- a/views/votes_show_open.erb +++ b/views/votes_show_open.erb @@ -66,9 +66,17 @@

<%= _("Participants") + " (#{@vote.ratings.collect { |rating| rating.user }.uniq.count})" %>

    -<% @vote.ratings.collect { |rating| rating.user }.uniq.sort_by { |user| user.email }.each do |user| %> -
  • <%= user.email %>
  • -<% end %> + <% all_users_sorted.each do |user| %> +
  • + <% if @vote.ratings.collect { |rating| rating.user }.include?(user) %> + + <% else %> + + <% end %> + <%= user.email %> + +
  • + <% end %>
<% if @vote.users.exists?(current_user.id) and @vote.expire_on.nil? %> From 50ad689b28cab477002dac37b5fc81fd091f569e Mon Sep 17 00:00:00 2001 From: ricola Date: Mon, 23 Mar 2026 19:00:32 -0600 Subject: [PATCH 5/5] Update Catalan translation --- po/ca/vedia.po | 115 +++++++++++++++++++++++++++++-------------------- po/vedia.pot | 97 +++++++++++++++++++++++++---------------- 2 files changed, 127 insertions(+), 85 deletions(-) diff --git a/po/ca/vedia.po b/po/ca/vedia.po index fe336e2..101eef6 100644 --- a/po/ca/vedia.po +++ b/po/ca/vedia.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-01-21 09:32-0600\n" +"POT-Creation-Date: 2026-03-23 18:58-0600\n" "PO-Revision-Date: 2025-03-29 20:41-0600\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -41,17 +41,25 @@ msgstr "Bé" msgid "Very good" msgstr "Molt bé" -#: ../vedia.rb:143 +#: ../vedia.rb:137 msgid "Incorrect email or password." msgstr "Correu o contrasenya incorrecte." -#: ../vedia.rb:170 +#: ../vedia.rb:164 msgid "Reset your password" msgstr "Reiniciar contrasenya" -#: ../vedia.rb:582 -msgid "Results of the vote: %{t}" -msgstr "Resultats de la votació: %{t}" +#: ../vedia.rb:593 +msgid "Results of the vote '%{t}'" +msgstr "Resultats de la votació '%{t}'" + +#: ../vedia.rb:613 +msgid "%{m} minutes left to vote on '%{t}'" +msgstr "Queden %{m} minuts per votar en '%{t}'" + +#: ../vedia.rb:615 +msgid "%{h} hours left to vote on '%{t}'" +msgstr "Queden %{h} hores per votar en '%{t}'" #: ../views/admin.erb:1 ../views/admin_users.erb:1 ../views/admin_votes.erb:1 #: ../views/layout.erb:30 @@ -104,7 +112,7 @@ msgid "Organized votes" msgstr "Votacions organitzades" #: ../views/admin_users.erb:19 ../views/admin_users.erb:38 -#: ../views/admin_votes.erb:27 ../views/admin_votes.erb:46 +#: ../views/admin_votes.erb:65 ../views/admin_votes.erb:84 #: ../views/votes_edit.erb:32 msgid "Delete" msgstr "Suprimir" @@ -113,12 +121,12 @@ msgstr "Suprimir" msgid "No vote organized." msgstr "Cap votació organitzada." -#: ../views/admin_users.erb:30 ../views/admin_votes.erb:38 -#: ../views/votes_show_closed.erb:165 +#: ../views/admin_users.erb:30 ../views/admin_votes.erb:76 +#: ../views/votes_show_closed.erb:167 msgid "Ratings" msgstr "Valoracions" -#: ../views/admin_users.erb:45 ../views/admin_votes.erb:53 +#: ../views/admin_users.erb:45 ../views/admin_votes.erb:91 msgid "No rating." msgstr "Cap valoració." @@ -138,29 +146,29 @@ msgstr "ID segura: %{secure_id}" msgid "Description: %{description}" msgstr "Descripció: %{description}" -#: ../views/admin_votes.erb:15 ../views/votes_open.erb:12 -msgid "Closing date: %{date}" -msgstr "Data de tancament: %{date}" +#: ../views/admin_votes.erb:18 +msgid "Closing date: " +msgstr "Data de tancament: " -#: ../views/admin_votes.erb:15 -msgid "None" -msgstr "Cap" +#: ../views/admin_votes.erb:50 +msgid "Change" +msgstr "Canviar" -#: ../views/admin_votes.erb:17 +#: ../views/admin_votes.erb:55 msgid "State: %{state}" msgstr "Estat: %{state}" -#: ../views/admin_votes.erb:19 ../views/votes_edit.erb:90 -#: ../views/votes_show_closed.erb:200 ../views/votes_show_draft.erb:29 -#: ../views/votes_show_open.erb:88 +#: ../views/admin_votes.erb:57 ../views/votes_edit.erb:90 +#: ../views/votes_show_closed.erb:206 ../views/votes_show_draft.erb:29 +#: ../views/votes_show_open.erb:96 msgid "Organizers" msgstr "Organitzadores" -#: ../views/admin_votes.erb:34 +#: ../views/admin_votes.erb:72 msgid "No organizer." msgstr "Cap organitzadora." -#: ../views/admin_votes.erb:60 ../views/votes_edit.erb:86 +#: ../views/admin_votes.erb:98 ../views/votes_edit.erb:86 msgid "Delete vote" msgstr "Suprimir la votació" @@ -204,14 +212,14 @@ msgid "Login" msgstr "Connexió" #: ../views/login.erb:6 ../views/reset.erb:1 ../views/reset.erb:16 -#: ../views/reset_change.erb:1 ../views/reset_change.erb:20 +#: ../views/reset_change.erb:1 ../views/reset_change.erb:21 #: ../views/reset_invalid.erb:1 ../views/reset_sent.erb:1 msgid "Reset password" msgstr "Reiniciar contrasenya" #: ../views/login.erb:12 ../views/reset.erb:13 ../views/reset_change.erb:13 #: ../views/signup.erb:24 ../views/votes_edit.erb:102 -#: ../views/votes_show_closed.erb:214 ../views/votes_show_open.erb:104 +#: ../views/votes_show_closed.erb:220 ../views/votes_show_open.erb:112 #: ../views/votes_show_unauthenticated.erb:9 msgid "Email" msgstr "Correu" @@ -269,7 +277,8 @@ msgstr "Un compte ja existeix pel correu %{email}." msgid "Voted" msgstr "Votat" -#: ../views/votes.erb:20 ../views/votes_show_open.erb:9 +#: ../views/votes.erb:20 ../views/votes_show_closed.erb:188 +#: ../views/votes_show_open.erb:9 msgid "Not voted" msgstr "Sense votar" @@ -320,8 +329,8 @@ msgid "Open vote to participants" msgstr "Obrir la votació als votants" #: ../views/votes_edit.erb:98 ../views/votes_edit.erb:105 -#: ../views/votes_show_closed.erb:210 ../views/votes_show_closed.erb:217 -#: ../views/votes_show_open.erb:100 ../views/votes_show_open.erb:107 +#: ../views/votes_show_closed.erb:216 ../views/votes_show_closed.erb:223 +#: ../views/votes_show_open.erb:108 ../views/votes_show_open.erb:115 msgid "Add organizer" msgstr "Afegeix organitzadora" @@ -341,6 +350,10 @@ msgstr "Títol" msgid "New vote" msgstr "Nova votació" +#: ../views/votes_open.erb:12 +msgid "Closing date: %{date}" +msgstr "Data de tancament: %{date}" + #: ../views/votes_open.erb:14 msgid "" "The vote will automatically close on that date and the results will\n" @@ -359,6 +372,14 @@ msgstr "Ja no podràs modificar o suprimir aquesta votació desprès d'obrir-la. msgid "Cancel" msgstr "Cancel·lar" +#: ../views/votes_reminder_email.erb:1 +msgid "You haven't voted yet!" +msgstr "Encara no has votat!" + +#: ../views/votes_reminder_email.erb:3 +msgid "Visit this link to vote:" +msgstr "Visita aquest enllaç per votar:" + #: ../views/votes_show_closed.erb:11 msgid "Closed on %{date}" msgstr "Tancada el %{date}" @@ -393,11 +414,11 @@ msgstr "Veure descripció" msgid "Analyze tiebreak" msgstr "Analitzar desempat" -#: ../views/votes_show_closed.erb:80 +#: ../views/votes_show_closed.erb:81 msgid "This candidate and the winning candidate have the same majority judgment." msgstr "Aquesta opció i l'opció guanyadora tenen el mateix judici majoritari." -#: ../views/votes_show_closed.erb:82 +#: ../views/votes_show_closed.erb:83 msgid "" "To break the tie, we remove the vote that corresponds to the majority judgment" " one-by-one until one candidate has a better majority judgment than the other." @@ -405,23 +426,23 @@ msgstr "" "Pel desempat, traiem el vot que correspon al judici majoritari un per un fins " "que alguna opció tingui un millor judici majoritari que l'altre." -#: ../views/votes_show_closed.erb:84 +#: ../views/votes_show_closed.erb:85 msgid "Votes for this candidate" msgstr "Vots per aquesta opció" -#: ../views/votes_show_closed.erb:85 +#: ../views/votes_show_closed.erb:86 msgid "Votes for the winning candidate" msgstr "Vots per l'opció guanyadora" -#: ../views/votes_show_closed.erb:99 +#: ../views/votes_show_closed.erb:100 msgid "" "Without removing any vote, both candidates have the same majority judgement of" " %{current}." msgstr "" -"Sense treure cap vot, les dues opcions tenen el mateix judici majoritari de " -"%{current}." +"Sense treure cap vot, les dues opcions tenen el mateix judici majoritari de %{" +"current}." -#: ../views/votes_show_closed.erb:104 +#: ../views/votes_show_closed.erb:105 msgid "" "Removing a vote of rating %{previous}, both candidates still have the same maj" "ority judgement of %{current}." @@ -429,16 +450,16 @@ msgstr "" "Traient un vot de valoració %{previous}, les dues opcions encara tenen el mate" "ix judici majoritari de %{current}." -#: ../views/votes_show_closed.erb:108 +#: ../views/votes_show_closed.erb:109 msgid "" "Removing a vote of rating %{previous}, this candidate has a majority judgement" " of %{losing}, but the winning candidate has a majority judgement of %{winning" "}." msgstr "" -"Traient un vot de valoració %{previous}, aquesta opció te un judici majoritar" -"i de %{losing} però l'opció guanyadora te un judici majoritari de %{winning}." +"Traient un vot de valoració %{previous}, aquesta opció te un judici majoritari" +" de %{losing} però l'opció guanyadora te un judici majoritari de %{winning}." -#: ../views/votes_show_closed.erb:114 +#: ../views/votes_show_closed.erb:115 msgid "" "Removing another vote of rating %{previous}, both candidates still have the sa" "me majority judgement of %{current}." @@ -446,21 +467,21 @@ msgstr "" "Traient un altre vot de valoració %{previous}, les dues opcions encara tenen e" "l mateix judici majoritari de %{current}." -#: ../views/votes_show_closed.erb:118 +#: ../views/votes_show_closed.erb:119 msgid "" "Removing another vote of rating %{previous}, this candidate has a majority jud" "gement of %{losing}, but the winning candidate has a majority judgement of %{w" "inning}." msgstr "" -"Traient un altre vot de valoració %{previous}, aquesta opció te un judici maj" -"oritari de %{losing} però l'opció guanyadora te un judici majoritari de %{winn" -"ing}." +"Traient un altre vot de valoració %{previous}, aquesta opció te un judici majo" +"ritari de %{losing} però l'opció guanyadora te un judici majoritari de %{winni" +"ng}." -#: ../views/votes_show_closed.erb:170 +#: ../views/votes_show_closed.erb:172 msgid "Participant" msgstr "Votant" -#: ../views/votes_show_closed.erb:195 +#: ../views/votes_show_closed.erb:201 msgid "Reopen voting period" msgstr "Reobrir el període de votació" @@ -484,11 +505,11 @@ msgstr "Votar" msgid "Participants" msgstr "Votants" -#: ../views/votes_show_open.erb:77 +#: ../views/votes_show_open.erb:85 msgid "Change back to draft vote" msgstr "Tornar a l'esborrany de votació" -#: ../views/votes_show_open.erb:81 +#: ../views/votes_show_open.erb:89 msgid "Close votes and show results" msgstr "Tancar la votació i veure els resultats" diff --git a/po/vedia.pot b/po/vedia.pot index f745e93..add93ac 100644 --- a/po/vedia.pot +++ b/po/vedia.pot @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-01-21 09:33-0600\n" -"PO-Revision-Date: 2026-01-21 09:33-0600\n" +"POT-Creation-Date: 2026-03-23 18:58-0600\n" +"PO-Revision-Date: 2026-03-23 18:58-0600\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" @@ -42,16 +42,24 @@ msgstr "" msgid "Very good" msgstr "" -#: ../vedia.rb:143 +#: ../vedia.rb:137 msgid "Incorrect email or password." msgstr "" -#: ../vedia.rb:170 +#: ../vedia.rb:164 msgid "Reset your password" msgstr "" -#: ../vedia.rb:582 -msgid "Results of the vote: %{t}" +#: ../vedia.rb:593 +msgid "Results of the vote '%{t}'" +msgstr "" + +#: ../vedia.rb:613 +msgid "%{m} minutes left to vote on '%{t}'" +msgstr "" + +#: ../vedia.rb:615 +msgid "%{h} hours left to vote on '%{t}'" msgstr "" #: ../views/admin.erb:1 ../views/admin_users.erb:1 ../views/admin_votes.erb:1 @@ -105,7 +113,7 @@ msgid "Organized votes" msgstr "" #: ../views/admin_users.erb:19 ../views/admin_users.erb:38 -#: ../views/admin_votes.erb:27 ../views/admin_votes.erb:46 +#: ../views/admin_votes.erb:65 ../views/admin_votes.erb:84 #: ../views/votes_edit.erb:32 msgid "Delete" msgstr "" @@ -114,12 +122,12 @@ msgstr "" msgid "No vote organized." msgstr "" -#: ../views/admin_users.erb:30 ../views/admin_votes.erb:38 -#: ../views/votes_show_closed.erb:165 +#: ../views/admin_users.erb:30 ../views/admin_votes.erb:76 +#: ../views/votes_show_closed.erb:167 msgid "Ratings" msgstr "" -#: ../views/admin_users.erb:45 ../views/admin_votes.erb:53 +#: ../views/admin_users.erb:45 ../views/admin_votes.erb:91 msgid "No rating." msgstr "" @@ -139,29 +147,29 @@ msgstr "" msgid "Description: %{description}" msgstr "" -#: ../views/admin_votes.erb:15 ../views/votes_open.erb:12 -msgid "Closing date: %{date}" +#: ../views/admin_votes.erb:18 +msgid "Closing date: " msgstr "" -#: ../views/admin_votes.erb:15 -msgid "None" +#: ../views/admin_votes.erb:50 +msgid "Change" msgstr "" -#: ../views/admin_votes.erb:17 +#: ../views/admin_votes.erb:55 msgid "State: %{state}" msgstr "" -#: ../views/admin_votes.erb:19 ../views/votes_edit.erb:90 -#: ../views/votes_show_closed.erb:200 ../views/votes_show_draft.erb:29 -#: ../views/votes_show_open.erb:88 +#: ../views/admin_votes.erb:57 ../views/votes_edit.erb:90 +#: ../views/votes_show_closed.erb:206 ../views/votes_show_draft.erb:29 +#: ../views/votes_show_open.erb:96 msgid "Organizers" msgstr "" -#: ../views/admin_votes.erb:34 +#: ../views/admin_votes.erb:72 msgid "No organizer." msgstr "" -#: ../views/admin_votes.erb:60 ../views/votes_edit.erb:86 +#: ../views/admin_votes.erb:98 ../views/votes_edit.erb:86 msgid "Delete vote" msgstr "" @@ -203,14 +211,14 @@ msgid "Login" msgstr "" #: ../views/login.erb:6 ../views/reset.erb:1 ../views/reset.erb:16 -#: ../views/reset_change.erb:1 ../views/reset_change.erb:20 +#: ../views/reset_change.erb:1 ../views/reset_change.erb:21 #: ../views/reset_invalid.erb:1 ../views/reset_sent.erb:1 msgid "Reset password" msgstr "" #: ../views/login.erb:12 ../views/reset.erb:13 ../views/reset_change.erb:13 #: ../views/signup.erb:24 ../views/votes_edit.erb:102 -#: ../views/votes_show_closed.erb:214 ../views/votes_show_open.erb:104 +#: ../views/votes_show_closed.erb:220 ../views/votes_show_open.erb:112 #: ../views/votes_show_unauthenticated.erb:9 msgid "Email" msgstr "" @@ -266,7 +274,8 @@ msgstr "" msgid "Voted" msgstr "" -#: ../views/votes.erb:20 ../views/votes_show_open.erb:9 +#: ../views/votes.erb:20 ../views/votes_show_closed.erb:188 +#: ../views/votes_show_open.erb:9 msgid "Not voted" msgstr "" @@ -317,8 +326,8 @@ msgid "Open vote to participants" msgstr "" #: ../views/votes_edit.erb:98 ../views/votes_edit.erb:105 -#: ../views/votes_show_closed.erb:210 ../views/votes_show_closed.erb:217 -#: ../views/votes_show_open.erb:100 ../views/votes_show_open.erb:107 +#: ../views/votes_show_closed.erb:216 ../views/votes_show_closed.erb:223 +#: ../views/votes_show_open.erb:108 ../views/votes_show_open.erb:115 msgid "Add organizer" msgstr "" @@ -338,6 +347,10 @@ msgstr "" msgid "New vote" msgstr "" +#: ../views/votes_open.erb:12 +msgid "Closing date: %{date}" +msgstr "" + #: ../views/votes_open.erb:14 msgid "" "The vote will automatically close on that date and the results will\n" @@ -354,6 +367,14 @@ msgstr "" msgid "Cancel" msgstr "" +#: ../views/votes_reminder_email.erb:1 +msgid "You haven't voted yet!" +msgstr "" + +#: ../views/votes_reminder_email.erb:3 +msgid "Visit this link to vote:" +msgstr "" + #: ../views/votes_show_closed.erb:11 msgid "Closed on %{date}" msgstr "" @@ -385,61 +406,61 @@ msgstr "" msgid "Analyze tiebreak" msgstr "" -#: ../views/votes_show_closed.erb:80 +#: ../views/votes_show_closed.erb:81 msgid "This candidate and the winning candidate have the same majority judgment." msgstr "" -#: ../views/votes_show_closed.erb:82 +#: ../views/votes_show_closed.erb:83 msgid "" "To break the tie, we remove the vote that corresponds to the majority judgment" " one-by-one until one candidate has a better majority judgment than the other." msgstr "" -#: ../views/votes_show_closed.erb:84 +#: ../views/votes_show_closed.erb:85 msgid "Votes for this candidate" msgstr "" -#: ../views/votes_show_closed.erb:85 +#: ../views/votes_show_closed.erb:86 msgid "Votes for the winning candidate" msgstr "" -#: ../views/votes_show_closed.erb:99 +#: ../views/votes_show_closed.erb:100 msgid "" "Without removing any vote, both candidates have the same majority judgement of" " %{current}." msgstr "" -#: ../views/votes_show_closed.erb:104 +#: ../views/votes_show_closed.erb:105 msgid "" "Removing a vote of rating %{previous}, both candidates still have the same maj" "ority judgement of %{current}." msgstr "" -#: ../views/votes_show_closed.erb:108 +#: ../views/votes_show_closed.erb:109 msgid "" "Removing a vote of rating %{previous}, this candidate has a majority judgement" " of %{losing}, but the winning candidate has a majority judgement of %{winning" "}." msgstr "" -#: ../views/votes_show_closed.erb:114 +#: ../views/votes_show_closed.erb:115 msgid "" "Removing another vote of rating %{previous}, both candidates still have the sa" "me majority judgement of %{current}." msgstr "" -#: ../views/votes_show_closed.erb:118 +#: ../views/votes_show_closed.erb:119 msgid "" "Removing another vote of rating %{previous}, this candidate has a majority jud" "gement of %{losing}, but the winning candidate has a majority judgement of %{w" "inning}." msgstr "" -#: ../views/votes_show_closed.erb:170 +#: ../views/votes_show_closed.erb:172 msgid "Participant" msgstr "" -#: ../views/votes_show_closed.erb:195 +#: ../views/votes_show_closed.erb:201 msgid "Reopen voting period" msgstr "" @@ -463,11 +484,11 @@ msgstr "" msgid "Participants" msgstr "" -#: ../views/votes_show_open.erb:77 +#: ../views/votes_show_open.erb:85 msgid "Change back to draft vote" msgstr "" -#: ../views/votes_show_open.erb:81 +#: ../views/votes_show_open.erb:89 msgid "Close votes and show results" msgstr ""