Compare commits

..

No commits in common. "3b2cf657b53767ec2c1ff49e05734a53b066af03" and "582562dae0f836a0e5cf3f543781fff6536aad23" have entirely different histories.

15 changed files with 91 additions and 26814 deletions

View file

@ -8,4 +8,3 @@ gem 'puma'
gem 'sqlite3'
gem 'bcrypt'
gem 'gettext'
gem 'chartkick'

View file

@ -23,7 +23,6 @@ GEM
bcrypt (3.1.20)
benchmark (0.4.0)
bigdecimal (3.1.9)
chartkick (5.1.4)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
drb (2.2.1)
@ -92,7 +91,6 @@ PLATFORMS
DEPENDENCIES
bcrypt
chartkick
gettext
puma
rackup

View file

@ -1,4 +1,4 @@
require_relative 'vedia'
require_relative 'vote'
require 'sinatra/activerecord/rake'
desc "Update PO files"

View file

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-06 16:13-0600\n"
"POT-Creation-Date: 2025-03-30 12:01-0600\n"
"PO-Revision-Date: 2025-03-29 20:41-0600\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#: ../views/home.erb:1 ../views/layout.erb:13
#: ../views/home.erb:1 ../views/layout.erb:10
msgid "Home"
msgstr "Inici"
@ -57,43 +57,31 @@ msgstr "Crear una nova votació"
msgid "Vote"
msgstr "Votació"
#: ../views/layout.erb:12
#: ../views/layout.erb:9
msgid "Logged in as %{email}."
msgstr "Estàs connectada com a %{email}."
#: ../views/layout.erb:12
#: ../views/layout.erb:9
msgid "Logout"
msgstr "Desconnexió"
#: ../views/layout.erb:15 ../views/login.erb:1 ../views/login.erb:16
#: ../views/layout.erb:12 ../views/login.erb:1 ../views/login.erb:14
msgid "Login"
msgstr "Connexió"
#: ../views/login.erb:9 ../views/signup.erb:24 ../views/votes_edit.erb:51
#: ../views/votes_show_closed.erb:85 ../views/votes_show_open.erb:58
#: ../views/login.erb:7 ../views/signup.erb:5 ../views/votes_edit.erb:51
#: ../views/votes_show_closed.erb:69 ../views/votes_show_open.erb:58
msgid "Email"
msgstr "Correu"
#: ../views/login.erb:13 ../views/signup.erb:28
#: ../views/login.erb:11 ../views/signup.erb:9
msgid "Password"
msgstr "Contrasenya"
#: ../views/login.erb:18 ../views/signup.erb:1 ../views/signup.erb:31
#: ../views/login.erb:16 ../views/signup.erb:1 ../views/signup.erb:12
msgid "Create account"
msgstr "Crear un compte"
#: ../views/signup.erb:6
msgid "Specify a password."
msgstr "Entra una contrasenya."
#: ../views/signup.erb:14
msgid "Email is not a valid email address."
msgstr "El correu no és una direcció de correu vàlida."
#: ../views/signup.erb:17
msgid "An account already exists for %{email}."
msgstr "Un compte ja existeix pel correu %{email}."
#: ../views/votes_edit.erb:1
msgid "Edit draft vote"
msgstr "Editar un esborrany de votació"
@ -128,34 +116,30 @@ msgid "Name"
msgstr "Nom"
#: ../views/votes_edit.erb:36 ../views/votes_edit.erb:54
#: ../views/votes_show_closed.erb:81 ../views/votes_show_closed.erb:88
#: ../views/votes_show_open.erb:61
#: ../views/votes_show_closed.erb:72 ../views/votes_show_open.erb:61
msgid "Add"
msgstr "Afegir"
#: ../views/votes_edit.erb:39 ../views/votes_show_closed.erb:65
#: ../views/votes_edit.erb:39 ../views/votes_show_closed.erb:49
#: ../views/votes_show_draft.erb:5 ../views/votes_show_open.erb:34
msgid "Organizers"
msgstr "Organitzadores"
#: ../views/votes_edit.erb:47 ../views/votes_show_open.erb:54
#: ../views/votes_edit.erb:47 ../views/votes_show_closed.erb:65
#: ../views/votes_show_open.erb:54
msgid "Add organizer"
msgstr "Afegeix organitzadora"
#: ../views/votes_edit.erb:57 ../views/votes_show_closed.erb:75
#: ../views/votes_edit.erb:57 ../views/votes_show_closed.erb:59
#: ../views/votes_show_open.erb:44
msgid "Actions for organizers"
msgstr "Accions per les organitzadores"
#: ../views/votes_edit.erb:61 ../views/votes_edit.erb:64
#: ../views/votes_edit.erb:60
msgid "Open vote to participants"
msgstr "Obrir la votació als participants"
#: ../views/votes_edit.erb:62
msgid "Add at least 2 candidates before opening the vote to participants."
msgstr "Afegeix com a mínim 2 candidats abans d'obrir la votació als participants"
#: ../views/votes_edit.erb:68
#: ../views/votes_edit.erb:63
msgid "Delete vote"
msgstr "Suprimir la votació"
@ -171,31 +155,31 @@ msgstr "Totes les valoracions"
msgid "Participant"
msgstr "Participant"
#: ../views/votes_show_closed.erb:27
#: ../views/votes_show_closed.erb:26
msgid "Results"
msgstr "Resultats"
#: ../views/votes_show_closed.erb:31
#: ../views/votes_show_closed.erb:30
msgid "Rank"
msgstr "Rang"
#: ../views/votes_show_closed.erb:32
#: ../views/votes_show_closed.erb:31
msgid "Candidate"
msgstr "Candidat"
#: ../views/votes_show_closed.erb:33
#: ../views/votes_show_closed.erb:32
msgid "Majority Judgment"
msgstr "Judici majoritari"
#: ../views/votes_show_closed.erb:34
#: ../views/votes_show_closed.erb:33
msgid "Proponents"
msgstr "Defensores"
#: ../views/votes_show_closed.erb:35
#: ../views/votes_show_closed.erb:34
msgid "Opponents"
msgstr "Detractores"
#: ../views/votes_show_closed.erb:78
#: ../views/votes_show_closed.erb:62
msgid "Reopen voting period"
msgstr "Reobrir el període de votació"
@ -215,30 +199,30 @@ msgstr "Tornar a l'esborrany de votació"
msgid "Close votes and show results"
msgstr "Tancar la votació i veure els resultats"
#: ../vote.rb:62
#: ../vote.rb:59
msgid "Awful"
msgstr "Molt malament"
#: ../vote.rb:63
#: ../vote.rb:60
msgid "Very bad"
msgstr "Malament"
#: ../vote.rb:64
#: ../vote.rb:61
msgid "Bad"
msgstr "Poc bé"
#: ../vote.rb:65
#: ../vote.rb:62
msgid "Mediocre"
msgstr "Mig bé"
#: ../vote.rb:66
#: ../vote.rb:63
msgid "Good"
msgstr "Bé"
#: ../vote.rb:67
#: ../vote.rb:64
msgid "Very good"
msgstr "Molt bé"
#: ../vote.rb:114
msgid "Incorrect email or password."
msgstr "Correu o contrasenya incorrecte."
#: ../vote.rb:65
msgid "Excellent"
msgstr "Excel·lent"

View file

@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-06 16:13-0600\n"
"PO-Revision-Date: 2025-04-06 16:13-0600\n"
"POT-Creation-Date: 2025-03-30 12:01-0600\n"
"PO-Revision-Date: 2025-03-30 12:01-0600\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
@ -18,7 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#: ../views/home.erb:1 ../views/layout.erb:13
#: ../views/home.erb:1 ../views/layout.erb:10
msgid "Home"
msgstr ""
@ -58,43 +58,31 @@ msgstr ""
msgid "Vote"
msgstr ""
#: ../views/layout.erb:12
#: ../views/layout.erb:9
msgid "Logged in as %{email}."
msgstr ""
#: ../views/layout.erb:12
#: ../views/layout.erb:9
msgid "Logout"
msgstr ""
#: ../views/layout.erb:15 ../views/login.erb:1 ../views/login.erb:16
#: ../views/layout.erb:12 ../views/login.erb:1 ../views/login.erb:14
msgid "Login"
msgstr ""
#: ../views/login.erb:9 ../views/signup.erb:24 ../views/votes_edit.erb:51
#: ../views/votes_show_closed.erb:85 ../views/votes_show_open.erb:58
#: ../views/login.erb:7 ../views/signup.erb:5 ../views/votes_edit.erb:51
#: ../views/votes_show_closed.erb:69 ../views/votes_show_open.erb:58
msgid "Email"
msgstr ""
#: ../views/login.erb:13 ../views/signup.erb:28
#: ../views/login.erb:11 ../views/signup.erb:9
msgid "Password"
msgstr ""
#: ../views/login.erb:18 ../views/signup.erb:1 ../views/signup.erb:31
#: ../views/login.erb:16 ../views/signup.erb:1 ../views/signup.erb:12
msgid "Create account"
msgstr ""
#: ../views/signup.erb:6
msgid "Specify a password."
msgstr ""
#: ../views/signup.erb:14
msgid "Email is not a valid email address."
msgstr ""
#: ../views/signup.erb:17
msgid "An account already exists for %{email}."
msgstr ""
#: ../views/votes_edit.erb:1
msgid "Edit draft vote"
msgstr ""
@ -129,34 +117,30 @@ msgid "Name"
msgstr ""
#: ../views/votes_edit.erb:36 ../views/votes_edit.erb:54
#: ../views/votes_show_closed.erb:81 ../views/votes_show_closed.erb:88
#: ../views/votes_show_open.erb:61
#: ../views/votes_show_closed.erb:72 ../views/votes_show_open.erb:61
msgid "Add"
msgstr ""
#: ../views/votes_edit.erb:39 ../views/votes_show_closed.erb:65
#: ../views/votes_edit.erb:39 ../views/votes_show_closed.erb:49
#: ../views/votes_show_draft.erb:5 ../views/votes_show_open.erb:34
msgid "Organizers"
msgstr ""
#: ../views/votes_edit.erb:47 ../views/votes_show_open.erb:54
#: ../views/votes_edit.erb:47 ../views/votes_show_closed.erb:65
#: ../views/votes_show_open.erb:54
msgid "Add organizer"
msgstr ""
#: ../views/votes_edit.erb:57 ../views/votes_show_closed.erb:75
#: ../views/votes_edit.erb:57 ../views/votes_show_closed.erb:59
#: ../views/votes_show_open.erb:44
msgid "Actions for organizers"
msgstr ""
#: ../views/votes_edit.erb:61 ../views/votes_edit.erb:64
#: ../views/votes_edit.erb:60
msgid "Open vote to participants"
msgstr ""
#: ../views/votes_edit.erb:62
msgid "Add at least 2 candidates before opening the vote to participants."
msgstr ""
#: ../views/votes_edit.erb:68
#: ../views/votes_edit.erb:63
msgid "Delete vote"
msgstr ""
@ -172,31 +156,31 @@ msgstr ""
msgid "Participant"
msgstr ""
#: ../views/votes_show_closed.erb:27
#: ../views/votes_show_closed.erb:26
msgid "Results"
msgstr ""
#: ../views/votes_show_closed.erb:31
#: ../views/votes_show_closed.erb:30
msgid "Rank"
msgstr ""
#: ../views/votes_show_closed.erb:32
#: ../views/votes_show_closed.erb:31
msgid "Candidate"
msgstr ""
#: ../views/votes_show_closed.erb:33
#: ../views/votes_show_closed.erb:32
msgid "Majority Judgment"
msgstr ""
#: ../views/votes_show_closed.erb:34
#: ../views/votes_show_closed.erb:33
msgid "Proponents"
msgstr ""
#: ../views/votes_show_closed.erb:35
#: ../views/votes_show_closed.erb:34
msgid "Opponents"
msgstr ""
#: ../views/votes_show_closed.erb:78
#: ../views/votes_show_closed.erb:62
msgid "Reopen voting period"
msgstr ""
@ -216,30 +200,30 @@ msgstr ""
msgid "Close votes and show results"
msgstr ""
#: ../vote.rb:62
#: ../vote.rb:59
msgid "Awful"
msgstr ""
#: ../vote.rb:63
#: ../vote.rb:60
msgid "Very bad"
msgstr ""
#: ../vote.rb:64
#: ../vote.rb:61
msgid "Bad"
msgstr ""
#: ../vote.rb:65
#: ../vote.rb:62
msgid "Mediocre"
msgstr ""
#: ../vote.rb:66
#: ../vote.rb:63
msgid "Good"
msgstr ""
#: ../vote.rb:67
#: ../vote.rb:64
msgid "Very good"
msgstr ""
#: ../vote.rb:114
msgid "Incorrect email or password."
#: ../vote.rb:65
msgid "Excellent"
msgstr ""

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3,9 +3,6 @@
<head>
<meta charset="utf-8" />
<title><%= _("Vote") %></title>
<script src="/chartkick.js"></script>
<script src="/Chart.bundle.js"></script>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<% if current_user %>

View file

@ -1,9 +1,7 @@
<h1><%= _("Login") %></h1>
<% if @error %>
<p class="error"><%= @error %></p>
<% end %>
<form action="/login" method="POST">
<p>
<label for="email"><%= _("Email") %></label>

View file

@ -1,32 +1,13 @@
<h1><%= _("Create account") %></h1>
<% if @errors %>
<% @errors.each do |error| %>
<% if error.attribute == :password and error.type == :blank %>
<p class="error"><%= _("Specify a password.") %></p>
<% end %>
<% end %>
<% end %>
<% if @user and @user.errors.any? %>
<% @user.errors.each do |error| %>
<% if error.attribute == :email and error.type == :invalid %>
<p class="error"><%= _("Email is not a valid email address.") %></p>
<% end %>
<% if error.attribute == :email and error.type == :taken %>
<p class="error"><%= _("An account already exists for %{email}.") % { email: @user.email } %></p>
<% end %>
<% end %>
<% end %>
<form action="/signup" method="post">
<p>
<label for="email"><%= _("Email") %></label>
<input type="text" name="email" value="<%= params[:email] %>">
<input type="text" name="email">
</p>
<p>
<label for="password"><%= _("Password") %></label>
<input type="password" name="password" value="<%= params[:password] %>">
<input type="password" name="password">
</p>
<button type="submit"><%= _("Create account") %></button>
</form>

View file

@ -1,9 +0,0 @@
.error {
color: red;
}
<% settings.values.each do |v| %>
.value-<%= v[:id] %> {
background: <%= v[:color] %>;
}
<% end %>

View file

@ -57,12 +57,7 @@
<h3><%= _("Actions for organizers") %></h2>
<form action="/votes/<%= @vote.secure_id %>/open" method="post">
<% if @vote.candidates.length < 2 %>
<button type="submit" disabled><%= _("Open vote to participants") %></button>
<p><%= _("Add at least 2 candidates before opening the vote to participants.") %></p>
<% else %>
<button type="submit"><%= _("Open vote to participants") %></button>
<% end %>
</form>
<form action="/votes/<%= @vote.secure_id %>/delete" method="post">
<button type="submit"><%= _("Delete vote") %></button>

View file

@ -16,8 +16,7 @@
<td><%= user.email %></td>
<% @vote.candidates.each do |candidate| %>
<% if rating = @vote.ratings.find { |rating| rating.user == user and rating.candidate == candidate } %>
<% value = settings.values.select { |e| e[:id] == rating.value }.first %>
<td class="value-<%= value[:id] %>"><%= value[:label] %></td>
<td><%= settings.values.select { |e| e[:id] == rating.value }.first[:label] %></td>
<% end %>
<% end %>
</tr>
@ -28,11 +27,11 @@
<table>
<tr>
<th><%= _("Rank") %></th>
<th><%= _("Candidate") %></th>
<th><%= _("Majority Judgment") %></th>
<th><%= _("Proponents") %></th>
<th><%= _("Opponents") %></th>
<td><%= _("Rank") %></td>
<td><%= _("Candidate") %></td>
<td><%= _("Majority Judgment") %></td>
<td><%= _("Proponents") %></td>
<td><%= _("Opponents") %></td>
</tr>
<% i = 0 %>
<% @vote.candidates.sort { |a, b| a.mj <=> b.mj }.reverse.each do |candidate| %>
@ -40,28 +39,13 @@
<tr>
<td><%= i %></td>
<td><%= candidate.name %></td>
<% value = settings.values.select { |e| e[:id] == candidate.mj.mj }.first %>
<td class="value-<%= value[:id] %>"><%= value[:label] %></td>
<td><%= settings.values.select { |e| e[:id] == candidate.mj.mj }.first[:label] %></td>
<td><%= candidate.mj.proponents %></td>
<td><%= candidate.mj.opponents %></td>
</tr>
<% end %>
</table>
<%
data = []
colors = []
settings.values.reverse.each do |v|
d = { name: v[:label], data: [] }
@vote.candidates.each do |c|
d[:data] << [c.name, c.mj.count[v[:id]]]
end
data << d
colors << v[:color]
end
%>
<%= bar_chart data, colors: colors, stacked: true, legend: 'bottom' %>
<h2><%= _("Organizers") %></h2>
<ul>

View file

@ -12,11 +12,11 @@
<li>
<p><%= candidate.name %></p>
<p><%= candidate.description %></p>
<ul>
<ol>
<% settings.values.reverse.each do |v| %>
<li><input type="radio" name="<%= candidate.id %>" id="<%= candidate.id %>-<%= v[:id] %>" value="<%= v[:id] %>" <% if value == v[:id] %>checked<% end %>><label for="<%= candidate.id %>-<%= v[:id] %>" class="value-<%= v[:id] %>"><%= v[:label] %></label></li>
<input type="radio" name="<%= candidate.id %>" id="<%= candidate.id %>-<%= v[:id] %>" value="<%= v[:id] %>" <% if value == v[:id] %>checked<% end %>><label for="<%= candidate.id %>-<%= v[:id] %>"><%= v[:label] %></label>
<% end %>
</ul>
</ol>
</li>
<% end %>
</ul>

View file

@ -3,7 +3,6 @@ require 'sinatra/activerecord'
require 'bcrypt'
require 'gettext'
require 'securerandom'
require 'chartkick'
require_relative 'mj'
class Vote < ActiveRecord::Base
@ -28,8 +27,6 @@ class User < ActiveRecord::Base
has_many :ratings
has_many :organizers
has_many :votes, through: :organizers
validates :email, uniqueness: true
validates :email, format: URI::MailTo::EMAIL_REGEXP
end
class Organizer < ActiveRecord::Base
@ -55,16 +52,17 @@ end
include GetText
set_output_charset('UTF-8')
bindtextdomain('vedia', 'locale')
bindtextdomain('vote', 'locale')
set_locale('ca')
enable :sessions
set :values, [ { :id => 1, :label => _("Awful"), :color => '#ff4500' },
{ :id => 2, :label => _("Very bad"), :color => '#ffa500' },
{ :id => 3, :label => _("Bad"), :color => '#ffff00' },
{ :id => 4, :label => _("Mediocre"), :color => '#9acd32' },
{ :id => 5, :label => _("Good"), :color => '#228b22' },
{ :id => 6, :label => _("Very good"), :color => '#006400' } ]
set :values, [ { :id => 1, :label => _("Awful") },
{ :id => 2, :label => _("Very bad") },
{ :id => 3, :label => _("Bad") },
{ :id => 4, :label => _("Mediocre") },
{ :id => 5, :label => _("Good") },
{ :id => 6, :label => _("Very good") },
{ :id => 7, :label => _("Excellent") } ]
MajorityJudgment.values = settings.values
get '/' do
@ -73,31 +71,14 @@ get '/' do
erb :home
end
get '/style.css' do
content_type 'text/css'
erb :style, :layout => false
end
get '/signup' do
erb :signup
end
post '/signup' do
@user = User.create(email: params[:email])
@errors = []
if params[:password].empty?
@errors << OpenStruct.new(:attribute => :password, :type => :blank)
else
@user.password = hash_password(params[:password])
end
if @errors.empty? and @user.valid?
@user.save
session.clear
session[:user_id] = @user.id
redirect '/'
else
erb :signup
end
@user = User.create(email: params[:email],
password: hash_password(params[:password]))
redirect '/'
end
get '/login' do
@ -111,7 +92,7 @@ post '/login' do
session[:user_id] = user.id
redirect '/'
else
@error = _("Incorrect email or password.")
@error = 'Username or password was incorrect'
erb :login
end
end
@ -200,10 +181,8 @@ post '/votes/:id/open' do
find_vote
require_organizer
require_draft_vote
if not @vote.candidates.length < 2
@vote.state = 'open'
@vote.save
end
@vote.state = 'open'
@vote.save
redirect '/votes/' + @vote.secure_id
end