Merge branch 'master' into api-dev-0.18.11
This commit is contained in:
@@ -901,16 +901,12 @@ img.avatar, img.admin-avatar, img.moderator-avatar, img.initialjs-avatar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.author-deleted, .user-deleted {
|
.author-deleted, .user-deleted {
|
||||||
background-color: rgba(255,255,255,.5);
|
|
||||||
color: rgba(0,0,0,.4);
|
color: rgba(0,0,0,.4);
|
||||||
font-size: rem-calc(40);
|
display: inline-block;
|
||||||
left: 11px;
|
font-size: rem-calc(32);
|
||||||
position: absolute;
|
line-height: rem-calc(32);
|
||||||
top: 72px;
|
height: rem-calc(32);
|
||||||
}
|
vertical-align: top;
|
||||||
|
|
||||||
.user-deleted {
|
|
||||||
top: -4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-permissions {
|
.user-permissions {
|
||||||
@@ -1069,10 +1065,6 @@ img.avatar, img.admin-avatar, img.moderator-avatar, img.initialjs-avatar {
|
|||||||
background: #C0392B;
|
background: #C0392B;
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-deleted {
|
|
||||||
background: #E7E7E7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.level-1 {
|
.level-1 {
|
||||||
background: #1ABC9C;
|
background: #1ABC9C;
|
||||||
}
|
}
|
||||||
@@ -1601,7 +1593,10 @@ table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.comment-body {
|
.comment-body {
|
||||||
margin-left: rem-calc(42);
|
|
||||||
|
img {
|
||||||
|
margin-right: $line-height/2;
|
||||||
|
}
|
||||||
|
|
||||||
.reply {
|
.reply {
|
||||||
background: white;
|
background: white;
|
||||||
@@ -1609,20 +1604,28 @@ table {
|
|||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
font-size: $small-font-size;
|
font-size: $small-font-size;
|
||||||
margin: rem-calc(6) 0;
|
margin: $line-height/4 0;
|
||||||
padding: rem-calc(6);
|
padding: $line-height/4;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
a.relative, [class^="icon-arrow"] {
|
||||||
|
padding-left: $line-height/2;
|
||||||
|
}
|
||||||
|
|
||||||
[class^="icon-arrow"] {
|
[class^="icon-arrow"] {
|
||||||
font-size: rem-calc(18);
|
font-size: $base-font-size;
|
||||||
left: -20px;
|
left: -20px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
color: $text-light;
|
color: $text-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin-top: $line-height/2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-user {
|
.comment-user {
|
||||||
@@ -1650,27 +1653,19 @@ table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-deleted {
|
|
||||||
background: #E7E7E7;
|
|
||||||
margin-left: rem-calc(42);
|
|
||||||
padding: $line-height/4 $line-height/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.comment-children {
|
.comment-children {
|
||||||
border-left: 1px dashed $border;
|
border-left: 1px dashed $border;
|
||||||
margin-left: rem-calc(42);
|
display: inline-block;
|
||||||
padding-left: $line-height/4;
|
margin-left: rem-calc(16);
|
||||||
|
padding-left: rem-calc(8);
|
||||||
@media only screen and (max-width: 40em) {
|
width: 100%;
|
||||||
margin-left: rem-calc(16);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-info {
|
.comment-info {
|
||||||
color: $text-medium;
|
color: $text-medium;
|
||||||
|
display: inline-block;
|
||||||
font-size: $small-font-size;
|
font-size: $small-font-size;
|
||||||
margin-top: $line-height/4;
|
line-height: rem-calc(32); // Same as avatar height
|
||||||
vertical-align: middle;
|
|
||||||
|
|
||||||
span.user-name {
|
span.user-name {
|
||||||
color: $text;
|
color: $text;
|
||||||
@@ -1703,6 +1698,11 @@ table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.comment-form {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
// 16. Flags
|
// 16. Flags
|
||||||
// ---------
|
// ---------
|
||||||
|
|
||||||
|
|||||||
@@ -325,9 +325,13 @@
|
|||||||
clear: both;
|
clear: both;
|
||||||
color: $text-medium;
|
color: $text-medium;
|
||||||
font-size: $small-font-size;
|
font-size: $small-font-size;
|
||||||
min-height: $line-height*2;
|
margin-bottom: $line-height/2;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
span {
|
||||||
|
line-height: rem-calc(32); // Same as avatar height
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $text-medium;
|
color: $text-medium;
|
||||||
}
|
}
|
||||||
@@ -337,15 +341,6 @@
|
|||||||
line-height: $line-height;
|
line-height: $line-height;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.author-deleted {
|
|
||||||
left: 0;
|
|
||||||
top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.author.deleted {
|
|
||||||
margin-left: rem-calc(48);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.debate-description, .proposal-description {
|
.debate-description, .proposal-description {
|
||||||
@@ -370,9 +365,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.author-photo {
|
.author-photo {
|
||||||
line-height: $line-height*2;
|
line-height: rem-calc(32);
|
||||||
margin-right: rem-calc(6);
|
margin-right: rem-calc(6);
|
||||||
vertical-align: middle;
|
vertical-align: top;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
32
app/controllers/admin/signature_sheets_controller.rb
Normal file
32
app/controllers/admin/signature_sheets_controller.rb
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
class Admin::SignatureSheetsController < Admin::BaseController
|
||||||
|
|
||||||
|
def index
|
||||||
|
@signature_sheets = SignatureSheet.all
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@signature_sheet = SignatureSheet.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@signature_sheet = SignatureSheet.new(signature_sheet_params)
|
||||||
|
@signature_sheet.author = current_user
|
||||||
|
if @signature_sheet.save
|
||||||
|
@signature_sheet.delay.verify_signatures
|
||||||
|
redirect_to [:admin, @signature_sheet], notice: I18n.t('flash.actions.create.signature_sheet')
|
||||||
|
else
|
||||||
|
render :new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
@signature_sheet = SignatureSheet.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def signature_sheet_params
|
||||||
|
params.require(:signature_sheet).permit(:signable_type, :signable_id, :document_numbers)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
8
app/helpers/signature_sheets_helper.rb
Normal file
8
app/helpers/signature_sheets_helper.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module SignatureSheetsHelper
|
||||||
|
|
||||||
|
def signable_options
|
||||||
|
[[t("activerecord.models.proposal", count: 1), Proposal],
|
||||||
|
[t("activerecord.models.spending_proposal", count: 1), SpendingProposal]]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -51,7 +51,7 @@ class Proposal < ActiveRecord::Base
|
|||||||
scope :last_week, -> { where("proposals.created_at >= ?", 7.days.ago)}
|
scope :last_week, -> { where("proposals.created_at >= ?", 7.days.ago)}
|
||||||
scope :retired, -> { where.not(retired_at: nil) }
|
scope :retired, -> { where.not(retired_at: nil) }
|
||||||
scope :not_retired, -> { where(retired_at: nil) }
|
scope :not_retired, -> { where(retired_at: nil) }
|
||||||
scope :successfull, -> { where("cached_votes_up + physical_votes >= ?", Proposal.votes_needed_for_success)}
|
scope :successfull, -> { where("cached_votes_up >= ?", Proposal.votes_needed_for_success)}
|
||||||
|
|
||||||
def to_param
|
def to_param
|
||||||
"#{id}-#{title}".parameterize
|
"#{id}-#{title}".parameterize
|
||||||
@@ -100,7 +100,7 @@ class Proposal < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def total_votes
|
def total_votes
|
||||||
cached_votes_up + physical_votes
|
cached_votes_up
|
||||||
end
|
end
|
||||||
|
|
||||||
def voters
|
def voters
|
||||||
|
|||||||
92
app/models/signature.rb
Normal file
92
app/models/signature.rb
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
class Signature < ActiveRecord::Base
|
||||||
|
belongs_to :signature_sheet
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
validates :document_number, presence: true
|
||||||
|
validates :signature_sheet, presence: true
|
||||||
|
|
||||||
|
scope :verified, -> { where(verified: true) }
|
||||||
|
scope :unverified, -> { where(verified: false) }
|
||||||
|
|
||||||
|
delegate :signable, to: :signature_sheet
|
||||||
|
|
||||||
|
before_validation :clean_document_number
|
||||||
|
|
||||||
|
def verified?
|
||||||
|
user_exists? || in_census?
|
||||||
|
end
|
||||||
|
|
||||||
|
def verify
|
||||||
|
if verified?
|
||||||
|
assign_vote
|
||||||
|
mark_as_verified
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_vote
|
||||||
|
if user_exists?
|
||||||
|
assign_vote_to_user
|
||||||
|
else
|
||||||
|
create_user
|
||||||
|
assign_vote_to_user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_vote_to_user
|
||||||
|
set_user
|
||||||
|
signable.register_vote(user, "yes")
|
||||||
|
assign_signature_to_vote
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_signature_to_vote
|
||||||
|
vote = Vote.where(votable: signable, voter: user).first
|
||||||
|
vote.update(signature: self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_exists?
|
||||||
|
User.where(document_number: document_number).any?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_user
|
||||||
|
user_params = {
|
||||||
|
document_number: document_number,
|
||||||
|
created_from_signature: true,
|
||||||
|
verified_at: Time.now,
|
||||||
|
erased_at: Time.now,
|
||||||
|
password: random_password,
|
||||||
|
terms_of_service: '1',
|
||||||
|
email: nil
|
||||||
|
}
|
||||||
|
User.create!(user_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def clean_document_number
|
||||||
|
return if self.document_number.blank?
|
||||||
|
self.document_number = self.document_number.gsub(/[^a-z0-9]+/i, "").upcase
|
||||||
|
end
|
||||||
|
|
||||||
|
def random_password
|
||||||
|
(0...20).map { ('a'..'z').to_a[rand(26)] }.join
|
||||||
|
end
|
||||||
|
|
||||||
|
def in_census?
|
||||||
|
response = document_types.detect do |document_type|
|
||||||
|
CensusApi.new.call(document_type, document_number).valid?
|
||||||
|
end
|
||||||
|
response.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_user
|
||||||
|
user = User.where(document_number: document_number).first
|
||||||
|
update(user: user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def mark_as_verified
|
||||||
|
update(verified: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def document_types
|
||||||
|
%w(1 2 3 4)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
38
app/models/signature_sheet.rb
Normal file
38
app/models/signature_sheet.rb
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
class SignatureSheet < ActiveRecord::Base
|
||||||
|
belongs_to :signable, polymorphic: true
|
||||||
|
belongs_to :author, class_name: 'User', foreign_key: 'author_id'
|
||||||
|
|
||||||
|
VALID_SIGNABLES = %w( Proposal SpendingProposal )
|
||||||
|
|
||||||
|
has_many :signatures
|
||||||
|
|
||||||
|
validates :author, presence: true
|
||||||
|
validates :signable_type, inclusion: {in: VALID_SIGNABLES}
|
||||||
|
validates :document_numbers, presence: true
|
||||||
|
validates :signable, presence: true
|
||||||
|
validate :signable_found
|
||||||
|
|
||||||
|
def name
|
||||||
|
"#{signable_name} #{signable_id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def signable_name
|
||||||
|
I18n.t("activerecord.models.#{signable_type.underscore}", count: 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def verify_signatures
|
||||||
|
parsed_document_numbers.each do |document_number|
|
||||||
|
signature = self.signatures.where(document_number: document_number).first_or_create
|
||||||
|
signature.verify
|
||||||
|
end
|
||||||
|
update(processed: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def parsed_document_numbers
|
||||||
|
document_numbers.split(/\r\n|\n|[,]/).collect {|d| d.gsub(/\s+/, '') }
|
||||||
|
end
|
||||||
|
|
||||||
|
def signable_found
|
||||||
|
errors.add(:signable_id, :not_found) if errors.messages[:signable].present?
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -35,6 +35,14 @@
|
|||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% if feature?(:signature_sheets) %>
|
||||||
|
<li <%= "class=active" if controller_name == "signature_sheets" %>>
|
||||||
|
<%= link_to admin_signature_sheets_path do %>
|
||||||
|
<span class="icon-budget"></span><%= t("admin.menu.signature_sheets") %>
|
||||||
|
<% end %>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<li <%= "class=active" if controller_name == "banners" %>>
|
<li <%= "class=active" if controller_name == "banners" %>>
|
||||||
<%= link_to admin_banners_path do %>
|
<%= link_to admin_banners_path do %>
|
||||||
<span class="icon-eye"></span><%= t("admin.menu.banner") %>
|
<span class="icon-eye"></span><%= t("admin.menu.banner") %>
|
||||||
|
|||||||
31
app/views/admin/signature_sheets/index.html.erb
Normal file
31
app/views/admin/signature_sheets/index.html.erb
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<h2 class="inline-block"><%= t("admin.signature_sheets.index.title") %></h2>
|
||||||
|
|
||||||
|
<%= link_to t("admin.signature_sheets.index.new"), new_admin_signature_sheet_path,
|
||||||
|
class: "button success float-right" %>
|
||||||
|
|
||||||
|
<% if @signature_sheets.any? %>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th><%= t("admin.signature_sheets.name") %></th>
|
||||||
|
<th><%= t("admin.signature_sheets.author") %></th>
|
||||||
|
<th><%= t("admin.signature_sheets.created_at") %></th>
|
||||||
|
</tr>
|
||||||
|
<% @signature_sheets.each do |signature_sheet| %>
|
||||||
|
<tr id="<%= dom_id(signature_sheet) %>" class="signature_sheet">
|
||||||
|
<td>
|
||||||
|
<%= link_to signature_sheet.name, [:admin, signature_sheet] %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%= signature_sheet.author.name %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%= l(signature_sheet.created_at, format: :short) %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
<% else %>
|
||||||
|
<div class="callout primary margin-top">
|
||||||
|
<%= t("admin.signature_sheets.no_signature_sheets") %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
22
app/views/admin/signature_sheets/new.html.erb
Normal file
22
app/views/admin/signature_sheets/new.html.erb
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<%= render 'shared/back_link' %>
|
||||||
|
|
||||||
|
<h2><%= t("admin.signature_sheets.new.title") %></h2>
|
||||||
|
|
||||||
|
<%= form_for [:admin, @signature_sheet] do |f| %>
|
||||||
|
<%= render 'shared/errors',
|
||||||
|
resource: @signature_sheet %>
|
||||||
|
|
||||||
|
<div class="small-12 medium-6 large-4">
|
||||||
|
<%= f.select :signable_type, signable_options %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="small-12 medium-6 large-4">
|
||||||
|
<%= f.text_field :signable_id %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= f.label :document_numbers %>
|
||||||
|
<p class="note"><%= t("admin.signature_sheets.new.document_numbers_note") %></p>
|
||||||
|
<%= f.text_area :document_numbers, rows: "6", label: false %>
|
||||||
|
|
||||||
|
<%= f.submit(class: "button", value: t("admin.signature_sheets.new.submit")) %>
|
||||||
|
<% end %>
|
||||||
44
app/views/admin/signature_sheets/show.html.erb
Normal file
44
app/views/admin/signature_sheets/show.html.erb
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<h2 class="inline-block"><%= @signature_sheet.name %></h2>
|
||||||
|
|
||||||
|
<div class="callout secondary float-right">
|
||||||
|
<%= t("admin.signature_sheets.show.created_at") %>
|
||||||
|
<strong><%= l(@signature_sheet.created_at, format: :short) %></strong>
|
||||||
|
<span class="bullet"> • </span>
|
||||||
|
<%= t("admin.signature_sheets.show.author") %>
|
||||||
|
<strong><%= @signature_sheet.author.name %></strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 id="document_count" class="block">
|
||||||
|
<%= t("admin.signature_sheets.show.document_count") %>
|
||||||
|
<%= @signature_sheet.signatures.count %>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="callout margin-top">
|
||||||
|
<p><strong><%= t("admin.signature_sheets.show.documents") %></strong></p>
|
||||||
|
<%= simple_format @signature_sheet.document_numbers %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="verified_signatures" class="callout success">
|
||||||
|
<strong>
|
||||||
|
<%= t("admin.signature_sheets.show.verified",
|
||||||
|
count: @signature_sheet.signatures.verified.count ) %>
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="unverified_signatures" class="callout alert">
|
||||||
|
<p>
|
||||||
|
<strong>
|
||||||
|
<%= t("admin.signature_sheets.show.unverified",
|
||||||
|
count: @signature_sheet.signatures.unverified.count ) %>
|
||||||
|
<%= t("admin.signature_sheets.show.unverified_error") %>
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
|
<%= @signature_sheet.signatures.unverified.map(&:document_number).join(", ") %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% unless @signature_sheet.processed? %>
|
||||||
|
<div class="callout primary margin-top">
|
||||||
|
<%= t("admin.signature_sheets.show.loading") %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
<% cache [locale_and_user_status(comment), comment, commentable_cache_key(comment.commentable), comment.author, (@comment_flags[comment.id] if @comment_flags)] do %>
|
<% cache [locale_and_user_status(comment), comment, commentable_cache_key(comment.commentable), comment.author, (@comment_flags[comment.id] if @comment_flags)] do %>
|
||||||
<div class="row">
|
<ul id="<%= dom_id(comment) %>" class="comment no-bullet small-12">
|
||||||
<ul id="<%= dom_id(comment) %>" class="comment no-bullet small-12 column">
|
<li class="comment-body">
|
||||||
|
|
||||||
<% if comment.hidden? || comment.user.hidden? %>
|
<% if comment.hidden? || comment.user.hidden? %>
|
||||||
<% if comment.children.size > 0 %>
|
<% if comment.children.size > 0 %>
|
||||||
<div class="is-deleted">
|
<div class="callout secondary">
|
||||||
<p><%= t("comments.comment.deleted") %></p>
|
<p><%= t("comments.comment.deleted") %></p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -23,82 +22,84 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<li class="comment-body">
|
<div class="comment-info">
|
||||||
<div class="comment-info">
|
|
||||||
|
|
||||||
<% if comment.as_administrator? %>
|
<% if comment.as_administrator? %>
|
||||||
<span class="user-name"><%= t("comments.comment.admin") %> #<%= comment.administrator_id%></span>
|
<span class="user-name"><%= t("comments.comment.admin") %> #<%= comment.administrator_id%></span>
|
||||||
<% elsif comment.as_moderator? %>
|
<% elsif comment.as_moderator? %>
|
||||||
<span class="user-name"><%= t("comments.comment.moderator") %> #<%= comment.moderator_id%></span>
|
<span class="user-name"><%= t("comments.comment.moderator") %> #<%= comment.moderator_id%></span>
|
||||||
|
<% else %>
|
||||||
|
|
||||||
|
<% if comment.user.hidden? || comment.user.erased? %>
|
||||||
|
<span class="user-name"><%= t("comments.comment.user_deleted") %></span>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
<span class="user-name"><%= link_to comment.user.name, user_path(comment.user) %></span>
|
||||||
<% if comment.user.hidden? || comment.user.erased? %>
|
<% if comment.user.display_official_position_badge? %>
|
||||||
<span class="user-name"><%= t("comments.comment.user_deleted") %></span>
|
|
||||||
<% else %>
|
|
||||||
<span class="user-name"><%= link_to comment.user.name, user_path(comment.user) %></span>
|
|
||||||
<% if comment.user.display_official_position_badge? %>
|
|
||||||
•
|
|
||||||
<span class="label round level-<%= comment.user.official_level %>">
|
|
||||||
<%= comment.user.official_position %>
|
|
||||||
</span>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
<% if comment.user.verified_organization? %>
|
|
||||||
•
|
•
|
||||||
<span class="label round is-association">
|
<span class="label round level-<%= comment.user.official_level %>">
|
||||||
<%= t("shared.collective") %>
|
<%= comment.user.official_position %>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if comment.user_id == comment.commentable.author_id %>
|
<% end %>
|
||||||
•
|
<% if comment.user.verified_organization? %>
|
||||||
<span class="label round is-author">
|
•
|
||||||
<%= t("comments.comment.author") %>
|
<span class="label round is-association">
|
||||||
</span>
|
<%= t("shared.collective") %>
|
||||||
<% end %>
|
</span>
|
||||||
|
<% end %>
|
||||||
|
<% if comment.user_id == comment.commentable.author_id %>
|
||||||
|
•
|
||||||
|
<span class="label round is-author">
|
||||||
|
<%= t("comments.comment.author") %>
|
||||||
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
• <time><%= l comment.created_at.to_datetime, format: :datetime %></time>
|
<% end %>
|
||||||
|
|
||||||
|
• <span><%= l comment.created_at.to_datetime, format: :datetime %></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="comment-user
|
||||||
|
<%= user_level_class comment %>
|
||||||
|
<%= comment_author_class comment, comment.commentable.author_id %>">
|
||||||
|
<%= simple_format text_with_links(comment.body), {}, sanitize: false %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="<%= dom_id(comment) %>_reply" class="reply">
|
||||||
|
<div id="<%= dom_id(comment) %>_votes" class="comment-votes float-right">
|
||||||
|
<%= render 'comments/votes', comment: comment %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="comment-user
|
<% if comment.children.size > 0 %>
|
||||||
<%= user_level_class comment %>
|
<%= link_to "#{dom_id(comment)}", class: "js-toggle-children relative", data: {'id': "#{dom_id(comment)}"} do %>
|
||||||
<%= comment_author_class comment, comment.commentable.author_id %>">
|
<span class="sr-only js-child-toggle" style="display: none;"><%= t("shared.show") %></span>
|
||||||
<%= simple_format text_with_links(comment.body), {}, sanitize: false %>
|
<span class="sr-only js-child-toggle"><%= t("shared.hide") %></span>
|
||||||
</div>
|
<span id="<%= dom_id(comment) %>_children_arrow" class="icon-arrow-down"></span> <%= t("comments.comment.responses", count: comment.children.size) %>
|
||||||
|
|
||||||
<div id="<%= dom_id(comment) %>_reply" class="reply">
|
|
||||||
<span id="<%= dom_id(comment) %>_votes" class="comment-votes float-right">
|
|
||||||
<%= render 'comments/votes', comment: comment %>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<% if comment.children.size > 0 %>
|
|
||||||
<%= link_to "", class: "js-toggle-children relative", data: {'id': "#{dom_id(comment)}"} do %>
|
|
||||||
<span class="sr-only js-child-toggle" style="display: none;"><%= t("shared.show") %></span>
|
|
||||||
<span class="sr-only js-child-toggle"><%= t("shared.hide") %></span>
|
|
||||||
<span id="<%= dom_id(comment) %>_children_arrow" class="icon-arrow-down"></span> <%= t("comments.comment.responses", count: comment.children.size) %>
|
|
||||||
<% end %>
|
|
||||||
<% else %>
|
|
||||||
<%= t("comments.comment.responses", count: 0) %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= t("comments.comment.responses", count: 0) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<% if user_signed_in? %>
|
<% if user_signed_in? %>
|
||||||
<span class="divider"> | </span>
|
<span class="divider"> | </span>
|
||||||
<%= link_to(comment_link_text(comment), "",
|
<%= link_to(comment_link_text(comment), "",
|
||||||
class: "js-add-comment-link", data: {'id': dom_id(comment)}) %>
|
class: "js-add-comment-link", data: {'id': dom_id(comment)}) %>
|
||||||
|
|
||||||
<%= render 'comments/actions', comment: comment %>
|
<%= render 'comments/actions', comment: comment %>
|
||||||
|
|
||||||
<%= render 'comments/form', {commentable: comment.commentable, parent_id: comment.id, toggeable: true} %>
|
<%= render 'comments/form', {commentable: comment.commentable, parent_id: comment.id, toggeable: true} %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
<ul id="<%= dom_id(comment) %>_children" class="no-bullet comment-children">
|
<ul id="<%= dom_id(comment) %>_children" class="no-bullet comment-children">
|
||||||
<% child_comments_of(comment).each do |child| %>
|
<% child_comments_of(comment).each do |child| %>
|
||||||
<%= render 'comments/comment', comment: child %>
|
<li>
|
||||||
|
<%= render 'comments/comment', comment: child %>
|
||||||
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
</ul>
|
</li>
|
||||||
</div>
|
</ul>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<% cache [locale_and_user_status, parent_id, commentable_cache_key(commentable)] do %>
|
<% cache [locale_and_user_status, parent_id, commentable_cache_key(commentable)] do %>
|
||||||
<% css_id = parent_or_commentable_dom_id(parent_id, commentable) %>
|
<% css_id = parent_or_commentable_dom_id(parent_id, commentable) %>
|
||||||
<div id="js-comment-form-<%= css_id %>" <%= "style='display:none'".html_safe if toggeable %>>
|
<div id="js-comment-form-<%= css_id %>" <%= "style='display:none'".html_safe if toggeable %> class="comment-form">
|
||||||
<%= form_for Comment.new, remote: true do |f| %>
|
<%= form_for Comment.new, remote: true do |f| %>
|
||||||
<%= label_tag "comment-body-#{css_id}", t("comments.form.leave_comment") %>
|
<%= label_tag "comment-body-#{css_id}", t("comments.form.leave_comment") %>
|
||||||
<%= f.text_area :body, id: "comment-body-#{css_id}", maxlength: Comment.body_max_length, label: false %>
|
<%= f.text_area :body, id: "comment-body-#{css_id}", maxlength: Comment.body_max_length, label: false %>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<%= form_for(@debate) do |f| %>
|
<%= form_for(@debate) do |f| %>
|
||||||
|
|
||||||
|
|
||||||
<%= render 'shared/errors', resource: @debate %>
|
<%= render 'shared/errors', resource: @debate %>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
5
app/views/layouts/_meta_tags.html.erb
Normal file
5
app/views/layouts/_meta_tags.html.erb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<meta name="description"
|
||||||
|
content="<%= content_for?(:meta_description) ? yield(:meta_description) : setting["meta_description"] %>" />
|
||||||
|
|
||||||
|
<meta name="keywords"
|
||||||
|
content="<%= content_for?(:meta_keywords) ? yield(:meta_keywords) : setting["meta_keywords"] %>" />
|
||||||
@@ -4,7 +4,8 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<%=render "layouts/tracking_data"%>
|
<%= render "layouts/tracking_data" %>
|
||||||
|
<%= render "layouts/meta_tags" %>
|
||||||
<title><%= content_for?(:title) ? yield(:title) : setting['org_name'] %></title>
|
<title><%= content_for?(:title) ? yield(:title) : setting['org_name'] %></title>
|
||||||
<%= stylesheet_link_tag "application" %>
|
<%= stylesheet_link_tag "application" %>
|
||||||
<!--[if lt IE 9]>
|
<!--[if lt IE 9]>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<title><%= content_for?(:title) ? yield(:title) : "Gobierno abierto" %></title>
|
<title><%= content_for?(:title) ? yield(:title) : "Gobierno abierto" %></title>
|
||||||
|
<%= render "layouts/meta_tags" %>
|
||||||
<%= stylesheet_link_tag "application" %>
|
<%= stylesheet_link_tag "application" %>
|
||||||
<%= javascript_include_tag "application", 'data-turbolinks-track' => true %>
|
<%= javascript_include_tag "application", 'data-turbolinks-track' => true %>
|
||||||
<%= csrf_meta_tags %>
|
<%= csrf_meta_tags %>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<div class="relative">
|
<div class="relative">
|
||||||
<%= link_to t("shared.advanced_search.title"), "#", id: 'js-advanced-search-title', class: "advanced-search small" %>
|
<%= link_to t("shared.advanced_search.title"), "#advanced_search_form", id: 'js-advanced-search-title', class: "advanced-search small" %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row advanced-search-form">
|
<div class="row advanced-search-form">
|
||||||
<%= form_tag search_path, method: :get do %>
|
<%= form_tag search_path, id: "advanced_search_form", method: :get do %>
|
||||||
<div id='js-advanced-search' data-advanced-search-terms=<%= @advanced_search_terms.present? %> style="display: none">
|
<div id='js-advanced-search' data-advanced-search-terms=<%= @advanced_search_terms.present? %> style="display: none">
|
||||||
|
|
||||||
<div class="small-12 column">
|
<div class="small-12 column">
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<%= text_field_tag 'advanced_search[date_min]',
|
<%= text_field_tag 'advanced_search[date_min]',
|
||||||
params[:advanced_search].try(:[], :date_min),
|
params[:advanced_search].try(:[], :date_min),
|
||||||
|
type: "date",
|
||||||
placeholder: t("shared.advanced_search.date_placeholder"),
|
placeholder: t("shared.advanced_search.date_placeholder"),
|
||||||
class: 'js-calendar' %>
|
class: 'js-calendar' %>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<%= text_field_tag 'advanced_search[date_max]',
|
<%= text_field_tag 'advanced_search[date_max]',
|
||||||
params[:advanced_search].try(:[], :date_max),
|
params[:advanced_search].try(:[], :date_max),
|
||||||
|
type: "date",
|
||||||
placeholder: t("shared.advanced_search.date_placeholder"),
|
placeholder: t("shared.advanced_search.date_placeholder"),
|
||||||
class: 'js-calendar' %>
|
class: 'js-calendar' %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<%= t("verification.letter.new.office",
|
<%= t("verification.letter.new.office",
|
||||||
office: link_to(t("verification.letter.new.offices"), t("verification.letter.new.offices_url"),
|
office: link_to(t("verification.letter.new.offices"), setting['verification_offices_url'],
|
||||||
target: "blank")).html_safe %>
|
target: "blank")).html_safe %>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<div data-alert class="callout success">
|
<div data-alert class="callout success">
|
||||||
<%= t("verification.letter.create.flash.success_html",
|
<%= t("verification.letter.create.flash.success_html",
|
||||||
offices: link_to(t("verification.letter.create.flash.offices"),
|
offices: link_to(t("verification.letter.create.flash.offices"),
|
||||||
t("verification.letter.create.flash.offices_url"),
|
setting['verification_offices_url'],
|
||||||
title: t('shared.target_blank_html'),
|
title: t('shared.target_blank_html'),
|
||||||
target: "_blank")).html_safe
|
target: "_blank")).html_safe
|
||||||
%>
|
%>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<%= t("verification.residence.new.error_verifying_census",
|
<%= t("verification.residence.new.error_verifying_census",
|
||||||
offices: link_to( t("verification.residence.new.error_verifying_census_offices"),
|
offices: link_to( t("verification.residence.new.error_verifying_census_offices"),
|
||||||
t("verification.residence.new.error_verifying_census_offices_url"), title: t('shared.target_blank_html'), target: "_blank")).html_safe %>
|
setting['verification_offices_url'], title: t('shared.target_blank_html'), target: "_blank")).html_safe %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% else %>
|
<% else %>
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ set :keep_releases, 5
|
|||||||
set :local_user, ENV['USER']
|
set :local_user, ENV['USER']
|
||||||
|
|
||||||
set :delayed_job_workers, 2
|
set :delayed_job_workers, 2
|
||||||
|
set :delayed_job_roles, :background
|
||||||
|
|
||||||
set(:config_files, %w(
|
set(:config_files, %w(
|
||||||
log_rotation
|
log_rotation
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ set :ssh_options, port: deploysecret(:ssh_port)
|
|||||||
set :stage, :preproduction
|
set :stage, :preproduction
|
||||||
set :rails_env, :preproduction
|
set :rails_env, :preproduction
|
||||||
|
|
||||||
server deploysecret(:server1), user: deploysecret(:user), roles: %w(web app db importer cron)
|
server deploysecret(:server1), user: deploysecret(:user), roles: %w(web app db importer cron background)
|
||||||
server deploysecret(:server2), user: deploysecret(:user), roles: %w(web app db importer)
|
server deploysecret(:server2), user: deploysecret(:user), roles: %w(web app db importer)
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ set :stage, :production
|
|||||||
set :rails_env, :production
|
set :rails_env, :production
|
||||||
|
|
||||||
#server deploysecret(:server1), user: deploysecret(:user), roles: %w(web app db importer)
|
#server deploysecret(:server1), user: deploysecret(:user), roles: %w(web app db importer)
|
||||||
server deploysecret(:server2), user: deploysecret(:user), roles: %w(web app db importer cron)
|
server deploysecret(:server2), user: deploysecret(:user), roles: %w(web app db importer cron background)
|
||||||
server deploysecret(:server3), user: deploysecret(:user), roles: %w(web app db importer)
|
server deploysecret(:server3), user: deploysecret(:user), roles: %w(web app db importer)
|
||||||
server deploysecret(:server4), user: deploysecret(:user), roles: %w(web app db importer)
|
server deploysecret(:server4), user: deploysecret(:user), roles: %w(web app db importer)
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ search:
|
|||||||
# - '{devise,simple_form}.*'
|
# - '{devise,simple_form}.*'
|
||||||
ignore_missing:
|
ignore_missing:
|
||||||
- 'unauthorized.*'
|
- 'unauthorized.*'
|
||||||
|
- 'activerecord.models.proposal'
|
||||||
|
- 'activerecord.models.spending_proposal'
|
||||||
- 'activerecord.errors.models.proposal_notification.*'
|
- 'activerecord.errors.models.proposal_notification.*'
|
||||||
- 'activerecord.errors.models.direct_message.*'
|
- 'activerecord.errors.models.direct_message.*'
|
||||||
- 'errors.messages.blank'
|
- 'errors.messages.blank'
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ end
|
|||||||
Delayed::Worker.destroy_failed_jobs = false
|
Delayed::Worker.destroy_failed_jobs = false
|
||||||
Delayed::Worker.sleep_delay = 2
|
Delayed::Worker.sleep_delay = 2
|
||||||
Delayed::Worker.max_attempts = 3
|
Delayed::Worker.max_attempts = 3
|
||||||
Delayed::Worker.max_run_time = 30.seconds
|
Delayed::Worker.max_run_time = 30.minutes
|
||||||
Delayed::Worker.read_ahead = 10
|
Delayed::Worker.read_ahead = 10
|
||||||
Delayed::Worker.default_queue_name = 'default'
|
Delayed::Worker.default_queue_name = 'default'
|
||||||
Delayed::Worker.raise_signal_exceptions = :term
|
Delayed::Worker.raise_signal_exceptions = :term
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ Devise.setup do |config|
|
|||||||
# Configure the e-mail address which will be shown in Devise::Mailer,
|
# Configure the e-mail address which will be shown in Devise::Mailer,
|
||||||
# note that it will be overwritten if you use your own mailer class
|
# note that it will be overwritten if you use your own mailer class
|
||||||
# with default "from" parameter.
|
# with default "from" parameter.
|
||||||
if Rails.env.test?
|
if Rails.env.test? || !ActiveRecord::Base.connection.table_exists?('settings')
|
||||||
config.mailer_sender = "noreply@example.org"
|
config.mailer_sender = "noreply@consul.dev"
|
||||||
else
|
else
|
||||||
config.mailer_sender = "#{Setting['mailer_from_name']} <#{Setting['mailer_from_address']}>"
|
config.mailer_sender = "#{Setting['mailer_from_name']} <#{Setting['mailer_from_address']}>"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
ActsAsVotable::Vote.class_eval do
|
ActsAsVotable::Vote.class_eval do
|
||||||
|
belongs_to :signature
|
||||||
|
|
||||||
def self.for_debates(debates)
|
def self.for_debates(debates)
|
||||||
where(votable_type: 'Debate', votable_id: debates)
|
where(votable_type: 'Debate', votable_id: debates)
|
||||||
end
|
end
|
||||||
@@ -14,4 +16,5 @@ ActsAsVotable::Vote.class_eval do
|
|||||||
def value
|
def value
|
||||||
vote_flag
|
vote_flag
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ en:
|
|||||||
external_url: "Link to additional documentation"
|
external_url: "Link to additional documentation"
|
||||||
geozone_id: "Scope of operation"
|
geozone_id: "Scope of operation"
|
||||||
title: "Title"
|
title: "Title"
|
||||||
|
signature_sheet:
|
||||||
|
signable_type: "Signable type"
|
||||||
|
signable_id: "Signable ID"
|
||||||
|
document_numbers: "Documents numbers"
|
||||||
errors:
|
errors:
|
||||||
models:
|
models:
|
||||||
user:
|
user:
|
||||||
@@ -90,4 +94,9 @@ en:
|
|||||||
proposal_notification:
|
proposal_notification:
|
||||||
attributes:
|
attributes:
|
||||||
minimum_interval:
|
minimum_interval:
|
||||||
invalid: "You have to wait a minium of %{interval} days between notifications"
|
invalid: "You have to wait a minium of %{interval} days between notifications"
|
||||||
|
signature:
|
||||||
|
attributes:
|
||||||
|
document_number:
|
||||||
|
not_in_census: 'Not verified by Census'
|
||||||
|
already_voted: 'Already voted this proposal'
|
||||||
@@ -69,6 +69,10 @@ es:
|
|||||||
external_url: "Enlace a documentación adicional"
|
external_url: "Enlace a documentación adicional"
|
||||||
geozone_id: "Ámbito de actuación"
|
geozone_id: "Ámbito de actuación"
|
||||||
title: "Título"
|
title: "Título"
|
||||||
|
signature_sheet:
|
||||||
|
signable_type: "Tipo de hoja de firmas"
|
||||||
|
signable_id: "ID Propuesta ciudadana/Propuesta inversión"
|
||||||
|
document_numbers: "Números de documentos"
|
||||||
errors:
|
errors:
|
||||||
models:
|
models:
|
||||||
user:
|
user:
|
||||||
@@ -90,4 +94,9 @@ es:
|
|||||||
proposal_notification:
|
proposal_notification:
|
||||||
attributes:
|
attributes:
|
||||||
minimum_interval:
|
minimum_interval:
|
||||||
invalid: "Debes esperar un mínimo de %{interval} días entre notificaciones"
|
invalid: "Debes esperar un mínimo de %{interval} días entre notificaciones"
|
||||||
|
signature:
|
||||||
|
attributes:
|
||||||
|
document_number:
|
||||||
|
not_in_census: 'No verificado por Padrón'
|
||||||
|
already_voted: 'Ya ha votado esta propuesta'
|
||||||
@@ -111,6 +111,7 @@ en:
|
|||||||
settings: Configuration settings
|
settings: Configuration settings
|
||||||
spending_proposals: Spending proposals
|
spending_proposals: Spending proposals
|
||||||
stats: Statistics
|
stats: Statistics
|
||||||
|
signature_sheets: Signature Sheets
|
||||||
moderators:
|
moderators:
|
||||||
index:
|
index:
|
||||||
title: Moderators
|
title: Moderators
|
||||||
@@ -295,6 +296,31 @@ en:
|
|||||||
delete:
|
delete:
|
||||||
success: Geozone successfully deleted
|
success: Geozone successfully deleted
|
||||||
error: This geozone can't be deleted since there are elements attached to it
|
error: This geozone can't be deleted since there are elements attached to it
|
||||||
|
signature_sheets:
|
||||||
|
author: Author
|
||||||
|
created_at: Creation date
|
||||||
|
name: Name
|
||||||
|
no_signature_sheets: "There are not signature_sheets"
|
||||||
|
index:
|
||||||
|
title: Signature sheets
|
||||||
|
new: New signature sheets
|
||||||
|
new:
|
||||||
|
title: New signature sheets
|
||||||
|
document_numbers_note: "Write the numbers separated by commas (,)"
|
||||||
|
submit: Create signature sheet
|
||||||
|
show:
|
||||||
|
created_at: Created
|
||||||
|
author: Author
|
||||||
|
documents: Documents
|
||||||
|
document_count: "Number of documents:"
|
||||||
|
verified:
|
||||||
|
one: "There is %{count} valid signature"
|
||||||
|
other: "There are %{count} valid signatures"
|
||||||
|
unverified:
|
||||||
|
one: "There is %{count} invalid signature"
|
||||||
|
other: "There are %{count} invalid signatures"
|
||||||
|
unverified_error: (Not verified by Census)
|
||||||
|
loading: "There are still signatures that are being verified by the Census, please refresh the page in a few moments"
|
||||||
stats:
|
stats:
|
||||||
show:
|
show:
|
||||||
stats_title: Stats
|
stats_title: Stats
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ es:
|
|||||||
settings: Configuración global
|
settings: Configuración global
|
||||||
spending_proposals: Propuestas de inversión
|
spending_proposals: Propuestas de inversión
|
||||||
stats: Estadísticas
|
stats: Estadísticas
|
||||||
|
signature_sheets: Hojas de firmas
|
||||||
moderators:
|
moderators:
|
||||||
index:
|
index:
|
||||||
title: Moderadores
|
title: Moderadores
|
||||||
@@ -293,6 +294,31 @@ es:
|
|||||||
delete:
|
delete:
|
||||||
success: Distrito borrado correctamente
|
success: Distrito borrado correctamente
|
||||||
error: No se puede borrar el distrito porque ya tiene elementos asociados
|
error: No se puede borrar el distrito porque ya tiene elementos asociados
|
||||||
|
signature_sheets:
|
||||||
|
author: Autor
|
||||||
|
created_at: Fecha de creación
|
||||||
|
name: Nombre
|
||||||
|
no_signature_sheets: "No existen hojas de firmas"
|
||||||
|
index:
|
||||||
|
title: Hojas de firmas
|
||||||
|
new: Nueva hoja de firmas
|
||||||
|
new:
|
||||||
|
title: Nueva hoja de firmas
|
||||||
|
document_numbers_note: "Introduce los números separados por comas (,)"
|
||||||
|
submit: Crear hoja de firmas
|
||||||
|
show:
|
||||||
|
created_at: Creado
|
||||||
|
author: Autor
|
||||||
|
documents: Documentos
|
||||||
|
document_count: "Número de documentos:"
|
||||||
|
verified:
|
||||||
|
one: "Hay %{count} firma válida"
|
||||||
|
other: "Hay %{count} firmas válidas"
|
||||||
|
unverified:
|
||||||
|
one: "Hay %{count} firma inválida"
|
||||||
|
other: "Hay %{count} firmas inválidas"
|
||||||
|
unverified_error: (No verificadas por el Padrón)
|
||||||
|
loading: "Aún hay firmas que se están verificando por el Padrón, por favor refresca la página en unos instantes"
|
||||||
stats:
|
stats:
|
||||||
show:
|
show:
|
||||||
stats_title: Estadísticas
|
stats_title: Estadísticas
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ en:
|
|||||||
spending_proposal: Spending proposal
|
spending_proposal: Spending proposal
|
||||||
user: Account
|
user: Account
|
||||||
verification/sms: phone
|
verification/sms: phone
|
||||||
|
signature_sheet: Signature sheet
|
||||||
geozones:
|
geozones:
|
||||||
none: All city
|
none: All city
|
||||||
all: All scopes
|
all: All scopes
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ es:
|
|||||||
spending_proposal: la propuesta de gasto
|
spending_proposal: la propuesta de gasto
|
||||||
user: la cuenta
|
user: la cuenta
|
||||||
verification/sms: el teléfono
|
verification/sms: el teléfono
|
||||||
|
signature_sheet: la hoja de firmas
|
||||||
geozones:
|
geozones:
|
||||||
none: Toda la ciudad
|
none: Toda la ciudad
|
||||||
all: Todos los ámbitos
|
all: Todos los ámbitos
|
||||||
|
|||||||
@@ -1497,7 +1497,6 @@ fr:
|
|||||||
create:
|
create:
|
||||||
flash:
|
flash:
|
||||||
offices: Bureaux de soutien aux citoyens
|
offices: Bureaux de soutien aux citoyens
|
||||||
offices_url: http://offices.consul
|
|
||||||
success_html: Merci d'avoir demandé votre <b>code de sécurité maximum (uniquement
|
success_html: Merci d'avoir demandé votre <b>code de sécurité maximum (uniquement
|
||||||
requis pour le vote final)</b>. Dans quelques jours, nous vous enverrons
|
requis pour le vote final)</b>. Dans quelques jours, nous vous enverrons
|
||||||
un courrier vers votre adresse postale. Vous pouvez le réclamer dans n'importe
|
un courrier vers votre adresse postale. Vous pouvez le réclamer dans n'importe
|
||||||
@@ -1512,7 +1511,6 @@ fr:
|
|||||||
go_to_index: Voir les propositions
|
go_to_index: Voir les propositions
|
||||||
office: Vérifier dans n'importe quel %{office}
|
office: Vérifier dans n'importe quel %{office}
|
||||||
offices: Bureaux de soutien aux citoyens
|
offices: Bureaux de soutien aux citoyens
|
||||||
offices_url: http://offices.consul
|
|
||||||
send_letter: Envoyer une lettre avec le code
|
send_letter: Envoyer une lettre avec le code
|
||||||
title: Félicitations
|
title: Félicitations
|
||||||
user_permission_info: Avec votre compte, vous pouvez
|
user_permission_info: Avec votre compte, vous pouvez
|
||||||
|
|||||||
@@ -1518,7 +1518,6 @@ pt-BR:
|
|||||||
create:
|
create:
|
||||||
flash:
|
flash:
|
||||||
offices: Escritórios de Apoio ao Cidadão
|
offices: Escritórios de Apoio ao Cidadão
|
||||||
offices_url: http://offices.consul
|
|
||||||
success_html: Obrigado por solicitar seu <b>código de segurança máxima (somente
|
success_html: Obrigado por solicitar seu <b>código de segurança máxima (somente
|
||||||
solicitado em votações finais)</b>. Em poucos dias nós lhe enviaremos
|
solicitado em votações finais)</b>. Em poucos dias nós lhe enviaremos
|
||||||
para seu endereço relacionado nos dados que temos em arquivo. Por favor
|
para seu endereço relacionado nos dados que temos em arquivo. Por favor
|
||||||
@@ -1534,7 +1533,6 @@ pt-BR:
|
|||||||
go_to_index: Ver propostas
|
go_to_index: Ver propostas
|
||||||
office: Verificar em qualquer %{office}
|
office: Verificar em qualquer %{office}
|
||||||
offices: Escritórios de Apoio ao Cidadão
|
offices: Escritórios de Apoio ao Cidadão
|
||||||
offices_url: http://offices.consul
|
|
||||||
send_letter: Envie-me uma carta com o código
|
send_letter: Envie-me uma carta com o código
|
||||||
title: Parabéns!
|
title: Parabéns!
|
||||||
user_permission_info: Com a sua conta você pode...
|
user_permission_info: Com a sua conta você pode...
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ en:
|
|||||||
proposal: "Proposal created successfully."
|
proposal: "Proposal created successfully."
|
||||||
proposal_notification: "Your message has been sent correctly."
|
proposal_notification: "Your message has been sent correctly."
|
||||||
spending_proposal: "Spending proposal created successfully. You can access it from %{activity}"
|
spending_proposal: "Spending proposal created successfully. You can access it from %{activity}"
|
||||||
|
signature_sheet: "Signature sheet created successfully"
|
||||||
save_changes:
|
save_changes:
|
||||||
notice: Changes saved
|
notice: Changes saved
|
||||||
update:
|
update:
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ es:
|
|||||||
proposal: "Propuesta creada correctamente."
|
proposal: "Propuesta creada correctamente."
|
||||||
proposal_notification: "Tu message ha sido enviado correctamente."
|
proposal_notification: "Tu message ha sido enviado correctamente."
|
||||||
spending_proposal: "Propuesta de inversión creada correctamente. Puedes acceder a ella desde %{activity}"
|
spending_proposal: "Propuesta de inversión creada correctamente. Puedes acceder a ella desde %{activity}"
|
||||||
|
signature_sheet: "Hoja de firmas creada correctamente"
|
||||||
save_changes:
|
save_changes:
|
||||||
notice: Cambios guardados
|
notice: Cambios guardados
|
||||||
update:
|
update:
|
||||||
|
|||||||
@@ -27,8 +27,12 @@ en:
|
|||||||
facebook_login: Facebook login
|
facebook_login: Facebook login
|
||||||
google_login: Google login
|
google_login: Google login
|
||||||
debates: Debates
|
debates: Debates
|
||||||
|
signature_sheets: Signature sheets
|
||||||
spending_proposals: Investment projects
|
spending_proposals: Investment projects
|
||||||
spending_proposal_features:
|
spending_proposal_features:
|
||||||
voting_allowed: Voting on investment projects
|
voting_allowed: Voting on investment projects
|
||||||
mailer_from_name: Origin email name
|
mailer_from_name: Origin email name
|
||||||
mailer_from_address: Origin email address
|
mailer_from_address: Origin email address
|
||||||
|
meta_description: "Site description (SEO)"
|
||||||
|
meta_keywords: "Keywords (SEO)"
|
||||||
|
verification_offices_url: Verification offices URL
|
||||||
|
|||||||
@@ -27,8 +27,12 @@ es:
|
|||||||
facebook_login: Registro con Facebook
|
facebook_login: Registro con Facebook
|
||||||
google_login: Registro con Google
|
google_login: Registro con Google
|
||||||
debates: Debates
|
debates: Debates
|
||||||
|
signature_sheets: Hojas de firmas
|
||||||
spending_proposals: Propuestas de inversión
|
spending_proposals: Propuestas de inversión
|
||||||
spending_proposal_features:
|
spending_proposal_features:
|
||||||
voting_allowed: Votaciones sobre propuestas de inversión.
|
voting_allowed: Votaciones sobre propuestas de inversión.
|
||||||
mailer_from_name: Nombre email remitente
|
mailer_from_name: Nombre email remitente
|
||||||
mailer_from_address: Dirección email remitente
|
mailer_from_address: Dirección email remitente
|
||||||
|
meta_description: "Descripción del sitio (SEO)"
|
||||||
|
meta_keywords: "Palabras clave (SEO)"
|
||||||
|
verification_offices_url: URL oficinas verificación
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ en:
|
|||||||
create:
|
create:
|
||||||
flash:
|
flash:
|
||||||
offices: Citizen Support Offices
|
offices: Citizen Support Offices
|
||||||
offices_url: http://offices.consul
|
|
||||||
success_html: Thank you for requesting your <b>maximum security code (only required for the final votes)</b>. In a few days we will send it to the address featuring in the data we have on file. Please remember that, if you prefer, you can collect your code from any of the %{offices}.
|
success_html: Thank you for requesting your <b>maximum security code (only required for the final votes)</b>. In a few days we will send it to the address featuring in the data we have on file. Please remember that, if you prefer, you can collect your code from any of the %{offices}.
|
||||||
edit:
|
edit:
|
||||||
see_all: See proposals
|
see_all: See proposals
|
||||||
@@ -33,7 +32,6 @@ en:
|
|||||||
go_to_index: See proposals
|
go_to_index: See proposals
|
||||||
office: Verify in any %{office}
|
office: Verify in any %{office}
|
||||||
offices: Citizen Support Offices
|
offices: Citizen Support Offices
|
||||||
offices_url: http://offices.consul
|
|
||||||
send_letter: Send me a letter with the code
|
send_letter: Send me a letter with the code
|
||||||
title: Congratulations!
|
title: Congratulations!
|
||||||
user_permission_info: With your account you can...
|
user_permission_info: With your account you can...
|
||||||
@@ -65,7 +63,6 @@ en:
|
|||||||
error_not_allowed_postal_code: In order to be verified, you must be registered.
|
error_not_allowed_postal_code: In order to be verified, you must be registered.
|
||||||
error_verifying_census: The Census was unable to verify your information. Please confirm that your census details are correct by calling to City Council or visit one %{offices}.
|
error_verifying_census: The Census was unable to verify your information. Please confirm that your census details are correct by calling to City Council or visit one %{offices}.
|
||||||
error_verifying_census_offices: Citizen Support Office
|
error_verifying_census_offices: Citizen Support Office
|
||||||
error_verifying_census_offices_url: http://offices.consul
|
|
||||||
form_errors: prevented the verification of your residence
|
form_errors: prevented the verification of your residence
|
||||||
postal_code: Postcode
|
postal_code: Postcode
|
||||||
postal_code_note: To verify your account you must be registered
|
postal_code_note: To verify your account you must be registered
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ es:
|
|||||||
create:
|
create:
|
||||||
flash:
|
flash:
|
||||||
offices: Oficinas de Atención al Ciudadano
|
offices: Oficinas de Atención al Ciudadano
|
||||||
offices_url: http://offices.consul
|
|
||||||
success_html: Antes de las votaciones recibirás una carta con las instrucciones para verificar tu cuenta.<br> Recuerda que puedes ahorrar el envío verificándote presencialmente en cualquiera de las %{offices}.
|
success_html: Antes de las votaciones recibirás una carta con las instrucciones para verificar tu cuenta.<br> Recuerda que puedes ahorrar el envío verificándote presencialmente en cualquiera de las %{offices}.
|
||||||
edit:
|
edit:
|
||||||
see_all: Ver propuestas
|
see_all: Ver propuestas
|
||||||
@@ -33,7 +32,6 @@ es:
|
|||||||
go_to_index: Ver propuestas
|
go_to_index: Ver propuestas
|
||||||
office: Verificarte presencialmente en cualquier %{office}
|
office: Verificarte presencialmente en cualquier %{office}
|
||||||
offices: Oficina de Atención al Ciudadano
|
offices: Oficina de Atención al Ciudadano
|
||||||
offices_url: http://offices.consul
|
|
||||||
send_letter: Solicitar una carta por correo postal
|
send_letter: Solicitar una carta por correo postal
|
||||||
title: "¡Felicidades!"
|
title: "¡Felicidades!"
|
||||||
user_permission_info: Con tu cuenta ya puedes...
|
user_permission_info: Con tu cuenta ya puedes...
|
||||||
@@ -65,7 +63,6 @@ es:
|
|||||||
error_not_allowed_postal_code: Para verificarte debes estar empadronado.
|
error_not_allowed_postal_code: Para verificarte debes estar empadronado.
|
||||||
error_verifying_census: El Padrón no pudo verificar tu información. Por favor, confirma que tus datos de empadronamiento sean correctos llamando al Ayuntamiento o visitando una %{offices}.
|
error_verifying_census: El Padrón no pudo verificar tu información. Por favor, confirma que tus datos de empadronamiento sean correctos llamando al Ayuntamiento o visitando una %{offices}.
|
||||||
error_verifying_census_offices: oficina de Atención al ciudadano
|
error_verifying_census_offices: oficina de Atención al ciudadano
|
||||||
error_verifying_census_offices_url: http://offices.consul
|
|
||||||
form_errors: evitaron verificar tu residencia
|
form_errors: evitaron verificar tu residencia
|
||||||
postal_code: Código postal
|
postal_code: Código postal
|
||||||
postal_code_note: Para verificar tus datos debes estar empadronado
|
postal_code_note: Para verificar tus datos debes estar empadronado
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ Rails.application.routes.draw do
|
|||||||
get :summary, on: :collection
|
get :summary, on: :collection
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resources :signature_sheets, only: [:index, :new, :create, :show]
|
||||||
|
|
||||||
resources :banners, only: [:index, :new, :create, :edit, :update, :destroy] do
|
resources :banners, only: [:index, :new, :create, :edit, :update, :destroy] do
|
||||||
collection { get :search}
|
collection { get :search}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -30,10 +30,14 @@ Setting.create(key: 'feature.spending_proposal_features.voting_allowed', value:
|
|||||||
Setting.create(key: 'feature.twitter_login', value: "true")
|
Setting.create(key: 'feature.twitter_login', value: "true")
|
||||||
Setting.create(key: 'feature.facebook_login', value: "true")
|
Setting.create(key: 'feature.facebook_login', value: "true")
|
||||||
Setting.create(key: 'feature.google_login', value: "true")
|
Setting.create(key: 'feature.google_login', value: "true")
|
||||||
|
Setting.create(key: 'feature.signature_sheets', value: "true")
|
||||||
Setting.create(key: 'per_page_code', value: "")
|
Setting.create(key: 'per_page_code', value: "")
|
||||||
Setting.create(key: 'comments_body_max_length', value: '1000')
|
Setting.create(key: 'comments_body_max_length', value: '1000')
|
||||||
Setting.create(key: 'mailer_from_name', value: 'Consul')
|
Setting.create(key: 'mailer_from_name', value: 'Consul')
|
||||||
Setting.create(key: 'mailer_from_address', value: 'noreply@consul.dev')
|
Setting.create(key: 'mailer_from_address', value: 'noreply@consul.dev')
|
||||||
|
Setting.create(key: 'meta_description', value: 'Citizen Participation and Open Government Application')
|
||||||
|
Setting.create(key: 'meta_keywords', value: 'citizen participation, open government')
|
||||||
|
Setting.create(key: 'verification_offices_url', value: 'http://oficinas-atencion-ciudadano.url/')
|
||||||
|
|
||||||
puts "Creating Geozones"
|
puts "Creating Geozones"
|
||||||
('A'..'Z').each { |i| Geozone.create(name: "District #{i}", external_code: i.ord, census_code: i.ord) }
|
('A'..'Z').each { |i| Geozone.create(name: "District #{i}", external_code: i.ord, census_code: i.ord) }
|
||||||
|
|||||||
11
db/migrate/20161214212918_create_signature_sheets.rb
Normal file
11
db/migrate/20161214212918_create_signature_sheets.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
class CreateSignatureSheets < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :signature_sheets do |t|
|
||||||
|
t.references :signable, polymorphic: true
|
||||||
|
t.text :document_numbers
|
||||||
|
t.boolean :processed, default: false
|
||||||
|
t.references :author
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
11
db/migrate/20161214233817_create_signatures.rb
Normal file
11
db/migrate/20161214233817_create_signatures.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
class CreateSignatures < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :signatures do |t|
|
||||||
|
t.references :signature_sheet
|
||||||
|
t.references :user
|
||||||
|
t.string :document_number
|
||||||
|
t.boolean :verified, default: false
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
5
db/migrate/20161221131403_add_signture_id_to_votes.rb
Normal file
5
db/migrate/20161221131403_add_signture_id_to_votes.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class AddSigntureIdToVotes < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_reference :votes, :signature, index: true
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class AddCreatedFromSignatureToUsers < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :users, :created_from_signature, :boolean, default: false
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class RemovePhysicalVotesFromProposals < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
remove_column :proposals, :physical_votes
|
||||||
|
end
|
||||||
|
end
|
||||||
31
db/schema.rb
31
db/schema.rb
@@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20161102133838) do
|
ActiveRecord::Schema.define(version: 20161229110336) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
@@ -123,10 +123,10 @@ ActiveRecord::Schema.define(version: 20161102133838) do
|
|||||||
t.string "visit_id"
|
t.string "visit_id"
|
||||||
t.datetime "hidden_at"
|
t.datetime "hidden_at"
|
||||||
t.integer "flags_count", default: 0
|
t.integer "flags_count", default: 0
|
||||||
|
t.datetime "ignored_flag_at"
|
||||||
t.integer "cached_votes_total", default: 0
|
t.integer "cached_votes_total", default: 0
|
||||||
t.integer "cached_votes_up", default: 0
|
t.integer "cached_votes_up", default: 0
|
||||||
t.integer "cached_votes_down", default: 0
|
t.integer "cached_votes_down", default: 0
|
||||||
t.datetime "ignored_flag_at"
|
|
||||||
t.integer "comments_count", default: 0
|
t.integer "comments_count", default: 0
|
||||||
t.datetime "confirmed_hide_at"
|
t.datetime "confirmed_hide_at"
|
||||||
t.integer "cached_anonymous_votes_total", default: 0
|
t.integer "cached_anonymous_votes_total", default: 0
|
||||||
@@ -145,7 +145,6 @@ ActiveRecord::Schema.define(version: 20161102133838) do
|
|||||||
add_index "debates", ["cached_votes_total"], name: "index_debates_on_cached_votes_total", using: :btree
|
add_index "debates", ["cached_votes_total"], name: "index_debates_on_cached_votes_total", using: :btree
|
||||||
add_index "debates", ["cached_votes_up"], name: "index_debates_on_cached_votes_up", using: :btree
|
add_index "debates", ["cached_votes_up"], name: "index_debates_on_cached_votes_up", using: :btree
|
||||||
add_index "debates", ["confidence_score"], name: "index_debates_on_confidence_score", using: :btree
|
add_index "debates", ["confidence_score"], name: "index_debates_on_confidence_score", using: :btree
|
||||||
add_index "debates", ["description"], name: "index_debates_on_description", using: :btree
|
|
||||||
add_index "debates", ["geozone_id"], name: "index_debates_on_geozone_id", using: :btree
|
add_index "debates", ["geozone_id"], name: "index_debates_on_geozone_id", using: :btree
|
||||||
add_index "debates", ["hidden_at"], name: "index_debates_on_hidden_at", using: :btree
|
add_index "debates", ["hidden_at"], name: "index_debates_on_hidden_at", using: :btree
|
||||||
add_index "debates", ["hot_score"], name: "index_debates_on_hot_score", using: :btree
|
add_index "debates", ["hot_score"], name: "index_debates_on_hot_score", using: :btree
|
||||||
@@ -298,7 +297,6 @@ ActiveRecord::Schema.define(version: 20161102133838) do
|
|||||||
t.string "responsible_name", limit: 60
|
t.string "responsible_name", limit: 60
|
||||||
t.text "summary"
|
t.text "summary"
|
||||||
t.string "video_url"
|
t.string "video_url"
|
||||||
t.integer "physical_votes", default: 0
|
|
||||||
t.tsvector "tsv"
|
t.tsvector "tsv"
|
||||||
t.integer "geozone_id"
|
t.integer "geozone_id"
|
||||||
t.datetime "retired_at"
|
t.datetime "retired_at"
|
||||||
@@ -310,7 +308,6 @@ ActiveRecord::Schema.define(version: 20161102133838) do
|
|||||||
add_index "proposals", ["author_id"], name: "index_proposals_on_author_id", using: :btree
|
add_index "proposals", ["author_id"], name: "index_proposals_on_author_id", using: :btree
|
||||||
add_index "proposals", ["cached_votes_up"], name: "index_proposals_on_cached_votes_up", using: :btree
|
add_index "proposals", ["cached_votes_up"], name: "index_proposals_on_cached_votes_up", using: :btree
|
||||||
add_index "proposals", ["confidence_score"], name: "index_proposals_on_confidence_score", using: :btree
|
add_index "proposals", ["confidence_score"], name: "index_proposals_on_confidence_score", using: :btree
|
||||||
add_index "proposals", ["description"], name: "index_proposals_on_description", using: :btree
|
|
||||||
add_index "proposals", ["geozone_id"], name: "index_proposals_on_geozone_id", using: :btree
|
add_index "proposals", ["geozone_id"], name: "index_proposals_on_geozone_id", using: :btree
|
||||||
add_index "proposals", ["hidden_at"], name: "index_proposals_on_hidden_at", using: :btree
|
add_index "proposals", ["hidden_at"], name: "index_proposals_on_hidden_at", using: :btree
|
||||||
add_index "proposals", ["hot_score"], name: "index_proposals_on_hot_score", using: :btree
|
add_index "proposals", ["hot_score"], name: "index_proposals_on_hot_score", using: :btree
|
||||||
@@ -326,6 +323,25 @@ ActiveRecord::Schema.define(version: 20161102133838) do
|
|||||||
|
|
||||||
add_index "settings", ["key"], name: "index_settings_on_key", using: :btree
|
add_index "settings", ["key"], name: "index_settings_on_key", using: :btree
|
||||||
|
|
||||||
|
create_table "signature_sheets", force: :cascade do |t|
|
||||||
|
t.integer "signable_id"
|
||||||
|
t.string "signable_type"
|
||||||
|
t.text "document_numbers"
|
||||||
|
t.boolean "processed", default: false
|
||||||
|
t.integer "author_id"
|
||||||
|
t.datetime "created_at"
|
||||||
|
t.datetime "updated_at"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "signatures", force: :cascade do |t|
|
||||||
|
t.integer "signature_sheet_id"
|
||||||
|
t.integer "user_id"
|
||||||
|
t.string "document_number"
|
||||||
|
t.boolean "verified", default: false
|
||||||
|
t.datetime "created_at"
|
||||||
|
t.datetime "updated_at"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "spending_proposals", force: :cascade do |t|
|
create_table "spending_proposals", force: :cascade do |t|
|
||||||
t.string "title"
|
t.string "title"
|
||||||
t.text "description"
|
t.text "description"
|
||||||
@@ -464,7 +480,8 @@ ActiveRecord::Schema.define(version: 20161102133838) do
|
|||||||
t.boolean "email_digest", default: true
|
t.boolean "email_digest", default: true
|
||||||
t.boolean "email_on_direct_message", default: true
|
t.boolean "email_on_direct_message", default: true
|
||||||
t.boolean "official_position_badge", default: false
|
t.boolean "official_position_badge", default: false
|
||||||
t.datetime "password_changed_at", default: '2016-11-02 13:51:14', null: false
|
t.datetime "password_changed_at", default: '2016-12-21 17:55:08', null: false
|
||||||
|
t.boolean "created_from_signature", default: false
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
|
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
|
||||||
@@ -544,8 +561,10 @@ ActiveRecord::Schema.define(version: 20161102133838) do
|
|||||||
t.integer "vote_weight"
|
t.integer "vote_weight"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
|
t.integer "signature_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
add_index "votes", ["signature_id"], name: "index_votes_on_signature_id", using: :btree
|
||||||
add_index "votes", ["votable_id", "votable_type", "vote_scope"], name: "index_votes_on_votable_id_and_votable_type_and_vote_scope", using: :btree
|
add_index "votes", ["votable_id", "votable_type", "vote_scope"], name: "index_votes_on_votable_id_and_votable_type_and_vote_scope", using: :btree
|
||||||
add_index "votes", ["voter_id", "voter_type", "vote_scope"], name: "index_votes_on_voter_id_and_voter_type_and_vote_scope", using: :btree
|
add_index "votes", ["voter_id", "voter_type", "vote_scope"], name: "index_votes_on_voter_id_and_voter_type_and_vote_scope", using: :btree
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ Setting["org_name"] = "Consul"
|
|||||||
# Consul installation place name (City, Country...)
|
# Consul installation place name (City, Country...)
|
||||||
Setting["place_name"] = "Consul-land"
|
Setting["place_name"] = "Consul-land"
|
||||||
|
|
||||||
|
# Meta tags for SEO
|
||||||
|
Setting["meta_description"] = nil
|
||||||
|
Setting["meta_keywords"] = nil
|
||||||
|
|
||||||
# Feature flags
|
# Feature flags
|
||||||
Setting['feature.debates'] = true
|
Setting['feature.debates'] = true
|
||||||
Setting['feature.spending_proposals'] = true
|
Setting['feature.spending_proposals'] = true
|
||||||
@@ -64,6 +68,7 @@ Setting['feature.twitter_login'] = true
|
|||||||
Setting['feature.facebook_login'] = true
|
Setting['feature.facebook_login'] = true
|
||||||
Setting['feature.google_login'] = true
|
Setting['feature.google_login'] = true
|
||||||
Setting['feature.public_stats'] = true
|
Setting['feature.public_stats'] = true
|
||||||
|
Setting['feature.signature_sheets'] = true
|
||||||
|
|
||||||
# Spending proposals feature flags
|
# Spending proposals feature flags
|
||||||
Setting['feature.spending_proposal_features.voting_allowed'] = true
|
Setting['feature.spending_proposal_features.voting_allowed'] = true
|
||||||
@@ -85,3 +90,6 @@ Setting['direct_message_max_per_day'] = 3
|
|||||||
# Email settings
|
# Email settings
|
||||||
Setting['mailer_from_name'] = 'Consul'
|
Setting['mailer_from_name'] = 'Consul'
|
||||||
Setting['mailer_from_address'] = 'noreply@consul.dev'
|
Setting['mailer_from_address'] = 'noreply@consul.dev'
|
||||||
|
|
||||||
|
# Verification settings
|
||||||
|
Setting['verification_offices_url'] = 'http://oficinas-atencion-ciudadano.url/'
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class CensusApi
|
|||||||
if end_point_available?
|
if end_point_available?
|
||||||
client.call(:get_habita_datos, message: request(document_type, document_number)).body
|
client.call(:get_habita_datos, message: request(document_type, document_number)).body
|
||||||
else
|
else
|
||||||
stubbed_response_body
|
stubbed_response(document_type, document_number)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -97,8 +97,20 @@ class CensusApi
|
|||||||
Rails.env.staging? || Rails.env.preproduction? || Rails.env.production?
|
Rails.env.staging? || Rails.env.preproduction? || Rails.env.production?
|
||||||
end
|
end
|
||||||
|
|
||||||
def stubbed_response_body
|
def stubbed_response(document_type, document_number)
|
||||||
{get_habita_datos_response: {get_habita_datos_return: {hay_errores: false, datos_habitante: { item: {fecha_nacimiento_string: "31-12-1980", identificador_documento: "12345678Z", descripcion_sexo: "Varón" }}, datos_vivienda: {item: {codigo_postal: "28013", codigo_distrito: "01"}}}}}
|
if document_number == "12345678Z" && document_type == "1"
|
||||||
|
stubbed_valid_response
|
||||||
|
else
|
||||||
|
stubbed_invalid_response
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stubbed_valid_response
|
||||||
|
{get_habita_datos_response: {get_habita_datos_return: {datos_habitante: { item: {fecha_nacimiento_string: "31-12-1980", identificador_documento: "12345678Z", descripcion_sexo: "Varón", nombre: "José", apellido1: "García" }}, datos_vivienda: {item: {codigo_postal: "28013", codigo_distrito: "01"}}}}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def stubbed_invalid_response
|
||||||
|
{get_habita_datos_response: {get_habita_datos_return: {datos_habitante: {}, datos_vivienda: {}}}}
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_dni?(document_type)
|
def is_dni?(document_type)
|
||||||
|
|||||||
@@ -344,4 +344,15 @@ FactoryGirl.define do
|
|||||||
association :sender, factory: :user
|
association :sender, factory: :user
|
||||||
association :receiver, factory: :user
|
association :receiver, factory: :user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :signature_sheet do
|
||||||
|
association :signable, factory: :proposal
|
||||||
|
association :author, factory: :user
|
||||||
|
document_numbers "123A, 456B, 789C"
|
||||||
|
end
|
||||||
|
|
||||||
|
factory :signature do
|
||||||
|
signature_sheet
|
||||||
|
sequence(:document_number) { |n| "#{n}A" }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
75
spec/features/admin/signature_sheets_spec.rb
Normal file
75
spec/features/admin/signature_sheets_spec.rb
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
feature 'Signature sheets' do
|
||||||
|
|
||||||
|
background do
|
||||||
|
admin = create(:administrator)
|
||||||
|
login_as(admin.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Index" do
|
||||||
|
3.times { create(:signature_sheet) }
|
||||||
|
|
||||||
|
visit admin_signature_sheets_path
|
||||||
|
|
||||||
|
expect(page).to have_css(".signature_sheet", count: 3)
|
||||||
|
|
||||||
|
SignatureSheet.all.each do |signature_sheet|
|
||||||
|
expect(page).to have_content signature_sheet.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Create' do
|
||||||
|
proposal = create(:proposal)
|
||||||
|
visit new_admin_signature_sheet_path
|
||||||
|
|
||||||
|
select "Citizen proposal", from: "signature_sheet_signable_type"
|
||||||
|
fill_in "signature_sheet_signable_id", with: proposal.id
|
||||||
|
fill_in "signature_sheet_document_numbers", with: "12345678Z, 99999999Z"
|
||||||
|
click_button "Create signature sheet"
|
||||||
|
|
||||||
|
expect(page).to have_content "Signature sheet created successfully"
|
||||||
|
|
||||||
|
visit proposal_path(proposal)
|
||||||
|
|
||||||
|
expect(page).to have_content "1 support"
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Errors on create' do
|
||||||
|
visit new_admin_signature_sheet_path
|
||||||
|
|
||||||
|
click_button "Create signature sheet"
|
||||||
|
|
||||||
|
expect(page).to have_content error_message
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Show' do
|
||||||
|
proposal = create(:proposal)
|
||||||
|
user = Administrator.first.user
|
||||||
|
signature_sheet = create(:signature_sheet,
|
||||||
|
signable: proposal,
|
||||||
|
document_numbers: "12345678Z, 123A, 123B",
|
||||||
|
author: user)
|
||||||
|
signature_sheet.verify_signatures
|
||||||
|
|
||||||
|
visit admin_signature_sheet_path(signature_sheet)
|
||||||
|
|
||||||
|
expect(page).to have_content "Citizen proposal #{proposal.id}"
|
||||||
|
expect(page).to have_content "12345678Z, 123A, 123B"
|
||||||
|
expect(page).to have_content signature_sheet.created_at.strftime("%d %b %H:%M")
|
||||||
|
expect(page).to have_content user.name
|
||||||
|
|
||||||
|
within("#document_count") do
|
||||||
|
expect(page).to have_content 3
|
||||||
|
end
|
||||||
|
|
||||||
|
within("#verified_signatures") do
|
||||||
|
expect(page).to have_content 1
|
||||||
|
end
|
||||||
|
|
||||||
|
within("#unverified_signatures") do
|
||||||
|
expect(page).to have_content 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -47,7 +47,7 @@ feature 'DocumentVerifications' do
|
|||||||
scenario 'Verifying a user which does exists in the census but not in the db redirects allows sending an email' do
|
scenario 'Verifying a user which does exists in the census but not in the db redirects allows sending an email' do
|
||||||
|
|
||||||
visit management_document_verifications_path
|
visit management_document_verifications_path
|
||||||
fill_in 'document_verification_document_number', with: '1234'
|
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||||
click_button 'Check'
|
click_button 'Check'
|
||||||
|
|
||||||
expect(page).to have_content "Please introduce the email used on the account"
|
expect(page).to have_content "Please introduce the email used on the account"
|
||||||
@@ -66,7 +66,7 @@ feature 'DocumentVerifications' do
|
|||||||
expect_any_instance_of(Verification::Management::Document).to receive(:under_sixteen?).and_return(true)
|
expect_any_instance_of(Verification::Management::Document).to receive(:under_sixteen?).and_return(true)
|
||||||
|
|
||||||
visit management_document_verifications_path
|
visit management_document_verifications_path
|
||||||
fill_in 'document_verification_document_number', with: '1234'
|
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||||
click_button 'Check'
|
click_button 'Check'
|
||||||
|
|
||||||
expect(page).to have_content "You must be over 16 to verify your account."
|
expect(page).to have_content "You must be over 16 to verify your account."
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ feature 'EmailVerifications' do
|
|||||||
user = create(:user)
|
user = create(:user)
|
||||||
|
|
||||||
visit management_document_verifications_path
|
visit management_document_verifications_path
|
||||||
fill_in 'document_verification_document_number', with: '1234'
|
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||||
click_button 'Check'
|
click_button 'Check'
|
||||||
|
|
||||||
expect(page).to have_content "Please introduce the email used on the account"
|
expect(page).to have_content "Please introduce the email used on the account"
|
||||||
@@ -30,7 +30,7 @@ feature 'EmailVerifications' do
|
|||||||
expect(page).to_not have_link "Verify my account"
|
expect(page).to_not have_link "Verify my account"
|
||||||
expect(page).to have_content "Account verified"
|
expect(page).to have_content "Account verified"
|
||||||
|
|
||||||
expect(user.reload.document_number).to eq('1234')
|
expect(user.reload.document_number).to eq('12345678Z')
|
||||||
expect(user).to be_level_three_verified
|
expect(user).to be_level_three_verified
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ feature 'Managed User' do
|
|||||||
user = create(:user)
|
user = create(:user)
|
||||||
|
|
||||||
visit management_document_verifications_path
|
visit management_document_verifications_path
|
||||||
fill_in 'document_verification_document_number', with: '1234'
|
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||||
click_button 'Check'
|
click_button 'Check'
|
||||||
|
|
||||||
within(".account-info") do
|
within(".account-info") do
|
||||||
@@ -66,7 +66,7 @@ feature 'Managed User' do
|
|||||||
expect(page).not_to have_content "Email"
|
expect(page).not_to have_content "Email"
|
||||||
expect(page).to have_content "Document type"
|
expect(page).to have_content "Document type"
|
||||||
expect(page).to have_content "Document number"
|
expect(page).to have_content "Document number"
|
||||||
expect(page).to have_content "1234"
|
expect(page).to have_content "12345678Z"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page).to have_content "Please introduce the email used on the account"
|
expect(page).to have_content "Please introduce the email used on the account"
|
||||||
@@ -88,7 +88,7 @@ feature 'Managed User' do
|
|||||||
login_as_manager
|
login_as_manager
|
||||||
|
|
||||||
visit management_document_verifications_path
|
visit management_document_verifications_path
|
||||||
fill_in 'document_verification_document_number', with: '1234'
|
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||||
click_button 'Check'
|
click_button 'Check'
|
||||||
|
|
||||||
expect(page).to have_content "Please introduce the email used on the account"
|
expect(page).to have_content "Please introduce the email used on the account"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ feature 'Users' do
|
|||||||
scenario 'Create a level 3 user from scratch' do
|
scenario 'Create a level 3 user from scratch' do
|
||||||
|
|
||||||
visit management_document_verifications_path
|
visit management_document_verifications_path
|
||||||
fill_in 'document_verification_document_number', with: '1234'
|
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||||
click_button 'Check'
|
click_button 'Check'
|
||||||
|
|
||||||
expect(page).to have_content "Please introduce the email used on the account"
|
expect(page).to have_content "Please introduce the email used on the account"
|
||||||
@@ -45,10 +45,10 @@ feature 'Users' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario 'Delete a level 2 user account from document verification page', :js do
|
scenario 'Delete a level 2 user account from document verification page', :js do
|
||||||
level_2_user = create(:user, :level_two, document_number: 13579)
|
level_2_user = create(:user, :level_two, document_number: "12345678Z")
|
||||||
|
|
||||||
visit management_document_verifications_path
|
visit management_document_verifications_path
|
||||||
fill_in 'document_verification_document_number', with: '13579'
|
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||||
click_button 'Check'
|
click_button 'Check'
|
||||||
|
|
||||||
expect(page).to_not have_content "This user account is already verified."
|
expect(page).to_not have_content "This user account is already verified."
|
||||||
@@ -62,7 +62,7 @@ feature 'Users' do
|
|||||||
expect(level_2_user.reload.erase_reason).to eq "Deleted by manager: manager_user_#{Manager.last.user_id}"
|
expect(level_2_user.reload.erase_reason).to eq "Deleted by manager: manager_user_#{Manager.last.user_id}"
|
||||||
|
|
||||||
visit management_document_verifications_path
|
visit management_document_verifications_path
|
||||||
fill_in 'document_verification_document_number', with: '13579'
|
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||||
click_button 'Check'
|
click_button 'Check'
|
||||||
|
|
||||||
expect(page).to have_content "no user account associated to it"
|
expect(page).to have_content "no user account associated to it"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ feature 'Verify Letter' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario 'Go to office instead of send letter' do
|
scenario 'Go to office instead of send letter' do
|
||||||
|
Setting["verification_offices_url"] = "http://offices.consul"
|
||||||
user = create(:user, residence_verified_at: Time.current,
|
user = create(:user, residence_verified_at: Time.current,
|
||||||
confirmed_phone: "611111111")
|
confirmed_phone: "611111111")
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ describe ProposalsHelper do
|
|||||||
expect(progress_bar_percentage(proposal)).to eq 50
|
expect(progress_bar_percentage(proposal)).to eq 50
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should take into account the physical votes" do
|
|
||||||
proposal = create(:proposal, cached_votes_up: ((Proposal.votes_needed_for_success/2)-100), physical_votes: 100)
|
|
||||||
expect(progress_bar_percentage(proposal)).to eq 50
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should be 100 if there are more votes than needed" do
|
it "should be 100 if there are more votes than needed" do
|
||||||
proposal = create(:proposal, cached_votes_up: Proposal.votes_needed_for_success*2)
|
proposal = create(:proposal, cached_votes_up: Proposal.votes_needed_for_success*2)
|
||||||
expect(progress_bar_percentage(proposal)).to eq 100
|
expect(progress_bar_percentage(proposal)).to eq 100
|
||||||
@@ -45,10 +40,6 @@ describe ProposalsHelper do
|
|||||||
expect(supports_percentage(proposal)).to eq "100%"
|
expect(supports_percentage(proposal)).to eq "100%"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should take into account the physical votes" do
|
|
||||||
proposal = create(:proposal, physical_votes: Proposal.votes_needed_for_success/2)
|
|
||||||
expect(supports_percentage(proposal)).to eq "50%"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
87
spec/models/signature_sheet_spec.rb
Normal file
87
spec/models/signature_sheet_spec.rb
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe SignatureSheet do
|
||||||
|
|
||||||
|
let(:signature_sheet) { build(:signature_sheet) }
|
||||||
|
|
||||||
|
describe "validations" do
|
||||||
|
|
||||||
|
it "should be valid" do
|
||||||
|
expect(signature_sheet).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be valid with a valid signable" do
|
||||||
|
signature_sheet.signable = create(:proposal)
|
||||||
|
expect(signature_sheet).to be_valid
|
||||||
|
|
||||||
|
signature_sheet.signable = create(:spending_proposal)
|
||||||
|
expect(signature_sheet).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not be valid without signable" do
|
||||||
|
signature_sheet.signable = nil
|
||||||
|
expect(signature_sheet).to_not be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not be valid without a valid signable" do
|
||||||
|
signature_sheet.signable = create(:comment)
|
||||||
|
expect(signature_sheet).to_not be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not be valid without document numbers" do
|
||||||
|
signature_sheet.document_numbers = nil
|
||||||
|
expect(signature_sheet).to_not be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not be valid without an author" do
|
||||||
|
signature_sheet.author = nil
|
||||||
|
expect(signature_sheet).to_not be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#name" do
|
||||||
|
it "returns name for proposal signature sheets" do
|
||||||
|
proposal = create(:proposal)
|
||||||
|
signature_sheet.signable = proposal
|
||||||
|
|
||||||
|
expect(signature_sheet.name).to eq("Citizen proposal #{proposal.id}")
|
||||||
|
end
|
||||||
|
it "returns name for spending proposal signature sheets" do
|
||||||
|
spending_proposal = create(:spending_proposal)
|
||||||
|
signature_sheet.signable = spending_proposal
|
||||||
|
|
||||||
|
expect(signature_sheet.name).to eq("Spending proposal #{spending_proposal.id}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#verify_signatures" do
|
||||||
|
it "creates signatures for each document number" do
|
||||||
|
signature_sheet = create(:signature_sheet, document_numbers: "123A, 456B")
|
||||||
|
signature_sheet.verify_signatures
|
||||||
|
|
||||||
|
expect(Signature.count).to eq(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "marks signature sheet as processed" do
|
||||||
|
signature_sheet = create(:signature_sheet)
|
||||||
|
signature_sheet.verify_signatures
|
||||||
|
|
||||||
|
expect(signature_sheet.processed).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#parsed_document_numbers" do
|
||||||
|
it "returns an array after spliting document numbers by newlines or commas" do
|
||||||
|
signature_sheet.document_numbers = "123A\r\n456B\n789C,123B"
|
||||||
|
|
||||||
|
expect(signature_sheet.parsed_document_numbers).to eq(['123A', '456B', '789C', '123B'])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "strips spaces between number and letter" do
|
||||||
|
signature_sheet.document_numbers = "123 A\n456 B \n 789C"
|
||||||
|
|
||||||
|
expect(signature_sheet.parsed_document_numbers).to eq(['123A', '456B', '789C'])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
195
spec/models/signature_spec.rb
Normal file
195
spec/models/signature_spec.rb
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe Signature do
|
||||||
|
|
||||||
|
let(:signature) { build(:signature) }
|
||||||
|
|
||||||
|
describe "validations" do
|
||||||
|
|
||||||
|
it "should be valid" do
|
||||||
|
expect(signature).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not be valid without a document number" do
|
||||||
|
signature.document_number = nil
|
||||||
|
expect(signature).to_not be_valid
|
||||||
|
|
||||||
|
signature.document_number = ""
|
||||||
|
expect(signature).to_not be_valid
|
||||||
|
|
||||||
|
signature.document_number = " "
|
||||||
|
expect(signature).to_not be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not be valid without an associated signature sheet" do
|
||||||
|
signature.signature_sheet = nil
|
||||||
|
expect(signature).to_not be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#clean_document_number" do
|
||||||
|
it "removes non alphanumeric characters" do
|
||||||
|
signature = create(:signature, document_number: "123-[;,9]")
|
||||||
|
expect(signature.document_number).to eq("1239")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "upcases letter in document number" do
|
||||||
|
signature = create(:signature, document_number: "123a")
|
||||||
|
expect(signature.document_number).to eq("123A")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "deals gracefully with empty document numbers" do
|
||||||
|
signature = build(:signature, document_number: "")
|
||||||
|
signature.clean_document_number
|
||||||
|
expect(signature.document_number).to eq("")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#verified?" do
|
||||||
|
|
||||||
|
it "returns true if user exists" do
|
||||||
|
user = create(:user, :level_two, document_number: "123A")
|
||||||
|
signature = create(:signature, document_number: user.document_number)
|
||||||
|
|
||||||
|
expect(signature.verified?).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true if document number in census" do
|
||||||
|
signature = create(:signature, document_number: "12345678Z")
|
||||||
|
|
||||||
|
expect(signature.verified?).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if user does not exist and not in census" do
|
||||||
|
signature = create(:signature, document_number: "123A")
|
||||||
|
|
||||||
|
expect(signature.verified?).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#assign_vote" do
|
||||||
|
|
||||||
|
describe "existing user" do
|
||||||
|
|
||||||
|
it "assigns vote to user" do
|
||||||
|
user = create(:user, :level_two, document_number: "123A")
|
||||||
|
signature = create(:signature, document_number: user.document_number)
|
||||||
|
proposal = signature.signable
|
||||||
|
|
||||||
|
signature.assign_vote
|
||||||
|
|
||||||
|
expect(user.voted_for?(proposal)).to be
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not assign vote to user multiple times" do
|
||||||
|
user = create(:user, :level_two, document_number: "123A")
|
||||||
|
signature = create(:signature, document_number: user.document_number)
|
||||||
|
|
||||||
|
signature.assign_vote
|
||||||
|
signature.assign_vote
|
||||||
|
|
||||||
|
expect(Vote.count).to eq(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not assign vote to user if already voted" do
|
||||||
|
proposal = create(:proposal)
|
||||||
|
user = create(:user, :level_two, document_number: "123A")
|
||||||
|
vote = create(:vote, votable: proposal, voter: user)
|
||||||
|
signature_sheet = create(:signature_sheet, signable: proposal)
|
||||||
|
signature = create(:signature, signature_sheet: signature_sheet, document_number: user.document_number)
|
||||||
|
|
||||||
|
signature.assign_vote
|
||||||
|
|
||||||
|
expect(Vote.count).to eq(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "marks the vote as coming from a signature" do
|
||||||
|
signature = create(:signature, document_number: "12345678Z")
|
||||||
|
|
||||||
|
signature.assign_vote
|
||||||
|
|
||||||
|
expect(Vote.last.signature).to eq(signature)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "inexistent user" do
|
||||||
|
|
||||||
|
it "creates a user with that document number" do
|
||||||
|
signature = create(:signature, document_number: "12345678Z")
|
||||||
|
proposal = signature.signable
|
||||||
|
|
||||||
|
signature.assign_vote
|
||||||
|
|
||||||
|
user = User.last
|
||||||
|
expect(user.document_number).to eq("12345678Z")
|
||||||
|
expect(user.created_from_signature).to eq(true)
|
||||||
|
expect(user.verified_at).to be
|
||||||
|
expect(user.erased_at).to be
|
||||||
|
end
|
||||||
|
|
||||||
|
it "assign the vote to newly created user" do
|
||||||
|
signature = create(:signature, document_number: "12345678Z")
|
||||||
|
proposal = signature.signable
|
||||||
|
|
||||||
|
signature.assign_vote
|
||||||
|
|
||||||
|
user = signature.user
|
||||||
|
expect(user.voted_for?(proposal)).to be
|
||||||
|
end
|
||||||
|
|
||||||
|
it "assigns signature to vote" do
|
||||||
|
signature = create(:signature, document_number: "12345678Z")
|
||||||
|
|
||||||
|
signature.assign_vote
|
||||||
|
|
||||||
|
expect(Vote.last.signature).to eq(signature)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#verify" do
|
||||||
|
|
||||||
|
describe "document in census" do
|
||||||
|
|
||||||
|
it "calls assign_vote" do
|
||||||
|
signature = create(:signature, document_number: "12345678Z")
|
||||||
|
|
||||||
|
expect(signature).to receive(:assign_vote)
|
||||||
|
signature.verify
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets signature as verified" do
|
||||||
|
user = create(:user, :level_two, document_number: "123A")
|
||||||
|
signature = create(:signature, document_number: user.document_number)
|
||||||
|
|
||||||
|
signature.verify
|
||||||
|
|
||||||
|
expect(signature).to be_verified
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "document not in census" do
|
||||||
|
|
||||||
|
it "does not call assign_vote" do
|
||||||
|
signature = create(:signature, document_number: "123A")
|
||||||
|
|
||||||
|
expect(signature).to_not receive(:assign_vote)
|
||||||
|
signature.verify
|
||||||
|
end
|
||||||
|
|
||||||
|
it "maintains signature as not verified" do
|
||||||
|
signature = create(:signature, document_number: "123A")
|
||||||
|
|
||||||
|
signature.verify
|
||||||
|
expect(signature).to_not be_verified
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user